주 콘텐츠로 건너뛰기
이 프로젝트는 베타 단계입니다. 버그를 발견하셨나요? GitHub 이슈 만들기. 질문이나 아이디어가 있으신가요? Discussions에서 질문하기 — 피드백을 기다립니다!
이 페이지의 번역 품질은 어떻습니까?

개방 껍질과 폐쇄 껍질 옵션 및 부분공간 구성에 미치는 영향 이해하기

이 가이드에서는 자기 일관적 구성 복원 기법을 사용해 양자 샘플을 후처리하기 위해 qiskit_addon_sqd 패키지에서 부분공간 차원을 선택하는 방법을 보여 드립니다.

더 중요한 점으로, 이 가이드는 open_shell = False 모드와 open_shell = True 모드로 실행할 때 부분공간 구성 동작의 몇 가지 차이도 강조합니다.

  • open_shell = False는 스핀 업 전자와 스핀 다운 전자의 수가 같을 때만 작동합니다.

  • open_shell = True는 스핀 업 전자와 스핀 다운 전자의 수가 다를 때 반드시 사용해야 합니다. 두 수가 같을 때도 사용할 수 있습니다. 다만 이 마지막 경우에는 이 가이드에서 설명하듯이 open_shell = False와 open_shell = True 사이에 생성되는 부분공간의 크기에 차이가 있습니다.

참고: 이 패키지의 전자 구성(비트열) 조작 중 일부는 전체 스핀 대칭성 S2S^2를 보존하는 것을 목표로 합니다. 표준 선택적 구성 상호작용(SCI) 솔버는 S2S^2 보존을 정확하게 강제할 수 없습니다. 따라서 라그랑주 승수를 통해 근사적으로 강제합니다.

고유 상태 솔버에 입력되는 전자 구성의 선택도 스핀 보존에 큰 영향을 줄 수 있습니다. 예를 들어 (전자 2개, 오비탈 2개) 시스템에서 구성 ∣1001⟩|1001\rangle(RHF 상태 ∣0101⟩|0101\rangle 위에 스핀 업 들뜸이 하나 있는 구성)을 샘플링할 수 있는데, 이는 개방 껍질 단일항과 삼중항 상태 (∣1001⟩±∣0110⟩)/2(|1001\rangle ± |0110\rangle) /\sqrt{2}의 선형 결합입니다. 구성 |0110⟩이 샘플링되지 않으면 전체 스핀의 고유 함수를 어느 것도 구성할 수 없으며, 이는 스핀 오염이나 중복으로 이어집니다(구성 |1001⟩은 CI 계산에 포함되지만 CI 벡터에서 계수가 0입니다). 양자 컴퓨터에서 단일 샘플 ∣1001⟩|1001\rangle이 생성되었다고 할 때, sqd 패키지는 이 상황을 다음과 같이 처리합니다.

  • open_shell = False:

    1. 10011001 비트열은 절반으로 나뉘어 스핀 업과 스핀 다운 구성을 나타냅니다. 1010(업)과 0101(다운)입니다.

    2. 고유한 스핀 편극 구성의 목록이 만들어집니다. U=[01,10]\mathcal{U} = [01, 10].

    3. 그런 다음 U\mathcal{U} 원소의 가능한 모든 조합을 고려하여 기저를 구성합니다. {∣0101⟩,∣0110⟩,∣1001⟩,∣1010⟩}\left \{ |0101\rangle, |0110\rangle , |1001\rangle , |1010\rangle \right \}이며, 여기에는 단일항과 삼중항 상태가 포함됩니다.

  • open_shell = True:

    1. 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개이고 샘플링된 비트열은 0001001000010010과 0100100001001000이지만, 스핀 종류별로 전자 구성이 네 개 생성된다는 점에 유의하세요. 이 경우 고유한 스핀 편극 구성의 집합은 다음과 같습니다.

U={0001,0010,0100,1000}\mathcal{U} = \{ 0001, 0010, 0100, 1000 \}

이를 십진수로 표현하면 다음과 같습니다.

U10={1,2,4,8}\mathcal{U}_{10} = \{ 1, 2, 4, 8 \}

부분공간의 기저:

고유 상태 솔버는 스핀 업과 스핀 다운 비트열의 가능한 모든 쌍을 취해 부분공간의 기저 B\mathcal{B}를 구성합니다.

  • 요소 1: ∣00010001⟩|00010001\rangle

  • 요소 2: ∣00010010⟩|00010010\rangle

  • 요소 3: ∣00010100⟩|00010100\rangle

  • 요소 4: ∣00011000⟩|00011000\rangle

  • 요소 5: ∣00100001⟩|00100001\rangle

  • 요소 6: ∣00100010⟩|00100010\rangle

  • 요소 7: ∣00100100⟩|00100100\rangle

  • 요소 8: ∣00101000⟩|00101000\rangle

  • 요소 9: ∣01000001⟩|01000001\rangle

  • 요소 10: ∣01000010⟩|01000010\rangle

  • 요소 11: ∣01000100⟩|01000100\rangle

  • 요소 12: ∣01001000⟩|01001000\rangle

  • 요소 13: ∣10000001⟩|10000001\rangle

  • 요소 14: ∣10000010⟩|10000010\rangle

  • 요소 15: ∣10000100⟩|10000100\rangle

  • 요소 16: ∣10001000⟩|10001000\rangle

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>

부분공간 차원의 상한은 2⋅2 \cdot (samples_per_batch)2^2입니다.

개방 껍질​

이 예제는 (전자 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로 지정할 때보다 기저가 작아집니다. 부분공간의 기저:

고유 상태 솔버는 스핀 업과 스핀 다운 비트열의 가능한 모든 쌍을 취해 부분공간의 기저 B\mathcal{B}를 구성합니다.

  • 요소 1: ∣00010010⟩|00010010\rangle

  • 요소 2: ∣00011000⟩|00011000\rangle

  • 요소 3: ∣01000010⟩|01000010\rangle

  • 요소 4: ∣01001000⟩|01001000\rangle

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)2^2입니다.