Vai al contenuto principale

Costruire circuiti

Versioni dei pacchetti

Il codice in questa pagina è stato sviluppato utilizzando i seguenti requisiti. Raccomandiamo di usare queste versioni o versioni più recenti.

qiskit[all]~=2.3.0

Questa pagina approfondisce la classe QuantumCircuit nell'SDK di Qiskit, inclusi alcuni metodi più avanzati che puoi usare per creare circuiti quantistici.

Che cos'è un circuito quantistico?​

Un semplice circuito quantistico è un insieme di qubit e un elenco di istruzioni che agiscono su quei qubit. Per illustrarlo, la cella seguente crea un nuovo circuito con due nuovi qubit, quindi visualizza l'attributo qubits del circuito, che è un elenco di Qubit in ordine dal bit meno significativo q0q_0 al bit più significativo qnq_n.

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

È possibile combinare più oggetti QuantumRegister e ClassicalRegister per creare un circuito. Ogni QuantumRegister e ClassicalRegister può anche essere denominato.

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

Puoi trovare l'indice e il registro di un qubit usando il metodo find_bit del circuito e i suoi attributi.

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

Aggiungere un'istruzione al circuito fa sì che l'istruzione venga accodata all'attributo data del circuito. L'output della cella seguente mostra che data è un elenco di oggetti CircuitInstruction, ognuno dei quali ha un attributo operation e un attributo qubits.

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

Il modo più semplice per visualizzare queste informazioni è tramite il metodo draw, che restituisce una rappresentazione grafica di un circuito. Consulta la pagina Visualizzare i circuiti per i diversi modi di visualizzare i circuiti quantistici.

qc.draw("mpl")

Output della cella di codice precedente

Gli oggetti istruzione del circuito possono contenere circuiti di "definizione" che descrivono l'istruzione in termini di istruzioni più fondamentali. Ad esempio, la X-gate è definita come un caso particolare della U3-gate, un gate a singolo qubit più generale.

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

Output della cella di codice precedente

Istruzioni e circuiti si somigliano nel senso che entrambi descrivono operazioni su bit e qubit, ma hanno scopi diversi:

  • Le istruzioni sono trattate come fisse, e i loro metodi di solito restituiscono nuove istruzioni (senza mutare l'oggetto originale).
  • I circuiti sono progettati per essere costruiti in molte righe di codice, e i metodi di QuantumCircuit spesso mutano l'oggetto esistente.

Che cos'è la profondità di un circuito?​

La profondità (depth()) di un circuito quantistico è una misura del numero di "strati" di gate quantistici, eseguiti in parallelo, necessari per completare il calcolo definito dal circuito. Poiché i gate quantistici richiedono tempo per essere implementati, la profondità di un circuito corrisponde approssimativamente al tempo che impiega il computer quantistico per eseguirlo. La profondità è quindi una delle quantità importanti usate per valutare se un circuito quantistico può essere eseguito su un dispositivo.

Il resto di questa pagina illustra come manipolare i circuiti quantistici.

Costruire circuiti​

Metodi come QuantumCircuit.h e QuantumCircuit.cx aggiungono istruzioni specifiche ai circuiti. Per aggiungere istruzioni a un circuito in modo più generale, usa il metodo append. Questo metodo accetta un'istruzione e un elenco di qubit a cui applicarla. Consulta la documentazione API della Circuit Library per un elenco delle istruzioni supportate.

from qiskit.circuit.library import HGate

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

Output della cella di codice precedente

Per combinare due circuiti, usa il metodo compose. Questo accetta un altro QuantumCircuit e un elenco opzionale di mappature di qubit.

nota

Il metodo compose restituisce un nuovo circuito e non muta nessuno dei circuiti su cui agisce. Per mutare il circuito su cui stai chiamando compose, usa l'argomento 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 della cella di codice precedente

Potresti anche voler compilare i circuiti in istruzioni per mantenere i tuoi circuiti organizzati. Puoi convertire un circuito in un'istruzione usando il metodo to_instruction, quindi aggiungerla a un altro circuito come faresti con qualsiasi altra istruzione. Il circuito disegnato nella cella seguente è funzionalmente equivalente al circuito disegnato nella cella precedente.

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

Output della cella di codice precedente

Se il tuo circuito è unitario, puoi convertirlo in un Gate usando il metodo to_gate. Gli oggetti Gate sono tipi specifici di istruzioni che hanno alcune funzionalità aggiuntive, come il metodo control, che aggiunge un controllo quantistico.

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

Output della cella di codice precedente

Per capire cosa sta succedendo, puoi usare il metodo decompose per espandere ogni istruzione nella sua definizione.

nota

Il metodo decompose restituisce un nuovo circuito e non muta il circuito su cui agisce.

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

Output della cella di codice precedente

Misurare i qubit​

Le misurazioni vengono usate per campionare gli stati dei singoli qubit e trasferire i risultati in un registro classico. Tieni presente che se stai inviando circuiti a una primitiva Sampler, le misurazioni sono obbligatorie. Invece, i circuiti inviati a una primitiva Estimator non devono contenere misurazioni.

I qubit possono essere misurati usando tre metodi: measure, measure_all e measure_active. Per scoprire come visualizzare i risultati delle misurazioni, consulta la pagina Visualizzare i risultati.

  1. QuantumCircuit.measure : misura ogni qubit nel primo argomento sul bit classico fornito come secondo argomento. Questo metodo consente il pieno controllo su dove viene memorizzato il risultato della misurazione.

  2. QuantumCircuit.measure_all : non richiede argomenti e può essere usato per circuiti quantistici senza bit classici predefiniti. Crea i fili classici e memorizza i risultati delle misurazioni in ordine. Ad esempio, la misurazione del qubit qiq_i viene memorizzata nel cbit measimeas_i). Aggiunge anche una barriera prima della misurazione.

  3. QuantumCircuit.measure_active : simile a measure_all, ma misura solo i qubit che hanno operazioni.

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

Output della cella di codice precedente

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

Output della cella di codice precedente

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

Output della cella di codice precedente

Circuiti parametrizzati​

Molti algoritmi quantistici a breve termine prevedono l'esecuzione di numerose varianti di un circuito quantistico. Poiché la costruzione e l'ottimizzazione di circuiti di grandi dimensioni possono essere costose dal punto di vista computazionale, Qiskit supporta i circuiti parametrizzati. Questi circuiti hanno parametri non definiti, i cui valori non devono essere specificati fino a poco prima dell'esecuzione del circuito. Questo ti permette di spostare la costruzione e l'ottimizzazione del circuito fuori dal ciclo principale del programma. La cella seguente crea e visualizza un circuito parametrizzato.

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 della cella di codice precedente

La cella seguente crea molte varianti di questo circuito e ne visualizza una.

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

circuits[0].draw("mpl")

Output della cella di codice precedente

Puoi trovare l'elenco dei parametri non definiti di un circuito nel suo attributo parameters.

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

Modificare il nome di un parametro​

Per impostazione predefinita, i nomi dei parametri per un circuito parametrizzato sono preceduti dal prefisso x— ad esempio, x[0]. Puoi modificare i nomi dopo che sono stati definiti, come mostrato nell'esempio seguente.

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)
Hai dimenticato il nome del metodo? Prova a chiedere a Qiskit Code Assistant.

Passi successivi​

Raccomandazioni