Zum Hauptinhalt springen

Schaltkreise erstellen

Paketversionen

Der Code auf dieser Seite wurde mit den folgenden Anforderungen entwickelt. Wir empfehlen, diese oder neuere Versionen zu verwenden.

qiskit[all]~=2.3.0

Diese Seite wirft einen genaueren Blick auf die QuantumCircuit Klasse im Qiskit SDK, einschließlich einiger fortgeschrittener Methoden, die du zum Erstellen von Quantenschaltkreisen verwenden kannst.

Was ist ein Quantenschaltkreis?

Ein einfacher Quantenschaltkreis ist eine Sammlung von Qubits und eine Liste von Instruktionen, die auf diese Qubits wirken. Zur Demonstration erstellt die folgende Zelle einen neuen Schaltkreis mit zwei neuen Qubits und zeigt dann das qubits Attribut des Schaltkreises an, welches eine Liste von Qubits in Reihenfolge vom niederwertigsten Bit q0q_0 bis zum höchstwertigen Bit qnq_n ist.

# Added by doQumentation — required packages for this notebook
!pip install -q qiskit
from qiskit import QuantumCircuit

qc = QuantumCircuit(2)
qc.qubits
[<Qubit register=(2, "q"), index=0>, <Qubit register=(2, "q"), index=1>]

Mehrere QuantumRegister und ClassicalRegister Objekte können kombiniert werden, um einen Schaltkreis zu erstellen. Jedes QuantumRegister und ClassicalRegister kann auch 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.qubits
[<Qubit register=(2, "qreg1"), index=0>,
<Qubit register=(2, "qreg1"), index=1>,
<Qubit register=(1, "qreg2"), index=0>]

Du kannst den Index und das Register eines Qubits finden, indem du die find_bit Methode des Schaltkreises und deren Attribute verwendest.

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)
Index: 2
Register: [(QuantumRegister(1, 'qreg2'), 0)]

Das Hinzufügen einer Instruktion zum Schaltkreis hängt die Instruktion an das data Attribut des Schaltkreises an. Die folgende Zellenausgabe zeigt, dass data eine Liste von CircuitInstruction Objekten ist, von denen jedes ein operation Attribut und ein qubits Attribut hat.

qc.x(0)  # Add X-gate to qubit 0
qc.data
[CircuitInstruction(operation=Instruction(name='x', num_qubits=1, num_clbits=0, params=[]), qubits=(<Qubit register=(2, "q"), index=0>,), clbits=())]

Der einfachste Weg, diese Information zu betrachten, ist über die draw Methode, die eine Visualisierung eines Schaltkreises zurückgibt. Siehe Schaltkreise visualisieren für verschiedene Möglichkeiten zur Darstellung von Quantenschaltkreisen.

qc.draw("mpl")

Output of the previous code cell

Schaltkreis-Instruktionsobjekte können "Definitions"-Schaltkreise enthalten, die die Instruktion in Bezug auf fundamentalere Instruktionen beschreiben. Beispielsweise ist das X-Gate als ein spezieller Fall des U3-Gates definiert, einem allgemeineren Single-Qubit-Gate.

# Draw definition circuit of 0th instruction in `qc`
qc.data[0].operation.definition.draw("mpl")

Output of the previous code cell

Instruktionen und Schaltkreise sind insofern ähnlich, als dass beide Operationen auf Bits und Qubits beschreiben, aber sie haben unterschiedliche Zwecke:

  • Instruktionen werden als fest behandelt, und ihre Methoden geben normalerweise neue Instruktionen zurück (ohne das ursprüngliche Objekt zu verändern).
  • Schaltkreise sind so konzipiert, dass sie über viele Codezeilen hinweg aufgebaut werden, und QuantumCircuit Methoden verändern oft das bestehende Objekt.

Was ist die Schaltkreistiefe?

Die depth() eines Quantenschaltkreises ist ein Maß für die Anzahl der "Schichten" von Quantengattern, die parallel ausgeführt werden, um die durch den Schaltkreis definierte Berechnung abzuschließen. Da Quantengatter Zeit zur Implementierung benötigen, entspricht die Tiefe eines Schaltkreises ungefähr der Zeit, die der Quantencomputer zur Ausführung des Schaltkreises benötigt. Daher ist die Tiefe eines Schaltkreises eine wichtige Größe, die verwendet wird, um zu messen, ob ein Quantenschaltkreis auf einem Gerät ausgeführt werden kann.

Der Rest dieser Seite veranschaulicht, wie Quantenschaltkreise manipuliert werden können.

Schaltkreise erstellen

Methoden wie QuantumCircuit.h und QuantumCircuit.cx fügen spezifische Instruktionen zu Schaltkreisen hinzu. Um Instruktionen allgemeiner zu einem Schaltkreis hinzuzufügen, verwende die append Methode. Diese nimmt eine Instruktion und eine Liste von Qubits, auf die die Instruktion angewendet werden soll. Siehe die Circuit Library API Dokumentation für eine Liste unterstützter Instruktionen.

from qiskit.circuit.library import HGate

qc = QuantumCircuit(1)
qc.append(
HGate(), # New HGate instruction
[0], # Apply to qubit 0
)
qc.draw("mpl")

Output of the previous code cell

