Vai al contenuto principale
Questo progetto è in fase beta. Hai trovato un bug? Apri una issue su GitHub. Hai una domanda o un'idea? Chiedi su GitHub Discussions — apprezziamo il tuo feedback!
Com'è la qualità della traduzione su questa pagina?

Aggiungi transizioni fermioniche al pool di configurazioni

Qui mostriamo le funzionalità per ampliare il pool di configurazioni elettroniche ottenuto tramite l'azione di operatori di transizione su ciascuna configurazione elettronica.

Mostriamo come aggiungere salti di singolo elettrone del tipo:

cpσ†cqσ∣x⟩c^\dagger_{p\sigma} c_{q\sigma} |\textbf{x} \rangle

per p,q=1,...,Norbp, q = 1, ..., N_\textrm{orb} e σ∈{↑,↓}\sigma \in \{ \uparrow, \downarrow\}, e per tutti i ∣x⟩|\textbf{x} \rangle nel batch di configurazioni elettroniche. Iniziamo generando un batch di configurazioni elettroniche casuali:

# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util

_needed = {"numpy": "numpy", "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")
import numpy as np

n_qubits = 8
n_orb = n_qubits // 2

rand_seed = 22
np.random.seed(rand_seed)

# Generate some random bitstrings for testing
def random_bitstrings(n_samples, n_qubits):
return (
np.round(np.random.rand(n_samples, n_qubits))
.astype("int")
.astype("bool")
)

bitstring_matrix = random_bitstrings(100, n_qubits)

Gli operatori di eccitazione sono specificati all'interno di un array numpy la cui lunghezza è pari al numero di nodi fermionici (o qubit). Ogni elemento dell'array deve essere una stringa che può assumere i valori:

  • 'I': Identity

  • '+': operatore di creazione

  • '-': operatore di annichilazione

Generiamo tutte le possibili transizioni di singolo elettrone (tra specie di spin uguali).

transitions_single = np.array(
[
["I" for i in range(2 * n_orb)]
for j in range(4 * (n_orb**2 - n_orb) // 2 + 1)
]
)
count = 1
for i in range(n_orb):
for j in range(i + 1, n_orb):
# spin up
transitions_single[count, i] = "+"
transitions_single[count, j] = "-"
count += 1
transitions_single[count, i] = "-"
transitions_single[count, j] = "+"
count += 1

# spin down
transitions_single[count, i + n_orb] = "+"
transitions_single[count, j + n_orb] = "-"
count += 1
transitions_single[count, i + n_orb] = "-"
transitions_single[count, j + n_orb] = "+"
count += 1

print(transitions_single)
[['I' 'I' 'I' 'I' 'I' 'I' 'I' 'I']
['+' '-' 'I' 'I' 'I' 'I' 'I' 'I']
['-' '+' 'I' 'I' 'I' 'I' 'I' 'I']
['I' 'I' 'I' 'I' '+' '-' 'I' 'I']
['I' 'I' 'I' 'I' '-' '+' 'I' 'I']
['+' 'I' '-' 'I' 'I' 'I' 'I' 'I']
['-' 'I' '+' 'I' 'I' 'I' 'I' 'I']
['I' 'I' 'I' 'I' '+' 'I' '-' 'I']
['I' 'I' 'I' 'I' '-' 'I' '+' 'I']
['+' 'I' 'I' '-' 'I' 'I' 'I' 'I']
['-' 'I' 'I' '+' 'I' 'I' 'I' 'I']
['I' 'I' 'I' 'I' '+' 'I' 'I' '-']
['I' 'I' 'I' 'I' '-' 'I' 'I' '+']
['I' '+' '-' 'I' 'I' 'I' 'I' 'I']
['I' '-' '+' 'I' 'I' 'I' 'I' 'I']
['I' 'I' 'I' 'I' 'I' '+' '-' 'I']
['I' 'I' 'I' 'I' 'I' '-' '+' 'I']
['I' '+' 'I' '-' 'I' 'I' 'I' 'I']
['I' '-' 'I' '+' 'I' 'I' 'I' 'I']
['I' 'I' 'I' 'I' 'I' '+' 'I' '-']
['I' 'I' 'I' 'I' 'I' '-' 'I' '+']
['I' 'I' '+' '-' 'I' 'I' 'I' 'I']
['I' 'I' '-' '+' 'I' 'I' 'I' 'I']
['I' 'I' 'I' 'I' 'I' 'I' '+' '-']
['I' 'I' 'I' 'I' 'I' 'I' '-' '+']]

Ora applichiamo gli operatori di transizione alle configurazioni in bitstring_matrix:

from qiskit_addon_sqd.fermion import enlarge_batch_from_transitions

bitstring_matrix_aug = enlarge_batch_from_transitions(
bitstring_matrix, transitions_single
)

print(bitstring_matrix_aug.shape)
print(bitstring_matrix_aug)
(723, 8)
[[False False False ... False False True]
[False True False ... True False False]
[ True True True ... True False True]
...
[ True False True ... False False True]
[ True True True ... True False True]
[False False False ... False False True]]