Skip to main content
IBM Quantum Platform

TransferVertexOperator

class TransferVertexOperator(coeffs, left_indices, right_indices, boundaries)

Basi: object

Un operatore di trasferimento dei vertici.


Definizione

Questo operatore è definito in termini degli operatori "transfer-vertex" ( TjkT_{jk}, VjV_j ):

Vj=−iγ2j−1γ2j=−(ajaj−ajaj†+aj†aj−aj†aj†)=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} = -(a_j a_j - a_j a^\dagger_j + a^\dagger_j a_j - a^\dagger_j a^\dagger_j) = 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 EdgeVertexOperator 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}

Un semplice esempio può essere rappresentato visivamente in questo modo:

Una rappresentazione visiva di un operatore di trasferimento di vertici.

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:

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

dove lrlr indica l'indice dei termini dell'operatore coinvolti 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 TlrT_{lr} i come operatori di trasferimento generalizzati.


Implementazione

Questa classe 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 (vedi ll ).
right_indicesUn vettore di interi a 32 bit che memorizza gli indici delle modalità fermioniche di destra (vedi rr ).
boundariesUn vettore di numeri interi che indica i limiti in e actions modes.

Le modalità fermioniche indicizzate da left_indices e right_indices sono considerate prive di spin.

Nota

È possibile accedere a copie in sola lettura di questi array interni tramite i rispettivi metodi: get_coeffs(), get_left_indices(), get_right_indices(), e get_boundaries().

Questa struttura dati consente una creazione e una manipolazione degli operatori estremamente efficienti. Tuttavia, ciò implica che in qualsiasi momento un operatore possa contenere termini duplicati. Questi devono essere risolti manualmente utilizzando simplify().

Costruzioni

È possibile creare un operatore direttamente fornendo gli array descritti sopra:

>>> from qiskit_fermions.operators import TransferVertexOperator
>>> coeffs = [1.0, 2.0, -3.0, 4.0j, -0.5j]
>>> left_indices = [0, 3, 0, 2, 3, 0]
>>> right_indices = [1, 4, 1, 2, 3, 1]
>>> boundaries = [0, 0, 1, 2, 4, 6]
>>> op = TransferVertexOperator(coeffs, left_indices, right_indices, boundaries)
>>> print(format(op))
  1.000000e0 +0.000000e0j * ()
  2.000000e0 +0.000000e0j * (T(0,1))
  0.000000e0 +4.000000e0j * (T(0,1) V(2))
 -0.000000e0-5.000000e-1j * (V(3) T(0,1))
 -3.000000e0 +0.000000e0j * (T(3,4))

Per comodità, è possibile creare un operatore a partire da un dizionario di tipo “ Python ” in questo modo:

>>> op = TransferVertexOperator.from_dict(
...     {
...         (): 1.0,
...         ((0, 1),): 2.0,
...         ((3, 4),): -3.0,
...         ((0, 1), (2, 2)): 4.0j,
...         ((3, 3), (0, 1)): -0.5j,
...     }
... )
>>> print(format(op))
  1.000000e0 +0.000000e0j * ()
  2.000000e0 +0.000000e0j * (T(0,1))
  0.000000e0 +4.000000e0j * (T(0,1) V(2))
 -0.000000e0-5.000000e-1j * (V(3) T(0,1))
 -3.000000e0 +0.000000e0j * (T(3,4))

Inoltre, sono disponibili i seguenti metodi di costruzione e di assistenza rapida:

Rubrica 1
Rubrica 2
zero()Costruisce l'operatore di identità additiva.
one()Crea l'operatore di identità moltiplicativa.
from_terms(termini)Crea un nuovo operatore a partire da un iteratore di termini (vedi anche iter_terms()).
from_terms_with_groups(termini)Crea un nuovo operatore a partire da un iteratore di termini con gruppi (vedi anche iter_terms_with_groups()).

Formattazione

Negli esempi precedenti, gli operatori creati sono stati visualizzati utilizzando l'output di format(), ottenendo così una rappresentazione dell'operatore leggibile dall'utente.

>>> print(format(op))
  1.000000e0 +0.000000e0j * ()
  2.000000e0 +0.000000e0j * (T(0,1))
  0.000000e0 +4.000000e0j * (T(0,1) V(2))
 -0.000000e0-5.000000e-1j * (V(3) T(0,1))
 -3.000000e0 +0.000000e0j * (T(3,4))
