ข้ามไปยังเนื้อหาหลัก
โครงการนี้อยู่ในช่วงเบต้า พบข้อผิดพลาด? สร้าง GitHub Issue มีคำถามหรือไอเดีย? ถามใน Discussions — ยินดีรับฟังความคิดเห็น!
คุณภาพการแปลในหน้านี้เป็นอย่างไร?

ตั้งค่าระดับการปรับแต่งของ Transpiler

Package versions

โค้ดในหน้านี้ถูกพัฒนาโดยใช้ข้อกำหนดต่อไปนี้ เราแนะนำให้ใช้เวอร์ชันเหล่านี้หรือใหม่กว่า

qiskit[all]~=2.6.1
qiskit-ibm-runtime~=0.50.0

อุปกรณ์ควอนตัมจริงนั้นมีสัญญาณรบกวนและข้อผิดพลาดของ Gate ดังนั้นการปรับแต่ง Circuit เพื่อลดความลึกและจำนวน Gate จึงสามารถปรับปรุงผลลัพธ์ที่ได้จากการรัน Circuit เหล่านั้นได้อย่างมาก ฟังก์ชัน generate_preset_pass_manager มีอาร์กิวเมนต์ตำแหน่งบังคับหนึ่งตัวคือ optimization_level ซึ่งควบคุมความพยายามที่ Transpiler ใช้ในการปรับแต่ง Circuit อาร์กิวเมนต์นี้เป็นจำนวนเต็มที่รับค่าได้คือ 0, 1, 2 หรือ 3 ระดับการปรับแต่งที่สูงขึ้นจะสร้าง Circuit ที่ปรับแต่งมากขึ้นแต่ใช้เวลา compile นานขึ้น ตารางต่อไปนี้อธิบายการปรับแต่งที่ทำในแต่ละการตั้งค่า

ระดับการปรับแต่งคำอธิบาย
0

ไม่มีการปรับแต่ง: โดยทั่วไปใช้สำหรับการกำหนดคุณสมบัติของฮาร์ดแวร์

  • การแปลง Gate พื้นฐาน
  • Layout/Routing: TrivialLayout ซึ่งเลือกหมายเลข Qubit ทางกายภาพเดียวกับ Qubit เสมือน และแทรก SWAP เพื่อให้ทำงานได้ (โดยใช้ SabreSwap)
1

การปรับแต่งระดับเบา:

  • Layout/Routing: ลอง Layout ด้วย TrivialLayout ก่อน ถ้าต้องการ SWAP เพิ่มเติม จะหา Layout ที่มีจำนวน SWAP น้อยที่สุดโดยใช้ SabreSwap แล้วใช้ VF2LayoutPostLayout เพื่อพยายามเลือก Qubit ที่ดีที่สุดในกราฟ
  • InverseCancellation
  • การปรับแต่ง Gate แบบ 1Q
2

การปรับแต่งระดับกลาง:

  • Layout/Routing: ระดับการปรับแต่ง 1 (ไม่มี trivial) + heuristic ที่ปรับแต่งด้วยความลึกการค้นหาและจำนวนการทดลองฟังก์ชันการปรับแต่งที่มากขึ้น เนื่องจากไม่ใช้ TrivialLayout จึงไม่มีการพยายามใช้หมายเลข Qubit ทางกายภาพและเสมือนเหมือนกัน
  • CommutativeCancellation
3

การปรับแต่งระดับสูง:

  • ระดับการปรับแต่ง 2 + heuristic ที่ปรับแต่งใน layout/routing มากขึ้นด้วยความพยายาม/การทดลองมากขึ้น
  • การสังเคราะห์บล็อก Gate แบบสอง Qubit ขึ้นใหม่โดยใช้ Cartan's KAK Decomposition
  • Passes ที่ทำลาย unitarity:
    • OptimizeSwapBeforeMeasure: ย้ายการวัดเพื่อหลีกเลี่ยง SWAP
    • RemoveDiagonalGatesBeforeMeasure: ลบ Gate ก่อนการวัดที่ไม่มีผลต่อการวัด

ระดับการปรับแต่งในทางปฏิบัติ​

เนื่องจาก Gate แบบสอง Qubit โดยทั่วไปเป็นแหล่งข้อผิดพลาดที่สำคัญที่สุด เราจึงสามารถประมาณ "ประสิทธิภาพฮาร์ดแวร์" ของการ transpile ได้โดยการนับจำนวน Gate แบบสอง Qubit ใน Circuit ที่ได้ ในที่นี้ เราจะลองใช้ระดับการปรับแต่งต่างๆ กับ Circuit อินพุตที่ประกอบด้วย unitary สุ่มตามด้วย SWAP Gate

# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util

_needed = {"numpy": "numpy", "qiskit": "qiskit", "qiskit_ibm_runtime": "qiskit-ibm-runtime"}
_missing = [pip for module, pip in _needed.items()
if importlib.util.find_spec(module) is None]
# One at a time, so a package that fails to install does not block the others
for _pip in _missing:
%pip install -q {_pip}
if not _missing:
print("\u2713 All required packages are installed")
from qiskit import QuantumCircuit
from qiskit.circuit.library import UnitaryGate
from qiskit.quantum_info import Operator, random_unitary

UU = random_unitary(4, seed=12345)
rand_U = UnitaryGate(UU)

qc = QuantumCircuit(2)
qc.append(rand_U, range(2))
qc.swap(0, 1)
qc.draw("mpl", style="iqp")

Output of the previous code cell

หมายเหตุ

