QfEdgeVertexOperator
QfEdgeVertexOperator
struct QfEdgeVertexOperator
Un operatore bordo-vertice.
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 in termini degli operatori " " e " ":
che soddisfano le seguenti relazioni di commutazione miste fermioniche-bosoniche per l’ o: [1]
In sintesi, gli operatori di spigolo e di vertice commutano, a meno che non condividano esattamente un indice, nel qual caso anticommutano.
Le relazioni sopra riportate valgono per , quindi non tengono conto di due operatori di bordo che coprono la stessa coppia di modi. Quelli che commutano: poiché , tale coppia è allineata e ogni operatore commuta con se stesso. Ecco perché la condizione è “esattamente un” indice condiviso anziché “almeno uno”.
Possiamo prendere un po’ di libertà con la notazione e definire , che riflette il funzionamento della struttura interna di questo operatore. Ne consegue che la definizione dell'intero operatore è la seguente:
dove indica i termini dell'operatore in questione e è il coefficiente (complesso) che costituisce la combinazione lineare dei prodotti. Gli indici e possono assumere qualsiasi valore compreso tra 0 e il numero di modi fermionici su cui agisce l’operatore meno 1.
Ci riferiremo agli operatori di tipo “ ” come operatori di bordo generalizzati.
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:
Rubrica 1 | Rubrica 2 |
|---|---|
coeffs | Un vettore di coefficienti complessi costituito da due numeri in virgola mobile a 64 bit. |
left_indices | Un vettore di interi a 32 bit che memorizza gli indici delle modalità fermioniche di sinistra ( ). |
right_indices | Un vettore di interi a 32 bit che memorizza gli indici delle modalità fermioniche di destra ( ). |
boundaries | Un vettore di numeri interi che indica i confini tra i termini. |
Le modalità fermioniche indicizzate da left_indices e right_indices sono considerate prive di spin. I due array di indici hanno sempre la stessa lunghezza, poiché ogni generatore è identificato da una sola coppia (left, right) ; ecco perché il costruttore accetta un unico valore di lunghezza num_indices per entrambi.
È possibile accedere alle istanze in sola lettura di questi array interni tramite le rispettive funzioni:
qf_edge_op_get_coeffs()qf_edge_op_get_left_indices()qf_edge_op_get_right_indices()qf_edge_op_get_boundaries()
I puntatori restituiti rimangono validi solo fino a quando l'operatore non viene modificato o liberato e non devono essere liberati dal chiamante.
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_edge_op_simplify().
Costruzioni
È possibile creare un nuovo operatore direttamente specificando gli array corrispondenti descritti sopra. In alternativa, un campo vuoto può QfEdgeVertexOperator essere inizializzato con e qf_edge_op_zero() i termini possono essere aggiunti in modo iterativo tramite qf_edge_op_add_term().
Rubrica 1 | Rubrica 2 |
|---|---|
qf_edge_op_new() | Crea un nuovo operatore a partire dagli array forniti. |
qf_edge_op_zero() | Costruisce l'operatore di identità additiva. |
qf_edge_op_one() | Crea l'operatore di identità moltiplicativa. |
qf_edge_op_add_term() | Aggiunge un termine a un file esistente QfEdgeVertexOperator. |
A QfEdgeVertexOperator può essere liberato con qf_edge_op_free().
Aritmetica
Le seguenti funzioni consentono di eseguire operazioni aritmetiche:
Rubrica 1 | Rubrica 2 |
|---|---|
qf_edge_op_add() | Somma due operatori. |
qf_edge_op_mul() | Moltiplica un operatore per uno scalare. |
qf_edge_op_compose() | Combina due operatori tra loro. |
qf_edge_op_adjoint() | Restituisce l'operatore coniugato ermitiano. |
Manipolazione
Le seguenti funzioni forniscono la logica di manipolazione degli operatori:
Rubrica 1 | Rubrica 2 |
|---|---|
qf_edge_op_ichop() | Elimina i termini con coefficienti di piccola entità. |
qf_edge_op_simplify() | Restituisce un operatore equivalente ma semplificato. |
qf_edge_op_normal_ordered() | Restituisce un operatore equivalente con termini ordinati normalmente. |
qf_edge_op_relabel_modes() | Rinomina le modalità di un operatore. |
Proprietà
Sono disponibili le seguenti funzioni per verificare determinate proprietà di un operatore.
Rubrica 1 | Rubrica 2 |
|---|---|
qf_edge_op_is_hermitian() | Restituisce se un operatore è ermitiano. |
qf_edge_op_len() | Restituisce il numero di termini presenti in questo operatore. |
Associazione
Le seguenti funzioni mappano questo operatore in un'altra rappresentazione:
Rubrica 1 | Rubrica 2 |
|---|---|
qf_edge_vertex_to_fermion() | Mappe in formato QfFermionOperator. |
qf_edge_vertex_to_majorana() | Mappe in formato QfMajoranaOperator. |
[ 1 ]
https://arxiv.org/abs/2512.11418
Membri
qf_edge_op_new
QfEdgeVertexOperator *qf_edge_op_new(uint64_t num_terms, uint64_t num_indices, const QkComplex64 *coeffs, const uint32_t *left_indices, const uint32_t *right_indices, const uint32_t *boundaries)
Crea un nuovo operatore.
Qualsiasi argomento di tipo puntatore può essere NULL se e solo se la sua lunghezza corrispondente è pari a zero.
Un generatore con indici uguali è un operatore di vertice, ; uno con indici diversi è un operatore di spigolo (generalizzato), .
Esempio
1// this builds `1.0 + (-1.0) * V(0) E(0,1)`
2uint64_t num_terms = 2;
3uint64_t num_indices = 2;
4uint32_t left_indices[2] = {0, 0};
5uint32_t right_indices[2] = {0, 1};
6QkComplex64 coeffs[2] = {{1.0, 0.0}, {-1.0, 0.0}};
7uint32_t boundaries[3] = {0, 0, 2};
8QfEdgeVertexOperator *op = qf_edge_op_new(num_terms, num_indices, coeffs,
9 left_indices, right_indices, boundaries);Parametri
- num_terms – Il numero di termini presenti nell'operatore.
- num_indices – Il numero di generatori, calcolato sommando tutti i termini. Entrambi gli array di indici hanno la stessa lunghezza, poiché ogni generatore è identificato da una sola coppia
(left, right). - coeffs – Un puntatore a un array di coefficienti dei termini. La lunghezza di questo array dovrebbe essere
num_terms. - left_indices – Un puntatore a un array di indici della modalità sinistra relativi a tutti i termini. La lunghezza di questo array dovrebbe essere
num_indices. - right_indices – Un puntatore a un array di indici in modalità destra relativi a tutti i termini. La lunghezza di questo array dovrebbe essere
num_indices. - confini – Un puntatore a un array contenente i confini tra i termini. La lunghezza di questo array dovrebbe essere
num_terms + 1.
Risultati
Un puntatore all'operatore creato.
qf_edge_op_free
void qf_edge_op_free(QfEdgeVertexOperator *op)
Rilascia un operatore esistente.
Esempio
1QfEdgeVertexOperator *op = qf_edge_op_one();
2qf_edge_op_free(op);Parametri
- op – Un puntatore all’operatore bordo-vertice da liberare.
qf_edge_op_get_coeffs
void qf_edge_op_get_coeffs(const QfEdgeVertexOperator *op, QkComplex64 **coeffs_out, uint64_t *coeffs_len)
Fornisce accesso in sola lettura ai coefficienti dell'operatore.
La spiegazione della struttura interna dei dati è disponibile qui.
Esempio
1uint64_t num_terms = 2;
2QkComplex64 coeffs[2] = {{1.0, 0.0}, {0.0, -1.0}};
3uint32_t boundaries[3] = {0, 0, 0};
4QfEdgeVertexOperator *op =
5 qf_edge_op_new(num_terms, 0, coeffs, NULL, NULL, boundaries);
6
7QkComplex64 *coeffs_out;
8uint64_t coeffs_len;
9
10qf_edge_op_get_coeffs(op, &coeffs_out, &coeffs_len);
11
12assert(coeffs_len == 2);Questa funzione utilizza il buffer interno dell'operatore anziché copiarlo. Il puntatore restituito rimane valido solo fino a quando l'operatore non viene modificato o liberato; non liberarlo manualmente.
Parametri
- op – Un puntatore all’operatore bordo-vertice 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_edge_op_get_left_indices
void qf_edge_op_get_left_indices(const QfEdgeVertexOperator *op, uint32_t **left_indices_out, uint64_t *left_indices_len)
Fornisce accesso in sola lettura agli indici della modalità sinistra dell’operatore.
La spiegazione della struttura interna dei dati è disponibile qui.
Esempio
1uint64_t num_terms = 1;
2uint64_t num_indices = 2;
3uint32_t left_indices[2] = {0, 0};
4uint32_t right_indices[2] = {0, 1};
5QkComplex64 coeffs[1] = {{1.0, 0.0}};
6uint32_t boundaries[2] = {0, 2};
7QfEdgeVertexOperator *op = qf_edge_op_new(num_terms, num_indices, coeffs,
8 left_indices, right_indices, boundaries);
9
10uint32_t *left_out;
11uint64_t left_len;
12
13qf_edge_op_get_left_indices(op, &left_out, &left_len);
14
15assert(left_len == 2);Questa funzione utilizza il buffer interno dell'operatore anziché copiarlo. Il puntatore restituito rimane valido solo fino a quando l'operatore non viene modificato o liberato; non liberarlo manualmente.
Parametri
- op – Un puntatore all’operatore bordo-vertice di cui si desidera accedere agli indici di sinistra.
- left_indices_out – Un puntatore all'array di numeri interi in cui scrivere gli indici.
- left_indices_len – Un puntatore all'intero in cui scrivere la lunghezza dell'array di output.
qf_edge_op_get_right_indices
void qf_edge_op_get_right_indices(const QfEdgeVertexOperator *op, uint32_t **right_indices_out, uint64_t *right_indices_len)
Fornisce accesso in sola lettura agli indici della modalità a destra dell’operatore.
La spiegazione della struttura interna dei dati è disponibile qui.
Esempio
1uint64_t num_terms = 1;
2uint64_t num_indices = 2;
3uint32_t left_indices[2] = {0, 0};
4uint32_t right_indices[2] = {0, 1};
5QkComplex64 coeffs[1] = {{1.0, 0.0}};
6uint32_t boundaries[2] = {0, 2};
7QfEdgeVertexOperator *op = qf_edge_op_new(num_terms, num_indices, coeffs,
8 left_indices, right_indices, boundaries);
9
10uint32_t *right_out;
11uint64_t right_len;
12
13qf_edge_op_get_right_indices(op, &right_out, &right_len);
14
15assert(right_len == 2);Questa funzione utilizza il buffer interno dell'operatore anziché copiarlo. Il puntatore restituito rimane valido solo fino a quando l'operatore non viene modificato o liberato; non liberarlo manualmente.
Parametri
- op – Un puntatore all'operatore bordo-vertice di cui si desidera accedere agli indici a destra.
- right_indices_out – Un puntatore all'array di numeri interi in cui scrivere gli indici.
- right_indices_len – Un puntatore all’intero in cui scrivere la lunghezza dell’array di output.
qf_edge_op_get_boundaries
void qf_edge_op_get_boundaries(const QfEdgeVertexOperator *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.
La spiegazione della struttura interna dei dati è disponibile qui.
Esempio
1uint64_t num_terms = 1;
2uint64_t num_indices = 2;
3uint32_t left_indices[2] = {0, 0};
4uint32_t right_indices[2] = {0, 1};
5QkComplex64 coeffs[1] = {{1.0, 0.0}};
6uint32_t boundaries[2] = {0, 2};
7QfEdgeVertexOperator *op = qf_edge_op_new(num_terms, num_indices, coeffs,
8 left_indices, right_indices, boundaries);
9
10size_t *boundaries_out;
11uint64_t boundaries_len;
12
13qf_edge_op_get_boundaries(op, &boundaries_out, &boundaries_len);
14
15assert(boundaries_len == 2);Questa funzione utilizza il buffer interno dell'operatore anziché copiarlo. Il puntatore restituito rimane valido solo fino a quando l'operatore non viene modificato o liberato; non liberarlo manualmente.
Parametri
- op – Un puntatore all’operatore bordo-vertice di cui si desidera accedere ai confini.
- boundaries_out – Un puntatore all'array di numeri interi in cui scrivere i limiti.
- boundaries_len – Un puntatore all’intero in cui scrivere la lunghezza dell’array di output.
qf_edge_op_num_support
uint32_t qf_edge_op_num_support(const QfEdgeVertexOperator *op)
Restituisce la dimensione del supporto di un operatore.
Utilizzare questa opzione per impostare la dimensione del buffer di output di qf_edge_op_get_support(), che non riporta una lunghezza propria.
Esempio
1uint32_t left_indices[3] = {2, 0, 2};
2uint32_t right_indices[3] = {2, 1, 2};
3QkComplex64 coeffs[2] = {{1.0, 0.0}, {1.0, 0.0}};
4uint32_t boundaries[3] = {0, 2, 3};
5QfEdgeVertexOperator *op =
6 qf_edge_op_new(2, 3, coeffs, left_indices, right_indices, boundaries);
7
8uint32_t num_support = qf_edge_op_num_support(op);
9
10assert(num_support == 3);Parametri
- op – Un puntatore all’operatore bordo-vertice di cui si desidera ottenere la dimensione del supporto.
Risultati
Il numero di indici di modalità distinti su cui agisce l'operatore.
qf_edge_op_get_support
void qf_edge_op_get_support(const QfEdgeVertexOperator *op, uint32_t *support_out)
Ottiene il supporto di un operatore, ovvero gli indici di modalità su cui agisce l'operatore.
Gli indici sono scritti in ordine crescente e ogni indice compare esattamente una volta, indipendentemente dal numero di termini a cui si riferisce.
Esempio
1uint32_t left_indices[3] = {2, 0, 2};
2uint32_t right_indices[3] = {2, 1, 2};
3QkComplex64 coeffs[2] = {{1.0, 0.0}, {1.0, 0.0}};
4uint32_t boundaries[3] = {0, 2, 3};
5QfEdgeVertexOperator *op =
6 qf_edge_op_new(2, 3, coeffs, left_indices, right_indices, boundaries);
7
8uint32_t num_support = qf_edge_op_num_support(op);
9uint32_t *support_out = malloc(num_support * sizeof(uint32_t));
10
11qf_edge_op_get_support(op, support_out);
12
13assert(support_out[0] == 0);
14assert(support_out[1] == 1);
15assert(support_out[2] == 2);
16
17free(support_out);A differenza degli altri getter, questo non restituisce un puntatore all'operatore: il supporto viene calcolato al momento della richiesta anziché essere memorizzato, quindi è il chiamante a fornire il buffer di output. Verifica innanzitutto qf_edge_op_num_support() la lunghezza richiesta.
Sia l'indice sinistro che quello destro di ogni operatore di bordo generalizzato contribuiscono al supporto.
Parametri
- op – Un puntatore all’operatore bordo-vertice di cui si desidera ottenere il supporto.
- support_out – Un puntatore all'array di interi in cui scrivere il supporto. Deve avere una dimensione di almeno :c:func:
qf_edge_op_num_supportelementi.
qf_edge_op_zero
QfEdgeVertexOperator *qf_edge_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
1QfEdgeVertexOperator *zero = qf_edge_op_zero();
2
3QfEdgeVertexOperator *op_plus_zero = qf_edge_op_add(op, zero);
4
5assert(qf_edge_op_equal(op, op_plus_zero));Risultati
Un puntatore all'operatore creato.
qf_edge_op_one
QfEdgeVertexOperator *qf_edge_op_one(void)
Crea l'operatore di identità moltiplicativa.
La composizione dell'operatore ottenuto con questo metodo con un altro operatore non ha alcun effetto.
Esempio
1QfEdgeVertexOperator *one = qf_edge_op_one();
2
3QfEdgeVertexOperator *op_times_one = qf_edge_op_compose(op, one);
4
5assert(qf_edge_op_equal(op, op_times_one));Risultati
Un puntatore all'operatore creato.
qf_edge_op_has_groups
bool qf_edge_op_has_groups(const QfEdgeVertexOperator *op)
Verifica se un operatore ha l'attributo groups impostato.
Spiegazione dei termini relativi agli operatori di gruppo: utilizzare la struttura degli operatori.
Esempio
1QfEdgeVertexOperator *op = ...;
2
3bool has_groups = qf_edge_op_has_groups(op);Parametri
- op – Un puntatore all’operatore bordo-vertice da verificare.
Risultati
Se l'operatore tiene traccia degli indici di gruppo.
qf_edge_op_num_groups
uint32_t qf_edge_op_num_groups(const QfEdgeVertexOperator *op)
Recupera il numero di gruppi associati a un operatore.
Spiegazione dei termini relativi agli operatori di gruppo: utilizzare la struttura degli operatori.
Esempio
1QfEdgeVertexOperator *op = ...;
2
3uint32_t num_groups = qf_edge_op_num_groups(op);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 bordo-vertice di cui si desidera ottenere il numero di gruppi.
Risultati
Il numero di indici di gruppo derivante dall'attributo groups dell'operatore.
qf_edge_op_get_groups
void qf_edge_op_get_groups(const QfEdgeVertexOperator *op, uint32_t **groups_out, uint64_t *groups_len)
Recupera gli indici di gruppo per tutti i termini dell'operatore.
Spiegazione dei termini relativi agli operatori di gruppo: utilizzare la struttura degli operatori.
Esempio
1QfEdgeVertexOperator *op = ...;
2uint32_t *groups_out;
3uint64_t groups_len;
4
5qf_edge_op_get_groups(op, &groups_out, &groups_len);Questa funzione utilizza il buffer interno dell'operatore anziché copiarlo. Il puntatore restituito rimane valido solo fino a quando l'operatore non viene modificato o liberato; non liberarlo manualmente.
Parametri
- op – Un puntatore all’operatore bordo-vertice 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_edge_op_set_groups
QfExitCode qf_edge_op_set_groups(QfEdgeVertexOperator *op, const uint32_t *groups_in, uint64_t groups_len)
Imposta l'attributo groups dell'operatore specificato.
La lunghezza viene verificata in questa fase perché nessun altro passaggio successivo la ricontrolla: un numero insufficiente di indici causerebbe l’omissione silenziosa dei termini finali ogni volta che i termini vengono iterati insieme ai rispettivi gruppi, mentre un numero eccessivo darebbe origine a gruppi di report qf_edge_op_num_groups() che nessun termine contiene.
Spiegazione dei termini relativi agli operatori di gruppo: utilizzare la struttura degli operatori.
Esempio
1QfEdgeVertexOperator *op = ...;
2
3uint32_t num_terms = 4;
4uint32_t groups_in[4] = {0, 1, 0, 1};
5qf_edge_op_set_groups(op, groups_in, num_terms);Parametri
- op – Un puntatore all’operatore bordo-vertice di cui si desidera scrivere l’attributo
groups. - groups_in – Un puntatore all'array di interi
groupsin cui scrivere nell'operatore. - groups_len – Il numero di elementi presenti nell'array
groups_in.
Risultati
Un codice di uscita.
QfExitCode_Successin caso di successoQfExitCode_ValueErrorsegroups_lenè diverso dal numero di termini presenti nell'operatore
qf_edge_op_del_groups
void qf_edge_op_del_groups(QfEdgeVertexOperator *op)
Elimina l'attributo groups dall'operatore specificato.
Spiegazione dei termini relativi agli operatori di gruppo: utilizzare la struttura degli operatori.
Esempio
1QfEdgeVertexOperator *op = ...;
2
3qf_edge_op_del_groups(op);Parametri
- op – Un puntatore all'operatore bordo-vertice di cui si desidera eliminare l'attributo
groups.
qf_edge_op_split_out_groups
void qf_edge_op_split_out_groups(const QfEdgeVertexOperator *op, const uint32_t *group_indices, uint64_t num_indices, QfEdgeVertexOperator **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 ignorati anziché essere aggiunti in qualsiasi punto.
Spiegazione dei termini relativi agli operatori di gruppo: utilizzare la struttura degli operatori.
Esempio
1QfEdgeVertexOperator *op = ...;
2
3uint32_t groups_in[4] = {0, 1, 0, 1};
4qf_edge_op_set_groups(op, groups_in, 4);
5
6// build every group, in index order
7QfEdgeVertexOperator *group_ops[2];
8qf_edge_op_split_out_groups(op, NULL, 0, group_ops);
9
10// build only group 1
11uint32_t group_indices[1] = {1};
12QfEdgeVertexOperator *group_op[1];
13qf_edge_op_split_out_groups(op, group_indices, 1, group_op);Parametri
- op – Un puntatore all’operatore bordo-vertice
groupsda 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 da0a :c:func:qf_edge_op_num_groups- 1). - num_indices – Il numero di indici presenti nell'array
group_indices. Viene ignorato se ègroup_indicesNULL. - group_ops_out – Un puntatore all'array di :c:struct:
QfEdgeVertexOperatorin cui scrivere gli operatori per ciascun gruppo richiesto. Deve essere dimensionato in base anum_indicesquandogroup_indicesè diverso daNULL, oppure in base a :c:func:qf_edge_op_num_groupsquando èNULL.
qf_edge_op_add_term
void qf_edge_op_add_term(QfEdgeVertexOperator *op, uint64_t num_indices, const uint32_t *left_indices, const uint32_t *right_indices, const QkComplex64 *coeff)
Aggiunge un termine a un operatore esistente.
Qualsiasi argomento di tipo puntatore può essere NULL se e solo se la sua lunghezza corrispondente è pari a zero.
Questa funzione reimposta l'attributo groups dell'operatore su NULL.
Esempio
1QfEdgeVertexOperator *one = qf_edge_op_one();
2
3QfEdgeVertexOperator *op = qf_edge_op_zero();
4QkComplex64 coeff = {1.0, 0.0};
5
6qf_edge_op_add_term(op, 0, NULL, NULL, &coeff);
7
8assert(qf_edge_op_equal(op, one));Parametri
- op – Un puntatore all’operatore bordo-vertice da modificare.
- num_indices – La lunghezza di entrambi gli array di indici.
- left_indices – Un puntatore a un array di indici della modalità sinistra. La lunghezza di questo array dovrebbe essere
num_indices. - right_indices – Un puntatore a un array di indici in modalità destra. La lunghezza di questo array dovrebbe essere
num_indices. - coeff – Un puntatore al coefficiente complesso.
qf_edge_op_add
QfEdgeVertexOperator *qf_edge_op_add(const QfEdgeVertexOperator *left, const QfEdgeVertexOperator *right)
Somma due operatori.
Esempio
1QfEdgeVertexOperator *one = qf_edge_op_one();
2QfEdgeVertexOperator *zero = qf_edge_op_zero();
3
4QfEdgeVertexOperator *result = qf_edge_op_add(one, zero);
5
6assert(qf_edge_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_edge_op_scaled_add
QfEdgeVertexOperator *qf_edge_op_scaled_add(const QfEdgeVertexOperator *left, const QfEdgeVertexOperator *right, const QkComplex64 *factor)
Somma due operatori, ridimensionando i coefficienti di quello di destra.
In questo modo il ridimensionamento viene integrato nell'operazione di aggiunta, evitando così di creare una copia completamente ridimensionata solo right per aggiungerla. Il fatto di moltiplicare per un fattore equivale -1 quindi a una sottrazione; ecco perché non è prevista una funzione di sottrazione separata.
Esempio
1QfEdgeVertexOperator *one = qf_edge_op_one();
2QfEdgeVertexOperator *other = qf_edge_op_one();
3
4// Subtracting via a factor of -1 leaves the two terms cancelling each other out.
5QkComplex64 factor = {-1.0, 0.0};
6QfEdgeVertexOperator *result = qf_edge_op_scaled_add(one, other, &factor);
7
8QfEdgeVertexOperator *simplified = qf_edge_op_simplify(result, 1e-10);
9assert(qf_edge_op_len(simplified) == 0);In altre parole qf_edge_op_add(), questa operazione aggiunge i termini di right senza combinarli con quelli di left, quindi il risultato non tiene traccia di alcun indice di gruppo. Chiamare in seguito qf_edge_op_simplify() per concordare le stesse condizioni.
Parametri
- sinistra – Un puntatore all'operatore di sinistra.
- right – Un puntatore all'operatore "a destra".
- fattore – Un puntatore al fattore con cui ridimensionare i coefficienti dell’operatore a destra.
Risultati
Un puntatore all'operatore risultante, left + factor * right.
qf_edge_op_add_inplace
void qf_edge_op_add_inplace(QfEdgeVertexOperator *left, const QfEdgeVertexOperator *right)
Aggiunge un operatore all'interno di un altro, in loco.
La controparte "in-place" di qf_edge_op_add(), che evita di copiare left in una variabile di risultato appena allocata.
Questa funzione reimposta l'attributo groups dell'operatore su NULL.
Esempio
1QfEdgeVertexOperator *left = qf_edge_op_one();
2QfEdgeVertexOperator *right = qf_edge_op_one();
3
4qf_edge_op_add_inplace(left, right);
5
6assert(qf_edge_op_len(left) == 2);Parametri
- sinistra – Un puntatore all'operatore in cui effettuare l'aggiunta.
- right – Un puntatore all'operatore da aggiungere.
qf_edge_op_scaled_add_inplace
void qf_edge_op_scaled_add_inplace(QfEdgeVertexOperator *left, const QfEdgeVertexOperator *right, const QkComplex64 *factor)
Aggiunge un operatore a un altro operatore in loco, ridimensionando i coefficienti di quest'ultimo.
La controparte "in-place" di qf_edge_op_scaled_add(), che esegue il calcolo left + factor * right senza allocare un risultato. In quel caso, si sottrae -1 un fattore di.
Questa funzione reimposta l'attributo groups dell'operatore su NULL.
Esempio
1QfEdgeVertexOperator *left = qf_edge_op_one();
2QfEdgeVertexOperator *right = qf_edge_op_one();
3
4// Subtract, leaving two terms that cancel each other out.
5QkComplex64 factor = {-1.0, 0.0};
6qf_edge_op_scaled_add_inplace(left, right, &factor);
7
8QfEdgeVertexOperator *simplified = qf_edge_op_simplify(left, 1e-10);
9assert(qf_edge_op_len(simplified) == 0);Parametri
- sinistra – Un puntatore all'operatore in cui effettuare l'aggiunta.
- right – Un puntatore all'operatore da aggiungere.
- fattore – Un puntatore al fattore con cui ridimensionare i coefficienti dell’operatore a destra.
qf_edge_op_mul_inplace
void qf_edge_op_mul_inplace(QfEdgeVertexOperator *op, const QkComplex64 *scalar)
Moltiplica un operatore per uno scalare, in loco.
La controparte "in-place" di qf_edge_op_mul(), che evita di copiare l'operatore in una variabile di risultato appena allocata.
Esempio
1QfEdgeVertexOperator *op = qf_edge_op_one();
2QkComplex64 scalar = {2.0, 0.0};
3
4qf_edge_op_mul_inplace(op, &scalar);A differenza delle due aggiunte in loco descritte sopra, questa operazione preserva l’attributo groups : il ridimensionamento dei coefficienti lascia inalterato il numero di termini e, di conseguenza, l’invariante “un indice per termine”.
Parametri
- op – Un puntatore all’operatore di ridimensionamento.
- scalare – Un puntatore allo scalare.
qf_edge_op_mul
QfEdgeVertexOperator *qf_edge_op_mul(const QfEdgeVertexOperator *op, const QkComplex64 *scalar)
Moltiplica un operatore per uno scalare.
Esempio
1QfEdgeVertexOperator *one = qf_edge_op_one();
2QkComplex64 coeff = {2.0, 0.0};
3QfEdgeVertexOperator *result = qf_edge_op_mul(one, &coeff);
4
5QfEdgeVertexOperator *expected = qf_edge_op_zero();
6qf_edge_op_add_term(expected, 0, NULL, NULL, &coeff);
7
8assert(qf_edge_op_equal(result, expected));Parametri
- op – Un puntatore all'operatore.
- scalare – Un puntatore allo scalare.
Risultati
Un puntatore all’operatore risultante.
qf_edge_op_compose
QfEdgeVertexOperator *qf_edge_op_compose(const QfEdgeVertexOperator *left, const QfEdgeVertexOperator *right)
Combina due operatori tra loro.
Esempio
1QfEdgeVertexOperator *one = qf_edge_op_one();
2QfEdgeVertexOperator *zero = qf_edge_op_zero();
3
4QfEdgeVertexOperator *result = qf_edge_op_compose(one, zero);
5
6assert(qf_edge_op_equal(result, zero));La composizione di due operatori non tiene traccia di alcun gruppo, anche quando entrambi gli operandi lo fanno.
Parametri
- sinistra – Un puntatore all'operatore di sinistra.
- right – Un puntatore all'operatore "a destra".
Risultati
Un puntatore a left.compose(right), che equivale all'operatore result = right @ left in termini di moltiplicazione matriciale @. In altre parole, right viene applicato per primo. Per ottenere left @ right, scambia gli argomenti.
qf_edge_op_adjoint
QfEdgeVertexOperator *qf_edge_op_adjoint(const QfEdgeVertexOperator *op)
Restituisce il coniugato ermitiano (o aggiunto) di un operatore.
Ciò influisce sui termini e sui coefficienti come segue:
- i generatori in ogni termine invertono il loro ordine
- i coefficienti sono complessi coniugati
Esempio
1QfEdgeVertexOperator *op = qf_edge_op_zero();
2QkComplex64 coeff = {0.0, 1.0};
3qf_edge_op_add_term(op, 0, NULL, NULL, &coeff);
4
5QfEdgeVertexOperator *adjoint = qf_edge_op_adjoint(op);
6
7QfEdgeVertexOperator *expected = qf_edge_op_zero();
8QkComplex64 coeff_adj = {0.0, -1.0};
9qf_edge_op_add_term(expected, 0, NULL, NULL, &coeff_adj);
10
11assert(qf_edge_op_equal(adjoint, expected));È fondamentale invertire la stringa dell'operatore: i generatori di spigoli e vertici anticommutano quando condividono esattamente un indice, quindi, in BA != AB generale.
Parametri
- op – Un puntatore all'operatore.
Risultati
Un puntatore all'operatore creato.
qf_edge_op_ichop
void qf_edge_op_ichop(QfEdgeVertexOperator *op, double atol)
Rimuove i termini il cui coefficiente è inferiore alla soglia specificata.
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_edge_op_simplify() di chiamare!
Esempio
1QfEdgeVertexOperator *op = qf_edge_op_zero();
2QkComplex64 coeff = {1e-8, 0.0};
3qf_edge_op_add_term(op, 0, NULL, NULL, &coeff);
4
5qf_edge_op_ichop(op, 1e-6);
6
7QfEdgeVertexOperator *expected = qf_edge_op_zero();
8
9assert(qf_edge_op_equal(op, expected));Parametri
- op – Un puntatore all'operatore.
- atol – La tolleranza assoluta per il troncamento del coefficiente.
qf_edge_op_simplify
QfEdgeVertexOperator *qf_edge_op_simplify(const QfEdgeVertexOperator *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_edge_op_ichop()).
Quando un operatore è stato manipolato aritmeticamente o costruito in modo tale da non garantire l'unicità dei termini, è opportuno ricorrere a questo metodo prima di applicare qualsiasi metodo che filtri i coefficienti numericamente piccoli, al fine di evitare la perdita di informazioni.
Esempio
1QfEdgeVertexOperator *op = qf_edge_op_zero();
2QkComplex64 coeff = {1e-5, 0.0};
3for (int i = 0; i < 100; i++) {
4 qf_edge_op_add_term(op, 0, NULL, NULL, &coeff);
5}
6
7QfEdgeVertexOperator *canon = qf_edge_op_simplify(op, 1e-4);
8
9assert(qf_edge_op_len(canon) == 1);Questo raggruppa i termini in base ai loro array di indici esatti memorizzati. Due termini matematicamente uguali ma memorizzati con orientamenti del generatore diversi (come già ricordato E_kj = -E_jk) non vengono riconosciuti come duplicati; chiamare qf_edge_op_normal_ordered() prima per portarli in una forma comune.
Parametri
- op – Un puntatore all’operatore bordo-vertice da semplificare.
- atol – La tolleranza assoluta per il troncamento del coefficiente.
Risultati
Un operatore equivalente ma semplificato.
qf_edge_op_normal_ordered
QfEdgeVertexOperator *qf_edge_op_normal_ordered(const QfEdgeVertexOperator *op, bool ascending, bool reduce)
Restituisce un operatore equivalente con termini ordinati normalmente.
Il flag ascending stabilisce la convenzione di orientamento degli operatori di spigolo generalizzati: poiché , ogni operatore di spigolo ha due rappresentazioni, e questo sceglie (true) oppure (false), incorporando il segno nel coefficiente. Gli operatori di vertice non subiscono alcuna modifica.
Il flag reduce contrai inoltre i generatori adiacenti, ed è proprio questo che rende il risultato una vera e propria forma canonica. Le regole sono , , e la regola di fusione per i valori distinti .
qf_transfer_op_normal_ordered(), che non accetta alcun ascending flag poiché gli operatori di trasferimento e sono effettivamente operatori diversi, anziché due rappresentazioni dello stesso operatore.
Esempio
1// `E(1,0)` normal-orders to `-E(0,1)` when ascending
2QfEdgeVertexOperator *op = qf_edge_op_zero();
3uint32_t left[1] = {1};
4uint32_t right[1] = {0};
5QkComplex64 coeff = {1.0, 0.0};
6qf_edge_op_add_term(op, 1, left, right, &coeff);
7
8QfEdgeVertexOperator *ordered = qf_edge_op_normal_ordered(op, true, true);
9
10QfEdgeVertexOperator *expected = qf_edge_op_zero();
11uint32_t left_exp[1] = {0};
12uint32_t right_exp[1] = {1};
13QkComplex64 coeff_exp = {-1.0, 0.0};
14qf_edge_op_add_term(expected, 1, left_exp, right_exp, &coeff_exp);
15
16assert(qf_edge_op_equal(ordered, expected));Parametri
- op – Un puntatore all'operatore.
- ascendente – Se gli indici di ciascun operatore di bordo debbano essere crescenti o decrescenti.
- ridurre – Se contrarre i generatori adiacenti tramite le identità dell’algebra.
Risultati
Un puntatore all'operatore creato.
qf_edge_op_is_hermitian
bool qf_edge_op_is_hermitian(const QfEdgeVertexOperator *op, double atol)
Verifica se un operatore è ermitiano.
Esempio
1// `V(0) E(0,1)` is *not* Hermitian: the two generators share the index 0 and therefore
2// anticommute.
3QfEdgeVertexOperator *op = qf_edge_op_zero();
4uint32_t left[2] = {0, 0};
5uint32_t right[2] = {0, 1};
6QkComplex64 coeff = {1.0, 0.0};
7qf_edge_op_add_term(op, 2, left, right, &coeff);
8
9assert(!qf_edge_op_is_hermitian(op, 1e-10));Questo controllo viene implementato utilizzando qf_edge_op_equiv() la differenza qf_edge_op_normal_ordered() tra e op i suoi e qf_edge_op_adjoint() qf_edge_op_zero().
Parametri
- op – Un puntatore all’operatore bordo-vertice da verificare.
- atol – La tolleranza assoluta entro la quale i coefficienti sono considerati uguali.
Risultati
Se l'operatore fornito è ermitiano.
qf_edge_op_equal
bool qf_edge_op_equal(const QfEdgeVertexOperator *left, const QfEdgeVertexOperator *right)
Confronta due operatori per verificare se sono uguali.
In questo contesto, per "uguaglianza" si intende una corrispondenza esatta tra gli array di dati interni.
Esempio
1QfEdgeVertexOperator *one = qf_edge_op_one();
2QfEdgeVertexOperator *zero = qf_edge_op_zero();
3
4assert(qf_edge_op_equal(one, one));
5assert(!qf_edge_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_edge_op_equiv
bool qf_edge_op_equiv(const QfEdgeVertexOperator *left, const QfEdgeVertexOperator *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
1QfEdgeVertexOperator *zero = qf_edge_op_zero();
2
3QfEdgeVertexOperator *op = qf_edge_op_zero();
4QkComplex64 coeff = {1e-7, 0.0};
5qf_edge_op_add_term(op, 0, NULL, NULL, &coeff);
6
7assert(qf_edge_op_equiv(op, zero, 1e-6));
8assert(!qf_edge_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_edge_op_len
size_t qf_edge_op_len(const QfEdgeVertexOperator *op)
Restituisce la lunghezza (ovvero il numero di termini) dell'operatore specificato.
Esempio
1QfEdgeVertexOperator *op = qf_edge_op_zero();
2uint32_t left[2] = {0, 1};
3uint32_t right[2] = {1, 2};
4QkComplex64 coeff = {1.0, 0.0};
5qf_edge_op_add_term(op, 2, left, right, &coeff);
6
7assert(qf_edge_op_len(op) == 1);Parametri
- op – Un puntatore all’operatore bordo-vertice.
Risultati
La lunghezza (o il numero di termini) dell'operatore.
qf_edge_op_relabel_modes
QfExitCode qf_edge_op_relabel_modes(QfEdgeVertexOperator *op, uint64_t num_modes, const uint32_t *permutation)
Rinomina le modalità dell'operatore specificato.
Esempio
1QfEdgeVertexOperator *op = qf_edge_op_zero();
2uint32_t left[2] = {0, 2};
3uint32_t right[2] = {1, 3};
4QkComplex64 coeff = {1.0, 0.0};
5qf_edge_op_add_term(op, 2, left, right, &coeff);
6
7uint32_t permutation[4] = {3, 2, 1, 0};
8
9QfExitCode exit = qf_edge_op_relabel_modes(op, 4, permutation);
10
11assert(exit == QfExitCode_Success);Entrambi gli array di indici vengono rinominati. A differenza della maggior parte delle operazioni, questa preserva l’attributo groups dell’operatore, poiché la rietichettatura permuta gli indici di modalità senza riordinare, dividere o unire i termini.
Parametri
- op – Un puntatore all’operatore bordo-vertice.
- num_modes – Il numero di indici di modalità presenti nell'elenco di permutazioni fornito.
- permutazione – L'elenco delle permutazioni degli indici.
Risultati
Un codice di uscita.
QfExitCode_Successin caso di successoQfExitCode_DuplicateIndexErrorse nella permutazione sono stati rilevati indici duplicatiQfExitCode_IndexErrorper eventuali altri errori relativi agli indici, come ad esempio indici non validi.