Nota

L'ordine di stampa di format(op) viene ordinato in modo esplicito prima della stampa. Pertanto, non riflette l'ordine dei termini all'interno dell'operatore.

È possibile ottenere una forma alternativa dalla funzione repr() , che produce una rappresentazione interpretabile secondo il modello " Python ". In altre parole, questo output può essere facilmente copiato e incollato nella shell di Python :

>>> print(repr(op))
TransferVertexOperator.from_dict({...})

Infine, per gli operatori di grandi dimensioni, entrambi questi output potrebbero risultare molto lunghi e indesiderabili. A questo punto, dalla funzione str() è possibile ottenere un modulo molto semplice con informazioni minime:

>>> print(str(op))
<TransferVertexOperator with 5 terms>

Iterazione

Poiché la struttura dati sottostante è implementata in Rust e presenta un layout non banale, non è possibile iterare direttamente su di essa:

>>> list(iter(op))
Traceback (most recent call last):
  ...
TypeError: 'qiskit_fermions.operators.transfer_vertex_operator.TransferVertexOperator' object is not iterable

Questa classe fornisce invece degli iteratori personalizzati per soddisfare tale scopo:

>>> list(sorted(op.iter_terms()))
[([], (1+0j)), ([(0, 1)], (2+0j)), ([(0, 1), (2, 2)], 4j), ([(3, 3), (0, 1)], (-0-0.5j)), ([(3, 4)], (-3+0j))]
Vedi anche

iter_terms()

Per ulteriori dettagli relativi all'implementazione.

La tabella seguente elenca tutti gli iteratori disponibili:

Rubrica 1
Rubrica 2
iter_terms()Un iteratore sui termini dell'operatore.
iter_terms_with_groups()Un iteratore sui termini dell’operatore con il relativo indice di gruppo.

Aritmetica

Sono supportate le seguenti operazioni aritmetiche:

Addizione/Sottrazione

>>> op = TransferVertexOperator.one()
>>> (op + op).simplify()
TransferVertexOperator.from_dict({(): 2+0j})
>>> (op - op).simplify()
TransferVertexOperator.from_dict({})
>>> op += op
>>> op.simplify()
TransferVertexOperator.from_dict({(): 2+0j})
>>> op -= op
>>> op.simplify()
TransferVertexOperator.from_dict({})

Moltiplicazione/divisione scalare

>>> op = TransferVertexOperator.one()
>>> (2 * op).simplify()
TransferVertexOperator.from_dict({(): 2+0j})
>>> (op / 2).simplify()
TransferVertexOperator.from_dict({(): 0.5+0j})
>>> op *= 2
>>> op.simplify()
TransferVertexOperator.from_dict({(): 2+0j})
>>> op /= 2
>>> op.simplify()
TransferVertexOperator.from_dict({(): 1+0j})

Composizione dell'operatore

Nota

La composizione degli operatori corrisponde alla moltiplicazione a sinistra: c = a & b corrisponde a C=BAC = B A. In altre parole, la composizione di due operatori restituisce un operatore risultante che esegue “prima a e poi ”. b

>>> op1 = TransferVertexOperator.from_dict({(): 2.0, ((0, 1),): 3.0})
>>> op2 = TransferVertexOperator.from_dict({(): 1.5, ((2, 2),): 4.0})
>>> comp = (op1 & op2).simplify()
>>> print(format(comp))
  3.000000e0 +0.000000e0j * ()
  4.500000e0 +0.000000e0j * (T(0,1))
  8.000000e0 +0.000000e0j * (V(2))
  1.200000e1 +0.000000e0j * (V(2) T(0,1))
>>> op2 &= op1
>>> print(format(op2.simplify()))
  3.000000e0 +0.000000e0j * ()
  4.500000e0 +0.000000e0j * (T(0,1))
  1.200000e1 +0.000000e0j * (T(0,1) V(2))
  8.000000e0 +0.000000e0j * (V(2))
>>> squared = (op1 ** 2).simplify()
>>> print(format(squared))
  4.000000e0 +0.000000e0j * ()
  1.200000e1 +0.000000e0j * (T(0,1))
  9.000000e0 +0.000000e0j * (T(0,1) T(0,1))
