Lumaktaw sa pangunahing nilalaman

Circuit cutting para sa periodic boundary conditions

Tantiya sa paggamit: Dalawang minuto sa isang Eagle processor (PAALALA: Ito ay isang tantiya lamang. Maaaring mag-iba ang inyong runtime.)

Background​

Sa notebook na ito, isasaalang-alang natin ang simulation ng isang periodic chain ng mga qubit kung saan may two qubit operation sa pagitan ng bawat dalawang magkatabi na mga qubit, kabilang ang una at ang huli. Ang mga periodic chain ay madalas makita sa mga problema sa physics at chemistry tulad ng Ising models at molecular simulation.

Ang kasalukuyang mga IBM Quantum® device ay planar. Posible na mag-embed ng ilang periodic chains sa topology nang direkta kung saan ang una at huling mga qubit ay magkapitbahay. Gayunpaman, para sa sapat na malalaking problema, ang una at huling mga qubit ay maaaring malayong magkalayo, kaya naman nangangailangan ng maraming SWAP gates para sa 2-qubit operation sa pagitan ng dalawang qubit na ito. Ang ganitong periodic boundary problem ay pinag-aralan sa papel na ito.

Sa notebook na ito ipapakita natin ang paggamit ng circuit cutting upang harapin ang ganitong utility scale periodic chain problem kung saan ang una at huling mga qubit ay hindi magkapitbahay. Ang pagputol sa long range connectivity na ito ay nag-iiwas sa extra SWAP gates sa gastos ng pag-execute ng maraming instances ng circuit, at ilang classical post-processing. Sa buod, ang cutting ay maaaring isama upang lohikal na kalkulahin ang malayo na 2-qubit operations. Sa ibang salita, ang diskarteng ito ay humahantong sa epektibong pagtaas sa connectivity ng coupling map, kaya naman humahantong sa mas kaunting bilang ng SWAP gates.

Tandaan na may dalawang uri ng cuts - ang pagputol sa wire ng isang circuit (tinatawag na wire cutting), o ang pagpapalit ng 2-qubit gate ng maraming single qubit operations (tinatawag na gate cutting). Sa notebook na ito, tutuklasin natin ang gate cutting. Para sa mas detalyadong impormasyon tungkol sa gate cutting, sumangguni sa explanatory materials sa qiskit-addon-cutting, at sa kaukulang mga reperensya. Para sa mas detalyadong impormasyon tungkol sa wire cutting, sumangguni sa Wire cutting for expectation values estimation tutorial, o sa mga tutorials sa qiskit-addon-cutting.

Requirements​

Bago simulan ang tutorial na ito, siguruhing mayroon kayong mga sumusunod na naka-install:

  • Qiskit SDK v1.2 o mas bago (pip install qiskit)
  • Qiskit Runtime v0.3 o mas bago (pip install qiskit-ibm-runtime)
  • Circuit cutting Qiskit addon v.9.0 o mas bago (pip install qiskit-addon-cutting)

Setup​

# 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

Step 1: Map classical inputs to a quantum problem​

Dito, bubuo tayo ng TwoLocal circuit at magtatakda ng ilang observables.

  • Input: Mga parameter upang lumikha ng circuit
  • Output: Abstract circuit at observables

Isasaalang-alang natin ang isang hardware-efficient na entangler map para sa TwoLocal circuit na may periodic connectivity sa pagitan ng huli at ng unang mga qubit ng entangler map. Ang long range interaction na ito ay maaaring humantong sa extra SWAP gates sa panahon ng transpilation, kaya naman tumataas ang lalim ng circuit.

Select backend and initial layout​

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

Para sa notebook na ito isasaalang-alang natin ang isang 109 qubit periodic 1D chain, na siyang pinakamahabang 1D chain sa topology ng isang 127-qubit IBM Quantum device. Hindi posible na ayusin ang isang 109 qubit periodic chain sa isang 127 qubit device na ang una at huling mga qubit ay magkapitbahay nang hindi nagsasama ng extra SWAP gates.

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

Build the entangler map for the TwoLocal circuit​

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

Ang TwoLocal circuit ay nagpapahintulot ng paulit-ulit na rotation_blocks at entangler map ng maraming beses. Para sa kasong ito, ang bilang ng mga pag-uulit ay tumutukoy sa bilang ng mga periodic gates na kailangang putulin. Dahil ang sampling overhead ay tumataas nang exponentially sa bilang ng mga cuts (sumangguni sa Wire cutting for expectation values estimation tutorial para sa mas maraming detalye), itinakda natin ang bilang ng mga pag-uulit sa 2 sa notebook na ito.

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)

Output of the previous code cell

Upang ma-verify ang kalidad ng kinalabasan gamit ang circuit cutting, kailangan nating malaman ang ideal na kinalabasan. Ang kasalukuyang circuit na pinili ay lampas sa brute force classical simulation. Samakatuwid, maingat nating itinatakda ang mga parameter sa circuit upang maging clifford ito.

