Skip to main content
IBM Quantum Platform

QfFermionOperator

QfFermionOperator

struct QfFermionOperator

Un operatore fermionico senza spin.

Nota

Si tratta di una struttura dati trasparente rispetto all'API C, i cui meccanismi interni sono implementati interamente in Rust. Il resto di questa pagina descrive la struttura e le relative funzioni per l'utilizzo di questa struttura.



Definizione

Questo operatore è definito da una combinazione lineare di prodotti di operatori di creazione e annichilimento fermionici che agiscono su modi fermionici privi di spin. In altre parole, i singoli termini soddisfano le seguenti relazioni anticommutative: [1]

{ai,aj}={ai,aj}=0,  and  {ai,aj}=δij,\left\{a^\dagger_i, a^\dagger_j\right\} = \left\{a_i, a_j\right\} = 0,~~\text{and}~~ \left\{a_i, a^\dagger_j\right\} = \delta_{ij} \, ,

dove ii e jj non distinguono la specie di spin delle modalità fermioniche a cui fanno riferimento.

Ne consegue che la definizione dell'intero operatore è la seguente:

QfFermionOperator=icijAj^,\text{\texttt{QfFermionOperator}} = \sum_i c_i \bigotimes_j \hat{A_j} \, ,

dove Aj^{aj,aj}\hat{A_j} \in \{ a_j, a^\dagger_j \} e cic_i è il coefficiente (complesso) che costituisce la combinazione lineare dei prodotti. L'indice jj può assumere qualsiasi valore compreso tra 0 e il numero di modi fermionici su cui agisce l'operatore meno 1.



Implementazione

Questa struttura memorizza i termini e i coefficienti in più vettori sparsi, analogamente al formato "compressed sparse row" comunemente utilizzato per le matrici sparse. Più precisamente, un singolo operatore contiene 4 array:

coeffsUn vettore di coefficienti complessi costituito da due numeri in virgola mobile a 64 bit.
actionsUn vettore di valori booleani che memorizza la natura delle operazioni di seconda quantizzazione.
modesUn vettore di interi a 32 bit che memorizza gli indici delle modalità fermioniche su cui è stata eseguita l'operazione.
boundariesUn vettore di numeri interi che indica i confini in e actions modes.

Le voci in actions indicano operatori di creazione (annichilimento) da parte di ( True``False ). Le modalità fermioniche indicizzate da modes sono considerate prive di spin.

Nota

È possibile accedere a copie in sola lettura di questi array interni tramite le rispettive funzioni:

Questa struttura dati consente di creare e manipolare gli operatori in modo molto efficiente. Tuttavia, ciò implica che in qualsiasi momento un operatore possa contenere termini duplicati. Questi devono essere risolti manualmente utilizzando qf_ferm_op_simplify().

Costruzioni

È possibile costruire un nuovo operatore direttamente specificando gli array corrispondenti descritti sopra. In alternativa, un campo vuoto può QfFermionOperator essere inizializzato con e qf_ferm_op_zero() i termini possono essere aggiunti in modo iterativo tramite qf_ferm_op_add_term().

qf_ferm_op_new()Crea un nuovo operatore a partire dagli array forniti.
qf_ferm_op_zero()Costruisce l'operatore di identità additiva.
qf_ferm_op_one()Crea l'operatore di identità moltiplicativo.
qf_ferm_op_add_term()Aggiunge un termine a un file esistente QfFermionOperator.
Nota

A QfFermionOperator può essere liberato con qf_ferm_op_free().

Aritmetica

Le seguenti funzioni consentono di eseguire operazioni aritmetiche:

qf_ferm_op_add()Somma due operatori.
qf_ferm_op_mul()Moltiplica un operatore per uno scalare.
qf_ferm_op_compose()Combina due operatori tra loro.
qf_ferm_op_adjoint()Restituisce l'operatore coniugato ermitiano.

Manipolazione

Le seguenti funzioni forniscono la logica di manipolazione degli operatori:

qf_ferm_op_ichop()Elimina i termini con coefficienti di piccola entità.
qf_ferm_op_simplify()Restituisce un operatore equivalente ma semplificato.
qf_ferm_op_normal_ordered()Restituisce un operatore equivalente con termini ordinati normalmente.
qf_ferm_op_relabel_modes()Rinomina le modalità di un operatore.

Proprietà

Sono disponibili le seguenti funzioni per verificare determinate proprietà di un operatore.

qf_ferm_op_is_hermitian()Restituisce se un operatore è ermitiano.
qf_ferm_op_max_rank()Restituisce il rango massimo dei termini presenti in questo operatore.
qf_ferm_op_conserves_particle_number()Restituisce se un operatore conserva il numero di particelle.

[ 1 ]

https://en.wikipedia.org/wiki/Second _quantizzazione#Operatori_di_creazione_e_annichilimento_dei_fermioni


Membri

qf_ferm_op_new

