Apprendere il modello di rumore di un gate
Questo tutorial mostra come apprendere un modello di rumore per un gate unitario con un protocollo di apprendimento standard accessibile tramite le funzioni di protocollo di alto livello prepare_vanilla_program() e process_vanilla_result().
-
Definire il gate
-
Configurare la simulazione locale
-
Preparare il programma quantistico
-
Eseguire il programma quantistico
-
Leggere i risultati
I circuiti seguenti vengono simulati in locale, quindi questa guida non richiede credenziali IBM Quantum®. Per eseguirla invece su un dispositivo reale:
-
Passo 1: sostituisci
FakeMarrakeshcon un backend reale. -
Passo 2: passa quel backend come modalità dell'executor e rimuovi le opzioni del simulatore.
1. Definire il gate
Il gate è un BoxOp che contiene uno strato con twirling di sei gate CZ disgiunti.
from qiskit.circuit import QuantumCircuit
from qiskit_ibm_runtime.fake_provider import FakeMarrakesh
from samplomatic import InjectNoise, Tag, Twirl
backend = FakeMarrakesh()
cz_pairs = [(91, 92), (93, 94), (95, 99), (98, 111), (112, 113), (114, 115)]
circuit = QuantumCircuit(backend.num_qubits)
with circuit.box([Twirl(), Tag("cz_gate"), InjectNoise("cz_gate")]):
for pair in cz_pairs:
circuit.cz(*pair)
from qiskit_ibm_runtime import QiskitRuntimeService
backend = QiskitRuntimeService().backend("ibm_marrakesh")
2. Configurare la simulazione locale
Gli indici di Pauli all'interno di ogni mappa sono locali al gate, in ordine crescente dei qubit fisici:
cz_qubits = sorted({qubit for pair in cz_pairs for qubit in pair})
local = {qubit: index for index, qubit in enumerate(cz_qubits)}
local
{91: 0,
92: 1,
93: 2,
94: 3,
95: 4,
98: 5,
99: 6,
111: 7,
112: 8,
113: 9,
114: 10,
115: 11}
Definisci il rumore con un termine ZZ correlato e un termine XX più debole su ogni coppia CZ, più un termine Z a singolo qubit ovunque; la misura riceve un termine di bit-flip per ogni qubit.
from qiskit.quantum_info import PauliLindbladMap
num_qubits = len(cz_qubits)
cz_noise = PauliLindbladMap.from_sparse_list(
[("ZZ", [local[a], local[b]], 8e-4) for a, b in cz_pairs]
+ [("XX", [local[a], local[b]], 4e-4) for a, b in cz_pairs]
+ [("Z", [index], 3e-4) for index in range(num_qubits)],
num_qubits=num_qubits,
)
readout_noise = PauliLindbladMap.from_sparse_list(
[("X", [index], 5e-3) for index in range(num_qubits)], num_qubits=num_qubits
)
Costruisci un box per la misura da apprendere.
measurement = QuantumCircuit(backend.num_qubits, num_qubits)
with measurement.box([Twirl(), Tag("readout"), InjectNoise("readout")]):
for clbit, qubit in enumerate(cz_qubits):
measurement.measure(qubit, clbit)
Ogni voce di layer_noise_model associa uno di questi box alla mappa da applicargli. Usa il metodo di simulazione stabilizer e imposta seed_simulator per rendere riproducibili i dati simulati.
from qiskit_aer import AerSimulator
from qiskit_ibm_runtime import Executor
executor = Executor(
mode=AerSimulator(method="stabilizer"),
options={
"simulator": {
"layer_noise_model": [
(circuit[0], cz_noise),
(measurement[0], readout_noise),
],
"seed_simulator": 1234,
}
},
)
executor = Executor(mode=backend)
3. Prepara il programma quantistico
Usa prepare_vanilla_program() per costruire il programma quantistico che contiene gli esperimenti di apprendimento.
from qiskit_noise_learning.protocols import prepare_vanilla_program
program = prepare_vanilla_program(
backend,
[circuit[0], measurement[0]],
fragment_depths=[2, 16, 64, 128],
num_randomizations=50,
shots_per_randomization=20,
)
print(f"Number of template circuits: {len(program.items)}")
Number of template circuits: 5
4. Esegui il programma quantistico
Invia il programma quantistico. Questo passaggio è identico sia che l'executor punti a un simulatore sia a un dispositivo reale.
result = executor.run(program).result()
5. Leggi i risultati
Elabora il risultato con process_vanilla_result().
from qiskit_noise_learning.protocols import process_vanilla_result
noise_maps, gate_names, fit = process_vanilla_result(result)
Traccia i decadimenti della fedeltà per ogni coppia di qubit: sia i dati sia il fit esponenziale.
fit.plot_qubit_pair_decays(
pairs=cz_pairs,
observable_type="means",
exponential_fit=True,
)