Lewati ke konten utama

Quantum kernel dengan fractional gates

Estimasi penggunaan: di bawah 30 detik pada prosesor Heron r2 (CATATAN: Ini hanya estimasi. Waktu aktual bisa berbeda.)

Hasil pembelajaran

  • Apa itu fractional gates dan bagaimana gate ini mengurangi kedalaman dan durasi circuit pada QPU IBM®

  • Batasan yang terkait dengan penggunaan fractional gates (khususnya, rentang sudut RZZ)

  • Cara membangun alur kerja quantum kernel yang menggunakan fractional gates dengan IBM Quantum Compute Service

  • Cara membandingkan metrik eksekusi perangkat keras (kedalaman, durasi, jumlah Gate non-lokal, fidelitas) dengan dan tanpa fractional gates

  • Cara menggunakan hanya fractional RX gates sambil tetap menggunakan alur kerja Qiskit patterns standar

Prasyarat

Latar Belakang

Fractional Gates pada IBM QPU

Fractional gates adalah quantum gates berparameter yang memungkinkan eksekusi langsung rotasi sudut sembarang (dalam batas tertentu), menghilangkan kebutuhan untuk menguraikannya menjadi beberapa basis gates. Dengan memanfaatkan interaksi native (asli) antar-qubit fisik, kamu dapat mengimplementasikan unitary tertentu secara lebih efisien pada perangkat keras.

IBM Quantum® Heron QPU mendukung fractional gates berikut:

  • RZZ(θ)R_{ZZ}(\theta) untuk 0<θ<π/20 < \theta < \pi / 2
  • RX(θ)R_X(\theta) untuk nilai real θ\theta apa pun

Gates ini dapat secara signifikan mengurangi kedalaman maupun durasi quantum circuit. Keunggulannya terutama terasa pada aplikasi yang banyak mengandalkan RZZR_{ZZ} dan RXR_X, seperti simulasi Hamiltonian, Quantum Approximate Optimization Algorithm (QAOA), dan metode quantum kernel. Dalam tutorial ini, kita fokus pada quantum kernel sebagai contoh praktis.

Keterbatasan

Fractional gates saat ini merupakan fitur eksperimental dan memiliki beberapa batasan:

Fractional gates memerlukan alur kerja yang berbeda dibandingkan pendekatan standar. Tutorial ini menjelaskan cara bekerja dengan fractional gates melalui aplikasi praktis.

Lihat referensi berikut untuk detail lebih lanjut tentang fractional gates.

Pendekatan alur kerja untuk batasan sudut RZZ

Alur kerja untuk menggunakan fractional gates umumnya mengikuti alur kerja Qiskit patterns. Perbedaan utamanya adalah semua sudut RZZ harus memenuhi batasan 0<θπ/20 < \theta \leq \pi/2. Ada dua pendekatan untuk memastikan kondisi ini terpenuhi, seperti yang akan kita bahas di bawah ini. Kami merekomendasikan pendekatan kedua, dan dalam tutorial ini, kita mendemonstrasikannya melalui contoh yang terinspirasi dari metode quantum kernel. Untuk lebih memahami di mana quantum kernel kemungkinan besar berguna, kami sarankan membaca Liu, Arunachalam & Temme (2021).

Kamu juga bisa mempelajari tutorial Quantum kernel training dan pelajaran Quantum kernels dalam kursus Quantum machine learning di IBM Quantum® Learning.

# Added by doQumentation — required packages for this notebook
!pip install -q matplotlib numpy qiskit qiskit-aer qiskit-basis-constructor qiskit-ibm-runtime

1. Buat nilai parameter yang memenuhi batasan sudut RZZ

Jika kamu yakin semua sudut RZZ berada dalam rentang yang valid, kamu bisa mengikuti alur kerja Qiskit patterns standar. Dalam hal ini, kamu cukup mengirimkan nilai parameter sebagai bagian dari PUB. Alur kerjanya adalah sebagai berikut.

pm = generate_preset_pass_manager(backend=backend, ...)
t_circuit = pm.run(circuit)
t_observable = observable.apply_layout(t_circuit.layout)
sampler.run([(t_circuit, parameter_values)])
estimator.run([(t_circuit, t_observable, parameter_values)])