Nota

Per comodità, la moltiplicazione a destra viene implementata tramite c = a @ b (il che porta a C=ABC = A B ).

>>> (op1 @ op2).equiv(op2 & op1)
True

Altre operazioni

Oltre ai metodi magici corrispondenti alle operazioni aritmetiche descritte sopra, sono disponibili i seguenti metodi:

Rubrica 1
Rubrica 2
adjoint()Restituisce il coniugato ermitiano (o aggiunto) di questo operatore.
ichop( [atol] )Rimuove i termini il cui coefficiente è inferiore alla soglia specificata.
simplify( [atol] )Restituisce un operatore equivalente ma semplificato.
normal_ordered( [ridurre] )Restituisce un operatore equivalente con termini ordinati normalmente.
relabel_modes(permutazione)Restituisce un nuovo operatore con le modalità rinominate.

Proprietà

Infine, esistono vari metodi per verificare determinate proprietà di un operatore:

Rubrica 1
Rubrica 2
is_hermitian( [atol] )Restituisce se questo operatore è ermitiano.

[ 1 ]

Gandon et al., arXiv:2512.11418.


Attributi

groups

Un vettore facoltativo di indici di gruppo per ciascun termine.

Per ulteriori informazioni, consultare il modulo grouping .


Metodi

adjoint

adjoint()

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

A ogni termine accadono due cose:

  • i coefficienti sono complessi coniugati
  • l'ordine dei generatori all'interno di ciascun termine è invertito

L'inversione è necessaria perché (AB)†=B†A†(AB)^\dagger = B^\dagger A^\dagger. Sebbene i singoli generatori di vertici e di trasferimento siano ermitiani, essi anticommutano quando condividono un indice (vedi la definizione sopra ), quindi il prodotto invertito non è uguale a quello originale e l'ordine non può essere semplicemente omesso.

Si noti che ciò non rende l'operatore autoaggiunto in generale: un operatore con coefficienti complessi differisce dal suo aggiunto (come illustra il doctest riportato di seguito).

>>> from qiskit_fermions.operators import TransferVertexOperator
>>> op = TransferVertexOperator.from_dict({(): -1.0j, ((0, 0), (0, 1)): 1.0})
>>> adj = op.adjoint()
>>> print(format(adj))
 -0.000000e0 +1.000000e0j * ()
  1.000000e0 -0.000000e0j * (T(0,1) V(0))
equiv

equiv(other, atol=1e-08)

Verifica se questo operatore è equivalente a un altro operatore.

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.

Nota

Questo è il confronto matematico che quasi sempre ti serve. Si differenzia dall'operatore == , che verifica l'uguaglianza esatta dei termini memorizzati (i loro coefficienti, indici e limiti interni dei termini) senza tolleranza né semplificazione. Due operatori matematicamente uguali possono quindi risultare diversi nel confronto == se sono memorizzati in modo diverso – ad esempio, un non semplificato a + a rispetto a 2 * a, oppure termini disposti in un ordine diverso. Utilizzare equiv per confrontare gli operatori entro i limiti della tolleranza numerica.

>>> from qiskit_fermions.operators import TransferVertexOperator
>>> op = TransferVertexOperator.from_dict({(): 1e-7})
>>> zero = TransferVertexOperator.zero()
>>> op.equiv(zero)
False
>>> op.equiv(zero, 1e-6)
True
>>> op.equiv(zero, 1e-9)
False

Parametri

  • altro – l’altro operatore con cui effettuare il confronto.
  • atol – la tolleranza assoluta per il confronto. Il valore predefinito è 1e-8.
from_dict

classmethod from_dict(data)

Crea un nuovo operatore a partire da un dizionario.

>>> from qiskit_fermions.operators import TransferVertexOperator
>>> op = TransferVertexOperator.from_dict(
...     {
...         (): 1.0-1.0j,
...         ((0, 0),): 2.0,
...         ((0, 1),): 2.0j,
...     }
... )
>>> print(format(op))
  1.000000e0 -1.000000e0j * ()
  2.000000e0 +0.000000e0j * (V(0))
  0.000000e0 +2.000000e0j * (T(0,1))

Parametri