QfFermionOperator *qf_ferm_op_new(uint64_t num_terms, uint64_t num_actions, const QkComplex64 *coeffs, const bool *actions, const uint32_t *modes, const uint32_t *boundaries)

Crea un nuovo operatore.

Qualsiasi argomento di tipo puntatore può essere NULL se e solo se la lunghezza corrispondente è zero.

Esempio

1uint64_t num_terms = 3;
2uint64_t num_actions = 4;
3bool actions[4] = {true, false, true, false};
4uint32_t modes[4] = {0, 1, 2, 3};
5QkComplex64 coeffs[3] = {{1.0, 0.0}, {-1.0, 0.0}, {0.0, -1.0}};
6uint32_t boundaries[4] = {0, 0, 2, 4};
7QfFermionOperator *op = qf_ferm_op_new(num_terms, num_actions, coeffs,
8                                       actions, modes, boundaries);

Parametri

  • num_terms – Il numero di termini presenti nell'operatore.
  • num_actions – Il numero di azioni sommato su tutti i termini.
  • coeffs – Un puntatore a un array di coefficienti dei termini. La lunghezza di questo array dovrebbe essere num_terms.
  • azioni – Un puntatore a un array di azioni relative a tutti i termini. La lunghezza di questo array dovrebbe essere num_actions.
  • modalità – Un puntatore a un array contenente le modalità di azione per tutti i termini. La lunghezza di questo array dovrebbe essere num_actions.
  • confini – Un puntatore a un array contenente i confini tra i termini. La lunghezza di questo array dovrebbe essere num_terms + 1.

qf_ferm_op_free

void qf_ferm_op_free(QfFermionOperator *op)

Rilascia un operatore esistente.

Esempio

1QfFermionOperator *op = qf_ferm_op_one();
2qf_ferm_op_free(op);

Parametri

  • op – Un puntatore all’operatore fermionico da liberare.

qf_ferm_op_get_coeffs

void qf_ferm_op_get_coeffs(const QfFermionOperator *op, QkComplex64 **coeffs_out, uint64_t *coeffs_len)

Fornisce accesso in sola lettura ai coefficienti dell'operatore.

Vedi anche

La spiegazione della struttura interna dei dati è disponibile qui.

Esempio

 1uint64_t num_terms = 2;
 2uint64_t num_actions = 0;
 3QkComplex64 coeffs[2] = {{1.0, 0.0}, {0.0, -1.0}};
 4uint32_t boundaries[3] = {0, 0, 0};
 5QfFermionOperator *op =
 6    qf_ferm_op_new(num_terms, num_actions, coeffs, NULL, NULL, boundaries);
 7
 8QkComplex64 *coeffs_out;
 9uint64_t *coeffs_len;
10
11qf_ferm_op_get_coeffs(op, &coeffs_out, &coeffs_len);
12
13assert(coeffs_len == 2);
Nota

Questa funzione restituisce una copia dei dati interni.

Parametri

  • op – Un puntatore all’operatore fermionico di cui si desidera accedere ai coefficienti.
  • coeffs_out – Un puntatore all'array di valori complessi in cui scrivere i coefficienti.
  • coeffs_len – Un puntatore all’intero in cui scrivere la lunghezza dell’array di output.

qf_ferm_op_get_actions

void qf_ferm_op_get_actions(const QfFermionOperator *op, bool **actions_out, uint64_t *actions_len)

Fornisce un accesso in sola lettura alle azioni dell'operatore.

Vedi anche

La spiegazione della struttura interna dei dati è disponibile qui.

Esempio

 1uint64_t num_terms = 2;
 2uint64_t num_actions = 2;
 3bool actions[2] = {true, false};
 4uint32_t modes[2] = {0, 1};
 5QkComplex64 coeffs[2] = {{1.0, 0.0}, {0.0, -1.0}};
 6uint32_t boundaries[3] = {0, 0, 2};
 7QfFermionOperator *op =
 8    qf_ferm_op_new(num_terms, num_actions, coeffs, actions, modes, boundaries);
 9
10QkComplex64 *actions_out;
11uint64_t *actions_len;
12
13qf_ferm_op_get_actions(op, &actions_out, &actions_len);
14
15assert(actions_len == 2);
Nota

Questa funzione restituisce una copia dei dati interni.

Parametri

  • op – Un puntatore all’operatore fermionico le cui azioni si desidera accedere.
  • actions_out – Un puntatore all'array di valori booleani in cui scrivere le azioni.
  • actions_len – Un puntatore all'intero in cui scrivere la lunghezza dell'array di output.

qf_ferm_op_get_modes

void qf_ferm_op_get_modes(const QfFermionOperator *op, uint32_t **modes_out, uint64_t *modes_len)

Fornisce accesso in sola lettura agli indici delle modalità su cui l’operatore ha agito.

Vedi anche

La spiegazione della struttura interna dei dati è disponibile qui.

