Gate Cutting para Bawasan ang Circuit Width
Sa notebook na ito, dadaan tayo sa mga hakbang ng isang Qiskit pattern habang ginagamit ang circuit cutting upang bawasan ang bilang ng mga qubit sa isang circuit. Magpuputol tayo ng mga gate upang ma-reconstruct natin ang expectation value ng isang four-qubit circuit gamit lamang ang two-qubit experiments.
Ito ang mga hakbang na gagawin natin:
- Hakbang 1: I-map ang problema sa quantum circuits at operators:
- I-map ang hamiltonian sa isang quantum circuit.
- Hakbang 2: I-optimize para sa target hardware [Ginagamit ang cutting addon]:
- Putulin ang circuit at observable.
- I-transpile ang mga subexperiment para sa hardware.
- Hakbang 3: Isagawa sa target hardware:
- Patakbuhin ang mga subexperiment na nakuha sa Hakbang 2 gamit ang isang
Samplerprimitive.
- Patakbuhin ang mga subexperiment na nakuha sa Hakbang 2 gamit ang isang
- Hakbang 4: I-post-process ang mga resulta [Ginagamit ang cutting addon]:
- Pagsamahin ang mga resulta ng Hakbang 3 upang ma-reconstruct ang expectation value ng observable na pinag-uusapan.
Hakbang 1: Mapβ
Gumawa ng circuit na puputulinβ
# Added by doQumentation β required packages for this notebook
!pip install -q numpy qiskit qiskit-addon-cutting qiskit-aer qiskit-ibm-runtime
from qiskit.circuit.library import efficient_su2
qc = efficient_su2(4, entanglement="linear", reps=2)
qc.assign_parameters([0.4] * len(qc.parameters), inplace=True)
qc.draw("mpl", scale=0.8)

Tukuyin ang isang observableβ
from qiskit.quantum_info import SparsePauliOp
observable = SparsePauliOp(["ZZII", "IZZI", "-IIZZ", "XIXI", "ZIZZ", "IXIX"])
Hakbang 2: Optimizeβ
Paghiwalayin ang circuit at observable ayon sa isang tinukoy na qubit partitioningβ
Bawat label sa partition_labels ay tumutugma sa circuit qubit sa parehong index. Ang mga qubit na naghahati ng karaniwang partition label ay pagsasama-samahin, at ang mga non-local gate na sumasaklaw sa higit sa isang partition ay puputulin.
Tandaan: Ang observables kwarg sa partition_problem ay may type na PauliList. Ang mga observable term coefficient at phase ay binabalewala sa panahon ng decomposition ng problema at execution ng mga subexperiment. Maaari silang ilapat muli sa panahon ng reconstruction ng expectation value.
from qiskit_addon_cutting import partition_problem
partitioned_problem = partition_problem(
circuit=qc, partition_labels="AABB", observables=observable.paulis
)
subcircuits = partitioned_problem.subcircuits
subobservables = partitioned_problem.subobservables
bases = partitioned_problem.bases
I-visualize ang decomposed na problemaβ
subobservables
{'A': PauliList(['II', 'ZI', 'ZZ', 'XI', 'ZZ', 'IX']),
'B': PauliList(['ZZ', 'IZ', 'II', 'XI', 'ZI', 'IX'])}
subcircuits["A"].draw("mpl", scale=0.8)

subcircuits["B"].draw("mpl", scale=0.8)