dati – un dizionario che associa tuple di termini a coefficienti complessi. Ogni chiave è una tupla di coppie (int, int) che indicano gli indici dell’operatore di trasferimento generalizzato, TlrT_{lr} (se l=rl = r, allora ciò corrisponde all’operatore di vertice VlV_l ).

Risultati

Un nuovo operatore.

from_terms

classmethod from_terms(terms)

Crea un nuovo operatore a partire da un iteratore di termini (vedi anche iter_terms()).

>>> from qiskit_fermions.operators import TransferVertexOperator
>>> op = TransferVertexOperator.from_dict({(): 2.0, ((0, 0),): 1.0, ((0, 1),): -1.0j})
>>> op.equiv(TransferVertexOperator.from_terms(op.iter_terms()))
True

Parametri

termini – un iteratore di termini generato da iter_terms().

Risultati

Un nuovo operatore.

from_terms_with_groups

classmethod from_terms_with_groups(terms)

Crea un nuovo operatore a partire da un iteratore di termini con gruppi (vedi anche iter_terms_with_groups()).

>>> from qiskit_fermions.operators import TransferVertexOperator
>>> op = TransferVertexOperator([2.0, 1.0, -1.0j], [0, 0], [0, 1], [0, 0, 1, 2])
>>> op.groups = [0, 1, 1]
>>> reconstructed = TransferVertexOperator.from_terms_with_groups(op.iter_terms_with_groups())
>>> op.equiv(reconstructed) and op.groups == reconstructed.groups
True

Parametri

termini – un iteratore di termini generato da iter_terms_with_groups().

Risultati

Un nuovo operatore.

get_boundaries

get_boundaries()

Restituisce un elenco in sola lettura degli indici che indicano i confini tra i termini dell'operatore.

Nota

Questo metodo restituisce una copia dei dati interni.

Vedi anche

La spiegazione della struttura interna dei dati è disponibile qui.

>>> from qiskit_fermions.operators import TransferVertexOperator
>>> op = TransferVertexOperator.one()
>>> op += TransferVertexOperator.from_dict({((0, 1),): 1.0})
>>> op.get_boundaries()
[0, 0, 1]

Risultati

Un elenco dei limiti previsti dalle condizioni dell'operatore.

get_coeffs

get_coeffs()

Restituisce un elenco in sola lettura dei coefficienti dell'operatore.

Nota

Questo metodo restituisce una copia dei dati interni.

Vedi anche

La spiegazione della struttura interna dei dati è disponibile qui.

>>> from qiskit_fermions.operators import TransferVertexOperator
>>> op = TransferVertexOperator.one()
>>> op += -1j * TransferVertexOperator.one()
>>> op.get_coeffs()
[(1+0j), -1j]

Risultati

Un elenco dei coefficienti dell'operatore.

get_left_indices

get_left_indices()

Restituisce un elenco in sola lettura degli indici a sinistra di tutti i termini dell'operatore di trasferimento generalizzato.

Nota

Questo metodo restituisce una copia dei dati interni.

Vedi anche

La spiegazione della struttura interna dei dati è disponibile qui.

>>> from qiskit_fermions.operators import TransferVertexOperator
>>> op = TransferVertexOperator.from_dict({((0, 0),): 1.0})
>>> op += TransferVertexOperator.from_dict({((0, 1),): 1.0})
>>> op.get_left_indices()
[0, 0]

Risultati

Un elenco degli indici di sinistra di tutti i termini dell'operatore di trasferimento generalizzato.

get_right_indices

get_right_indices()

Restituisce un elenco in sola lettura degli indici a destra di tutti i termini dell'operatore di trasferimento generalizzato.

Nota

Questo metodo restituisce una copia dei dati interni.

Vedi anche

La spiegazione della struttura interna dei dati è disponibile qui.

>>> from qiskit_fermions.operators import TransferVertexOperator
>>> op = TransferVertexOperator.from_dict({((0, 0),): 1.0})
>>> op += TransferVertexOperator.from_dict({((0, 1),): 1.0})
>>> op.get_right_indices()
[0, 1]

Risultati

Un elenco degli indici corretti di tutti i termini dell'operatore di trasferimento generalizzato.

get_support

get_support()

Restituisce l'insieme degli indici di modalità su cui agisce questo operatore.

