ข้ามไปยังเนื้อหาหลัก

จำลองโมเดล 2D tilted-field Ising ด้วยฟังก์ชัน QESEM

หมายเหตุ

Qiskit Functions เป็นฟีเจอร์ทดลองที่ให้บริการเฉพาะผู้ใช้งาน IBM Quantum® Premium Plan, Flex Plan และ On-Prem (ผ่าน IBM Quantum Platform API) Plan เท่านั้น ขณะนี้อยู่ในสถานะ preview release และอาจมีการเปลี่ยนแปลงได้

ประมาณการเวลาใช้งาน: 20 นาทีบนโปรเซสเซอร์ Heron r2 (หมายเหตุ: เป็นเพียงการประมาณเท่านั้น เวลาจริงอาจแตกต่างกันได้)

พื้นหลัง

บทช่วยสอนนี้แสดงวิธีใช้ QESEM ซึ่งเป็น Qiskit Function ของ Qedma เพื่อจำลองพลวัตของโมเดลสปินควอนตัมแบบ canonical อย่างโมเดล 2D tilted-field Ising (TFI) ที่มีมุมแบบ non-Clifford:

H=Ji,jZiZj+gxiXi+gziZi,H = J \sum_{\langle i,j \rangle} Z_i Z_j + g_x \sum_i X_i + g_z \sum_i Z_i ,

โดยที่ i,j\langle i,j \rangle หมายถึงเพื่อนบ้านที่อยู่ใกล้กันบนแลตทิซ การจำลองวิวัฒนาการตามเวลาของระบบควอนตัมแบบ many-body เป็นงานที่ท้าทายทางการคำนวณสำหรับคอมพิวเตอร์คลาสสิก ในทางตรงกันข้าม คอมพิวเตอร์ควอนตัมถูกออกแบบมาโดยธรรมชาติให้ทำงานนี้ได้อย่างมีประสิทธิภาพ โดยเฉพาะโมเดล TFI ได้กลายเป็น benchmark ยอดนิยมบนฮาร์ดแวร์ควอนตัม เนื่องจากพฤติกรรมทางฟิสิกส์ที่หลากหลายและการนำไปใช้บนฮาร์ดแวร์ที่ทำได้สะดวก

แทนที่จะจำลองพลวัตแบบต่อเนื่องตามเวลา เราใช้โมเดล kicked Ising ที่มีความสัมพันธ์กันอย่างใกล้ชิด พลวัตดังกล่าวสามารถแสดงออกมาได้อย่างแม่นยำในรูปแบบ Circuit ควอนตัมแบบ periodic โดยแต่ละขั้นตอนวิวัฒนาการประกอบด้วยสามชั้นของ Gate สองQubit แบบเศษส่วน RZZ(αZZ)R_{ZZ} (\alpha_{ZZ}) สลับกับชั้นของ Gate หนึ่ง Qubit RX(αX)R_X (\alpha_X) และ RZ(αZ)R_Z (\alpha_Z)

เราจะใช้มุมทั่วไปที่ท้าทายทั้งสำหรับการจำลองแบบคลาสสิกและการลดข้อผิดพลาด โดยเฉพาะเราเลือก αZZ=1.0\alpha_{ZZ} = 1.0, αX=0.53\alpha_X = 0.53 และ αZ=0.1\alpha_Z = 0.1 ซึ่งทำให้โมเดลอยู่ห่างไกลจากจุด integrable ใดๆ

ในบทช่วยสอนนี้เราจะทำสิ่งต่อไปนี้:

  • ประมาณเวลา QPU ที่คาดว่าจะใช้สำหรับการลดข้อผิดพลาดเต็มรูปแบบโดยใช้ฟีเจอร์การประมาณเวลาแบบวิเคราะห์และเชิงประจักษ์ของ QESEM
  • สร้างและจำลอง Circuit โมเดล 2D tilted-field Ising โดยใช้เลย์เอาต์ Qubit และชั้น Gate ที่ได้รับแรงบันดาลใจจากฮาร์ดแวร์
  • แสดงภาพการเชื่อมต่อ Qubit บนอุปกรณ์และ subgraph ที่เลือกสำหรับการทดลอง
  • สาธิตการใช้ operator backpropagation (OBP) เพื่อลดความลึกของ Circuit เทคนิคนี้ตัดการดำเนินการออกจากปลาย Circuit โดยแลกกับการวัด operator มากขึ้น
  • ดำเนินการลดข้อผิดพลาด (EM) แบบ unbiased สำหรับ observable หลายตัวพร้อมกันโดยใช้ QESEM และเปรียบเทียบผลลัพธ์ที่สมบูรณ์แบบ มีสัญญาณรบกวน และที่ผ่านการลดข้อผิดพลาด
  • วิเคราะห์และพล็อตผลกระทบของการลดข้อผิดพลาดต่อค่า magnetization ในความลึก Circuit ที่แตกต่างกัน