Esempio

 1uint64_t num_terms = 2;
 2uint64_t num_actions = 2;
 3bool actions[2] = {true, false};
 4uint32_t modes[2] = {0, 1};
 5QkComplex64 coeffs[2] = {{1.0, 0.0}, {0.0, -1.0}};
 6uint32_t boundaries[3] = {0, 0, 2};
 7QfFermionOperator *op =
 8    qf_ferm_op_new(num_terms, num_actions, coeffs, actions, modes, boundaries);
 9
10QkComplex64 *modes_out;
11uint64_t *modes_len;
12
13qf_ferm_op_get_modes(op, &modes_out, &modes_len);
14
15assert(modes_len == 2);
Nota

Questa funzione restituisce una copia dei dati interni.

Parametri

  • op – Un puntatore all’operatore fermionico di cui si desidera accedere alle modalità.
  • modes_out – Un puntatore all’array di valori booleani in cui scrivere le modalità.
  • modes_len – Un puntatore all’intero in cui scrivere la lunghezza dell’array di output.

qf_ferm_op_get_boundaries

void qf_ferm_op_get_boundaries(const QfFermionOperator *op, size_t **boundaries_out, uint64_t *boundaries_len)

Fornisce un accesso in sola lettura agli indici che indicano i confini tra i termini dell’operatore.

Vedi anche

La spiegazione della struttura interna dei dati è disponibile qui.

Esempio

 1uint64_t num_terms = 2;
 2uint64_t num_actions = 2;
 3bool actions[2] = {true, false};
 4uint32_t modes[2] = {0, 1};
 5QkComplex64 coeffs[2] = {{1.0, 0.0}, {0.0, -1.0}};
 6uint32_t boundaries[3] = {0, 0, 2};
 7QfFermionOperator *op =
 8    qf_ferm_op_new(num_terms, num_actions, coeffs, actions, modes, boundaries);
 9
10QkComplex64 *boundaries_out;
11uint64_t *boundaries_len;
12
13qf_ferm_op_get_boundaries(op, &boundaries_out, &boundaries_len);
14
15assert(boundaries_len == 3);
Nota

Questa funzione restituisce una copia dei dati interni.

Parametri

  • op – Un puntatore all’operatore fermionico ai cui confini si desidera accedere.
  • boundaries_out – Un puntatore all'array di valori booleani in cui scrivere i limiti.
  • boundaries_len – Un puntatore all’intero in cui scrivere la lunghezza dell’array di output.

qf_ferm_op_zero

QfFermionOperator *qf_ferm_op_zero(void)

Costruisce l'operatore di identità additiva.

L'aggiunta di un operatore costruito con questo metodo a un altro operatore non ha alcun effetto.

Esempio

1QfFermionOperator *zero = qf_ferm_op_zero();
2
3QfFermionOperator *op_plus_zero = qf_ferm_op_add(op, zero);
4
5assert(qf_ferm_op_equal(op, op_plus_zero));

Risultati

Un puntatore all’operatore creato.

qf_ferm_op_one

QfFermionOperator *qf_ferm_op_one(void)

Crea l'operatore di identità moltiplicativo.

La composizione dell'operatore ottenuto con questo metodo con un altro operatore non ha alcun effetto.

Esempio

1QfFermionOperator *one = qf_ferm_op_one();
2
3QfFermionOperator *op_times_one = qf_ferm_op_compose(op, one);
4
5assert(qf_ferm_op_equal(op, op_times_one));

Risultati

Un puntatore all’operatore creato.

qf_ferm_op_has_groups

bool qf_ferm_op_has_groups(const QfFermionOperator *op)

Verifica se questo operatore tiene traccia degli indici di gruppo.

Vedi anche

Spiegazione dei termini relativi agli operatori di gruppo: utilizzare la struttura degli operatori.

Esempio

1QfFCIDump *fcidump = qf_fcidump_from_file("molecule.fcidump");
2QfFermionOperator *op = qf_ferm_op_from_fcidump(fcidump);
3
4bool has_groups = qf_ferm_op_has_groups(op);
5
6assert(!has_groups);

Parametri

  • op – Un puntatore all’operatore fermionico da verificare.

Risultati

Se l'operatore specificato possiede un attributo groups .

qf_ferm_op_num_groups

uint32_t qf_ferm_op_num_groups(const QfFermionOperator *op)

Recupera il numero di gruppi associati a un operatore.

Vedi anche

Spiegazione dei termini relativi agli operatori di gruppo: utilizzare la struttura degli operatori.

Esempio

1QfFCIDump *fcidump = qf_fcidump_from_file("molecule.fcidump");
2QfFermionOperator *op = qf_ferm_op_from_fcidump(fcidump);
3
4uint32_t num_groups = qf_ferm_op_num_groups(op);
Nota

Il numero di gruppi viene calcolato in modo differito come l'indice del gruppo più grande presente più 1.

Parametri

  • op – Un puntatore all’operatore fermionico di cui si desidera ottenere il numero di gruppi.

Risultati

Il numero di indici di gruppo derivante dall'attributo groups dell'operatore.

qf_ferm_op_group_weights

void qf_ferm_op_group_weights(const QfFermionOperator *op, double *weights_out)

