Schaltkreise konstruieren
Der Code auf dieser Seite wurde unter Berücksichtigung der folgenden Anforderungen entwickelt. Wir empfehlen die Verwendung dieser oder neuerer Versionen.
qiskit[all]~=2.5.2
Diese Seite wirft einen genaueren Blick auf die QuantumCircuit klasse im Qiskit SDK, einschließlich einiger fortgeschrittener Methoden, die Sie zur Erstellung von Quantenschaltungen verwenden können.
Was ist ein Quantenschaltkreis?
Ein einfacher Quantenschaltkreis ist eine Sammlung von Qubits und eine Liste von Anweisungen, die auf diese Qubits wirken. Zur Veranschaulichung erstellt die folgende Zelle einen neuen Schaltkreis mit zwei neuen Qubits und zeigt dann das Attribut des Schaltkreises qubits attribut der Schaltung an, das eine Liste von Qubits in der Reihenfolge vom niedrigstwertigen Bit bis zum höchstwertigen Bit .
from qiskit import QuantumCircuit
qc = QuantumCircuit(2)
qc.qubitsOutput:
[<Qubit register=(2, "q"), index=0>, <Qubit register=(2, "q"), index=1>]
Mehrere QuantumRegister und ClassicalRegister Objekte können kombiniert werden, um einen Stromkreis zu erstellen. Jede QuantumRegister und ClassicalRegister können ebenfalls benannt werden.
from qiskit.circuit import QuantumRegister, ClassicalRegister
qr1 = QuantumRegister(2, "qreg1") # Create a QuantumRegister with 2 qubits
qr2 = QuantumRegister(1, "qreg2") # Create a QuantumRegister with 1 qubit
cr1 = ClassicalRegister(3, "creg1") # Create a ClassicalRegister with 3 cbits
combined_circ = QuantumCircuit(
qr1, qr2, cr1
) # Create a quantum circuit with 2 QuantumRegisters and 1 ClassicalRegister
combined_circ.qubitsOutput:
[<Qubit register=(2, "qreg1"), index=0>,
<Qubit register=(2, "qreg1"), index=1>,
<Qubit register=(1, "qreg2"), index=0>]
Sie können den Index und das Register eines Qubits finden, indem Sie die find_bit methode und deren Attribute.
desired_qubit = qr2[0] # Qubit 0 of register 'qreg2'
print("Index:", combined_circ.find_bit(desired_qubit).index)
print("Register:", combined_circ.find_bit(desired_qubit).registers)Output:
Index: 2
Register: [(QuantumRegister(1, 'qreg2'), 0)]
Das Hinzufügen einer Anweisung zum Stromkreis fügt die Anweisung an das data attribut an. Die folgende Zellenausgabe zeigt: data ist eine Liste von CircuitInstruction objekten, von denen jedes ein Attribut operation und ein Attribut qubits hat.
qc.x(0) # Add X-gate to qubit 0
qc.dataOutput:
[CircuitInstruction(operation=Instruction(name='x', num_qubits=1, num_clbits=0, params=[]), qubits=(<Qubit register=(2, "q"), index=0>,), clbits=())]
Am einfachsten lassen sich diese Informationen über die draw Methode abrufen, die eine Visualisierung des Schaltkreises zurückgibt. Unter „Schaltkreise visualisieren“ finden Sie verschiedene Möglichkeiten zur Darstellung von Quantenschaltkreisen.
qc.draw("mpl")Output:
Schaltkreisanweisungsobjekte können "Definitionsschaltungen" enthalten, die die Anweisung in Form von grundlegenderen Anweisungen beschreiben. So ist beispielsweise das X-Gatter als ein Sonderfall des U3-gate definiert, einem allgemeineren Ein-Qubit-Gatter.
# Draw definition circuit of 0th instruction in `qc`
qc.data[0].operation.definition.draw("mpl")Output:
Anweisungen und Schaltkreise ähneln sich insofern, als sie beide Operationen mit Bits und Qubits beschreiben, aber sie haben unterschiedliche Zwecke:
- Anweisungen werden als feststehend behandelt, und ihre Methoden geben normalerweise neue Anweisungen zurück (ohne das ursprüngliche Objekt zu verändern).
- Schaltkreise sind so konzipiert, dass sie über viele Codezeilen aufgebaut werden, und
QuantumCircuitmethoden verändern oft das bestehende Objekt.
Was ist die Schaltungstiefe?
Die Tiefe() eines Quantenschaltkreises ist ein Maß für die Anzahl der "Schichten" von Quantengattern, die parallel ausgeführt werden müssen, um die durch den Schaltkreis definierte Berechnung abzuschließen. Da die Implementierung von Quantengattern Zeit in Anspruch nimmt, entspricht die Tiefe eines Schaltkreises in etwa der Zeit, die der Quantencomputer zur Ausführung des Schaltkreises benötigt. So ist die Tiefe eines Schaltkreises eine wichtige Größe, um zu messen, ob ein Quantenschaltkreis auf einem Gerät ausgeführt werden kann.
Der Rest dieser Seite zeigt, wie man Quantenschaltungen manipulieren kann.
Schaltungen bauen
Methoden wie QuantumCircuit.h und QuantumCircuit.cx fügen den Schaltkreisen spezifische Anweisungen hinzu. Um einer Schaltung allgemeinere Anweisungen hinzuzufügen, verwenden Sie die append methode. Dieser nimmt eine Anweisung und eine Liste von Qubits entgegen, auf die die Anweisung angewendet werden soll. Eine Liste der unterstützten Anweisungen finden Sie in der API-Dokumentation der Circuit Library.
from qiskit.circuit.library import HGate
qc = QuantumCircuit(1)
qc.append(
HGate(), # New HGate instruction
[0], # Apply to qubit 0
)
qc.draw("mpl")Output:
Um zwei Stromkreise zu kombinieren, verwenden Sie die compose methode. Dies akzeptiert eine weitere QuantumCircuit und eine optionale Liste von Qubit-Zuordnungen.
qc_a = QuantumCircuit(4)
qc_a.x(0)
qc_b = QuantumCircuit(2, name="qc_b")
qc_b.y(0)
qc_b.z(1)
# keep qubits (0, 1) of qc_a with same index.
# compose qubits (0,1) of qc_b to qubits (1, 3), respectively, of new composite circuit
combined = qc_a.compose(qc_b, qubits=[1, 3])
combined.draw("mpl")Output:
Sie können auch Schaltungen in Anweisungen zusammenfassen, um Ihre Schaltungen zu organisieren. Sie können eine Schaltung in eine Anweisung umwandeln, indem Sie die to_instruction methode in eine Anweisung umwandeln und diese dann wie jede andere Anweisung an eine andere Schaltung anhängen. Die in der folgenden Zelle gezeichnete Schaltung ist funktional äquivalent zu der in der vorherigen Zelle gezeichneten Schaltung.
inst = qc_b.to_instruction()
qc_a.append(inst, [1, 3])
qc_a.draw("mpl")Output:
Wenn Ihre Schaltung einheitlich ist, können Sie sie in eine Gate umwandeln, indem Sie die to_gate methode. Gate objekte sind spezielle Arten von Anweisungen, die einige zusätzliche Funktionen haben, wie z. B. die control methode, die eine Quantenkontrolle hinzufügt.
gate = qc_b.to_gate().control()
qc_a.append(gate, [0, 1, 3])
qc_a.draw("mpl")Output:
Um zu sehen, was vor sich geht, können Sie mit der decompose methode verwenden, um jede Anweisung in ihre Definition zu zerlegen.
Die Methode decompose methode gibt einen neuen Stromkreis zurück und verändert den Stromkreis, auf den sie wirkt, nicht.
qc_a.decompose().draw("mpl")Output:
Qubits messen
Messungen dienen dazu, die Zustände einzelner Qubits abzutasten und die Ergebnisse in ein klassisches Register zu übertragen. Beachten Sie, dass bei der Übermittlung von Schaltkreisen an eine Sampler -Primitive Messungen erforderlich sind. An eine Estimator -Primitive übergebene Schaltkreise dürfen jedoch keine Messwerte enthalten.
Qubits können mit drei Methoden gemessen werden: measure, measure_all und measure_active. Informationen zur Darstellung von Messergebnissen finden Sie auf der Seite „Ergebnisse anzeigen “.
-
QuantumCircuit.measurequbit: misst jedes Qubit im ersten Argument auf das klassische Bit, das als zweites Argument angegeben wird. Bei dieser Methode haben Sie die volle Kontrolle darüber, wo das Messergebnis gespeichert wird. -
QuantumCircuit.measure_all: benötigt kein Argument und kann für Quantenschaltungen ohne vordefinierte klassische Bits verwendet werden. Es erstellt klassische Drähte und speichert die Messergebnisse der Reihe nach. Zum Beispiel wird die Messung des Qubits in cbit ) gespeichert. Außerdem wird vor der Messung eine Barriere hinzugefügt. -
QuantumCircuit.measure_active: ähnlich wiemeasure_all, misst aber nur Qubits, die Operationen haben.
qc1 = QuantumCircuit(2, 2)
qc1.measure(0, 1)
qc1.draw("mpl", cregbundle=False)Output:
qc2 = QuantumCircuit(2)
qc2.measure_all()
qc2.draw("mpl", cregbundle=False)Output:
qc3 = QuantumCircuit(2)
qc3.x(1)
qc3.measure_active()
qc3.draw("mpl", cregbundle=False)Output:
Parametrisierte Schaltungen
Bei vielen Quantenalgorithmen, die in naher Zukunft entwickelt werden, werden viele Variationen einer Quantenschaltung ausgeführt. Da die Konstruktion und Optimierung großer Schaltungen rechenintensiv sein kann, unterstützt Qiskit parametrisierte Schaltungen. Diese Schaltungen haben undefinierte Parameter, deren Werte erst unmittelbar vor der Ausführung der Schaltung festgelegt werden müssen. Auf diese Weise können Sie die Schaltkreiskonstruktion und -optimierung aus der Hauptprogrammschleife herausnehmen. Mit der folgenden Zelle wird eine parametrisierte Schaltung erstellt und angezeigt.
from qiskit.transpiler import generate_preset_pass_manager
from qiskit.circuit import Parameter
angle = Parameter("angle") # undefined number
# Create and optimize circuit once
qc = QuantumCircuit(1)
qc.rx(angle, 0)
qc = generate_preset_pass_manager(
optimization_level=3, basis_gates=["u", "cx"]
).run(qc)
qc.draw("mpl")Output:
Die folgende Zelle erzeugt viele Variationen dieser Schaltung und zeigt eine der Variationen an.
circuits = []
for value in range(100):
circuits.append(qc.assign_parameters({angle: value}))
circuits[0].draw("mpl")Output:
Eine Liste der undefinierten Parameter eines Schaltkreises finden Sie in seinem Attribut parameters .
qc.parametersOutput:
ParameterView([Parameter(angle)])
Ändern Sie den Namen eines Parameters
Standardmäßig werden Parameternamen für eine parametrisierte Schaltung mit einem Präfix xversehen, beispielsweise. x[0] Sie können die Namen nach ihrer Definition ändern, wie im folgenden Beispiel gezeigt.
from qiskit.circuit.library import z_feature_map
from qiskit.circuit import ParameterVector
# Define a parameterized circuit with default names
# For example, x[0]
circuit = z_feature_map(2)
# Set new parameter names
# They will now be prefixed by `hi` instead
# For example, hi[0]
training_params = ParameterVector("hi", 2)
# Assign parameter names to the quantum circuit
circuit = circuit.assign_parameters(parameters=training_params)Nächste Schritte
- Wenn Sie mehr über Quantenalgorithmen in naher Zukunft erfahren möchten, besuchen Sie den Kurs zum Entwurf von Variationsalgorithmen.
- Ein Beispiel für die Verwendung von Schaltkreisen finden Sie im Tutorial über den Grover-Algorithmus.
- Arbeiten Sie mit einfachen Schaltungen mit IBM Quantum Composer.