Apprendre le modèle de bruit d'une porte
Ce tutoriel montre comment apprendre un modèle de bruit pour une porte unitaire avec un protocole d'apprentissage standard accessible via les fonctions de protocole de haut niveau prepare_vanilla_program() et process_vanilla_result().
-
Définir la porte
-
Configurer la simulation locale
-
Préparer le programme quantique
-
Exécuter le programme quantique
-
Lire les résultats
Les circuits ci-dessous sont simulés localement, donc ce pas à pas ne nécessite aucun identifiant IBM Quantum®. Pour l'exécuter plutôt sur un appareil réel :
-
Étape 1 : remplace
FakeMarrakeshpar un vrai backend. -
Étape 2 : passe ce backend comme mode de l'executor, et supprime les options du simulateur.
1. Définir la porte
La porte est un BoxOp contenant une couche twirlée de six portes CZ disjointes.
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. Configurer la simulation locale
Les indices de Pauli à l'intérieur de chaque map sont locaux à la porte, dans l'ordre croissant des qubits physiques :
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}
Définis le bruit avec un terme ZZ corrélé et un terme XX plus faible sur chaque paire CZ, plus un terme Z à un seul qubit partout ; la mesure reçoit un terme de bit-flip par 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
)
Construis une boîte que la mesure doit apprendre.
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)
Chaque entrée de layer_noise_model associe une de ces boîtes à la map à lui appliquer. Utilise la méthode de simulation stabilizer et définis seed_simulator pour rendre les données simulées reproductibles.
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. Préparer le programme quantique
Utilise prepare_vanilla_program() pour construire le programme quantique contenant les expériences d'apprentissage.
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. Exécuter le programme quantique
Soumets le programme quantique. Cette étape est la même que l'executor pointe vers un simulateur ou vers un appareil réel.
result = executor.run(program).result()
5. Lire les résultats
Traite le résultat avec process_vanilla_result().
from qiskit_noise_learning.protocols import process_vanilla_result
noise_maps, gate_names, fit = process_vanilla_result(result)
Trace les décroissances de fidélité par paire de qubits : à la fois les données et l'ajustement exponentiel.
fit.plot_qubit_pair_decays(
pairs=cz_pairs,
observable_type="means",
exponential_fit=True,
)