Calcola la media del modulo assoluto del coefficiente per ciascun gruppo.

La i-esima voce è la somma di abs(coeff) sui termini del gruppo i, divisa per il numero di termini di quel gruppo. Si tratta del peso di campionamento di una formula di prodotto randomizzata (ad esempio qDRIFT ) che estrae interi gruppi anziché singoli termini, e viene calcolato in un unico passaggio sull’operatore anziché riducendo e qf_ferm_op_get_coeffs() ( qf_ferm_op_get_groups() un valore per ciascun termine non raggruppato ) dal lato del chiamante.

Vedi anche

Spiegazione dei termini relativi agli operatori di gruppo: utilizzare la struttura degli operatori.

Esempio

 1uint64_t num_terms = 4;
 2uint64_t num_actions = 8;
 3bool actions[8] = {true, false, true, false, true, false, true, false};
 4uint32_t modes[8] = {0, 1, 2, 3, 1, 0, 3, 2};
 5QkComplex64 coeffs[4] = {{1.0, 0.0}, {2.0, 0.0}, {-1.0, 0.0}, {-2.0, 0.0}};
 6uint32_t boundaries[5] = {0, 2, 4, 6, 8};
 7QfFermionOperator *op =
 8    qf_ferm_op_new(num_terms, num_actions, coeffs, actions, modes, boundaries);
 9
10uint32_t groups_in[4] = {0, 1, 0, 1};
11qf_ferm_op_set_groups(op, groups_in, num_terms);
12
13double weights[2];
14qf_ferm_op_group_weights(op, weights);
15
16assert(weights[0] == 1.0);
17assert(weights[1] == 2.0);
Nota

Un indice di gruppo a cui nessun termine è associato ha peso 0.0, il che lo esclude dal campione.

Parametri

  • op – Un puntatore all’operatore fermionico di cui si devono calcolare i pesi di gruppo.
  • weights_out – Un puntatore all'array di valori di tipo double in cui scrivere i pesi. Deve essere dimensionato in base a :c:funcqf_ferm_op_num_groups:.

qf_ferm_op_get_groups

void qf_ferm_op_get_groups(const QfFermionOperator *op, uint32_t **groups_out, uint64_t *groups_len)

Recupera gli indici di gruppo per tutti i termini dell'operatore.

Vedi anche

Spiegazione dei termini relativi agli operatori di gruppo: utilizzare la struttura degli operatori.

Esempio

1QfFermionOperator *op = ...;
2uint32_t *groups_out;
3uint32_t groups_len;
4
5qf_ferm_op_get_groups(op, &groups_out, &groups_len);

Parametri

  • op – Un puntatore all'operatore fermionico di cui si desidera ottenere gli indici di gruppo.
  • groups_out – Un puntatore all'array di interi in cui scrivere gli indici dei gruppi.
  • groups_len – Un puntatore all’intero in cui scrivere la lunghezza dell’array di output.

qf_ferm_op_set_groups

void qf_ferm_op_set_groups(QfFermionOperator *op, const uint32_t *groups_in, uint64_t groups_len)

Imposta l'attributo groups dell'operatore specificato.

Vedi anche

Spiegazione dei termini relativi agli operatori di gruppo: utilizzare la struttura degli operatori.

Esempio

1QfFermionOperator *op = ...;
2
3uint32_t num_terms = 4;
4uint32_t groups_in[4] = {0, 1, 0, 1};
5qf_ferm_op_set_groups(op, groups_in, num_terms);

Parametri

  • op – Un puntatore all'operatore fermionico di cui si desidera scrivere l'attributo groups .
  • groups_in – Un puntatore all'array di interi groups in cui scrivere nell'operatore.
  • groups_len – Il numero di elementi presenti nell'array groups_in .

qf_ferm_op_del_groups

void qf_ferm_op_del_groups(QfFermionOperator *op)

Elimina l'attributo groups dall'operatore specificato.

Vedi anche

Spiegazione dei termini relativi agli operatori di gruppo: utilizzare la struttura degli operatori.

Esempio

1QfFermionOperator *op = ...;
2
3qf_ferm_op_del_groups(op);

Parametri

  • op – Un puntatore all’operatore fermionico di cui si desidera eliminare l’attributo groups .

qf_ferm_op_split_out_groups

void qf_ferm_op_split_out_groups(const QfFermionOperator *op, const uint32_t *group_indices, uint64_t num_indices, QfFermionOperator **group_ops_out)

Suddivide questo operatore in un elenco di nuovi operatori in base al suo attributo groups .

Un indice duplicato in group_indices viene scritto una volta per ogni occorrenza in group_ops_out. Richiedere solo un numero limitato di gruppi rispetto a un totale molto più ampio è notevolmente più economico rispetto a richiederli tutti, poiché i termini appartenenti a un gruppo non richiesto vengono saltati anziché essere aggiunti in qualsiasi punto.

Vedi anche

Spiegazione dei termini relativi agli operatori di gruppo: utilizzare la struttura degli operatori.