Kalkulahin ang sampling overhead para sa napiling mga cutβ
Dito, pinuputol natin ang dalawang CNOT gate, na nagreresulta sa sampling overhead na .
Para sa higit pa tungkol sa sampling overhead na nakukuha mula sa circuit cutting, sumangguni sa explanatory material.
import numpy as np
print(f"Sampling overhead: {np.prod([basis.overhead for basis in bases])}")
Sampling overhead: 81.0
Bumuo ng mga subexperiment na patatakbuhin sa backendβ
Ang generate_cutting_experiments ay tumatanggap ng circuits/observables args bilang mga dictionary na nagma-map sa qubit partition labels patungo sa mga kaukulang subcircuit/subobservables.
Upang i-simulate ang expectation value ng full-sized na circuit, maraming subexperiment ang nabubuo mula sa joint quasiprobability distribution ng mga decomposed na gate at pagkatapos ay isinasagawa sa isa o higit pang backend. Ang bilang ng mga sample na kinukuha mula sa distribution ay kinokontrol ng num_samples, at isang combined coefficient ang ibinibigay para sa bawat unique sample. Para sa karagdagang impormasyon kung paano kinakalkula ang mga coefficient, sumangguni sa explanatory material.
from qiskit_addon_cutting import generate_cutting_experiments
subexperiments, coefficients = generate_cutting_experiments(
circuits=subcircuits, observables=subobservables, num_samples=np.inf
)
Pumili ng backendβ
Dito ay gumagamit tayo ng fake backend, na magreresulta sa Qiskit Runtime na tumatakbo sa local mode (i.e., sa isang local simulator).
from qiskit_ibm_runtime.fake_provider import FakeManilaV2
backend = FakeManilaV2()
Ihanda ang mga subexperiment para sa backendβ
Kailangan nating i-transpile ang mga circuit gamit ang ating backend bilang target bago isumite ang mga ito sa Qiskit Runtime.
from qiskit.transpiler import generate_preset_pass_manager
# Transpile the subexperiments to ISA circuits
pass_manager = generate_preset_pass_manager(optimization_level=1, backend=backend)
isa_subexperiments = {
label: pass_manager.run(partition_subexpts)
for label, partition_subexpts in subexperiments.items()
}
Hakbang 3: Executeβ
Patakbuhin ang mga subexperiment gamit ang Qiskit Runtime Sampler primitiveβ
from qiskit_ibm_runtime import SamplerV2, Batch
# Submit each partition's subexperiments to the Qiskit Runtime Sampler
# primitive, in a single batch so that the jobs will run back-to-back.
with Batch(backend=backend) as batch:
sampler = SamplerV2(mode=batch)
jobs = {
label: sampler.run(subsystem_subexpts, shots=2**12)
for label, subsystem_subexpts in isa_subexperiments.items()
}
/home/garrison/Qiskit/qiskit-ibm-runtime/qiskit_ibm_runtime/session.py:157: UserWarning: Session is not supported in local testing mode or when using a simulator.
warnings.warn(
# Retrieve results
results = {label: job.result() for label, job in jobs.items()}
Hakbang 4: Post-processβ
I-reconstruct ang expectation valueβ
I-reconstruct ang expectation values para sa bawat observable term at pagsamahin ang mga ito upang ma-reconstruct ang expectation value para sa orihinal na observable.
from qiskit_addon_cutting import reconstruct_expectation_values
# Get expectation values for each observable term
reconstructed_expval_terms = reconstruct_expectation_values(
results,
coefficients,
subobservables,
)
# Reconstruct final expectation value
reconstructed_expval = np.dot(reconstructed_expval_terms, observable.coeffs)
Ikumpara ang reconstructed expectation value sa exact expectation value mula sa orihinal na circuit at observableβ
from qiskit_aer.primitives import EstimatorV2
estimator = EstimatorV2()
exact_expval = estimator.run([(qc, observable)]).result()[0].data.evs
print(f"Reconstructed expectation value: {np.real(np.round(reconstructed_expval, 8))}")
print(f"Exact expectation value: {np.round(exact_expval, 8)}")
print(f"Error in estimation: {np.real(np.round(reconstructed_expval-exact_expval, 8))}")
print(
f"Relative error in estimation: {np.real(np.round((reconstructed_expval-exact_expval) / exact_expval, 8))}"
)
Reconstructed expectation value: 0.6991539
Exact expectation value: 0.56254612
Error in estimation: 0.13660778
Relative error in estimation: 0.24283836