격자 해밀토니안의 Krylov 양자 대각화
사용 시간 예상: Heron r2에서 20분 (참고: 이는 예상치이며, 실제 실행 시간은 다를 수 있습니다.)
# 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
배경
이 튜토리얼은 Qiskit 패턴의 맥락에서 Krylov 양자 대각화 알고리즘(KQD)을 구현하는 방법을 설명합니다. 먼저 알고리즘의 이론적 배경을 학습한 후, QPU에서의 실행 데모를 확인할 수 있습니다.
다양한 분야에서 양자 시스템의 바닥 상태 특성을 파악하는 것이 중요합니다. 입자와 힘의 근본적인 성질을 이해하고, 복잡한 물질의 동작을 예측·이해하며, 생화학적 상호작용과 반응을 이해하는 것이 그 예입니다. 힐베르트 공간의 지수적 증가와 얽힌 시스템에서 발생하는 상관관계로 인해, 고전 알고리즘은 규모가 커지는 양자 시스템에서 이 문제를 풀기 어렵습니다. 한쪽 극단에는 양자 하드웨어를 활용하는 기존 방식인 변분 양자 방법(예: 변분 양자 고유값 분해기)이 있습니다. 이 기법들은 최적화 과정에서 많은 함수 호출이 필요하고, 고급 오류 완화 기법을 적용하면 리소스 오버헤드가 커져 소규모 시스템에서만 효과적이라는 한계가 있습니다. 반대쪽 극단에는 성능 보장이 있는 내결함성 양자 방법(예: 양자 위상 추정)이 있으며, 이는 내결함성 장치에서만 실행 가능한 깊은 Circuit을 요구합니다. 이러한 이유로, 여기서는 부분 공간 방법(이 리뷰 논문 참조)에 기반한 양자 알고리즘인 Krylov 양자 대각화(KQD) 알고리즘을 소개합니다. 이 알고리즘은 기존 양자 하드웨어에서 대규모[1]로 잘 작동하며, 위상 추정과 유사한 성능 보장을 갖추고, 고급 오류 완화 기법과 호환되며, 고전적으로는 접근하기 어려운 결과를 제공할 수 있습니다.
요구 사항
이 튜토리얼을 시작하기 전에 다음이 설치되어 있는지 확인하세요:
- Qiskit SDK v2.0 이상(시각화 지원 포함)
- Qiskit Runtime v0.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단계: 고전적 입력을 양자 문제로 매핑하기
크릴로프 공간
차수 의 크릴로프 공간 은 행렬 의 거듭제곱(최대 )을 기준 벡터 에 곱하여 얻은 벡터들로 생성되는 공간입니다.