Skip to main content
IBM Quantum Platform

QfTransferVertexOperator

QfTransferVertexOperator

struct QfTransferVertexOperator

Un operatore di trasferimento dei vertici.

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 in termini degli operatori "transfer-vertex" ( TjkT_{jk}, VjV_j ):

Vj=−iγ2j−1γ2j=1−2aj†aj ,Tjk=i2VjEjk=i2γ2jγ2k−1 ,Tkj=i2EjkVk=−i2γ2j−1γ2k\begin{align} V_j &= -i \gamma_{2j-1} \gamma_{2j} = 1 - 2 a^\dagger_j a_j \, , \nonumber \\ T_{jk} &= \frac{i}{2} V_j E_{jk} = \frac{i}{2} \gamma_{2j} \gamma_{2k-1} \, , \nonumber \\ T_{kj} &= \frac{i}{2} E_{jk} V_k = -\frac{i}{2} \gamma_{2j-1} \gamma_{2k} \nonumber \end{align}

dove EjkE_{jk} è un operatore di bordo di e QfEdgeVertexOperator questi singoli termini soddisfano le seguenti relazioni di commutazione miste fermionico-bosoniche per j<k<l<mj \lt k \lt l \lt m : [1]

{Tjk,Vk}=0{Tjk,Tlk}=0[Vk,Vl]=0[Tjk,Vl]=0[Tjk,Tlm]=0[Tjk,Tkj]=0[Tjk,Tkm]=0 .\begin{align} \left\{ T_{jk}, V_k \right\} &= 0 \nonumber \\ \left\{ T_{jk}, T_{lk} \right\} &= 0 \nonumber \\ \left[ V_k, V_l \right] &= 0 \nonumber \\ \left[ T_{jk}, V_l \right] &= 0 \nonumber \\ \left[ T_{jk}, T_{lm} \right] &= 0 \nonumber \\ \left[ T_{jk}, T_{kj} \right] &= 0 \nonumber \\ \left[ T_{jk}, T_{km} \right] &= 0 \nonumber \, . \end{align}
Attenzione

A differenza degli operatori di bordo, in cui Ekj=−EjkE_{kj} = -E_{jk} rende i due orientamenti due rappresentazioni di un unico operatore, TjkT_{jk} e TkjT_{kj} sono operatori diversi. L'ordine dei due array di indici è quindi significativo e non esiste una convenzione di orientamento da normalizzare — motivo per cui non qf_transfer_op_normal_ordered() accetta alcun parametro ascending , mentre lo qf_edge_op_normal_ordered() fa.

Possiamo prendere un po’ di libertà con la notazione e definire Vj=TjjV_j = T_{jj}, che riflette il funzionamento della struttura interna di questo operatore. Ne consegue che la definizione dell'intero operatore è la seguente:

TransferVertexOperator=∑ici⨂lrTlr ,\text{\texttt{TransferVertexOperator}} = \sum_i c_i \bigotimes_{lr} T_{lr} \, ,

dove lrlr indica i termini dell'operatore in questione e cic_i è il coefficiente (complesso) che costituisce la combinazione lineare dei prodotti. Gli indici ll e rr 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 “ TlrT_{lr} ” come a operatori di trasferimento 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
coeffsUn vettore di coefficienti complessi costituito da due numeri in virgola mobile a 64 bit.
left_indicesUn vettore di interi a 32 bit che memorizza gli indici delle modalità fermioniche di sinistra ( ll ).
right_indicesUn vettore di interi a 32 bit che memorizza gli indici delle modalità fermioniche di destra ( rr ).
boundariesUn vettore di numeri interi che indica i confini tra i termini.

Le modalità fermioniche indicizzate da e left_indices 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.

Nota

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

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_transfer_op_simplify().

Costruzioni

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

Rubrica 1
Rubrica 2
qf_transfer_op_new()Crea un nuovo operatore dagli array forniti.
qf_transfer_op_zero()Costruisce l'operatore di identità additiva.
qf_transfer_op_one()Crea l'operatore di identità moltiplicativa.
qf_transfer_op_add_term()Aggiunge un termine a un file esistente QfTransferVertexOperator.
Nota

