Bumuo ng learning experiment
Ipinapakita ng tutorial na ito kung paano bumuo ng standard na learning experiment mula sa simula, at gamitin ito para matutunan ang isang model mula sa simulated na noisy data.
-
Tukuyin ang gate set sa isang ring ng mga qubit
-
Pumili ng 2-local na Pauli-Lindblad model
-
Buuin ang learning experiment
-
Bumuo ng mga circuit
-
I-set up ang local simulation
-
Patakbuhin ang program
-
Suriin ang data
Ang mga circuit sa ibaba ay lokal na sinisimulate, kaya hindi kailangan ng walkthrough na ito ng IBM Quantum® credentials. Para patakbuhin ito sa totoong device:
-
Hakbang 1: palitan ang
FakeMarrakeshng totoong backend. -
Hakbang 5: ipasa ang backend na iyon bilang mode ng executor, at alisin ang mga simulator option.
1. Tukuyin ang gate set sa isang ring ng mga qubit
Bumuo ng QiskitGateSet mula sa Target ng isang backend at isang subset ng mga qubit nito — dito, isang ring na may labindalawang qubit ng FakeMarrakesh — pagkatapos ay magdagdag dito ng isang gate: isang layer ng anim na CZ gate na sumasaklaw sa ring na iyon. Bilang default, ang gate set ay ini-initialize na may preparation gate na P at measurement gate na M.
from qiskit_ibm_runtime.fake_provider import FakeMarrakesh
from qiskit_noise_learning.gate_sets import QiskitGateSet
backend = FakeMarrakesh()
qubit_subset = [*range(25, 30), *range(37, 39), *range(45, 50)]
cz_pairs = [(25, 26), (27, 28), (29, 38), (37, 45), (46, 47), (48, 49)]
gate_set = QiskitGateSet(backend.num_qubits, target=backend.target, qubit_subset=qubit_subset)
with gate_set.build_new_gate("cz_gate", latex_str=r"\mathrm{CZ}") as builder:
for pair in cz_pairs:
builder.circuit.cz(*pair)
list(gate_set)
['M', 'P', 'cz_gate']
from qiskit_ibm_runtime import QiskitRuntimeService
backend = QiskitRuntimeService().backend("ibm_marrakesh")
Tawagin ang draw() para makita ang gate sa topology ng device: ang ring ng mga qubit sa gate set, at kung aling mga pares nito ang ine-entangle ng gate.
gate_set.draw()
2. Pumili ng 2-local na Pauli-Lindblad model
Magpasya kung aling mga Pauli-Lindblad generator ang maaaring taglayin ng noise gamit ang PauliLindbladModel. Buuin ang generator set na iyon mula sa connectivity ng gate set gamit ang k_local() — dito, bawat 2-local na Pauli sa mga konektadong qubit pair ng unitary gate, at mga single-qubit na Pauli para sa preparation at measurement.
from qiskit_noise_learning.models import PauliLindbladModel
model = PauliLindbladModel.k_local(gate_set, gate_k={"cz_gate": 2, "M": 1, "P": 1})
Ipakita ang bilang ng hindi kilalang parameter para sa noise model ng bawat gate.
{name: len(generators) for name, generators in model.generators.items()}
{'M': 12, 'P': 12, 'cz_gate': 144}
3. Buuin ang learning experiment
Buuin ang isang Experiment sa pamamagitan ng pagsasama-sama ng mga builder stage. Binabasa ng bawat stage ang isinulat ng mga naunang stage, kaya mahalaga ang pagkakasunod-sunod:
from qiskit_noise_learning.experiment_builder import (
BindFragmentDepths,
CompleteSequences,
EvenDepthVanillaPaths,
Experiment,
GenerateInstructionSequences,
IdentifyRelations,
MergeInstructionSequences,
SPAMPaths,
VanillaInstructionSequences,
)
experiment_builder = (
# Add standard vanilla learning paths and instruction sequences, and identify relations
EvenDepthVanillaPaths()
+ VanillaInstructionSequences()
+ IdentifyRelations()
# Add paths for learning SPAM, then generate and merge instruction sequences for measuring them
+ SPAMPaths()
+ GenerateInstructionSequences()
+ MergeInstructionSequences()
# Finalize by completing the instruction sequences and setting experiment depths
+ CompleteSequences()
+ BindFragmentDepths([2, 16, 32, 64])
)
experiment = experiment_builder.run(
Experiment(fidelity_model=model, shots=20, randomizations=50)
)
print(f"Number of paths: {len(experiment.paths)}")
print(f"Number of instruction sequences: {len(experiment.instruction_sequences)}")
Number of paths: 156
Number of instruction sequences: 37
Obserbahan ang rank ng design matrix:
print(f"Design matrix rank: {experiment.design_matrix.rank}")
Design matrix rank: 120
4. Bumuo ng mga circuit
I-compile ang experiment gamit ang isang ExecutorCircuitGenerator, na bumubuo ng isang QuantumProgram — isang parameterized na template circuit bawat fragment depth.
from qiskit_noise_learning.circuit_generator import ExecutorCircuitGenerator
circuit_generator = ExecutorCircuitGenerator(gate_set)
quantum_program = circuit_generator.generate(experiment)
print(f"Number of template circuits: {len(quantum_program.items)}")
Number of template circuits: 5
Gumuhit ng template circuit para suriin.
quantum_program.items[0].circuit.draw("mpl", idle_wires=False, fold=False)
5. I-set up ang local simulation
Para tukuyin ang noise model para sa simulation, gagamitin natin ang mga generator na nasa model na may random na rate para buuin ang isang PauliLindbladMap.
import numpy as np
from qiskit.quantum_info import PauliLindbladMap
rng = np.random.default_rng(1234)
true_maps = {
name: PauliLindbladMap.from_terms(
[
PauliLindbladMap.GeneratorTerm(rate, generator)
for generator, rate in zip(generators, rng.uniform(2e-4, 1.5e-3, len(generators)))
]
)
for name, generators in model.generators.items()
if name != "P"
}
{name: noise_map.num_qubits for name, noise_map in true_maps.items()}
{'M': 156, 'cz_gate': 156}
Kasinlapad ng device ang mga map na iyon, dahil ang model ay ipinapahayag sa qubit indexing ng backend, pero gusto ng simulator na ang bawat map ay kasinlapad ng gate na pinag-aapplyan nito, na ang mga Pauli index ay tumatakbo sa mga qubit ng gate sa pataas na pisikal na pagkakasunod-sunod. Paliitin ang mga ito gamit ang keep_qubits(), na nagta-trace out ng lahat ng nasa labas ng ring:
noise_dict = {
name: noise_map.keep_qubits(qubit_subset) for name, noise_map in true_maps.items()
}
{name: noise_map.num_qubits for name, noise_map in noise_dict.items()}
{'M': 12, 'cz_gate': 12}
Pinapangalanan ng simulator ang noise ng isang layer ayon sa box instruction kung saan binuo ang layer, na ibinabalik ng to_instruction() para sa anumang gate sa gate set. Ipares ang bawat box sa map nito, gamitin ang stabilizer simulation method, at itakda ang seed_simulator para maging reproducible ang simulated na data:
from qiskit_aer import AerSimulator
from qiskit_ibm_runtime import Executor
executor = Executor(
mode=AerSimulator(method="stabilizer"),
options={
"simulator": {
"layer_noise_model": [
(gate_set[name].to_instruction(), noise_map)
for name, noise_map in noise_dict.items()
],
"seed_simulator": 42,
}
},
)
executor = Executor(mode=backend)
6. Patakbuhin ang program
Patakbuhin ang program, pagkatapos ay i-format ang mga resulta gamit ang collect(), para makabuo ng Fit — ang container na binabasahan at sinusulatan ng mga analysis stage.
Pareho ang hakbang na ito kahit ang executor ay nakaturo sa simulator o sa totoong device.
job = executor.run(quantum_program)
fit = circuit_generator.collect(job.result())
7. Suriin ang data
Bumuo ng analysis pipeline sa paligid ng nonnegative least squares fitting ng model.
from qiskit_noise_learning.analysis import (
ComputeObservables, # computes observables from raw data
CurveFitObservables, # performs exponential fitting
LeastSquaresSolve, # solves model with (nonnegative) least squares
)
analyzer = ComputeObservables() + CurveFitObservables() + LeastSquaresSolve()
fit = analyzer.run(fit)
/opt/hostedtoolcache/Python/3.15.1/x64/lib/python3.15/site-packages/qiskit_noise_learning/analysis/model_solve.py:250: UserWarning: 7 of 156 row(s) of the linear system have a non-positive or non-finite uncertainty, so they carry no usable statistical weight. Positions in LinearSystemData.row_labels: 144, 145, 148, 149, 151, 152, 154.
system = LinearSystemData.from_fit(fit)
I-plot ang mga sinukat na mean ng observable laban sa kanilang mga fitted na exponential, isang subplot bawat CZ pair, para makita kung exponential nga ba ang mga decay na pino-fit.
fit.plot_qubit_pair_decays(
pairs=cz_pairs,
observable_type="means",
exponential_fit=True,
)
Palitan ang exponential_fit ng model_prediction para ihambing ang parehong data sa mga decay na ipinahihiwatig ng mga rate na lumabas mula sa non-negative least squares solve.
fit.plot_qubit_pair_decays(
pairs=cz_pairs,
observable_type="means",
model_prediction=True,
)