Um zwei Schaltkreise zu kombinieren, verwende die compose Methode. Diese akzeptiert einen anderen QuantumCircuit und eine optionale Liste von Qubit-Zuordnungen.

hinweis

Die compose Methode gibt einen neuen Schaltkreis zurück und verändert nicht einen der beiden Schaltkreise, auf die sie wirkt. Um den Schaltkreis zu verändern, auf dem du die compose Methode aufrufst, verwende das Argument inplace=True.

qc_a = QuantumCircuit(4)
qc_a.x(0)

qc_b = QuantumCircuit(2, name="qc_b")
qc_b.y(0)
qc_b.z(1)

# compose qubits (0, 1) of qc_a to qubits (1, 3) of qc_b respectively
combined = qc_a.compose(qc_b, qubits=[1, 3])
combined.draw("mpl")

Output of the previous code cell

Du möchtest vielleicht auch Schaltkreise in Instruktionen kompilieren, um deine Schaltkreise organisiert zu halten. Du kannst einen Schaltkreis mit der to_instruction Methode in eine Instruktion konvertieren und diese dann wie jede andere Instruktion an einen anderen Schaltkreis anhängen. Der in der folgenden Zelle gezeichnete Schaltkreis ist funktionell äquivalent zu dem in der vorherigen Zelle gezeichneten Schaltkreis.

inst = qc_b.to_instruction()
qc_a.append(inst, [1, 3])
qc_a.draw("mpl")

Output of the previous code cell

Falls dein Schaltkreis unitär ist, kannst du ihn mit der to_gate Methode in ein Gate konvertieren. Gate Objekte sind spezielle Arten von Instruktionen, 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 of the previous code cell

Um zu sehen, was vor sich geht, kannst du die decompose Methode verwenden, um jede Instruktion in ihre Definition zu erweitern.

hinweis

Die decompose Methode gibt einen neuen Schaltkreis zurück und verändert nicht den Schaltkreis, auf den sie wirkt.

qc_a.decompose().draw("mpl")

Output of the previous code cell

Qubits messen

Messungen werden verwendet, um die Zustände einzelner Qubits zu sampeln und die Ergebnisse in ein klassisches Register zu übertragen. Beachte, dass, wenn du Schaltkreise an ein Sampler Primitive übermittelst, Messungen erforderlich sind. Schaltkreise, die an ein Estimator Primitive übermittelt werden, dürfen jedoch keine Messungen enthalten.

Qubits können mit drei Methoden gemessen werden: measure, measure_all und measure_active. Um zu erfahren, wie gemessene Ergebnisse visualisiert werden können, siehe die Seite Ergebnisse visualisieren.

  1. QuantumCircuit.measure: misst jedes Qubit im ersten Argument auf das klassische Bit, das als zweites Argument angegeben ist. Diese Methode ermöglicht volle Kontrolle darüber, wo das Messergebnis gespeichert wird.

  2. QuantumCircuit.measure_all: nimmt kein Argument und kann für Quantenschaltkreise ohne vordefinierte klassische Bits verwendet werden. Sie erstellt klassische Drähte und speichert Messergebnisse in Reihenfolge. Zum Beispiel wird die Messung von Qubit qiq_i in cbit measimeas_i gespeichert. Sie fügt auch eine Barriere vor der Messung hinzu.

  3. QuantumCircuit.measure_active: ähnlich wie measure_all, misst aber nur Qubits, die Operationen haben.

qc1 = QuantumCircuit(2, 2)
qc1.measure(0, 1)
qc1.draw("mpl", cregbundle=False)

Output of the previous code cell

qc2 = QuantumCircuit(2)
qc2.measure_all()
qc2.draw("mpl", cregbundle=False)

Output of the previous code cell

qc3 = QuantumCircuit(2)
qc3.x(1)
qc3.measure_active()
qc3.draw("mpl", cregbundle=False)

Output of the previous code cell

Parametrisierte Schaltkreise

Viele kurzfristige Quantenalgorithmen beinhalten die Ausführung vieler Variationen eines Quantenschaltkreises. Da das Konstruieren und Optimieren großer Schaltkreise rechenintensiv sein kann, unterstützt Qiskit parametrisierte Schaltkreise. Diese Schaltkreise haben undefinierte Parameter, und ihre Werte müssen erst kurz vor der Ausführung des Schaltkreises definiert werden. Dies ermöglicht es dir, die Schaltkreiskonstruktion und -optimierung aus der Hauptprogrammschleife zu verschieben. Die folgende Zelle erstellt und zeigt einen parametrisierten Schaltkreis an.

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 of the previous code cell

Die folgende Zelle erstellt viele Variationen dieses Schaltkreises und zeigt eine der Variationen an.

circuits = []
for value in range(100):
circuits.append(qc.assign_parameters({angle: value}))

circuits[0].draw("mpl")

Output of the previous code cell

Du kannst eine Liste der undefinierten Parameter eines Schaltkreises in seinem parameters Attribut finden.

qc.parameters
ParameterView([Parameter(angle)])

Namen eines Parameters ändern

Standardmäßig werden Parameternamen für einen parametrisierten Schaltkreis mit x präfixiert - zum Beispiel x[0]. Du kannst die Namen ändern, nachdem sie definiert wurden, 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)
Methodennamen vergessen? Frag den Qiskit Code Assistant.

Nächste Schritte

Empfehlungen