Esempio

 1uint64_t num_terms = 4;
 2uint64_t num_actions = 8;
 3bool actions[8] = {true, false, true, false, true, false, true, false};
 4uint32_t modes[8] = {0, 1, 2, 3, 1, 0, 3, 2};
 5QkComplex64 coeffs[4] = {{1.0, 0.0}, {1.0, 0.0}, {1.0, 0.0}, {1.0, 0.0}};
 6uint32_t boundaries[5] = {0, 2, 4, 6, 8};
 7QfFermionOperator *op =
 8    qf_ferm_op_new(num_terms, num_actions, coeffs, actions, modes, boundaries);
 9
10uint32_t groups_in[4] = {0, 1, 0, 1};
11qf_ferm_op_set_groups(op, groups_in, num_terms);
12
13// build every group, in index order
14QfFermionOperator *group_ops[2];
15qf_ferm_op_split_out_groups(op, NULL, 0, group_ops);
16
17// build only group 1
18uint32_t group_indices[1] = {1};
19QfFermionOperator *group_op[1];
20qf_ferm_op_split_out_groups(op, group_indices, 1, group_op);

Parametri

  • op – Un puntatore all'operatore fermionico groups da estrarre.
  • group_indices – Un puntatore all'array degli indici dei gruppi per i quali costruire gli operatori, nell'ordine di output desiderato. È possibile che NULL, in tal caso, ogni gruppo venga costruito in ordine di indice (il che equivale a passare ogni indice da 0 a :c:func:qf_ferm_op_num_groups - 1).
  • num_indices – Il numero di indici presenti nell'array group_indices . Viene ignorato se è group_indices NULL.
  • group_ops_out – Un puntatore all'array di :c:struct:QfFermionOperator in cui scrivere gli operatori per ciascun gruppo richiesto. Deve essere dimensionato in base a num_indices quando group_indices è diverso da NULL, oppure in base a :c:func:qf_ferm_op_num_groups quando è NULL.

qf_ferm_op_add_term

void qf_ferm_op_add_term(QfFermionOperator *op, uint64_t num_actions, const bool *actions, const uint32_t *modes, const QkComplex64 *coeff)

Aggiunge un termine a un operatore esistente.

Qualsiasi argomento di tipo puntatore può essere NULL se e solo se la lunghezza corrispondente è zero.

Attenzione

Questa funzione reimposta l'attributo groups dell'operatore su NULL.

Esempio

 1QfFermionOperator *one = qf_ferm_op_one();
 2
 3QfFermionOperator *op = qf_ferm_op_zero();
 4bool actions[0] = {};
 5uint32_t modes[0] = {};
 6QkComplex64 coeff = {1.0, 0.0};
 7
 8qf_ferm_op_add_term(op, 0, actions, modes, &coeff);
 9
10assert(qf_ferm_op_equal(op, one));

Parametri

  • op – Un puntatore all'operatore fermionico da modificare.
  • num_actions – La lunghezza dell'array delle azioni.
  • azioni – Un puntatore a un array di azioni. La lunghezza di questo array dovrebbe essere num_actions.
  • modalità – Un puntatore a un array di modalità di azione. La lunghezza di questo array dovrebbe essere num_actions.
  • coeff – Un puntatore al coefficiente complesso.

qf_ferm_op_add

QfFermionOperator *qf_ferm_op_add(const QfFermionOperator *left, const QfFermionOperator *right)

Somma due operatori.

Esempio

1QfFermionOperator *one = qf_ferm_op_one();
2QfFermionOperator *zero = qf_ferm_op_zero();
3
4QfFermionOperator *result = qf_ferm_op_add(one, zero);
5
6assert(qf_ferm_op_equal(result, one));

Parametri

  • sinistra – Un puntatore all'operatore di sinistra.
  • right – Un puntatore all'operatore "a destra".

Risultati

Un puntatore all'operatore risultante.

qf_ferm_op_mul

QfFermionOperator *qf_ferm_op_mul(const QfFermionOperator *op, const QkComplex64 *scalar)

Moltiplica un operatore per uno scalare.

Esempio

 1QfFermionOperator *one = qf_ferm_op_one();
 2QkComplex64 coeff = {2.0, 0.0};
 3QfFermionOperator *result = qf_ferm_op_mul(one, &coeff);
 4
 5QfFermionOperator *expected = qf_ferm_op_zero();
 6bool actions[0] = {};
 7uint32_t modes[0] = {};
 8qf_ferm_op_add_term(expected, 0, actions, modes, &coeff);
 9
10assert(qf_ferm_op_equal(result, expected));

Parametri

  • op – Un puntatore all'operatore.
  • scalare – Un puntatore allo scalare.

Risultati

Un puntatore all'operatore risultante.

qf_ferm_op_compose

QfFermionOperator *qf_ferm_op_compose(const QfFermionOperator *left, const QfFermionOperator *right)

Combina due operatori tra loro.

Esempio

