Skip to main content
IBM Quantum Platform

Construire des circuits

  • Le code de cette page a été développé en tenant compte des exigences suivantes. Nous recommandons d'utiliser ces versions ou des versions plus récentes.

    qiskit[all]~=2.5.1
    

Cette page examine de plus près la classe QuantumCircuit dans le SDK Qiskit, y compris certaines méthodes plus avancées que vous pouvez utiliser pour créer des circuits quantiques.


Qu'est-ce qu'un circuit quantique?

Un circuit quantique simple est une collection de qubits et une liste d'instructions qui agissent sur ces qubits. Pour le démontrer, la cellule suivante crée un nouveau circuit avec deux nouveaux qubits, puis affiche l'attribut qubits du circuit, qui est une liste de Qubits dans l'ordre du bit le moins significatif q0q_0 au bit le plus significatif qnq_n.

from qiskit import QuantumCircuit

qc = QuantumCircuit(2)
qc.qubits

Output:

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

Plusieurs objets QuantumRegister et ClassicalRegister peuvent être combinés pour créer un circuit. Chaque QuantumRegister et ClassicalRegister peuvent également être nommés.

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

Output:

[<Qubit register=(2, "qreg1"), index=0>,
 <Qubit register=(2, "qreg1"), index=1>,
 <Qubit register=(1, "qreg2"), index=0>]

Vous pouvez trouver l'index et le registre d'un qubit en utilisant la méthode et les attributs du circuit find_bit du circuit et de ses attributs.

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)]

L'ajout d'une instruction au circuit ajoute l'instruction à l'attribut du circuit data du circuit. La sortie de cellule suivante montre que data est une liste d'objets qui ont chacun un attribut et un attribut CircuitInstruction objets, dont chacun possède un attribut operation et un attribut qubits .

qc.x(0)  # Add X-gate to qubit 0
qc.data

Output:

[CircuitInstruction(operation=Instruction(name='x', num_qubits=1, num_clbits=0, params=[]), qubits=(<Qubit register=(2, "q"), index=0>,), clbits=())]

La manière la plus simple de consulter ces informations consiste à utiliser la draw méthode, qui renvoie une représentation graphique du circuit. Consultez la section « Visualisation des circuits » pour découvrir différentes façons de représenter les circuits quantiques.

qc.draw("mpl")

Output:

Output of the previous code cell

Les objets d'instruction de circuit peuvent contenir des circuits de "définition" qui décrivent l'instruction en termes d'instructions plus fondamentales. Par exemple, la porte X est définie comme un cas spécifique de la U3-gate, une porte à qubit unique plus générale.

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

Output:

Output of the previous code cell

Les instructions et les circuits sont similaires en ce sens qu'ils décrivent tous deux des opérations sur des bits et des qubits, mais ils ont des objectifs différents :

  • Les instructions sont considérées comme fixes et leurs méthodes renvoient généralement de nouvelles instructions (sans modifier l'objet d'origine).
  • Les circuits sont conçus pour être construits sur plusieurs lignes de code, et les méthodes mutent souvent l'objet existant QuantumCircuit mutent souvent l'objet existant.

Qu'est-ce que la profondeur de circuit?

La profondeur() d'un circuit quantique est une mesure du nombre de "couches" de portes quantiques, exécutées en parallèle, nécessaires pour effectuer le calcul défini par le circuit. Comme la mise en œuvre des portes quantiques prend du temps, la profondeur d'un circuit correspond approximativement au temps qu'il faut à l'ordinateur quantique pour exécuter le circuit. Ainsi, la profondeur d'un circuit est une quantité importante utilisée pour mesurer si un circuit quantique peut être exécuté sur un appareil.

Le reste de cette page illustre comment manipuler les circuits quantiques.


Construire des circuits

Des méthodes telles que QuantumCircuit.h et QuantumCircuit.cx ajoutent des instructions spécifiques aux circuits. Pour ajouter des instructions à un circuit de manière plus générale, utilisez la méthode append méthode. Elle prend une instruction et une liste de qubits auxquels appliquer l'instruction. Voir la documentation de l'API de la bibliothèque de circuits pour une liste des instructions prises en charge.

from qiskit.circuit.library import HGate

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

Output:

Output of the previous code cell

Pour combiner deux circuits, utilisez la méthode compose méthode. Il accepte un autre QuantumCircuit et une liste optionnelle de mappages de qubits.