Itatakda natin ang parameter value na 00 para sa unang dalawang layers ng Rx gates, at ang value na π\pi para sa huling layer. Tinitiyak nito na ang ideal na kinalabasan ng circuit na ito ay ∣1⟩⊗n|1\rangle^{\otimes n}, kung saan ang nn ay ang bilang ng mga qubit. Samakatuwid, ang mga expectation values ng ⟨Zi⟩\langle Z_i \rangle at ⟨ZiZi+1⟩\langle Z_i Z_{i+1} \rangle, kung saan ang ii ay ang index ng qubit, ay −1-1 at +1+1 ayon sa pagkakabanggit.

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)

Select observables​

Upang sukatin ang mga benepisyo ng gate cutting sinusukat natin ang mga expectation values ng mga observables na 1n∑i=1n⟨Zi⟩\frac{1}{n}\sum_{i=1}^n \langle Z_i \rangle at 1n−1∑i=1n−1⟨ZiZi+1⟩\frac{1}{n-1}\sum_{i=1}^{n-1} \langle Z_i Z_{i+1} \rangle. Gaya ng tinalakay kanina, ang mga ideal na expectation values ay −1-1 at +1+1 ayon sa pagkakabanggit.

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

Step 2: Optimize problem for quantum hardware execution​

  • Input: Abstract circuit at observables
  • Output: Target circuit at observables na ginawa sa pamamagitan ng pagputol ng long range gates

Transpile the circuit​

Tandaan na ang circuit ay maaaring i-transpile sa yugtong ito, o pagkatapos ng pagputol. Kung ating i-transpile pagkatapos ng pagputol, kailangan nating i-transpile ang bawat isa sa mga subexperiments na nabuo dahil sa sampling overhead. Samakatuwid, mas makatwiran na i-transpile sa yugtong ito upang mabawasan ang overhead ng transpilation.

Gayunpaman, kung ang transpilation ay ginawa sa yugtong ito gamit ang native hardware connectivity, ang transpiler ay magdadagdag ng maraming SWAP gates upang ilagay ang periodic 2-qubit operation – na naglilinlang sa mga benepisyo ng circuit cutting. Upang maiwasan ang problemang ito maaari nating samantalahin na alam natin ang eksaktong mga gates na kailangang putulin. Partikular, maaari tayong lumikha ng virtual coupling map sa pamamagitan ng pagdagdag ng virtual connections sa pagitan ng malayong mga qubit upang matugunan ang mga periodic 2-qubit gates na ito. Tinitiyak nito na ang circuit ay maaaring i-transpile sa yugtong ito nang hindi nagsasama ng extra SWAP gates.

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)

Output of the previous code cell

Cut the long range periodic connectivities​

Ngayon ay puputulin natin ang mga gates sa transpiled circuit. Tandaan na ang mga 2-qubit gates na kailangang putulin ay ang mga kumukonekta sa huli at sa unang mga qubit ng layout.

# 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]}
]

Ilalapat natin ang layout ng transpiled circuit sa observable.

trans_observables = observables.apply_layout(virtual_mapped_circuit.layout)

Sa wakas, ang mga subexperiments ay binubuo sa pamamagitan ng sampling sa iba't ibang measurement at preparation bases.

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,
)

Tandaan na ang pagputol sa long range interactions ay humahantong sa pag-execute ng maraming samples ng circuit na naiiba sa measurement at preparation bases. Mas maraming impormasyon tungkol dito ay matatagpuan sa Constructing a virtual two-qubit gate by sampling single-qubit operations at Cutting circuits with multiple two-qubit unitaries.

Ang bilang ng mga periodic gates na putulin ay katumbas ng bilang ng mga pag-uulit ng TwoLocal layer, na tinukoy bilang num_reps sa itaas. Ang sampling overhead ng gate cutting ay 6. Samakatuwid, ang kabuuang bilang ng mga subexperiments ay magiging 6num_reps6^{num\_reps}.

print(f"Number of subexperiments is {len(subexperiments)} = 6**{num_reps}")
Number of subexperiments is 36 = 6**2

Transpile the subexperiments​

Sa puntong ito, ang mga subexperiments ay naglalaman ng mga circuits na may ilang 1-qubit gates na wala sa basis gate set. Ito ay dahil ang mga cut qubits ay sinusukat sa iba't ibang basis, at ang mga rotation gates na ginamit para dito ay hindi kinakailangang kabilang sa basis gate set. Halimbawa, ang measurement sa X basis ay nangangahulugan ng pag-apply ng Hadamard gate bago ang karaniwang measurement sa Z basis. Ngunit ang Hadamard ay hindi bahagi ng basis gate set.

Sa halip na ilapat ang buong transpilation process sa bawat isa sa mga circuits sa mga subexperiments, maaari tayong gumamit ng mga partikular na transpilation passes. Sumangguni sa dokumentasyong ito para sa detalyadong paglalarawan ng lahat ng available na transpilation passes.