1QfFermionOperator *one = qf_ferm_op_one();
2QfFermionOperator *zero = qf_ferm_op_zero();
3
4QfFermionOperator *result = qf_ferm_op_compose(one, zero);
5
6assert(qf_ferm_op_equal(result, zero));

Parametri

  • sinistra – Un puntatore all'operatore di sinistra.
  • right – Un puntatore all'operatore "a destra".

Risultati

Un puntatore all'operatore risultante.

qf_ferm_op_adjoint

QfFermionOperator *qf_ferm_op_adjoint(const QfFermionOperator *op)

Restituisce il coniugato ermitiano (o aggiunto) di un operatore.

Ciò influisce sui termini e sui coefficienti come segue:

  • le azioni in ogni termine invertono il loro ordine e alternano creazione e annichilimento
  • i coefficienti sono complessi coniugati

Esempio

 1QfFermionOperator *op = qf_ferm_op_zero();
 2bool actions[0] = {};
 3uint32_t modes[0] = {};
 4QkComplex64 coeff = {0.0, 1.0};
 5qf_ferm_op_add_term(op, 0, actions, modes, &coeff);
 6
 7QfFermionOperator *adjoint = qf_ferm_op_adjoint(op);
 8
 9QfFermionOperator *expected = qf_ferm_op_zero();
10QkComplex64 coeff_adj = {0.0, -1.0};
11qf_ferm_op_add_term(expected, 0, actions, modes, &coeff_adj);
12
13assert(qf_ferm_op_equal(adjoint, expected));

Parametri

  • op – Un puntatore all'operatore.

Risultati

Un puntatore all’operatore creato.

qf_ferm_op_ichop

void qf_ferm_op_ichop(QfFermionOperator *op, double atol)

Rimuove i termini il cui coefficiente è inferiore alla soglia specificata.

Attenzione

Questa funzione tronca i coefficienti in modo avido! Se l'operatore su cui si agisce dovesse contenere coefficienti distinti per termini duplicati, valuta invece qf_ferm_op_simplify() di chiamare!

Esempio

 1QfFermionOperator *op = qf_ferm_op_zero();
 2bool actions[0] = {};
 3uint32_t modes[0] = {};
 4QkComplex64 coeff = {1e-8};
 5qf_ferm_op_add_term(op, 0, actions, modes, &coeff);
 6
 7qf_ferm_op_ichop(op, 1e-6);
 8
 9QfFermionOperator *expected = qf_ferm_op_zero();
10
11assert(qf_ferm_op_equal(op, expected));

Parametri

  • op – Un puntatore all'operatore.
  • atol – La tolleranza assoluta per il troncamento dei coefficienti.

qf_ferm_op_simplify

QfFermionOperator *qf_ferm_op_simplify(const QfFermionOperator *op, double atol)

Restituisce un operatore equivalente ma semplificato.

Il processo di semplificazione somma innanzitutto tutti i coefficienti appartenenti a termini uguali e poi mantiene solo quelli il cui coefficiente totale supera la tolleranza specificata (proprio come qf_ferm_op_ichop()).

Quando un operatore è stato manipolato aritmeticamente o costruito in modo tale da non garantire l'unicità dei termini, è opportuno richiamare questo metodo prima di applicare qualsiasi metodo che filtri i coefficienti numericamente piccoli, al fine di evitare la perdita di informazioni. Si veda l'esempio riportato di seguito, che illustra come qf_ferm_op_ichop() sia possibile troncare termini la cui somma porta a un coefficiente di grandezza totale che non dovrebbe essere troncato:

 1uint64_t num_terms = 100000;
 2uint64_t num_actions = 0;
 3bool actions[0] = {};
 4uint32_t modes[0] = {};
 5QkComplex64 coeffs[100000];
 6uint32_t boundaries[100001];
 7for (int i = 0; i < 100000; i++) {
 8  coeffs[i].re = 1e-5;
 9  coeffs[i].im = 0.0;
10  boundaries[i] = 0;
11}
12boundaries[100000] = 0;
13QfFermionOperator *op = qf_ferm_op_new(num_terms, num_actions, coeffs,
14                                       actions, modes, boundaries);
15
16QfFermionOperator *canon = qf_ferm_op_simplify(op, 1e-4);
17
18QfFermionOperator *one = qf_ferm_op_one();
19bool canon_is_equal = qf_ferm_op_equiv(canon, one, 1e-6);
20
21qf_ferm_op_ichop(op, 1e-4);
22
23QfFermionOperator *zero = qf_ferm_op_zero();
24bool ichop_is_equal = qf_ferm_op_equiv(op, zero, 1e-6);

Parametri

  • op – Un puntatore all’operatore fermionico da semplificare.
  • atol – La tolleranza assoluta per il troncamento dei coefficienti.

Risultati

Un operatore equivalente ma semplificato.

qf_ferm_op_normal_ordered

QfFermionOperator *qf_ferm_op_normal_ordered(const QfFermionOperator *op, const bool *sandwich)