Jika kamu mencoba mengirimkan PUB yang menyertakan gate RZZ dengan sudut di luar rentang yang valid, kamu akan menemui pesan error seperti:

'The instruction rzz is supported only for angles in the range [0, pi/2], but an angle (20.0) outside of this range has been requested; via parameter value(s) γ[0]=10.0, substituted in parameter expression 2.0*γ[0].'

Untuk menghindari error ini, gunakan pendekatan kedua yang dijelaskan di bawah.

2. Tetapkan nilai parameter ke circuit sebelum transpilasi

Paket qiskit-ibm-runtime menyediakan transpiler pass khusus bernama FoldRzzAngle. Pass ini mengubah quantum circuit agar semua sudut RZZ memenuhi batasan sudut RZZ. Jika kamu menyediakan backend ke generate_preset_pass_manager atau transpile, Qiskit secara otomatis menerapkan FoldRzzAngle ke quantum circuit. Ini mengharuskan kamu menetapkan nilai parameter ke quantum circuit sebelum transpilasi. Alur kerjanya adalah sebagai berikut.

pm = generate_preset_pass_manager(backend=backend, ...)
b_circuit = circuit.assign_parameters(parameter_values)
t_circuit = pm.run(b_circuit)
t_observable = observable.apply_layout(t_circuit.layout)
sampler.run([(t_circuit,)])
estimator.run([(t_circuit, t_observable)])

Perhatikan bahwa alur kerja ini memerlukan biaya komputasi yang lebih tinggi dibandingkan pendekatan pertama, karena melibatkan penetapan nilai parameter ke quantum circuit dan menyimpan circuit yang parameternya sudah terikat secara lokal.

perhatian

Perhatikan adanya masalah yang diketahui di qiskit-ibm-runtime v0.47.0 di mana Gate RZZ dengan sudut tidak valid mungkin masih ada dalam Circuit bahkan setelah transpilasi dalam skenario tertentu.

Lihat qiskit-ibm-runtime#2441 untuk memantau perkembangan masalah ini. Kami menyarankan solusi sementara berikut sampai masalah ini teratasi.

pm = generate_preset_pass_manager(backend=backend, ...)
pm.post_optimization = PassManager(
[
FoldRzzAngle(),
Optimize1qGatesDecomposition(target=backend.target),
RemoveIdentityEquivalent(target=backend.target),
]
)
... = pm.run(...)

Persyaratan

Sebelum memulai tutorial ini, pastikan kamu sudah menginstal hal-hal berikut:

  • Qiskit SDK v2.0 atau lebih baru, dengan dukungan visualisasi
  • Qiskit Runtime v0.41 atau lebih baru (pip install qiskit-ibm-runtime)
  • Qiskit Aer v0.17 atau lebih baru (pip install qiskit-aer)
  • Qiskit Basis Constructor (pip install qiskit_basis_constructor)

Setup

import matplotlib.pyplot as plt
import numpy as np
from qiskit import QuantumCircuit, generate_preset_pass_manager
from qiskit.circuit import ParameterVector
from qiskit.circuit.library import UGate, n_local, unitary_overlap
from qiskit.transpiler import Target, PassManager
from qiskit.transpiler.passes import (
Optimize1qGatesDecomposition,
RemoveIdentityEquivalent,
)
from qiskit_aer.primitives import SamplerV2 as AerSampler
from qiskit_basis_constructor import DEFAULT_EQUIVALENCE_LIBRARY
from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2
from qiskit_ibm_runtime.transpiler.passes import FoldRzzAngle

Aktifkan fractional gates dan periksa basis gates

Untuk menggunakan fractional gates, kamu bisa mendapatkan backend yang mendukungnya dengan mengatur opsi use_fractional_gates=True. Jika backend mendukung fractional gates, kamu akan melihat rzz dan rx tercantum di antara basis gates-nya.

