Ladění úloh Qiskit Runtime
Verze balíčků
Kód na této stránce byl vyvinut s použitím následujících požadavků. Doporučujeme používat tyto verze nebo novější.
qiskit[all]~=2.3.0
qiskit-ibm-runtime~=0.43.1
qiskit-aer~=0.17
Před odesláním náročné úlohy Qiskit Runtime ke spuštění na hardwaru můžeš použít třídu Qiskit Runtime Neat (Noisy Estimator Analyzer Tool) k ověření, že je tvoje úloha Estimatoru správně nastavena, pravděpodobně vrátí přesné výsledky, používá nejvhodnější možnosti pro zadaný problém a podobně.
Neat Cliffordizuje vstupní Circuit pro efektivní simulaci, přičemž zachovává jeho strukturu a hloubku. Cliffordovy Circuit trpí podobnou mírou šumu a jsou dobrým přibližovadlem pro studium původního Circuit zájmu.
Následující příklady ilustrují situace, kde může být Neat užitečným nástrojem.
Nejprve importuj příslušné balíčky a ověř svoji identitu ve službě Qiskit Runtime.
Příprava prostředí
# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit qiskit-aer qiskit-ibm-runtime
import numpy as np
import random
from qiskit.circuit import QuantumCircuit
from qiskit.transpiler import generate_preset_pass_manager
from qiskit.quantum_info import SparsePauliOp
from qiskit_ibm_runtime import QiskitRuntimeService, EstimatorV2 as Estimator
from qiskit_ibm_runtime.debug_tools import Neat
from qiskit_aer.noise import NoiseModel, depolarizing_error
# Choose the least busy backend
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)
# Generate a preset pass manager
# This will be used to convert the abstract circuit to an equivalent Instruction Set Architecture (ISA) circuit.
pm = generate_preset_pass_manager(backend=backend, optimization_level=0)
# Set the random seed
random.seed(10)
Inicializace cílového Circuit
Uvažuj šestiqubitový Circuit s následujícími vlastnostmi:
- Střídá náhodné rotace
RZa vrstvy GateCNOT. - Má zrcadlovou strukturu, tedy aplikuje unitární operaci
Unásledovanou její inverzí.
def generate_circuit(n_qubits, n_layers):
r"""
A function to generate a pseudo-random a circuit with ``n_qubits`` qubits and
``2*n_layers`` entangling layers of the type used in this notebook.
"""
# An array of random angles
angles = [
[random.random() for q in range(n_qubits)] for s in range(n_layers)
]
qc = QuantumCircuit(n_qubits)
qubits = list(range(n_qubits))
# do random circuit
for layer in range(n_layers):
# rotations
for q_idx, qubit in enumerate(qubits):
qc.rz(angles[layer][q_idx], qubit)
# cx gates
control_qubits = (
qubits[::2] if layer % 2 == 0 else qubits[1 : n_qubits - 1 : 2]
)
for qubit in control_qubits:
qc.cx(qubit, qubit + 1)
# undo random circuit
for layer in range(n_layers)[::-1]:
# cx gates
control_qubits = (
qubits[::2] if layer % 2 == 0 else qubits[1 : n_qubits - 1 : 2]
)
for qubit in control_qubits:
qc.cx(qubit, qubit + 1)
# rotations
for q_idx, qubit in enumerate(qubits):
qc.rz(-angles[layer][q_idx], qubit)
return qc
# Generate a random circuit
qc = generate_circuit(6, 3)
# Convert the abstract circuit to an equivalent ISA circuit.
isa_qc = pm.run(qc)
qc.draw("mpl", idle_wires=0)
Jako pozorovatelné veličiny zvol jednopauliové operátory Z a použij je k inicializaci primitiv unified blocs (PUBs).
# Initialize the observables
obs = ["ZIIIII", "IZIIII", "IIZIII", "IIIZII", "IIIIZI", "IIIIIZ"]
print(f"Observables: {obs}")
# Map the observables to the backend's layout
isa_obs = [SparsePauliOp(o).apply_layout(isa_qc.layout) for o in obs]
# Initialize the PUBs, which consist of six-qubit circuits with `n_layers` 1, ..., 6
all_n_layers = [1, 2, 3, 4, 5, 6]
pubs = [(pm.run(generate_circuit(6, n)), isa_obs) for n in all_n_layers]
Observables: ['ZIIIII', 'IZIIII', 'IIZIII', 'IIIZII', 'IIIIZI', 'IIIIIZ']
Cliffordizace Circuit
Dříve definované PUB Circuit nejsou Cliffordovy, což je ztěžuje klasicky simulovat. Můžeš však použít metodu Neat to_clifford k jejich mapování na Cliffordovy Circuit pro efektivnější simulaci. Metoda to_clifford je obalová funkce kolem Transpiler průchodu ConvertISAToClifford, který lze také použít samostatně. Konkrétně nahrazuje nekliffordovy jednoqubitové Gate v původním Circuit Cliffordovými jednoqubitovými Gate, ale nemění dvoququbitové Gate, počet Qubitů ani hloubku Circuit.
Více informací o simulaci Cliffordových Circuit najdeš v části Efektivní simulace stabilizátorových Circuit s primitiv Qiskit Aer.
Nejprve inicializuj Neat.
# You could specify a custom `NoiseModel` here. If `None`, `Neat`
# pulls the noise model from the given backend
noise_model = None
# Initialize `Neat`
analyzer = Neat(backend, noise_model)
Poté Cliffordizuj PUBs.
clifford_pubs = analyzer.to_clifford(pubs)
clifford_pubs[0].circuit.draw("mpl", idle_wires=0)
Aplikace 1: Analýza dopadu šumu na výstupy Circuit
Tento příklad ukazuje, jak použít Neat ke studiu dopadu různých modelů šumu na PUBs v závislosti na hloubce Circuit spouštěním simulací v ideálních podmínkách (ideal_sim) i v podmínkách se šumem (noisy_sim). Toto může být užitečné pro nastavení očekávání ohledně kvality experimentálních výsledků před spuštěním úlohy na QPU. Více o modelech šumu se dozvíš v části Přesná a šumová simulace s primitiv Qiskit Aer.
Simulované výsledky podporují matematické operace, a proto je lze navzájem porovnávat (nebo s experimentálními výsledky) za účelem výpočtu ukazatelů kvality.
QPU může být ovlivněn různými druhy šumu. Model šumu Qiskit Aer použitý zde simuluje pouze některé z nich, a proto bude pravděpodobně méně závažný než šum na reálném QPU.
Podrobnosti o tom, jaké chyby jsou zahrnuty při inicializaci modelu šumu z QPU, najdeš v referenční dokumentaci Aer NoiseModel API.
Začni provedením ideálních a šumových klasických simulací.
# Perform a noiseless simulation
ideal_results = analyzer.ideal_sim(clifford_pubs)
print(f"Ideal results:\n {ideal_results}\n")
# Perform a noisy simulation with the backend's noise model
noisy_results = analyzer.noisy_sim(clifford_pubs)
print(f"Noisy results:\n {noisy_results}\n")
Ideal results:
NeatResult([NeatPubResult(vals=array([1., 1., 1., 1., 1., 1.])), NeatPubResult(vals=array([1., 1., 1., 1., 1., 1.])), NeatPubResult(vals=array([1., 1., 1., 1., 1., 1.])), NeatPubResult(vals=array([1., 1., 1., 1., 1., 1.])), NeatPubResult(vals=array([1., 1., 1., 1., 1., 1.])), NeatPubResult(vals=array([1., 1., 1., 1., 1., 1.]))])
Noisy results:
NeatResult([NeatPubResult(vals=array([0.99023438, 0.99609375, 0.9921875 , 0.99023438, 0.99414062,
0.99414062])), NeatPubResult(vals=array([0.984375 , 0.99414062, 0.98242188, 0.98828125, 0.98632812,
0.99414062])), NeatPubResult(vals=array([0.96679688, 0.97070312, 0.95898438, 0.97851562, 0.98046875,
0.98828125])), NeatPubResult(vals=array([0.9453125 , 0.953125 , 0.97070312, 0.96875 , 0.98242188,
0.99023438])), NeatPubResult(vals=array([0.93164062, 0.9375 , 0.953125 , 0.96875 , 0.96484375,
0.98046875])), NeatPubResult(vals=array([0.92578125, 0.921875 , 0.93359375, 0.953125 , 0.95898438,
0.9765625 ]))])
Dále proveď matematické operace pro výpočet absolutního rozdílu. Zbytek průvodce používá absolutní rozdíl jako ukazatel kvality pro porovnání ideálních výsledků s šumovými nebo experimentálními výsledky, ale lze sestavit i podobné ukazatele kvality.
Absolutní rozdíl ukazuje, že dopad šumu roste s velikostí Circuit.
# Figure of merit: Absolute difference
def rdiff(res1, re2):
r"""The absolute difference between `res1` and re2`.
--> The closer to `0`, the better.
"""
d = abs(res1 - re2)
return np.round(d.vals * 100, 2)
for idx, (ideal_res, noisy_res) in enumerate(
zip(ideal_results, noisy_results)
):
vals = rdiff(ideal_res, noisy_res)
# Print the mean absolute difference for the observables
mean_vals = np.round(np.mean(vals), 2)
print(
f"Mean absolute difference between ideal and noisy results for circuits with {all_n_layers[idx]} layers:\n {mean_vals}%\n"
)
Mean absolute difference between ideal and noisy results for circuits with 1 layers:
0.72%
Mean absolute difference between ideal and noisy results for circuits with 2 layers:
1.17%
Mean absolute difference between ideal and noisy results for circuits with 3 layers:
2.6%
Mean absolute difference between ideal and noisy results for circuits with 4 layers:
3.16%
Mean absolute difference between ideal and noisy results for circuits with 5 layers:
4.4%
Mean absolute difference between ideal and noisy results for circuits with 6 layers:
5.5%
Pro zlepšení Circuit tohoto typu můžeš dodržovat tato přibližná a zjednodušená pravidla:
- Pokud je střední absolutní rozdíl větší než 90 %, mitigace pravděpodobně nepomůže.
- Pokud je střední absolutní rozdíl menší než 90 %, Probabilistic Error Amplification (PEA) pravděpodobně dokáže zlepšit výsledky.
- Pokud je střední absolutní rozdíl menší než 80 %, ZNE s Gate foldingem také pravděpodobně dokáže zlepšit výsledky.
Protože všechny výše uvedené absolutní rozdíly jsou menší než 90 %, použití PEA na původní Circuit by mělo zlepšit kvalitu jeho výsledků. V analyzátoru můžeš specifikovat různé modely šumu. Následující příklad provede stejný test, ale přidá vlastní model šumu.
# Set up a noise model with strength 0.02 on every two-qubit gate
noise_model = NoiseModel()
for qubits in backend.coupling_map:
noise_model.add_quantum_error(
depolarizing_error(0.02, 2), ["ecr", "cx"], qubits
)
# Update the analyzer's noise model
analyzer.noise_model = noise_model
# Perform a noiseless simulation
ideal_results = analyzer.ideal_sim(clifford_pubs)
# Perform a noisy simulation with the backend's noise model
noisy_results = analyzer.noisy_sim(clifford_pubs)
# Compare the results
for idx, (ideal_res, noisy_res) in enumerate(
zip(ideal_results, noisy_results)
):
values = rdiff(ideal_res, noisy_res)
# Print the mean absolute difference for the observables
mean_values = np.round(np.mean(values), 2)
print(
f"Mean absolute difference between ideal and noisy results for circuits with {all_n_layers[idx]} layers:\n {mean_values}%\n"
)
Mean absolute difference between ideal and noisy results for circuits with 1 layers:
0.0%
Mean absolute difference between ideal and noisy results for circuits with 2 layers:
0.0%
Mean absolute difference between ideal and noisy results for circuits with 3 layers:
0.0%
Mean absolute difference between ideal and noisy results for circuits with 4 layers:
0.0%
Mean absolute difference between ideal and noisy results for circuits with 5 layers:
0.0%
Mean absolute difference between ideal and noisy results for circuits with 6 layers:
0.0%
Jak je vidět, při daném modelu šumu můžeš před spuštěním PUBs na QPU zkusit kvantifikovat dopad šumu na (Cliffordizovanou verzi) PUBs zájmu.
Aplikace 2: Porovnání různých strategií
Tento příklad používá Neat k identifikaci nejlepších možností pro tvoje PUBs. K tomu zvažuj spuštění problému odhadování s PEA, který nelze simulovat pomocí qiskit_aer. Můžeš použít Neat k určení, které faktory zesílení šumu budou fungovat nejlépe, a poté tyto faktory použít při spuštění původního experimentu na QPU.
# Generate a circuit with six qubits and six layers
isa_qc = pm.run(generate_circuit(6, 3))
# Use the same observables as previously
pubs = [(isa_qc, isa_obs)]
clifford_pubs = analyzer.to_clifford(pubs)
noise_factors = [
[1, 1.1],
[1, 1.1, 1.2],
[1, 1.5, 2],
[1, 1.5, 2, 2.5, 3],
[1, 4],
]
# Run the PUBs on a QPU
estimator = Estimator(backend)
estimator.options.default_shots = 100000
estimator.options.twirling.enable_gates = True
estimator.options.twirling.enable_measure = True
estimator.options.twirling.shots_per_randomization = 100
estimator.options.resilience.measure_mitigation = True
estimator.options.resilience.zne_mitigation = True
estimator.options.resilience.zne.amplifier = "pea"
jobs = []
for factors in noise_factors:
estimator.options.resilience.zne.noise_factors = factors
jobs.append(estimator.run(clifford_pubs))
results = [job.result() for job in jobs]
# Perform a noiseless simulation
ideal_results = analyzer.ideal_sim(clifford_pubs)
# Look at the mean absolute difference to quickly tell the best choice for your options
for factors, res in zip(noise_factors, results):
d = rdiff(ideal_results[0], res[0])
print(
f"Mean absolute difference for factors {factors}:\n {np.round(np.mean(d), 2)}%\n"
)
Mean absolute difference for factors [1, 1.1]:
6.83%
Mean absolute difference for factors [1, 1.1, 1.2]:
8.76%
Mean absolute difference for factors [1, 1.5, 2]:
8.03%
Mean absolute difference for factors [1, 1.5, 2, 2.5, 3]:
10.17%
Mean absolute difference for factors [1, 4]:
8.02%
Výsledek s nejmenším rozdílem naznačuje, které možnosti zvolit.
Další kroky
- Zjisti více o přesné a šumové simulaci s primitiv Qiskit Aer.
- Zjisti více o dostupných možnostech Qiskit Runtime.
- Zjisti více o technikách mitigace a potlačení chyb.
- Navštiv téma Transpilace s pass managery.
- Zjisti, jak transpilovat Circuit jako součást pracovních postupů Qiskit patterns pomocí Qiskit Runtime.
- Přečti si dokumentaci API nástrojů pro ladění.