เริ่มต้นอย่างรวดเร็ว
คู่มือนี้แสดงตัวอย่างขั้นต่ำที่ใช้งานได้จริงของแพ็กเกจ qiskit-addon-sqd เราใช้ sample-based quantum diagonalization (SQD) เพื่อปรับปรุงตัวอย่างที่มีสัญญาณรบกวนซึ่งได้จาก quantum circuit ที่ประมาณสถานะพื้นของแฮมิลโทเนียนทางเคมี พลังงานสถานะพื้นถูกประมาณโดยการทำ diagonalization แฮมิลโทเนียนในปริภูมิย่อยที่เกิดจากตัวอย่างที่ผ่านการปรับปรุงแล้ว
สำหรับเวิร์กโฟลว์แบบ end-to-end ที่อธิบายละเอียดกว่าและรันบนฮาร์ดแวร์ควอนตัม ดูบทเรียนเหล่านี้:
-
Sample-based quantum diagonalization: เวิร์กโฟลว์แฮมิลโทเนียนทางเคมี
-
Sample-based Krylov quantum diagonalization: เวิร์กโฟลว์แบบจำลองแลตทิซเฟอร์มิออน
1. เตรียมอินพุตสำหรับ SQD
ก่อนอื่น เรากำหนดแฮมิลโทเนียนทางเคมีและ quantum circuit ที่ประมาณสถานะพื้นของมัน ระบบที่ศึกษาในตัวอย่างนี้คือ N₂ ที่เรขาคณิตสมดุลในเบซิส STO-3G โดยตรึงออร์บิทัลแกนกลางสองตัว ระบบนี้มีออร์บิทัลเชิงพื้นที่ 8 ตัวและอิเล็กตรอน 10 ตัว ซึ่งหมายความว่า quantum circuit ถูกกำหนดบน 16 qubit โดย qubit 0-7 แทนออร์บิทัลสปินขึ้น และ qubit 8-15 แทนออร์บิทัลสปินลง เนื่องจากนี่เป็นระบบเปลือกปิดที่มีอิเล็กตรอน 10 ตัว เราจึงรู้ว่าตัวอย่างที่ถูกต้องทางกายภาพทุกตัวควรมี hamming weight เท่ากับ 10 โดย hamming weight ของทั้งครึ่งซ้ายและครึ่งขวาของบิตสตริงเท่ากับ 5
# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util
_needed = {"numpy": "numpy", "pyscf": "pyscf", "qiskit_addon_sqd": "qiskit-addon-sqd"}
_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 pyscf import ao2mo, gto, mcscf, scf
# Construct the Hamiltonian, pull out integrals and other information about the system
mol = gto.M(
atom="N 0 0 0; N 0 0 1.09768", basis="sto-3g", spin=0, charge=0, verbose=0
)
mf = scf.RHF(mol).run()
cas = mcscf.CASCI(mf, ncas=8, nelecas=10)
hcore, nuclear_repulsion_energy = cas.get_h1eff()
eri = cas.get_h2eff()
num_orbitals = cas.ncas
eri = ao2mo.restore(1, eri, num_orbitals)
n_alpha, n_beta = cas.nelecas
nelec = (n_alpha, n_beta)
print(
f"Spatial orbitals: {num_orbitals}\nQubits: {num_orbitals * 2}\nElectrons (alpha, beta): {nelec}"
)
Spatial orbitals: 8
Qubits: 16
Electrons (alpha, beta): (5, 5)
2. สร้างตัวอย่างที่มีสัญญาณรบกวน
ในเวิร์กโฟลว์จริง คุณจะออกแบบ ansatz circuit ปรับให้เหมาะกับฮาร์ดแวร์ แล้วสุ่มตัวอย่างบน QPU แต่ในที่นี้เราข้ามขั้นตอนนั้น แล้วสุ่มบิตสตริงแบบสม่ำเสมอ 10,000 ตัวแทน แม้ตัวอย่างของเราจะไม่มีข้อมูลเกี่ยวกับสถานะพื้นจริง แต่เราจะเห็นว่าโพรโทคอล SQD ยังสามารถกู้คืนสถานะพื้นที่แท้จริงได้ โดยปรับปรุงตัวอย่างซ้ำ ๆ ทำ diagonalization และใช้พลังงานในแต่ละรอบเพื่อนำทางการปรับปรุงบิตสตริงในรอบถัดไป เราสามารถกู้คืนสถานะพื้นที่แน่นอนได้ในที่สุดด้วยวิธีนี้ เพราะปริภูมิย่อยที่มีสถานะพื้นเล็กพอที่จะคำนวณได้อย่างแน่นอน กล่าวคือ เนื่องจากเรารู้ว่าแต่ละครึ่งของแต่ละบิตสตริง (8 บิต) ควรมี hamming weight เท่ากับ 5 เราจึงรู้ว่าปริภูมิย่อยฮิลเบิร์ตเต็มของระบบมีขนาด
import numpy as np
from qiskit_addon_sqd.counts import generate_bit_array_uniform
# Generate some uniformly-random bitstrings to simulate QPU samples
rng = np.random.default_rng(24)
bit_array = generate_bit_array_uniform(
10_000, num_orbitals * 2, rand_seed=rng
)
print(
f"Generated {bit_array.num_shots} uniformly-random, {bit_array.num_bits}-qubit samples."
)
Generated 10000 uniformly-random, 16-qubit samples.
3. ประมวลผลภายหลังด้วย SQD
จุดประสงค์ของอัลกอริทึม SQD คือปรับปรุงตัวอย่างที่มีสัญญาณรบกวนซึ่งได้จาก QPU และท้ายที่สุดทำ diagonalization แฮมิลโทเนียนในปริภูมิย่อยที่ขึงด้วยตัวอย่างที่ผ่านการปรับปรุงเหล่านั้น ทำซ้ำดังนี้:
-
ปรับปรุงตัวอย่างโดยเลือกเฉพาะตัวที่มีจำนวนอนุภาคถูกต้องทั้งในระบบย่อยสปินขึ้นและสปินลง
-
ทำ diagonalization ในปริภูมิย่อยขนาดเล็กที่ขึงด้วยตัวอย่างที่ผ่านการปรับปรุงแล้ว และรวบรวมข้อมูลเกี่ยวกับปริภูมิย่อยที่ให้พลังงานดีที่สุด (ต่ำที่สุด)
-
ในแต่ละรอบ:
-
ปรับปรุงตัวอย่างที่มีสัญญาณรบกวนโดยสลับบิตแบบสุ่มตามความน่าจะเป็นในตัวอย่างที่มีจำนวนอนุภาคไม่ถูกต้อง ความน่าจะเป็นคำนวณจากข้อมูลปริภูมิย่อยของ diagonalization ครั้งล่าสุด
-
ทำ diagonalization ในปริภูมิย่อยขนาดเล็กที่ขึงด้วยตัวอย่างที่ผ่านการปรับปรุงแล้ว
-
รวบรวมข้อมูลเกี่ยวกับปริภูมิย่อยที่ให้พลังงานดีที่สุด (ต่ำที่สุด)
-
เราเห็นจากเอาต์พุตว่าอัลกอริทึมลู่เข้าสู่พลังงานสถานะพื้นที่แน่นอนหลังจาก 6 รอบ และการทำ diagonalization ทำบนปริภูมิย่อยฮิลเบิร์ตเต็มที่มีมิติ แน่นอนว่าการทำ diagonalization บนปริภูมิเต็มมักทำไม่ได้ ดังนั้นระบบที่สถานะพื้นมีตัวรองรับแบบเบาบางจึงมีแนวโน้มได้ประโยชน์สูงสุดจากเทคนิค subspace diagonalization เช่น SQD
สำหรับข้อมูลเพิ่มเติมเกี่ยวกับฟังก์ชัน diagonalize_fermionic_hamiltonian ดูที่ เอกสาร API
from functools import partial
from pyscf import fci
from qiskit_addon_sqd.fermion import (
SCIResult,
diagonalize_fermionic_hamiltonian,
solve_sci_batch,
)
exact_energy, _ = fci.direct_spin1.kernel(
hcore, eri, int(num_orbitals), nelec
)
exact_energy += nuclear_repulsion_energy
print(f"Exact (FCI) reference energy: {exact_energy:.6f} Ha\n")
sci_solver = partial(solve_sci_batch, spin_sq=0.0, max_cycle=200)
result_history = []
def callback(results: list[SCIResult]):
result_history.append(results)
iteration = len(result_history)
print(f"Iteration {iteration}")
for i, result in enumerate(results):
error = result.energy + nuclear_repulsion_energy - exact_energy
print(f" Subsample {i}")
print(f" Energy: {result.energy + nuclear_repulsion_energy:.6f}")
print(
f" Subspace dimension: {np.prod(result.sci_state.amplitudes.shape)}"
)
print(f" Error vs exact: {error:.6f} Ha")
samples_per_batch = 20
result = diagonalize_fermionic_hamiltonian(
hcore,
eri,
bit_array,
samples_per_batch=samples_per_batch,
norb=num_orbitals,
nelec=nelec,
occupancies_tol=1e-7,
max_iterations=30,
sci_solver=sci_solver,
symmetrize_spin=True,
callback=callback,
seed=np.random.default_rng(32),
)
Exact (FCI) reference energy: -107.652521 Ha
Iteration 1
Subsample 0
Energy: -106.908481
Subspace dimension: 784
Error vs exact: 0.744040 Ha
Iteration 2
Subsample 0
Energy: -106.934921
Subspace dimension: 1764
Error vs exact: 0.717600 Ha
Iteration 3
Subsample 0
Energy: -106.953430
Subspace dimension: 2209
Error vs exact: 0.699091 Ha
Iteration 4
Subsample 0
Energy: -107.651946
Subspace dimension: 2916
Error vs exact: 0.000575 Ha
Iteration 5
Subsample 0
Energy: -107.652003
Subspace dimension: 3025
Error vs exact: 0.000518 Ha
Iteration 6
Subsample 0
Energy: -107.652521
Subspace dimension: 3136
Error vs exact: 0.000000 Ha
Iteration 7
Subsample 0
Energy: -107.652521
Subspace dimension: 3136
Error vs exact: 0.000000 Ha