Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.
Dieser Abschnitt enthält Beispiele für das Definieren eines Schaltkreises, das Anzeigen verfügbarer Gatter, das Erweitern eines Schaltkreises und das Anzeigen von Gates, die jedes Gerät unterstützt. Er enthält auch Anweisungen zur manuellen Zuweisung qubits, weisen Sie den Compiler an, Ihre Schaltungen genau wie definiert auszuführen, und erstellen Sie mit einem Geräuschsimulator verrauschte Schaltungen.
Mit bestimmten Werten können Sie in Braket auch auf Pulsebene für verschiedene Gatter arbeiten. QPUs Weitere Informationen finden Sie unter Pulse Control auf Amazon Braket.
In diesem Abschnitt:
Tore und Stromkreise
Quantengatter und -schaltungen sind in der braket.circuits
Circuit()
Beispiel: Definieren Sie einen Schaltkreis
Das Beispiel beginnt mit der Definition eines Beispielkreislaufs aus vier qubits (beschriftet mitq0
, q1
q2
, undq3
) bestehend aus standardmäßigen Single-Qubit-Hadamard-Gattern und Zwei-Qubit-CNOT-Gattern. Sie können diesen Schaltkreis visualisieren, indem Sie die Funktion aufrufen, wie das folgende Beispiel zeigt. print
# 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 |
Beispiel: Definieren Sie einen parametrisierten Schaltkreis
In diesem Beispiel definieren wir einen Schaltkreis mit Gattern, die von freien Parametern abhängen. Wir können die Werte dieser Parameter angeben, um eine neue Schaltung zu erstellen oder, wenn wir die Schaltung einreichen, sie als Quantenaufgabe auf bestimmten Geräten laufen zu lassen.
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)
Sie können aus einem parametrisierten Schaltkreis einen neuen, nicht parametrisierten Schaltkreis erstellen, indem Sie entweder einzelne Argumente float
(das ist der Wert, den alle freien Parameter annehmen) oder Schlüsselwortargumente angeben, die den Wert jedes Parameters für den Schaltkreis wie folgt angeben.
my_fixed_circuit = my_circuit(1.2)
my_fixed_circuit = my_circuit(alpha=1.2)
Beachten Sie, dass er unverändert my_circuit
ist, sodass Sie ihn verwenden können, um viele neue Schaltungen mit festen Parameterwerten zu instanziieren.
Beispiel: Ändern Sie Gates in einem Schaltkreis
Das folgende Beispiel definiert einen Schaltkreis mit Gattern, die Steuerungs- und Leistungsmodifikatoren verwenden. Sie können diese Änderungen verwenden, um neue Tore zu erstellen, z. B. das gesteuerte Ry
Tor.
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)
Tormodifikatoren werden nur auf dem lokalen Simulator unterstützt.
Beispiel: Alle verfügbaren Gates anzeigen
Das folgende Beispiel zeigt, wie Sie sich alle verfügbaren Gates in ansehen Amazon Klammer.
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)
Die Ausgabe dieses Codes listet alle Gates auf.
['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']
Jedes dieser Gatter kann an einen Schaltkreis angehängt werden, indem die Methode für diesen Schaltungstyp aufgerufen wird. Sie würden zum Beispiel aufrufencirc.h(0)
, um dem ersten ein Hadamard-Gate hinzuzufügen qubit.
Anmerkung
Gatter werden an der richtigen Stelle angefügt, und im folgenden Beispiel werden alle im vorherigen Beispiel aufgelisteten Gatter zu demselben Schaltkreis hinzugefügt.
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)
Neben dem vordefinierten Gattersatz können Sie dem Schaltkreis auch selbstdefinierte einheitliche Gatter zuweisen. Dabei kann es sich um Single-Qubit-Gates (wie im folgenden Quellcode gezeigt) oder um Multi-Qubit-Gates handeln, die auf die qubits durch den Parameter definiert. targets
import numpy as np
# apply a general unitary
my_unitary = np.array([[0, 1],[1, 0]])
circ.unitary(matrix=my_unitary, targets=[0])
Beispiel: Erweitern Sie bestehende Schaltungen
Sie können bestehende Schaltkreise erweitern, indem Sie Anweisungen hinzufügen. An Instruction
ist eine Quantenrichtlinie, die die Quantenaufgabe beschreibt, die auf einem Quantengerät ausgeführt werden muss. Instruction
Operatoren schließen Gate
nur Objekte des Typs ein.
# 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})
Beispiel: Sehen Sie sich die Gates an, die jedes Gerät unterstützt
Simulatoren unterstützen alle Gates im Braket-SDK, aber QPU-Geräte unterstützen eine kleinere Teilmenge. Sie finden die unterstützten Gates eines Geräts in den Geräteeigenschaften. Das Folgende zeigt ein Beispiel mit einem IonQ-Gerät:
# 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']
Unterstützte Gates müssen möglicherweise zu systemeigenen Gates kompiliert werden, bevor sie auf Quantenhardware laufen können. Wenn Sie eine Schaltung einreichen, Amazon Braket führt diese Kompilierung automatisch durch.
Beispiel: Rufen Sie programmgesteuert die Genauigkeit von systemeigenen Gates ab, die von einem Gerät unterstützt werden
Sie können die Genauigkeitsinformationen auf der Geräteseite der Braket-Konsole einsehen. Manchmal ist es hilfreich, programmgesteuert auf dieselben Informationen zuzugreifen. Der folgende Code zeigt, wie die beiden extrahiert werden qubit Gate-Treue zwischen zwei Gates einer 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}")
Teilweise Messung
In Anlehnung an die vorherigen Beispiele haben wir alle Qubits im Quantenkreis gemessen. Es ist jedoch möglich, einzelne Qubits oder eine Teilmenge von Qubits zu messen.
Beispiel: Messen Sie eine Teilmenge von Qubits
In diesem Beispiel demonstrieren wir eine Teilmessung, indem wir am Ende der measure
Schaltung eine Anweisung mit den Ziel-Qubits hinzufügen.
# 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)
Manuell qubit Zuweisung
Wenn Sie eine Quantenschaltung auf Quantencomputern von ausführen Rigetti, können Sie optional manuell verwenden qubit Zuordnung, um welche zu kontrollieren qubits werden für Ihren Algorithmus verwendet. Die Amazon Braket-Konsole
Manuell qubit Die Zuordnung ermöglicht es Ihnen, Schaltungen mit größerer Genauigkeit auszuführen und einzelne zu untersuchen qubit Eigenschaften. Forscher und fortgeschrittene Anwender optimieren ihr Schaltungsdesign auf der Grundlage der neuesten Gerätekalibrierungsdaten und können genauere Ergebnisse erzielen.
Das folgende Beispiel zeigt, wie die Zuordnung erfolgt qubits explizit.
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)
Weitere Informationen finden Sie in den Amazon Braket-Beispielen auf GitHub
Wörtliche Zusammenstellung
Wenn Sie eine Quantenschaltung auf Gate-basierten Quantencomputern ausführen, können Sie den Compiler anweisen, Ihre Schaltungen ohne Änderungen exakt so auszuführen, wie sie definiert sind. Mithilfe der wörtlichen Kompilierung können Sie entweder festlegen, dass ein ganzer Schaltkreis exakt wie spezifiziert erhalten bleibt oder dass nur bestimmte Teile davon erhalten bleiben (unterstützt von Rigetti nur). Bei der Entwicklung von Algorithmen für Hardware-Benchmarking- oder Fehlerminimierungsprotokolle müssen Sie die Möglichkeit haben, die Gates und Schaltungslayouts, die Sie auf der Hardware ausführen, genau zu spezifizieren. Die wörtliche Kompilierung gibt Ihnen direkte Kontrolle über den Kompilierungsprozess, indem Sie bestimmte Optimierungsschritte ausschalten und so sicherstellen, dass Ihre Schaltungen genau so laufen, wie sie entworfen wurden.
Die verbatim-Kompilierung wird derzeit unterstützt auf Rigetti, IonQ, und IQM Geräte und erfordert die Verwendung nativer Gates. Bei der wörtlichen Kompilierung ist es ratsam, die Topologie des Geräts zu überprüfen, um sicherzustellen, dass die Gates aufgerufen werden und verbunden sind qubits und dass die Schaltung die systemeigenen Gates verwendet, die von der Hardware unterstützt werden. Das folgende Beispiel zeigt, wie Sie programmgesteuert auf die Liste der systemeigenen Gates zugreifen können, die von einem Gerät unterstützt werden.
device.properties.paradigm.nativeGateSet
Wählen Sie in der &Snowconsole; Ihren Auftrag aus der Tabelle. Rigetti, qubit Die Neuverkabelung muss durch die Einstellung disableQubitRewiring=True
für die Verwendung mit wörtlicher Kompilierung ausgeschaltet werden. Wenn diese disableQubitRewiring=False
Option gesetzt ist, wenn in einer Kompilierung wörtliche Boxen verwendet werden, schlägt der Quantenschaltkreis bei der Validierung fehl und kann nicht ausgeführt werden.
Wenn die wörtliche Kompilierung für eine Schaltung aktiviert ist und auf einer QPU ausgeführt wird, die sie nicht unterstützt, wird ein Fehler generiert, der darauf hinweist, dass ein nicht unterstützter Vorgang zum Fehlschlagen der Aufgabe geführt hat. Da immer mehr Quantenhardware Compilerfunktionen nativ unterstützt, wird diese Funktion um diese Geräte erweitert. Geräte, die die wörtliche Kompilierung unterstützen, schließen sie als unterstützten Vorgang ein, wenn sie mit dem folgenden Code abgefragt werden.
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
Mit der verbatim-Kompilierung sind keine zusätzlichen Kosten verbunden. Ihnen werden weiterhin Quantenaufgaben, die auf Braket QPU-Geräten, Notebook-Instances und On-Demand-Simulatoren ausgeführt werden, auf der Grundlage der aktuellen Tarife berechnet, die auf der Seite mit den Amazon Braket-Preisen
Anmerkung
Wenn Sie OpenQASM verwenden, um Ihre Schaltungen für das zu schreiben IonQ Gerät, und Sie möchten Ihre Schaltung direkt den physikalischen Qubits zuordnen, müssen Sie das verwenden, #pragma braket verbatim
da das disableQubitRewiring
Flag von OpenQASM komplett ignoriert wird.
Simulation von Geräuschen
Um den lokalen Geräuschsimulator zu instanziieren, können Sie das Backend wie folgt ändern.
device = LocalSimulator(backend="braket_dm")
Sie können geräuschbehaftete Schaltungen auf zwei Arten aufbauen:
-
Baue den lauten Stromkreis von unten nach oben auf.
-
Nehmen Sie einen vorhandenen, rauschfreien Stromkreis und fügen Sie überall Rauschen ein.
Das folgende Beispiel zeigt die Ansätze, bei denen eine einfache Schaltung mit depolarisierendem Rauschen und ein benutzerdefinierter Kraus-Kanal verwendet werden.
# 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)
Das Ausführen einer Schaltung bietet dieselbe Benutzererfahrung wie zuvor, wie in den folgenden beiden Beispielen gezeigt.
Beispiel 1
task = device.run(circ, s3_location)
Oder
Beispiel 2
task = device.run(circ_noise, s3_location)
Weitere Beispiele finden Sie im einführenden Beispiel für einen Geräuschsimulator in Braket