Skip to main content
IBM Quantum Platform

Compreender as opções de camada aberta versus camada fechada e o efeito na construção do subespaço

Neste guia, mostraremos como escolher as dimensões do subespaço no qiskit_addon_sqd pacote para realizar o pós-processamento de amostras quânticas utilizando a técnica de recuperação de configuração autoconsistente.

Mais importante ainda, este guia também destaca algumas diferenças no comportamento da construção do subespaço quando executada nos open_shell = False modos ou open_shell = True :

  • open_shell = False só funciona quando o número de elétrons em aceleração e desaceleração é o mesmo.

  • open_shell = True deve ser utilizado quando o número de elétrons em aceleração e desaceleração for diferente. Também pode ser usado quando o número de elétrons em estado de aceleração e desaceleração é o mesmo. No entanto, neste último caso, há uma diferença nos tamanhos dos subespaços gerados entre open_shell = False e open_shell = True, conforme discutido neste guia.

NOTA: Algumas das manipulações da configuração eletrônica (sequência de bits) neste pacote têm como objetivo preservar a simetria total de spin S2S^2. Os solucionadores padrão de Interação de Configuração Selecionada (SCI) não conseguem impor exatamente a conservação d S2S^2. Consequentemente, eles fazem isso, aproximadamente, por meio de um multiplicador de Lagrange.

A escolha das configurações eletrônicas inseridas no solucionador de estados próprios também pode ter um forte efeito na conservação do spin. Por exemplo, em um sistema (2 elétrons, 2 orbitais), é possível amostrar a configuração 1001|1001\rangle (que possui uma única excitação de spin-up sobre o estado RHF 0101|0101\rangle ), que é uma combinação linear dos estados singletos e tripletos de camada aberta, respectivamente (1001±0110)/2(|1001\rangle ± |0110\rangle) /\sqrt{2}. Se a configuração |0110⟩ não for amostrada, não é possível construir nenhuma função própria do spin total, o que leva à contaminação ou redundância de spin (a configuração |1001⟩ está envolvida em um cálculo de CI, mas possui coeficiente 0 no vetor CI). Como uma única amostra 1001|1001\rangle é gerada no computador quântico, é assim que o sqd pacote lida com essa situação:

  • open_shell = False:

    1. A sequência de bits 10011001 é dividida ao meio, representando as configurações de rotação para cima e para baixo: 1010 (para cima) e 0101 (para baixo).

    2. A lista de configurações únicas com polarização de spin foi elaborada: U=[01,10]\mathcal{U} = [01, 10].

    3. Em seguida, consideramos todas as combinações possíveis de elementos d U\mathcal{U} es para formar a base: {0101,0110,1001,1010}\left \{ |0101\rangle, |0110\rangle , |1001\rangle , |1010\rangle \right \}, que contém os estados singlete e triplete.

  • open_shell = True:

    1. Ao contrário do que open_shell = False ocorre nesse caso, não combinamos as metades da sequência de bits para formar a base.

De estrutura fechada

Este exemplo mostra como as cadeias de bits são manipuladas em um sistema (2 elétrons, 4 orbitais).

# Specify molecule properties
num_orbitals = 4
num_elec_a = num_elec_b = 1
open_shell = False

Especifique manualmente um dicionário de resultados de medição:

counts_dict = {
    "00010010": 1 / 2.0 - 0.01,
    "01001000": 1 / 2.0 - 0.01,
    "00010001": 0.02,
}

Transforme as contagens dict em uma matriz de sequência de bits e em um array de probabilidades para o pós-processamento:

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]

Selecionar uma subamostra de um único lote com tamanho igual a dois:

  • n_batches = 1: Número de lotes de configurações utilizados pelas diferentes chamadas ao solucionador de estados próprios
  • samples_per_batch = 2: Número de configurações únicas a serem incluídas em 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]]

Obter a representação decimal das sequências de bits de spin-up e spin-down utilizadas pelo solucionador de estados próprios.

