Circuit cutting pro periodické okrajové podmínky
Odhadovaná spotřeba: Dvě minuty na procesoru Eagle (POZNÁMKA: Jedná se pouze o odhad. Skutečná doba běhu se může lišit.)
Pozadí
V tomto notebooku uvažujeme simulaci periodického řetězce Qubitů, kde mezi každými dvěma sousedními Qubity probíhá dvouqubitová operace, včetně prvního a posledního. Periodické řetězce se často vyskytují ve fyzikáln ích a chemických problémech, jako jsou Isingovy modely a molekulární simulace.
Současná zařízení IBM Quantum® jsou planární. Na jejich topologii lze přímo vložit některé periodické řetězce, kde jsou první a poslední Qubity sousední. U dostatečně velkých problémů však mohou být první a poslední Qubity daleko od sebe, a proto je pro dvouqubitovou operaci mezi těmito dvěma Qubity potřeba mnoho hradel SWAP. Takový problém periodických okrajových podmínek byl studován v tomto článku.
V tomto notebooku ukazujeme využití circuit cutting k řešení takového problému periodického řetězce v měřítku utility, kde první a poslední Qubity nejsou sousední. Přestřižením tohoto dlouhého dosahu konektivity se vyhneme extra hradlům SWAP za cenu spuštění více instancí Circuit a klasického následného zpracování. Stručně řečeno, cutting lze začlenit pro logický výpočet dvouqubitových operací na dlouhou vzdálenost. Jinými slovy, tento přístup vede k efektivnímu zvýšení konektivity coupling mapy, a tím k menšímu počtu hradel SWAP.
Všimni si, že existují dva typy přestřižení — přestřižení drátu Circuit (tzv. wire cutting) nebo nahrazení dvouqubitového Gate více jednoQubitovými operacemi (tzv. gate cutting). V tomto notebooku se zaměříme na gate cutting. Další podrobnosti o gate cutting najdeš v vysvětlujících materiálech v qiskit-addon-cutting a v příslušných referencích. Další podrobnosti o wire cutting najdeš v tutoriálu Wire cutting pro odhad středních hodnot nebo v tutoriálech v qiskit-addon-cutting.
Požadavky
Před zahájením tohoto tutoriálu se ujisti, že máš nainstalováno následující:
- Qiskit SDK v1.2 nebo novější (
pip install qiskit) - Qiskit Runtime v0.3 nebo novější (
pip install qiskit-ibm-runtime) - Circuit cutting Qiskit addon v.9.0 nebo novější (
pip install qiskit-addon-cutting)
Nastavení
# Added by doQumentation — required packages for this notebook
!pip install -q matplotlib numpy qiskit qiskit-addon-cutting qiskit-ibm-runtime
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
from qiskit.transpiler import PassManager
from qiskit.transpiler.passes import (
BasisTranslator,
Optimize1qGatesDecomposition,
)
from qiskit.circuit.equivalence_library import (
SessionEquivalenceLibrary as sel,
)
from qiskit.converters import circuit_to_dag, dag_to_circuit
from qiskit.result import sampled_expectation_value
from qiskit.quantum_info import SparsePauliOp
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit.circuit.library import TwoLocal
from qiskit_addon_cutting import (
cut_gates,
generate_cutting_experiments,
reconstruct_expectation_values,
)
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_ibm_runtime import SamplerV2, SamplerOptions, Batch
Krok 1: Mapování klasických vstupů na kvantový problém
Zde vygenerujeme Circuit TwoLocal a definujeme některé observabily.
- Vstup: Parametry pro vytvoření Circuit
- Výstup: Abstraktní Circuit a observabily
Uvažujeme hardwarově efektivní entangler map pro Circuit TwoLocal s periodickou konektivitou mezi posledním a prvním Qubitem entangler map. Tato interakce na dlouhou vzdálenost může při transpilaci vést k extra hradlům SWAP, čímž se zvyšuje hloubka Circuit.
Výběr Backendu a počátečního rozmístění
service = QiskitRuntimeService()
backend = service.least_busy(
operational=True, simulator=False, min_num_qubits=127
)
Pro tento notebook budeme uvažovat periodický 1D řetězec o 109 Qubitech, což je nejdelší 1D řetězec v topologii 127-qubitového zařízení IBM Quantum. Na 127-qubitovém zařízení není možné uspořádat periodický řetězec o 109 Qubitech tak, aby byly první a poslední Qubity sousední, bez použití extra hradel SWAP.
init_layout = [
13,
12,
11,
10,
9,
8,
7,
6,
5,
4,
3,
2,
1,
0,
14,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
36,
51,
50,
49,
48,
47,
46,
45,
44,
43,
42,
41,
40,
39,
38,
37,
52,
56,
57,
58,
59,
60,
61,
62,
63,
64,
65,
66,
67,
68,
69,
70,
74,
89,
88,
87,
86,
85,
84,
83,
82,
81,
80,
79,
78,
77,
76,
75,
90,
94,
95,
96,
97,
98,
99,
100,
101,
102,
103,
104,
105,
106,
107,
108,
112,
126,
125,
124,
123,
122,
121,
120,
119,
118,
117,
116,
115,
114,
113,
]
# the number of qubits in the circuit is governed by the length of the initial layout
num_qubits = len(init_layout)
num_qubits
109
Sestavení entangler map pro Circuit TwoLocal
coupling_map = [(i, i + 1) for i in range(0, len(init_layout) - 1)]
coupling_map.append(
(len(init_layout) - 1, 0)
) # adding in the periodic connectivity
Circuit TwoLocal umožňuje opakování rotation_blocks a entangler map vícekrát. V tomto případě počet opakování určuje počet periodických Gate, které je nutné přestřihnout. Protože vzorkovací overhead roste exponenciálně s počtem přestřižení (více podrobností najdeš v tutoriálu Wire cutting pro odhad středních hodnot), v tomto notebooku fixujeme počet opakování na 2.
num_reps = 2
entangler_map = []
for even_edge in coupling_map[0 : len(coupling_map) : 2]:
entangler_map.append(even_edge)
for odd_edge in coupling_map[1 : len(coupling_map) : 2]:
entangler_map.append(odd_edge)
ansatz = TwoLocal(
num_qubits=num_qubits,
rotation_blocks="rx",
entanglement_blocks="cx",
entanglement=entangler_map,
reps=num_reps,
).decompose()
ansatz.draw("mpl", fold=-1)

Abychom mohli ověřit kvalitu výsledku pomocí circuit cutting, potřebujeme znát ideální výsledek. Zvolený Circuit přesahuje možnosti přímé klasické simulace. Proto pečlivě fixujeme parametry Circuit tak, aby byl Cliffordův.
Prvním dvěma vrstvám hradel Rx přiřadíme hodnotu parametru a poslední vrstvě hodnotu . Tím se zajistí, že ideálním výsledkem tohoto Circuit je , kde je počet Qubitů. Střední hodnoty a , kde je index Qubitu, jsou tedy resp. .
params_last_layer = [np.pi] * ansatz.num_qubits
params = [0] * (ansatz.num_parameters - ansatz.num_qubits)
params.extend(params_last_layer)
ansatz.assign_parameters(params, inplace=True)
Výběr observabilů
Abychom kvantifikovali přínosy gate cutting, měříme střední hodnoty observabilů a . Jak bylo uvedeno výše, ideální střední hodnoty jsou resp. .
observables = []
for i in range(num_qubits):
obs = "I" * (i) + "Z" + "I" * (num_qubits - i - 1)
observables.append(obs)
for i in range(num_qubits):
if i == num_qubits - 1:
obs = "Z" + "I" * (num_qubits - 2) + "Z"
else:
obs = "I" * i + "ZZ" + "I" * (num_qubits - i - 2)
observables.append(obs)
observables = SparsePauliOp(observables)
paulis = observables.paulis
coeffs = observables.coeffs
Krok 2: Optimalizace problému pro provádění na kvantovém hardwaru
- Vstup: Abstraktní Circuit a pozorovatelné veličiny
- Výstup: Cílový Circuit a pozorovatelné veličiny vzniklé řezáním hradel s dlouhým dosahem
Transpilace Circuitu
Všimni si, že Circuit lze transpilovat v této fázi nebo po řezání. Pokud transpilujeme po řezání, budeme muset transpilovat každý z dílčích experimentů vzniklých díky vzorkovací režii. Proto je rozumnější transpilovat v této fázi, aby se snížila režie transpilace.
Pokud se však transpilace provede v této fázi s nativní konektivitou hardwaru, Transpiler přidá několik hradel SWAP pro realizaci periodické 2-qubitové operace – čímž zastírá výhody řezání Circuitu. Abychom se tomuto problému vyhnuli, můžeme využít toho, že přesně víme, která hradla je třeba přeříznou. Konkrétně můžeme vytvořit virtuální coupling map přidáním virtuálních spojení mezi vzdálenými qubity tak, aby se tyto periodické 2-qubitové Gaty daly zapojit. Tím zajistíme, že Circuit lze v této fázi transpilovat bez zapojení navíc hradel SWAP.
coupling_map = backend.configuration().coupling_map
# create a virtual coupling map with long range connectivity
virtual_coupling_map = coupling_map.copy()
virtual_coupling_map.append([init_layout[-1], init_layout[0]])
virtual_coupling_map.append([init_layout[0], init_layout[-1]])
pm_virtual = generate_preset_pass_manager(
optimization_level=1,
coupling_map=virtual_coupling_map,
initial_layout=init_layout,
basis_gates=backend.configuration().basis_gates,
)
virtual_mapped_circuit = pm_virtual.run(ansatz)
virtual_mapped_circuit.draw("mpl", fold=-1, idle_wires=False)

Řezání dlouhých periodických spojení
Nyní přeřízname hradla v transpilovaném Circuitu. Všimni si, že 2-qubitové Gaty, které je třeba přeříznou, jsou ty, jež spojují poslední a první Qubit v layoutu.
# Find the indices of the distant gates
cut_indices = [
i
for i, instruction in enumerate(virtual_mapped_circuit.data)
if {virtual_mapped_circuit.find_bit(q)[0] for q in instruction.qubits}
== {init_layout[-1], init_layout[0]}
]
Layout transpilovaného Circuitu aplikujeme na pozorovatelnou veličinu.
trans_observables = observables.apply_layout(virtual_mapped_circuit.layout)
Nakonec jsou dílčí experimenty vygenerovány vzorkováním přes různé základy měření a přípravy.
qpd_circuit, bases = cut_gates(virtual_mapped_circuit, cut_indices)
subexperiments, coefficients = generate_cutting_experiments(
circuits=qpd_circuit,
observables=trans_observables.paulis,
num_samples=np.inf,
)
Všimni si, že řezání dlouhých interakcí vede ke spuštění více vzorků Circuitu, které se liší v základech měření a přípravy. Více informací o tom najdeš v Constructing a virtual two-qubit gate by sampling single-qubit operations a Cutting circuits with multiple two-qubit unitaries.
Počet periodických hradel, která je třeba přeříznou, se rovná počtu opakování vrstvy TwoLocal, definované jako num_reps výše. Vzorkovací režie řezání hradel je 6. Celkový počet dílčích experimentů tedy bude .
print(f"Number of subexperiments is {len(subexperiments)} = 6**{num_reps}")
Number of subexperiments is 36 = 6**2
Transpilace dílčích experimentů
V tomto okamžiku dílčí experimenty obsahují Circuity s některými 1-qubitovými hradly, která nepatří do sady bázových hradel. Je to proto, že přeříznuté Qubity jsou měřeny v různých základech a rotační Gaty k tomu používané nemusí nezbytně patřit do sady bázových hradel. Například měření v bázi X znamená aplikovat Hadamardovu Gate před běžným měřením v bázi Z. Hadamard ale není součástí sady bázových hradel.
Místo toho, abychom aplikovali celý transpilační proces na každý Circuit v dílčích experimentech, můžeme použít konkrétní transpilační průchody. Podrobný popis všech dostupných transpilačních průchodů najdeš v této dokumentaci.
Aplikujeme průchody BasisTranslator a pak Optimize1qGatesDecomposition, aby všechna hradla v těchto Circuitech patřila do sady bázových hradel. Použití těchto dvou průchodů je rychlejší než celý transpilační proces, protože jiné kroky, jako je směrování a výběr počátečního layoutu, se neprovádějí znovu.
pass_ = PassManager(
[Optimize1qGatesDecomposition(basis=backend.configuration().basis_gates)]
)
subexperiments = pass_.run(
[
dag_to_circuit(
BasisTranslator(sel, target_basis=backend.basis_gates).run(
circuit_to_dag(circ)
)
)
for circ in subexperiments
]
)
Krok 3: Spuštění pomocí primitiv Qiski
- Vstup: Cílové Circuity
- Výstup: Kvazi-pravděpodobnostní distribuce
Pro spuštění přeříznutých Circuitů používáme primitivu SamplerV2. Zakážeme dynamical decoupling a twirling, aby jakékoli zlepšení výsledku bylo výhradně díky efektivnímu použití řezání hradel pro tento typ Circuitu.
options = SamplerOptions()
options.default_shots = 10000
options.dynamical_decoupling.enable = False
options.twirling.enable_gates = False
options.twirling.enable_measure = False
Nyní odeslemě úlohy v dávkovém režimu.
with Batch(backend=backend) as batch:
sampler = SamplerV2(options=options)
cut_job = sampler.run(subexperiments)
print(f"Job ID {cut_job.job_id()}")
Job ID cwxf7wq60bqg008pvt8g
result = cut_job.result()
Krok 4: Následné zpracování a vrácení výsledku v požadovaném klasickém formátu
- Vstup: Kvazi-pravděpodobnostní distribuce
- Výstup: Rekonstruované střední hodnoty
reconstructed_expvals = reconstruct_expectation_values(
result,
coefficients,
paulis,
)
Nyní vypočítáme průměr pozorovatelných veličin Z-typu s váhou 1 a váhou 2.
cut_weight_1 = np.mean(reconstructed_expvals[:num_qubits])
cut_weight_2 = np.mean(reconstructed_expvals[num_qubits:])
print(f"Average of weight-1 expectation values is {cut_weight_1}")
print(f"Average of weight-2 expectation values is {cut_weight_2}")
Average of weight-1 expectation values is -0.741733944954063
Average of weight-2 expectation values is 0.6968862385320495
Křížová verifikace: Získání nepřeříznuté střední hodnoty
Je užitečné křížově ověřit výhodu techniky řezání Circuitu oproti nepřeříznutému případu. Zde vypočítáme střední hodnoty bez přeříznutí Circuitu. Všimni si, že takový nepřeříznutý Circuit bude trpět velkým počtem hradel SWAP potřebných k realizaci 2-qubitové operace mezi prvním a posledním Qubitem. Použijeme funkci sampled_expectation_value k získání středních hodnot nepřeříznutého Circuitu po získání pravděpodobnostní distribuce pomocí SamplerV2. To umožňuje homogenní použití primitiv ve všech případech. Všimni si však, že bychom mohli použít také EstimatorV2 k přímému výpočtu středních hodnot.
if ansatz.num_clbits == 0:
ansatz.measure_all()
pm_uncut = generate_preset_pass_manager(
optimization_level=1, backend=backend, initial_layout=init_layout
)
transpiled_circuit = pm_uncut.run(ansatz)
sampler = SamplerV2(mode=backend, options=options)
uncut_job = sampler.run([transpiled_circuit])
uncut_job_id = uncut_job.job_id()
print(f"The job id for the uncut clifford circuit is {uncut_job_id}")
The job id for the uncut clifford circuit is cwxfads2ac5g008jhe7g
uncut_result = uncut_job.result()[0]
uncut_counts = uncut_result.data.meas.get_counts()
Nyní vypočítáme průměrné střední hodnoty všech pozorovatelných veličin Z-typu s váhou 1 a váhou 2 bez přeříznutí.
uncut_expvals = [
sampled_expectation_value(uncut_counts, obs) for obs in paulis
]
uncut_weight_1 = np.mean(uncut_expvals[:num_qubits])
uncut_weight_2 = np.mean(uncut_expvals[num_qubits:])
print(f"Average of weight-1 expectation values is {uncut_weight_1}")
print(f"Average of weight-2 expectation values is {uncut_weight_2}")
Average of weight-1 expectation values is -0.32494128440366965
Average of weight-2 expectation values is 0.32340917431192656
Vizualizace
Nyní vizualizujeme zlepšení dosažené pro pozorovatelné veličiny s váhou 1 a váhou 2 při použití řezání hradel pro periodický řetězcový Circuit.
mpl.rcParams.update(mpl.rcParamsDefault)
fig = plt.subplots(figsize=(12, 8), dpi=200)
width = 0.25
labels = ["Weight-1", "Weight-2"]
x = np.arange(len(labels))
ideal = [-1, 1]
cut = [cut_weight_1, cut_weight_2]
uncut = [uncut_weight_1, uncut_weight_2]
br1 = np.arange(len(ideal))
br2 = [x + width for x in br1]
br3 = [x + width for x in br2]
plt.bar(
br1, ideal, width=width, edgecolor="k", label="Ideal", color="#4589ff"
)
plt.bar(br2, cut, width=width, edgecolor="k", label="Cut", color="#a56eff")
plt.bar(
br3, uncut, width=width, edgecolor="k", label="Uncut", color="#009d9a"
)
plt.axhline(y=0, color="k", linestyle="-")
plt.xticks([r + width for r in range(len(ideal))], labels, fontsize=14)
plt.yticks(fontsize=14)
plt.legend(fontsize=14)
plt.show()