Aritmetica

Le seguenti funzioni consentono di eseguire operazioni aritmetiche:

Rubrica 1
Rubrica 2
qf_transfer_op_add()Somma due operatori.
qf_transfer_op_mul()Moltiplica un operatore per uno scalare.
qf_transfer_op_compose()Combina due operatori tra loro.
qf_transfer_op_adjoint()Restituisce l'operatore coniugato ermitiano.

Manipolazione

Le seguenti funzioni forniscono la logica di manipolazione degli operatori:

Rubrica 1
Rubrica 2
qf_transfer_op_ichop()Elimina i termini con coefficienti di piccola entità.
qf_transfer_op_simplify()Restituisce un operatore equivalente ma semplificato.
qf_transfer_op_normal_ordered()Restituisce un operatore equivalente con termini ordinati normalmente.
qf_transfer_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_transfer_op_is_hermitian()Restituisce se un operatore è ermitiano.
qf_transfer_op_len()Restituisce il numero di termini presenti in questo operatore.

Associazione

Le seguenti funzioni mappano questo operatore in un’altra rappresentazione:


[ 1 ]

https://arxiv.org/abs/2512.11418


Membri

qf_transfer_op_new

QfTransferVertexOperator *qf_transfer_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, VjV_j; uno con indici diversi è un operatore di trasferimento, TjkT_{jk}.

Attenzione

A differenza degli operatori di bordo, TjkT_{jk} e TkjT_{kj} sono operatori diversi, non due rappresentazioni dello stesso operatore. L'ordine dei due array di indici è quindi significativo.

Esempio

1// this builds `1.0 + (-1.0) * V(0) T(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};
8QfTransferVertexOperator *op = qf_transfer_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_transfer_op_free

void qf_transfer_op_free(QfTransferVertexOperator *op)

Rilascia un operatore esistente.

Esempio

1QfTransferVertexOperator *op = qf_transfer_op_one();
2qf_transfer_op_free(op);

Parametri

  • op – Un puntatore all’operatore di trasferimento dei vertici da liberare.

qf_transfer_op_get_coeffs

void qf_transfer_op_get_coeffs(const QfTransferVertexOperator *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;
 2QkComplex64 coeffs[2] = {{1.0, 0.0}, {0.0, -1.0}};
 3uint32_t boundaries[3] = {0, 0, 0};
 4QfTransferVertexOperator *op =
 5    qf_transfer_op_new(num_terms, 0, coeffs, NULL, NULL, boundaries);
 6
 7QkComplex64 *coeffs_out;
 8uint64_t coeffs_len;
 9
10qf_transfer_op_get_coeffs(op, &coeffs_out, &coeffs_len);
11
12assert(coeffs_len == 2);
Nota

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 di trasferimento dei vertici 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_transfer_op_get_left_indices

void qf_transfer_op_get_left_indices(const QfTransferVertexOperator *op, uint32_t **left_indices_out, uint64_t *left_indices_len)

Fornisce accesso in sola lettura agli indici della modalità sinistra dell’operatore.

Vedi anche

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};
 7QfTransferVertexOperator *op = qf_transfer_op_new(num_terms, num_indices, coeffs,
 8                                                  left_indices, right_indices, boundaries);
 9
10uint32_t *left_out;
11uint64_t left_len;
12
13qf_transfer_op_get_left_indices(op, &left_out, &left_len);
14
15assert(left_len == 2);
Nota

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 di trasferimento dei vertici a cui gli indici di sinistra devono accedere.
  • 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_transfer_op_get_right_indices

void qf_transfer_op_get_right_indices(const QfTransferVertexOperator *op, uint32_t **right_indices_out, uint64_t *right_indices_len)

Fornisce accesso in sola lettura agli indici della modalità a destra dell’operatore.

