القطرنة الكمومية بطريقة كريلوف لهاميلتونيات الشبكة
تقدير الاستخدام: 20 دقيقة على Heron r2 (ملاحظة: هذا تقدير فقط. قد يختلف وقت التشغيل الفعلي لديك.)
# Added by doQumentation — required packages for this notebook
!pip install -q matplotlib numpy qiskit qiskit-ibm-runtime scipy sympy
# This cell is hidden from users – it disables some lint rules
# ruff: noqa: E402 E722 F601
الخلفية
يوضح هذا البرنامج التعليمي كيفية تنفيذ خوارزمية القطرنة الكمومية بطريقة كريلوف (KQD) في سياق أنماط Qiskit. ستتعلم أولاً النظرية الكامنة وراء الخوارزمية ثم سترى عرضاً توضيحياً لتنفيذها على وحدة معالجة كمية (QPU).
عبر مختلف التخصصات، نهتم بمعرفة خصائص الحالة الأرضية للأنظمة الكمية. تشمل الأمثلة فهم الطبيعة الأساسية للجسيمات والقوى، والتنبؤ بسلوك المواد المعقدة وفهمه، وفهم التفاعلات والتفاعلات الكيميائية الحيوية. بسبب النمو الأسي لفضاء هيلبرت والارتباط الذي ينشأ في الأنظمة المتشابكة، تواجه الخوارزميات الكلاسيكية صعوبة في حل هذه المشكلة للأنظمة الكمية ذات الحجم المتزايد. في أحد طرفي الطيف يوجد النهج الحالي الذي يستفيد من العتاد الكمي ويركز على الطرق التباينية الكمية (على سبيل المثال، حل القيم الذاتية التباينية الكمي). تواجه هذه التقنيات تحديات مع الأجهزة الحالية بسبب العدد الكبير من استدعاءات الدوال المطلوبة في عملية التحسين، مما يضيف عبئاً كبيراً في الموارد بمجرد إدخال تقنيات تخفيف الأخطاء المتقدمة، وبالتالي يحد من فعاليتها للأنظمة الصغيرة. في الطرف الآخر من الطيف، توجد طرق كمية متسامحة مع الأخطاء مع ضمانات أداء (على سبيل المثال، تقدير الطور الكمي)، والتي تتطلب دوائر عميقة لا يمكن تنفيذها إلا على جهاز متسامح مع الأخطاء. لهذه الأسباب، نقدم هنا خوارزمية كمية تعتمد على طرق الفضاء الفرعي (كما هو موصوف في هذه الورقة المراجعة)، خوارزمية القطرنة الكمومية بطريقة كريلوف (KQD). تعمل هذه الخوارزمية بشكل جيد على نطاق واسع [1] على العتاد الكمي الحالي، وتشترك في ضمانات أداء مماثلة لتقدير الطور، وتتوافق مع تقنيات تخفيف الأخطاء المتقدم ة، ويمكن أن توفر نتائج لا يمكن الوصول إليها كلاسيكياً.
المتطلبات
قبل البدء بهذا البرنامج التعليمي، تأكد من تثبيت ما يلي:
- Qiskit SDK الإصدار 2.0 أو أحدث، مع دعم التصور المرئي
- Qiskit Runtime الإصدار 0.22 أو أحدث (
pip install qiskit-ibm-runtime)
الإعداد
import numpy as np
import scipy as sp
import matplotlib.pylab as plt
from typing import Union, List
import itertools as it
import copy
from sympy import Matrix
import warnings
warnings.filterwarnings("ignore")
from qiskit.quantum_info import SparsePauliOp, Pauli, StabilizerState
from qiskit.circuit import Parameter, IfElseOp
from qiskit import QuantumCircuit, QuantumRegister
from qiskit.circuit.library import PauliEvolutionGate
from qiskit.synthesis import LieTrotter
from qiskit.transpiler import Target, CouplingMap
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit_ibm_runtime import (
QiskitRuntimeService,
EstimatorV2 as Estimator,
)
def solve_regularized_gen_eig(
h: np.ndarray,
s: np.ndarray,
threshold: float,
k: int = 1,
return_dimn: bool = False,
) -> Union[float, List[float]]:
"""
Method for solving the generalized eigenvalue problem with regularization
Args:
h (numpy.ndarray):
The effective representation of the matrix in the Krylov subspace
s (numpy.ndarray):
The matrix of overlaps between vectors of the Krylov subspace
threshold (float):
Cut-off value for the eigenvalue of s
k (int):
Number of eigenvalues to return
return_dimn (bool):
Whether to return the size of the regularized subspace
Returns:
lowest k-eigenvalue(s) that are the solution of the regularized generalized eigenvalue problem
"""
s_vals, s_vecs = sp.linalg.eigh(s)
s_vecs = s_vecs.T
good_vecs = np.array(
[vec for val, vec in zip(s_vals, s_vecs) if val > threshold]
)
h_reg = good_vecs.conj() @ h @ good_vecs.T
s_reg = good_vecs.conj() @ s @ good_vecs.T
if k == 1:
if return_dimn:
return sp.linalg.eigh(h_reg, s_reg)[0][0], len(good_vecs)
else:
return sp.linalg.eigh(h_reg, s_reg)[0][0]
else:
if return_dimn:
return sp.linalg.eigh(h_reg, s_reg)[0][:k], len(good_vecs)
else:
return sp.linalg.eigh(h_reg, s_reg)[0][:k]
def single_particle_gs(H_op, n_qubits):
"""
Find the ground state of the single particle(excitation) sector
"""
H_x = []
for p, coeff in H_op.to_list():
H_x.append(set([i for i, v in enumerate(Pauli(p).x) if v]))
H_z = []
for p, coeff in H_op.to_list():
H_z.append(set([i for i, v in enumerate(Pauli(p).z) if v]))
H_c = H_op.coeffs
print("n_sys_qubits", n_qubits)
n_exc = 1
sub_dimn = int(sp.special.comb(n_qubits + 1, n_exc))
print("n_exc", n_exc, ", subspace dimension", sub_dimn)
few_particle_H = np.zeros((sub_dimn, sub_dimn), dtype=complex)
sparse_vecs = [
set(vec) for vec in it.combinations(range(n_qubits + 1), r=n_exc)
] # list all of the possible sets of n_exc indices of 1s in n_exc-particle states
m = 0
for i, i_set in enumerate(sparse_vecs):
for j, j_set in enumerate(sparse_vecs):
m += 1
if len(i_set.symmetric_difference(j_set)) <= 2:
for p_x, p_z, coeff in zip(H_x, H_z, H_c):
if i_set.symmetric_difference(j_set) == p_x:
sgn = ((-1j) ** len(p_x.intersection(p_z))) * (
(-1) ** len(i_set.intersection(p_z))
)
else:
sgn = 0
few_particle_H[i, j] += sgn * coeff
gs_en = min(np.linalg.eigvalsh(few_particle_H))
print("single particle ground state energy: ", gs_en)
return gs_en
الخطوة 1: تعيين المدخلات ال كلاسيكية إلى مشكلة كمية
فضاء كريلوف
فضاء كريلوف من الرتبة هو الفضاء المولّ د بالمتجهات المحصل عليها بضرب قوى أعلى من مصفوفة ، حتى ، بمتجه مرجعي .
إذا كانت المصفوفة هي الهاميلتونية ، فسنشير إلى الفضاء المقابل باسم فضاء كريلوف القوي . في الحالة التي يكون فيها هو مؤثر التطور الزمني المولّد بالهاميلتونية ، سنشير إلى الفضاء باسم فضاء كريلوف الوحدوي . لا يمكن توليد الفضاء الفرعي القوي لكريلوف الذي نستخدمه كلاسيكياً مباشرة على حاسوب كمي لأن ليس مؤثراً وحدوياً. بدلاً من ذلك، يمكننا استخدام مؤثر التطور الزمني الذي يمكن إثبات أنه يعطي ضمانات تقارب مماثلة للطريقة القوية. تصبح قوى حينها خطوات زمنية مختلفة .
انظر الملحق للاطلاع على اشتقاق مفصل لكيفية تمثيل فضاء كريلوف الوحدوي للحالات الذاتية منخفضة الطاقة بدقة.