หมายเหตุ: OBP โดยทั่วไปจะคืนค่า observable ชุดหนึ่งที่อาจไม่ commute กัน QESEM จะปรับ measurement basis ให้เหมาะสมโดยอัตโนมัติเมื่อ observable เป้าหมายมีเทอมที่ไม่ commute กัน ระบบจะสร้างชุด measurement basis ที่เป็นไปได้โดยใช้อัลกอริทึม heuristic หลายแบบและเลือกชุดที่ลดจำนวน basis ที่แตกต่างกันให้น้อยที่สุด ซึ่งหมายความว่า QESEM จะจัดกลุ่ม observable ที่เข้ากันได้ไว้ใน basis ร่วมกันเพื่อลดจำนวนการกำหนดค่าการวัดทั้งหมดที่จำเป็น ช่วยเพิ่มประสิทธิภาพ

เกี่ยวกับ QESEM

QESEM เป็นซอฟต์แวร์ที่เชื่อถือได้ มีความแม่นยำสูง ใช้การ characterization เป็นพื้นฐาน ซึ่งนำไปใช้การลดข้อผิดพลาดแบบ quasi-probabilistic ที่มีประสิทธิภาพและ unbiased ออกแบบมาเพื่อลดข้อผิดพลาดใน Circuit ควอนตัมทั่วไปและไม่ขึ้นกับแอปพลิเคชัน ได้รับการตรวจสอบในแพลตฟอร์มฮาร์ดแวร์ที่หลากหลาย รวมถึงการทดลองระดับ utility บนอุปกรณ์ IBM® Eagle และ Heron ขั้นตอนการทำงานของ QESEM มีดังนี้:

  1. การ characterize อุปกรณ์ — แมปฟิดิลิตี้ Gate และระบุ coherent error ให้ข้อมูล calibration แบบ real-time ขั้นตอนนี้ทำให้มั่นใจว่าการลดข้อผิดพลาดใช้ประโยชน์จากการดำเนินการที่มีฟิดิลิตี้สูงสุดที่มีอยู่
  2. การ transpile แบบ noise-aware — สร้างและประเมิน qubit mapping ทางเลือก ชุดการดำเนินการ และ measurement basis โดยเลือกตัวเลือกที่ลดเวลา QPU ที่ประมาณไว้ให้น้อยที่สุด พร้อมตัวเลือก parallelization เพื่อเร่งการเก็บข้อมูล
  3. การลด error — กำหนด native gate ใหม่ ใช้ Pauli twirling และปรับ pulse-level control (บนแพลตฟอร์มที่รองรับ) เพื่อปรับปรุงฟิดิลิตี้
  4. การ characterize Circuit — สร้างโมเดล local error ที่ปรับแต่งเฉพาะและ fit กับการวัด QPU เพื่อวัดปริมาณ noise ที่เหลืออยู่
  5. การลดข้อผิดพลาด — สร้าง quasi-probabilistic decomposition หลายประเภท และสุ่มตัวอย่างจากพวกมันในกระบวนการแบบ adaptive ที่ลดเวลา QPU สำหรับ mitigation และความไวต่อความผันผวนของฮาร์ดแวร์ให้น้อยที่สุด บรรลุความแม่นยำสูงในปริมาตร Circuit ขนาดใหญ่

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับ QESEM และการทดลองระดับ utility ของโมเดลนี้บน subgraph แบบ 103-Qubit high-connectivity ของรูปทรงเรขาคณิต heavy-hex ของ ibm_marrakesh โปรดดูที่ Reliable high-accuracy error mitigation for utility-scale quantum circuits. ขั้นตอนการทำงานของ QESEM

ข้อกำหนด

