Langkau ke kandungan utama

Gate Cutting untuk Mengurangkan Lebar Circuit

Dalam notebook ini, kita akan ikut langkah-langkah sebuah corak Qiskit sambil menggunakan circuit cutting untuk mengurangkan bilangan qubit dalam sebuah Circuit. Kita akan memotong gate-gate supaya kita boleh membina semula nilai jangkaan sebuah Circuit empat-qubit menggunakan eksperimen dua-qubit sahaja.

Ini adalah langkah-langkah yang akan kita ambil:

  • Langkah 1: Petakan masalah kepada circuit-circuit kuantum dan operator-operator:
    • Petakan hamiltonian ke atas sebuah circuit kuantum.
  • Langkah 2: Optimumkan untuk perkakasan sasaran [Menggunakan addon cutting]:
    • Potong Circuit dan observable.
    • Transpile subeksperimen-subeksperimen untuk perkakasan.
  • Langkah 3: Laksanakan pada perkakasan sasaran:
    • Jalankan subeksperimen-subeksperimen yang diperoleh dalam Langkah 2 menggunakan primitif Sampler.
  • Langkah 4: Proses keputusan [Menggunakan addon cutting]:
    • Gabungkan keputusan-keputusan Langkah 3 untuk membina semula nilai jangkaan observable yang berkenaan.

Langkah 1: Peta​

Buat Circuit untuk dipotong​

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

Rajah circuit kuantum

Tentukan sebuah observable​

from qiskit.quantum_info import SparsePauliOp

observable = SparsePauliOp(["ZZII", "IZZI", "-IIZZ", "XIXI", "ZIZZ", "IXIX"])

Langkah 2: Optimumkan​

Asingkan Circuit dan observable mengikut pembahagian qubit yang ditentukan​

Setiap label dalam partition_labels sepadan dengan qubit circuit pada indeks yang sama. Qubit-qubit yang berkongsi label partition yang sama akan dikumpulkan bersama, dan gate-gate bukan tempatan yang merentangi lebih daripada satu partition akan dipotong.

Nota: Argumen observables kepada partition_problem adalah jenis PauliList. Pekali dan fasa terma observable diabaikan semasa penguraian masalah dan pelaksanaan subeksperimen. Ia boleh digunakan semula semasa pembinaan semula nilai jangkaan.

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

Visualkan masalah yang telah diuraikan​

subobservables
{'A': PauliList(['II', 'ZI', 'ZZ', 'XI', 'ZZ', 'IX']),
'B': PauliList(['ZZ', 'IZ', 'II', 'XI', 'ZI', 'IX'])}
subcircuits["A"].draw("mpl", scale=0.8)

Rajah circuit kuantum

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

Rajah circuit kuantum

Kira overhead pensampelan untuk potongan yang dipilih​

Di sini kita memotong dua Gate CNOT, menghasilkan overhead pensampelan sebanyak 929^2.

Untuk maklumat lanjut tentang overhead pensampelan yang ditanggung oleh circuit cutting, rujuk bahan penerangan.

import numpy as np

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

Jana subeksperimen untuk dijalankan pada Backend​

generate_cutting_experiments menerima argumen circuits/observables sebagai kamus yang memetakan label partition qubit kepada subcircuit/subobservables masing-masing.

Untuk mensimulasikan nilai jangkaan Circuit bersaiz penuh, banyak subeksperimen dijana daripada taburan kuasiprobabiliti bersama gate-gate yang diuraikan dan kemudiannya dilaksanakan pada satu atau lebih Backend. Bilangan sampel yang diambil daripada taburan dikawal oleh num_samples, dan satu pekali gabungan diberikan bagi setiap sampel unik. Untuk maklumat lanjut tentang cara pekali dikira, rujuk bahan penerangan.

from qiskit_addon_cutting import generate_cutting_experiments

subexperiments, coefficients = generate_cutting_experiments(
circuits=subcircuits, observables=subobservables, num_samples=np.inf
)

Pilih sebuah Backend​

Di sini kita menggunakan Backend palsu, yang akan menyebabkan Qiskit Runtime berjalan dalam mod tempatan (iaitu, pada simulator tempatan).

from qiskit_ibm_runtime.fake_provider import FakeManilaV2

backend = FakeManilaV2()

Sediakan subeksperimen untuk Backend​

Kita mesti men-transpile Circuit-circuit dengan Backend kita sebagai sasaran sebelum menghantarnya ke 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()
}

Langkah 3: Laksanakan​

Jalankan subeksperimen menggunakan primitif Sampler Qiskit Runtime​

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

Langkah 4: Proses Keputusan​

Bina semula nilai jangkaan​

Bina semula nilai-nilai jangkaan bagi setiap terma observable dan gabungkannya untuk membina semula nilai jangkaan bagi observable asal.

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)

Bandingkan nilai jangkaan yang dibina semula dengan nilai jangkaan tepat daripada Circuit dan observable asal​

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