ตัวอย่างเหล่านี้ใช้ mock Backend FakeSherbrooke จาก qiskit_ibm_runtime แต่คุณสามารถลองใช้กับ Backend จริงหรือ fake Backend ที่รองรับ Qiskit ใดก็ได้ ผลลัพธ์ของคุณอาจแตกต่างออกไป

ก่อนอื่น มา transpile โดยใช้ระดับการปรับแต่ง 0

from qiskit.transpiler import generate_preset_pass_manager
from qiskit_ibm_runtime.fake_provider import FakeSherbrooke

backend = FakeSherbrooke()

pass_manager = generate_preset_pass_manager(
optimization_level=0, backend=backend, seed_transpiler=12345
)
qc_t1_exact = pass_manager.run(qc)
qc_t1_exact.draw("mpl", idle_wires=False)

Output of the previous code cell

Circuit ที่ transpile แล้วมี ECR Gate แบบสอง Qubit อยู่หกตัว

ทำซ้ำสำหรับระดับการปรับแต่ง 1:

from qiskit.transpiler import generate_preset_pass_manager
from qiskit_ibm_runtime.fake_provider import FakeSherbrooke

backend = FakeSherbrooke()

pass_manager = generate_preset_pass_manager(
optimization_level=1, backend=backend, seed_transpiler=12345
)
qc_t1_exact = pass_manager.run(qc)
qc_t1_exact.draw("mpl", idle_wires=False)

Output of the previous code cell

Circuit ที่ transpile แล้วยังคงมี ECR Gate หกตัว แต่จำนวน Gate แบบ Qubit เดียวลดลง

ทำซ้ำสำหรับระดับการปรับแต่ง 2:

pass_manager = generate_preset_pass_manager(
optimization_level=2, backend=backend, seed_transpiler=12345
)
qc_t2_exact = pass_manager.run(qc)
qc_t2_exact.draw("mpl", idle_wires=False)

Output of the previous code cell

ผลลัพธ์เหมือนกับระดับการปรับแต่ง 1 โปรดทราบว่าการเพิ่มระดับการปรับแต่งไม่ได้ให้ผลเสมอไป

ทำซ้ำอีกครั้ง สำหรับระดับการปรับแต่ง 3:

pass_manager = generate_preset_pass_manager(
optimization_level=3, backend=backend, seed_transpiler=12345
)
qc_t3_exact = pass_manager.run(qc)
qc_t3_exact.draw("mpl", idle_wires=False)

Output of the previous code cell

ตอนนี้มีเพียง ECR Gate สามตัว เราได้ผลลัพธ์นี้เพราะที่ระดับการปรับแต่ง 3 Qiskit พยายามสังเคราะห์บล็อก Gate แบบสอง Qubit ขึ้นใหม่ และ Gate แบบสอง Qubit ใดๆ ก็สามารถสร้างได้ด้วย ECR Gate ไม่เกินสาม Gate เราสามารถได้ ECR Gate น้อยลงอีกถ้าตั้งค่า approximation_degree ให้น้อยกว่า 1 ซึ่งยอมให้ Transpiler ทำการประมาณค่าที่อาจนำข้อผิดพลาดบางส่วนมาใน Gate decomposition (ดู พารามิเตอร์ที่ใช้บ่อยสำหรับการ transpilation):

pass_manager = generate_preset_pass_manager(
optimization_level=3,
approximation_degree=0.99,
backend=backend,
seed_transpiler=12345,
)
qc_t3_approx = pass_manager.run(qc)
qc_t3_approx.draw("mpl", idle_wires=False)

Output of the previous code cell

Circuit นี้มีเพียง ECR Gate สองตัว แต่เป็น Circuit แบบประมาณ เพื่อทำความเข้าใจว่าผลกระทบของมันแตกต่างจาก Circuit แบบแม่นยำอย่างไร เราสามารถคำนวณ fidelity ระหว่าง unitary operator ที่ Circuit นี้สร้างขึ้น และ unitary แบบแม่นยำ ก่อนทำการคำนวณ เราจะลด Circuit ที่ transpile แล้วซึ่งมี 127 Qubit ลงมาเป็น Circuit ที่มีเฉพาะ Qubit ที่ถูกใช้งานจริง ซึ่งมีอยู่สองตัว

import numpy as np

def trace_to_fidelity_2q(trace: float) -> float:
return (4.0 + trace * trace.conjugate()) / 20.0

# Reduce circuits down to 2 qubits so they are easy to simulate
qc_t3_exact_small = QuantumCircuit.from_instructions(qc_t3_exact)
qc_t3_approx_small = QuantumCircuit.from_instructions(qc_t3_approx)

# Compute the fidelity
exact_fid = trace_to_fidelity_2q(
np.trace(np.dot(Operator(qc_t3_exact_small).adjoint().data, UU))
)
approx_fid = trace_to_fidelity_2q(
np.trace(np.dot(Operator(qc_t3_approx_small).adjoint().data, UU))
)
print(
f"Synthesis fidelity\nExact: {exact_fid:.3f}\nApproximate: {approx_fid:.3f}"
)
Synthesis fidelity
Exact: 1.000+0.000j
Approximate: 0.992+0.000j

การปรับระดับการปรับแต่งสามารถเปลี่ยนแปลงด้านอื่นๆ ของ Circuit ได้เช่นกัน ไม่ใช่แค่จำนวน ECR Gate สำหรับตัวอย่างว่าการตั้งค่าระดับการปรับแต่งเปลี่ยน layout อย่างไร ดู การแสดงคอมพิวเตอร์ควอนตัม

ขั้นตอนต่อไป​

คำแนะนำ