ติดตั้งแพ็กเกจ Python ต่อไปนี้ก่อนรัน notebook:

  • Qiskit SDK v2.0.0 หรือใหม่กว่า (pip install qiskit)
  • Qiskit Runtime v0.40.0 หรือใหม่กว่า (pip install qiskit-ibm-runtime)
  • Qiskit Functions Catalog v0.8.0 หรือใหม่กว่า ( pip install qiskit-ibm-catalog )
  • Operator Backpropagation Qiskit addon v0.3.0 หรือใหม่กว่า ( pip install qiskit-addon-obp )
  • Qiskit Utils addon v0.1.1 หรือใหม่กว่า ( pip install qiskit-addon-utils )
  • Qiskit Aer simulator v0.17.1 หรือใหม่กว่า ( pip install qiskit-aer )
  • Matplotlib v3.10.3 หรือใหม่กว่า ( pip install matplotlib )

การตั้งค่า

ก่อนอื่น ให้ import ไลบรารีที่เกี่ยวข้อง:

# Added by doQumentation — required packages for this notebook
!pip install -q matplotlib numpy qiskit qiskit-addon-obp qiskit-addon-utils qiskit-aer qiskit-ibm-catalog qiskit-ibm-runtime
%matplotlib inline

from typing import Sequence

import matplotlib.pyplot as plt
import numpy as np

import qiskit
from qiskit_ibm_runtime import EstimatorV2 as Estimator
from qiskit_ibm_catalog import QiskitFunctionsCatalog
from qiskit_aer import AerSimulator
from qiskit_addon_utils.slicing import combine_slices, slice_by_gate_types
from qiskit_addon_obp import backpropagate
from qiskit_addon_obp.utils.simplify import OperatorBudget
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit.visualization import (
plot_gate_map,
)

ถัดไป ยืนยันตัวตนโดยใช้ API key จากแดชบอร์ด IBM Quantum Platform จากนั้นเลือก Qiskit Function ดังนี้ (สำหรับความปลอดภัย แนะนำให้ บันทึก credentials ไว้ในสภาพแวดล้อมโลคัล หากอยู่บนเครื่องที่เชื่อถือได้ เพื่อไม่ต้องกรอก API key ทุกครั้งที่ยืนยันตัวตน)

# Paste here your instance and token strings

instance = "YOUR_INSTANCE"
token = "YOUR_TOKEN"
channel = "ibm_quantum_platform"

catalog = QiskitFunctionsCatalog(
channel=channel, token=token, instance=instance
)
qesem_function = catalog.load("qedma/qesem")

ขั้นตอนที่ 1: แปลง input แบบคลาสสิกเป็นปัญหาควอนตัม

เราเริ่มต้นด้วยการกำหนดฟังก์ชันที่สร้าง Trotter Circuit:

def trotter_circuit_from_layers(
steps: int,
theta_x: float,
theta_z: float,
theta_zz: float,
layers: Sequence[Sequence[tuple[int, int]]],
init_state: str | None = None,
) -> qiskit.QuantumCircuit:
"""
Generates an ising trotter circuit
:param steps: trotter steps
:param theta_x: RX angle
:param theta_z: RZ angle
:param theta_zz: RZZ angle
:param layers: list of layers (can be list of layers in device)
:param init_state: Initial state to prepare. If None, will not prepare any state. If "+", will
add Hadamard gates to all qubits.
:return: QuantumCircuit
"""
qubits = sorted({i for layer in layers for edge in layer for i in edge})
circ = qiskit.QuantumCircuit(max(qubits) + 1)

if init_state == "+":
print("init_state = +")
for q in qubits:
circ.h(q)

for _ in range(steps):
for q in qubits:
circ.rx(theta_x, q)
circ.rz(theta_z, q)

for layer in layers:
for edge in layer:
circ.rzz(theta_zz, *edge)
circ.barrier(qubits)

return circ

ถัดไป เราสร้างฟังก์ชันเพื่อคำนวณค่า expectation value ที่สมบูรณ์แบบโดยใช้ AerSimulator