>>> from qiskit_fermions.operators import TransferVertexOperator
>>> op = TransferVertexOperator.from_dict(
...     {
...         ((0, 1), (3, 4)): 1,
...         ((7, 7),): 1,
...     }
... )
>>> assert op.get_support() == {0, 1, 3, 4, 7}

Risultati

L'insieme degli indici di modalità su cui agisce questo operatore.

has_groups

has_groups()

Indica se questo operatore tiene traccia degli indici di gruppo.

Ciò equivale a (ma è più economico di) verificare op.groups is not None, poiché non copia gli indici dei gruppi dall'operatore per esaminarli.

Nota

Questo restituisce un risultato anche True quando groups è una lista vuota, ovvero lo stato di un operatore raggruppato che non contiene termini.

>>> from qiskit_fermions.operators import TransferVertexOperator
>>> op = TransferVertexOperator(
...     [1.0, 2.0, -1.0],
...     [0, 1, 2, 3],
...     [1, 0, 3, 2],
...     [0, 1, 3, 4],
... )
>>> op.has_groups()
False
>>> op.groups = [0, 1, 0]
>>> op.has_groups()
True

Risultati

Se groups è impostato su questo operatore.

ichop

ichop(atol=1e-08)

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

Questo metodo modifica l'operatore direttamente e restituisce None.

Attenzione

Questo metodo tronca i coefficienti in modo avido! Se l'operatore su cui si agisce può contenere coefficienti distinti per termini duplicati, valuta invece simplify() di chiamare!

>>> from qiskit_fermions.operators import TransferVertexOperator
>>> op = TransferVertexOperator.from_dict({(): 1e-4, ((1, 0),): 1e-6, ((0, 1),): 1e-10})
>>> print(format(op))
  1.000000e-4 +0.000000e0j * ()
 1.000000e-10 +0.000000e0j * (T(0,1))
  1.000000e-6 +0.000000e0j * (T(1,0))
>>> op.ichop()
>>> print(format(op))
  1.000000e-4 +0.000000e0j * ()
  1.000000e-6 +0.000000e0j * (T(1,0))
>>> op.ichop(1e-5)
>>> print(format(op))
  1.000000e-4 +0.000000e0j * ()

Parametri

atol – la tolleranza assoluta per il valore di soglia. Il valore predefinito è 1e-8.

is_hermitian

is_hermitian(atol=1e-08)

Restituisce se questo operatore è ermitiano.

Nota

Questo controllo viene effettuato equiv() utilizzando la differenza normal_ordered() completamente ridotta tra e self i suoi e adjoint() zero().

Nota

Questo controllo è prudente : può restituire un risultato negativo per False un operatore che in realtà è ermitiano. Un risultato True è sempre affidabile.

normal_ordered() contrai ogni coppia di generatori adiacenti che si combinano in un termine più breve, ma due operatori di trasferimento che condividono una singola modalità non lo fanno: come spiegato in quella sede, TjkTjlT_{jk} T_{jl} può essere riscritto solo come un altro prodotto di lunghezza due. Poiché nessuna delle due forme è più canonica dell’altra, tali prodotti vengono lasciati così come sono, e un termine che si annullerebbe solo con il suo aggiunto dopo una riscrittura non viene riconosciuto come zero. EdgeVertexOperator non presenta tale lacuna, poiché in quel caso il prodotto analogo si riduce a un unico operatore di bordo.

Parametri

atol – Il livello di precisione numerica entro il quale i coefficienti sono considerati uguali. Il valore predefinito è 1e-8.

Risultati

Se questo operatore sia ermitiano.

iter_terms

iter_terms()

Un iteratore sui termini dell'operatore.

Avvertenza

La modifica degli elementi dell'iterazione non influisce sui dati sottostanti dell'operatore.

>>> from qiskit_fermions.operators import TransferVertexOperator
>>> op = TransferVertexOperator.from_dict({(): 2.0, ((0, 0),): 1.0, ((0, 1),): -1.0j})
>>> list(sorted(op.iter_terms()))
[([], (2+0j)), ([(0, 0)], (1+0j)), ([(0, 1)], (-0-1j))]
iter_terms_with_groups

iter_terms_with_groups()

Un iteratore sui termini dell'operatore con i relativi indici di gruppo.

Avvertenza

