

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

# Créez vos tâches quantiques avec Amazon Braket
<a name="braket-build"></a>

Braket fournit des environnements de blocs-notes Jupyter entièrement gérés qui facilitent la prise en main. Les blocs-notes Braket sont préinstallés avec des exemples d'algorithmes, de ressources et d'outils de développement, notamment le SDK Amazon Braket. Avec le SDK Amazon Braket, vous pouvez créer des algorithmes quantiques, puis les tester et les exécuter sur différents ordinateurs quantiques et simulateurs en modifiant une seule ligne de code.

**Topics**
+ [Construisez votre premier circuit](braket-get-started-run-circuit.md)
+ [Obtenir des conseils d'experts](braket-expert-advice.md)
+ [Exécutez vos circuits avec OpenQASM 3.0](braket-openqasm.md)
+ [Explorez les capacités expérimentales](braket-experimental-capabilities.md)
+ [Contrôle du pouls sur Amazon Braket](braket-pulse-control.md)
+ [Simulation hamiltonienne analogique](braket-analog-hamiltonian-simulation.md)
+ [Travailler avec AWS Boto3](braket-using-boto3.md)

# Construisez votre premier circuit
<a name="braket-get-started-run-circuit"></a>

Une fois votre instance de bloc-notes lancée, ouvrez-la avec une interface Jupyter standard en choisissant le bloc-notes que vous venez de créer.

![\[Interface de blocs-notes affichant une instance de bloc-notes existante nommée amazon-braket-test avec son statut InService et son URL.\]](http://docs.aws.amazon.com/fr_fr/braket/latest/developerguide/images/console-page.png)


Les instances du bloc-notes Amazon Braket sont préinstallées avec le SDK Amazon Braket et toutes ses dépendances. Commencez par créer un nouveau bloc-notes avec `conda_braket` le noyau.

![\[Interface de lancement pour les ordinateurs portables, la console et d'autres outils tels que le terminal, le fichier texte, le fichier Markdown, le fichier Python, avec l'environnement Python conda_braket mis en évidence.\]](http://docs.aws.amazon.com/fr_fr/braket/latest/developerguide/images/jupyter-open.png)


Vous pouvez commencer par un simple « Bonjour tout le monde \$1 » exemple. Construisez d'abord un circuit qui prépare un état de Bell, puis exécutez ce circuit sur différents appareils pour obtenir les résultats.

Commencez par importer le Commencez par importer les modules du SDK Amazon Braket, en définissant un module SDK simple BRAKETlong et en définissant un circuit Bell State de base.

```
import boto3
from braket.aws import AwsDevice
from braket.devices import LocalSimulator
from braket.circuits import Circuit

# Create the circuit
bell = Circuit().h(0).cnot(0, 1)
```

Vous pouvez visualiser le circuit avec cette commande :

```
print(bell)
```

```
T  : │  0  │  1  │
      ┌───┐       
q0 : ─┤ H ├───●───
      └───┘   │   
            ┌─┴─┐ 
q1 : ───────┤ X ├─
            └───┘ 
T  : │  0  │  1  │
```

 **Exécutez votre circuit sur le simulateur local** 

Ensuite, choisissez le dispositif quantique sur lequel exécuter le circuit. Le SDK Amazon Braket est fourni avec un simulateur local pour le prototypage et les tests rapides. Nous vous recommandons d'utiliser le simulateur local pour les circuits plus petits, qui peuvent atteindre 25 qubits (selon votre matériel local).

Pour instancier le simulateur local :

```
# Instantiate the local simulator
local_sim = LocalSimulator()
```

et lancez le circuit :

```
# Run the circuit
result = local_sim.run(bell, shots=1000).result()
counts = result.measurement_counts
print(counts)
```

Vous devriez voir un résultat semblable à celui-ci :

```
Counter({'11': 503, '00': 497})
```

L'état de Bell spécifique que vous avez préparé est une superposition égale de \$100⟩ et \$111⟩, et une distribution à peu près égale (jusqu'au shot bruit) de 00 et 11 en tant que résultats de mesure, comme prévu.

 **Exécutez votre circuit sur un simulateur à la demande** 

Amazon Braket donne également accès à un simulateur haute performance à la demandeSV1, pour exécuter de plus grands circuits. SV1est un simulateur vectoriel d'état à la demande qui permet de simuler des circuits quantiques allant jusqu'à 34qubits. Vous trouverez plus d'informations SV1 dans la section [Appareils pris en charge](braket-devices.md) et dans la AWS console. Lorsque vous exécutez des tâches quantiques sur SV1 (et sur TN1 ou sur n'importe quel QPU), les résultats de votre tâche quantique sont stockés dans un compartiment S3 de votre compte. Si vous ne spécifiez aucun compartiment, le SDK Braket crée un compartiment par défaut `amazon-braket-{region}-{accountID}` pour vous. Pour en savoir plus, consultez [Gérer l'accès à Amazon Braket](braket-manage-access.md).

**Note**  
Entrez le nom de votre bucket actuel, là où l'exemple suivant l'indique `amazon-braket-s3-demo-bucket` comme nom de compartiment. Les noms des compartiments pour Amazon Braket commencent `amazon-braket-` toujours par les autres caractères d'identification que vous ajoutez. Si vous avez besoin d'informations sur la configuration d'un compartiment S3, consultez [Getting started with Amazon S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/GetStartedWithS3.html).

```
# Get the account ID
aws_account_id = boto3.client("sts").get_caller_identity()["Account"]

# The name of the bucket
my_bucket = "amazon-braket-s3-demo-bucket"

# The name of the folder in the bucket
my_prefix = "simulation-output"
s3_folder = (my_bucket, my_prefix)
```

Pour exécuter un circuitSV1, vous devez fournir l'emplacement du compartiment S3 que vous avez précédemment sélectionné comme argument positionnel dans l'`.run()`appel.

```
# Choose the cloud-based on-demand simulator to run your circuit
device = AwsDevice("arn:aws:braket:::device/quantum-simulator/amazon/sv1")

# Run the circuit
task = device.run(bell, s3_folder, shots=100)

# Display the results
print(task.result().measurement_counts)
```

La console Amazon Braket fournit des informations supplémentaires sur votre tâche quantique. Accédez à l'onglet **Quantum Tasks** de la console et votre tâche quantique devrait figurer en haut de la liste. Vous pouvez également rechercher votre tâche quantique à l'aide de l'identifiant unique de la tâche quantique ou d'autres critères.

**Note**  
Au bout de 90 jours, Amazon Braket supprime automatiquement toutes les tâches quantiques IDs et autres métadonnées associées à vos tâches quantiques. Pour plus d'informations, consultez la section [Conservation des données](https://docs.aws.amazon.com/braket/latest/developerguide/security.html#braket-data-retention).

 **Exécution sur un QPU** 

Avec Amazon Braket, vous pouvez exécuter l'exemple de circuit quantique précédent sur un ordinateur quantique physique en modifiant simplement une seule ligne de code. Amazon Braket donne accès à une variété d'unités de traitement quantique (QPU). Vous trouverez des informations sur les différents appareils et les fenêtres de disponibilité dans la section [Appareils pris en charge](braket-devices.md) et dans la AWS console sous l'onglet **Appareils**. L'exemple suivant montre comment instancier un IQM appareil.

```
# Choose the IQM hardware to run your circuit
device = AwsDevice("arn:aws:braket:eu-north-1::device/qpu/iqm/Garnet")
```

Ou choisissez un IonQ appareil avec ce code :

```
# Choose the Ionq device to run your circuit
device = AwsDevice("arn:aws:braket:us-east-1::device/qpu/ionq/Aria-1")
```

Après avoir sélectionné un appareil et avant d'exécuter votre charge de travail, vous pouvez demander la profondeur de la file d'attente des appareils à l'aide du code suivant pour déterminer le nombre de tâches quantiques ou de tâches hybrides. En outre, les clients peuvent consulter la profondeur des files d'attente spécifiques aux appareils sur la page Appareils duAmazon Braket Management Console. 

```
# Print your queue depth
print(device.queue_depth().quantum_tasks)
# Returns the number of quantum tasks queued on the device
# {<QueueType.NORMAL: 'Normal'>: '0', <QueueType.PRIORITY: 'Priority'>: '0'}

print(device.queue_depth().jobs)
# Returns the number of hybrid jobs queued on the device
# '2'
```

Lorsque vous exécutez votre tâche, le SDK Amazon Braket interroge pour obtenir un résultat (avec un délai d'expiration par défaut de 5 jours). Vous pouvez modifier cette valeur par défaut en modifiant le `poll_timeout_seconds` paramètre dans la `.run()` commande, comme indiqué dans l'exemple suivant. N'oubliez pas que si votre délai d'interrogation est trop court, les résultats risquent de ne pas être renvoyés dans le délai imparti, par exemple lorsqu'un QPU n'est pas disponible et qu'une erreur de temporisation locale est renvoyée. Vous pouvez relancer le sondage en appelant la `task.result()` fonction.

```
# Define quantum task with 1 day polling timeout
task = device.run(bell, s3_folder, poll_timeout_seconds=24*60*60)
print(task.result().measurement_counts)
```

De plus, après avoir soumis votre tâche quantique ou votre tâche hybride, vous pouvez appeler la `queue_position()` fonction pour vérifier votre position dans la file d'attente.

```
print(task.queue_position().queue_position)
# Return the number of quantum tasks queued ahead of you
# '2'
```

# Création de vos premiers algorithmes quantiques
<a name="braket-explore-algorithm-library"></a>

La bibliothèque d'algorithmes Amazon Braket est un catalogue d'algorithmes quantiques prédéfinis écrits en Python. Exécutez ces algorithmes tels quels ou utilisez-les comme points de départ pour créer des algorithmes plus complexes. Vous pouvez accéder à la bibliothèque d'algorithmes depuis la console Braket. Pour plus d'informations, consultez la bibliothèque d'[algorithmes Braket Github](https://github.com/aws-samples/amazon-braket-algorithm-library).

![\[La page de la bibliothèque d'algorithmes d'Amazon Braket présente une liste d'algorithmes quantiques prédéfinis tels que Berstein Vazirani, Deutsch-Jozsa, l'algorithme de Grover et l'algorithme d'optimisation approximative quantique avec de brèves descriptions.\]](http://docs.aws.amazon.com/fr_fr/braket/latest/developerguide/images/AlgorithmLibrary.png)


La console Braket fournit une description de chaque algorithme disponible dans la bibliothèque d'algorithmes. Cliquez GitHub sur un lien pour voir les détails de chaque algorithme, ou choisissez **Ouvrir un bloc-notes** pour ouvrir ou créer un bloc-notes contenant tous les algorithmes disponibles. Si vous choisissez l'option bloc-notes, vous pouvez alors trouver la bibliothèque d'algorithmes Braket dans le dossier racine de votre bloc-notes.

# Construire des circuits dans le SDK
<a name="braket-constructing-circuit"></a>

Cette section fournit des exemples de définition d'un circuit, de visualisation des portes disponibles, d'extension d'un circuit et de visualisation des portes prises en charge par chaque appareil. Il contient également des instructions sur la façon d'allouer manuellementqubits, de demander au compilateur d'exécuter vos circuits exactement tels que définis et de créer des circuits bruyants à l'aide d'un simulateur de bruit.

Vous pouvez également travailler au niveau du pouls dans Braket pour différents portails avec certains QPUs. Pour plus d'informations, consultez [Pulse Control sur Amazon Braket](braket-pulse-control.md).

**Topics**
+ [Portails et circuits](#braket-gates)
+ [Ensembles de programmes](#braket-program-set)
+ [Mesure partielle](#braket-partial-measurement)
+ [qubitAllocation manuelle](#manual-qubit-allocation)
+ [Compilation textuelle](#verbatim-compilation)
+ [Simulation du bruit](#noise-simulation)

## Portails et circuits
<a name="braket-gates"></a>

Les portes et circuits quantiques sont définis dans la [https://github.com/aws/amazon-braket-sdk-python/blob/main/src/braket/circuits/circuit.py](https://github.com/aws/amazon-braket-sdk-python/blob/main/src/braket/circuits/circuit.py)classe du SDK Amazon Braket Python. À partir du SDK, vous pouvez instancier un nouvel objet de circuit en appelant. `Circuit()`

 **Exemple : définition d'un circuit** 

L'exemple commence par définir un exemple de circuit de quatre qubits (étiquetés`q0`, `q1``q2`, et`q3`) composé de portes Hadamard standard à un qubit et de portes CNOT à deux qubits. Vous pouvez visualiser ce circuit en appelant la `print` fonction, comme le montre l'exemple suivant.

```
# Import the circuit module
from braket.circuits import Circuit

# Define circuit with 4 qubits
my_circuit = Circuit().h(range(4)).cnot(control=0, target=2).cnot(control=1, target=3)
print(my_circuit)
```

```
T  : │  0  │     1     │
      ┌───┐             
q0 : ─┤ H ├───●─────────
      └───┘   │         
      ┌───┐   │         
q1 : ─┤ H ├───┼─────●───
      └───┘   │     │   
      ┌───┐ ┌─┴─┐   │   
q2 : ─┤ H ├─┤ X ├───┼───
      └───┘ └───┘   │   
      ┌───┐       ┌─┴─┐ 
q3 : ─┤ H ├───────┤ X ├─
      └───┘       └───┘ 
T  : │  0  │     1     │
```

 **Exemple : définition d'un circuit paramétré** 

Dans cet exemple, nous définissons un circuit dont les portes dépendent de paramètres libres. Nous pouvons spécifier les valeurs de ces paramètres pour créer un nouveau circuit ou, lors de la soumission du circuit, pour qu'il soit exécuté en tant que tâche quantique sur certains appareils.

```
from braket.circuits import Circuit, FreeParameter

# Define a FreeParameter to represent the angle of a gate
alpha = FreeParameter("alpha")

# Define a circuit with three qubits
my_circuit = Circuit().h(range(3)).cnot(control=0, target=2).rx(0, alpha).rx(1, alpha)
print(my_circuit)
```

Vous pouvez créer un nouveau circuit non paramétré à partir d'un circuit paramétré en fournissant soit un seul `float` (qui est la valeur que prendront tous les paramètres libres), soit des arguments par mot-clé spécifiant la valeur de chaque paramètre au circuit comme suit.

```
my_fixed_circuit = my_circuit(1.2)
my_fixed_circuit = my_circuit(alpha=1.2)
print(my_fixed_circuit)
```

Notez qu'il `my_circuit` n'est pas modifié, vous pouvez donc l'utiliser pour instancier de nombreux nouveaux circuits avec des valeurs de paramètres fixes.

 **Exemple : modifier les portes d'un circuit** 

L'exemple suivant définit un circuit avec des portes qui utilisent des modificateurs de commande et de puissance. Vous pouvez utiliser ces modifications pour créer de nouvelles portes, telles que la `Ry` porte contrôlée.

```
from braket.circuits import Circuit

# Create a bell circuit with a controlled x gate
my_circuit = Circuit().h(0).x(control=0, target=1)

# Add a multi-controlled Ry gate of angle .13
my_circuit.ry(angle=.13, target=2, control=(0, 1))

# Add a 1/5 root of X gate
my_circuit.x(0, power=1/5)

print(my_circuit)
```

Les modificateurs de porte ne sont pris en charge que sur le simulateur local.

 **Exemple : Voir toutes les portes disponibles** 

L'exemple suivant montre comment examiner toutes les portes disponibles dans Amazon Braket.

```
from braket.circuits import Gate
# Print all available gates in Amazon Braket
gate_set = [attr for attr in dir(Gate) if attr[0].isupper()]
print(gate_set)
```

La sortie de ce code répertorie toutes les portes.

```
['CCNot', 'CNot', 'CPhaseShift', 'CPhaseShift00', 'CPhaseShift01', 'CPhaseShift10', 'CSwap', 'CV', 'CY', 'CZ', 'ECR', 'GPhase', 'GPi', 'GPi2', 'H', 'I', 'ISwap', 'MS', 'PRx', 'PSwap', 'PhaseShift', 'PulseGate', 'Rx', 'Ry', 'Rz', 'S', 'Si', 'Swap', 'T', 'Ti', 'U', 'Unitary', 'V', 'Vi', 'X', 'XX', 'XY', 'Y', 'YY', 'Z', 'ZZ']
```

N'importe laquelle de ces portes peut être ajoutée à un circuit en appelant la méthode correspondant à ce type de circuit. Par exemple, appelez`circ.h(0)`, pour ajouter une porte Hadamard à la première. qubit

**Note**  
Les portes sont ajoutées en place, et l'exemple suivant ajoute toutes les portes répertoriées dans l'exemple précédent au même circuit.

```
circ = Circuit()
# toffoli gate with q0, q1 the control qubits and q2 the target.
circ.ccnot(0, 1, 2)
# cnot gate
circ.cnot(0, 1)
# controlled-phase gate that phases the |11> state, cphaseshift(phi) = diag((1,1,1,exp(1j*phi))), where phi=0.15 in the examples below
circ.cphaseshift(0, 1, 0.15)
# controlled-phase gate that phases the |00> state, cphaseshift00(phi) = diag([exp(1j*phi),1,1,1])
circ.cphaseshift00(0, 1, 0.15)
# controlled-phase gate that phases the |01> state, cphaseshift01(phi) = diag([1,exp(1j*phi),1,1])
circ.cphaseshift01(0, 1, 0.15)
# controlled-phase gate that phases the |10> state, cphaseshift10(phi) = diag([1,1,exp(1j*phi),1])
circ.cphaseshift10(0, 1, 0.15)
# controlled swap gate
circ.cswap(0, 1, 2)
# swap gate
circ.swap(0,1)
# phaseshift(phi)= diag([1,exp(1j*phi)])
circ.phaseshift(0,0.15)
# controlled Y gate
circ.cy(0, 1)
# controlled phase gate
circ.cz(0, 1)
# Echoed cross-resonance gate applied to q0, q1
circ = Circuit().ecr(0,1)
# X rotation with angle 0.15
circ.rx(0, 0.15)
# Y rotation with angle 0.15
circ.ry(0, 0.15)
# Z rotation with angle 0.15
circ.rz(0, 0.15)
# Hadamard gates applied to q0, q1, q2
circ.h(range(3))
# identity gates applied to q0, q1, q2
circ.i([0, 1, 2])
# iswap gate, iswap = [[1,0,0,0],[0,0,1j,0],[0,1j,0,0],[0,0,0,1]]
circ.iswap(0, 1)
# pswap gate, PSWAP(phi) = [[1,0,0,0],[0,0,exp(1j*phi),0],[0,exp(1j*phi),0,0],[0,0,0,1]]
circ.pswap(0, 1, 0.15)
# X gate applied to q1, q2
circ.x([1, 2])
# Y gate applied to q1, q2
circ.y([1, 2])
# Z gate applied to q1, q2
circ.z([1, 2])
# S gate applied to q0, q1, q2
circ.s([0, 1, 2])
# conjugate transpose of S gate applied to q0, q1
circ.si([0, 1])
# T gate applied to q0, q1
circ.t([0, 1])
# conjugate transpose of T gate applied to q0, q1
circ.ti([0, 1])
# square root of not gate applied to q0, q1, q2
circ.v([0, 1, 2])
# conjugate transpose of square root of not gate applied to q0, q1, q2
circ.vi([0, 1, 2])
# exp(-iXX theta/2)
circ.xx(0, 1, 0.15)
# exp(i(XX+YY) theta/4), where theta=0.15 in the examples below
circ.xy(0, 1, 0.15)
# exp(-iYY theta/2)
circ.yy(0, 1, 0.15)
# exp(-iZZ theta/2)
circ.zz(0, 1, 0.15)
# IonQ native gate GPi with angle 0.15 applied to q0
circ.gpi(0, 0.15)
# IonQ native gate GPi2 with angle 0.15 applied to q0
circ.gpi2(0, 0.15)
# IonQ native gate MS with angles 0.15, 0.15, 0.15 applied to q0, q1
circ.ms(0, 1, 0.15, 0.15, 0.15)
```

Outre le jeu de portes prédéfini, vous pouvez également appliquer des portes unitaires auto-définies au circuit. Il peut s'agir de portes à un seul qubit (comme indiqué dans le code source suivant) ou de portes à plusieurs qubits appliquées à la valeur qubits définie par le paramètre. `targets`

```
import numpy as np

# Apply a general unitary
my_unitary = np.array([[0, 1],[1, 0]])
circ.unitary(matrix=my_unitary, targets=[0])
```

 **Exemple : étendre les circuits existants** 

Vous pouvez étendre les circuits existants en ajoutant des instructions. An `Instruction` est une directive quantique qui décrit la tâche quantique à effectuer sur un dispositif quantique. `Instruction`les opérateurs incluent `Gate` uniquement les objets de type.

```
# Import the Gate and Instruction modules
from braket.circuits import Gate, Instruction

# Add instructions directly.
circ = Circuit([Instruction(Gate.H(), 4), Instruction(Gate.CNot(), [4, 5])])

# Or with add_instruction/add functions
instr = Instruction(Gate.CNot(), [0, 1])
circ.add_instruction(instr)
circ.add(instr)

# Specify where the circuit is appended
circ.add_instruction(instr, target=[3, 4])
circ.add_instruction(instr, target_mapping={0: 3, 1: 4})

# Print the instructions
print(circ.instructions)
# If there are multiple instructions, you can print them in a for loop
for instr in circ.instructions:
     print(instr)

# Instructions can be copied
new_instr = instr.copy()
# Appoint the instruction to target
new_instr = instr.copy(target=[5, 6])
new_instr = instr.copy(target_mapping={0: 5, 1: 6})
```

 **Exemple : Afficher les barrières prises en charge par chaque appareil** 

Les simulateurs prennent en charge toutes les portes du SDK Braket, mais les appareils QPU en prennent en charge un sous-ensemble plus restreint. Vous pouvez trouver les portes compatibles d'un appareil dans les propriétés de l'appareil. Voici un exemple avec un appareil IonQ :

```
# Import the device module
from braket.aws import AwsDevice

device = AwsDevice("arn:aws:braket:us-east-1::device/qpu/ionq/Aria-1")

# Get device name
device_name = device.name
# Show supportedQuantumOperations (supported gates for a device)
device_operations = device.properties.dict()['action']['braket.ir.openqasm.program']['supportedOperations']
print('Quantum Gates supported by {}:\n {}'.format(device_name, device_operations))
```

```
Quantum Gates supported by Aria 1:
 ['x', 'y', 'z', 'h', 's', 'si', 't', 'ti', 'v', 'vi', 'rx', 'ry', 'rz', 'cnot', 'swap', 'xx', 'yy', 'zz']
```

Les portes prises en charge devront peut-être être compilées dans des portes natives avant de pouvoir fonctionner sur du matériel quantique. Lorsque vous soumettez un circuit, Amazon Braket effectue cette compilation automatiquement.

 **Exemple : récupérer par programmation la fidélité des portes natives prises en charge par un appareil** 

Vous pouvez consulter les informations de fidélité sur la page **Appareils** de la console Braket. Il est parfois utile d'accéder aux mêmes informations par le biais d'un programme. Le code suivant montre comment extraire la fidélité à deux qubit portes entre deux portes d'un QPU.

```
# Import the device module
from braket.aws import AwsDevice
 
device = AwsDevice("arn:aws:braket:us-west-1::device/qpu/rigetti/Ankaa-3") 

# Specify the qubits 
a=10 
b=11
edge_properties_entry = device.properties.standardized.twoQubitProperties['10-11'].twoQubitGateFidelity
gate_name = edge_properties_entry[0].gateName
fidelity = edge_properties_entry[0].fidelity
print(f"Fidelity of the {gate_name} gate between qubits {a} and {b}: {fidelity}")
```

## Ensembles de programmes
<a name="braket-program-set"></a>

Les ensembles de programmes exécutent efficacement plusieurs circuits quantiques en une seule tâche quantique. Dans le cadre de cette tâche, vous pouvez soumettre jusqu'à 100 circuits quantiques ou un seul circuit paramétrique avec jusqu'à 100 ensembles de paramètres différents. Cette opération minimise le temps entre les exécutions de circuits suivantes et réduit la surcharge de traitement des tâches quantiques. Actuellement, les ensembles de programmes sont pris en charge sur Amazon Braket Local Simulator et sur AQT les appareilsIQM. Rigetti

**Définition d'un ProgramSet**

Le premier exemple de code suivant montre comment créer un `ProgramSet` en utilisant à la fois des circuits paramétrés et des circuits sans paramètres.

```
from braket.aws import AwsDevice
from braket.circuits import Circuit, FreeParameter
from braket.program_sets.circuit_binding import CircuitBinding
from braket.program_sets import ProgramSet

# Initialize the quantum device
device = AwsDevice("arn:aws:braket:eu-north-1::device/qpu/iqm/Garnet")

# Define circuits
circ1 = Circuit().h(0).cnot(0, 1)
circ2 = Circuit().rx(0, 0.785).ry(1, 0.393).cnot(1, 0)
circ3 = Circuit().t(0).t(1).cz(0, 1).s(0).cz(1, 2).s(1).s(2)
parameterize_circuit = Circuit().rx(0, FreeParameter("alpha")).cnot(0, 1).ry(1, FreeParameter("beta"))

# Create circuit bindings with different parameters
circuit_binding = CircuitBinding(
    circuit=parameterize_circuit,
    input_sets={
            'alpha': (0.10, 0.11, 0.22, 0.34, 0.45),
            'beta': (1.01, 1.01, 1.03, 1.04, 1.04),
    })

# Creating the program set
program_set_1 = ProgramSet([
    circ1,
    circ2,
    circ3,
    circuit_binding,
])
```

Cet ensemble de programmes contient quatre programmes uniques : `circ1``circ2`,`circ3`, et`circuit_binding`. Le `circuit_binding` programme s'exécute avec cinq liaisons de paramètres différentes, créant ainsi cinq exécutables. Les trois autres programmes sans paramètres créent chacun un exécutable. Cela donne huit exécutables au total, comme le montre l'image suivante.

![\[ProgramSet structure à quatre circuits, où c4 utilise CircuitBinding pour traiter cinq ensembles d'entrées.\]](http://docs.aws.amazon.com/fr_fr/braket/latest/developerguide/images/program_set1.png)


Le deuxième exemple de code suivant montre comment utiliser la `product()` méthode pour associer le même ensemble d'observables à chaque exécutable de l'ensemble de programmes.

```
from braket.circuits.observables import I, X, Y, Z

observables = [Z(0) @ Z(1), X(0) @ X(1), Z(0) @ X(1), X(0) @ Z(1)]

program_set_2 = ProgramSet.product(
    circuits=[circ1, circ2, circuit_binding],
    observables=observables
)
```

Pour les programmes sans paramètres, chaque observable est mesuré pour chaque circuit. Pour les programmes paramétriques, chaque observable est mesuré pour chaque ensemble d'entrées, comme indiqué dans l'image suivante.

![\[ProgramSet.product montrant l'exécution en parallèle de trois circuits, avec c3 utilisé CircuitBinding pour traiter cinq ensembles d'entrées avec cinq observables chacun.\]](http://docs.aws.amazon.com/fr_fr/braket/latest/developerguide/images/program_set2.png)


Le troisième exemple de code suivant montre comment utiliser la `zip()` méthode pour associer des observables individuels à des ensembles de paramètres spécifiques dans le`ProgramSet`.

```
program_set_3 = ProgramSet.zip(
    circuits=circuit_binding,
    observables=observables + [Y(0) @ Y(1)]
)
```

![\[ProgramSet.zip avec CircuitBinding démonstration de cinq exécutions parallèles utilisant un circuit partagé avec des observables individuels par ensemble d'entrées.\]](http://docs.aws.amazon.com/fr_fr/braket/latest/developerguide/images/program_set3.png)


Au lieu de cela`CircuitBinding()`, vous pouvez directement compresser une liste d'observables avec une liste de circuits et de jeux d'entrées. 

```
program_set_4 = ProgramSet.zip(
    circuits=[circ1, circ2, circ3],
    input_sets=[{}, {}, {}],
    observables=observables[:3]
)
```

![\[ProgramSet.zip montrant l'exécution en parallèle de sept circuits avec leur jeu d'entrées individuel correspondant et leurs observables individuels.\]](http://docs.aws.amazon.com/fr_fr/braket/latest/developerguide/images/program_set4.png)


Pour plus d'informations et des exemples sur les ensembles de programmes, consultez le [dossier Program set](https://github.com/amazon-braket/amazon-braket-examples/tree/main/examples/braket_features/program_sets) sur amazon-braket-examples Github.

**Inspecter et exécuter un programme défini sur un appareil**

Le nombre d'exécutables d'un ensemble de programmes est égal à son nombre de circuits uniques liés à des paramètres. Calculez le nombre total d'exécutables et de plans de circuit à l'aide de l'exemple de code suivant.

```
# Number of shots per executable
shots = 10
num_executables = program_set_1.total_executables

# Calculate total number of shots across all executables
total_num_shots = shots*num_executables
```

**Note**  
Avec les ensembles de programmes, vous payez des frais uniques par tâche et des frais par tir basés sur le nombre total de plans sur tous les circuits d'un ensemble de programmes.

Pour exécuter l'ensemble de programmes, utilisez l'exemple de code suivant.

```
# Run the program set
task = device.run(
   program_set_1, shots=total_num_shots,
)
```

Lorsque vous utilisez Rigetti des appareils, votre ensemble de programmes peut rester dans `RUNNING` cet état alors que les tâches sont partiellement terminées et partiellement mises en file d'attente. Pour obtenir des résultats plus rapidement, pensez à soumettre votre programme défini en tant que [Job hybride](braket-jobs-first.md).

**Analyse des résultats**

Exécutez le code suivant pour analyser et mesurer les résultats des exécutables dans un. `ProgramSet`

```
# Get the results from a program set 
result = task.result()

# Get the first executbable
first_program = result[0] 
first_executable = first_program[0]

# Inspect the results of the first executable
measurements_from_first_executable = first_executable.measurements
print(measurements_from_first_executable)
```

## Mesure partielle
<a name="braket-partial-measurement"></a>

Au lieu de mesurer tous les qubits d'un circuit quantique, utilisez une mesure partielle pour mesurer des qubits individuels ou un sous-ensemble de qubits. 

**Note**  
Des fonctionnalités supplémentaires telles que la mesure en milieu de circuit et les opérations d'anticipation sont disponibles en tant que capacités expérimentales, voir [Accès aux circuits dynamiques sur](braket-experimental-capabilities.md#braket-access-dynamic-circuits) les appareils IQM.

**Exemple : mesurer un sous-ensemble de qubits**

L'exemple de code suivant illustre une mesure partielle en mesurant uniquement le qubit 0 dans un circuit à états de Bell.

```
from braket.devices import LocalSimulator
from braket.circuits import Circuit

# Use the local state vector simulator
device = LocalSimulator()

# Define an example bell circuit and measure qubit 0
circuit = Circuit().h(0).cnot(0, 1).measure(0)

# Run the circuit
task = device.run(circuit, shots=10)

# Get the results
result = task.result()

# Print the circuit and measured qubits
print(circuit)
print()
print("Measured qubits: ", result.measured_qubits)
```

## qubitAllocation manuelle
<a name="manual-qubit-allocation"></a>

Lorsque vous exécutez un circuit quantique sur des ordinateurs quantiques à partir deRigetti, vous pouvez éventuellement utiliser qubit l'allocation manuelle pour contrôler ceux qui qubits sont utilisés pour votre algorithme. La [console Amazon Braket](https://console.aws.amazon.com/braket/home) et le SDK [Amazon Braket](https://github.com/aws/amazon-braket-sdk-python) vous aident à inspecter les données d'étalonnage les plus récentes de l'unité de traitement quantique (QPU) que vous avez sélectionnée, afin que vous puissiez sélectionner celle qui convient le mieux à votre expérience. qubits

qubitL'allocation manuelle vous permet d'exécuter des circuits avec une plus grande précision et d'étudier les qubit propriétés individuelles. Les chercheurs et les utilisateurs expérimentés optimisent la conception de leurs circuits en fonction des dernières données d'étalonnage des appareils et peuvent obtenir des résultats plus précis.

L'exemple suivant montre comment allouer de qubits manière explicite.

```
# Import the device module
from braket.aws import AwsDevice

device = AwsDevice("arn:aws:braket:us-west-1::device/qpu/rigetti/Ankaa-3")
circ = Circuit().h(0).cnot(0, 7)  # Indices of actual qubits in the QPU

# Set up S3 bucket (where results are stored)
my_bucket = "amazon-braket-s3-demo-bucket" # The name of the bucket
my_prefix = "your-folder-name" # The name of the folder in the bucket
s3_location = (my_bucket, my_prefix)

my_task = device.run(circ, s3_location, shots=100, disable_qubit_rewiring=True)
```

Pour plus d'informations, consultez [les exemples d'Amazon Braket sur GitHub](https://github.com/aws/amazon-braket-examples), ou plus précisément, ce bloc-notes : [Allocation de qubits sur les appareils QPU](https://github.com/aws/amazon-braket-examples/blob/main/examples/braket_features/Allocating_Qubits_on_QPU_Devices.ipynb).

## Compilation textuelle
<a name="verbatim-compilation"></a>

Lorsque vous exécutez un circuit quantique sur des ordinateurs quantiques basés sur des portes, vous pouvez demander au compilateur d'exécuter vos circuits exactement tels que définis, sans aucune modification. À l'aide de la compilation textuelle, vous pouvez spécifier soit qu'un circuit entier soit préservé exactement comme spécifié, soit que seules des parties spécifiques de celui-ci soient préservées (prises en charge Rigetti uniquement par). Lorsque vous développez des algorithmes pour l'analyse comparative du matériel ou des protocoles d'atténuation des erreurs, vous devez avoir la possibilité de spécifier exactement les portes et les configurations de circuits qui s'exécutent sur le matériel. La compilation Verbatim vous permet de contrôler directement le processus de compilation en désactivant certaines étapes d'optimisation, garantissant ainsi que vos circuits fonctionnent exactement comme prévu.

La compilation Verbatim est prise en charge sur les Rigetti appareils AQT IonQIQM,, et nécessite l'utilisation de portes natives. Lors de l'utilisation de la compilation textuelle, il est conseillé de vérifier la topologie de l'appareil pour s'assurer que les portes sont connectées qubits et que le circuit utilise les portes natives prises en charge par le matériel. L'exemple suivant montre comment accéder par programmation à la liste des portes natives prises en charge par un appareil.

```
device.properties.paradigm.nativeGateSet
```

En effetRigetti, qubit le recâblage doit être désactivé en le configurant `disableQubitRewiring=True` pour une utilisation avec la compilation textuelle. S'il `disableQubitRewiring=False` est défini lors de l'utilisation de boîtes verbatim dans une compilation, le circuit quantique échoue à la validation et ne s'exécute pas.

Si la compilation textuelle est activée pour un circuit et exécutée sur un QPU qui ne le prend pas en charge, une erreur est générée indiquant qu'une opération non prise en charge a entraîné l'échec de la tâche. Au fur et à mesure que de plus en plus de matériels quantiques prennent en charge nativement les fonctions de compilation, cette fonctionnalité sera étendue pour inclure ces appareils. Les appareils qui prennent en charge la compilation textuelle l'incluent en tant qu'opération prise en charge lorsqu'ils sont interrogés avec le code suivant.

```
from braket.aws import AwsDevice
from braket.device_schema.device_action_properties import DeviceActionType
device = AwsDevice("arn:aws:braket:us-west-1::device/qpu/rigetti/Ankaa-3")
device.properties.action[DeviceActionType.OPENQASM].supportedPragmas
```

Il n'y a aucun coût supplémentaire associé à l'utilisation de la compilation textuelle. Les tâches quantiques exécutées sur les appareils Braket QPU, les instances d'ordinateurs portables et les simulateurs à la demande continuent de vous être facturées sur la base des tarifs actuels, tels que spécifiés sur la page de tarification d'[Amazon](https://aws.amazon.com/braket/pricing/) Braket. Pour plus d'informations, consultez le bloc-notes d'exemple de [compilation Verbatim](https://github.com/aws/amazon-braket-examples/blob/main/examples/braket_features/Verbatim_Compilation.ipynb).

**Note**  
Si vous utilisez OpenQASM pour écrire vos circuits pour les IonQ périphériques AQT et, et que vous souhaitez mapper votre circuit directement aux qubits physiques, vous devez utiliser le `#pragma braket verbatim` car le `disableQubitRewiring` drapeau est ignoré par OpenQASM.

## Simulation du bruit
<a name="noise-simulation"></a>

Pour instancier le simulateur de bruit local, vous pouvez modifier le backend comme suit.

```
# Import the device module
from braket.aws import AwsDevice

device = LocalSimulator(backend="braket_dm")
```

Vous pouvez créer des circuits bruyants de deux manières :

1. Construisez le circuit bruyant de bas en haut.

1. Prenez un circuit sans bruit existant et injectez du bruit partout.

L'exemple suivant montre les approches utilisant un circuit de base avec un bruit dépolarisant et un canal Kraus personnalisé.

```
import scipy.stats
import numpy as np

# Bottom up approach
# Apply depolarizing noise to qubit 0 with probability of 0.1
circ = Circuit().x(0).x(1).depolarizing(0, probability=0.1)

# Create an arbitrary 2-qubit Kraus channel
E0 = scipy.stats.unitary_group.rvs(4) * np.sqrt(0.8)
E1 = scipy.stats.unitary_group.rvs(4) * np.sqrt(0.2)
K = [E0, E1]

# Apply a two-qubit Kraus channel to qubits 0 and 2
circ = circ.kraus([0, 2], K)
```

```
from braket.circuits import Noise

# Inject noise approach
# Define phase damping noise
noise = Noise.PhaseDamping(gamma=0.1)
# The noise channel is applied to all the X gates in the circuit
circ = Circuit().x(0).y(1).cnot(0, 2).x(1).z(2)
circ_noise = circ.copy()
circ_noise.apply_gate_noise(noise, target_gates=Gate.X)
```

L'exécution d'un circuit offre la même expérience utilisateur qu'auparavant, comme le montrent les deux exemples suivants.

 **Exemple 1** 

```
task = device.run(circ, shots=100)
```

Or

 **Exemple 2** 

```
task = device.run(circ_noise, shots=100)
```

Pour plus d'exemples, consultez [l'exemple d'introduction du simulateur de bruit Braket](https://github.com/aws/amazon-braket-examples/blob/main/examples/braket_features/Simulating_Noise_On_Amazon_Braket.ipynb) 

# Inspection du circuit
<a name="braket-inspecting-circut"></a>

Les circuits quantiques d'Amazon Braket ont un concept de pseudo-temps appelé. `Moments` Chacun qubit peut bénéficier d'une seule porte par`Moment`. L'objectif `Moments` est de faciliter l'adressage des circuits et de leurs portes et de fournir une structure temporelle.

**Note**  
Les moments ne correspondent généralement pas au temps réel auquel les portes sont exécutées sur un QPU.

La profondeur d'un circuit est donnée par le nombre total de moments qu'il contient. Vous pouvez visualiser la profondeur du circuit appelant la méthode`circuit.depth`, comme indiqué dans l'exemple suivant.

```
from braket.circuits import Circuit

# Define a circuit with parametrized gates
circ = Circuit().rx(0, 0.15).ry(1, 0.2).cnot(0, 2).zz(1, 3, 0.15).x(0)
print(circ)
print('Total circuit depth:', circ.depth)
```

```
T  : │     0      │        1         │  2  │
      ┌──────────┐                    ┌───┐ 
q0 : ─┤ Rx(0.15) ├───●────────────────┤ X ├─
      └──────────┘   │                └───┘ 
      ┌──────────┐   │   ┌──────────┐       
q1 : ─┤ Ry(0.20) ├───┼───┤ ZZ(0.15) ├───────
      └──────────┘   │   └────┬─────┘       
                   ┌─┴─┐      │             
q2 : ──────────────┤ X ├──────┼─────────────
                   └───┘      │             
                         ┌────┴─────┐       
q3 : ────────────────────┤ ZZ(0.15) ├───────
                         └──────────┘       
T  : │     0      │        1         │  2  │
Total circuit depth: 3
```

La profondeur totale du circuit ci-dessus est de 3 (exprimée en moments `0``1`, et`2`). Vous pouvez vérifier le fonctionnement du portail à chaque instant.

 `Moments`fonctionne comme un dictionnaire de paires *clé-valeur*.
+ La clé est qu'`MomentsKey()`il contient du pseudo-temps et des qubit informations.
+ La valeur est attribuée dans le type de`Instructions()`.

```
moments = circ.moments
for key, value in moments.items():
    print(key)
    print(value, "\n")
```

```
MomentsKey(time=0, qubits=QubitSet([Qubit(0)]), moment_type=<MomentType.GATE: 'gate'>, noise_index=0, subindex=0)
Instruction('operator': Rx('angle': 0.15, 'qubit_count': 1), 'target': QubitSet([Qubit(0)]), 'control': QubitSet([]), 'control_state': (), 'power': 1) 

MomentsKey(time=0, qubits=QubitSet([Qubit(1)]), moment_type=<MomentType.GATE: 'gate'>, noise_index=0, subindex=0)
Instruction('operator': Ry('angle': 0.2, 'qubit_count': 1), 'target': QubitSet([Qubit(1)]), 'control': QubitSet([]), 'control_state': (), 'power': 1) 

MomentsKey(time=1, qubits=QubitSet([Qubit(0), Qubit(2)]), moment_type=<MomentType.GATE: 'gate'>, noise_index=0, subindex=0)
Instruction('operator': CNot('qubit_count': 2), 'target': QubitSet([Qubit(0), Qubit(2)]), 'control': QubitSet([]), 'control_state': (), 'power': 1) 

MomentsKey(time=1, qubits=QubitSet([Qubit(1), Qubit(3)]), moment_type=<MomentType.GATE: 'gate'>, noise_index=0, subindex=0)
Instruction('operator': ZZ('angle': 0.15, 'qubit_count': 2), 'target': QubitSet([Qubit(1), Qubit(3)]), 'control': QubitSet([]), 'control_state': (), 'power': 1) 

MomentsKey(time=2, qubits=QubitSet([Qubit(0)]), moment_type=<MomentType.GATE: 'gate'>, noise_index=0, subindex=0)
Instruction('operator': X('qubit_count': 1), 'target': QubitSet([Qubit(0)]), 'control': QubitSet([]), 'control_state': (), 'power': 1)
```

Vous pouvez également ajouter des portes à un circuit`Moments`.

```
from braket.circuits import Instruction, Gate

new_circ = Circuit()
instructions = [Instruction(Gate.S(), 0),
                Instruction(Gate.CZ(), [1, 0]),
                Instruction(Gate.H(), 1)
                ]

new_circ.moments.add(instructions)
print(new_circ)
```

```
T  : │  0  │  1  │  2  │
      ┌───┐ ┌───┐       
q0 : ─┤ S ├─┤ Z ├───────
      └───┘ └─┬─┘       
              │   ┌───┐ 
q1 : ─────────●───┤ H ├─
                  └───┘ 
T  : │  0  │  1  │  2  │
```

# Liste des types de résultats
<a name="braket-result-types"></a>

Amazon Braket peut renvoyer différents types de résultats lorsqu'un circuit est mesuré à l'aide de. `ResultType` Un circuit peut renvoyer les types de résultats suivants.
+  `AdjointGradient`renvoie le gradient (dérivé vectoriel) de la valeur attendue d'un observable fourni. Cet observable agit sur une cible donnée par rapport à des paramètres spécifiés en utilisant la méthode de différenciation adjointe. Vous ne pouvez utiliser cette méthode que lorsque shots=0.
+  `Amplitude`renvoie l'amplitude des états quantiques spécifiés dans la fonction d'onde de sortie. Il n'est disponible que sur les simulateurs locaux SV1 et sur les simulateurs.
+  `Expectation`renvoie la valeur attendue d'un observable donné, qui peut être spécifiée avec la `Observable` classe présentée plus loin dans ce chapitre. La cible qubits utilisée pour mesurer l'observable doit être spécifiée, et le nombre de cibles spécifiées doit être égal au nombre de cibles qubits sur lesquelles l'observable agit. Si aucune cible n'est spécifiée, l'observable ne doit fonctionner que sur 1 qubit et il est appliqué à tous qubits en parallèle.
+  `Probability`renvoie les probabilités de mesure des états de base de calcul. Si aucune cible n'est spécifiée, `Probability` renvoie la probabilité de mesurer tous les états de base. Si des cibles sont spécifiées, seules les probabilités marginales des vecteurs de base sur les cibles spécifiées qubits sont renvoyées. Les simulateurs gérés QPUs sont limités à 15 qubits maximum, et les simulateurs locaux sont limités à la taille de la mémoire du système.
+  `Reduced density matrix`renvoie une matrice de densité pour un sous-système d'une cible spécifiée qubits à partir d'un système dequbits. Pour limiter la taille de ce type de résultat, Braket limite le nombre de cibles qubits à un maximum de 8.
+  `StateVector`renvoie le vecteur d'état complet. Il est disponible sur le simulateur local.
+  `Sample`renvoie le nombre de mesures d'un qubit ensemble cible spécifié et observable. Si aucune cible n'est spécifiée, l'observable ne doit fonctionner que sur 1 qubit et il est appliqué à tous qubits en parallèle. Si des cibles sont spécifiées, le nombre de cibles spécifiées doit être égal au nombre de cibles qubits sur lesquelles l'observable agit.
+  `Variance`renvoie la variance (`mean([x-mean(x)]2)`) de l'qubitensemble de cibles spécifié et observable en tant que type de résultat demandé. Si aucune cible n'est spécifiée, l'observable ne doit fonctionner que sur 1 qubit et il est appliqué à tous qubits en parallèle. Sinon, le nombre de cibles spécifiées doit être égal qubits au nombre auquel l'observable peut être appliqué.

 **Les types de résultats pris en charge par les différents fournisseurs :** 


|  |  |  |  |  |  |  |  |  | 
| --- |--- |--- |--- |--- |--- |--- |--- |--- |
|  |  SIM locale  |   SV1   |   DM1   |   TN1   |   AQT   |   IonQ   |   IQM   |   Rigetti   | 
|  Gradient adjoint  |  N  |  Y  |  N  |  N  |  N  |  N  |  N  |  N  | 
|  Amplitude  |  Y  |  Y  |  N  |  N  |  N  |  N  |  N  |  N  | 
|  Espérance  |  Y  |  Y  |  Y  |  Y  |  Y  |  Y  |  Y  |  Y  | 
|  Probability  |  Y  |  Y  |  Y  |  N  |  Y  |  Y  |  Y  |  Y  | 
|  Matrice à densité réduite  |  Y  |  N  |  Y  |  N  |  N  |  N  |  N  |  N  | 
|  Vecteur d'état  |  Y  |  N  |  N  |  N  |  N  |  N  |  N  |  N  | 
|  Exemple  |  Y  |  Y  |  Y  |  Y  |  Y  |  Y  |  Y  |  Y  | 
|  Variance  |  Y  |  Y  |  Y  |  Y  |  Y  |  Y  |  Y  |  Y  | 

Vous pouvez vérifier les types de résultats pris en charge en examinant les propriétés de l'appareil, comme indiqué dans l'exemple suivant.

```
from braket.aws import AwsDevice

device = AwsDevice("arn:aws:braket:us-west-1::device/qpu/rigetti/Ankaa-3")

# Print the result types supported by this device
for iter in device.properties.action['braket.ir.openqasm.program'].supportedResultTypes:
    print(iter)
```

```
name='Sample' observables=['x', 'y', 'z', 'h', 'i'] minShots=10 maxShots=50000
name='Expectation' observables=['x', 'y', 'z', 'h', 'i'] minShots=10 maxShots=50000
name='Variance' observables=['x', 'y', 'z', 'h', 'i'] minShots=10 maxShots=50000
name='Probability' observables=None minShots=10 maxShots=50000
```

Pour appeler a`ResultType`, ajoutez-le à un circuit, comme indiqué dans l'exemple suivant.

```
from braket.circuits import Circuit, Observable

circ = Circuit().h(0).cnot(0, 1).amplitude(state=["01", "10"])
circ.probability(target=[0, 1])
circ.probability(target=0)
circ.expectation(observable=Observable.Z(), target=0)
circ.sample(observable=Observable.X(), target=0)
circ.state_vector()
circ.variance(observable=Observable.Z(), target=0)

# Print one of the result types assigned to the circuit
print(circ.result_types[0])
```

**Note**  
Différents appareils quantiques fournissent des résultats sous différents formats. Par exemple, les Rigetti appareils renvoient des mesures, tandis que IonQ les appareils fournissent des probabilités. Le SDK Amazon Braket propose une propriété de mesures pour tous les résultats. Toutefois, pour les appareils qui renvoient des probabilités, ces mesures sont post-calculées et basées sur les probabilités, car les mesures par tir ne sont pas disponibles. Pour déterminer si un résultat a été post-calculé, cochez la case `measurements_copied_from_device` sur l'objet du résultat. Cette opération est détaillée dans le fichier [gate\$1model\$1quantum\$1task\$1result.py](https://github.com/aws/amazon-braket-sdk-python/blob/ca5b08dada4839ca31c012ff50aa20b656fd1879/src/braket/tasks/gate_model_quantum_task_result.py#L70-L72) du référentiel Amazon Braket SDK GitHub .

## Observables
<a name="braket-result-types-observables"></a>

La `Observable` classe d'Amazon Braket vous permet de mesurer un observable spécifique. 

Vous ne pouvez appliquer qu'une seule observable de non-identité unique à chacun. qubit Une erreur se produit si vous spécifiez deux ou plusieurs observables non identitaires différents pour la même chose. qubit À cette fin, chaque facteur d'un produit tensoriel compte comme un observable individuel. Cela signifie que vous pouvez avoir plusieurs produits tensoriels sur le même produitqubit, à condition que les facteurs agissant sur ceux-ci qubit restent les mêmes.

Un observable peut être redimensionné et ajouter d'autres observables (mis à l'échelle ou non). Cela crée un `Sum` qui peut être utilisé dans le type de `AdjointGradient` résultat.

La `Observable` classe inclut les observables suivants.

```
import numpy as np

Observable.I()
Observable.H()
Observable.X()
Observable.Y()
Observable.Z()

# Get the eigenvalues of the observable
print("Eigenvalue:", Observable.H().eigenvalues)
# Or rotate the basis to be computational basis
print("Basis rotation gates:", Observable.H().basis_rotation_gates)

# Get the tensor product of the observable for the multi-qubit case
tensor_product = Observable.Y() @ Observable.Z()
# View the matrix form of an observable by using
print("The matrix form of the observable:\n", Observable.Z().to_matrix())
print("The matrix form of the tensor product:\n", tensor_product.to_matrix())

# Factorize an observable in the tensor form
print("Factorize an observable:", tensor_product.factors)

# Self-define observables, given it is a Hermitian
print("Self-defined Hermitian:", Observable.Hermitian(matrix=np.array([[0, 1], [1, 0]])))

print("Sum of other (scaled) observables:", 2.0 * Observable.X() @ Observable.X() + 4.0 * Observable.Z() @ Observable.Z())
```

```
Eigenvalue: [ 1. -1.]
Basis rotation gates: (Ry('angle': -0.7853981633974483, 'qubit_count': 1),)
The matrix form of the observable:
 [[ 1.+0.j  0.+0.j]
 [ 0.+0.j -1.+0.j]]
The matrix form of the tensor product:
 [[ 0.+0.j  0.+0.j  0.-1.j  0.+0.j]
 [ 0.+0.j -0.+0.j  0.+0.j  0.+1.j]
 [ 0.+1.j  0.+0.j  0.+0.j  0.+0.j]
 [ 0.+0.j  0.-1.j  0.+0.j -0.+0.j]]
Factorize an observable: (Y('qubit_count': 1), Z('qubit_count': 1))
Self-defined Hermitian: Hermitian('qubit_count': 1, 'matrix': [[0.+0.j 1.+0.j], [1.+0.j 0.+0.j]])
Sum of other (scaled) observables: Sum(TensorProduct(X('qubit_count': 1), X('qubit_count': 1)), TensorProduct(Z('qubit_count': 1), Z('qubit_count': 1)))
```

## Parameters
<a name="braket-result-types-parameters"></a>

Les circuits peuvent intégrer des paramètres libres. Ces paramètres libres ne doivent être créés qu'une seule fois pour être exécutés plusieurs fois et peuvent être utilisés pour calculer des dégradés. 

Chaque paramètre gratuit utilise un nom codé sous forme de chaîne qui permet de : 
+ Définir les valeurs des paramètres
+ Identifier les paramètres à utiliser

```
from braket.circuits import Circuit, FreeParameter, observables
from braket.parametric import FreeParameter

theta = FreeParameter("theta")
phi = FreeParameter("phi")
circ = Circuit().h(0).rx(0, phi).ry(0, phi).cnot(0, 1).xx(0, 1, theta)
```

## Gradient adjoint
<a name="braket-result-types-adjoint-gradient"></a>

L'SV1appareil calcule le gradient adjoint d'une valeur attendue observable, y compris un hamiltonien à plusieurs termes. Pour différencier les paramètres, spécifiez leur nom (sous forme de chaîne) ou par référence directe.

```
from braket.aws import AwsDevice
from braket.devices import Devices

device = AwsDevice(Devices.Amazon.SV1)

circ.adjoint_gradient(observable=3 * Observable.Z(0) @ Observable.Z(1) - 0.5 * observables.X(0), parameters = ["phi", theta])
```

Le fait de transmettre des valeurs de paramètres fixes en tant qu'arguments à un circuit paramétré supprimera les paramètres libres. L'exécution de ce circuit `AdjointGradient` produit une erreur, car les paramètres libres n'existent plus. L'exemple de code suivant illustre l'utilisation correcte et incorrecte :

```
# Will error, as no free parameters will be present
#device.run(circ(0.2), shots=0)

# Will succeed
device.run(circ, shots=0, inputs={'phi': 0.2, 'theta': 0.2})
```

# Obtenir des conseils d'experts
<a name="braket-expert-advice"></a>

Connectez-vous à des experts en informatique quantique directement dans la console de gestion Braket pour obtenir des conseils supplémentaires sur vos charges de travail. 

Pour explorer les options de conseil d'expert via Braket Direct, ouvrez la console Braket, choisissez **Braket Direct** dans le volet de gauche et accédez à la section Conseils **d'experts**. Les options de conseil d'experts suivantes sont disponibles :
+ Heures de **bureau de Braket : Les heures** de bureau de Braket sont des sessions individuelles, premier arrivé, premier servi, qui ont lieu tous les mois. Chaque créneau horaire disponible est de 30 minutes et est gratuit. Discuter avec des experts de Braket peut vous aider à passer plus rapidement de l'idée à l'exécution en explorant l' use-case-to-deviceajustement, en identifiant les options permettant d'utiliser au mieux Braket pour votre algorithme et en obtenant des recommandations sur la manière d'utiliser certaines fonctionnalités de Braket, telles qu'Amazon Braket Hybrid Jobs, Braket Pulse ou Analog Hamiltonian Simulation.
  + Pour vous inscrire aux heures d'ouverture de Braket, sélectionnez **S'inscrire** et renseignez les informations de contact, les détails de la charge de travail et les sujets de discussion souhaités.
  + Vous recevrez une invitation au calendrier pour le prochain créneau disponible par e-mail.
**Note**  
Pour les problèmes urgents ou les questions de dépannage rapide, nous vous recommandons de contacter le [AWS Support](https://console.aws.amazon.com/support/home#/case/create?issueType=technical). Pour les questions non urgentes, vous pouvez également utiliser le [forum AWS Re:post](https://repost.aws/tags/questions/TAhMWeHkpfSMSCxIFNqcqYog?view=all) ou le [Quantum Computing Stack Exchange](https://quantumcomputing.stackexchange.com/questions/ask), où vous pouvez consulter les réponses aux questions précédentes et en poser de nouvelles.
+ **Offres des fournisseurs de matériel quantique :**IonQ,QuEra, et Rigetti chacun propose des offres de services professionnels via AWS Marketplace.
  + Pour découvrir leurs offres, sélectionnez **Connect** et parcourez leurs listes.
  + Pour en savoir plus sur les offres de services professionnels sur le AWS Marketplace, consultez la section [Produits de services professionnels](https://docs.aws.amazon.com/marketplace/latest/buyerguide/buyer-proserv-products.html).
+ **AmazonQuantum Solutions Lab (QSL) :** Le QSL est une équipe de recherche collaborative et de services professionnels composée d'experts en informatique quantique qui peuvent vous aider à explorer efficacement l'informatique quantique et à évaluer les performances actuelles de cette technologie.
  + Pour contacter le QSL, sélectionnez **Connect**, puis renseignez les informations de contact et les détails du cas d'utilisation.
  + L'équipe QSL vous contactera par e-mail pour vous indiquer les prochaines étapes.

# Exécutez vos circuits avec OpenQASM 3.0
<a name="braket-openqasm"></a>

 AmazonBraket prend désormais en charge [OpenQASM 3.0](https://openqasm.com/) pour les dispositifs quantiques et les simulateurs basés sur des portes. Ce guide de l'utilisateur fournit des informations sur le sous-ensemble d'OpenQASM 3.0 pris en charge par Braket. [Les clients de Braket ont désormais le choix de soumettre des circuits Braket avec le [SDK](braket-constructing-circuit.md) ou de fournir directement des chaînes OpenQASM 3.0 à tous les appareils basés sur un portail avec l'[API Amazon Braket et le SDK Amazon Braket](https://docs.aws.amazon.com/braket/latest/APIReference/Welcome.html) Python.](https://github.com/aws/amazon-braket-sdk-python)

Les rubriques de ce guide vous présentent divers exemples illustrant comment effectuer les tâches quantiques suivantes.
+  [Créez et soumettez des tâches quantiques OpenQASM sur différents appareils Braket](braket-openqasm-create-submit-task.md) 
+  [Accédez aux opérations prises en charge et aux types de résultats](braket-openqasm-device-support.md#braket-openqasm-supported-operations-results-result-types) 
+  [Simulez le bruit avec OpenQASM](braket-openqasm-noise-simulation.md) 
+  [Utiliser la compilation textuelle avec OpenQASM](braket-openqasm-verbatim-compilation.md) 
+  [Résoudre les problèmes liés à OpenQASM](https://docs.aws.amazon.com/braket/latest/developerguide/braket-troubleshooting-openqasm.html) 

Ce guide fournit également une introduction à certaines fonctionnalités spécifiques au matériel qui peuvent être implémentées avec OpenQASM 3.0 sur Braket et des liens vers d'autres ressources.

**Topics**
+ [Qu'est-ce qu'OpenQASM 3.0 ?](#braket-openqasm-what-is)
+ [Quand utiliser OpenQASM 3.0](#braket-openqasm-when-to-use)
+ [Comment fonctionne OpenQASM 3.0](#braket-openqasm-how-it-works)
+ [Conditions préalables](#braket-openqasm-prerequisites)
+ [Quelles sont les fonctionnalités d'OpenQASM prises en charge par Braket ?](braket-openqasm-supported-features.md)
+ [Créez et soumettez un exemple de tâche quantique OpenQASM 3.0](braket-openqasm-create-submit-task.md)
+ [Support d'OpenQASM sur différents appareils Braket](braket-openqasm-device-support.md)
+ [Simulez le bruit avec OpenQASM 3.0](braket-openqasm-noise-simulation.md)
+ [Qubitrecâblage avec OpenQASM 3.0](braket-openqasm-rewire-qubits.md)
+ [Compilation Verbatim avec OpenQASM 3.0](braket-openqasm-verbatim-compilation.md)
+ [La console Braket](#braket-openqasm-braket-console)
+ [Ressources supplémentaires](#braket-openqasm-more-resources)
+ [Calculer des dégradés avec OpenQASM 3.0](braket-openqasm-computing-gradients.md)
+ [Mesurer des qubits spécifiques avec OpenQASM 3.0](braket-openqasm-measure-qubits.md)

## Qu'est-ce qu'OpenQASM 3.0 ?
<a name="braket-openqasm-what-is"></a>

L'Open Quantum Assembly Language (OpenQASM) est une [représentation intermédiaire](https://en.wikipedia.org/wiki/Intermediate_representation) pour les instructions quantiques. OpenQASM est un framework open source largement utilisé pour la spécification de programmes quantiques pour les appareils basés sur des portes. Avec OpenQASM, les utilisateurs peuvent programmer les portes quantiques et les opérations de mesure qui constituent les éléments de base du calcul quantique. La version précédente d'OpenQASM (2.0) était utilisée par un certain nombre de bibliothèques de programmation quantique pour décrire des programmes de base.

La nouvelle version d'OpenQASM (3.0) étend la version précédente pour inclure davantage de fonctionnalités, telles que le contrôle du niveau des impulsions, le chronométrage des portes et le flux de contrôle classique pour combler le fossé entre l'interface utilisateur final et le langage de description du matériel. Les détails et les spécifications de la version 3.0 actuelle sont disponibles sur la spécification GitHub [OpenQASM 3.x Live](https://github.com/openqasm/openqasm). Le futur développement d'OpenQASM est régi par le [comité de pilotage technique](https://aws.amazon.com/blogs/quantum-computing/aws-joins-the-openqasm-3-0-technical-steering-committee/) d'OpenQASM 3.0, dont AWS il est membre aux côtés d'IBM, Microsoft et de l'université d'Innsbruck.

## Quand utiliser OpenQASM 3.0
<a name="braket-openqasm-when-to-use"></a>

OpenQASM fournit un cadre expressif permettant de spécifier des programmes quantiques par le biais de contrôles de bas niveau qui ne sont pas spécifiques à une architecture, ce qui le rend parfaitement adapté en tant que représentation sur plusieurs appareils basés sur des portes. La prise en charge d'OpenQASM par Braket favorise son adoption en tant qu'approche cohérente du développement d'algorithmes quantiques basés sur des portes, réduisant ainsi le besoin pour les utilisateurs d'apprendre et de gérer des bibliothèques dans plusieurs frameworks.

Si vous avez des bibliothèques de programmes existantes dans OpenQASM 3.0, vous pouvez les adapter pour les utiliser avec Braket plutôt que de réécrire complètement ces circuits. Les chercheurs et les développeurs devraient également bénéficier d'un nombre croissant de bibliothèques tierces disponibles prenant en charge le développement d'algorithmes dans OpenQASM.

## Comment fonctionne OpenQASM 3.0
<a name="braket-openqasm-how-it-works"></a>

Support d'OpenQASM 3.0 par Braket assure la parité des fonctionnalités avec la représentation intermédiaire actuelle. Cela signifie que tout ce que vous pouvez faire aujourd'hui sur des appareils matériels et des simulateurs à la demande avec Braket, vous pouvez le faire avec OpenQASM en utilisant Braket. API Vous pouvez exécuter des programmes OpenQASM 3.0 en fournissant directement des chaînes OpenQASM à tous les périphériques basés sur un portail, de la même manière que les circuits sont actuellement fournis aux périphériques sur Braket. Les utilisateurs de Braket peuvent également intégrer des bibliothèques tierces compatibles avec OpenQASM 3.0. Le reste de ce guide explique comment développer des représentations OpenQASM à utiliser avec Braket.

## Conditions préalables
<a name="braket-openqasm-prerequisites"></a>

[Pour utiliser OpenQASM 3.0 sur Amazon Braket, vous devez disposer de la version v1.8.0 des schémas Python Amazon Braket et de la version v1.17.0 ou supérieure du SDK [Amazon Braket Python](https://github.com/aws/amazon-braket-schemas-python).](https://github.com/aws/amazon-braket-sdk-python)

Si vous utilisez Amazon Braket pour la première fois, vous devez activer Amazon Braket. Pour obtenir des instructions, consultez [Activer Amazon Braket](https://docs.aws.amazon.com/braket/latest/developerguide/braket-enable-overview.html).

# Quelles sont les fonctionnalités d'OpenQASM prises en charge par Braket ?
<a name="braket-openqasm-supported-features"></a>

La section suivante répertorie les types de données, les instructions et les instructions pragma d'OpenQASM 3.0 pris en charge par Braket.

**Topics**
+ [Types de données OpenQASM pris en charge](#braket-openqasm-supported-features-datatypes)
+ [Déclarations OpenQASM prises en charge](#braket-openqasm-supported-features-statements)
+ [Pragmas OpenQASM de Braket](#braket-openqasm-supported-features-pragmas)
+ [Support des fonctionnalités avancées pour OpenQASM sur le simulateur local](#braket-openqasm-supported-features-advanced-feature-local-simulator)
+ [Opérations et grammaire prises en charge avec OpenPulse](#braket-openpulse-supported-operations-grammar)

## Types de données OpenQASM pris en charge
<a name="braket-openqasm-supported-features-datatypes"></a>

Les types de données OpenQASM suivants sont pris en charge par Amazon Braket.
+ Des entiers non négatifs sont utilisés pour les indices de qubits (virtuels et physiques) :
  +  `cnot q[0], q[1];` 
  +  `h $0;` 
+ Des nombres à virgule flottante ou des constantes peuvent être utilisés pour les angles de rotation des portes :
  +  `rx(-0.314) $0;` 
  +  `rx(pi/4) $0;` 

**Note**  
pi est une constante intégrée à OpenQASM et ne peut pas être utilisée comme nom de paramètre.
+ Les tableaux de nombres complexes (avec la `im` notation OpenQASM pour les parties imaginaires) sont autorisés dans les pragmas de type résultat pour définir les observables hermitiens généraux et dans les pragmas unitaires :
  +  `#pragma braket unitary [[0, -1im], [1im, 0]] q[0]` 
  +  `#pragma braket result expectation hermitian([[0, -1im], [1im, 0]]) q[0]` 

## Déclarations OpenQASM prises en charge
<a name="braket-openqasm-supported-features-statements"></a>

Les instructions OpenQASM suivantes sont prises en charge par Amazon Braket.
+  `Header: OPENQASM 3;` 
+ Déclarations binaires classiques :
  +  `bit b1;`(de manière équivalente,`creg b1;`)
  +  `bit[10] b2;`(de manière équivalente,`creg b2[10];`)
+ Déclarations Qubit :
  +  `qubit b1;`(de manière équivalente,`qreg b1;`)
  +  `qubit[10] b2;`(de manière équivalente,`qreg b2[10];`)
+ Indexation au sein de tableaux : `q[0]` 
+ Entrée : `input float alpha;` 
+ spécification physique qubits : `$0` 
+ Portails et opérations pris en charge sur un appareil :
  +  `h $0;` 
  +  `iswap q[0], q[1];` 

**Note**  
Les portes prises en charge par un périphérique se trouvent dans les propriétés de l'appareil pour les actions OpenQASM ; aucune définition de porte n'est nécessaire pour utiliser ces portes.
+ Relevés verbatim box. Actuellement, nous ne prenons pas en charge la notation de la durée des boîtes. Les portes natives et physiques qubits sont obligatoires dans les boîtes de saisie des verbatims.

```
#pragma braket verbatim
box{
    rx(0.314) $0;
}
```
+ Mesure et attribution de mesures sur qubits ou sur un qubit registre complet.
  +  `measure $0;` 
  +  `measure q;` 
  +  `measure q[0];` 
  +  `b = measure q;` 
  +  `measure q → b;` 
+ Les instructions Barrier fournissent un contrôle explicite sur la compilation et l'exécution des circuits en empêchant la réorganisation des portes et les optimisations au-delà des limites des barrières. Ils appliquent également un ordre temporel strict lors de l'exécution, garantissant ainsi toutes les opérations avant la fin d'une barrière avant le début des opérations suivantes.
  +  `barrier;` 
  +  `barrier q[0], q[1];` 
  +  `barrier $3, $6;` 

## Pragmas OpenQASM de Braket
<a name="braket-openqasm-supported-features-pragmas"></a>

Les instructions pragma OpenQASM suivantes sont prises en charge par Amazon Braket.
+ Pragmas relatifs au bruit
  +  `#pragma braket noise bit_flip(0.2) q[0]` 
  +  `#pragma braket noise phase_flip(0.1) q[0]` 
  +  `#pragma braket noise pauli_channel` 
+ Pragmas textuels
  +  `#pragma braket verbatim` 
+ Type de résultat : pragmas
  + Types de résultats invariants de base :
    + Vecteur d'état : `#pragma braket result state_vector` 
    + Matrice de densité : `#pragma braket result density_matrix` 
  + Pragmas de calcul du gradient :
    + Dégradé adjoint : `#pragma braket result adjoint_gradient expectation(2.2 * x[0] @ x[1]) all` 
  + Types de résultats de base Z :
    + Amplitude : `#pragma braket result amplitude "01"` 
    + Probabilité : `#pragma braket result probability q[0], q[1]` 
  + Types de résultats basés sur une rotation
    + Espérance : `#pragma braket result expectation x(q[0]) @ y([q1])` 
    + Écart : `#pragma braket result variance hermitian([[0, -1im], [1im, 0]]) $0` 
    + Échantillon : `#pragma braket result sample h($1)` 

**Note**  
OpenQASM 3.0 est rétrocompatible avec OpenQASM 2.0, de sorte que les programmes écrits à l'aide de la version 2.0 peuvent s'exécuter sur Braket. Cependant, les fonctionnalités d'OpenQASM 3.0 prises en charge par Braket présentent quelques différences syntaxiques mineures, telles que `qreg` vs et vs. `creg` `qubit` `bit` Il existe également des différences dans la syntaxe des mesures, et celles-ci doivent être prises en charge par leur syntaxe correcte.

## Support des fonctionnalités avancées pour OpenQASM sur le simulateur local
<a name="braket-openqasm-supported-features-advanced-feature-local-simulator"></a>

Il `LocalSimulator` prend en charge les fonctionnalités avancées d'OpenQASM qui ne sont pas proposées dans le cadre des QPU de Braket ou des simulateurs à la demande. La liste de fonctionnalités suivante n'est prise en charge que dans `LocalSimulator` :
+ Modificateurs de portail
+ Portails intégrés OpenQASM
+ Variables classiques
+ Opérations classiques
+ Portails personnalisés
+ Contrôle classique
+ fichiers QASM
+ Sous-programmes

Pour des exemples de chaque fonctionnalité avancée, consultez cet [exemple de bloc-notes](https://github.com/aws/amazon-braket-examples/blob/main/examples/braket_features/Simulating_Advanced_OpenQASM_Programs_with_the_Local_Simulator.ipynb). [Pour la spécification complète d'OpenQASM, consultez le site Web d'OpenQASM.](https://openqasm.com/language/index.html)

## Opérations et grammaire prises en charge avec OpenPulse
<a name="braket-openpulse-supported-operations-grammar"></a>

 **Types de OpenPulse données pris en charge** 

Blocs d'appels :

```
cal {
    ...
}
```

Blocs de décalcomanie :

```
// 1 qubit
defcal x $0 {
...
}

// 1 qubit w. input parameters as constants
defcal my_rx(pi) $0 {
...
}

// 1 qubit w. input parameters as free parameters
defcal my_rz(angle theta) $0 {
...
}

// 2 qubit (above gate args are also valid)
defcal cz $1, $0 {
...
}
```

Cadres :

```
frame my_frame = newframe(port_0, 4.5e9, 0.0);
```

Formes d'onde :

```
// prebuilt
waveform my_waveform_1 = constant(1e-6, 1.0);

//arbitrary
waveform my_waveform_2 = {0.1 + 0.1im, 0.1 + 0.1im, 0.1, 0.1};
```

 **Exemple d'étalonnage de portail personnalisé :** 

```
cal {
    waveform wf1 = constant(1e-6, 0.25);
}

defcal my_x $0 {
   play(wf1, q0_rf_frame);
}

defcal my_cz $1, $0 {
    barrier q0_q1_cz_frame, q0_rf_frame;
    play(q0_q1_cz_frame, wf1);
    delay[300ns] q0_rf_frame
    shift_phase(q0_rf_frame, 4.366186381749424);
    delay[300ns] q0_rf_frame;
    shift_phase(q0_rf_frame.phase, 5.916747563126659);
    barrier q0_q1_cz_frame, q0_rf_frame;
    shift_phase(q0_q1_cz_frame, 2.183093190874712);
}

bit[2] ro;
my_x $0;
my_cz $1,$0;
c[0] = measure $0;
```

 **Exemple d'impulsion arbitraire :** 

```
bit[2] ro;
cal {
    waveform wf1 = {0.1 + 0.1im, 0.1 + 0.1im, 0.1, 0.1};
    barrier q0_drive, q0_q1_cross_resonance;
    play(q0_q1_cross_resonance, wf1);
    delay[300ns] q0_drive;
    shift_phase(q0_drive, 4.366186381749424);
    delay[300dt] q0_drive;
   barrier q0_drive, q0_q1_cross_resonance;
   play(q0_q1_cross_resonance, wf1);
    ro[0] = capture_v0(r0_measure);
    ro[1] = capture_v0(r1_measure);
}
```

# Créez et soumettez un exemple de tâche quantique OpenQASM 3.0
<a name="braket-openqasm-create-submit-task"></a>

Vous pouvez utiliser le SDK Amazon Braket Python, Boto3 ou le pour envoyer des tâches quantiques OpenQASM 3.0 AWS CLI à un appareil Amazon Braket.

**Topics**
+ [Exemple de programme OpenQASM 3.0](#braket-openqasm-example-program)
+ [Utilisez le SDK Python pour créer des tâches quantiques OpenQASM 3.0](#braket-openqasm-create-tasks-with-python-sdk)
+ [Utilisez Boto3 pour créer des tâches quantiques OpenQASM 3.0](#braket-openqasm-create-tasks-with-boto3)
+ [Utilisez le AWS CLI pour créer des tâches OpenQASM 3.0](#braket-openqasm-create-tasks-with-aws-cli)

## Exemple de programme OpenQASM 3.0
<a name="braket-openqasm-example-program"></a>

[Pour créer une tâche OpenQASM 3.0, vous pouvez commencer par un programme OpenQASM 3.0 de base (ghz.qasm) qui prépare un état GHZ comme indiqué dans l'exemple suivant.](https://en.wikipedia.org/wiki/Greenberger%E2%80%93Horne%E2%80%93Zeilinger_state)

```
// ghz.qasm
// Prepare a GHZ state
OPENQASM 3;

qubit[3] q;
bit[3] c;

h q[0];
cnot q[0], q[1];
cnot q[1], q[2];

c = measure q;
```

## Utilisez le SDK Python pour créer des tâches quantiques OpenQASM 3.0
<a name="braket-openqasm-create-tasks-with-python-sdk"></a>

Vous pouvez utiliser le [SDK Amazon Braket Python](https://github.com/aws/amazon-braket-sdk-python) pour envoyer ce programme à un appareil Amazon Braket à l'aide du code suivant. Assurez-vous de remplacer l'exemple d'emplacement du compartiment Amazon S3 « amzn-s3-demo-bucket » par le nom de votre propre compartiment Amazon S3.

```
with open("ghz.qasm", "r") as ghz:
    ghz_qasm_string = ghz.read()

# Import the device module
from braket.aws import AwsDevice
# Choose the Rigetti device
device = AwsDevice("arn:aws:braket:us-west-1::device/qpu/rigetti/Ankaa-3")
from braket.ir.openqasm import Program

program = Program(source=ghz_qasm_string)
my_task = device.run(program)

# Specify an optional s3 bucket location and number of shots
s3_location = ("amzn-s3-demo-bucket", "openqasm-tasks")
my_task = device.run(
    program,
    s3_location,
    shots=100,
)
```

## Utilisez Boto3 pour créer des tâches quantiques OpenQASM 3.0
<a name="braket-openqasm-create-tasks-with-boto3"></a>

Vous pouvez également utiliser le [SDK AWS Python pour Braket (Boto3)](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/braket.html) pour créer les tâches quantiques à l'aide de chaînes OpenQASM 3.0, comme indiqué dans l'exemple suivant. [L'extrait de code suivant fait référence à ghz.qasm qui prépare un état GHZ comme indiqué ci-dessus.](https://en.wikipedia.org/wiki/Greenberger%E2%80%93Horne%E2%80%93Zeilinger_state)

```
import boto3
import json

my_bucket = "amzn-s3-demo-bucket"
s3_prefix = "openqasm-tasks"

with open("ghz.qasm") as f:
    source = f.read()

action = {
    "braketSchemaHeader": {
        "name": "braket.ir.openqasm.program",
        "version": "1"
    },
    "source": source
}
device_parameters = {}
device_arn = "arn:aws:braket:us-west-1::device/qpu/rigetti/Ankaa-3"
shots = 100

braket_client = boto3.client('braket', region_name='us-west-1')
rsp = braket_client.create_quantum_task(
    action=json.dumps(
        action
    ),
    deviceParameters=json.dumps(
        device_parameters
    ),
    deviceArn=device_arn,
    shots=shots,
    outputS3Bucket=my_bucket,
    outputS3KeyPrefix=s3_prefix,
)
```

## Utilisez le AWS CLI pour créer des tâches OpenQASM 3.0
<a name="braket-openqasm-create-tasks-with-aws-cli"></a>

La [AWS Command Line Interface (CLI)](https://aws.amazon.com/cli/) peut également être utilisée pour soumettre des programmes OpenQASM 3.0, comme indiqué dans l'exemple suivant.

```
aws braket create-quantum-task \
    --region "us-west-1" \
    --device-arn "arn:aws:braket:us-west-1::device/qpu/rigetti/Ankaa-3" \
    --shots 100 \
    --output-s3-bucket "amzn-s3-demo-bucket" \
    --output-s3-key-prefix "openqasm-tasks" \
    --action '{
        "braketSchemaHeader": {
            "name": "braket.ir.openqasm.program",
            "version": "1"
        },
        "source": $(cat ghz.qasm)
    }'
```

# Support d'OpenQASM sur différents appareils Braket
<a name="braket-openqasm-device-support"></a>

Pour les appareils compatibles avec OpenQASM 3.0, le `action` champ prend en charge une nouvelle action par le biais de la `GetDevice` réponse, comme indiqué dans l'exemple suivant pour les Rigetti périphériques et. IonQ

```
//OpenQASM as available with the Rigetti device capabilities
{
    "braketSchemaHeader": {
        "name": "braket.device_schema.rigetti.rigetti_device_capabilities",
        "version": "1"
    },
    "service": {...},
    "action": {
        "braket.ir.jaqcd.program": {...},
        "braket.ir.openqasm.program": {
            "actionType": "braket.ir.openqasm.program",
            "version": [
                "1"
            ],
            ….
        }
    }
}

//OpenQASM as available with the IonQ device capabilities
{
    "braketSchemaHeader": {
        "name": "braket.device_schema.ionq.ionq_device_capabilities",
        "version": "1"
    },
    "service": {...},
    "action": {
        "braket.ir.jaqcd.program": {...},
        "braket.ir.openqasm.program": {
            "actionType": "braket.ir.openqasm.program",
            "version": [
                "1"
            ],
            ….
        }
    }
}
```

Pour les appareils qui prennent en charge le contrôle du pouls, `pulse` le champ est affiché dans la `GetDevice` réponse. L'exemple suivant montre ce `pulse` champ pour le Rigetti périphérique.

```
// Rigetti
{
  "pulse": {
    "braketSchemaHeader": {
      "name": "braket.device_schema.pulse.pulse_device_action_properties",
      "version": "1"
    },
    "supportedQhpTemplateWaveforms": {
      "constant": {
        "functionName": "constant",
        "arguments": [
          {
            "name": "length",
            "type": "float",
            "optional": false
          },
          {
            "name": "iq",
            "type": "complex",
            "optional": false
          }
        ]
      },
      ...
    },
    "ports": {
      "q0_ff": {
        "portId": "q0_ff",
        "direction": "tx",
        "portType": "ff",
        "dt": 1e-9,
        "centerFrequencies": [
          375000000
        ]
      },
      ...
    },
    "supportedFunctions": {
      "shift_phase": {
        "functionName": "shift_phase",
        "arguments": [
          {
            "name": "frame",
            "type": "frame",
            "optional": false
          },
          {
            "name": "phase",
            "type": "float",
            "optional": false
          }
        ]
      },
     ...
    },
    "frames": {
      "q0_q1_cphase_frame": {
        "frameId": "q0_q1_cphase_frame",
        "portId": "q0_ff",
        "frequency": 462475694.24460185,
        "centerFrequency": 375000000,
        "phase": 0,
        "associatedGate": "cphase",
        "qubitMappings": [
          0,
          1
        ]
      },
      ...
    },
    "supportsLocalPulseElements": false,
    "supportsDynamicFrames": false,
    "supportsNonNativeGatesWithPulses": false,
    "validationParameters": {
      "MAX_SCALE": 4,
      "MAX_AMPLITUDE": 1,
      "PERMITTED_FREQUENCY_DIFFERENCE": 400000000
    }
  }
}
```

Les champs précédents détaillent les éléments suivants :

 **Ports :** 

Décrit les ports de périphériques externes (`extern`) prédéfinis déclarés sur le QPU en plus des propriétés associées au port donné. Tous les ports répertoriés dans cette structure sont prédéclarés en tant qu'identifiants valides dans le `OpenQASM 3.0` programme soumis par l'utilisateur. Les propriétés supplémentaires d'un port sont les suivantes :
+ Identifiant du port (PortID)
  + Le nom de port déclaré comme identifiant dans OpenQASM 3.0.
+ Direction (direction)
  + La direction du port. Les ports d'entraînement transmettent des impulsions (direction « tx »), tandis que les ports de mesure reçoivent des impulsions (direction « rx »).
+ Type de port (PortType)
  + Type d'action dont ce port est responsable (par exemple, drive, capture ou ff - fast-flux).
+ Dt (dt)
  + Durée en secondes qui représente un seul pas de temps d'échantillonnage sur le port donné.
+ Mappages de qubits (QubitMappings)
  + Les qubits associés au port donné.
+ Fréquences centrales (CenterFrequencies)
  + Liste des fréquences centrales associées pour toutes les trames prédéclarées ou définies par l'utilisateur sur le port. Pour plus d'informations, reportez-vous à la section Cadres.
+ Propriétés spécifiques à QHP () qhpSpecificProperties
  + Une carte facultative détaillant les propriétés existantes concernant le port spécifique au QHP.

 **Cadres :** 

Décrit les cadres externes préfabriqués déclarés sur le QPU ainsi que les propriétés associées aux cadres. Toutes les trames répertoriées dans cette structure sont prédéclarées comme des identifiants valides dans le `OpenQASM 3.0` programme soumis par l'utilisateur. Les propriétés supplémentaires d'un cadre sont les suivantes :
+ ID du cadre (FrameID)
  + Le nom du cadre déclaré comme identifiant dans OpenQASM 3.0.
+ Identifiant du port (ID du port)
  + Le port matériel associé à la trame.
+ Fréquence (fréquence)
  + Fréquence initiale par défaut de la trame.
+ Fréquence centrale (CenterFrequency)
  + Le centre de la bande passante de fréquence de la trame. Généralement, les trames ne peuvent être ajustées qu'à une certaine bande passante autour de la fréquence centrale. Par conséquent, les ajustements de fréquence doivent rester dans un delta donné par rapport à la fréquence centrale. Vous pouvez trouver la valeur de bande passante dans les paramètres de validation.
+ Phase (phase)
  + Phase initiale par défaut de la trame.
+ Porte associée (porte associée)
  + Les portes associées à la trame donnée.
+ Mappages de qubits (QubitMappings)
  + Les qubits associés à la trame donnée.
+ Propriétés spécifiques à QHP () qhpSpecificProperties
  + Une carte optionnelle détaillant les propriétés existantes concernant le cadre spécifique au QHP.

 **SupportsDynamicFrames:** 

Décrit si un cadre peut être déclaré `cal` ou bloqué par `defcal` le biais de la OpenPulse `newframe` fonction. Si cette valeur est fausse, seules les images répertoriées dans la structure des cadres peuvent être utilisées dans le programme.

 **SupportedFunctions:** 

Décrit les OpenPulse fonctions prises en charge par le périphérique en plus des arguments, des types d'arguments et des types de retour associés aux fonctions données. Pour voir des exemples d'utilisation des OpenPulse fonctions, reportez-vous à la [OpenPulsespécification](https://openqasm.com/language/openpulse.html). À l'heure actuelle, Braket prend en charge :
+ shift\$1phase
  + Déplace la phase d'une image d'une valeur spécifiée
+ set\$1phase
  + Définit la phase du cadre à la valeur spécifiée
+ phases d'échange
  + Échange les phases entre deux images.
+ shift\$1frequency
  + Déplace la fréquence d'une image d'une valeur spécifiée
+ set\$1frequency
  + Définit la fréquence de l'image à la valeur spécifiée
+ jouer
  + Planifie une forme d'onde
+ capture\$1v0
  + Renvoie la valeur d'une image de capture dans un registre de bits

 **SupportedQhpTemplateWaveforms:** 

Décrit les fonctions de forme d'onde prédéfinies disponibles sur le périphérique ainsi que les arguments et les types associés. Par défaut, Braket Pulse propose des routines de forme d'onde prédéfinies sur tous les appareils, à savoir :

 ***Constante*** 

![\[Équation mathématique montrant une fonction constante avec les paramètres t, tau et iq où le résultat est toujours égal à iq.\]](http://docs.aws.amazon.com/fr_fr/braket/latest/developerguide/images/ConstantFunction.png)


 `τ`est la longueur de la forme d'onde et `iq` est un nombre complexe.

```
def constant(length, iq)
```

 ***Gaussien*** 

![\[Équation mathématique montrant la fonction gaussienne avec les paramètres t, tau, sigma, A=1 et Zae=0.\]](http://docs.aws.amazon.com/fr_fr/braket/latest/developerguide/images/GaussianFunction.png)


 `τ`est la longueur de la forme d'onde, `σ` la largeur de la gaussienne et l'amplitude`A`. Si elle est réglée `ZaE` sur`True`, la valeur gaussienne est décalée et redimensionnée de telle sorte qu'elle soit égale à zéro au début et à la fin de la forme d'onde, et qu'elle atteigne son maximum. `A`

```
def gaussian(length, sigma, amplitude=1, zero_at_edges=False)
```

 ***DRAG Gaussien*** 

![\[Équation mathématique pour la distribution gaussienne DRAG avec les paramètres t, tau, sigma, beta, A=1 et zAE=0.\]](http://docs.aws.amazon.com/fr_fr/braket/latest/developerguide/images/DRAGGaussianFunction.png)


 `τ`est la longueur de la forme d'onde, `σ` est la largeur de la gaussienne, `β` est un paramètre libre et `A` est l'amplitude. Si cette valeur est `ZaE` définie sur`True`, la valeur gaussienne de suppression des dérivées par porte adiabatique (DRAG) est décalée et redimensionnée de telle sorte qu'elle soit égale à zéro au début et à la fin de la forme d'onde, et que la partie réelle atteigne son maximum. `A` Pour plus d'informations sur la forme d'onde DRAG, consultez l'article [Simple Pulses for Elimination of Leak in Weakly Nonlinear](https://doi.org/10.1103/PhysRevLett.103.110501) Qubits.

```
def drag_gaussian(length, sigma, beta, amplitude=1, zero_at_edges=False)
```

 ***Place Erf*** 

![\[Équation mathématique pour la distribution du carré d'Erf avec les paramètres t, longueur, largeur, sigma, A=1 et zAE=0.\]](http://docs.aws.amazon.com/fr_fr/braket/latest/developerguide/images/ErfSquareFunction.PNG)


Où `L` est la longueur, `W` est la largeur de la forme d'onde, `σ` définit la vitesse à laquelle les arêtes montent et descendent`t22=(L+W)/2`, `t1​=(L−W)/2` et quelle `A` est l'amplitude. Si elle est réglée `ZaE` sur`True`, la valeur gaussienne est décalée et redimensionnée de telle sorte qu'elle soit égale à zéro au début et à la fin de la forme d'onde, et qu'elle atteigne son maximum. `A` L'équation suivante est la version redimensionnée de la forme d'onde.

![\[Équation mathématique pour la distribution du carré d'Erf redimensionnée avec les paramètres Zae=1.\]](http://docs.aws.amazon.com/fr_fr/braket/latest/developerguide/images/RescaledErfSquareFunction.PNG)


Où `a=erf(W/2σ)` et`b=erf(-t1​/σ)/2+erf(t2​/σ)/2`.

```
def erf_square(length, width, sigma, amplitude=1, zero_at_edges=False)
```

 **SupportsLocalPulseElements:** 

Décrit si les éléments d'impulsion, tels que les ports, les trames et les formes d'onde, peuvent être définis localement par `defcal` blocs. Si la valeur est`false`, les éléments doivent être définis par `cal` blocs.

 **SupportsNonNativeGatesWithPulses:** 

Décrit si nous pouvons ou ne pouvons pas utiliser des portes non natives en combinaison avec des programmes d'impulsions. Par exemple, vous ne pouvez pas utiliser une porte non native comme une `H` porte dans un programme sans d'abord définir la porte `defcal` pour le qubit utilisé. Vous pouvez trouver la liste des `nativeGateSet` clés de porte natives sous les fonctionnalités de l'appareil.

 **ValidationParameters:** 

Décrit les limites de validation des éléments d'impulsion, notamment :
+ Échelle maximale/Valeurs d'amplitude maximales pour les formes d'onde (arbitraires et prédéfinies)
+ Largeur de bande de fréquence maximale à partir de la fréquence centrale fournie en Hz
+ Pouls minimal length/duration en secondes
+ Pouls maximal length/duration en secondes

## Opérations, résultats et types de résultats pris en charge avec OpenQASM
<a name="braket-openqasm-supported-operations-results-result-types"></a>

Pour savoir quelles fonctionnalités d'OpenQASM 3.0 sont prises en charge par chaque appareil, vous pouvez vous référer à la `braket.ir.openqasm.program` clé dans le `action` champ de sortie des capacités de l'appareil. Par exemple, les opérations prises en charge et les types de résultats disponibles pour le simulateur SV1 Braket State Vector sont les suivants.

```
...
  "action": {
    "braket.ir.jaqcd.program": {
      ...
    },
 "braket.ir.openqasm.program": {
      "version": [
        "1.0"
      ],
      "actionType": "braket.ir.openqasm.program",
      "supportedOperations": [
        "ccnot",
        "cnot",
        "cphaseshift",
        "cphaseshift00",
        "cphaseshift01",
        "cphaseshift10",
        "cswap",
        "cy",
        "cz",
        "h",
        "i",
        "iswap",
        "pswap",
        "phaseshift",
        "rx",
        "ry",
        "rz",
        "s",
        "si",
        "swap",
        "t",
        "ti",
        "v",
        "vi",
        "x",
        "xx",
        "xy",
        "y",
        "yy",
        "z",
        "zz"
      ],
      "supportedPragmas": [
        "braket_unitary_matrix"
      ],
      "forbiddenPragmas": [],
      "maximumQubitArrays": 1,
      "maximumClassicalArrays": 1,
      "forbiddenArrayOperations": [
        "concatenation",
        "negativeIndex",
        "range",
        "rangeWithStep",
        "slicing",
        "selection"
      ],
      "requiresAllQubitsMeasurement": true,
      "supportsPhysicalQubits": false,
      "requiresContiguousQubitIndices": true,
      "disabledQubitRewiringSupported": false,
      "supportedResultTypes": [
        {
          "name": "Sample",
          "observables": [
            "x",
            "y",
            "z",
            "h",
            "i",
            "hermitian"
          ],
          "minShots": 1,
          "maxShots": 100000
        },
        {
          "name": "Expectation",
          "observables": [
            "x",
            "y",
            "z",
            "h",
            "i",
            "hermitian"
          ],
          "minShots": 0,
          "maxShots": 100000
        },
        {
          "name": "Variance",
          "observables": [
            "x",
            "y",
            "z",
            "h",
            "i",
            "hermitian"
          ],
          "minShots": 0,
          "maxShots": 100000
        },
        {
          "name": "Probability",
          "minShots": 1,
          "maxShots": 100000
        },
        {
          "name": "Amplitude",
          "minShots": 0,
          "maxShots": 0
        }
        {
          "name": "AdjointGradient",
          "minShots": 0,
          "maxShots": 0
        }
      ]
    }
  },
...
```

# Simulez le bruit avec OpenQASM 3.0
<a name="braket-openqasm-noise-simulation"></a>

Pour simuler le bruit avec OpenQASM3, vous utilisez les instructions *pragma* pour ajouter des opérateurs de bruit. Par exemple, pour simuler la version bruyante du [programme GHZ](braket-openqasm-create-submit-task.md#braket-openqasm-example-program) fournie précédemment, vous pouvez soumettre le programme OpenQASM suivant.

```
// ghz.qasm
// Prepare a GHZ state
OPENQASM 3;

qubit[3] q;
bit[3] c;

h q[0];
#pragma braket noise depolarizing(0.75) q[0] cnot q[0], q[1];
#pragma braket noise depolarizing(0.75) q[0]
#pragma braket noise depolarizing(0.75) q[1] cnot q[1], q[2];
#pragma braket noise depolarizing(0.75) q[0]
#pragma braket noise depolarizing(0.75) q[1]

c = measure q;
```

Les spécifications de tous les opérateurs de bruit pragma pris en charge sont fournies dans la liste suivante.

```
#pragma braket noise bit_flip(<float in [0,1/2]>) <qubit>
#pragma braket noise phase_flip(<float in [0,1/2]>) <qubit>
#pragma braket noise pauli_channel(<float>, <float>, <float>)  <qubit>
#pragma braket noise depolarizing(<float in [0,3/4]>) <qubit>
#pragma braket noise two_qubit_depolarizing(<float in [0,15/16]>) <qubit>, <qubit>
#pragma braket noise two_qubit_dephasing(<float in [0,3/4]>) <qubit>, <qubit>
#pragma braket noise amplitude_damping(<float in [0,1]>) <qubit>
#pragma braket noise generalized_amplitude_damping(<float in [0,1]> <float in [0,1]>)  <qubit>
#pragma braket noise phase_damping(<float in [0,1]>) <qubit>
#pragma braket noise kraus([[<complex m0_00>, ], ...], [[<complex m1_00>, ], ...], ...) <qubit>[, <qubit>]     // maximum of 2 qubits and maximum of 4 matrices for 1 qubit, 16 for 2
```

## Opérateur Kraus
<a name="braket-openqasm-kraus-operator"></a>

Pour générer un opérateur Kraus, vous pouvez parcourir une liste de matrices en imprimant chaque élément de la matrice sous forme d'expression complexe.

Lorsque vous utilisez les opérateurs Kraus, n'oubliez pas les points suivants :
+ Le nombre de ne qubits doit pas dépasser 2. La [définition actuelle dans les schémas](https://github.com/aws/amazon-braket-sdk-python/blob/0d28a8fa89263daf5d88bc706e79200d8dc091a8/src/braket/circuits/noises.py#L811-L814)) définit cette limite.
+ La longueur de la liste d'arguments doit être un multiple de 8. Cela signifie qu'il ne doit être composé que de matrices 2x2.
+ La longueur totale ne dépasse pas 2 matrices 2\$1num\$1qubits. Cela signifie 4 matrices pour 1 qubit et 16 pour 2qubits.
+ Toutes les matrices fournies sont [totalement conservatrices de traces positives (CPTP).](https://github.com/aws/amazon-braket-sdk-python/blob/0d28a8fa89263daf5d88bc706e79200d8dc091a8/src/braket/circuits/quantum_operator_helpers.py#L94-L108)
+ Le produit des opérateurs de Kraus et de leurs conjugués de transposition doit constituer une matrice d'identité.

# Qubitrecâblage avec OpenQASM 3.0
<a name="braket-openqasm-rewire-qubits"></a>

[Amazon Braket prend en charge la qubit notation physique dans OpenQASM sur les Rigetti appareils (pour en savoir plus, consultez cette page).](https://github.com/openqasm/openqasm/blob/main/source/language/types.rst) Lorsque vous utilisez le physique qubits avec une [stratégie de recâblage naïve](https://pyquil-docs.rigetti.com/en/v2.28.1/compiler.html#naive), assurez-vous qu'qubitsils sont connectés sur le périphérique sélectionné. Sinon, si qubit des registres sont utilisés à la place, la stratégie de recâblage PARTIEL est activée par défaut sur Rigetti les appareils.

```
// ghz.qasm
// Prepare a GHZ state
OPENQASM 3;

h $0;
cnot $0, $1;
cnot $1, $2;

measure $0;
measure $1;
measure $2;
```

# Compilation Verbatim avec OpenQASM 3.0
<a name="braket-openqasm-verbatim-compilation"></a>

Lorsque vous exécutez un circuit quantique sur des ordinateurs quantiques fournis par des fournisseurs tels queRigetti, etIonQ, vous pouvez demander au compilateur d'exécuter vos circuits exactement comme définis, sans aucune modification. Cette fonctionnalité est connue sous le nom de *compilation textuelle.* Avec les appareils Rigetti, vous pouvez spécifier précisément ce qui doit être préservé, soit un circuit entier, soit uniquement des parties spécifiques de celui-ci. Pour ne conserver que des parties spécifiques d'un circuit, vous devrez utiliser des portes natives dans les régions préservées. Actuellement, il IonQ ne prend en charge que la compilation textuelle pour l'ensemble du circuit, de sorte que chaque instruction du circuit doit être incluse dans une boîte textuelle.

Avec OpenQASM, vous pouvez spécifier explicitement un pragma textuel autour d'une boîte de code qui est ensuite laissée intacte et non optimisée par la routine de compilation de bas niveau du matériel. L'exemple de code suivant montre comment utiliser la `#pragma braket verbatim` directive pour y parvenir.

```
OPENQASM 3;

bit[2] c;

#pragma braket verbatim
box{
    rx(0.314159) $0;
    rz(0.628318) $0, $1;
    cz $0, $1;
}

c[0] = measure $0;
c[1] = measure $1;
```

Pour des informations plus détaillées sur le processus de compilation des verbatim, y compris des exemples et des meilleures pratiques, consultez le bloc-notes d'exemples de [compilation Verbatim](https://github.com/aws/amazon-braket-examples/blob/main/examples/braket_features/Verbatim_Compilation.ipynb) disponible dans le référentiel github. amazon-braket-examples

## La console Braket
<a name="braket-openqasm-braket-console"></a>

Les tâches OpenQASM 3.0 sont disponibles et peuvent être gérées dans la console Amazon Braket. Sur la console, vous avez la même expérience en soumettant des tâches quantiques dans OpenQASM 3.0 qu'en soumettant des tâches quantiques existantes.

## Ressources supplémentaires
<a name="braket-openqasm-more-resources"></a>

OpenQASM est disponible dans toutes les régions Amazon Braket.

[Pour un exemple de bloc-notes permettant de démarrer avec OpenQASM sur Amazon Braket, consultez les didacticiels Braket. GitHub](https://github.com/aws/amazon-braket-examples/blob/main/examples/braket_features/Getting_Started_with_OpenQASM_on_Braket.ipynb)

# Calculer des dégradés avec OpenQASM 3.0
<a name="braket-openqasm-computing-gradients"></a>

Amazon Braket prend en charge le calcul des dégradés sur des simulateurs locaux et à la demande lors de l'exécution en mode (exact). `shots=0` Ceci est réalisé grâce à l'utilisation de la méthode de différenciation adjointe. Pour spécifier le gradient que vous souhaitez calculer, vous pouvez fournir le pragma approprié, comme illustré dans le code de l'exemple suivant.

```
OPENQASM 3.0;
input float alpha;

bit[2] b;
qubit[2] q;

h q[0];
h q[1];
rx(alpha) q[0];
rx(alpha) q[1];
b[0] = measure q[0];
b[1] = measure q[1];

#pragma braket result adjoint_gradient h(q[0]) @ i(q[1]) alpha
```

Au lieu de répertorier explicitement tous les paramètres individuels, vous pouvez également spécifier le `all` mot-clé dans le pragma. Cela permettra de calculer le gradient par rapport à tous les `input` paramètres listés, ce qui peut être une option pratique lorsque le nombre de paramètres est très élevé. Dans ce cas, le pragma ressemblera au code de l'exemple suivant.

```
#pragma braket result adjoint_gradient h(q[0]) @ i(q[1]) all
```

Tous les types d'observables sont pris en charge dans l'implémentation OpenQASM 3.0 d'Amazon Braket, y compris les opérateurs individuels, les produits tensoriels, les observables hermitiens et les observables. `Sum` L'opérateur spécifique que vous souhaitez utiliser lors du calcul des dégradés doit être intégré à la `expectation()` fonction, et les qubits sur lesquels agit chaque terme de l'observable doivent être explicitement spécifiés.

# Mesurer des qubits spécifiques avec OpenQASM 3.0
<a name="braket-openqasm-measure-qubits"></a>

Le simulateur vectoriel d'état local et le simulateur de matrice de densité local fournis par Amazon Braket permettent de soumettre des OpenQASM programmes dans lesquels un sous-ensemble des qubits du circuit peut être mesuré de manière sélective. Cette capacité, souvent appelée mesure partielle, permet des calculs quantiques plus ciblés et plus efficaces. Par exemple, dans l'extrait de code suivant, vous pouvez créer un circuit à deux qubits et choisir de mesurer uniquement le premier qubit, tout en laissant le second qubit non mesuré.

```
partial_measure_qasm = """
OPENQASM 3.0;
bit[1] b;
qubit[2] q;
h q[0];
cnot q[0], q[1];
b[0] = measure q[0];
"""
```

Dans cet exemple, nous avons un circuit quantique à deux qubits`q[1]`, `q[0]` mais nous ne voulons mesurer que l'état du premier qubit. Ceci est réalisé par la ligne`b[0] = measure q[0]`, qui mesure l'état du qubit [0] et stocke le résultat dans le bit classique b [0]. Pour exécuter ce scénario de mesure partielle, nous pouvons exécuter le code suivant sur le simulateur vectoriel d'état local fourni par Amazon Braket.

```
from braket.devices import LocalSimulator

local_sim = LocalSimulator()
partial_measure_local_sim_task = local_sim.run(OpenQASMProgram(source=partial_measure_qasm), shots = 10)
partial_measure_local_sim_result = partial_measure_local_sim_task.result()
print(partial_measure_local_sim_result.measurement_counts)
print("Measured qubits: ", partial_measure_local_sim_result.measured_qubits)
```

Vous pouvez vérifier si un appareil prend en charge les mesures partielles en inspectant le `requiresAllQubitsMeasurement` champ dans ses propriétés d'action ; si c'est le cas`False`, les mesures partielles sont prises en charge.

```
from braket.devices import Devices
            
AwsDevice(Devices.Rigetti.Ankaa3).properties.action['braket.ir.openqasm.program'].requiresAllQubitsMeasurement
```

`requiresAllQubitsMeasurement`Voilà`False`, ce qui indique que tous les qubits ne doivent pas être mesurés.

# Explorez les capacités expérimentales
<a name="braket-experimental-capabilities"></a>

Les capacités expérimentales permettent d'accéder à du matériel dont la disponibilité est limitée et aux nouvelles fonctionnalités logicielles émergentes. Ces fonctionnalités peuvent avoir un impact sur les performances de l'appareil au-delà des spécifications standard. Vous pouvez activer automatiquement les fonctionnalités logicielles expérimentales par tâche via le SDK Amazon Braket.

Pour utiliser les capacités expérimentales, spécifiez le `experimental_capabilities` paramètre lorsque vous créez des tâches quantiques. Définissez ce paramètre sur `"ALL"` pour activer toutes les fonctionnalités expérimentales disponibles pour cette tâche. L'exemple suivant montre comment activer les fonctionnalités expérimentales lorsque vous exécutez un circuit sur un périphérique :

```
from braket.aws import AwsDevice

device = AwsDevice("arn:aws:braket:us-east-1::device/qpu/quera/Aquila")

task = device.run(
   circuit,
   shots=1000,
   experimental_capabilities="ALL"
)
```

**Note**  
Ces fonctionnalités sont expérimentales et peuvent être modifiées sans préavis. Les performances de l'appareil peuvent différer des spécifications publiées, et les résultats peuvent différer des opérations standard. Vous devez activer explicitement les fonctionnalités expérimentales pour chaque tâche. Les tâches dépourvues de ce paramètre utiliseront uniquement les fonctionnalités standard de l'appareil.

**Topics**
+ [Accès au déréglage local sur Aquila QuEra](#braket-access-local-detuning)
+ [Accès à de hautes géométries sur Aquila QuEra](#braket-access-tall-geometries)
+ [Accès à des géométries serrées sur Aquila QuEra](#braket-access-tight-geometries)
+ [Circuits dynamiques sur les appareils IQM](#braket-access-dynamic-circuits)

## Accès au déréglage local sur Aquila QuEra
<a name="braket-access-local-detuning"></a>

Le déréglage local (LD) est un nouveau champ de contrôle dépendant du temps doté d'un modèle spatial personnalisable. Le champ LD affecte les qubits selon un schéma spatial personnalisable, réalisant différents hamiltoniens pour différents qubits, au-delà de ce que le champ de conduite uniforme et l'interaction Rydberg-Rydberg peuvent créer.

**Contraintes** :

Le modèle spatial du champ de désaccordage local est personnalisable pour chaque programme AHS, mais il est constant au cours d'un programme. La série chronologique du champ de désaccordage local doit commencer et se terminer à zéro, toutes les valeurs étant inférieures ou égales à zéro. De plus, les paramètres du champ de désaccordage local sont limités par des contraintes numériques, qui peuvent être consultées via le SDK Braket dans la section des propriétés spécifiques de l'appareil -. `aquila_device.properties.paradigm.rydberg.rydbergLocal`

**Limites :**

Lors de l'exécution de programmes quantiques utilisant le champ de désaccordage local (même si son amplitude est fixée à zéro constant dans l'hamiltonien), le dispositif présente une décohérence plus rapide que le temps T2 indiqué dans la section des propriétés d'Aquila consacrée aux performances. Lorsque cela n'est pas nécessaire, il est recommandé d'omettre le champ de désaccordage local de l'hamiltonien du programme AHS.

![\[Simulation hamiltonienne analogique dans la terminologie du spin, où il existe des qubits, un champ de conduite global dépendant du temps et un déréglage local dépendant du temps.\]](http://docs.aws.amazon.com/fr_fr/braket/latest/developerguide/images/AHS_spin_terminology.png)


**Exemples :**

1. **Simulation de l'effet d'un champ magnétique longitudinal non uniforme dans les systèmes de spin**

   Alors que l'amplitude et la phase du champ moteur ont le même effet sur les qubits que le champ magnétique transverse sur les spins, la somme du désaccord du champ moteur et du désaccord local produit le même effet sur les qubits que le champ longitudinal sur les spins. Grâce au contrôle spatial du champ de désaccordage local, des systèmes de spin plus complexes peuvent être simulés.

1. **Préparation des états initiaux hors équilibre**

   Le bloc-notes d'exemple [Simulation de la théorie des jauges en réseau avec des atomes de Rydberg](https://github.com/amazon-braket/amazon-braket-examples/blob/main/examples/analog_hamiltonian_simulation/07_Simulating_Lattice_Gauge_Theory_with_Rydberg_Atoms.ipynb) montre comment empêcher l'atome central d'un arrangement linéaire à 9 atomes d'être excité lors du recuit du système vers la phase ordonnée Z2. Après l'étape de préparation, le champ de désaccordage local est réduit et le programme AHS continue de simuler l'évolution temporelle du système à partir de cet état de non-équilibre particulier.

1. **Résolution de problèmes d'optimisation pondérée**

   L'exemple du kit MWIS ([Maximum Weight Independent Set](https://github.com/amazon-braket/amazon-braket-examples/blob/main/examples/analog_hamiltonian_simulation/08_Maximum_Weight_Independent_Set.ipynb)) pour ordinateur portable montre comment résoudre un problème MWIS sur Aquila. Le champ de désaccordage local est utilisé pour définir les poids sur les nœuds du graphe à disque unitaire, dont les arêtes sont réalisées par l'effet de blocage Rybderg. En partant de l'état fondamental uniforme et en augmentant progressivement le champ de désaccordage local, le système passe à l'état fondamental du MWIS Hamiltonian afin de trouver des solutions au problème.

## Accès à de hautes géométries sur Aquila QuEra
<a name="braket-access-tall-geometries"></a>

La fonction de géométries hautes vous permet de spécifier des géométries avec une hauteur accrue. Grâce à cette fonctionnalité, les arrangements atomiques de vos programmes AHS peuvent s'étendre sur une longueur supplémentaire dans la direction y au-delà des capacités habituelles d'Aquila.

**Contraintes** :

La hauteur maximale pour les géométries hautes est de 0,000128 m (128 um).

**Limites :**

Lorsque cette fonctionnalité expérimentale est activée pour votre compte, les fonctionnalités affichées sur la page des propriétés de l'appareil et lors de l'`GetDevice`appel continueront de refléter la limite inférieure normale de hauteur. Lorsqu'un programme AHS utilise des arrangements atomiques qui vont au-delà des capacités habituelles, l'erreur de remplissage devrait augmenter. Vous trouverez un nombre élevé de 0 inattendus dans la `pre_sequence` partie du résultat de la tâche, ce qui réduira les chances d'obtenir un arrangement parfaitement initialisé. Cet effet est le plus fort dans les rangées comportant de nombreux atomes.

![\[Les trois graphiques à points montrent des représentations de géométries hautes sous forme de ligne 1D, d'échelle et de multiplex.\]](http://docs.aws.amazon.com/fr_fr/braket/latest/developerguide/images/tall-geometry-graphs.PNG)


**Exemples :**

1. **Arrangements 1D et quasi-1D plus grands**

   Les chaînes d'atomes et les arrangements en forme d'échelle peuvent être étendus à des nombres d'atomes plus élevés. En orientant la direction longue parallèlement à y, il est possible de programmer des instances plus longues de ces modèles.

1. **Plus d'espace pour le multiplexage de l'exécution de tâches avec de petites géométries**

   L'exemple de bloc-notes [Tâches quantiques parallèles sur Aquila](https://github.com/amazon-braket/amazon-braket-examples/blob/main/examples/analog_hamiltonian_simulation/03_Parallel_tasks_on_Aquila.ipynb) montre comment tirer le meilleur parti de la zone disponible : en plaçant des copies multiplexées de la géométrie en question dans un arrangement d'atomes. Avec la plus grande surface disponible, davantage de copies peuvent être placées.

## Accès à des géométries serrées sur Aquila QuEra
<a name="braket-access-tight-geometries"></a>

La fonction de géométries serrées vous permet de spécifier des géométries avec un espacement plus court entre les lignes voisines. Dans un programme AHS, les atomes sont disposés en rangées, séparées par un espacement vertical minimal. La coordonnée y de deux sites atomiques doit être égale à zéro (même ligne) ou être différente de l'espacement minimal entre les lignes (ligne différente). Grâce à la fonctionnalité de géométries serrées, l'espacement minimal entre les rangées est réduit, ce qui permet de créer des arrangements atomiques plus serrés. Bien que cette extension ne modifie pas l'exigence de distance euclidienne minimale entre les atomes, elle permet de créer des réseaux où des atomes distants occupent des rangées voisines plus proches les unes des autres, comme le réseau triangulaire en est un exemple notable.

**Contraintes** :

L'espacement minimal entre les rangées pour les géométries serrées est de 0,000002 m (2 µm).

**Limites :**

Lorsque cette fonctionnalité expérimentale est activée pour votre compte, les fonctionnalités affichées sur la page des propriétés de l'appareil et lors de l'`GetDevice`appel continueront de refléter la limite inférieure normale de hauteur. Lorsqu'un programme AHS utilise des arrangements atomiques qui vont au-delà des capacités habituelles, l'erreur de remplissage devrait augmenter. Les clients trouveront un nombre élevé de 0 inattendus dans la `pre_sequence` partie du résultat de la tâche, ce qui réduira les chances d'obtenir un arrangement parfaitement initialisé. Cet effet est le plus fort dans les rangées comportant de nombreux atomes.

![\[Les graphiques montrent une géométrie étroite d'un réseau triangulaire de points sur la gauche et le graphique de droite est un réseau hexagonal de points.\]](http://docs.aws.amazon.com/fr_fr/braket/latest/developerguide/images/tight-geometry-graphs.PNG)


**Exemples :**

1. **Réseaux non rectangulaires avec de petites constantes de réseau**

   Un espacement des rangées plus serré permet de créer des réseaux où les voisins les plus proches de certains atomes se trouvent dans le sens de la diagonale. Les réseaux triangulaires, hexagonaux, les réseaux de Kagome et certains quasi-cristaux en sont des exemples notables.

1. **Famille de réseaux réglables**

   Dans les programmes AHS, les interactions sont ajustées en ajustant la distance entre les paires d'atomes. Un espacement des rangées plus serré permet d'ajuster les interactions entre les différentes paires d'atomes les unes par rapport aux autres avec plus de liberté, car les angles et les distances qui définissent la structure des atomes sont moins limités par la contrainte minimale d'espacement des lignes. Un exemple notable est la famille des réseaux de Shastry-Sutherland avec différentes longueurs de liaison.

## Circuits dynamiques sur les appareils IQM
<a name="braket-access-dynamic-circuits"></a>

Les circuits dynamiques des IQM appareils permettent des mesures en milieu de circuit (MCM) et des opérations anticipées. Ces fonctionnalités permettent aux chercheurs et aux développeurs quantiques de mettre en œuvre des algorithmes quantiques avancés dotés de fonctionnalités de logique conditionnelle et de réutilisation des qubits. Cette fonctionnalité expérimentale permet d'explorer des algorithmes quantiques avec une meilleure efficacité des ressources et d'étudier des schémas d'atténuation et de correction des erreurs quantiques.

**Principales instructions :**
+ `measure_ff`: implémente des mesures pour le contrôle anticipé, en mesurant un qubit et en stockant le résultat à l'aide d'une clé de rétroaction.
+ `cc_prx`: implémente une rotation contrôlée de manière classique qui s'applique uniquement lorsque le résultat associé à la clé de feedback donnée mesure un état \$11⟩.

Amazon Braket prend en charge les circuits dynamiques à traversOpenQASM, leAmazon Braket SDK, et le. Amazon Braket Qiskit Provider

**Contraintes** :

1. Les clés de commentaires figurant dans `measure_ff` les instructions doivent être uniques.

1. Cela `cc_prx` doit se produire ensuite `measure_ff` avec la même clé de feedback.

1. Dans un circuit unique, le feed-forward sur un qubit ne peut être contrôlé que par un qubit, soit seul, soit par un autre qubit. Dans différents circuits, vous pouvez avoir différentes paires de commande.<a name="lower"></a>

   1. Par exemple, si le qubit 1 est contrôlé par le qubit 2, il ne peut pas être contrôlé par le qubit 3 dans le même circuit. Il n'y a aucune contrainte quant au nombre de fois que le contrôle est appliqué entre le qubit 1 et le qubit 2. Le qubit 2 peut être contrôlé par le qubit 3 (ou le qubit 1), sauf si une réinitialisation active a été effectuée sur le qubit 2. 

1. Le contrôle ne peut être appliqué qu'aux qubits d'un même groupe. Les groupes de qubits pour les Emerald appareils IQM Garnet et sont présentés dans les images suivantes. 

1. Les programmes dotés de ces capacités doivent être soumis sous forme de programmes textuels. Pour en savoir plus sur les programmes Verbatim, voir [Compilation Verbatim avec OpenQASM 3.0](https://docs.aws.amazon.com/braket/latest/developerguide/braket-openqasm-verbatim-compilation.html).

**Limites :**

Le MCM ne peut être utilisé que pour le contrôle anticipé dans un programme. Les résultats MCM (0 ou 1) ne sont pas renvoyés dans le cadre du résultat d'une tâche.

![\[L'image de gauche est l'appareil IQM Garnet de 20 qubits avec 2 groupes de qubits dans un réseau carré, et l'image de droite est l'appareil IQM Emerald de 54 qubits avec 4 groupes de qubits dans un réseau carré.\]](http://docs.aws.amazon.com/fr_fr/braket/latest/developerguide/images/IQM-Garnet-Emerald-qubit-grouping.png)


Ces images montrent les groupements de qubits pour les deux IQM appareils. L'appareil Garnet à 20 qubits contient 2 groupes de qubits, tandis que l'appareil à Emerald 54 qubits contient 4 groupes de qubits. 

**Exemples :**

1. **Réutilisation des qubits par réinitialisation active**

   Le MCM avec des opérations de réinitialisation conditionnelle permet la réutilisation des qubits dans le cadre d'une exécution de circuit unique. Cela réduit les exigences de profondeur des circuits et améliore l'utilisation des ressources des dispositifs quantiques.

1. **Protection active contre le retournement des embouts**

   Les circuits dynamiques détectent les erreurs de retournement de bits et appliquent des opérations correctives en fonction des résultats de mesure. Cette implémentation sert d'expérience de détection d'erreurs quantiques.

1. **Expériences de téléportation**

   La téléportation d'État transfère les états des qubits à l'aide d'opérations quantiques locales et d'informations classiques provenant de. MCMs La téléportation par portes met en œuvre des portes entre les qubits sans opérations quantiques directes. Ces expériences mettent en évidence des sous-programmes fondamentaux dans trois domaines clés : la correction des erreurs quantiques, l'informatique quantique basée sur les mesures et la communication quantique.

1. **Simulation de systèmes quantiques ouverts**

   Les circuits dynamiques modélisent le bruit dans les systèmes quantiques grâce à l'enchevêtrement des qubits de données et de l'environnement, ainsi qu'à des mesures environnementales. Cette approche utilise des qubits spécifiques pour représenter les données et les éléments de l'environnement. Un canal de bruit peut être conçu par les portes et les mesures appliquées à l'environnement.

Pour plus d'informations sur l'utilisation des circuits dynamiques, consultez des exemples supplémentaires dans le référentiel de [blocs-notes Amazon Braket](https://github.com/amazon-braket/amazon-braket-examples/tree/main/examples/experimental_capabilities/dynamic_circuits).

# Contrôle du pouls sur Amazon Braket
<a name="braket-pulse-control"></a>

Les impulsions sont les signaux analogiques qui contrôlent les qubits d'un ordinateur quantique. Sur certains appareils d'Amazon Braket, vous pouvez accéder à la fonction de contrôle des impulsions pour soumettre des circuits à l'aide d'impulsions. Vous pouvez accéder au contrôle du pouls via le SDK Braket, à l'aide d'OpenQASM 3.0, ou directement via le Braket. APIs Tout d'abord, introduisez quelques concepts clés pour le contrôle du pouls dans Braket.

**Topics**
+ [Frames (Images)](#braket-frame)
+ [Ports](#braket-port)
+ [Formes d'onde](#braket-waveform)
+ [Travailler avec Hello Pulse](braket-hello-pulse.md)
+ [Accès aux portes natives à l'aide d'impulsions](braket-native-gate-pulse.md)

## Frames (Images)
<a name="braket-frame"></a>

Un cadre est une abstraction logicielle qui agit à la fois comme une horloge dans le programme quantique et comme une phase. Le temps d'horloge est incrémenté à chaque utilisation et un signal porteur dynamique est défini par une fréquence. Lors de la transmission de signaux vers le qubit, une trame détermine la fréquence porteuse du qubit, le décalage de phase et l'heure à laquelle l'enveloppe de forme d'onde est émise. Dans Braket Pulse, la construction des cadres dépend de l'appareil, de la fréquence et de la phase. Selon le périphérique, vous pouvez choisir un cadre prédéfini ou instancier de nouveaux cadres en fournissant un port.

```
from braket.aws import AwsDevice
from braket.pulse import Frame, Port

# Predefined frame from a device
device = AwsDevice("arn:aws:braket:us-west-1::device/qpu/rigetti/Ankaa-3")
drive_frame = device.frames["Transmon_5_charge_tx"]

# Create a custom frame
readout_frame = Frame(frame_id="r0_measure", port=Port("channel_0", dt=1e-9), frequency=5e9, phase=0)
```

## Ports
<a name="braket-port"></a>

Un port est une abstraction logicielle représentant n'importe quel composant input/output matériel contrôlant les qubits. Il aide les fournisseurs de matériel à fournir une interface avec laquelle les utilisateurs peuvent interagir pour manipuler et observer les qubits. Les ports sont caractérisés par une chaîne unique qui représente le nom du connecteur. Cette chaîne expose également un incrément de temps minimum qui indique avec quelle précision nous pouvons définir les formes d'onde.

```
from braket.pulse import Port

Port0 = Port("channel_0", dt=1e-9)
```

## Formes d'onde
<a name="braket-waveform"></a>

Une forme d'onde est une enveloppe dépendant du temps que nous pouvons utiliser pour émettre des signaux sur un port de sortie ou pour capturer des signaux via un port d'entrée. Vous pouvez spécifier vos formes d'onde directement via une liste de nombres complexes ou en utilisant un modèle de forme d'onde pour générer une liste auprès du fournisseur du matériel.

```
from braket.pulse import ArbitraryWaveform, ConstantWaveform
import numpy as np

cst_wfm = ConstantWaveform(length=1e-7, iq=0.1)
arb_wf = ArbitraryWaveform(amplitudes=np.linspace(0, 100))
```

 Braket Pulse fournit une bibliothèque standard de formes d'onde, notamment une forme d'onde constante, une forme d'onde gaussienne et une forme d'onde DRAG (Derivative Removal by Adiabatic Gate). Vous pouvez récupérer les données de forme d'onde à l'aide de la `sample` fonction pour dessiner la forme de la forme d'onde, comme indiqué dans l'exemple suivant.

```
from braket.pulse import GaussianWaveform
import numpy as np
import matplotlib.pyplot as plt

zero_at_edge1 = GaussianWaveform(1e-7, 25e-9, 0.1, True)
# or zero_at_edge1 = GaussianWaveform(1e-7, 25e-9, 0.1)
zero_at_edge2 = GaussianWaveform(1e-7, 25e-9, 0.1, False)

times_1 = np.arange(0, zero_at_edge1.length, drive_frame.port.dt)
times_2 = np.arange(0, zero_at_edge2.length, drive_frame.port.dt)

plt.plot(times_1, zero_at_edge1.sample(drive_frame.port.dt))
plt.plot(times_2, zero_at_edge2.sample(drive_frame.port.dt))
```

![\[Graphique montrant l'amplitude dans le temps pour deux cas : ZaE = vrai (courbe inférieure) et zAe = faux (courbe supérieure). Les courbes ont une forme de cloche culminant à environ 0,5 seconde avec une amplitude de 0,10 a. u.\]](http://docs.aws.amazon.com/fr_fr/braket/latest/developerguide/images/gaussianwaveform.png)


L'image précédente représente les formes d'onde gaussiennes créées à partir de. `GaussianWaveform` Nous avons choisi une durée d'impulsion de 100 ns, une largeur de 25 ns et une amplitude de 0,1 (unités arbitraires). Les formes d'onde sont centrées dans la fenêtre d'impulsion. `GaussianWaveform`accepte un argument booléen `zero_at_edges` (ZaE dans la légende). Lorsqu'il est défini sur`True`, cet argument décale la forme d'onde gaussienne de telle sorte que les points à t=0 et t= `length` soient à zéro et redimensionne son amplitude de telle sorte que la valeur maximale corresponde à l'argument. `amplitude`

# Travailler avec Hello Pulse
<a name="braket-hello-pulse"></a>

Dans cette section, vous apprendrez à caractériser et à construire une porte à qubit unique directement en utilisant l'impulsion d'un Rigetti appareil. L'application d'un champ électromagnétique à un qubit entraîne une oscillation de Rabi, faisant passer le qubit entre son état 0 et son état 1. Avec une longueur et une phase d'impulsion calibrées, l'oscillation de Rabi peut calculer une seule porte qubit. Ici, nous allons déterminer la longueur d'impulsion optimale pour mesurer une impulsion pi/2, un bloc élémentaire utilisé pour construire des séquences d'impulsions plus complexes.

Tout d'abord, pour créer une séquence d'impulsions, importez la `PulseSequence` classe.

```
from braket.aws import AwsDevice
from braket.circuits import FreeParameter
from braket.devices import Devices
from braket.pulse import PulseSequence, GaussianWaveform

import numpy as np
```

Ensuite, instanciez un nouveau périphérique Braket à l'aide de l'Amazon Resource NameARN du QPU. Le bloc de code suivant utiliseRigetti Ankaa-3.

```
device = AwsDevice(Devices.Rigetti.Ankaa3)
```

La séquence d'impulsions suivante comprend deux composantes : jouer une forme d'onde et mesurer un qubit. La séquence d'impulsions peut généralement être appliquée aux trames. À quelques exceptions près, telles que la barrière et le délai, qui peuvent être appliqués aux qubits. Avant de construire la séquence d'impulsions, vous devez récupérer les trames disponibles. Le cadre d'entraînement est utilisé pour appliquer l'impulsion nécessaire à l'oscillation de Rabi, et le cadre de lecture sert à mesurer l'état du qubit. Cet exemple utilise les images du qubit 25.

```
drive_frame = device.frames["Transmon_25_charge_tx"]
readout_frame = device.frames["Transmon_25_readout_rx"]
```

Créez maintenant la forme d'onde qui sera jouée dans le cadre du lecteur. L'objectif est de caractériser le comportement des qubits pour différentes durées d'impulsion. Vous allez jouer une forme d'onde avec des longueurs différentes à chaque fois. Au lieu d'instancier une nouvelle forme d'onde à chaque fois, utilisez la séquence d'impulsions supportée par le frein. `FreeParameter` Vous pouvez créer la forme d'onde et la séquence d'impulsions une seule fois avec des paramètres libres, puis exécuter la même séquence d'impulsions avec des valeurs d'entrée différentes. 

```
waveform = GaussianWaveform(FreeParameter("length"), FreeParameter("length") * 0.25, 0.2, False)
```

Enfin, assemblez-les sous forme de séquence d'impulsions. Dans la séquence d'impulsions, `play` lit la forme d'onde spécifiée sur le cadre du lecteur et `capture_v0` mesure l'état à partir du cadre de lecture.

```
pulse_sequence = (
    PulseSequence()
    .play(drive_frame, waveform)
    .capture_v0(readout_frame)
)
```

Scannez une plage de durées d'impulsion et soumettez-les au QPU. Avant d'exécuter les séquences d'impulsions sur un QPU, liez la valeur des paramètres libres.

```
start_length = 12e-9
end_length = 2e-7
lengths = np.arange(start_length, end_length, 12e-9)
N_shots = 100

tasks = [
    device.run(pulse_sequence(length=length), shots=N_shots)
    for length in lengths
]

probability_of_zero = [
    task.result().measurement_counts['0']/N_shots
    for task in tasks
]
```

Les statistiques de la mesure du qubit montrent la dynamique oscillatoire du qubit qui oscille entre l'état 0 et l'état 1. À partir des données de mesure, vous pouvez extraire la fréquence Rabi et affiner la durée de l'impulsion pour implémenter une porte à 1 qubit particulière. Par exemple, d'après les données de la figure ci-dessous, la périodicité est d'environ 154 ns. Ainsi, une porte de rotation pi/2 correspondrait à la séquence d'impulsions d'une longueur = 38,5 ns. 

![\[Graphique linéaire qui montre le nombre de personnes par rapport à la durée du pouls en secondes. Il y a deux pics et un creux sur le graphique.\]](http://docs.aws.amazon.com/fr_fr/braket/latest/developerguide/images/Rabi-frequency.png)


## Hello Pulse utilise OpenPulse
<a name="braket-hello-pulse-openpulse"></a>

 [OpenPulse](https://openqasm.com/language/openpulse.html)est un langage permettant de spécifier le contrôle au niveau des impulsions d'un dispositif quantique général et fait partie de la spécification OpenQASM 3.0. Amazon Braket prend en charge la programmation directe OpenPulse d'impulsions à l'aide de la représentation OpenQASM 3.0.

 Braket utilise OpenPulse comme représentation intermédiaire sous-jacente pour exprimer des impulsions dans des instructions natives. OpenPulsepermet d'ajouter des étalonnages d'instructions sous la forme de déclarations `defcal` (abréviation de « définir l'étalonnage »). Avec ces déclarations, vous pouvez spécifier une implémentation d'une instruction de porte dans une grammaire de contrôle de niveau inférieur.

Vous pouvez visualiser le OpenPulse programme d'un Braket à `PulseSequence` l'aide de la commande suivante.

```
print(pulse_sequence.to_ir())
```

Vous pouvez également créer un OpenPulse programme directement.

```
from braket.ir.openqasm import Program
 
openpulse_script = """
OPENQASM 3.0;
cal {
    bit[1] psb;
    waveform my_waveform = gaussian(12.0ns, 3.0ns, 0.2, false);
    play(Transmon_25_charge_tx, my_waveform);
    psb[0] = capture_v0(Transmon_25_readout_rx);
}
"""
```

Créez un `Program` objet à l'aide de votre script. Soumettez ensuite le programme à un QPU.

```
from braket.aws import AwsDevice
from braket.devices import Devices
from braket.ir.openqasm import Program

program = Program(source=openpulse_script)

device = AwsDevice(Devices.Rigetti.Ankaa3)
task = device.run(program, shots=100)
```

# Accès aux portes natives à l'aide d'impulsions
<a name="braket-native-gate-pulse"></a>

Les chercheurs ont souvent besoin de savoir exactement comment les portes *natives* prises en charge par un QPU particulier sont implémentées sous forme d'impulsions. Les séquences d'impulsions sont soigneusement calibrées par les fournisseurs de matériel, mais l'accès à celles-ci permet aux chercheurs de concevoir de meilleures portes ou d'explorer des protocoles pour atténuer les erreurs, tels que l'extrapolation sans bruit en étirant les impulsions de portes spécifiques.

Amazon Braket prend en charge l'accès programmatique aux portails natifs de Rigetti.

```
import math
from braket.aws import AwsDevice
from braket.circuits import Circuit, GateCalibrations, QubitSet
from braket.circuits.gates import Rx

device = AwsDevice("arn:aws:braket:us-west-1::device/qpu/rigetti/Ankaa-3")

calibrations = device.gate_calibrations
print(f"Downloaded {len(calibrations)} calibrations.")
```

**Note**  
Les fournisseurs de matériel étalonnent régulièrement le QPU, souvent plus d'une fois par jour. Le SDK Braket vous permet d'obtenir les derniers étalonnages de portail.

```
device.refresh_gate_calibrations()
```

Pour récupérer une porte native donnée, telle que la porte RX ou XY, vous devez transmettre l'`Gate`objet et les qubits qui vous intéressent. Par exemple, vous pouvez inspecter l'implémentation par impulsion du RX (π/2) appliqué à qubit 0.

```
rx_pi_2_q0 = (Rx(math.pi/2), QubitSet(0))

pulse_sequence_rx_pi_2_q0 = calibrations.pulse_sequences[rx_pi_2_q0]
```

Vous pouvez créer un ensemble filtré d'étalonnages à l'aide de cette `filter` fonction. Vous passez une liste de portes ou une liste de`QubitSet`. Le code suivant crée deux ensembles contenant tous les étalonnages pour RX (π/2) et pour 0. qubit

```
rx_calibrations = calibrations.filter(gates=[Rx(math.pi/2)])
q0_calibrations = calibrations.filter(qubits=QubitSet([0]))
```

Vous pouvez désormais fournir ou modifier l'action des portes natives en joignant un ensemble de calibrage personnalisé. Par exemple, considérez le circuit suivant.

```
bell_circuit = (
    Circuit()
    .rx(0, math.pi/2)
    .rx(1, math.pi/2)
    .iswap(0, 1)
    .rx(1, -math.pi/2)
)
```

Vous pouvez l'exécuter avec un calibrage de porte personnalisé pour la `rx` porte `qubit 0` en transmettant un dictionnaire d'`PulseSequence`objets à l'argument du `gate_definitions` mot clé. Vous pouvez créer un dictionnaire à partir de l'attribut `pulse_sequences` de l'`GateCalibrations`objet. Toutes les portes non spécifiées sont remplacées par l'étalonnage des impulsions du fournisseur de matériel quantique.

```
nb_shots = 50
custom_calibration = GateCalibrations({rx_pi_2_q0: pulse_sequence_rx_pi_2_q0})
task = device.run(bell_circuit, gate_definitions=custom_calibration.pulse_sequences, shots=nb_shots)
```

# Simulation hamiltonienne analogique
<a name="braket-analog-hamiltonian-simulation"></a>

La [simulation hamiltonienne analogique](https://en.wikipedia.org/wiki/Hamiltonian_simulation) (AHS) est un nouveau paradigme de l'informatique quantique qui diffère considérablement du modèle de circuit quantique traditionnel. Au lieu d'une séquence de portes, où chaque circuit n'agit que sur quelques qubits à la fois. Un programme AHS est défini par les paramètres dépendants du temps et de l'espace de l'hamiltonien en question. L'[hamiltonien d'un système](https://en.wikipedia.org/wiki/Hamiltonian_(quantum_mechanics)) code ses niveaux d'énergie et les effets des forces extérieures, qui, ensemble, régissent l'évolution temporelle de ses états. Pour un système à N qubits, l'hamiltonien peut être représenté par une matrice carrée de 2 N X2 N de nombres complexes.

Les dispositifs quantiques capables d'exécuter l'AHS sont conçus pour se rapprocher étroitement de l'évolution temporelle d'un système quantique selon un hamiltonien personnalisé en ajustant soigneusement leurs paramètres de contrôle interne. Par exemple, le réglage de l'amplitude et les paramètres de désaccordage d'un champ de conduite cohérent. Le paradigme AHS est bien adapté pour simuler les propriétés statiques et dynamiques de systèmes quantiques comportant de nombreuses particules en interaction, comme dans le cas de la physique de la matière condensée ou de la chimie quantique. Les unités de traitement quantique spécialement conçues (QPUs), comme le [dispositif Aquila](https://aws.amazon.com/braket/quantum-computers/quera/) deQuEra, ont été développées pour utiliser la puissance de l'AHS et résoudre des problèmes hors de portée des approches informatiques quantiques numériques conventionnelles de manière innovante.

**Topics**
+ [Bonjour AHS : Exécutez votre première simulation hamiltonienne analogique](braket-get-started-hello-ahs.md)
+ [Soumettre un programme analogique à l'aide d' QuEra Aquila](braket-quera-submitting-analog-program-aquila.md)

# Bonjour AHS : Exécutez votre première simulation hamiltonienne analogique
<a name="braket-get-started-hello-ahs"></a>

Cette section fournit des informations sur l'exécution de votre première simulation hamiltonienne analogique.

**Topics**
+ [Chaîne de spin en interaction](#braket-get-started-interacting-spin-chain)
+ [Arrangement](#braket-get-started-arrangement)
+ [Interaction](#braket-get-started-interaction)
+ [Champ de conduite](#braket-get-started-driving-field)
+ [Programme AHS](#braket-get-started-ahs-program)
+ [Exécution sur un simulateur local](#braket-get-started-running-local-simulator)
+ [Analyse des résultats du simulateur](#braket-get-started-analyzing-simulator-results)
+ [Running QuEra On's Aquila QPU](#braket-get-started-running-aquila-qpu)
+ [Analyse des résultats du QPU](#braket-get-started-analyzing-qpu-results)
+ [Étapes suivantes](#braket-get-started-ahs-next)

## Chaîne de spin en interaction
<a name="braket-get-started-interacting-spin-chain"></a>

Pour un exemple canonique d'un système de nombreuses particules en interaction, considérons un anneau de huit spins (dont chacun peut être dans les états « haut » ↑ ⟩ et « bas »). Bien que petit, ce système modèle présente déjà une poignée de phénomènes intéressants liés aux matériaux magnétiques naturels. Dans cet exemple, nous allons montrer comment préparer un ordre dit antiferromagnétique, dans lequel des spins consécutifs pointent dans des directions opposées.

![\[Schéma reliant 8 nœuds circulaires contenant des flèches inversées vers le haut et vers le bas.\]](http://docs.aws.amazon.com/fr_fr/braket/latest/developerguide/images/AntiFerromagnetic.png)


## Arrangement
<a name="braket-get-started-arrangement"></a>

Nous utiliserons un atome neutre pour représenter chaque spin, et les états de spin « haut » et « bas » seront codés dans l'état de Rydberg excité et dans l'état fondamental des atomes, respectivement. Tout d'abord, nous créons l'arrangement 2D. Nous pouvons programmer l'anneau de tours ci-dessus avec le code suivant.

 **Prérequis** : Vous devez installer le SDK [Braket](https://github.com/aws/amazon-braket-sdk-python#installing-the-amazon-braket-python-sdk) en un clin d'œil. (Si vous utilisez une instance de bloc-notes hébergée par Braket, ce SDK est préinstallé avec les blocs-notes.) Pour reproduire les tracés, vous devez également installer matplotlib séparément à l'aide de la commande shell. `pip install matplotlib`

```
from braket.ahs.atom_arrangement import AtomArrangement
import numpy as np
import matplotlib.pyplot as plt  # Required for plotting

a = 5.7e-6  # Nearest-neighbor separation (in meters)

register = AtomArrangement()
register.add(np.array([0.5, 0.5 + 1/np.sqrt(2)]) * a)
register.add(np.array([0.5 + 1/np.sqrt(2), 0.5]) * a)
register.add(np.array([0.5 + 1/np.sqrt(2), - 0.5]) * a)
register.add(np.array([0.5, - 0.5 - 1/np.sqrt(2)]) * a)
register.add(np.array([-0.5, - 0.5 - 1/np.sqrt(2)]) * a)
register.add(np.array([-0.5 - 1/np.sqrt(2), - 0.5]) * a)
register.add(np.array([-0.5 - 1/np.sqrt(2), 0.5]) * a)
register.add(np.array([-0.5, 0.5 + 1/np.sqrt(2)]) * a)
```

avec lequel nous pouvons également comploter

```
fig, ax = plt.subplots(1, 1, figsize=(7, 7))
xs, ys = [register.coordinate_list(dim) for dim in (0, 1)]
ax.plot(xs, ys, 'r.', ms=15)

for idx, (x, y) in enumerate(zip(xs, ys)):
    ax.text(x, y, f" {idx}", fontsize=12)

plt.show()  # This will show the plot below in an ipython or jupyter session
```

![\[Diagramme de dispersion montrant les points répartis entre des valeurs positives et négatives sur les deux axes.\]](http://docs.aws.amazon.com/fr_fr/braket/latest/developerguide/images/PlotNeutralAtoms.png)


## Interaction
<a name="braket-get-started-interaction"></a>

Pour préparer la phase antiferromagnétique, nous devons induire des interactions entre des spins voisins. Pour cela, nous utilisons l'[interaction de van der Waals](https://en.wikipedia.org/wiki/Van_der_Waals_force), qui est implémentée nativement par des appareils à atomes neutres (tels que le Aquila périphérique deQuEra). En utilisant la représentation du spin, le terme hamiltonien pour cette interaction peut être exprimé sous la forme d'une somme de toutes les paires de spins (j, k).

![\[Équation d'interaction hamiltonienne montrant cette interaction exprimée sous la forme d'une somme de toutes les paires de spins (j, k).\]](http://docs.aws.amazon.com/fr_fr/braket/latest/developerguide/images/HInteraction.png)


Ici, nj=↑ j ⟨↑ est j un opérateur qui prend la valeur 1 uniquement si le spin j est à l'état « up », et 0 dans le cas contraire. La force est V j,k =C6/(dj,k​) 6, où C 6 est le coefficient fixe, et d j,k est la distance euclidienne entre les spins j et k. L'effet immédiat de ce terme d'interaction est que tout état dans lequel le spin j et le spin k sont à la fois « en hausse » produit une énergie élevée (de la quantité Vj,k). En concevant soigneusement le reste du programme AHS, cette interaction empêchera les spins voisins d'être tous deux à l'état « actif », un effet communément appelé « blocus de Rydberg ».

## Champ de conduite
<a name="braket-get-started-driving-field"></a>

Au début du programme AHS, tous les spins (par défaut) démarrent dans leur état « down », ils sont dans une phase dite ferromagnétique. En gardant un œil sur notre objectif de préparer la phase antiferromagnétique, nous avons spécifié un champ de commande cohérent dépendant du temps qui fait passer en douceur les spins de cet état à un état à plusieurs corps où les états « haut » sont préférés. L'hamiltonien correspondant peut être écrit comme

![\[Équation mathématique illustrant le calcul d'une fonction d'entraînement hamiltonienne.\]](http://docs.aws.amazon.com/fr_fr/braket/latest/developerguide/images/HDrive.png)


où Ω (t), φ (t), Δ (t) sont l'amplitude globale (ou [fréquence de Rabi](https://en.wikipedia.org/wiki/Rabi_frequency)), la phase et le désaccord du champ moteur en fonction du temps, affectant tous les spins de manière uniforme. Ici, S −,k =↓ k​ ⟨↑ k et S \$1,k =( S−,k) † =↑ ± k​ ↓ ↓ k sont respectivement les opérateurs d'abaissement et d'augmentation du spin k, et n k =↑ k k La partie Ω du champ moteur couple de manière cohérente les états « bas » et « haut » de tous les spins simultanément, tandis que la partie Δ contrôle la récompense énergétique pour les états « haut ».

Pour programmer une transition en douceur de la phase ferromagnétique à la phase antiferromagnétique, nous indiquons le champ de commande avec le code suivant.

```
from braket.timings.time_series import TimeSeries
from braket.ahs.driving_field import DrivingField

# Smooth transition from "down" to "up" state
time_max = 4e-6  # seconds
time_ramp = 1e-7  # seconds
omega_max = 6300000.0  # rad / sec
delta_start = -5 * omega_max
delta_end = 5 * omega_max

omega = TimeSeries()
omega.put(0.0, 0.0)
omega.put(time_ramp, omega_max)
omega.put(time_max - time_ramp, omega_max)
omega.put(time_max, 0.0)

delta = TimeSeries()
delta.put(0.0, delta_start)
delta.put(time_ramp, delta_start)
delta.put(time_max - time_ramp, delta_end)
delta.put(time_max, delta_end)

phi = TimeSeries().put(0.0, 0.0).put(time_max, 0.0)

drive = DrivingField(
   amplitude=omega,
   phase=phi,
   detuning=delta
)
```

Nous pouvons visualiser les séries chronologiques du champ de conduite avec le script suivant.

```
fig, axes = plt.subplots(3, 1, figsize=(12, 7), sharex=True)

ax = axes[0]
time_series = drive.amplitude.time_series
ax.plot(time_series.times(), time_series.values(), '.-')
ax.grid()
ax.set_ylabel('Omega [rad/s]')

ax = axes[1]
time_series = drive.detuning.time_series
ax.plot(time_series.times(), time_series.values(), '.-')
ax.grid()
ax.set_ylabel('Delta [rad/s]')

ax = axes[2]
time_series = drive.phase.time_series
# Note: time series of phase is understood as a piecewise constant function
ax.step(time_series.times(), time_series.values(), '.-', where='post')
ax.set_ylabel('phi [rad]')
ax.grid()
ax.set_xlabel('time [s]')

plt.show()  # This will show the plot below in an ipython or jupyter session
```

![\[Trois graphiques montrant les valeurs phi, delta et oméga au fil du temps. Le sous-graphique supérieur montre la croissance juste au-dessus de 6, rads/s où elle reste pendant 4 secondes jusqu'à ce qu'elle retombe à 0. Le sous-diagramme du milieu représente la croissance linéaire associée de la dérivée, tandis que le sous-diagramme du bas illustre une ligne plate proche de zéro.\]](http://docs.aws.amazon.com/fr_fr/braket/latest/developerguide/images/DrivingTimeSeries.png)


## Programme AHS
<a name="braket-get-started-ahs-program"></a>

Le registre, le champ de conduite (et les interactions implicites de van der Waals) constituent le programme de simulation hamiltonienne analogique. `ahs_program`

```
from braket.ahs.analog_hamiltonian_simulation import AnalogHamiltonianSimulation

ahs_program = AnalogHamiltonianSimulation(
   register=register,
   hamiltonian=drive
)
```

## Exécution sur un simulateur local
<a name="braket-get-started-running-local-simulator"></a>

Comme cet exemple est petit (moins de 15 tours), avant de l'exécuter sur un QPU compatible AHS, nous pouvons l'exécuter sur le simulateur AHS local fourni avec le SDK Braket. Le simulateur local étant disponible gratuitement avec le SDK Braket, il s'agit d'une bonne pratique pour garantir que notre code puisse s'exécuter correctement.

Ici, nous pouvons régler le nombre de prises à une valeur élevée (disons, 1 million) car le simulateur local suit l'évolution temporelle de l'état quantique et prélève des échantillons à partir de l'état final, augmentant ainsi le nombre de prises de vue, tout en n'augmentant que légèrement le temps d'exécution total.

```
from braket.devices import LocalSimulator

device = LocalSimulator("braket_ahs")

result_simulator = device.run(
   ahs_program,
   shots=1_000_000
).result()  # Takes about 5 seconds
```

## Analyse des résultats du simulateur
<a name="braket-get-started-analyzing-simulator-results"></a>

Nous pouvons agréger les résultats des tirs à l'aide de la fonction suivante qui déduit l'état de chaque rotation (qui peut être « d » pour « vers le bas », « u » pour « haut » ou « e » pour un site vide) et compte le nombre de fois où chaque configuration s'est produite sur les plans.

```
from collections import Counter


def get_counts(result):
    """Aggregate state counts from AHS shot results

    A count of strings (of length = # of spins) are returned, where
    each character denotes the state of a spin (site):
      e: empty site
      u: up state spin
      d: down state spin

    Args:
      result (braket.tasks.analog_hamiltonian_simulation_quantum_task_result.AnalogHamiltonianSimulationQuantumTaskResult)

    Returns
       dict: number of times each state configuration is measured

    """
    state_counts = Counter()
    states = ['e', 'u', 'd']
    for shot in result.measurements:
        pre = shot.pre_sequence
        post = shot.post_sequence
        state_idx = np.array(pre) * (1 + np.array(post))
        state = "".join(map(lambda s_idx: states[s_idx], state_idx))
        state_counts.update((state,))
    return dict(state_counts)


counts_simulator = get_counts(result_simulator)  # Takes about 5 seconds
print(counts_simulator)
```

```
*[Output]*
{'dddddddd': 5, 'dddddddu': 12, 'ddddddud': 15, ...}
```

`counts`Voici un dictionnaire qui compte le nombre de fois que chaque configuration d'état est observée sur les plans. Nous pouvons également les visualiser avec le code suivant.

```
from collections import Counter


def has_neighboring_up_states(state):
    if 'uu' in state:
        return True
    if state[0] == 'u' and state[-1] == 'u':
        return True
    return False


def number_of_up_states(state):
    return Counter(state)['u']


def plot_counts(counts):
    non_blockaded = []
    blockaded = []
    for state, count in counts.items():
        if not has_neighboring_up_states(state):
            collection = non_blockaded
        else:
            collection = blockaded
        collection.append((state, count, number_of_up_states(state)))

    blockaded.sort(key=lambda _: _[1], reverse=True)
    non_blockaded.sort(key=lambda _: _[1], reverse=True)

    for configurations, name in zip((non_blockaded,
                                     blockaded),
                                    ('no neighboring "up" states',
                                     'some neighboring "up" states')):
        plt.figure(figsize=(14, 3))
        plt.bar(range(len(configurations)), [item[1] for item in configurations])
        plt.xticks(range(len(configurations)))
        plt.gca().set_xticklabels([item[0] for item in configurations], rotation=90)
        plt.ylabel('shots')
        plt.grid(axis='y')
        plt.title(f'{name} configurations')
        plt.show()


plot_counts(counts_simulator)
```

![\[Diagramme à barres montrant un grand nombre de prises de vue sans configurations d'états « up » voisines.\]](http://docs.aws.amazon.com/fr_fr/braket/latest/developerguide/images/AHSCounts1.png)


![\[Diagramme à barres montrant des plans de certaines configurations d'états « en haut » voisines, avec 4 états à 1,0 plan.\]](http://docs.aws.amazon.com/fr_fr/braket/latest/developerguide/images/AHSCounts2.png)


À partir des graphiques, nous pouvons lire les observations suivantes pour vérifier que nous avons bien préparé la phase antiferromagnétique.

1. En général, les états non bloqués (où aucun spin voisin n'est dans l'état « haut ») sont plus courants que les états où au moins une paire de spins voisins sont tous deux dans l'état « haut ».

1. En général, les états avec plus d'excitations « ascendantes » sont privilégiés, sauf si la configuration est bloquée.

1. Les états les plus courants sont en effet les états `"dudududu"` antiferromagnétiques parfaits et. `"udududud"`

1. Les deuxièmes états les plus courants sont ceux où il n'y a que 3 excitations « ascendantes » avec des séparations consécutives de 1, 2, 2. Cela montre que l'interaction de van der Waals a également un effet (bien que beaucoup plus faible) sur les voisins les plus proches.

## Running QuEra On's Aquila QPU
<a name="braket-get-started-running-aquila-qpu"></a>

 **Conditions préalables** [: Outre l'installation du [SDK](https://github.com/aws/amazon-braket-sdk-python#installing-the-amazon-braket-python-sdk) Braket par pip, si vous utilisez Amazon Braket pour la première fois, assurez-vous d'avoir suivi les étapes de démarrage nécessaires.](https://docs.aws.amazon.com/braket/latest/developerguide/braket-get-started.html)

**Note**  
Si vous utilisez une instance de bloc-notes hébergée par Braket, le SDK Braket est préinstallé avec l'instance.

Une fois toutes les dépendances installées, nous pouvons nous connecter au Aquila QPU.

```
from braket.aws import AwsDevice

aquila_qpu = AwsDevice("arn:aws:braket:us-east-1::device/qpu/quera/Aquila")
```

Pour que notre programme AHS soit adapté à la QuEra machine, nous devons arrondir toutes les valeurs afin de respecter les niveaux de précision autorisés par le Aquila QPU. (Ces exigences sont régies par les paramètres de l'appareil dont le nom contient « Résolution ». Nous pouvons les voir en les exécutant `aquila_qpu.properties.dict()` dans un carnet. Pour plus de détails sur les fonctionnalités et les exigences d'Aquila, consultez le bloc-notes [Introduction à Aquila](https://github.com/aws/amazon-braket-examples/blob/main/examples/analog_hamiltonian_simulation/01_Introduction_to_Aquila.ipynb).) Nous pouvons le faire en appelant la `discretize` méthode.

```
discretized_ahs_program = ahs_program.discretize(aquila_qpu)
```

Nous pouvons maintenant exécuter le programme (seulement 100 prises de vue pour le moment) sur le Aquila QPU.

**Note**  
L'exécution de ce programme sur le Aquila processeur entraînera un coût. Le SDK Amazon Braket inclut un outil de [suivi des coûts](https://aws.amazon.com/blogs/quantum-computing/managing-the-cost-of-your-experiments-in-amazon-braket/) qui permet aux clients de définir des limites de coûts et de suivre leurs coûts en temps quasi réel.

```
task = aquila_qpu.run(discretized_ahs_program, shots=100)

metadata = task.metadata()
task_arn = metadata['quantumTaskArn']
task_status = metadata['status']

print(f"ARN: {task_arn}")
print(f"status: {task_status}")
```

```
*[Output]*
ARN: arn:aws:braket:us-east-1:123456789012:quantum-task/12345678-90ab-cdef-1234-567890abcdef
status: CREATED
```

En raison de la grande variation de la durée d'exécution d'une tâche quantique (en fonction des fenêtres de disponibilité et de l'utilisation du QPU), il est conseillé de noter l'ARN de la tâche quantique, afin que nous puissions vérifier son statut ultérieurement à l'aide de l'extrait de code suivant.

```
# Optionally, in a new python session
from braket.aws import AwsQuantumTask

SAVED_TASK_ARN = "arn:aws:braket:us-east-1:123456789012:quantum-task/12345678-90ab-cdef-1234-567890abcdef"

task = AwsQuantumTask(arn=SAVED_TASK_ARN)
metadata = task.metadata()
task_arn = metadata['quantumTaskArn']
task_status = metadata['status']

print(f"ARN: {task_arn}")
print(f"status: {task_status}")
```

```
*[Output]*
ARN: arn:aws:braket:us-east-1:123456789012:quantum-task/12345678-90ab-cdef-1234-567890abcdef
status: COMPLETED
```

Une fois le statut TERMINÉ (qui peut également être vérifié depuis la page des tâches quantiques de la [console](https://us-east-1.console.aws.amazon.com/braket/home?region=us-east-1#/tasks) Amazon Braket), nous pouvons interroger les résultats avec :

```
result_aquila = task.result()
```

## Analyse des résultats du QPU
<a name="braket-get-started-analyzing-qpu-results"></a>

En utilisant les mêmes `get_counts` fonctions que précédemment, nous pouvons calculer les nombres :

```
counts_aquila = get_counts(result_aquila)
   print(counts_aquila)
```

```
*[Output]*
{'dddududd': 2, 'dudududu': 18, 'ddududud': 4, ...}
```

et tracez-les avec `plot_counts` :

```
plot_counts(counts_aquila)
```

![\[Diagramme à barres montrant un grand nombre de prises de vue sans configurations d'états « up » voisines.\]](http://docs.aws.amazon.com/fr_fr/braket/latest/developerguide/images/QPUPlotCounts1.png)


![\[Diagramme à barres montrant des plans de certaines configurations d'états « en haut » voisines, avec 4 états à 1,0 plan.\]](http://docs.aws.amazon.com/fr_fr/braket/latest/developerguide/images/QPUPlotCounts2.png)


Notez qu'une petite partie des prises de vue comportent des sites vides (marqués d'un « e »). Cela est dû à une imperfection de préparation de 1 à 2 % par atome du Aquila QPU. En outre, les résultats correspondent à la simulation dans les limites des fluctuations statistiques attendues en raison du faible nombre de prises de vue.

## Étapes suivantes
<a name="braket-get-started-ahs-next"></a>

Félicitations, vous venez d'exécuter votre première charge de travail AHS sur Amazon Braket à l'aide du simulateur AHS local et du Aquila QPU.

[Pour en savoir plus sur la physique de Rydberg, la simulation hamiltonienne analogique et le Aquila dispositif, consultez nos exemples de carnets de notes.](https://github.com/aws/amazon-braket-examples/tree/main/examples/analog_hamiltonian_simulation)

# Soumettre un programme analogique à l'aide d' QuEra Aquila
<a name="braket-quera-submitting-analog-program-aquila"></a>

Cette page fournit une documentation complète sur les fonctionnalités de la Aquila machine à partir deQuEra. Les détails abordés ici sont les suivants : 

1. L'hamiltonien paramétré simulé par Aquila

1. Paramètres du programme AHS

1. Contenu du résultat AHS

1. Aquilaparamètre de capacités

**Topics**
+ [hamiltonien](#braket-quera-aquila-device-hamiltonian)
+ [Schéma du programme Braket AHS](#braket-quera-ahs-program-schema)
+ [Schéma des résultats des tâches Braket AHS](#braket-quera-ahs-task-result-schema)
+ [QuEra schéma des propriétés de l'appareil](#braket-quera-device-properties-schema)

## hamiltonien
<a name="braket-quera-aquila-device-hamiltonian"></a>

La Aquila machine de QuEra simule nativement l'hamiltonien suivant (en fonction du temps) :

![\[Équation mathématique avec des sommations représentant l'hamiltonien d'un système, impliquant des termes d'entraînement, de désaccordage local et de couplage interpoints.\]](http://docs.aws.amazon.com/fr_fr/braket/latest/developerguide/images/TimeDependentDrivingHamiltonian.png)


**Note**  
L'accès au désaccordage local est une [fonctionnalité expérimentale](https://docs.aws.amazon.com/braket/latest/developerguide/braket-experimental-capabilities.html) et est disponible sur demande via Braket Direct.

où
+ H drive,k (t) = (1/2Ω (t) e iφ (t) S −,k \$1 1/2Ω (t) e −iφ (t) S) \$1 (−Δ global (t\$1,k​) n), k
  + Ω (t) est l'amplitude de conduite globale en fonction du temps (également appelée fréquence de Rabi), en unités de (rad/s)
  + φ (t) est la phase globale dépendante du temps, mesurée en radians
  + S −,k​ et S \$1,k sont les opérateurs d'abaissement et d'augmentation du spin de l'atome k (dans la base \$1↓⟩ =\$1g⟩, \$1↑=\$1r⟩, ils sont S − =\$1g \$1 −
  + Δ global (t) est le déréglage global dépendant du temps
  + n k est l'opérateur de projection sur l'état de Rydberg de l'atome k (c'est-à-dire, n=\$1r
+ H local detuning,k (t) =-Δ local (t) h n k k
  + Δ local (t) est le facteur dépendant du temps du décalage de fréquence local, en unités de (rad/s)
  + h k est le facteur dépendant du site, un nombre sans dimension compris entre 0,0 et 1,0
+ V vdw,k,l = C6​/(dk,l) 6 n k n, l
  + C 6 est le coefficient de van der Waals, en unités de (rad/s) \$1 (m) ^6
  + d k,l est la distance euclidienne entre l'atome k et l, mesurée en mètres.

Les utilisateurs peuvent contrôler les paramètres suivants via le schéma du programme Braket AHS.
+ Arrangement bidimensionnel des atomes (kcoordonnées x k et y de chaque atome k, en unités de µm), qui contrôle les distances atomiques par paires d k,l​ avec k, l=1,2,... N
+ Ω (t), fréquence globale de Rabi dépendante du temps, en unités de (rad/s)
+ φ (t), phase globale dépendante du temps, en unités de (rad)
+ Δ global (t), le désaccordage global dépendant du temps, en unités de (rad/s)
+ Δ local (t), le facteur (global) dépendant du temps de l'ampleur du déréglage local, en unités de (rad/s)
+ hk, le facteur (statique) dépendant du site de l'ampleur du déréglage local, un nombre adimensionnel compris entre 0,0 et 1,0

**Note**  
L'utilisateur ne peut pas contrôler les niveaux concernés (c'est-à-dire que les opérateurs S−, S\$1​, n sont fixes) ni la force du coefficient d'interaction Rydberg-Rydberg (C). 6

## Schéma du programme Braket AHS
<a name="braket-quera-ahs-program-schema"></a>

 **Objet Braket.IR.AHS.Program\$1V1.program** (exemple)

**Note**  
Si la fonctionnalité de [désaccordage local](https://docs.aws.amazon.com/braket/latest/developerguide/braket-experimental-capabilities.html#braket-access-local-detuning) n'est pas activée pour votre compte, utilisez-la `localDetuning=[]` dans l'exemple suivant.

```
Program(
    braketSchemaHeader=BraketSchemaHeader(
        name='braket.ir.ahs.program',
        version='1'
    ),
    setup=Setup(
        ahs_register=AtomArrangement(
            sites=[
                [Decimal('0'), Decimal('0')],
                [Decimal('0'), Decimal('4e-6')],
                [Decimal('4e-6'), Decimal('0')]
            ],
            filling=[1, 1, 1]
        )
    ),
    hamiltonian=Hamiltonian(
        drivingFields=[
            DrivingField(
                amplitude=PhysicalField(
                    time_series=TimeSeries(
                        values=[Decimal('0'), Decimal('15700000.0'), Decimal('15700000.0'), Decimal('0')],
                        times=[Decimal('0'), Decimal('0.000001'), Decimal('0.000002'), Decimal('0.000003')]
                    ),
                    pattern='uniform'
                ),
                phase=PhysicalField(
                    time_series=TimeSeries(
                        values=[Decimal('0'), Decimal('0')],
                        times=[Decimal('0'), Decimal('0.000003')]
                    ),
                    pattern='uniform'
                ),
                detuning=PhysicalField(
                    time_series=TimeSeries(
                        values=[Decimal('-54000000.0'), Decimal('54000000.0')],
                        times=[Decimal('0'), Decimal('0.000003')]
                    ),
                    pattern='uniform'
                )
            )
        ],
        localDetuning=[
            LocalDetuning(
                magnitude=PhysicalField(
                    times_series=TimeSeries(
                        values=[Decimal('0'), Decimal('25000000.0'), Decimal('25000000.0'), Decimal('0')],
                        times=[Decimal('0'), Decimal('0.000001'), Decimal('0.000002'), Decimal('0.000003')]
                    ),
                    pattern=Pattern([Decimal('0.8'), Decimal('1.0'), Decimal('0.9')])
                )
            )
        ]
    )
)
```

**JSON** (exemple)

**Note**  
Si la fonctionnalité de [désaccordage local](https://docs.aws.amazon.com/braket/latest/developerguide/braket-experimental-capabilities.html#braket-access-local-detuning) n'est pas activée pour votre compte, utilisez-la `"localDetuning": []` dans l'exemple suivant.

```
{
    "braketSchemaHeader": {
        "name": "braket.ir.ahs.program",
        "version": "1"
    },
    "setup": {
        "ahs_register": {
            "sites": [
                [0E-7, 0E-7], 
                [0E-7, 4E-6],
                [4E-6, 0E-7]
            ],
            "filling": [1, 1, 1]
        }
    },
    "hamiltonian": {
        "drivingFields": [
            {
                "amplitude": {
                    "time_series": {
                        "values": [0.0, 15700000.0, 15700000.0, 0.0],
                        "times": [0E-9, 0.000001000, 0.000002000, 0.000003000]
                    },
                    "pattern": "uniform"
                },
                "phase": {
                    "time_series": {
                        "values": [0E-7, 0E-7],
                        "times": [0E-9, 0.000003000]
                    },
                    "pattern": "uniform"
                },
                "detuning": {
                    "time_series": {
                        "values": [-54000000.0, 54000000.0],
                        "times": [0E-9, 0.000003000]
                    },
                    "pattern": "uniform"
                }
            }
        ],
        "localDetuning": [
            {
                "magnitude": {
                    "time_series": {
                        "values": [0.0, 25000000.0, 25000000.0, 0.0],
                        "times": [0E-9, 0.000001000, 0.000002000, 0.000003000]
                    },
                    "pattern": [0.8, 1.0, 0.9]
                }
            }
        ]
    }
}
```


**Principaux domaines**  

| Champ du programme | type | description | 
| --- | --- | --- | 
|  setup.ahs\$1register.sites  |  Liste [Liste [Décimal]]  |  Liste des coordonnées bidimensionnelles où la pince à épiler piège les atomes  | 
|  setup.ahs\$1register.filling  |  Liste [int]  |  Marque les atomes qui occupent les sites piégés avec 1 et les sites vides avec 0  | 
|  Hamiltonian.DrivingFields [] .amplitude.time\$1series.times  |  Liste [décimale]  |  points temporels de l'amplitude de conduite, Omega (t)  | 
|  Hamiltonian.DrivingFields [] .amplitude.time\$1series.values  |  Liste [décimale]  |  valeurs de l'amplitude de conduite, Omega (t)  | 
|  Hamiltonian.DrivingFields [] .amplitude.pattern  |  str  |  schéma spatial de l'amplitude de conduite, Omega (t) ; doit être « uniforme »  | 
|  Hamiltonian.DrivingFields [] .phase.time\$1series.times  |  Liste [décimale]  |  points temporels de la phase de conduite, phi (t)  | 
|  Hamiltonian.DrivingFields [] .phase.time\$1series.values  |  Liste [décimale]  |  valeurs de la phase de conduite, phi (t)  | 
|  Hamiltonian.DrivingFields [] .phase.pattern  |  str  |  schéma spatial de la phase de conduite, phi (t) ; doit être « uniforme »  | 
|  Hamiltonian.DrivingFields [] .detuning.time\$1series.times  |  Liste [décimale]  |  points temporels du désaccordage de conduite, Delta\$1global (t)  | 
|  Hamiltonian.DrivingFields [] .detuning.time\$1series.values  |  Liste [décimale]  |  valeurs du désaccordage de conduite, Delta\$1global (t)  | 
|  Hamiltonian.DrivingFields [] .detuning.pattern  |  str  |  schéma spatial de désaccordage de conduite, Delta\$1global (t) ; doit être « uniforme »  | 
|  Hamiltonian.LocalDeTuning [] .magnitude.time\$1series.times  |  Liste [décimale]  |  points temporels du facteur dépendant du temps de l'amplitude de désaccordage locale, Delta\$1local (t)  | 
|  Hamiltonian.LocalDeTuning [] .magnitude.time\$1series.values  |  Liste [décimale]  |  valeurs du facteur dépendant du temps de l'amplitude de déréglage locale, Delta\$1local (t)  | 
|  Hamiltonian.LocalDeTuning [] .magnitude.pattern  |  Liste [décimale]  |  facteur dépendant du site de l'amplitude du déréglage local, h\$1k (les valeurs correspondent aux sites dans setup.ahs\$1register.sites)  | 


**Champs de métadonnées**  

| Champ du programme | type | description | 
| --- | --- | --- | 
|  braketSchemaHeader.nom  |  str  |  nom du schéma ; doit être « braket.ir.ahs.program »  | 
|  braketSchemaHeader.version  |  str  |  version du schéma  | 

## Schéma des résultats des tâches Braket AHS
<a name="braket-quera-ahs-task-result-schema"></a>

 **braket.tasks.analog\$1hamiltonian\$1simulation\$1quantum\$1task\$1result. AnalogHamiltonianSimulationQuantumTaskResult**(exemple)

```
AnalogHamiltonianSimulationQuantumTaskResult(
    task_metadata=TaskMetadata(
        braketSchemaHeader=BraketSchemaHeader(
            name='braket.task_result.task_metadata',
            version='1'
        ),
        id='arn:aws:braket:us-east-1:123456789012:quantum-task/12345678-90ab-cdef-1234-567890abcdef',
        shots=2,
        deviceId='arn:aws:braket:us-east-1::device/qpu/quera/Aquila',
        deviceParameters=None,
        createdAt='2022-10-25T20:59:10.788Z',
        endedAt='2022-10-25T21:00:58.218Z',
        status='COMPLETED',
        failureReason=None
    ),
    measurements=[
        ShotResult(
            status=<AnalogHamiltonianSimulationShotStatus.SUCCESS: 'Success'>,

            pre_sequence=array([1, 1, 1, 1]),
            post_sequence=array([0, 1, 1, 1])
        ),

        ShotResult(
            status=<AnalogHamiltonianSimulationShotStatus.SUCCESS: 'Success'>,

            pre_sequence=array([1, 1, 0, 1]),
            post_sequence=array([1, 0, 0, 0])
        )
    ]
)
```

 **JSON** (exemple)

```
{
    "braketSchemaHeader": {
        "name": "braket.task_result.analog_hamiltonian_simulation_task_result",
        "version": "1"
    },
    "taskMetadata": {
        "braketSchemaHeader": {
            "name": "braket.task_result.task_metadata",
            "version": "1"
        },
        "id": "arn:aws:braket:us-east-1:123456789012:quantum-task/12345678-90ab-cdef-1234-567890abcdef",
        "shots": 2,
        "deviceId": "arn:aws:braket:us-east-1::device/qpu/quera/Aquila",

        "createdAt": "2022-10-25T20:59:10.788Z",
        "endedAt": "2022-10-25T21:00:58.218Z",
        "status": "COMPLETED"

    },
    "measurements": [
        {
            "shotMetadata": {"shotStatus": "Success"},
            "shotResult": {
                "preSequence": [1, 1, 1, 1],
                "postSequence": [0, 1, 1, 1]
            }
        },
        {
            "shotMetadata": {"shotStatus": "Success"},
            "shotResult": {
                "preSequence": [1, 1, 0, 1],
                "postSequence": [1, 0, 0, 0]
            }
        }
    ],
    "additionalMetadata": {
        "action": {...}
        "queraMetadata": {
            "braketSchemaHeader": {
                "name": "braket.task_result.quera_metadata",
                "version": "1"
            },
            "numSuccessfulShots": 100
        }
    }
}
```


**Principaux domaines**  

| Champ de résultat de la tâche | type | description | 
| --- | --- | --- | 
|  mesures [] .ShotResult.PreSequence  |  Liste [int]  |  Bits de mesure de pré-séquence (un pour chaque site atomique) pour chaque tir : 0 si le site est vide, 1 si le site est plein, mesurés avant les séquences d'impulsions qui exécutent l'évolution quantique  | 
|  mesures [] .ShotResult.PostSequence  |  Liste [int]  |  Bits de mesure post-séquence pour chaque tir : 0 si l'atome est dans l'état de Rydberg ou si le site est vide, 1 si l'atome est dans l'état fondamental, mesurés à la fin des séquences d'impulsions qui exécutent l'évolution quantique  | 


**Champs de métadonnées**  

| Champ de résultat de la tâche | type | description | 
| --- | --- | --- | 
|  braketSchemaHeader.nom  |  str  |  nom du schéma ; doit être « braket.task\$1result.analog\$1hamiltonian\$1simulation\$1task\$1result »  | 
|  braketSchemaHeader.version  |  str  |  version du schéma  | 
|  Métadonnées des tâches. braketSchemaHeader.nom  |  str  |  nom du schéma ; doit être « braket.task\$1result.task\$1metadata »  | 
|  Métadonnées des tâches. braketSchemaHeader.version  |  str  |  version du schéma  | 
|  TaskMetadata.id  |  str  |  L'identifiant de la tâche quantique. Pour les tâches AWS quantiques, il s'agit de l'ARN des tâches quantiques.  | 
|  TaskMetadata.Shots  |  int  |  Le nombre de tirs pour la tâche quantique  | 
|  TaskMetadata.Shots.DeviceID  |  str  |  L'identifiant de l'appareil sur lequel la tâche quantique s'est exécutée. Pour les AWS appareils, il s'agit de l'ARN de l'appareil.  | 
|  TaskMetadata.Shots.Créé à  |  str  |  Horodatage de la création ; le format doit être au format RFC3339 ISO-8601/ string format:MM:SS.SSSZ. YYYY-MM-DDTHH La valeur par défaut est None.  | 
|  TaskMetadata.shots.Endedat  |  str  |  Horodatage de la fin de la tâche quantique ; le format doit être au format RFC3339 ISO-8601/ string format:MM:SS.SSSZ. YYYY-MM-DDTHH La valeur par défaut est None.  | 
|  TaskMetadata.Shots.Status  |  str  |  État de la tâche quantique (CREATED, QUEUED, RUNNING, COMPLETED, FAILED). La valeur par défaut est None.  | 
|  TaskMetadata.Shots.Raison de l'échec  |  str  |  La raison de l'échec de la tâche quantique. La valeur par défaut est None.  | 
|  Métadonnées.Action supplémentaires  |  Braket.IR.AHS.Program\$1V1.program  |  (Voir la section sur le [schéma du programme Braket AHS](#braket-quera-ahs-program-schema))  | 
|  Métadonnées supplémentaires. Action. braketSchemaHeader.querametadata.name  |  str  |  nom du schéma ; doit être « braket.task\$1result.quera\$1metadata »  | 
|  Métadonnées supplémentaires. Action. braketSchemaHeader.Quera Metadata.Version  |  str  |  version du schéma  | 
|  Métadonnées supplémentaires. Action. numSuccessfulShots  |  int  |  nombre de prises complètement réussies ; doit être égal au nombre de prises demandé  | 
|  mesures [] .shotMetadata.shotStatus  |  int  |  Le statut du tir (succès, succès partiel, échec) doit être « Succès »  | 

## QuEra schéma des propriétés de l'appareil
<a name="braket-quera-device-properties-schema"></a>

 **braket.device\$1schema.quera.quera\$1device\$1capabilities\$1v1. QueraDeviceCapabilities**(exemple)

```
QueraDeviceCapabilities(
    service=DeviceServiceProperties(
        braketSchemaHeader=BraketSchemaHeader(
            name='braket.device_schema.device_service_properties', 
            version='1'
            ), 
            executionWindows=[
                DeviceExecutionWindow(
                    executionDay=<ExecutionDay.MONDAY: 'Monday'>, 
                    windowStartHour=datetime.time(1, 0), 
                    windowEndHour=datetime.time(23, 59, 59)
                ), 
                DeviceExecutionWindow(
                    executionDay=<ExecutionDay.TUESDAY: 'Tuesday'>, 
                    windowStartHour=datetime.time(0, 0), 
                    windowEndHour=datetime.time(12, 0)
                ), 
                DeviceExecutionWindow(
                    executionDay=<ExecutionDay.WEDNESDAY: 'Wednesday'>, 
                    windowStartHour=datetime.time(0, 0), 
                    windowEndHour=datetime.time(12, 0)
                ), 
                DeviceExecutionWindow(
                    executionDay=<ExecutionDay.FRIDAY: 'Friday'>, 
                    windowStartHour=datetime.time(0, 0), 
                    windowEndHour=datetime.time(23, 59, 59)
                ), 
                DeviceExecutionWindow(
                    executionDay=<ExecutionDay.SATURDAY: 'Saturday'>, 
                    windowStartHour=datetime.time(0, 0), 
                    windowEndHour=datetime.time(23, 59, 59)
                ), 
                DeviceExecutionWindow(
                    executionDay=<ExecutionDay.SUNDAY: 'Sunday'>, 
                    windowStartHour=datetime.time(0, 0), 
                    windowEndHour=datetime.time(12, 0)
                )
            ], 
            shotsRange=(1, 1000), 
            deviceCost=DeviceCost(
                price=0.01, 
                unit='shot'
            ), 
            deviceDocumentation=
                DeviceDocumentation(
                    imageUrl='https://a.b.cdn.console.awsstatic.com/59534b58c709fc239521ef866db9ea3f1aba73ad3ebcf60c23914ad8c5c5c878/a6cfc6fca26cf1c2e1c6.png', 
                    summary='Analog quantum processor based on neutral atom arrays', 
                    externalDocumentationUrl='https://www.quera.com/aquila'
                ), 
                deviceLocation='Boston, USA', 
                updatedAt=datetime.datetime(2024, 1, 22, 12, 0, tzinfo=datetime.timezone.utc), 
                getTaskPollIntervalMillis=None
    ), 
    action={
        <DeviceActionType.AHS: 'braket.ir.ahs.program'>: DeviceActionProperties(
                version=['1'], 
                actionType=<DeviceActionType.AHS: 'braket.ir.ahs.program'>
            )
    }, 
    deviceParameters={}, 
    braketSchemaHeader=BraketSchemaHeader(
        name='braket.device_schema.quera.quera_device_capabilities', 
        version='1'
    ), 
    paradigm=QueraAhsParadigmProperties(
        ...
        # See https://github.com/amazon-braket/amazon-braket-schemas-python/blob/main/src/braket/device_schema/quera/quera_ahs_paradigm_properties_v1.py
        ...
    )  
)
```

 **JSON** (exemple)

```
{
    "service": {
        "braketSchemaHeader": {
            "name": "braket.device_schema.device_service_properties",
            "version": "1"
        },
        "executionWindows": [
            {
                "executionDay": "Monday",
                "windowStartHour": "01:00:00",
                "windowEndHour": "23:59:59"
            },
            {
                "executionDay": "Tuesday",
                "windowStartHour": "00:00:00",
                "windowEndHour": "12:00:00"
            },
            {
                "executionDay": "Wednesday",
                "windowStartHour": "00:00:00",
                "windowEndHour": "12:00:00"
            },
            {
                "executionDay": "Friday",
                "windowStartHour": "00:00:00",
                "windowEndHour": "23:59:59"
            },
            {
                "executionDay": "Saturday",
                "windowStartHour": "00:00:00",
                "windowEndHour": "23:59:59"
            },
            {
                "executionDay": "Sunday",
                "windowStartHour": "00:00:00",
                "windowEndHour": "12:00:00"
            }
        ],
        "shotsRange": [
            1,
            1000
        ],
        "deviceCost": {
            "price": 0.01,
            "unit": "shot"
        },
        "deviceDocumentation": {
            "imageUrl": "https://a.b.cdn.console.awsstatic.com/59534b58c709fc239521ef866db9ea3f1aba73ad3ebcf60c23914ad8c5c5c878/a6cfc6fca26cf1c2e1c6.png",
            "summary": "Analog quantum processor based on neutral atom arrays",
            "externalDocumentationUrl": "https://www.quera.com/aquila"
        },
        "deviceLocation": "Boston, USA",
        "updatedAt": "2024-01-22T12:00:00+00:00"
    },
    "action": {
        "braket.ir.ahs.program": {
            "version": [
                "1"
            ],
            "actionType": "braket.ir.ahs.program"
        }
    },
    "deviceParameters": {},
    "braketSchemaHeader": {
        "name": "braket.device_schema.quera.quera_device_capabilities",
        "version": "1"
    },
    "paradigm": {
        ...
        # See Aquila device page > "Calibration" tab > "JSON" page
        ...
    }
}
```


**Champs des propriétés du service**  

| Champ des propriétés du service | type | description | 
| --- | --- | --- | 
|  Service.ExecutionWindows [] .ExecutionDay  |  ExecutionDay  |  Jours de la fenêtre d'exécution ; doivent être « Tous les jours », « Jours de semaine », « Week-end », « lundi », « mardi », « mercredi », « jeudi », « vendredi », « samedi » ou « dimanche »  | 
|  Service.ExecutionWindows []. windowStartHour  |  datetime.heure  |  Format UTC 24 heures de l'heure de début de la fenêtre d'exécution  | 
|  Service.ExecutionWindows []. windowEndHour  |  datetime.heure  |  Format UTC de 24 heures indiquant l'heure de fin de la fenêtre d'exécution  | 
|  service.qpu\$1capabilities.service.shotsRange  |  Tuple [int, int]  |  Nombre minimum et maximum de prises de vue pour l'appareil  | 
|  service.qpu\$1capabilities.service.DeviceCost.Price  |  float  |  Prix de l'appareil en dollars américains  | 
|  service.qpu\$1capabilities.service.DeviceCost.unit  |  str  |  unité pour facturer le prix, par exemple : « minute », « heure », « shot », « task »  | 


**Champs de métadonnées**  

| Champ de métadonnées | type | description | 
| --- | --- | --- | 
|  action [] .version  |  str  |  version du schéma du programme AHS  | 
|  action [] .ActionType  |  ActionType  |  Nom du schéma du programme AHS ; doit être « braket.ir.ahs.program »  | 
|  service. braketSchemaHeader.nom  |  str  |  nom du schéma ; doit être « braket.device\$1schema.device\$1service\$1properties »  | 
|  service. braketSchemaHeader.version  |  str  |  version du schéma  | 
|  Service.DeviceDocumentation.URL de l'image  |  str  |  URL de l'image de l'appareil  | 
|  Service.DeviceDocumentation.Résumé  |  str  |  brève description de l'appareil  | 
|  Service.DeviceDocumentation. externalDocumentationUrl  |  str  |  URL de documentation externe  | 
|  Service.Emplacement de l'appareil  |  str  |  emplacement géographique de l'appareil  | 
|  Service. Mis à jour à  |  datetime  |  heure à laquelle les propriétés de l'appareil ont été mises à jour pour la dernière fois  | 

# Travailler avec AWS Boto3
<a name="braket-using-boto3"></a>

Boto3 est le AWS SDK pour Python. Avec Boto3, les développeurs Python peuvent créer, configurer et gérer Services AWS, comme Amazon Braket. Boto3 fournit un accès orienté objet API ainsi qu'un accès de bas niveau à Amazon Braket.

Suivez les instructions du [guide de démarrage rapide du Boto3](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html) pour savoir comment installer et configurer Boto3.

Boto3 fournit les fonctionnalités de base qui fonctionnent avec le SDK Amazon Braket Python pour vous aider à configurer et à exécuter vos tâches quantiques. Les clients de Python doivent toujours installer Boto3, car il s'agit de l'implémentation principale. Si vous souhaitez utiliser des méthodes d'assistance supplémentaires, vous devez également installer le SDK Amazon Braket.

Par exemple, lorsque vous appelez`CreateQuantumTask`, le SDK Amazon Braket envoie la demande à Boto3, qui appelle ensuite le. AWS API

**Topics**
+ [Activez le client Amazon Braket Boto3](braket-using-boto3-client.md)
+ [Configuration AWS CLI des profils pour Boto3 et le SDK Braket](braket-using-boto3-profiles.md)

# Activez le client Amazon Braket Boto3
<a name="braket-using-boto3-client"></a>

Pour utiliser Boto3 avec Amazon Braket, vous devez importer Boto3, puis définir un client que vous utiliserez pour vous connecter à Amazon Braket. API Dans l'exemple suivant, le client Boto3 est nommé. `braket`

```
import boto3
import botocore

braket = boto3.client("braket")
```

**Note**  
[Supports de support IPv6](https://docs.aws.amazon.com/vpc/latest/userguide/aws-ipv6-support.html). Si vous utilisez un réseau IPv6 uniquement ou si vous souhaitez vous assurer que votre charge de travail utilise IPv6 du trafic, utilisez les points de terminaison à double pile, comme indiqué dans le guide des points de terminaison [à double pile et FIPS](https://docs.aws.amazon.com/sdkref/latest/guide/feature-endpoints.html).

Maintenant que vous avez un `braket` client établi, vous pouvez faire des demandes et traiter les réponses depuis le service Amazon Braket. Vous pouvez obtenir plus de détails sur les données de demande et de réponse dans la [référence de l'API](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/braket.html).

**Topics**
+ [Rechercher des appareils](#braket-using-boto3-example-search-devices)
+ [Récupérez un appareil](#braket-using-boto3-example-retrieve-devices)
+ [Créez une tâche quantique](#braket-using-boto3-example-create-task)
+ [Récupérez une tâche quantique](#braket-using-boto3-example-retrieve-task)
+ [Recherche de tâches quantiques](#braket-using-boto3-example-search-tasks)
+ [Annuler une tâche quantique](#braket-using-boto3-example-cancel-task)

## Rechercher des appareils
<a name="braket-using-boto3-example-search-devices"></a>
+  `search_devices(**kwargs)` 

Recherchez des appareils à l'aide des filtres spécifiés.

```
# Pass search filters and optional parameters when sending the
# request and capture the response
response = braket.search_devices(filters=[{
    'name': 'deviceArn',
    'values': ['arn:aws:braket:::device/quantum-simulator/amazon/sv1']
}], maxResults=10)

print(f"Found {len(response['devices'])} devices")

for i in range(len(response['devices'])):
    device = response['devices'][i]
    print(device['deviceArn'])
```

## Récupérez un appareil
<a name="braket-using-boto3-example-retrieve-devices"></a>
+  `get_device(deviceArn)` 

Récupérez les appareils disponibles sur Amazon Braket.

```
# Pass the device ARN when sending the request and capture the repsonse
response = braket.get_device(deviceArn='arn:aws:braket:::device/quantum-simulator/amazon/sv1')

print(f"Device {response['deviceName']} is {response['deviceStatus']}")
```

## Créez une tâche quantique
<a name="braket-using-boto3-example-create-task"></a>
+  `create_quantum_task(**kwargs)` 

Créez une tâche quantique.

```
# Create parameters to pass into create_quantum_task()
kwargs = {
    # Create a Bell pair
    'action': '{"braketSchemaHeader": {"name": "braket.ir.jaqcd.program", "version": "1"}, "results": [], "basis_rotation_instructions": [], "instructions": [{"type": "h", "target": 0}, {"type": "cnot", "control": 0, "target": 1}]}',
    # Specify the SV1 Device ARN
    'deviceArn': 'arn:aws:braket:::device/quantum-simulator/amazon/sv1',
    # Specify 2 qubits for the Bell pair
    'deviceParameters': '{"braketSchemaHeader": {"name": "braket.device_schema.simulators.gate_model_simulator_device_parameters", "version": "1"}, "paradigmParameters": {"braketSchemaHeader": {"name": "braket.device_schema.gate_model_parameters", "version": "1"}, "qubitCount": 2}}',
    # Specify where results should be placed when the quantum task completes.
    # You must ensure the S3 Bucket exists before calling create_quantum_task()
    'outputS3Bucket': 'amazon-braket-examples',
    'outputS3KeyPrefix': 'boto-examples',
    # Specify number of shots for the quantum task
    'shots': 100
}

# Send the request and capture the response
response = braket.create_quantum_task(**kwargs)

print(f"Quantum task {response['quantumTaskArn']} created")
```

## Récupérez une tâche quantique
<a name="braket-using-boto3-example-retrieve-task"></a>
+  `get_quantum_task(quantumTaskArn)` 

Récupérez la tâche quantique spécifiée.

```
# Pass the quantum task ARN when sending the request and capture the response
response = braket.get_quantum_task(quantumTaskArn='arn:aws:braket:us-west-1:123456789012:quantum-task/ce78c429-cef5-45f2-88da-123456789012')

print(response['status'])
```

## Recherche de tâches quantiques
<a name="braket-using-boto3-example-search-tasks"></a>
+  `search_quantum_tasks(**kwargs)` 

Recherchez les tâches quantiques qui correspondent aux valeurs de filtre spécifiées.

```
# Pass search filters and optional parameters when sending the
# request and capture the response
response = braket.search_quantum_tasks(filters=[{
    'name': 'deviceArn',
    'operator': 'EQUAL',
    'values': ['arn:aws:braket:::device/quantum-simulator/amazon/sv1']
}], maxResults=25)

print(f"Found {len(response['quantumTasks'])} quantum tasks")

for n in range(len(response['quantumTasks'])):
    task = response['quantumTasks'][n]
    print(f"Quantum task {task['quantumTaskArn']} for {task['deviceArn']} is {task['status']}")
```

## Annuler une tâche quantique
<a name="braket-using-boto3-example-cancel-task"></a>
+  `cancel_quantum_task(quantumTaskArn)` 

Annulez la tâche quantique spécifiée.

```
# Pass the quantum task ARN when sending the request and capture the response
response = braket.cancel_quantum_task(quantumTaskArn='arn:aws:braket:us-west-1:123456789012:quantum-task/ce78c429-cef5-45f2-88da-123456789012')

print(f"Quantum task {response['quantumTaskArn']} is {response['cancellationStatus']}")
```

# Configuration AWS CLI des profils pour Boto3 et le SDK Braket
<a name="braket-using-boto3-profiles"></a>

Le SDK Amazon Braket repose sur les informations d' AWS CLI identification par défaut, sauf indication contraire explicite de votre part. Nous vous recommandons de conserver la valeur par défaut lorsque vous exécutez sur un bloc-notes Amazon Braket géré, car vous devez fournir un rôle IAM autorisé à lancer l'instance de bloc-notes.

Facultativement, si vous exécutez votre code localement (sur une instance Amazon EC2, par exemple), vous pouvez établir des profils nommés AWS CLI . Vous pouvez attribuer à chaque profil un ensemble d'autorisations différent, plutôt que de remplacer régulièrement le profil par défaut.

Cette section explique brièvement comment configurer une telle CLI `profile` et comment intégrer ce profil dans Amazon Braket afin que les API appels soient effectués avec les autorisations de ce profil.

**Topics**
+ [Étape 1 : Configuration d'une AWS CLI locale `profile`](#braket-using-boto3-profiles-step-1)
+ [Étape 2 : établir un objet de session Boto3](#braket-using-boto3-profiles-step-2)
+ [Étape 3 : Incorporez la session Boto3 dans le Braket AwsSession](#braket-using-boto3-profiles-step-3)

## Étape 1 : Configuration d'une AWS CLI locale `profile`
<a name="braket-using-boto3-profiles-step-1"></a>

Il n'entre pas dans le cadre de ce document d'expliquer comment créer un utilisateur et comment configurer un profil autre que celui par défaut. Pour plus d'informations sur ces sujets, voir :
+  [Premiers pas](https://docs.aws.amazon.com/singlesignon/latest/userguide/getting-started.html) 
+  [Configuration du AWS CLI à utiliser AWS IAM Identity Center](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html) 

Pour utiliser Amazon Braket, vous devez fournir à cet utilisateur (et à la CLI associée`profile`) les autorisations Braket nécessaires. Par exemple, vous pouvez joindre la **AmazonBraketFullAccess**politique.

## Étape 2 : établir un objet de session Boto3
<a name="braket-using-boto3-profiles-step-2"></a>

Pour établir un objet de session Boto3, utilisez l'exemple de code suivant.

```
from boto3 import Session

# Insert CLI profile name here
boto_sess = Session(profile_name=`profile`)
```

**Note**  
Si les API appels attendus comportent des restrictions basées sur la région qui ne sont pas alignées sur votre région `profile` par défaut, vous pouvez spécifier une région pour la session Boto3 comme indiqué dans l'exemple suivant.

```
# Insert CLI profile name _and_ region
boto_sess = Session(profile_name=`profile`, region_name=`region`)
```

Pour l'argument désigné comme`region`, remplacez une valeur qui correspond à l'une des valeurs Régions AWS dans lesquelles Amazon Braket est disponible `us-east-1``us-west-1`, par exemple, etc.

## Étape 3 : Incorporez la session Boto3 dans le Braket AwsSession
<a name="braket-using-boto3-profiles-step-3"></a>

L'exemple suivant montre comment initialiser une session Boto3 Braket et instancier un appareil dans cette session.

```
from braket.aws import AwsSession, AwsDevice

# Initialize Braket session with Boto3 Session credentials
aws_session = AwsSession(boto_session=boto_sess)

# Instantiate any Braket QPU device with the previously initiated AwsSession
sim_arn = 'arn:aws:braket:::device/quantum-simulator/amazon/sv1'
device = AwsDevice(sim_arn, aws_session=aws_session)
```

Une fois cette configuration terminée, vous pouvez soumettre des tâches quantiques à cet `AwsDevice` objet instancié (en appelant la `device.run(…​)` commande par exemple). Tous les API appels effectués par cet appareil peuvent utiliser les informations d'identification IAM associées au profil CLI que vous avez précédemment désigné`profile`.