สำหรับ Circuit ขนาดใหญ่ (30 Qubit ขึ้นไป) แนะนำให้ใช้ค่าที่คำนวณล่วงหน้าจากการจำลองแบบ belief-propagation (BP) PEPS โค้ดนี้รวมค่าที่คำนวณล่วงหน้าสำหรับ 35 Qubit เป็นตัวอย่าง โดยอิงจากแนวทาง BP สำหรับการวิวัฒนาการ PEPS tensor network ที่แนะนำ ในบทความนี้ (ซึ่งเราเรียกว่า PEPS-BP) โดยใช้แพ็กเกจ Python สำหรับ tensor-network ที่ชื่อ quimb

def calculate_ideal_evs(circ, obs, num_qubits, step):
# Predefined results for large circuits - calculated using bppeps for 3, 5, 7, 9 trotter steps
predefined_35 = [
0.79537,
0.78653,
0.79699,
]

if num_qubits == 35:
print(
"Using precalculated ideal values for large circuits calculated with belief propagation PEPS. Currently only for 35 qubits."
)
return predefined_35[step]

else:
simulator = AerSimulator()

# Use Estimator primitive to get expectation value
estimator = Estimator(simulator)
sim_result = estimator.run([(circ, [obs])], precision=0.0001).result()

# Extracting the result
ideal_values = sim_result[0].data.evs[0]
return ideal_values

เราใช้การแมปชั้น RZZR_{ZZ} ที่อิงจากฮาร์ดแวร์ที่นำมาจากอุปกรณ์ Heron และตัดชั้นเหล่านั้นตามจำนวน Qubit ที่ต้องการจำลอง เรากำหนด subgraph สำหรับ 10, 21, 28 และ 35 Qubit ที่คงโครงสร้าง 2D ไว้ (สามารถเปลี่ยนเป็น subgraph ที่ชื่นชอบได้):

LAYERS_HERON_R2 = [  # the full set of hardware layers for Heron r2
[
(2, 3),
(6, 7),
(10, 11),
(14, 15),
(20, 21),
(16, 23),
(24, 25),
(17, 27),
(28, 29),
(18, 31),
(32, 33),
(19, 35),
(36, 41),
(42, 43),
(37, 45),
(46, 47),
(38, 49),
(50, 51),
(39, 53),
(60, 61),
(56, 63),
(64, 65),
(57, 67),
(68, 69),
(58, 71),
(72, 73),
(59, 75),
(76, 81),
(82, 83),
(77, 85),
(86, 87),
(78, 89),
(90, 91),
(79, 93),
(94, 95),
(100, 101),
(96, 103),
(104, 105),
(97, 107),
(108, 109),
(98, 111),
(112, 113),
(99, 115),
(116, 121),
(122, 123),
(117, 125),
(126, 127),
(118, 129),
(130, 131),
(119, 133),
(134, 135),
(140, 141),
(136, 143),
(144, 145),
(137, 147),
(148, 149),
(138, 151),
(152, 153),
(139, 155),
],
[
(1, 2),
(3, 4),
(5, 6),
(7, 8),
(9, 10),
(11, 12),
(13, 14),
(21, 22),
(23, 24),
(25, 26),
(27, 28),
(29, 30),
(31, 32),
(33, 34),
(40, 41),
(43, 44),
(45, 46),
(47, 48),
(49, 50),
(51, 52),
(53, 54),
(55, 59),
(61, 62),
(63, 64),
(65, 66),
(67, 68),
(69, 70),
(71, 72),
(73, 74),
(80, 81),
(83, 84),
(85, 86),
(87, 88),
(89, 90),
(91, 92),
(93, 94),
(95, 99),
(101, 102),
(103, 104),
(105, 106),
(107, 108),
(109, 110),
(111, 112),
(113, 114),
(120, 121),
(123, 124),
(125, 126),
(127, 128),
(129, 130),
(131, 132),
(133, 134),
(135, 139),
(141, 142),
(143, 144),
(145, 146),
(147, 148),
(149, 150),
(151, 152),
(153, 154),
],
[
(3, 16),
(7, 17),
(11, 18),
(22, 23),
(26, 27),
(30, 31),
(34, 35),
(21, 36),
(25, 37),
(29, 38),
(33, 39),
(41, 42),
(44, 45),
(48, 49),
(52, 53),
(43, 56),
(47, 57),
(51, 58),
(62, 63),
(66, 67),
(70, 71),
(74, 75),
(61, 76),
(65, 77),
(69, 78),
(73, 79),
(81, 82),
(84, 85),
(88, 89),
(92, 93),
(83, 96),
(87, 97),
(91, 98),
(102, 103),
(106, 107),
(110, 111),
(114, 115),
(101, 116),
(105, 117),
(109, 118),
(113, 119),
(121, 122),
(124, 125),
(128, 129),
(132, 133),
(123, 136),
(127, 137),
(131, 138),
(142, 143),
(146, 147),
(150, 151),
(154, 155),
(0, 1),
(4, 5),
(8, 9),
(12, 13),
(54, 55),
(15, 19),
],
]