La modifica degli elementi dell'iterazione non influisce sui dati sottostanti dell'operatore.

>>> from qiskit_fermions.operators import TransferVertexOperator
>>> op = TransferVertexOperator([2.0, 1.0, -1.0j], [0, 0], [0, 1], [0, 0, 1, 2])
>>> op.groups = [0, 1, 1]
>>> list(op.iter_terms_with_groups())
[([], (2+0j), 0), ([(0, 0)], (1+0j), 1), ([(0, 1)], (-0-1j), 1)]
normal_ordered

normal_ordered(reduce=True)

Restituisce un operatore equivalente con termini ordinati normalmente.

L'ordine normale di un termine operatore è definito in modo tale che tutti gli operatori di vertice compaiano prima di tutti gli operatori di trasferimento. All’interno di ciascun gruppo, le modalità su cui agisce l’azione sono ordinate lessicograficamente.

Nota

Quando si riorganizza un termine, occorre tenere conto delle relazioni miste di commutazione e anticommutazione. Per le definizioni dettagliate, consultare qui.

Nota

Qui sono disponibili meno contrazioni rispetto a EdgeVertexOperator. Due operatori di bordo che condividono una singola modalità si fondono in uno solo, ma il prodotto di trasferimento analogo non lo fa: scrivendo Tjk=i2γ2jγ2k−1T_{jk} = \frac{i}{2} \gamma_{2j} \gamma_{2k-1}, l'annullamento del Majorana condiviso lascia sempre una coppia (pari, dispari) tratta da due modalità diverse, che non costituisce un singolo generatore. Solo V(j) V(j), e T(j,k) T(j,k) contratto T(j,k) T(k,j) .

>>> from qiskit_fermions.operators import TransferVertexOperator
>>> op = TransferVertexOperator.from_dict({((0, 1), (1, 0), (1, 2), (0, 0), (2, 2)): 1})
>>> print(format(op.normal_ordered(reduce=False).simplify()))
 -1.000000e0 -0.000000e0j * (V(0) V(2) T(0,1) T(1,0) T(1,2))
>>> print(format(op.normal_ordered().simplify()))
 2.500000e-1 +0.000000e0j * (V(1) V(2) T(1,2))

Parametri

ridurre – se contrarre i generatori adiacenti in modo che si combinino in uno scalare o in una coppia di operatori di vertice. Vedi l'esempio sopra. Il valore predefinito è True.

Risultati

Un operatore equivalente ma con ordinamento normale.

num_groups

num_groups()

Restituisce il numero di gruppi.

Se è groups None, questa funzione restituisce anch'essa None. In caso contrario, restituirà il numero di gruppi, definito come l'indice del gruppo più grande presente più 1 (che potrà quindi essere utilizzato come indice per il gruppo successivo).

>>> from qiskit_fermions.operators import TransferVertexOperator
>>> op = TransferVertexOperator(
...     [1.0, 2.0, -1.0],
...     [0, 1, 2, 3],
...     [1, 0, 3, 2],
...     [0, 1, 3, 4],
... )
>>> op.groups = [0, 1, 0]
>>> op.num_groups()
2

Risultati

L'indice di gruppo più importante è in groups rialzo di 1.

one

classmethod one()

Crea l'operatore di identità moltiplicativa.

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

>>> from qiskit_fermions.operators import TransferVertexOperator
>>> op = TransferVertexOperator.from_dict({(): 2.0})
>>> one = TransferVertexOperator.one()
>>> op & one == op
True
relabel_modes

relabel_modes(permutation)

Restituisce un nuovo operatore con le modalità rinominate.

>>> from qiskit_fermions.operators import TransferVertexOperator
>>> op = TransferVertexOperator.from_dict({
...     ((0, 1), (2, 3)): 1,
...     ((1, 2), (3, 0)): 1,
... })
>>> permutation = [4, 2, 5, 3]
>>> relabeled = op.relabel_modes(permutation)
>>> print(format(relabeled))
  1.000000e0 +0.000000e0j * (T(2,5) T(3,4))
  1.000000e0 +0.000000e0j * (T(4,2) T(5,3))

Parametri