service = QiskitRuntimeService()
backend = service.least_busy(
operational=True, simulator=False, min_num_qubits=133
) # backend should be a heron device or later
backend_name = backend.name
backend_c = service.backend(backend_name) # w/o fractional gates
backend_f = service.backend(
backend_name, use_fractional_gates=True
) # w/ fractional gates
print(f"Backend: {backend_name}")
print(f"No fractional gates: {backend_c.basis_gates}")
print(f"With fractional gates: {backend_f.basis_gates}")
if "rzz" not in backend_f.basis_gates:
print(f"Backend {backend_name} does not support fractional gates")
Backend: ibm_marrakesh
No fractional gates: ['cz', 'id', 'rz', 'sx', 'x']
With fractional gates: ['cz', 'id', 'rx', 'rz', 'rzz', 'sx', 'x']

Contoh simulator skala kecil

Pada bagian ini, kita akan menelusuri empat langkah alur kerja Qiskit patterns pada simulator, menggunakan quantum kernel circuit sebagai contoh praktis.

Langkah 1: Petakan input klasik ke masalah kuantum

Circuit quantum kernel

Di bagian ini, kita mengeksplorasi circuit quantum kernel menggunakan Gate RZZ untuk memperkenalkan alur kerja fractional gates.

Kita mulai dengan membangun Circuit kuantum untuk menghitung entri-entri individual dari matriks kernel. Ini dilakukan dengan menggabungkan Circuit ZZ feature map dengan unitary overlap. Fungsi kernel mengambil vektor dalam ruang yang dipetakan fitur dan mengembalikan hasil kali dalamnya sebagai entri matriks kernel: K(x,y)=Φ(x)Φ(y),K(x, y) = \langle \Phi(x) | \Phi(y) \rangle, di mana Φ(x)|\Phi(x)\rangle merepresentasikan state kuantum yang dipetakan fitur.

Kita membangun Circuit ZZ feature map secara manual menggunakan Gate RZZ. Meskipun Qiskit menyediakan zz_feature_map bawaan, fitur ini belum mendukung Gate RZZ per Qiskit v2.4.1 (lihat issue).

Selanjutnya, kita menghitung fungsi kernel untuk input yang identik — misalnya, K(x,x)=1K(x, x) = 1. Pada komputer kuantum yang bising, nilai ini bisa kurang dari 1 akibat noise. Hasil yang lebih mendekati 1 menunjukkan noise yang lebih rendah dalam eksekusi. Dalam tutorial ini, kita menyebut nilai ini sebagai fidelitas, yang didefinisikan sebagai fidelity=K(x,x).\text{fidelity} = K(x, x).

optimization_level = 2
shots = 2000
reps = 3
rng = np.random.default_rng(seed=123)
def my_zz_feature_map(num_qubits: int, reps: int = 1) -> QuantumCircuit:
x = ParameterVector("x", num_qubits * reps)
qc = QuantumCircuit(num_qubits)
qc.h(range(num_qubits))
for k in range(reps):
K = k * num_qubits
for i in range(num_qubits):
qc.rz(x[i + K], i)
pairs = [(i, i + 1) for i in range(num_qubits - 1)]
for i, j in pairs[0::2] + pairs[1::2]:
qc.rzz((np.pi - x[i + K]) * (np.pi - x[j + K]), i, j)
return qc

def quantum_kernel(num_qubits: int, reps: int = 1) -> QuantumCircuit:
qc = my_zz_feature_map(num_qubits, reps=reps)
inner_product = unitary_overlap(qc, qc, "x", "y", insert_barrier=True)
inner_product.measure_all()
return inner_product

