Přeskočit na hlavní obsah
Tento projekt je v betě. Našel jsi chybu? Otevřít issue na GitHubu. Máš otázku nebo nápad? Zeptej se v Discussions — rádi si poslechneme tvou zpětnou vazbu!
Jaká je kvalita překladu na této stránce?

Krájení Circuit pro snížení hloubky

Odhad využití: osm minut na procesoru Eagle (POZNÁMKA: Jedná se pouze o odhad. Skutečná doba běhu se může lišit.)

Pozadí​

Tento tutoriál ukazuje, jak sestavit Qiskit pattern pro krájení Gate v kvantovém Circuit za účelem snížení hloubky Circuit. Podrobnější diskusi o circuit cutting najdeš v dokumentaci doplňku Qiskit pro circuit cutting.

Požadavky​

Před zahájením tohoto tutoriálu se ujisti, že máš nainstalováno následující:

  • Qiskit SDK v2.0 nebo novější, s podporou vizualizace
  • Qiskit Runtime v0.22 nebo novější (pip install qiskit-ibm-runtime)
  • Doplněk Qiskit pro circuit cutting v0.9.0 nebo novější (pip install qiskit-addon-cutting)

Nastavení​

# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util

_needed = {"numpy": "numpy", "qiskit": "qiskit", "qiskit_addon_cutting": "qiskit-addon-cutting", "qiskit_ibm_runtime": "qiskit-ibm-runtime"}
_missing = [pip for module, pip in _needed.items()
if importlib.util.find_spec(module) is None]
# One at a time, so a package that fails to install does not block the others
for _pip in _missing:
%pip install -q {_pip}
if not _missing:
print("\u2713 All required packages are installed")
import numpy as np

from qiskit.circuit.library import EfficientSU2
from qiskit.quantum_info import PauliList, Statevector, SparsePauliOp
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager

from qiskit_addon_cutting import (
cut_gates,
generate_cutting_experiments,
reconstruct_expectation_values,
)

from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2

Krok 1: Mapování klasických vstupů na kvantový problém​

Náš Qiskit pattern implementujeme pomocí čtyř kroků popsaných v dokumentaci. V tomto případě budeme simulovat střední hodnoty na obvodu určité hloubky tím, že rozřízneme Gate, které by jinak vyžadovaly swap gate, a spustíme dílčí experimenty na mělčích Circuit. Krájení Gate je relevantní pro kroky 2 (optimalizace Circuit pro kvantové spuštění rozkladem vzdálených Gate) a 4 (post-processing pro rekonstrukci středních hodnot na původním Circuit). V prvním kroku vygenerujeme Circuit z knihovny Qiskit a definujeme některé observovatelné.

  • Vstup: Klasické parametry pro definici Circuit

  • Výstup: Abstraktní Circuit a observovatelné

circuit = EfficientSU2(num_qubits=4, entanglement="circular").decompose()
circuit.assign_parameters([0.4] * len(circuit.parameters), inplace=True)
observables = PauliList(["ZZII", "IZZI", "IIZZ", "XIXI", "ZIZZ", "IXIX"])
circuit.draw("mpl", scale=0.8, style="iqp")

Output of the previous code cell

Krok 2: Optimalizace problému pro spuštění na kvantovém hardwaru​

  • Vstup: Abstraktní Circuit a observovatelné

  • Výstup: Cílový Circuit a observovatelné vzniklé krájením vzdálených Gate za účelem snížení hloubky transpilovánného Circuit

Zvolíme počáteční rozvržení, které vyžaduje dva swapy pro provedení Gate mezi qubit 3 a 0, a další dva swapy pro návrat qubit do jejich počátečních pozic. Zvolíme optimization_level=3, což je nejvyšší úroveň optimalizace dostupná s přednastaveným pass managerem.

service = QiskitRuntimeService()
backend = service.least_busy(
operational=True, min_num_qubits=circuit.num_qubits, simulator=False
)

pm = generate_preset_pass_manager(
optimization_level=3, initial_layout=[0, 1, 2, 3], backend=backend
)
transpiled_qc = pm.run(circuit)

Coupling map showing the qubits that will need to be swapped

print(f"Transpiled circuit depth: {transpiled_qc.depth()}")
transpiled_qc.draw("mpl", scale=0.4, idle_wires=False, style="iqp", fold=-1)
Transpiled circuit depth: 103

Output of the previous code cell

Nalezení a krájení vzdálených Gate: Vzdálené Gate (Gate spojující nelokální qubit 0 a 3) nahradíme objekty TwoQubitQPDGate zadáním jejich indexů. cut_gates nahradí Gate na zadaných indexech objekty TwoQubitQPDGate a také vrátí seznam instancí QPDBasis — jeden pro každý rozklad Gate. Objekt QPDBasis obsahuje informace o tom, jak rozložit nakrájené Gate na jednoqubitové operace.

# Find the indices of the distant gates
cut_indices = [
i
for i, instruction in enumerate(circuit.data)
if {circuit.find_bit(q)[0] for q in instruction.qubits} == {0, 3}
]

# Decompose distant CNOTs into TwoQubitQPDGate instances
qpd_circuit, bases = cut_gates(circuit, cut_indices)

qpd_circuit.draw("mpl", scale=0.8)

Output of the previous code cell

Generování dílčích experimentů pro spuštění na Backend: generate_cutting_experiments přijímá Circuit obsahující instance TwoQubitQPDGate a observovatelné jako PauliList.

Aby bylo možné simulovat střední hodnotu Circuit plné velikosti, generuje se ze sdruženého kvazipravděpodobnostního rozdělení rozložených Gate mnoho dílčích experimentů, které se pak spouštějí na jednom nebo více Backend. Počet vzorků odebraných z rozdělení je řízen parametrem num_samples a pro každý jedinečný vzorek je uveden jeden kombinovaný koeficient. Více informací o výpočtu koeficientů najdeš ve vysvětlujícím materiálu.

# Generate the subexperiments and sampling coefficients
subexperiments, coefficients = generate_cutting_experiments(
circuits=qpd_circuit, observables=observables, num_samples=np.inf
)

Pro srovnání vidíme, že dílčí experimenty QPD budou po nakrájení vzdálených Gate mělčí: Zde je příklad libovolně zvoleného dílčího experimentu generovaného z QPD Circuit. Jeho hloubka se snížila o více než polovinu. Aby bylo možné rekonstruovat střední hodnotu hlubšího Circuit, musí být vygenerováno a vyhodnoceno mnoho těchto pravděpodobnostních dílčích experimentů.

# Transpile the decomposed circuit to the same layout
transpiled_qpd_circuit = pm.run(subexperiments[100])

print(f"Original circuit depth after transpile: {transpiled_qc.depth()}")
print(
f"QPD subexperiment depth after transpile: {transpiled_qpd_circuit.depth()}"
)
transpiled_qpd_circuit.draw(
"mpl", scale=0.6, style="iqp", idle_wires=False, fold=-1
)
Original circuit depth after transpile: 103
QPD subexperiment depth after transpile: 46

Output of the previous code cell

Na druhou stranu krájení vede k potřebě extra vzorkování. Zde nakrájíme tři CNOT Gate, čímž vznikne režie vzorkování 939^3. Více o režii vzorkování způsobené circuit cutting najdeš v dokumentaci Circuit Knitting Toolbox.

print(f"Sampling overhead: {np.prod([basis.overhead for basis in bases])}")
Sampling overhead: 729.0

Krok 3: Spuštění pomocí primitiv Qiskit​

Spusť cílové Circuit ("dílčí experimenty") pomocí primitivy Sampler.

  • Vstup: Cílové Circuit

  • Výstup: Kvazipravděpodobnostní rozdělení

# Transpile the subexperiments to the backend's instruction set architecture (ISA)
isa_subexperiments = pm.run(subexperiments)

# Set up the IBM Quantum Sampler primitive. For a fake backend, this will use a local simulator.
sampler = SamplerV2(backend)
sampler.options.environment.job_tags = ["TUT_CCDR"]

# Submit the subexperiments
job = sampler.run(isa_subexperiments)
# Retrieve the results
results = job.result()
print(job.job_id())
czypg1r6rr3g008mgp6g

Krok 4: Post-processing a vrácení výsledku v požadovaném klasickém formátu​

Pomocí výsledků dílčích experimentů, dílčích observovatelných a vzorkovacích koeficientů rekonstruuj střední hodnotu původního Circuit.

Vstup: Kvazipravděpodobnostní rozdělení Výstup: Rekonstruované střední hodnoty

reconstructed_expvals = reconstruct_expectation_values(
results,
coefficients,
observables,
)
# Reconstruct final expectation value
final_expval = np.dot(reconstructed_expvals, [1] * len(observables))
print("Final reconstructed expectation value")
print(final_expval)
Final reconstructed expectation value
1.0751342773437473
ideal_expvals = [
Statevector(circuit).expectation_value(SparsePauliOp(observable))
for observable in observables
]
print("Ideal expectation value")
print(np.dot(ideal_expvals, [1] * len(observables)).real)
Ideal expectation value
1.2283177520039992

Průzkum k tutoriálu​

Prosím, vyplň tento krátký průzkum a poskytni zpětnou vazbu k tomuto tutoriálu. Tvoje poznatky nám pomohou zlepšit naši nabídku obsahu a uživatelský zážitek.

Poznámka: Tento průzkum pochází od IBM Quantum a týká se obsahu tutoriálu (napsaného IBM). doQumentation poskytuje web, překlady a spouštění kódu – pro zpětnou vazbu k těmto oblastem prosím otevři GitHub issue.

Odkaz na průzkum