permutazione – l'elenco delle permutazioni degli indici. La modalità viene i rinominata in permutation[i], pertanto l'elenco non deve contenere voci duplicate e deve essere sufficientemente lungo da indicizzare tutte le modalità su cui agisce l'operatore (la sua lunghezza deve superare l'indice di modalità più alto dell'operatore).

Risultati

Un nuovo operatore con le modalità rinominate.

Aumenti

ValueError – se contiene permutation voci duplicate o è troppo breve per ridenominare una modalità su cui agisce l'operatore.

simplify

simplify(atol=1e-08)

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 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. Si veda l'esempio riportato di seguito, che illustra come ichop() sia possibile troncare termini la cui somma porta a un coefficiente di grandezza totale che non dovrebbe essere troncato:

>>> from qiskit_fermions.operators import TransferVertexOperator
>>> coeffs = [1e-5] * int(1e5)
>>> boundaries = [0] + [0] * int(1e5)
>>> op = TransferVertexOperator(coeffs, [], [], boundaries)
>>> canon = op.simplify(1e-4)
>>> assert canon.equiv(op.one(), 1e-6)
>>> op.ichop(1e-4)
>>> assert op.equiv(op.zero(), 1e-6)

Parametri

atol – la tolleranza assoluta per il valore di soglia. Il valore predefinito è 1e-8.

Risultati

Un operatore equivalente ma semplificato.

split_out_groups

split_out_groups(group_indices=None)

Suddivide questo operatore in un elenco facoltativo di nuovi operatori in base a groups.

Se è groups None, questa funzione restituisce anch'essa None. Altrimenti, se group_indices è None (impostazione predefinita), restituisce una lista contenente un nuovo operatore per ogni indice di gruppo in groups, in ordine di indice. Se group_indices è specificato, vengono costruiti solo gli indici richiesti, nell'ordine indicato: ciò evita il costo legato alla costruzione di operatori per gruppi che non vengono mai utilizzati, il che è particolarmente vantaggioso quando è necessario solo un numero ridotto di gruppi rispetto a un totale molto più ampio, ad esempio quando si effettua un sottocampionamento dei gruppi per una formula di prodotto randomizzata. Un indice duplicato in group_indices viene restituito una volta per ogni occorrenza.

>>> from qiskit_fermions.operators import TransferVertexOperator
>>> op = TransferVertexOperator(
...     [1.0, 2.0, -1.0],
...     [0, 1, 2, 3],
...     [1, 0, 3, 2],
...     [0, 1, 3, 4],
... )
>>> print(op.split_out_groups())
None
>>> op.groups = [0, 1, 0]
>>> groups = op.split_out_groups()
>>> for g in groups:
...     print(list(sorted(g.iter_terms())))
[([(0, 1)], (1+0j)), ([(3, 2)], (-1+0j))]
[([(1, 0), (2, 3)], (2+0j))]
>>> groups = op.split_out_groups(group_indices=[1])
>>> for g in groups:
...     print(list(sorted(g.iter_terms())))
[([(1, 0), (2, 3)], (2+0j))]

Parametri

group_indices – gli indici dei gruppi per i quali creare gli operatori, nell'ordine di output desiderato. Se non specificato, vengono creati tutti i gruppi, in ordine di indice.

Risultati

Un vettore facoltativo contenente un nuovo operatore per ciascun indice di gruppo richiesto.

zero

classmethod zero()

Costruisce l'operatore di identità additiva.

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

>>> from qiskit_fermions.operators import TransferVertexOperator
>>> op = TransferVertexOperator.from_dict({(): 2.0})
>>> zero = TransferVertexOperator.zero()
>>> op + zero == op
True

Metodi del protocollo

_anti_commutator_

static _anti_commutator_(op_a, op_b)

_commutator_

static _commutator_(op_a, op_b)

_double_commutator_

static _double_commutator_(op_a, op_b, op_c, sign)

_fermion_operator_

_fermion_operator_()

Converte questo operatore in un FermionOperator.

Questo implementa il protocollo SupportsFermionOperator delegando a transfer_vertex_to_fermion().

_majorana_operator_

_majorana_operator_()

Converte questo operatore in un MajoranaOperator.

Questo implementa il protocollo SupportsMajoranaOperator delegando a transfer_vertex_to_majorana().

Questa pagina è stata utile?
Segnala un bug, un errore di battitura o richiedi contenuti su GitHub.