def random_parameters(inner_product: QuantumCircuit) -> np.ndarray:
return np.tile(rng.random(inner_product.num_parameters // 2), 2)

def fidelity(result) -> float:
ba = result.data.meas
return ba.get_int_counts().get(0, 0) / ba.num_shots

Circuit quantum kernel beserta nilai parameter-nya dibuat untuk sistem dengan 4 hingga 40 qubit, lalu fidelitasnya dievaluasi.

qubits = list(range(4, 12, 2))
circuits = [quantum_kernel(i, reps=reps) for i in qubits]
params = [random_parameters(circ) for circ in circuits]

Circuit empat-Qubit divisualisasikan di bawah ini.

circuits[0].draw("mpl", fold=-1)

Output of the previous code cell

Dalam alur kerja Qiskit patterns standar, nilai parameter biasanya diteruskan ke primitif Sampler atau Estimator sebagai bagian dari PUB. Namun, ketika menggunakan Backend yang mendukung fractional gates, nilai parameter tersebut harus ditetapkan secara eksplisit ke Circuit kuantum sebelum transpilasi.

b_qc = [
circ.assign_parameters(param) for circ, param in zip(circuits, params)
]
b_qc[0].draw("mpl", fold=-1)

Output of the previous code cell

Langkah 2: Optimalkan masalah untuk eksekusi perangkat keras kuantum

Kita kemudian men-transpile Circuit menggunakan pass manager sesuai pola Qiskit standar. Dengan menyediakan Backend yang mendukung fractional gates ke generate_preset_pass_manager, sebuah pass khusus bernama FoldRzzAngle dimasukkan secara otomatis. Pass ini memodifikasi Circuit agar memenuhi batasan sudut RZZ. Hasilnya, Gate RZZ dengan nilai negatif pada gambar sebelumnya diubah menjadi nilai positif, dan beberapa Gate X tambahan ditambahkan.

backend_f = service.backend(name=backend_name, use_fractional_gates=True)
# pm_f includes `FoldRzzAngle` pass
pm_f = generate_preset_pass_manager(
optimization_level=optimization_level, backend=backend_f
)
pm_f.post_optimization = PassManager(
[
FoldRzzAngle(),
Optimize1qGatesDecomposition(target=backend_f.target),
RemoveIdentityEquivalent(target=backend_f.target),
]
)
t_qc_f = pm_f.run(b_qc)
print(t_qc_f[0].count_ops())
t_qc_f[0].draw("mpl", fold=-1)
OrderedDict({'rz': 35, 'rzz': 18, 'x': 13, 'rx': 9, 'measure': 4, 'barrier': 2})

Output of the previous code cell

Untuk menilai dampak fractional gates, kita mengevaluasi jumlah gate non-lokal (CZ dan RZZ untuk Backend ini), beserta kedalaman dan durasi Circuit, dan membandingkan metrik-metrik ini dengan alur kerja standar nanti.

nnl_f = [qc.num_nonlocal_gates() for qc in t_qc_f]
depth_f = [qc.depth() for qc in t_qc_f]
duration_f = [
qc.estimate_duration(backend_f.target, unit="u") for qc in t_qc_f
]

Langkah 3: Eksekusi menggunakan primitif Qiskit

Kita menjalankan Circuit yang sudah di-transpile dengan Backend yang mendukung fractional gates.

sampler_f = AerSampler.from_backend(backend_f)
job = sampler_f.run(t_qc_f, shots=shots)
print(job.job_id())
085ce928-767e-4200-93bf-3905e5411cfe

Langkah 4: Pasca-proses dan kembalikan hasil dalam format klasik yang diinginkan

Kamu bisa mendapatkan nilai fungsi kernel K(x,x)K(x, x) dengan mengukur probabilitas bitstring semua-nol 00...00 pada output.

result = job.result()
fidelity_f = [fidelity(result=res) for res in result]
print(fidelity_f)
[0.929, 0.882, 0.8645, 0.817]

Perbandingan alur kerja dan Circuit tanpa fractional gates

Di bagian ini, kita menyajikan alur kerja Qiskit patterns standar menggunakan Backend yang tidak mendukung fractional gates. Dengan membandingkan Circuit yang di-transpile, kamu akan melihat bahwa versi yang menggunakan fractional gates (dari bagian sebelumnya) lebih ringkas dibanding yang tanpa fractional gates.

# step 1: map classical inputs to quantum problem
# `circuits` and `params` from the previous section are reused here
# step 2: optimize circuits
backend_c = service.backend(backend_name) # w/o fractional gates
pm_c = generate_preset_pass_manager(
optimization_level=optimization_level, backend=backend_c
)
t_qc_c = pm_c.run(circuits)
print(t_qc_c[0].count_ops())
t_qc_c[0].draw("mpl", fold=-1)
OrderedDict({'rz': 130, 'sx': 80, 'cz': 36, 'measure': 4, 'barrier': 2})

Output of the previous code cell

nnl_c = [qc.num_nonlocal_gates() for qc in t_qc_c]
depth_c = [qc.depth() for qc in t_qc_c]
duration_c = [
qc.estimate_duration(backend_c.target, unit="u") for qc in t_qc_c
]
# step 3: execute
sampler_c = AerSampler.from_backend(backend_c)
job = sampler_c.run(pubs=zip(t_qc_c, params), shots=shots)
print(job.job_id())
f2cca29d-7263-4976-9e51-13a91b75c3ae
# step 4: post-processing
result = job.result()
fidelity_c = [fidelity(res) for res in result]
print(fidelity_c)
[0.8625, 0.7605, 0.702, 0.671]

Perbandingan kedalaman, durasi, dan fidelitas

Di bagian ini, kita membandingkan jumlah gate non-lokal dan fidelitas antara Circuit dengan dan tanpa fractional gates. Ini menonjolkan potensi manfaat penggunaan fractional gates dari segi efisiensi eksekusi dan kualitas.

plt.plot(qubits, depth_c, "-o", label="no fractional gates")
plt.plot(qubits, depth_f, "-o", label="with fractional gates")
plt.xlabel("number of qubits")
plt.ylabel("depth")
plt.title("Comparison of depths")
plt.grid()
plt.legend()
<matplotlib.legend.Legend at 0x116af3cb0>

Output of the previous code cell

plt.plot(qubits, duration_c, "-o", label="no fractional gates")
plt.plot(qubits, duration_f, "-o", label="with fractional gates")
plt.xlabel("number of qubits")
plt.ylabel("duration (µs)")
plt.title("Comparison of durations")
plt.grid()
plt.legend()
<matplotlib.legend.Legend at 0x11ea4f4d0>

Output of the previous code cell

plt.plot(qubits, nnl_c, "-o", label="no fractional gates")
plt.plot(qubits, nnl_f, "-o", label="with fractional gates")
plt.xlabel("number of qubits")
plt.ylabel("number of non-local gates")
plt.title("Comparison of numbers of non-local gates")
plt.grid()
plt.legend()
<matplotlib.legend.Legend at 0x1247fc440>

Output of the previous code cell

plt.plot(qubits, fidelity_c, "-o", label="no fractional gates")
plt.plot(qubits, fidelity_f, "-o", label="with fractional gates")
plt.xlabel("number of qubits")
plt.ylabel("fidelity")
plt.title("Comparison of fidelities")
plt.grid()
plt.legend()
<matplotlib.legend.Legend at 0x120b792b0>

Output of the previous code cell

Contoh perangkat keras skala besar

Pada bagian ini, kita melakukan benchmark terhadap alur kerja quantum kernel dengan dan tanpa fractional gates pada perangkat keras kuantum dengan hingga 40 qubit.

Langkah 1-4 digabungkan

Alur kerja ini mengikuti struktur yang sama dengan contoh skala kecil. Kita men-transpile semua circuit dengan dan tanpa fractional gates, mengumpulkan metrik, kemudian mengirimkan circuit ke perangkat keras kuantum sungguhan.

# -------------------------Step 1-------------------------
qubits = list(range(4, 44, 4))
circuits = [quantum_kernel(i, reps=reps) for i in qubits]
params = [random_parameters(circ) for circ in circuits]
b_qc = [
circ.assign_parameters(param) for circ, param in zip(circuits, params)
]

def benchmark(b_qc, backend):
# -------------------------Step 2-------------------------
pm = generate_preset_pass_manager(optimization_level, backend=backend)
if "rzz" in backend.target.operation_names:
# workaround until https://github.com/Qiskit/qiskit-ibm-runtime/issues/2441 is resolved
pm.post_optimization = PassManager(
[
FoldRzzAngle(),
Optimize1qGatesDecomposition(target=backend.target),
RemoveIdentityEquivalent(target=backend.target),
]
)
t_qc = pm.run(b_qc)
nnl = [qc.num_nonlocal_gates() for qc in t_qc]
depth = [qc.depth() for qc in t_qc]
duration = [
qc.estimate_duration(backend_f.target, unit="u") for qc in t_qc
]

# -------------------------Step 3-------------------------
sampler = SamplerV2(mode=backend)
sampler.options.dynamical_decoupling.enable = True
sampler.options.dynamical_decoupling.sequence_type = "XY4"
sampler.options.dynamical_decoupling.skip_reset_qubits = True
sampler.options.environment.job_tags = ["TUT_FG"]
job = sampler.run(t_qc, shots=shots)
job_id = job.job_id()
return nnl, depth, duration, job_id

def postprocessing(job_id: str):
# -------------------------Step 4-------------------------
job = service.job(job_id)
result = job.result()
fidelities = [fidelity(result=res) for res in result]
usage = job.usage()
return fidelities, usage

backend_f = service.backend(backend_name, use_fractional_gates=True)
nnl_f, depth_f, duration_f, job_id_f = benchmark(
b_qc, backend_f
) # step 2 & 3
print("job id (w/ fractional gates):", job_id_f)
fidelity_f, usage_f = postprocessing(job_id_f) # step 4
job id (w/ fractional gates): d8uasitbh0os73eqnpig
backend_c = service.backend(backend_name, use_fractional_gates=False)
nnl_c, depth_c, duration_c, job_id_c = benchmark(b_qc, backend_c)
print("job id (w/o fractional gates):", job_id_c)
fidelity_c, usage_c = postprocessing(job_id_c)
job id (w/o fractional gates): d8uav3lposuc738pruug

Kemudian kita membandingkan metrik.

plt.plot(qubits, depth_c, "-o", label="no fractional gates")
plt.plot(qubits, depth_f, "-o", label="with fractional gates")
plt.xlabel("number of qubits")
plt.ylabel("depth")
plt.title("Comparison of depths")
plt.grid()
plt.legend()
<matplotlib.legend.Legend at 0x12461e660>

Output of the previous code cell

plt.plot(qubits, duration_c, "-o", label="no fractional gates")
plt.plot(qubits, duration_f, "-o", label="with fractional gates")
plt.xlabel("number of qubits")
plt.ylabel("duration (µs)")
plt.title("Comparison of durations")
plt.grid()
plt.legend()
<matplotlib.legend.Legend at 0x11f2ac980>

Output of the previous code cell

plt.plot(qubits, nnl_c, "-o", label="no fractional gates")
plt.plot(qubits, nnl_f, "-o", label="with fractional gates")
plt.xlabel("number of qubits")
plt.ylabel("number of non-local gates")
plt.title("Comparison of numbers of non-local gates")
plt.grid()
plt.legend()
<matplotlib.legend.Legend at 0x125c91be0>

Output of the previous code cell

plt.plot(qubits, fidelity_c, "-o", label="no fractional gates")
plt.plot(qubits, fidelity_f, "-o", label="with fractional gates")
plt.xlabel("number of qubits")
plt.ylabel("fidelity")
plt.title("Comparison of fidelities")
plt.grid()
plt.legend()
<matplotlib.legend.Legend at 0x11fcf6e40>

Output of the previous code cell

Kita membandingkan waktu penggunaan QPU dengan dan tanpa fractional gates. Hasil pada sel berikut menunjukkan bahwa waktu penggunaan QPU hampir identik.

print(f"no fractional gates: {usage_c} seconds")
print(f"fractional gates: {usage_f} seconds")
no fractional gates: 8 seconds
fractional gates: 8 seconds

Topik lanjutan: Menggunakan hanya fractional RX gates

Kebutuhan alur kerja yang dimodifikasi saat menggunakan fractional gates terutama berasal dari pembatasan sudut Gate RZZ. Namun, jika kamu hanya menggunakan fractional RX gates dan mengecualikan fractional RZZ gates, kamu tetap bisa mengikuti alur kerja Qiskit patterns standar. Pendekatan ini masih bisa memberikan manfaat yang berarti, terutama pada Circuit yang banyak menggunakan Gate RX dan Gate U, dengan mengurangi jumlah gate keseluruhan dan berpotensi meningkatkan performa. Di bagian ini, kita menunjukkan cara mengoptimalkan Circuit menggunakan hanya fractional RX gates, tanpa Gate RZZ.

Untuk mendukung ini, kita menyediakan fungsi utilitas yang memungkinkan kamu menonaktifkan basis gate tertentu dalam objek Target. Di sini, kita menggunakannya untuk menonaktifkan Gate RZZ.

def remove_instruction_from_target(target: Target, gate_name: str) -> Target:
new_target = Target(
description=target.description,
num_qubits=target.num_qubits,
dt=target.dt,
granularity=target.granularity,
min_length=target.min_length,
pulse_alignment=target.pulse_alignment,
acquire_alignment=target.acquire_alignment,
qubit_properties=target.qubit_properties,
concurrent_measurements=target.concurrent_measurements,
)

for name, qarg_map in target.items():
if name == gate_name:
continue
instruction = target.operation_from_name(name)
if qarg_map == {None: None}:
qarg_map = None
new_target.add_instruction(instruction, qarg_map, name=name)
return new_target

Kita menggunakan Circuit yang terdiri dari Gate U, CZ, dan RZZ sebagai contoh.

qc = n_local(3, "u", "cz", "linear", reps=1)
qc.rzz(1.1, 0, 1)
qc.draw("mpl")

Output of the previous code cell

Pertama, kita men-transpile Circuit untuk Backend yang tidak mendukung fractional gates.

pm_c = generate_preset_pass_manager(
optimization_level=optimization_level, backend=backend_c
)
t_qc = pm_c.run(qc)
print(t_qc.count_ops())
t_qc.draw("mpl")
OrderedDict({'rz': 23, 'sx': 16, 'cz': 4})

Output of the previous code cell

Kemudian, kita men-transpile Circuit yang sama menggunakan fractional RX gates, dengan mengecualikan Gate RZZ. Ini menghasilkan sedikit pengurangan jumlah gate total, berkat implementasi Gate RX yang lebih efisien.

backend_f = service.backend(backend_name, use_fractional_gates=True)
target = remove_instruction_from_target(backend_f.target, "rzz")
pm_f = generate_preset_pass_manager(
optimization_level=optimization_level,
target=target,
)
t_qc = pm_f.run(qc)
print(t_qc.count_ops())
t_qc.draw("mpl")
OrderedDict({'rz': 22, 'sx': 14, 'cz': 4, 'rx': 1})

Output of the previous code cell

Optimalkan Gate U dengan fractional RX gates

Pada bagian ini, kita mendemonstrasikan cara mengoptimalkan Gate U menggunakan fractional RX gates, dengan melanjutkan dari circuit yang sama yang diperkenalkan pada bagian sebelumnya. Kita men-transpile Circuit menggunakan hanya fractional RX gates, dengan mengecualikan Gate RZZ. Dengan memperkenalkan aturan dekomposisi kustom, seperti yang ditunjukkan berikut ini, kita bisa mengurangi jumlah gate single-qubit yang diperlukan untuk mengimplementasikan Gate U.

Fitur ini sedang dalam diskusi di GitHub issue ini.

# special decomposition rule for UGate
x = ParameterVector("x", 3)
zxz = QuantumCircuit(1)
zxz.rz(x[2] - np.pi / 2, 0)
zxz.rx(x[0], 0)
zxz.rz(x[1] + np.pi / 2, 0)
DEFAULT_EQUIVALENCE_LIBRARY.add_equivalence(UGate(x[0], x[1], x[2]), zxz)

Selanjutnya, kita menerapkan Transpiler menggunakan metode translation (translasi basis) constructor-beta yang disediakan oleh paket qiskit-basis-constructor. Hasilnya, total jumlah gate berkurang dibandingkan dengan transpilasi sebelumnya.

pm_f = generate_preset_pass_manager(
optimization_level=optimization_level,
target=target,
translation_method="constructor-beta",
)
t_qc = pm_f.run(qc)
print(t_qc.count_ops())
t_qc.draw("mpl")
OrderedDict({'rz': 16, 'rx': 9, 'cz': 4})

Output of the previous code cell

Langkah selanjutnya

Rekomendasi

Jika kamu merasa pekerjaan ini menarik, kamu mungkin tertarik dengan materi berikut: