Vai al contenuto principale
Questo progetto è in fase beta. Hai trovato un bug? Apri una issue su GitHub. Hai una domanda o un'idea? Chiedi su GitHub Discussions — apprezziamo il tuo feedback!
Com'è la qualità della traduzione su questa pagina?

Gate frazionari

Versioni dei pacchetti

Il codice di questa pagina è stato sviluppato usando i seguenti requisiti. Si consiglia di usare queste versioni o versioni più recenti.

qiskit[all]~=2.5.2
qiskit-ibm-runtime~=0.47.0

Questa pagina introduce due nuovi tipi di Gate supportati sulla flotta di QPU IBM Quantum®. Questi Gate frazionari sono supportati sulle QPU Heron nella forma di:

  • RZZ(θ)R_{ZZ}(\theta) per 0<θ≤π/20 \lt \theta \leq \pi/2
  • RX(θ)R_X(\theta) per qualsiasi θ\theta

Questa pagina tratta i casi d'uso in cui l'impiego dei gate frazionari può migliorare l'efficienza dei tuoi flussi di lavoro, oltre a spiegare come utilizzarli sulle QPU IBM Quantum.

# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util

_needed = {"qiskit": "qiskit", "qiskit_ibm_runtime": "qiskit-ibm-runtime"}
_missing = [pip for module, pip in _needed.items()
if importlib.util.find_spec(module) is None]
# One at a time, so a package that fails to install does not block the others
for _pip in _missing:
%pip install -q {_pip}
if not _missing:
print("\u2713 All required packages are installed")

Come usare i gate frazionari​

Internamente, questi gate frazionari funzionano eseguendo direttamente una rotazione RZZ(θ)R_{ZZ}(\theta) e RX(θ)R_X(\theta) per un angolo arbitrario. L'uso del gate RX(θ)R_X(\theta) può ridurre la durata e l'errore per le rotazioni a qubit singolo di angolo arbitrario fino a un fattore due. L'esecuzione diretta della rotazione del gate RZZ(θ)R_{ZZ}(\theta) evita la decomposizione in più oggetti CZGate, riducendo in modo analogo la durata e l'errore del circuito. Questo è particolarmente utile per i circuiti che contengono molte rotazioni a uno e due qubit, come quando si simulano le dinamiche di un sistema quantistico o quando si usa un ansatz variazionale con molti parametri.

Sebbene questi tipi di gate siano presenti nella libreria di gate standard che un QuantumCircuit può possedere, possono essere usati solo su specifiche QPU IBM Quantum, che devono essere caricate con il flag use_fractional_gates impostato a True (come mostrato di seguito). Questo flag garantirà che i gate frazionari siano inclusi nel Target del backend per il transpiler.

service = QiskitRuntimeService()
backend = service.backend('ibm_torino', use_fractional_gates=True)

Questo esempio di codice mostra come usare i gate frazionari nel contesto di un flusso di lavoro che simula le dinamiche di una catena di Ising usando i gate frazionari. La durata del circuito viene poi confrontata con un backend che non usa gate frazionari.

Nota sui tassi di errore riportati

Il valore di errore riportato nel Target di un backend con gate frazionari abilitati è semplicemente una copia dell'analogo gate non frazionario (che potrebbe non essere lo stesso). Questo perché la comunicazione dei tassi di errore sui gate frazionari non è ancora supportata.

Tuttavia, poiché il tempo di gate dei gate frazionari rispetto a quelli non frazionari è lo stesso, è ragionevole assumere che i loro tassi di errore siano comparabili — soprattutto quando la sorgente di errore dominante in un circuito è dovuta al rilassamento.

from qiskit import QuantumCircuit
from qiskit.circuit import Parameter
from qiskit.transpiler import generate_preset_pass_manager
from qiskit.visualization.timeline import draw as draw_timeline, IQXSimple

from qiskit_ibm_runtime import QiskitRuntimeService

num_qubits = 5
num_time_steps = 3
rx_angle = 0.1
rzz_angle = 0.1

ising_circuit = QuantumCircuit(num_qubits)
for i in range(num_time_steps):
# rx layer
for q in range(num_qubits):
ising_circuit.rx(rx_angle, q)
for q in range(1, num_qubits - 1, 2):
ising_circuit.rzz(rzz_angle, q, q + 1)
# 2nd rzz layer
for q in range(0, num_qubits - 1, 2):
ising_circuit.rzz(rzz_angle, q, q + 1)
ising_circuit.barrier()
ising_circuit.draw("mpl")

Output della cella di codice precedente

Specifica due oggetti backend: uno con i gate frazionari abilitati e l'altro con essi disabilitati, poi esegui il transpiling di entrambi.

service = QiskitRuntimeService()
backend_name = service.least_busy(operational=True, simulator=False).name
backend_fractional = service.backend(backend_name, use_fractional_gates=True)
backend_conventional = service.backend(
backend_name, use_fractional_gates=False
)

pm_fractional = generate_preset_pass_manager(
optimization_level=3, backend=backend_fractional, scheduling_method="alap"
)
pm_conventional = generate_preset_pass_manager(
optimization_level=3,
backend=backend_conventional,
scheduling_method="alap",
)

ising_circuit_fractional = pm_fractional.run(ising_circuit)
ising_circuit_conventional = pm_conventional.run(ising_circuit)

Visualizza la timeline del circuito usando i due tipi di gate.

# Draw timeline of circuit with conventional gates
draw_timeline(
ising_circuit_conventional,
idle_wires=False,
target=backend_conventional.target,
time_range=(0, 500),
style=IQXSimple(),
)

