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.
Construire des circuits dans le SDK
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 manuellement qubits, demandez au compilateur d'exécuter vos circuits exactement tels que définis et créez 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 certainsQPUs. Pour plus d'informations, consultez Pulse Control sur Amazon Braket.
Dans cette section :
Portails et circuits
Les portes et circuits quantiques sont définis dans la braket.circuits
Circuit()
Exemple : définition d'un circuit
L'exemple commence par définir un circuit d'échantillonnage de quatre qubits (étiquetéq0
, q1
q2
, etq3
) composé de portes Hadamard standard à un qubit et de portes à deux qubits. CNOT 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-C--- | q1 : -H-|-C- | | 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)
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 Support.
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', 'GPi', 'GPi2', 'H', 'I', 'ISwap', 'MS', 'PSwap', 'PhaseShift', 'PulseGate', 'Rx', 'Ry', 'Rz', 'S', 'Si', 'Swap', 'T', 'Ti', '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, vous appelleriezcirc.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 au qubits défini par le targets
paramètre.
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]) new_instr = instr.copy(target_mapping={0: 5})
Exemple : Afficher les barrières prises en charge par chaque appareil
Les simulateurs prennent en charge toutes les portes du BraketSDK, mais les QPU appareils en prennent en charge un sous-ensemble plus restreint. Vous trouverez 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 the Aria-1 device: ['x', 'y', 'z', 'rx', 'ry', 'rz', 'h', 'cnot', 's', 'si', 't', 'ti', 'v', 'vi', 'xx', 'yy', 'zz', 'swap']
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 les deux qubit fidélité entre deux portes d'unQPU.
# import the device module from braket.aws import AwsDevice device = AwsDevice("arn:aws:braket:us-west-1::device/qpu/rigetti/Ankaa-2") #specify the qubits a=10 b=11 print(f"Fidelity of the ISWAP gate between qubits {a} and {b}: ", device.properties.provider.specs["2Q"][f"{a}-{b}"]["fISWAP"])
Mesure partielle
En suivant les exemples précédents, nous avons mesuré tous les qubits du circuit quantique. Cependant, il est possible de mesurer des qubits individuels ou un sous-ensemble de qubits.
Exemple : mesurer un sous-ensemble de qubits
Dans cet exemple, nous démontrons une mesure partielle en ajoutant une measure
instruction avec les qubits cibles à la fin du 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)
Manuelle qubit allocation
Lorsque vous exécutez un circuit quantique sur des ordinateurs quantiques à partir de Rigetti, vous pouvez éventuellement utiliser le manuel qubit allocation pour contrôler laquelle qubits sont utilisés pour votre algorithme. La console Amazon Braket
Manuelle qubit l'allocation vous permet d'exécuter des circuits avec une plus grande précision et d'étudier des circuits individuels qubit propriétés. 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 qubits explicitement.
circ = Circuit().h(0).cnot(0, 7) # Indices of actual qubits in the QPU 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
Compilation textuelle
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 (soutenu par Rigetti uniquement). 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 que vous utilisez 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 actuellement prise en charge sur le Rigetti, IonQ, et IQM appareils 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 appelées lorsqu'elles sont connectées qubits et que le circuit utilise les portes natives supportées 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
Dans Rigetti, qubit le recâblage doit être désactivé en configurant disableQubitRewiring=True
pour être utilisé 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 circuit 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-2") 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 des QPU appareils Braket, des instances d'ordinateurs portables et des 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 Braket
Note
Si vous utilisez Open QASM pour écrire vos circuits pour le IonQ appareil, et si vous souhaitez mapper votre circuit directement aux qubits physiques, vous devez utiliser le #pragma braket verbatim
car le disableQubitRewiring
drapeau est complètement ignoré par OpenQASM.
Simulation du bruit
Pour instancier le simulateur de bruit local, vous pouvez modifier le backend comme suit.
device = LocalSimulator(backend="braket_dm")
Vous pouvez créer des circuits bruyants de deux manières :
-
Construisez le circuit bruyant de bas en haut.
-
Prenez un circuit sans bruit existant et injectez du bruit partout.
L'exemple suivant montre les approches utilisant un circuit simple avec un bruit dépolarisant et un canal Kraus personnalisé.
# 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)
# 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, s3_location)
Ou
Exemple 2
task = device.run(circ_noise, s3_location)
Pour plus d'exemples, consultez l'exemple d'introduction du simulateur de bruit Braket