Ilalapat natin ang mga passes na BasisTranslator at pagkatapos ay Optimize1qGatesDecomposition upang matiyak na lahat ng gates sa mga circuits na ito ay kabilang sa basis gate set. Ang paggamit ng dalawang passes na ito ay mas mabilis kaysa sa buong transpilation process, dahil ang ibang mga hakbang tulad ng routing at initial layout selection ay hindi na ginagawa muli.

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
]
)

Step 3: Execute using Qiskit primitives​

  • Input: Target circuits
  • Output: Quasi-probability distributions

Gumagamit tayo ng SamplerV2 primitive para sa pag-execute ng mga cut circuits. Dini-disable natin ang dynamical decoupling at twirling upang ang anumang pagpapabuti na makukuha natin sa resulta ay dahil lamang sa epektibong paggamit ng gate cutting para sa uri ng circuit na ito.

options = SamplerOptions()
options.default_shots = 10000
options.dynamical_decoupling.enable = False
options.twirling.enable_gates = False
options.twirling.enable_measure = False

Ngayon ay isusubmit natin ang mga jobs gamit ang batch mode.

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()

Step 4: Post-process and return result in desired classical format​

  • Input: Quasi-probability distributions
  • Output: Reconstructed expectation values
reconstructed_expvals = reconstruct_expectation_values(
result,
coefficients,
paulis,
)

Ngayon ay kakalkulahin natin ang average ng weight-1 at weight-2 Z-type observables.

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

Cross Verify: Obtain uncut expectation value​

Kapaki-pakinabang na i-verify ang bentahe ng circuit cutting technique laban sa uncut. Dito ay kakalkulahin natin ang mga expectation values nang walang pagputol sa circuit. Tandaan na ang ganitong uncut circuit ay magdurusa mula sa malaking bilang ng SWAP gates na kinakailangan upang ipatupad ang 2-qubit operation sa pagitan ng una at ng huling mga qubit. Gagamitin natin ang sampled_expectation_value function upang makuha ang mga expectation values ng uncut circuit pagkatapos makuha ang probability distribution sa pamamagitan ng SamplerV2. Pinapayagan nito ang homogenous na paggamit ng primitive sa lahat ng instances. Gayunpaman, tandaan na maaari din nating gamitin ang EstimatorV2 upang direktang kalkulahin ang mga expectation values.

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()

Ngayon ay kakalkulahin natin ang average na expectation values ng lahat ng weight-1 at weight-2 Z-type observables nang walang pagputol.

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

Visualize​

Ipakita natin ngayon ang pagpapabuti na nakuha para sa weight-1 at weight-2 observables kapag gumagamit ng gate cutting para sa periodic chain 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()

Output of the previous code cell

Summary​

Sa buod, kinalkula natin ang average na expectation values ng weight-1 at weight-2 Z-types observables para sa isang periodic 1D chain ng 109 qubits. Upang magawa ito, ating

  • lumikha ng virtual coupling map sa pamamagitan ng pagdagdag ng long range connectivity sa pagitan ng una at ng huling mga qubit ng 1D chain, at i-transpile ang circuit.
    • ang transpilation sa yugtong ito ay nagpahintulot sa atin na maiwasan ang overhead ng pag-transpile ng bawat subexperiment nang hiwalay pagkatapos ng pagputol,
    • ang paggamit ng virtual coupling map ay nagpahintulot sa atin na maiwasan ang extra SWAP gates para sa 2-qubit operation sa pagitan ng una at ng huling mga qubit.
  • tinanggal ang long range connectivity mula sa transpiled circuit sa pamamagitan ng gate cutting.
  • na-convert ang mga cut circuits sa basis gate set sa pamamagitan ng paglalapat ng naaangkop na transpilation passes.
  • na-execute ang mga cut circuits sa IBM Quantum device gamit ang SamplerV2 primitive.
  • nakuha ang expectation value sa pamamagitan ng pag-reconstruct ng mga kinalabasan ng mga cut circuits.

Inference​

Napapansin natin mula sa mga resulta na ang average ng weight-1 ⟨Z⟩\langle Z \rangle at weight-2 ⟨ZZ⟩\langle ZZ \rangle type observables ay makabuluhang napabuti sa pamamagitan ng pagputol ng mga periodic gates. Tandaan na ang pag-aaral na ito ay hindi nagsasama ng anumang error suppression o mitigation techniques. Ang pagpapabuting naobserbahan ay dahil lamang sa wastong paggamit ng gate cutting para sa problemang ito. Ang mga resulta ay maaari pang mapabuti pa sa pamamagitan ng paggamit ng mitigation at suppression techniques.

Ang pag-aaral na ito ay nagpapakita ng halimbawa ng epektibong paggamit ng gate cutting upang mapabuti ang performance ng computation.

Tutorial survey​

Mangyaring sagutin ang maikling survey na ito upang magbigay ng feedback sa tutorial na ito. Ang inyong mga insight ay makakatulong sa amin na mapabuti ang aming mga content offerings at user experience.

Link to survey