개방 껍질과 폐쇄 껍질 옵션 및 부분공간 구성에 미치는 영향 이해하기
이 가이드에서는 자기 일관적 구성 복원 기법을 사용해 양자 샘플을 후처리하기 위해 qiskit_addon_sqd 패키지에서 부분공간 차원을 선택하는 방법을 보여 드립니다.
더 중요한 점으로, 이 가이드는 open_shell = False 모드와 open_shell = True 모드로 실행할 때 부분공간 구성 동작의 몇 가지 차이도 강조합니다.
-
open_shell = False는 스핀 업 전자와 스핀 다운 전자의 수가 같을 때만 작동합니다. -
open_shell = True는 스핀 업 전자와 스핀 다운 전자의 수가 다를 때 반드시 사용해야 합니다. 두 수가 같을 때도 사용할 수 있습니다. 다만 이 마지막 경우에는 이 가이드에서 설명하듯이open_shell = False와open_shell = True사이에 생성되는 부분공간의 크기에 차이가 있습니다.
참고: 이 패키지의 전자 구성(비트열) 조작 중 일부는 전체 스핀 대칭성 를 보존하는 것을 목표로 합니다. 표준 선택적 구성 상호작용(SCI) 솔버는 보존을 정확하게 강제할 수 없습니다. 따라서 라그랑주 승수를 통해 근사적으로 강제합니다.
고유 상태 솔버에 입력되는 전자 구성의 선택도 스핀 보존에 큰 영향을 줄 수 있습니다. 예를 들어 (전자 2개, 오비탈 2개) 시스템에서 구성 (RHF 상태 위에 스핀 업 들뜸이 하나 있는 구성)을 샘플링할 수 있는데, 이는 개방 껍질 단일항과 삼중항 상태 의 선형 결합입니다. 구성 |0110⟩이 샘플링되지 않으면 전체 스핀의 고유 함수를 어느 것도 구성할 수 없으며, 이는 스핀 오염이나 중복으로 이어집니다(구성 |1001⟩은 CI 계산에 포함되지만 CI 벡터에서 계수가 0입니다). 양자 컴퓨터에서 단일 샘플 이 생성되었다고 할 때, sqd 패키지는 이 상황을 다음과 같이 처리합니다.
-
open_shell = False:-
비트열은 절반으로 나뉘어 스핀 업과 스핀 다운 구성을 나타냅니다. (업)과 (다운)입니다.
-
고유한 스핀 편극 구성의 목록이 만들어집니다. .
-
그런 다음 원소의 가능한 모든 조합을 고려하여 기저를 구성합니다. 이며, 여기에는 단일항과 삼중항 상태가 포함됩니다.
-
-
open_shell = True:open_shell = False인 경우와 달리, 비트열의 절반들을 결합하여 기저를 구성하지 않습니다.
폐쇄 껍질
이 예제는 (전자 2개, 오비탈 4개) 시스템에서 비트열이 어떻게 조작되는지 보여 줍니다.
# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util
_needed = {"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")
# Specify molecule properties
num_orbitals = 4
num_elec_a = num_elec_b = 1
open_shell = False
측정 결과의 딕셔너리를 직접 지정합니다.
counts_dict = {
"00010010": 1 / 2.0 - 0.01,
"01001000": 1 / 2.0 - 0.01,
"00010001": 0.02,
}
카운트 dict를 후처리용 비트열 행렬과 확률 배열로 변환합니다.
from qiskit_addon_sqd.counts import counts_to_arrays
# Convert counts into bitstring and probability arrays
bitstring_matrix_full, probs_arr_full = counts_to_arrays(counts_dict)
print(bitstring_matrix_full)
print(probs_arr_full)
[[False False False True False False True False]
[False True False False True False False False]
[False False False True False False False True]]
[0.49 0.49 0.02]
크기 2인 단일 배치를 부분 샘플링합니다.
-
n_batches = 1: 고유 상태 솔버를 여러 번 호출할 때 사용하는 구성 배치의 수 -
samples_per_batch = 2: 각 배치에 포함할 고유한 구성의 수
from qiskit_addon_sqd.subsampling import (
postselect_by_hamming_right_and_left,
subsample,
)
n_batches = 1
samples_per_batch = 2
# seed for random number generator
rand_seed = 48
# Post-select the configurations with the correct Hamming weight on each half
bitstring_matrix_postsel, probs_arr_postsel = (
postselect_by_hamming_right_and_left(
bitstring_matrix_full,
probs_arr_full,
hamming_right=num_elec_a,
hamming_left=num_elec_b,
)
)
# Generate the batches
batches = subsample(
bitstring_matrix_postsel,
probs_arr_postsel,
samples_per_batch,
n_batches,
rand_seed=rand_seed,
)
print(batches[0])
[[False False False True False False True False]
[False True False False True False False False]]
고유 상태 솔버가 사용하는 스핀 업과 스핀 다운 비트열의 십진수 표현을 구합니다.
튜플의 첫 번째 원소는 스핀 업 구성의 십진수 표현에, 두 번째 원소는 스핀 다운 구성의 십진수 표현에 해당합니다.
from qiskit_addon_sqd.fermion import bitstring_matrix_to_ci_strs
ci_strs = bitstring_matrix_to_ci_strs(batches[0], open_shell=open_shell)
print(ci_strs)
(array([1, 2, 4, 8], dtype=int64), array([1, 2, 4, 8], dtype=int64))
배치당 샘플 수는 2개이고 샘플링된 비트열은 과 이지만, 스핀 종류별로 전자 구성이 네 개 생성된다는 점에 유의하세요. 이 경우 고유한 스핀 편극 구성의 집합은 다음과 같습니다.
이를 십진수로 표현하면 다음과 같습니다.
부분공간의 기저:
고유 상태 솔버는 스핀 업과 스핀 다운 비트열의 가능한 모든 쌍을 취해 부분공간의 기저 를 구성합니다.
-
요소 1:
-
요소 2:
-
요소 3:
-
요소 4:
-
요소 5:
-
요소 6:
-
요소 7:
-
요소 8:
-
요소 9:
-
요소 10:
-
요소 11:
-
요소 12:
-
요소 13:
-
요소 14:
-
요소 15:
-
요소 16:
ci_strs_up, ci_strs_dn = ci_strs
print("Basis elements of the subspace:")
for ci_str_up in ci_strs_up:
for ci_str_dn in ci_strs_dn:
format_name = "{0:0" + str(num_orbitals) + "b}"
print(
"|"
+ format_name.format(ci_str_up)
+ format_name.format(ci_str_dn)
+ ">"
)
Basis elements of the subspace:
|00010001>
|00010010>
|00010100>
|00011000>
|00100001>
|00100010>
|00100100>
|00101000>
|01000001>
|01000010>
|01000100>
|01001000>
|10000001>
|10000010>
|10000100>
|10001000>
부분공간 차원의 상한은 (samples_per_batch)입니다.
개방 껍질
이 예제는 (전자 2개, 오비탈 4개) 시스템에서 비트열이 어떻게 조작되는지 보여 줍니다.
# Specify molecule properties
num_orbitals = 4
num_elec_a = num_elec_b = 1
open_shell = True
측정 결과의 딕셔너리를 직접 지정합니다.
counts_dict = {
"00010010": 1 / 2.0 - 0.01,
"01001000": 1 / 2.0 - 0.01,
"00010001": 0.02,
}
카운트 dict를 후처리용 비트열 행렬과 확률 배열로 변환합니다.
# Convert counts into bitstring and probability arrays
bitstring_matrix_full, probs_arr_full = counts_to_arrays(counts_dict)
print(bitstring_matrix_full)
print(probs_arr_full)
[[False False False True False False True False]
[False True False False True False False False]
[False False False True False False False True]]
[0.49 0.49 0.02]
크기 2인 단일 배치를 부분 샘플링합니다.
-
n_batches = 1: 고유 상태 솔버를 여러 번 호출할 때 사용하는 구성 배치의 수 -
samples_per_batch = 2: 각 배치에 포함할 고유한 구성의 수
n_batches = 1
samples_per_batch = 2
# seed for random number generator
rand_seed = 48
# Post-select the configurations with the correct Hamming weight on each half
bitstring_matrix_postsel, probs_arr_postsel = (
postselect_by_hamming_right_and_left(
bitstring_matrix_full,
probs_arr_full,
hamming_right=num_elec_a,
hamming_left=num_elec_b,
)
)
# Generate the batches
batches = subsample(
bitstring_matrix_postsel,
probs_arr_postsel,
samples_per_batch,
n_batches,
rand_seed=rand_seed,
)
print(batches[0])
[[False False False True False False True False]
[False True False False True False False False]]
고유 상태 솔버가 사용하는 스핀 업과 스핀 다운 비트열의 십진수 표현을 구합니다.
튜플의 첫 번째 원소는 스핀 업 구성의 십진수 표현에, 두 번째 원소는 스핀 다운 구성의 십진수 표현에 해당합니다.
ci_strs = bitstring_matrix_to_ci_strs(batches[0], open_shell=open_shell)
print(ci_strs)
(array([2, 8], dtype=int64), array([1, 4], dtype=int64))
open_shell = True로 지정하면 모든 고유한 절반 비트열을 스핀 업과 스핀 다운 구성으로 포함하지 않으므로, open_shell = False로 지정할 때보다 기저가 작아집니다.
부분공간의 기저:
고유 상태 솔버는 스핀 업과 스핀 다운 비트열의 가능한 모든 쌍을 취해 부분공간의 기저 를 구성합니다.
-
요소 1:
-
요소 2:
-
요소 3:
-
요소 4:
ci_strs_up, ci_strs_dn = ci_strs
print("Basis elements of the subspace:")
for ci_str_up in ci_strs_up:
for ci_str_dn in ci_strs_dn:
format_name = "{0:0" + str(num_orbitals) + "b}"
print(
"|"
+ format_name.format(ci_str_up)
+ format_name.format(ci_str_dn)
+ ">"
)
Basis elements of the subspace:
|00100001>
|00100100>
|10000001>
|10000100>
부분공간 차원의 상한은 (samples_per_batch)입니다.