Restituisce un operatore equivalente con termini ordinati normalmente.

L'ordine normale di un termine operatore è definito in modo tale che tutte le azioni di creazione compaiano prima di tutte le azioni di annichilimento. All’interno di ciascun gruppo, le modalità su cui agisce l’azione sono ordinate lessicograficamente. Il fatto che l'ordine sia crescente o decrescente dipende dal valore dell'argomento sandwich :

  • NULL: entrambi i gruppi sono ordinati in ordine lessicografico decrescente (ad es. +_1 +_0 -_1 -_0)
  • True: gli indici più grandi compaiono verso il centro, ovvero le azioni di creazione sono in ordine lessicografico crescente mentre quelle di annichilimento sono in ordine lessicografico decrescente (ad es. +_0 +_1 -_1 -_0)
  • False: gli indici più piccoli compaiono verso il centro, ovvero le azioni di creazione sono in ordine lessicografico decrescente mentre quelle di annichilimento sono in ordine crescente (ad es. +_1 +_0 -_0 -_1)

Esempio

 1QfFermionOperator *op = qf_ferm_op_zero();
 2bool actions[4] = {false, true, false, true};
 3uint32_t modes[4] = {1, 1, 0, 0};
 4QkComplex64 coeff = {1.0, 0.0};
 5qf_ferm_op_add_term(op, 4, actions, modes, &coeff);
 6
 7QfFermionOperator *normal_ordered = qf_ferm_op_normal_ordered(op, NULL);
 8
 9uint64_t num_terms = 4;
10uint64_t num_actions = 8;
11bool actions_exp[8] = {true, false, true, false, true, true, false, false};
12uint32_t modes_exp[8] = {0, 0, 1, 1, 1, 0, 1, 0};
13QkComplex64 coeffs_exp[4] = {
14    {1.0, 0.0}, {-1.0, 0.0}, {-1.0, 0.0}, {-1.0, 0.0}};
15uint32_t boundaries_exp[5] = {0, 0, 2, 4, 8};
16QfFermionOperator *expected =
17    qf_ferm_op_new(num_terms, num_actions, coeffs_exp, actions_exp,
18                   modes_exp, boundaries_exp);
19
20assert(qf_ferm_op_equal(normal_ordered, expected));
Nota

Quando si riorganizza un termine, occorre tenere conto delle relazioni di anticommutazione, aiaj=δijajaia_i a^\dagger_j = \delta_{ij} - a^\dagger_j a^i, il che implica che il numero dei termini potrebbe variare.

Parametri

  • op – Un puntatore all'operatore.
  • sandwich – Un puntatore a un valore booleano. Questo puntatore può essere NULL.

Risultati

Un puntatore all’operatore creato.

qf_ferm_op_is_hermitian

bool qf_ferm_op_is_hermitian(const QfFermionOperator *op, double atol)

Verifica se un operatore è ermitiano.

Esempio

 1QfFermionOperator *op = qf_ferm_op_zero();
 2bool actions1[2] = {true, false};
 3uint32_t modes1[2] = {0, 1};
 4QkComplex64 coeff1 = {0.0, 1.00001};
 5qf_ferm_op_add_term(op, 2, actions1, modes1, &coeff1);
 6bool actions2[2] = {true, false};
 7uint32_t modes2[2] = {1, 0};
 8QkComplex64 coeff2 = {0.0, -1};
 9qf_ferm_op_add_term(op, 2, actions2, modes2, &coeff1);
10
11assert(qf_ferm_op_is_hermitian(op, 1e-4));
12assert(!qf_ferm_op_is_hermitian(op, 1e-8));
Nota

Questo controllo viene implementato utilizzando qf_ferm_op_equiv() la differenza qf_ferm_op_normal_ordered() tra e op i suoi e qf_ferm_op_adjoint() qf_ferm_op_zero().

Parametri

  • op – Un puntatore all’operatore fermionico da verificare.
  • atol – La tolleranza assoluta entro la quale i coefficienti sono considerati uguali.

Risultati

Se l'operatore fornito è ermitiano.

qf_ferm_op_max_rank

uint32_t qf_ferm_op_max_rank(const QfFermionOperator *op)

Verifica il grado massimo di un operatore.

Esempio

1QfFermionOperator *op = qf_ferm_op_zero();
2bool actions[4] = {true, false, true, false};
3uint32_t modes[4] = {0, 1, 2, 3};
4QkComplex64 coeff = {1.0, 0.0};
5qf_ferm_op_add_term(op, 4, actions, modes, &coeff);
6
7assert(qf_ferm_op_max_rank(op), 4);
Nota

La lunghezza del termine più lungo può dipendere dalla forma dell’operatore, il che significa che (ad esempio) la semplificazione dell’operatore o l’ordinamento normale possono determinare un rango massimo diverso.

Parametri

  • op – Un puntatore all’operatore fermionico da verificare.

Risultati

Il grado massimo dell'operatore.

qf_ferm_op_conserves_particle_number

