Pagputol ng circuit para sa pagbawas ng lalim
Tinantyang paggamit: Walong minuto sa isang Eagle processor (PAUNAWA: Ito ay tantiya lamang. Maaaring mag-iba ang inyong runtime.)
Pinagmulanβ
Ipinakikita ng tutorial na ito kung paano bumuo ng Qiskit pattern para sa pagputol ng mga gate sa quantum circuit upang bawasan ang lalim ng circuit. Para sa mas malalim na talakayan tungkol sa pagputol ng circuit, bisitahin ang circuit cutting Qiskit addon docs.
Mga Kinakailanganβ
Bago magsimula sa tutorial na ito, siguraduhing mayroon kayong naka-install na sumusunod:
- Qiskit SDK v2.0 o mas bago, na may suportang visualization
- Qiskit Runtime v0.22 o mas bago (
pip install qiskit-ibm-runtime) - Circuit cutting Qiskit addon v0.9.0 o mas bago (
pip install qiskit-addon-cutting)
Pag-setupβ
# Added by doQumentation β required packages for this notebook
!pip install -q numpy qiskit qiskit-addon-cutting qiskit-ibm-runtime
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
Hakbang 1: Magtakda ng classical inputs sa quantum problemβ
Isasagawa natin ang ating Qiskit pattern gamit ang apat na hakbang na nakabalangkas sa docs. Sa kasong ito, sisimulahin natin ang mga expectation value sa isang circuit na may tiyak na lalim sa pamamagitan ng pagputol ng mga gate na nagreresulta sa swap gates at pagsasagawa ng mga subexperiment sa mas mababaw na mga circuit. Ang pagputol ng gate ay nauugnay sa Hakbang 2 (mag-optimize ng circuit para sa quantum execution sa pamamagitan ng pagbubukod ng mga malayong gate) at 4 (post-processing upang muling itayo ang mga expectation value sa orihinal na circuit). Sa unang hakbang, bubuo tayo ng circuit mula sa Qiskit circuit library at magtakda ng ilang mga observable.
- Input: Mga classical parameter upang tukuyin ang isang circuit
- Output: Abstract circuit at mga observable
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")
Hakbang 2: I-optimize ang problema para sa quantum hardware executionβ
- Input: Abstract circuit at mga observable
- Output: Target circuit at mga observable na ginawa sa pamamagitan ng pagputol ng mga malayong gate upang bawasan ang transpiled circuit depth
Pumipili tayo ng paunang layout na nangangailangan ng dalawang swap upang maisagawa ang mga gate sa pagitan ng mga qubit 3 at 0 at isa pang dalawang swap upang ibalik ang mga qubit sa kanilang mga paunang posisyon. Pumipili tayo ng optimization_level=3, na siyang pinakamataas na antas ng optimization na magagamit sa preset pass manager.
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)

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
Hanapin at putulin ang mga malayong gate: Papalitan natin ang mga malayong gate (mga gate na nag-uugnay ng mga non-local qubit, 0 at 3) ng mga TwoQubitQPDGate object sa pamamagitan ng pagtukoy ng kanilang mga indise. Ang cut_gates ay papalitan ang mga gate sa tinukoy na mga indise ng mga TwoQubitQPDGate object at magbabalik din ng listahan ng mga QPDBasis instance -- isa para sa bawat gate decomposition. Ang QPDBasis object ay naglalaman ng impormasyon tungkol sa kung paano bubuuin ang mga pinutol na gate sa mga single-qubit operation.
# 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)
Bumuo ng mga subexperiment na isasagawa sa backend: Tumatanggap ang generate_cutting_experiments ng circuit na naglalaman ng mga TwoQubitQPDGate instance at mga observable bilang PauliList.
Upang simulahin ang expectation value ng buong circuit, maraming subexperiment ang nabubuo mula sa joint quasiprobability distribution ng mga nabukod na gate at pagkatapos ay isinasagawa sa isa o higit pang mga backend. Ang bilang ng mga sample na kinuha mula sa distribusyon ay kontrolado ng num_samples, at isang pinagsama na coefficient ang ibinibigay para sa bawat natatanging sample. Para sa higit pang impormasyon tungkol sa kung paano kinakalkula ang mga coefficient, sumangguni sa explanatory material.
# Generate the subexperiments and sampling coefficients
subexperiments, coefficients = generate_cutting_experiments(
circuits=qpd_circuit, observables=observables, num_samples=np.inf
)
Para sa paghahambing, nakikita natin na ang mga QPD subexperiment ay magiging mas mababa pagkatapos ng pagputol ng mga malayong gate: Narito ang isang halimbawa ng isang arbitraryong piniling subexperiment na nabuo mula sa QPD circuit. Ang lalim nito ay nabawasan ng higit sa kalahati. Maraming ganitong probabilistic subexperiment ang dapat buuin at suriin upang muling itayo ang expectation value ng mas malalim na circuit.
# 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
Sa kabilang banda, ang pagputol ay nagreresulta sa pangangailangan ng karagdagang sampling. Dito ay pinutol natin ang tatlong CNOT gate, na nagreresulta sa sampling overhead na . Para sa higit pa tungkol sa sampling overhead na dala ng pagputol ng circuit, sumangguni sa Circuit Knitting Toolbox documentation.
print(f"Sampling overhead: {np.prod([basis.overhead for basis in bases])}")
Sampling overhead: 729.0
Hakbang 3: Isagawa gamit ang Qiskit primitivesβ
Isagawa ang mga target circuit ("subexperiments") gamit ang Sampler Primitive.
- Input: Mga target circuit
- Output: Mga quasi-probability distribution
# Transpile the subexperiments to the backend's instruction set architecture (ISA)
isa_subexperiments = pm.run(subexperiments)
# Set up the Qiskit Runtime Sampler primitive. For a fake backend, this will use a local simulator.
sampler = SamplerV2(backend)
# Submit the subexperiments
job = sampler.run(isa_subexperiments)
# Retrieve the results
results = job.result()
print(job.job_id())
czypg1r6rr3g008mgp6g
Hakbang 4: Mag-post-process at ibalik ang resulta sa nais na classical formatβ
Gamitin ang mga resulta ng subexperiment, mga subobservable, at mga sampling coefficient upang muling itayo ang expectation value ng orihinal na circuit.
Input: Mga quasi-probability distribution Output: Muling itinayong mga expectation value
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
Survey ng tutorialβ
Mangyaring sagutin ang maikling survey na ito upang magbigay ng feedback sa tutorial na ito. Ang inyong mga pananaw ay makakatulong sa amin na mapabuti ang aming mga content offering at karanasan ng user.