Libreria di circuiti
Versioni dei pacchetti
Il codice in questa pagina è stato sviluppato utilizzando i seguenti requisiti. Si consiglia di usare queste versioni o versioni più recenti.
qiskit[all]~=2.3.0
L'SDK di Qiskit include una libreria di circuiti popolari da utilizzare come blocchi di costruzione nei tuoi programmi. Usare circuiti predefiniti consente di risparmiare tempo nella ricerca, nella scrittura del codice e nel debug. La libreria include circuiti diffusi nel quantum computing, circuiti difficili da simulare classicamente e circuiti utili per il benchmarking dell'hardware quantistico.
Questa pagina elenca le diverse categorie di circuiti fornite dalla libreria. Per un elenco completo dei circuiti, consulta la documentazione API della libreria di circuiti.
gate standard​
La libreria di circuiti include anche gate quantistici standard. Alcuni sono gate più fondamentali (come UGate), altri sono gate multi-qubit che di solito devono essere costruiti a partire da gate a uno e due qubit. Per aggiungere gate importati al tuo circuito, usa il metodo append; il primo argomento è il gate, il successivo è una lista di qubit a cui applicarlo.
Ad esempio, la seguente cella di codice crea un circuito con un gate di Hadamard e un gate multi-controlled-X.
# Added by doQumentation — required packages for this notebook
!pip install -q qiskit
from qiskit import QuantumCircuit
from qiskit.circuit.library import HGate, MCXGate
mcx_gate = MCXGate(3)
hadamard_gate = HGate()
qc = QuantumCircuit(4)
qc.append(hadamard_gate, [0])
qc.append(mcx_gate, [0, 1, 2, 3])
qc.draw("mpl")
Vedi Standard gates nella documentazione API della libreria di circuiti.
Circuiti N-local​
Questi circuiti alternano strati di gate di rotazione a singolo qubit con strati di gate di entanglement multi-qubit.
Questa famiglia di circuiti è molto diffusa negli algoritmi quantistici variazionali perché può produrre un'ampia varietà di stati quantistici. Gli algoritmi variazionali regolano i parametri dei gate per trovare stati che abbiano determinate proprietà (ad esempio stati che rappresentano una buona soluzione a un problema di ottimizzazione). A questo scopo, molti circuiti nella libreria sono parametrizzati, il che significa che puoi definirli senza valori fissi.
La seguente cella di codice importa un circuito n_local, in cui i gate di entanglement sono gate a due qubit. Questo circuito alterna blocchi di gate a singolo qubit parametrizzati con blocchi di entanglement a due qubit. Il codice seguente crea un circuito a tre qubit, con gate RX a singolo qubit e gate CZ a due qubit.
from qiskit.circuit.library import n_local
two_local = n_local(3, "rx", "cz")
two_local.draw("mpl")
Puoi ottenere un oggetto simile a una lista dei parametri del circuito dall'attributo parameters.
two_local.parameters
ParameterView([ParameterVectorElement(θ[0]), ParameterVectorElement(θ[1]), ParameterVectorElement(θ[2]), ParameterVectorElement(θ[3]), ParameterVectorElement(θ[4]), ParameterVectorElement(θ[5]), ParameterVectorElement(θ[6]), ParameterVectorElement(θ[7]), ParameterVectorElement(θ[8]), ParameterVectorElement(θ[9]), ParameterVectorElement(θ[10]), ParameterVectorElement(θ[11])])
Puoi anche usarlo per assegnare questi parametri a valori reali tramite un dizionario della forma { Parameter: numero }. A titolo di esempio, la seguente cella di codice assegna a ogni parametro del circuito il valore 0.
bound_circuit = two_local.assign_parameters(
{p: 0 for p in two_local.parameters}
)
bound_circuit.decompose().draw("mpl")
Per ulteriori informazioni, consulta N-local gates nella documentazione API della libreria di circuiti, oppure segui il corso di progettazione di algoritmi variazionali su IBM Quantum Learning.
Circuiti di codifica dei dati​
Questi circuiti parametrizzati codificano i dati in stati quantistici per l'elaborazione da parte di algoritmi di quantum machine learning. Alcuni circuiti supportati da Qiskit sono:
- La codifica in ampiezza (amplitude encoding), che codifica ogni numero nell'ampiezza di uno stato della base. Questo consente di memorizzare numeri in un singolo stato, ma può essere costoso da implementare.
- La codifica in base (basis encoding), che codifica un intero preparando il corrispondente stato della base .
- La codifica angolare (angle encoding), che imposta ogni numero nei dati come angolo di rotazione in un circuito parametrizzato.
L'approccio migliore dipende dalle specifiche della tua applicazione. Sui computer quantistici attuali, tuttavia, si usano spesso circuiti di codifica angolare come zz_feature_map.
from qiskit.circuit.library import zz_feature_map
features = [0.2, 0.4, 0.8]
feature_map = zz_feature_map(feature_dimension=len(features))
encoded = feature_map.assign_parameters(features)
encoded.draw("mpl")
Vedi Data encoding circuits nella documentazione API della libreria di circuiti.
Circuiti di evoluzione temporale​
Questi circuiti simulano l'evoluzione nel tempo di uno stato quantistico. Usa i circuiti di evoluzione temporale per studiare effetti fisici come il trasferimento di calore o le transizioni di fase in un sistema. I circuiti di evoluzione temporale sono anche un blocco fondamentale delle funzioni d'onda in chimica (come gli stati di prova unitary coupled-cluster) e dell'algoritmo QAOA utilizzato per i problemi di ottimizzazione.
from qiskit.circuit.library import PauliEvolutionGate
from qiskit.circuit import QuantumCircuit
from qiskit.quantum_info import SparsePauliOp
# Prepare an initial state with a Hadamard on the middle qubit
state = QuantumCircuit(3)
state.h(1)
hamiltonian = SparsePauliOp(["ZZI", "IZZ"])
evolution = PauliEvolutionGate(hamiltonian, time=1)
# Evolve state by appending the evolution gate
state.compose(evolution, inplace=True)
state.draw("mpl")
Consulta la documentazione API di PauliEvolutionGate.
Circuiti di benchmarking e di teoria della complessità ​
I circuiti di benchmarking ci danno un'idea di quanto bene stia effettivamente funzionando il nostro hardware, mentre i circuiti di teoria della complessità ci aiutano a capire quanto difficili siano i problemi che vogliamo risolvere.
Ad esempio, il benchmark del "quantum volume" misura con quale precisione un computer quantistico esegue un tipo di circuito quantistico casuale. Il punteggio del computer quantistico aumenta con la dimensione del circuito che riesce a eseguire in modo affidabile. Questo tiene conto di tutti gli aspetti del computer, inclusi il numero di qubit, la fedeltà delle istruzioni, la connettività dei qubit e lo stack software per il transpiling e la post-elaborazione dei risultati. Per saperne di più sul quantum volume, consulta il paper originale sul quantum volume.
Il codice seguente mostra un esempio di circuito di quantum volume costruito in Qiskit che gira su quattro qubit (i blocchi unitary sono gate a due qubit randomizzati).
from qiskit.circuit.library import quantum_volume
quantum_volume(4).draw("mpl")
La libreria di circuiti include anche circuiti ritenuti difficili da simulare classicamente, come i circuiti IQP (instantaneous quantum polynomial). Questi circuiti racchiudono certi gate diagonali (nella base computazionale) tra blocchi di gate di Hadamard.
Altri circuiti includono grover_operator da usare nell'algoritmo di Grover e il circuito fourier_checking per il problema del Fourier checking. Consulta questi circuiti in Particular quantum circuits nella documentazione API della libreria di circuiti.
Circuiti aritmetici​
Le operazioni aritmetiche sono funzioni classiche, come l'addizione di interi e le operazioni bit a bit. Possono essere utili con algoritmi come l'amplitude estimation per applicazioni finanziarie e in algoritmi come l'algoritmo HHL, che risolve sistemi lineari di equazioni.
Come esempio, proviamo ad addizionare due numeri a tre bit usando un circuito "ripple-carry" per eseguire un'addizione in-place (FullAdderGate). Questo addizionatore somma due numeri (che chiameremo "A" e "B") e scrive il risultato nel registro che conteneva B. Nell'esempio seguente, A=2 e B=3.
from qiskit.circuit.library import FullAdderGate
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
adder = FullAdderGate(3) # Adder of 3-bit numbers
# Create the number A=2
reg_a = QuantumRegister(3, "a")
number_a = QuantumCircuit(reg_a)
number_a.initialize(2) # Number 2; |010>
# Create the number B=3
reg_b = QuantumRegister(3, "b")
number_b = QuantumCircuit(reg_b)
number_b.initialize(3) # Number 3; |011>
# Create a circuit to hold everything, including a classical register for
# the result
qregs = [
QuantumRegister(1, "cin"),
QuantumRegister(3, "a"),
QuantumRegister(3, "b"),
QuantumRegister(1, "cout"),
]
reg_result = ClassicalRegister(3)
circuit = QuantumCircuit(*qregs, reg_result)
# Compose number initializers with the adder. Adder stores the result to
# register B, so we'll measure those qubits.
circuit = (
circuit.compose(number_a, qubits=reg_a)
.compose(number_b, qubits=reg_b)
.compose(adder)
)
circuit.measure(reg_b, reg_result)
circuit.draw("mpl")
La simulazione del circuito mostra che produce 5 per tutte le 1024 shot (ovvero viene misurato con probabilità 1.0).
from qiskit.primitives import StatevectorSampler
result = StatevectorSampler().run([circuit]).result()
print(f"Count data:\n {result[0].data.c0.get_int_counts()}")
Count data:
{5: 1024}
Vedi Arithmetic nella documentazione API della libreria di circuiti.
Passi successivi​
- Scopri metodi avanzati per la creazione di circuiti nell'argomento Costruire circuiti.
- Guarda un esempio di utilizzo dei circuiti nel tutorial Algoritmo di Grover.
- Consulta il riferimento all'API della libreria di circuiti.