bool qf_ferm_op_conserves_particle_number(const QfFermionOperator *op)

Verifica se un operatore conserva il numero di particelle.

Esempio

 1QfFermionOperator *op = qf_ferm_op_zero();
 2bool actions1[2] = {true, false};
 3uint32_t modes1[2] = {0, 1};
 4QkComplex64 coeff1 = {0.0, 1.00001};
 5qf_ferm_op_add_term(op, 2, actions1, modes1, &coeff1);
 6bool actions2[2] = {true, false};
 7uint32_t modes2[2] = {1, 0};
 8QkComplex64 coeff2 = {0.0, -1};
 9qf_ferm_op_add_term(op, 2, actions2, modes2, &coeff2);
10
11assert(qf_ferm_op_is_hermitian(op, 1e-4));
12assert(!qf_ferm_op_is_hermitian(op, 1e-8));

Parametri

  • op – Un puntatore all’operatore fermionico da verificare.

Risultati

Se l'operatore fornito conserva il numero di particelle.

qf_ferm_op_equal

bool qf_ferm_op_equal(const QfFermionOperator *left, const QfFermionOperator *right)

Confronta due operatori per verificare se sono uguali.

Esempio

1QfFermionOperator *one = qf_ferm_op_one();
2QfFermionOperator *zero = qf_ferm_op_zero();
3
4assert(qf_ferm_op_equal(one, one));
5assert(!qf_ferm_op_equal(one, zero));

Parametri

  • sinistra – Un puntatore all'operatore di sinistra.
  • right – Un puntatore all'operatore "a destra".

Risultati

Se i due operatori sono uguali.

qf_ferm_op_equiv

bool qf_ferm_op_equiv(const QfFermionOperator *left, const QfFermionOperator *right, double atol)

Confronta due operatori per verificare se sono equivalenti.

In questo contesto, per “equivalenza” si intende un’uguaglianza approssimativa entro i limiti della tolleranza assoluta specificata. Per essere più precisi, questo metodo restituisce True, quando tutti i valori assoluti dei coefficienti nella differenza other - self sono inferiori alla soglia specificata atol.

Esempio

 1QfFermionOperator *zero = qf_ferm_op_zero();
 2
 3QfFermionOperator *op = qf_ferm_op_zero();
 4bool actions[0] = {};
 5uint32_t modes[0] = {};
 6QkComplex64 coeff = {1e-7, 0.0};
 7qf_ferm_op_add_term(op, 0, actions, modes, &coeff);
 8
 9assert(qf_ferm_op_equiv(op, zero, 1e-6));
10assert(!qf_ferm_op_equiv(op, zero, 1e-8));

Parametri

  • sinistra – Un puntatore all'operatore di sinistra.
  • right – Un puntatore all'operatore "a destra".
  • atol – La tolleranza assoluta per l'equivalenza dei coefficienti.

Risultati

Se i due operatori sono equivalenti.

qf_ferm_op_len

size_t qf_ferm_op_len(const QfFermionOperator *op)

Restituisce la lunghezza (ovvero il numero di termini) dell'operatore specificato.

Esempio

1QfFermionOperator *op = qf_ferm_op_zero();
2bool actions[4] = {true, false, true, false};
3uint32_t modes[4] = {0, 1, 2, 3};
4QkComplex64 coeff = {1.0, 0.0};
5qf_ferm_op_add_term(op, 4, actions, modes, &coeff);
6
7assert(qf_ferm_op_len(op) == 1);

Parametri

  • op – Un puntatore all’operatore fermionico.

Risultati

La lunghezza (o il numero di termini) dell'operatore.

qf_ferm_op_relabel_modes

QfExitCode qf_ferm_op_relabel_modes(QfFermionOperator *op, uint64_t num_modes, const uint32_t *permutation)

Rinomina gli indici dell'operatore specificato.

Esempio

 1QfFermionOperator *op = qf_ferm_op_zero();
 2bool actions[4] = {true, false, true, false};
 3uint32_t indices[4] = {0, 1, 2, 3};
 4QkComplex64 coeff = {1.0, 0.0};
 5qf_ferm_op_add_term(op, 4, actions, indices, &coeff);
 6
 7uint32_t permutation[4] = {3, 2, 1, 0};
 8
 9QfExitCode exit = qf_ferm_op_relabel_modes(op, 4, permutation);
10
11assert(exit == QfExitCode_Success);

Parametri

  • op – Un puntatore all’operatore fermionico.
  • num_modes – Il numero di indici di modalità presenti nell'elenco delle permutazioni fornito.
  • permutazione – L'elenco delle permutazioni degli indici.

Risultati

Un codice di uscita.

  • QfExitCode_Success in caso di successo
  • QfExitCode_DuplicateIndexError se nella permutazione sono stati rilevati indici duplicati
  • QfExitCode_IndexError per eventuali altri errori relativi agli indici, come ad esempio indici non validi.
Questa pagina è stata utile?
Segnala un bug, un errore di battitura o richiedi contenuti su GitHub.