Output della cella di codice precedente

# Draw timeline of circuit with fractional gates
draw_timeline(
ising_circuit_fractional,
idle_wires=False,
target=backend_fractional.target,
time_range=(0, 500),
style=IQXSimple(),
)

Output della cella di codice precedente

Vincoli sugli angoli​

Per il gate RZZ(θ)R_{ZZ}(\theta) a due qubit, sull'hardware IBM Quantum possono essere eseguiti solo angoli compresi tra 00 e π/2\pi/2. Se un circuito contiene gate RZZ(θ)R_{ZZ}(\theta) con un angolo fuori da questo intervallo, la pipeline di transpilation standard lo correggerà generalmente con un'appropriata trasformazione del circuito (tramite il pass FoldRzzAngle). Tuttavia, per qualsiasi gate RZZ(θ)R_{ZZ}(\theta) che contiene uno o più Parameters, il transpiler assumerà che questi parametri riceveranno angoli compresi in questo intervallo a runtime. Il job fallirà se uno qualsiasi dei valori dei parametri specificati nel PUB inviato a IBM Quantum Compute Service è fuori da questo intervallo.

Dove usare i gate frazionari​

Storicamente, i gate base disponibili sulle QPU IBM Quantum sono stati CZ, X, RZ, SX e ID, che non riescono a rappresentare in modo efficiente circuiti con rotazioni a uno e due qubit che non siano multipli di π/2\pi / 2. Ad esempio, un gate RX(θ)R_X(\theta), quando viene sottoposto a transpiling, deve decomporsi in una serie di gate RZRZ e X\sqrt{X}, creando un circuito con due gate di durata finita invece di uno.

Allo stesso modo, quando rotazioni a due qubit come un gate RZZ(θ)R_{ZZ}(\theta) vengono sottoposte a transpiling, la decomposizione richiede due gate CZ e diversi gate a qubit singolo, aumentando la profondità del circuito. Queste decomposizioni sono mostrate nel codice seguente.

qc = QuantumCircuit(1)
param = Parameter("θ")
qc.rx(param, 0)
qc.draw("mpl")

Output della cella di codice precedente

# Decomposition of an RX(θ) gate using the IBM Quantum QPU basis
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)
optimization_level = 3
pm = generate_preset_pass_manager(optimization_level, backend=backend)
transpiled_circuit = pm.run(qc)
transpiled_circuit.draw("mpl", idle_wires=False)

Output della cella di codice precedente

from qiskit import QuantumCircuit
from qiskit.circuit import Parameter
from qiskit.transpiler import generate_preset_pass_manager

from qiskit_ibm_runtime import QiskitRuntimeService

qc = QuantumCircuit(2)
param = Parameter("θ")
qc.rzz(param, 0, 1)
qc.draw("mpl")

Output della cella di codice precedente

# Decomposition of an RZZ(θ) gate using the IBM Quantum QPU basis
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)
optimization_level = 3
pm = generate_preset_pass_manager(optimization_level, backend=backend)
transpiled_circuit = pm.run(qc)
transpiled_circuit.draw("mpl", idle_wires=False)

Output della cella di codice precedente

Per i flussi di lavoro che richiedono molte rotazioni a singolo Qubit RX(θ)R_X(\theta) o a due Qubit (come in un ansatz variazionale o quando si simula l'evoluzione temporale di sistemi quantistici), questo vincolo fa crescere rapidamente la profondità del circuito. Tuttavia, i Gate frazionari eliminano questo requisito, poiché le rotazioni a uno e due Qubit vengono eseguite direttamente, creando un Circuit quantistico più efficiente (e quindi con soppressione degli errori).

Quando non usare i gate frazionari​

È importante notare che i gate frazionari sono una funzionalità sperimentale e il comportamento del flag use_fractional_gates potrebbe cambiare in futuro. Consulta le note di rilascio delle nuove versioni di qiskit-ibm-runtime per ulteriori informazioni. Consulta anche la documentazione di riferimento dell'API per QiskitRuntimeService.backend, che descrive use_fractional_gates.

Inoltre, il transpiler di Qiskit ha una capacità limitata di usare RZZ(θ)R_{ZZ}(\theta) nei propri pass di ottimizzazione. Questo richiede maggiore attenzione nella costruzione e nell'ottimizzazione dei circuiti che contengono queste istruzioni.

Infine, l'uso dei gate frazionari non è supportato per:

Leggi la guida sulle opzioni delle primitive per saperne di più su come personalizzare le tecniche di mitigazione e soppressione degli errori per un dato carico di lavoro quantistico.

Quali backend supportano i Gate frazionari?​

Non tutti i Backend supportano i Gate frazionari. Esegui service.backends(use_fractional_gates=True) per trovare quelli che li supportano. Con il rilascio di qiskit-ibm-runtime v0.48, puoi anche eseguire service.least_busy(fractional_gates=True) per trovare il Backend meno occupato che supporta i Gate frazionari. Un fake Backend supporta i Gate frazionari solo se il relativo Backend "reale" li supporta.

Nota che i fake Backend non supportano i Gate frazionari per impostazione predefinita, poiché i Gate frazionari sono disabilitati per impostazione predefinita. Per abilitare i Gate frazionari su un fake Backend che li supporta, aggiorna la sua configurazione.

Example:

service = QiskitRuntimeService()
fake_backend = FakeBoston()
fake_backend.refresh(service=service, use_fractional_gates=True)

Passi successivi​

Raccomandazioni