Comprender las opciones de «capa abierta» frente a «capa cerrada» y su efecto en la construcción de subespacios
En esta guía, mostraremos cómo elegir las dimensiones del subespacio en el qiskit_addon_sqd paquete para procesar posteriormente muestras cuánticas utilizando la técnica de recuperación de configuración autoconsistente.
Y lo que es más importante, esta guía también destaca algunas diferencias en el comportamiento de la construcción del subespacio cuando se ejecuta en open_shell = False los modos o open_shell = True :
-
open_shell = Falsesolo funciona cuando el número de electrones en fase de aceleración y de desaceleración es el mismo. -
open_shell = TrueDebe utilizarse cuando el número de electrones en fase de aceleración y de desaceleración es diferente. También se puede utilizar cuando el número de electrones en estado de aceleración y de desaceleración es el mismo. Sin embargo, en este último caso, existe una diferencia en el tamaño de los subespacios generados entreopen_shell = Falseyopen_shell = True, tal y como se explica en esta guía.
NOTA: Algunas de las manipulaciones de la configuración electrónica (cadena de bits) de este paquete tienen como objetivo preservar la simetría de espín total . Los solucionadores estándar de la Interacción de Configuración Seleccionada (SCI) no pueden imponer exactamente la conservación de . Por consiguiente, lo hacen, aproximadamente, mediante un multiplicador de Lagrange.
La elección de las configuraciones electrónicas que se introducen en el solucionador de estados propios también puede tener un gran impacto en la conservación del espín. Por ejemplo, en un sistema (2 electrones, 2 orbitales), se puede muestrear la configuración (que presenta una única excitación de espín hacia arriba sobre el estado RHF ), la cual es una combinación lineal de los estados de singulete y triplete de capa abierta, respectivamente . Si no se incluye la configuración |0110⟩, no es posible construir ninguna de las funciones propias del espín total, lo que da lugar a contaminación o redundancia de espín (la configuración |1001⟩ está incluida en un cálculo de CI, pero tiene coeficiente 0 en el vector CI). Dado que en el ordenador cuántico se genera una única muestra , así es como el sqd paquete gestiona esta situación:
-
open_shell = False:-
La cadena de bits « » se divide en dos partes, que representan las configuraciones de «spin-up» y «spin-down»: « » (arriba) y « » (abajo).
-
Se ha elaborado la lista de configuraciones únicas con polarización de espín: .
-
A continuación, consideramos todas las combinaciones posibles de elementos de la función de para formar la base: , que contiene los estados de singulete y de triplete.
-
-
open_shell = True:- A diferencia de lo que
open_shell = Falseocurre en ese caso, no combinamos las mitades de la cadena de bits para formar la base.
- A diferencia de lo que
De carcasa cerrada
Este ejemplo muestra cómo se manipulan las cadenas de bits en un sistema (de 2 electrones y 4 orbitales).
# Specify molecule properties
num_orbitals = 4
num_elec_a = num_elec_b = 1
open_shell = FalseEspecifica manualmente un diccionario de resultados de medición:
counts_dict = {
"00010010": 1 / 2.0 - 0.01,
"01001000": 1 / 2.0 - 0.01,
"00010001": 0.02,
}Transforma los recuentos dict en una matriz de cadenas de bits y en una matriz de probabilidades para su posterior procesamiento:
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)Output:
[[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]
Realizar un submuestreo de un único lote de tamaño dos:
n_batches = 1: Número de lotes de configuraciones utilizados por las diferentes llamadas al solucionador de estados propiossamples_per_batch = 2: Número de configuraciones únicas que se deben incluir en cada lote
from qiskit_addon_sqd.subsampling import postselect_and_subsample
n_batches = 1
samples_per_batch = 2
# seed for random number generator
rand_seed = 48
# Generate the batches
batches = postselect_and_subsample(
bitstring_matrix_full,
probs_arr_full,
hamming_right=num_elec_a,
hamming_left=num_elec_b,
samples_per_batch=samples_per_batch,
num_batches=n_batches,
rand_seed=rand_seed,
)
print(batches[0])Output:
[[False False False True False False True False]
[False True False False True False False False]]
Obtener la representación decimal de las cadenas de bits de «spin-up» y «spin-down» utilizadas por el solucionador de estados propios.
El primer elemento de la tupla corresponde a la representación decimal de las configuraciones de espín hacia arriba, mientras que el segundo elemento de la tupla corresponde a la representación decimal de las configuraciones de espín hacia abajo:
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)Output:
(array([1, 2, 4, 8], dtype=int64), array([1, 2, 4, 8], dtype=int64))
Cabe señalar que, aunque el número de muestras por lote es dos, y las cadenas de bits muestreadas son: y , se generan cuatro configuraciones electrónicas por especie de espín. En este caso, el conjunto de configuraciones únicas con polarización de espín viene dado por:
cuya representación decimal base-10 es
Base del subespacio:
El solucionador de estados propios toma todos los pares posibles de cadenas de bits de espín hacia arriba y espín hacia abajo para construir la base del subespacio:
-
Elemento 1:
-
Elemento 2:
-
Elemento 3:
-
Elemento 4:
-
Elemento 5:
-
Elemento 6:
-
Elemento 7:
-
Elemento 8:
-
Elemento 9:
-
Elemento 10:
-
Elemento 11:
-
Elemento 12:
-
Elemento 13:
-
Elemento 14:
-
Elemento 15:
-
Elemento 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)
+ ">"
)Output:
Basis elements of the subspace:
|00010001>
|00010010>
|00010100>
|00011000>
|00100001>
|00100010>
|00100100>
|00101000>
|01000001>
|01000010>
|01000100>
|01001000>
|10000001>
|10000010>
|10000100>
|10001000>
La dimensión del subespacio tiene como límite superior : (samples_per_batch) .
De carcasa abierta
Este ejemplo muestra cómo se manipulan las cadenas de bits en un sistema (de 2 electrones y 4 orbitales).
# Specify molecule properties
num_orbitals = 4
num_elec_a = num_elec_b = 1
open_shell = TrueEspecifica manualmente un diccionario de resultados de medición:
counts_dict = {
"00010010": 1 / 2.0 - 0.01,
"01001000": 1 / 2.0 - 0.01,
"00010001": 0.02,
}Transforma los recuentos dict en una matriz de cadenas de bits y en una matriz de probabilidades para su posterior procesamiento:
# 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)Output:
[[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]
Realizar un submuestreo de un único lote de tamaño dos:
n_batches = 1: Número de lotes de configuraciones utilizados por las diferentes llamadas al solucionador de estados propiossamples_per_batch = 2: Número de configuraciones únicas que se deben incluir en cada lote
n_batches = 1
samples_per_batch = 2
# seed for random number generator
rand_seed = 48
# Generate the batches
batches = postselect_and_subsample(
bitstring_matrix_full,
probs_arr_full,
hamming_right=num_elec_a,
hamming_left=num_elec_b,
samples_per_batch=samples_per_batch,
num_batches=n_batches,
rand_seed=rand_seed,
)
print(batches[0])Output:
[[False False False True False False True False]
[False True False False True False False False]]
Obtener la representación decimal de las cadenas de bits de «spin-up» y «spin-down» utilizadas por el solucionador de estados propios.
El primer elemento de la tupla corresponde a la representación decimal de las configuraciones de espín hacia arriba, mientras que el segundo elemento de la tupla corresponde a la representación decimal de las configuraciones de espín hacia abajo:
ci_strs = bitstring_matrix_to_ci_strs(batches[0], open_shell=open_shell)
print(ci_strs)Output:
(array([2, 8], dtype=int64), array([1, 4], dtype=int64))
Si especificamos que open_shell = True, no incluimos todas las semicadenas de bits únicas como configuraciones de «spin-up» y «spin-down», lo que da lugar a una base más reducida que cuando se especifica open_shell = False.
Base del subespacio:
El solucionador de estados propios toma todos los pares posibles de cadenas de bits de espín hacia arriba y espín hacia abajo para construir la base del subespacio:
-
Elemento 1:
-
Elemento 2:
-
Elemento 3:
-
Elemento 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)
+ ">"
)Output:
Basis elements of the subspace:
|00100001>
|00100100>
|10000001>
|10000100>
La dimensión del subespacio tiene como límite superior : (samples_per_batch) .