Vedi anche

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};
 7QfTransferVertexOperator *op = qf_transfer_op_new(num_terms, num_indices, coeffs,
 8                                                  left_indices, right_indices, boundaries);
 9
10uint32_t *right_out;
11uint64_t right_len;
12
13qf_transfer_op_get_right_indices(op, &right_out, &right_len);
14
15assert(right_len == 2);
Nota

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 di trasferimento dei vertici a cui gli indici di destra devono accedere.
  • 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_transfer_op_get_boundaries

void qf_transfer_op_get_boundaries(const QfTransferVertexOperator *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 = 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};
 7QfTransferVertexOperator *op = qf_transfer_op_new(num_terms, num_indices, coeffs,
 8                                                  left_indices, right_indices, boundaries);
 9
10size_t *boundaries_out;
11uint64_t boundaries_len;
12
13qf_transfer_op_get_boundaries(op, &boundaries_out, &boundaries_len);
14
15assert(boundaries_len == 2);
Nota

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 “transfer-vertex” 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_transfer_op_num_support

uint32_t qf_transfer_op_num_support(const QfTransferVertexOperator *op)

Recupera la dimensione del supporto di un operatore.

Utilizzare questa opzione per impostare la dimensione del buffer di output di qf_transfer_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};
 5QfTransferVertexOperator *op =
 6    qf_transfer_op_new(2, 3, coeffs, left_indices, right_indices, boundaries);
 7
 8uint32_t num_support = qf_transfer_op_num_support(op);
 9
10assert(num_support == 3);

Parametri

  • op – Un puntatore all'operatore di trasferimento dei vertici di cui si desidera ottenere la dimensione del supporto.

Risultati

Il numero di indici di modalità distinti su cui agisce l'operatore.

qf_transfer_op_get_support

void qf_transfer_op_get_support(const QfTransferVertexOperator *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};
 5QfTransferVertexOperator *op =
 6    qf_transfer_op_new(2, 3, coeffs, left_indices, right_indices, boundaries);
 7
 8uint32_t num_support = qf_transfer_op_num_support(op);
 9uint32_t *support_out = malloc(num_support * sizeof(uint32_t));
10
11qf_transfer_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);
Nota

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_transfer_op_num_support() la lunghezza richiesta.

Nota

Sia l'indice sinistro che quello destro di ogni operatore di trasferimento generalizzato contribuiscono al supporto.

Parametri

  • op – Un puntatore all’operatore di trasferimento dei vertici 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_transfer_op_num_support elementi.

qf_transfer_op_zero

QfTransferVertexOperator *qf_transfer_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

1QfTransferVertexOperator *zero = qf_transfer_op_zero();
2
3QfTransferVertexOperator *op_plus_zero = qf_transfer_op_add(op, zero);
4
5assert(qf_transfer_op_equal(op, op_plus_zero));

Risultati

Un puntatore all'operatore creato.

qf_transfer_op_one

QfTransferVertexOperator *qf_transfer_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

1QfTransferVertexOperator *one = qf_transfer_op_one();
2
3QfTransferVertexOperator *op_times_one = qf_transfer_op_compose(op, one);
4
5assert(qf_transfer_op_equal(op, op_times_one));

Risultati

Un puntatore all'operatore creato.

qf_transfer_op_has_groups

bool qf_transfer_op_has_groups(const QfTransferVertexOperator *op)

Verifica se un operatore ha l'attributo groups impostato.

Vedi anche

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

Esempio

1QfTransferVertexOperator *op = ...;
2
3bool has_groups = qf_transfer_op_has_groups(op);

Parametri

  • op – Un puntatore all’operatore di trasferimento dei vertici da verificare.

Risultati

Se l'operatore tiene traccia degli indici di gruppo.

qf_transfer_op_num_groups