subgraphs = { # the subgraphs for the different qubit counts such that it's 2D
10: list(range(22, 29)) + [16, 17, 37],
21: list(range(3, 12)) + list(range(23, 32)) + [16, 17, 18],
28: list(range(3, 12))
+ list(range(23, 32))
+ list(range(45, 50))
+ [16, 17, 18, 37, 38],
35: list(range(3, 12))
+ list(range(21, 32))
+ list(range(41, 50))
+ [16, 17, 18, 36, 37, 38],
42: list(range(3, 12))
+ list(range(21, 32))
+ list(range(41, 50))
+ list(range(63, 68))
+ [16, 17, 18, 36, 37, 38, 56, 57],
}

n_qubits = 35 # 21, 28, 35, 42
layers = [
[
edge
for edge in layer
if edge[0] in subgraphs[n_qubits] and edge[1] in subgraphs[n_qubits]
]
for layer in LAYERS_HERON_R2
]

print(layers)
[[(6, 7), (10, 11), (16, 23), (24, 25), (17, 27), (28, 29), (18, 31), (36, 41), (42, 43), (37, 45), (46, 47), (38, 49)], [(3, 4), (5, 6), (7, 8), (9, 10), (21, 22), (23, 24), (25, 26), (27, 28), (29, 30), (43, 44), (45, 46), (47, 48)], [(3, 16), (7, 17), (11, 18), (22, 23), (26, 27), (30, 31), (21, 36), (25, 37), (29, 38), (41, 42), (44, 45), (48, 49), (4, 5), (8, 9)]]

ตอนนี้เราแสดงภาพเลย์เอาต์ Qubit บนอุปกรณ์ Heron สำหรับ subgraph ที่เลือก:

service = QiskitRuntimeService(
channel=channel,
token=token,
instance=instance,
)
backend = service.backend("ibm_fez") # or any available device

selected_qubits = subgraphs[n_qubits]
num_qubits = backend.configuration().num_qubits
qubit_color = [
"#ff7f0e" if i in selected_qubits else "#d3d3d3"
for i in range(num_qubits)
]

plot_gate_map(
backend=backend,
figsize=(15, 10),
qubit_color=qubit_color,
)
plt.show()

ผลลัพธ์ของ code cell ก่อนหน้า

สังเกตว่าการเชื่อมต่อของเลย์เอาต์ Qubit ที่เลือกนั้นไม่จำเป็นต้องเป็นแบบเชิงเส้น และสามารถครอบคลุมพื้นที่ขนาดใหญ่ของอุปกรณ์ Heron ได้ขึ้นอยู่กับจำนวน Qubit ที่เลือก

ตอนนี้เราสร้าง Trotter Circuit และ observable ค่า magnetization เฉลี่ยสำหรับจำนวน Qubit และพารามิเตอร์ที่เลือก:

# Chosen parameters:
theta_x = 0.53
theta_z = 0.1
theta_zz = 1.0
steps = 9

circ = trotter_circuit_from_layers(steps, theta_x, theta_z, theta_zz, layers)
print(
f"Circuit 2q layers: {circ.depth(filter_function=lambda instr: len(instr.qubits) == 2)}"
)
print("\nCircuit structure:")

circ.draw("mpl", scale=0.8, fold=-1, idle_wires=False)
plt.show()

observable = qiskit.quantum_info.SparsePauliOp.from_sparse_list(
[("Z", [q], 1 / n_qubits) for q in subgraphs[n_qubits]],
np.max(subgraphs[n_qubits]) + 1,
) # Average magnetization observable

print(observable)
obs_list = [observable]
Circuit 2q layers: 27

Circuit structure:

ผลลัพธ์ของ code cell ก่อนหน้า

