Înțelege opțiunile pentru strat deschis versus strat închis și efectul asupra construcției subspațiului
În acest ghid vom arăta cum să alegi dimensiunile subspațiului în pachetul qiskit_addon_sqd pentru a post-procesa eșantioane cuantice folosind tehnica de recuperare auto-consistentă a configurațiilor.
Mai important, acest ghid evidențiază și unele diferențe de comportament în construcția subspațiului atunci când se rulează în modurile open_shell = False sau open_shell = True:
-
open_shell = Falsefuncționează doar când numărul de electroni cu spin în sus și cu spin în jos este același. -
open_shell = Truetrebuie folosit când numărul de electroni cu spin în sus și cu spin în jos este diferit. Poate fi folosit și când numărul de electroni cu spin în sus și cu spin în jos este același. Totuși, în acest ultim caz, există o diferență între dimensiunile subspațiilor generate deopen_shell = Falseșiopen_shell = True, după cum se discută în acest ghid.
NOTĂ: Unele dintre manipulările configurațiilor electronice (șiruri de biți) din acest pachet au ca scop păstrarea simetriei de spin total . Solverele standard de Interacțiune de Configurații Selectate (SCI) nu pot impune exact conservarea lui . În consecință, o fac aproximativ printr-un multiplicator Lagrange.
Alegerea configurațiilor electronice care intră în solverul de stări proprii poate avea, de asemenea, un efect puternic asupra conservării spinului. De exemplu, într-un sistem (2 electroni, 2 orbitali), se poate eșantiona configurația (având o singură excitație cu spin în sus peste starea RHF ), care este o combinație liniară a stărilor singlet și triplet cu strat deschis, respectiv . Dacă configurația |0110⟩ nu este eșantionată, nu se poate construi nici una dintre funcțiile proprii de spin total, ceea ce duce la contaminare de spin sau redundanță (configurația |1001⟩ este implicată într-un calcul CI, dar are coeficientul 0 în vectorul CI). Dat fiind că în computerul cuantic se generează un singur eșantion , iată cum gestionează pachetul sqd această situație:
-
open_shell = False:-
Șirul de biți este împărțit în jumătate, reprezentând configurațiile cu spin în sus și cu spin în jos: (sus) și (jos).
-
Se construiește lista configurațiilor unice polarizate în spin: .
-
Considerăm apoi toate combinațiile posibile ale elementelor lui pentru a forma baza: , care conține stările singlet și triplet.
-
-
open_shell = True:- Spre deosebire de cazul
open_shell = False, nu combinăm jumătățile șirului de biți pentru a forma baza.
- Spre deosebire de cazul
Strat închis
Acest exemplu arată cum sunt manipulate șirurile de biți într-un sistem (2 electroni, 4 orbitali).
# 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
Specifică manual un dicționar de rezultate ale măsurătorilor:
counts_dict = {
"00010010": 1 / 2.0 - 0.01,
"01001000": 1 / 2.0 - 0.01,
"00010001": 0.02,
}
Transformă dict-ul de numărători într-o matrice de șiruri de biți și un tablou de probabilități pentru post-procesare:
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]
Subeșantionează un singur lot de dimensiune doi:
-
n_batches = 1: Numărul de loturi de configurații folosite de diferitele apeluri ale solverului de stări proprii -
samples_per_batch = 2: Numărul de configurații unice incluse în fiecare lot
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]]
Obține reprezentarea zecimală a șirurilor de biți cu spin în sus și cu spin în jos folosite de solverul de stări proprii.
Primul element din tuplu corespunde reprezentării zecimale a configurațiilor cu spin în sus, iar al doilea element din tuplu corespunde reprezentării zecimale a configurațiilor cu spin în jos:
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))
Observă că, deși numărul de eșantioane per lot este doi, iar șirurile de biți eșantionate sunt: și , se generează patru configurații electronice per specie de spin. În acest caz, mulțimea configurațiilor unice polarizate în spin este dată de:
cu reprezentarea zecimală în baza 10
Baza subspațiului:
Solverul de stări proprii ia toate perechile posibile de șiruri de biți cu spin în sus și cu spin în jos pentru a construi baza a subspațiului:
-
Elementul 1:
-
Elementul 2:
-
Elementul 3:
-
Elementul 4:
-
Elementul 5:
-
Elementul 6:
-
Elementul 7:
-
Elementul 8:
-
Elementul 9:
-
Elementul 10:
-
Elementul 11:
-
Elementul 12:
-
Elementul 13:
-
Elementul 14:
-
Elementul 15:
-
Elementul 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>
Dimensiunea subspațiului este limitată superior de: (samples_per_batch).
Strat deschis
Acest exemplu arată cum sunt manipulate șirurile de biți într-un sistem (2 electroni, 4 orbitali).
# Specify molecule properties
num_orbitals = 4
num_elec_a = num_elec_b = 1
open_shell = True
Specifică manual un dicționar de rezultate ale măsurătorilor:
counts_dict = {
"00010010": 1 / 2.0 - 0.01,
"01001000": 1 / 2.0 - 0.01,
"00010001": 0.02,
}
Transformă dict-ul de numărători într-o matrice de șiruri de biți și un tablou de probabilități pentru post-procesare:
# 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]
Subeșantionează un singur lot de dimensiune doi:
-
n_batches = 1: Numărul de loturi de configurații folosite de diferitele apeluri ale solverului de stări proprii -
samples_per_batch = 2: Numărul de configurații unice incluse în fiecare lot
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]]
Obține reprezentarea zecimală a șirurilor de biți cu spin în sus și cu spin în jos folosite de solverul de stări proprii.
Primul element din tuplu corespunde reprezentării zecimale a configurațiilor cu spin în sus, iar al doilea element din tuplu corespunde reprezentării zecimale a configurațiilor cu spin în jos:
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))
Dacă specificăm open_shell = True, nu includem toate jumătățile unice de șiruri de biți ca configurații cu spin în sus și cu spin în jos, obținând astfel o bază mai mică decât atunci când se specifică open_shell = False.
Baza subspațiului:
Solverul de stări proprii ia toate perechile posibile de șiruri de biți cu spin în sus și cu spin în jos pentru a construi baza a subspațiului:
-
Elementul 1:
-
Elementul 2:
-
Elementul 3:
-
Elementul 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>
Dimensiunea subspațiului este limitată superior de: (samples_per_batch).