Shrnutí
Stručně řečeno, vypočítali jsme průměrné střední hodnoty pozorovatelných veličin Z-typu s váhou 1 a váhou 2 pro periodický 1D řetězec 109 qubitů. Abychom toho dosáhli:
- vytvořili jsme virtuální coupling map přidáním dlouhosahové konektivity mezi první a poslední Qubit 1D řetězce a transpilovali Circuit.
- transpilace v této fázi nám umožnila vyhnout se režii transpilace každého dílčího experimentu zvlášť po přeříznutí,
- použití virtuální coupling map nám umožnilo vyhnout se navíc hradlům SWAP pro 2-qubitovou operaci mezi prvním a posledním Qubitem.
- odstranili jsme dlouhosahovou konektivitu z transpilovaného Circuitu pomocí řezání hradel.
- převedli jsme přeříznuté Circuity do sady bázových hradel aplikací příslušných transpilačních průchodů.
- spustili jsme přeříznuté Circuity na zařízení IBM Quantum pomocí primitiv
SamplerV2. - získali jsme střední hodnotu rekonstrukcí výsledků přeříznutých Circuitů.
Závěr
Ze výsledků vidíme, že průměr pozorovatelných veličin Z-typu s váhou 1 a váhou 2 je výrazně zlepšen přeříznutím periodických hradel. Všimni si, že tato studie nezahrnuje žádné techniky potlačení nebo zmírňování chyb. Pozorované zlepšení je výhradně díky správnému použití řezání hradel pro tento problém. Výsledky by mohly být dále zlepšeny použitím technik zmírňování a potlačování chyb.
Tato studie ukazuje příklad efektivního použití řezání hradel ke zlepšení výkonu výpočtu.
Průzkum k tutoriálu
Prosím, vyplň tento krátký průzkum a poskytni zpětnou vazbu k tomuto tutoriálu. Tvé postřehy nám pomohou zlepšit naši nabídku obsahu a uživatelskou zkušenost.
Note: This survey is provided by IBM Quantum and relates to the original English content. To give feedback on doQumentation's website, translations, or code execution, please open a GitHub issue.