uint32_t qf_transfer_op_num_groups(const QfTransferVertexOperator *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

1QfTransferVertexOperator *op = ...;
2
3uint32_t num_groups = qf_transfer_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 del vertice di trasferimento di cui si desidera ottenere il numero di gruppi.

Risultati

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

qf_transfer_op_get_groups

void qf_transfer_op_get_groups(const QfTransferVertexOperator *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

1QfTransferVertexOperator *op = ...;
2uint32_t *groups_out;
3uint64_t groups_len;
4
5qf_transfer_op_get_groups(op, &groups_out, &groups_len);
Nota

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 del vertice di trasferimento 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_transfer_op_set_groups

QfExitCode qf_transfer_op_set_groups(QfTransferVertexOperator *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’eliminazione silenziosa dei termini finali ogni volta che i termini vengono iterati insieme ai rispettivi gruppi, mentre un numero eccessivo porterebbe a qf_transfer_op_num_groups() segnalare gruppi di cui nessun termine fa parte.

Vedi anche

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

Esempio

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

Parametri

  • op – Un puntatore all'operatore del vertice di trasferimento 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 .

Risultati

Un codice di uscita.

  • QfExitCode_Success in caso di successo
  • QfExitCode_ValueError se groups_len è diverso dal numero di termini presenti nell'operatore

qf_transfer_op_del_groups

void qf_transfer_op_del_groups(QfTransferVertexOperator *op)

Elimina l'attributo groups dall'operatore specificato.

Vedi anche

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

Esempio

1QfTransferVertexOperator *op = ...;
2
3qf_transfer_op_del_groups(op);

Parametri

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

qf_transfer_op_split_out_groups

void qf_transfer_op_split_out_groups(const QfTransferVertexOperator *op, const uint32_t *group_indices, uint64_t num_indices, QfTransferVertexOperator **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 che 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

 1QfTransferVertexOperator *op = ...;
 2
 3uint32_t groups_in[4] = {0, 1, 0, 1};
 4qf_transfer_op_set_groups(op, groups_in, 4);
 5
 6// build every group, in index order
 7QfTransferVertexOperator *group_ops[2];
 8qf_transfer_op_split_out_groups(op, NULL, 0, group_ops);
 9
10// build only group 1
11uint32_t group_indices[1] = {1};
12QfTransferVertexOperator *group_op[1];
13qf_transfer_op_split_out_groups(op, group_indices, 1, group_op);

Parametri

  • op – Un puntatore all'operatore del vertice di trasferimento da cui groups effettuare la suddivisione.
  • 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_transfer_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:QfTransferVertexOperator 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_transfer_op_num_groups quando è NULL.

qf_transfer_op_add_term

void qf_transfer_op_add_term(QfTransferVertexOperator *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.

Attenzione

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

Esempio

1QfTransferVertexOperator *one = qf_transfer_op_one();
2
3QfTransferVertexOperator *op = qf_transfer_op_zero();
4QkComplex64 coeff = {1.0, 0.0};
5
6qf_transfer_op_add_term(op, 0, NULL, NULL, &coeff);
7
8assert(qf_transfer_op_equal(op, one));

Parametri

  • op – Un puntatore all’operatore del vertice di trasferimento 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_transfer_op_add

QfTransferVertexOperator *qf_transfer_op_add(const QfTransferVertexOperator *left, const QfTransferVertexOperator *right)

Somma due operatori.

Esempio

1QfTransferVertexOperator *one = qf_transfer_op_one();
2QfTransferVertexOperator *zero = qf_transfer_op_zero();
3
4QfTransferVertexOperator *result = qf_transfer_op_add(one, zero);
5
6assert(qf_transfer_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_transfer_op_scaled_add

QfTransferVertexOperator *qf_transfer_op_scaled_add(const QfTransferVertexOperator *left, const QfTransferVertexOperator *right, const QkComplex64 *factor)

Somma due operatori, scalando 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

1QfTransferVertexOperator *one = qf_transfer_op_one();
2QfTransferVertexOperator *other = qf_transfer_op_one();
3
4// Subtracting via a factor of -1 leaves the two terms cancelling each other out.
5QkComplex64 factor = {-1.0, 0.0};
6QfTransferVertexOperator *result = qf_transfer_op_scaled_add(one, other, &factor);
7
8QfTransferVertexOperator *simplified = qf_transfer_op_simplify(result, 1e-10);
9assert(qf_transfer_op_len(simplified) == 0);
Nota

In altre parole qf_transfer_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_transfer_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_transfer_op_add_inplace

void qf_transfer_op_add_inplace(QfTransferVertexOperator *left, const QfTransferVertexOperator *right)

Aggiunge un operatore a un altro, in loco.

La controparte "in-place" di qf_transfer_op_add(), che evita di copiare in left una variabile di risultato appena allocata.

Attenzione

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

Esempio

1QfTransferVertexOperator *left = qf_transfer_op_one();
2QfTransferVertexOperator *right = qf_transfer_op_one();
3
4qf_transfer_op_add_inplace(left, right);
5
6assert(qf_transfer_op_len(left) == 2);

Parametri

  • sinistra – Un puntatore all’operatore in cui effettuare l’aggiunta.
  • right – Un puntatore all'operatore da aggiungere.

qf_transfer_op_scaled_add_inplace

void qf_transfer_op_scaled_add_inplace(QfTransferVertexOperator *left, const QfTransferVertexOperator *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_transfer_op_scaled_add(), che esegue il calcolo left + factor * right senza allocare un risultato. In quel caso, si sottrae -1 un fattore di.

Attenzione

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

Esempio

1QfTransferVertexOperator *left = qf_transfer_op_one();
2QfTransferVertexOperator *right = qf_transfer_op_one();
3
4// Subtract, leaving two terms that cancel each other out.
5QkComplex64 factor = {-1.0, 0.0};
6qf_transfer_op_scaled_add_inplace(left, right, &factor);
7
8QfTransferVertexOperator *simplified = qf_transfer_op_simplify(left, 1e-10);
9assert(qf_transfer_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_transfer_op_mul_inplace

void qf_transfer_op_mul_inplace(QfTransferVertexOperator *op, const QkComplex64 *scalar)

Moltiplica un operatore per uno scalare, in loco.

La controparte "in-place" di qf_transfer_op_mul(), che evita di copiare l'operatore in una variabile di risultato appena allocata.

Esempio

1QfTransferVertexOperator *op = qf_transfer_op_one();
2QkComplex64 scalar = {2.0, 0.0};
3
4qf_transfer_op_mul_inplace(op, &scalar);
Nota

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_transfer_op_mul

QfTransferVertexOperator *qf_transfer_op_mul(const QfTransferVertexOperator *op, const QkComplex64 *scalar)

Moltiplica un operatore per uno scalare.

Esempio

1QfTransferVertexOperator *one = qf_transfer_op_one();
2QkComplex64 coeff = {2.0, 0.0};
3QfTransferVertexOperator *result = qf_transfer_op_mul(one, &coeff);
4
5QfTransferVertexOperator *expected = qf_transfer_op_zero();
6qf_transfer_op_add_term(expected, 0, NULL, NULL, &coeff);
7
8assert(qf_transfer_op_equal(result, expected));

Parametri

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

Risultati

Un puntatore all'operatore risultante.

qf_transfer_op_compose

QfTransferVertexOperator *qf_transfer_op_compose(const QfTransferVertexOperator *left, const QfTransferVertexOperator *right)

Combina due operatori tra loro.

Esempio

1QfTransferVertexOperator *one = qf_transfer_op_one();
2QfTransferVertexOperator *zero = qf_transfer_op_zero();
3
4QfTransferVertexOperator *result = qf_transfer_op_compose(one, zero);
5
6assert(qf_transfer_op_equal(result, zero));
Nota

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_transfer_op_adjoint

QfTransferVertexOperator *qf_transfer_op_adjoint(const QfTransferVertexOperator *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

 1QfTransferVertexOperator *op = qf_transfer_op_zero();
 2QkComplex64 coeff = {0.0, 1.0};
 3qf_transfer_op_add_term(op, 0, NULL, NULL, &coeff);
 4
 5QfTransferVertexOperator *adjoint = qf_transfer_op_adjoint(op);
 6
 7QfTransferVertexOperator *expected = qf_transfer_op_zero();
 8QkComplex64 coeff_adj = {0.0, -1.0};
 9qf_transfer_op_add_term(expected, 0, NULL, NULL, &coeff_adj);
10
11assert(qf_transfer_op_equal(adjoint, expected));
Nota

È fondamentale invertire la stringa dell'operatore: i generatori di trasferimento e di vertice anticommutano quando condividono un indice, quindi, in BA != AB generale.

Parametri

  • op – Un puntatore all'operatore.

Risultati

Un puntatore all'operatore creato.

qf_transfer_op_ichop

void qf_transfer_op_ichop(QfTransferVertexOperator *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_transfer_op_simplify() di chiamare!

Esempio

1QfTransferVertexOperator *op = qf_transfer_op_zero();
2QkComplex64 coeff = {1e-8, 0.0};
3qf_transfer_op_add_term(op, 0, NULL, NULL, &coeff);
4
5qf_transfer_op_ichop(op, 1e-6);
6
7QfTransferVertexOperator *expected = qf_transfer_op_zero();
8
9assert(qf_transfer_op_equal(op, expected));

Parametri

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

qf_transfer_op_simplify

QfTransferVertexOperator *qf_transfer_op_simplify(const QfTransferVertexOperator *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_transfer_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.

Esempio

1QfTransferVertexOperator *op = qf_transfer_op_zero();
2QkComplex64 coeff = {1e-5, 0.0};
3for (int i = 0; i < 100; i++) {
4  qf_transfer_op_add_term(op, 0, NULL, NULL, &coeff);
5}
6
7QfTransferVertexOperator *canon = qf_transfer_op_simplify(op, 1e-4);
8
9assert(qf_transfer_op_len(canon) == 1);
Nota

Questo raggruppa i termini in base agli array di indici esatti in cui sono memorizzati. Effettuare prima qf_transfer_op_normal_ordered() la per ridurre i termini matematicamente equivalenti a una forma comune.

Parametri

  • op – Un puntatore all’operatore di trasferimento dei vertici da semplificare.
  • atol – La tolleranza assoluta per il troncamento del coefficiente.

Risultati

Un operatore equivalente ma semplificato.

qf_transfer_op_normal_ordered

QfTransferVertexOperator *qf_transfer_op_normal_ordered(const QfTransferVertexOperator *op, bool reduce)

Restituisce un operatore equivalente con termini ordinati normalmente.

Il flag reduce attiva i generatori adiacenti. Ci sono esattamente due regole: VjVj=1V_j V_j = 1 e TjkTjk=1/4T_{jk} T_{jk} = 1/4 (due fattori identici adiacenti si contraggono in uno scalare), e TjkTkj=−14VjVkT_{jk} T_{kj} = -\frac{1}{4} V_j V_k (due operatori di trasferimento antiparalleli diventano una coppia di operatori di vertice).

Esempio

 1// `T(0,1) T(1,0)` reduces to `-1/4 V(0) V(1)`
 2QfTransferVertexOperator *op = qf_transfer_op_zero();
 3uint32_t left[2] = {0, 1};
 4uint32_t right[2] = {1, 0};
 5QkComplex64 coeff = {4.0, 0.0};
 6qf_transfer_op_add_term(op, 2, left, right, &coeff);
 7
 8QfTransferVertexOperator *ordered = qf_transfer_op_normal_ordered(op, true);
 9
10QfTransferVertexOperator *expected = qf_transfer_op_zero();
11uint32_t left_exp[2] = {0, 1};
12uint32_t right_exp[2] = {0, 1};
13QkComplex64 coeff_exp = {-1.0, 0.0};
14qf_transfer_op_add_term(expected, 2, left_exp, right_exp, &coeff_exp);
15
16assert(qf_transfer_op_equal(ordered, expected));
Nota

A differenza di qf_edge_op_normal_ordered(), questa funzione non accetta alcun parametro ascending . Non esiste una convenzione di orientamento da stabilire: TjkT_{jk} e TkjT_{kj} sono operatori diversi, non due rappresentazioni dello stesso operatore.

Nota

Non esiste alcuna regola di fusione. Due operatori di trasferimento che condividono una singola modalità non si fondono mai in uno solo, quindi un prodotto come TjkTjlT_{jk} T_{jl} non può essere abbreviato.

Parametri

  • op – Un puntatore all'operatore.
  • ridurre – Se contrarre i generatori adiacenti tramite le identità algebriche.

Risultati

Un puntatore all'operatore creato.

qf_transfer_op_is_hermitian

bool qf_transfer_op_is_hermitian(const QfTransferVertexOperator *op, double atol)

Verifica se un operatore è ermitiano.

Esempio

1// `V(0) T(0,1)` is *not* Hermitian: the two generators share the index 0 and therefore
2// anticommute.
3QfTransferVertexOperator *op = qf_transfer_op_zero();
4uint32_t left[2] = {0, 0};
5uint32_t right[2] = {0, 1};
6QkComplex64 coeff = {1.0, 0.0};
7qf_transfer_op_add_term(op, 2, left, right, &coeff);
8
9assert(!qf_transfer_op_is_hermitian(op, 1e-10));
Nota

Questo controllo viene implementato utilizzando qf_transfer_op_equiv() la differenza qf_transfer_op_normal_ordered() tra e op i suoi e qf_transfer_op_adjoint() qf_transfer_op_zero().

Parametri

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

Risultati

Se l'operatore fornito è ermitiano.

qf_transfer_op_equal

bool qf_transfer_op_equal(const QfTransferVertexOperator *left, const QfTransferVertexOperator *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

1QfTransferVertexOperator *one = qf_transfer_op_one();
2QfTransferVertexOperator *zero = qf_transfer_op_zero();
3
4assert(qf_transfer_op_equal(one, one));
5assert(!qf_transfer_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_transfer_op_equiv

bool qf_transfer_op_equiv(const QfTransferVertexOperator *left, const QfTransferVertexOperator *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

1QfTransferVertexOperator *zero = qf_transfer_op_zero();
2
3QfTransferVertexOperator *op = qf_transfer_op_zero();
4QkComplex64 coeff = {1e-7, 0.0};
5qf_transfer_op_add_term(op, 0, NULL, NULL, &coeff);
6
7assert(qf_transfer_op_equiv(op, zero, 1e-6));
8assert(!qf_transfer_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_transfer_op_len

size_t qf_transfer_op_len(const QfTransferVertexOperator *op)

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

Esempio

1QfTransferVertexOperator *op = qf_transfer_op_zero();
2uint32_t left[2] = {0, 1};
3uint32_t right[2] = {1, 2};
4QkComplex64 coeff = {1.0, 0.0};
5qf_transfer_op_add_term(op, 2, left, right, &coeff);
6
7assert(qf_transfer_op_len(op) == 1);

Parametri

  • op – Un puntatore all'operatore del vertice di trasferimento.

Risultati

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

qf_transfer_op_relabel_modes

QfExitCode qf_transfer_op_relabel_modes(QfTransferVertexOperator *op, uint64_t num_modes, const uint32_t *permutation)

Rinomina le modalità dell'operatore specificato.

Esempio

 1QfTransferVertexOperator *op = qf_transfer_op_zero();
 2uint32_t left[2] = {0, 2};
 3uint32_t right[2] = {1, 3};
 4QkComplex64 coeff = {1.0, 0.0};
 5qf_transfer_op_add_term(op, 2, left, right, &coeff);
 6
 7uint32_t permutation[4] = {3, 2, 1, 0};
 8
 9QfExitCode exit = qf_transfer_op_relabel_modes(op, 4, permutation);
10
11assert(exit == QfExitCode_Success);
Nota

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 del vertice di trasferimento.
  • 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_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.