O primeiro elemento da tupla corresponde à representação decimal das configurações de spin para cima, enquanto o segundo elemento da tupla corresponde à representação decimal das configurações de spin para baixo:

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))

Observe que, embora o número de amostras por lote seja dois, e as sequências de bits amostradas sejam: 0001001000010010 e 0100100001001000, são geradas quatro configurações eletrônicas por espécie de spin. Nesse caso, o conjunto de configurações únicas com polarização de spin é dado por:

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

cuja representação decimal em base-10 é

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

Base do subespaço:

O solucionador de estados próprios considera todos os pares possíveis de sequências de bits com spin para cima e spin para baixo para construir a base B\mathcal{B} do subespaço:

  • Elemento 1: 00010001|00010001\rangle

  • Elemento 2: 00010010|00010010\rangle

  • Elemento 3: 00010100|00010100\rangle

  • Elemento 4: 00011000|00011000\rangle

  • Elemento 5: 00100001|00100001\rangle

  • Elemento 6: 00100010|00100010\rangle

  • Elemento 7: 00100100|00100100\rangle

  • Elemento 8: 00101000|00101000\rangle

  • Elemento 9: 01000001|01000001\rangle

  • Elemento 10: 01000010|01000010\rangle

  • Elemento 11: 01000100|01000100\rangle

  • Elemento 12: 01001000|01001000\rangle

  • Elemento 13: 10000001|10000001\rangle

  • Elemento 14: 10000010|10000010\rangle

  • Elemento 15: 10000100|10000100\rangle

  • Elemento 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)
            + ">"
        )

Output:

Basis elements of the subspace:
|00010001>
|00010010>
|00010100>
|00011000>
|00100001>
|00100010>
|00100100>
|00101000>
|01000001>
|01000010>
|01000100>
|01001000>
|10000001>
|10000010>
|10000100>
|10001000>

A dimensão do subespaço é limitada superiormente por : 22 \cdot (samples_per_batch) 2^2.

Concha aberta

Este exemplo mostra como as cadeias de bits são manipuladas em um sistema (2 elétrons, 4 orbitais).

# Specify molecule properties
num_orbitals = 4
num_elec_a = num_elec_b = 1
open_shell = True

Especifique manualmente um dicionário de resultados de medição:

counts_dict = {
    "00010010": 1 / 2.0 - 0.01,
    "01001000": 1 / 2.0 - 0.01,
    "00010001": 0.02,
}

Transforme as contagens dict em uma matriz de sequência de bits e em um array de probabilidades para o pós-processamento:

# 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]

Selecionar uma subamostra de um único lote com tamanho igual a dois:

  • n_batches = 1: Número de lotes de configurações utilizados pelas diferentes chamadas ao solucionador de estados próprios
  • samples_per_batch = 2: Número de configurações únicas a serem incluídas em 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]]

Obter a representação decimal das sequências de bits de spin-up e spin-down utilizadas pelo solucionador de estados próprios.

O primeiro elemento da tupla corresponde à representação decimal das configurações de spin para cima, enquanto o segundo elemento da tupla corresponde à representação decimal das configurações de spin para baixo:

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))

Se especificarmos que open_shell = True, não incluiremos todas as meias-cadeias de bits únicas como configurações “spin-up” e “spin-down”, resultando assim em uma base menor do que quando especificamos open_shell = False.

Base do subespaço:

O solucionador de estados próprios considera todos os pares possíveis de sequências de bits com spin para cima e spin para baixo para construir a base B\mathcal{B} do subespaço:

  • Elemento 1: 00010010|00010010\rangle

  • Elemento 2: 00011000|00011000\rangle

  • Elemento 3: 01000010|01000010\rangle

  • Elemento 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)
            + ">"
        )

Output:

Basis elements of the subspace:
|00100001>
|00100100>
|10000001>
|10000100>

A dimensão do subespaço é limitada superiormente por : (samples_per_batch) 2^2.

Esta página foi útil?
Relate um bug, erro de digitação ou solicite conteúdo no GitHub.