Note

La méthode compose renvoie un nouveau circuit et ne modifie aucun des circuits sur lesquels elle agit. Pour muter le circuit sur lequel vous appelez la méthode compose utilisez l'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:

Output of the previous code cell

Vous pouvez également compiler les circuits en instructions afin de les organiser. Vous pouvez convertir un circuit en instruction en utilisant la méthode to_instruction puis l'ajouter à un autre circuit comme n'importe quelle autre instruction. Le circuit dessiné dans la cellule suivante est fonctionnellement équivalent au circuit dessiné dans la cellule précédente.

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

Output:

Output of the previous code cell

Si votre circuit est unitaire, vous pouvez le convertir en un circuit Gate en utilisant la méthode to_gate méthode. Gate les objets sont des types d'instructions spécifiques qui présentent des caractéristiques supplémentaires, telles que la méthode, qui ajoute un contrôle quantique control qui ajoute un contrôle quantique.

gate = qc_b.to_gate().control()
qc_a.append(gate, [0, 1, 3])
qc_a.draw("mpl")

Output:

Output of the previous code cell

Pour voir ce qui se passe, vous pouvez utiliser la méthode decompose pour développer chaque instruction dans sa définition.

Note

Le decompose la méthode renvoie un nouveau circuit et ne modifie pas le circuit sur lequel elle agit.

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

Output:

Output of the previous code cell

Mesurer les qubits

Les mesures permettent de déterminer l'état de chaque qubit et de transférer les résultats vers un registre classique. Notez que si vous soumettez des circuits à une primitive Sampler, des mesures sont obligatoires. Cependant, les circuits transmis à une primitive Estimator ne doivent pas contenir de mesures.

Il existe trois méthodes pour mesurer les qubits : measure, measure_all et measure_active. Pour savoir comment visualiser les résultats mesurés, consultez la page « Visualiser les résultats ».

  1. QuantumCircuit.measure : mesure chaque qubit du premier argument sur le bit classique donné en second argument. Cette méthode permet de contrôler entièrement l'endroit où le résultat de la mesure est stocké.

  2. QuantumCircuit.measure_all : ne prend aucun argument et peut être utilisé pour les circuits quantiques sans bits classiques prédéfinis. Il crée des fils classiques et stocke les résultats des mesures dans l'ordre. Par exemple, la mesure du qubit qiq_i est stockée dans le cbit measimeas_i ). Il ajoute également une barrière avant la mesure.

  3. QuantumCircuit.measure_active : similaire à measure_all, mais ne mesure que les qubits qui ont des opérations.

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

Output:

Output of the previous code cell
qc2 = QuantumCircuit(2)
qc2.measure_all()
qc2.draw("mpl", cregbundle=False)

Output:

Output of the previous code cell
qc3 = QuantumCircuit(2)
qc3.x(1)
qc3.measure_active()
qc3.draw("mpl", cregbundle=False)

Output:

Output of the previous code cell

Circuits paramétrés

De nombreux algorithmes quantiques à court terme impliquent l'exécution de nombreuses variations d'un circuit quantique. Étant donné que la construction et l'optimisation de grands circuits peuvent être coûteuses en termes de calcul, Qiskit prend en charge les circuits paramétrés. Ces circuits ont des paramètres non définis et leurs valeurs ne doivent être définies que juste avant l'exécution du circuit. Cela vous permet de sortir la construction et l'optimisation du circuit de la boucle principale du programme. La cellule suivante crée et affiche un circuit paramétré.

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:

Output of the previous code cell

La cellule suivante crée plusieurs variantes de ce circuit et affiche l'une d'entre elles.

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

circuits[0].draw("mpl")

Output:

Output of the previous code cell

Vous trouverez la liste des paramètres non définis d'un circuit dans son attribut parameters .

qc.parameters

Output:

ParameterView([Parameter(angle)])

Modifier le nom d'un paramètre

Par défaut, les noms des paramètres d'un circuit paramétré sont préfixés par xun signe -, par exemple x[0]. Vous pouvez modifier les noms après les avoir définis, comme illustré dans l'exemple suivant.

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)

Etapes suivantes

Recommandations
Cette page a-t-elle été utile ?
Signaler un bogue, une coquille ou proposer du contenu sur GitHub.