SparsePauliOp(['IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'ZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII'],
coeffs=[0.02857143+0.j, 0.02857143+0.j, 0.02857143+0.j, 0.02857143+0.j,
0.02857143+0.j, 0.02857143+0.j, 0.02857143+0.j, 0.02857143+0.j,
0.02857143+0.j, 0.02857143+0.j, 0.02857143+0.j, 0.02857143+0.j,
0.02857143+0.j, 0.02857143+0.j, 0.02857143+0.j, 0.02857143+0.j,
0.02857143+0.j, 0.02857143+0.j, 0.02857143+0.j, 0.02857143+0.j,
0.02857143+0.j, 0.02857143+0.j, 0.02857143+0.j, 0.02857143+0.j,
0.02857143+0.j, 0.02857143+0.j, 0.02857143+0.j, 0.02857143+0.j,
0.02857143+0.j, 0.02857143+0.j, 0.02857143+0.j, 0.02857143+0.j,
0.02857143+0.j, 0.02857143+0.j, 0.02857143+0.j])

ขั้นตอนที่ 2: ปรับแต่งปัญหาสำหรับการรันบนฮาร์ดแวร์ควอนตัม

การประมาณเวลา QPU แบบมีและไม่มี OBP

โดยทั่วไปผู้ใช้อยากรู้ว่าต้องใช้เวลา QPU เท่าไหร่สำหรับการทดลองของตน อย่างไรก็ตาม นี่ถือเป็นปัญหาที่ยากสำหรับคอมพิวเตอร์คลาสสิก

QESEM มีสองโหมดในการประมาณเวลาเพื่อแจ้งให้ผู้ใช้ทราบถึงความเป็นไปได้ของการทดลอง:

  1. การประมาณเวลาแบบวิเคราะห์ - ให้การประมาณคร่าวๆ และไม่ต้องใช้เวลา QPU เลย สามารถใช้เพื่อทดสอบว่า transpilation pass จะลดเวลา QPU ได้หรือไม่
  2. การประมาณเวลาเชิงประจักษ์ (แสดงที่นี่) - ให้การประมาณที่ค่อนข้างดีและใช้เวลา QPU สองสามนาที

ในทั้งสองกรณี QESEM จะแสดงผลการประมาณเวลาสำหรับการบรรลุความแม่นยำที่ต้องการสำหรับ observable ทั้งหมด

run_on_real_hardware = True

precision = 0.05
if run_on_real_hardware:
backend_name = "ibm_fez"
else:
backend_name = "fake_fez"

# Start a job for empirical time estimation
estimation_job_wo_obp = qesem_function.run(
pubs=[(circ, obs_list)],
instance=instance,
backend_name=backend_name, # E.g. "ibm_brisbane"
options={
"estimate_time_only": "empirical", # "empirical" - gets actual time estimates without running full mitigation
"max_execution_time": 120, # Limits the QPU time, specified in seconds.
"default_precision": precision,
},
)
print(estimation_job_wo_obp.job_id)
print(estimation_job_wo_obp.status())
17d3828e-9fdb-482e-8e9b-392f3eefe313
DONE
# Get the result object (blocking method). Use job.status() in a loop for non-blocking.
# This takes 1-3 minutes
result = estimation_job_wo_obp.result()
print(
f"Empirical time estimation (sec): {result[0].metadata['time_estimation_sec']}"
)
Empirical time estimation (sec): 1200

ตอนนี้เราจะใช้ operator backpropagation (OBP) (ดูคู่มือ OBP สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับ OBP Qiskit addon) เราจะสร้างฟังก์ชันที่สร้าง circuit slices สำหรับการ backpropagation:

def run_backpropagation(circ_vec, observable, steps_vec, max_qwc_groups=8):
"""
Runs backpropagation for a list of circuits and observables.
Returns lists of backpropagated circuits and observables.
"""
op_budget = OperatorBudget(max_qwc_groups=max_qwc_groups)
bp_circuit_vec = []
bp_observable_vec = []

for i, circ in enumerate(circ_vec):
slices = slice_by_gate_types(circ)
bp_observable, remaining_slices, metadata = backpropagate(
observable,
slices,
operator_budget=op_budget,
)
bp_circuit = combine_slices(remaining_slices, include_barriers=True)
bp_circuit_vec.append(bp_circuit)
bp_observable_vec.append(bp_observable)
print(f"n.o. steps: {steps_vec[i]}")
print(f"Backpropagated {metadata.num_backpropagated_slices} slices.")
print(
f"New observable has {len(bp_observable.paulis)} terms, which can be combined into "
f"{len(bp_observable.group_commuting(qubit_wise=True))} groups.\n"
f"After truncation, the error in our observable is bounded by {metadata.accumulated_error(0):.3e}"
)
print("-----------------")
return bp_circuit_vec, bp_observable_vec

เรียกใช้ฟังก์ชัน:

bp_circ_vec, bp_obs_vec = run_backpropagation([circ], observable, [steps])
n.o. steps: 9
Backpropagated 11 slices.
New observable has 363 terms, which can be combined into 4 groups.
After truncation, the error in our observable is bounded by 0.000e+00
-----------------
print("The remaining circuit after backpropagation looks as follows:")
bp_circ_vec[-1].draw("mpl", scale=0.8, fold=-1, idle_wires=False)
None
The remaining circuit after backpropagation looks as follows:

Output of the previous code cell

จะเห็นว่า backpropagation ลด Circuit สองเลเยอร์ออกไปได้ ตอนนี้ที่เรามี Circuit ที่ลดขนาดแล้วและ observable ที่ขยายออกแล้ว มาทำการประมาณเวลาสำหรับ Circuit ที่ผ่าน backpropagation:

# Start a job for empirical time estimation
estimation_job_obp = qesem_function.run(
pubs=[(bp_circ_vec[-1], [bp_obs_vec[-1]])],
instance=instance,
backend_name=backend_name,
options={
"estimate_time_only": "empirical",
"max_execution_time": 120,
"default_precision": precision,
},
)
print(estimation_job_obp.job_id)
print(estimation_job_obp.status())
8bae699d-a16b-4d39-bbd9-d123fbcce55d
DONE
result_obp = estimation_job_obp.result()
print(
f"Empirical time estimation (sec): {result_obp[0].metadata['time_estimation_sec']}"
)
Empirical time estimation (sec): 900

จะเห็นว่า OBP ช่วยลดต้นทุนด้านเวลาสำหรับการ mitigation ของ Circuit

ขั้นตอนที่ 3: รันด้วย Qiskit primitives

รันบน Backend จริง

ตอนนี้เรารันการทดลองแบบเต็มรูปแบบบน Trotter สองสามขั้น จำนวน Qubit ความแม่นยำที่ต้องการ และเวลา QPU สูงสุดสามารถปรับได้ตามทรัพยากร QPU ที่มี โปรดทราบว่าการจำกัดเวลา QPU สูงสุดจะส่งผลต่อความแม่นยำของผลลัพธ์สุดท้าย ดังที่จะเห็นในกราฟสุดท้ายด้านล่าง

เราวิเคราะห์ Circuit สี่แบบที่มี 5, 7 และ 9 Trotter steps ด้วยความแม่นยำ 0.05 โดยเปรียบเทียบค่า expectation values ที่ ideal, noisy และผ่านการแก้ไขข้อผิดพลาด:

steps_vec = [5, 7, 9]

circ_vec = []
for steps in steps_vec:
circ = trotter_circuit_from_layers(
steps, theta_x, theta_z, theta_zz, layers
)
circ_vec.append(circ)

อีกครั้ง เรารัน OBP บน Circuit แต่ละอันเพื่อลดเวลาการรัน:

bp_circ_vec_35, bp_obs_vec_35 = run_backpropagation(
circ_vec, observable, steps_vec
)
n.o. steps: 5
Backpropagated 11 slices.
New observable has 363 terms, which can be combined into 4 groups.
After truncation, the error in our observable is bounded by 0.000e+00
-----------------
n.o. steps: 7
Backpropagated 11 slices.
New observable has 363 terms, which can be combined into 4 groups.
After truncation, the error in our observable is bounded by 0.000e+00
-----------------
n.o. steps: 9
Backpropagated 11 slices.
New observable has 363 terms, which can be combined into 4 groups.
After truncation, the error in our observable is bounded by 0.000e+00
-----------------

ตอนนี้เรารัน batch ของงาน QESEM แบบเต็มรูปแบบ เราจำกัดเวลา QPU สูงสุดสำหรับแต่ละจุดเพื่อควบคุมงบ QPU ได้ดีขึ้น

run_on_real_hardware = True

precision = 0.05
if run_on_real_hardware:
backend_name = "ibm_marrakesh"
else:
backend_name = "fake_fez"
# Running full jobs for:
pubs_list = [
[(bp_circ_vec_35[i], bp_obs_vec_35[i])] for i in range(len(bp_obs_vec_35))
]
# Initiating multiple jobs for different lengths
job_list = []
for pubs in pubs_list:
job_obp = qesem_function.run(
pubs=pubs,
instance=instance,
backend_name=backend_name, # E.g. "ibm_brisbane"
options={
"max_execution_time": 300, # Limits the QPU time, specified in seconds.
"default_precision": 0.05,
},
)
job_list.append(job_obp)

ที่นี่เราตรวจสอบสถานะของแต่ละงาน:

for job in job_list:
print(job.status())
DONE
DONE
DONE
DONE

ขั้นตอนที่ 4: ประมวลผลหลังการรันและส่งผลลัพธ์ในรูปแบบ classical ที่ต้องการ

เมื่องานทั้งหมดรันเสร็จแล้ว เราสามารถเปรียบเทียบค่า expectation value แบบ noisy และแบบที่ผ่านการแก้ไขแล้วได้

ideal_values = []
noisy_values = []
error_mitigated_values = []
error_mitigated_stds = []

for i in range(len(job_list)):
job = job_list[i]
result = job.result() # Blocking - takes 3-5 minutes
noisy_results = result[0].metadata["noisy_results"]

ideal_val = calculate_ideal_evs(circ_vec[i], observable, n_qubits, i)
print("---------------------------------")
print(f"Ideal: {ideal_val}")
print(f"Noisy: {noisy_results.evs}")
print(f"QESEM: {result[0].data.evs} \u00b1 {result[0].data.stds}")

ideal_values.append(ideal_val)
noisy_values.append(noisy_results.evs)
error_mitigated_values.append(result[0].data.evs)
error_mitigated_stds.append(result[0].data.stds)
Using precalculated ideal values for large circuits calculated with belief propagation PEPS. Currently only for 35 qubits.
---------------------------------
Ideal: 0.79537
Noisy: 0.7039237951821501
QESEM: 0.7828018244130982 ± 0.013257266977728376
Using precalculated ideal values for large circuits calculated with belief propagation PEPS. Currently only for 35 qubits.
---------------------------------
Ideal: 0.78653
Noisy: 0.6478583812958806
QESEM: 0.7875259197423828 ± 0.02703045139248604
Using precalculated ideal values for large circuits calculated with belief propagation PEPS. Currently only for 35 qubits.
---------------------------------
Ideal: 0.79699
Noisy: 0.6171787879868142
QESEM: 0.6918791909168913 ± 0.0740873782039517

สุดท้าย เราสามารถพล็อตค่าแม่เหล็กสัมพัทธ์เทียบกับจำนวน steps ได้ ซึ่งสรุปประโยชน์ของการใช้ QESEM Qiskit Function สำหรับการแก้ไขข้อผิดพลาดแบบไม่มี bias บนอุปกรณ์ quantum แบบ noisy

plt.plot(steps_vec, ideal_values, "--", label="ideal")
plt.scatter(steps_vec, noisy_values, label="noisy")
plt.errorbar(
steps_vec,
error_mitigated_values,
yerr=error_mitigated_stds,
fmt="o",
capsize=5,
label="QESEM mitigation",
)
plt.legend()
plt.xlabel("n.o. steps")
plt.ylabel("Magnetization")
Text(0, 0.5, 'Magnetization')

Output of the previous code cell

หมายเหตุ

ขั้นตอนที่เก้ามี error bar ทางสถิติขนาดใหญ่ เนื่องจากเราจำกัดเวลา QPU ไว้ที่ 5 นาที หากรันขั้นตอนนี้นาน 15 นาที (ตามที่การประมาณเวลาเชิงประสบการณ์แนะนำ) คุณจะได้ error bar ที่เล็กลง ดังนั้น ค่าที่ผ่านการแก้ไขแล้วจะใกล้เคียงกับค่า ideal มากขึ้น

Source: IBM Quantum docs — updated 27 เม.ย. 2569
English version on doQumentation — updated 7 พ.ค. 2569
This translation based on the English version of 9 เม.ย. 2569