# netket.experimental.operator.FermionOperator2nd#

class netket.experimental.operator.FermionOperator2nd[source]#

Bases: FermionOperator2ndBase

A fermionic operator in $$2^{nd}$$ quantization, using Numba for indexing.

Warning

This class is not a Pytree, so it cannot be used inside of jax-transformed functions like jax.grad or jax.jit.

The standard usage is to index into the operator from outside the jax function transformation and pass the results to the jax-transformed functions.

To use this operator inside of a jax function transformation, convert it to a jax operator (class:netket.experimental.operator.FermionOperator2ndJax) by using netket.experimental.operator.FermionOperator2nd.to_jax_operator().

When using native (experimental) sharding, or when working with GPUs, we reccomend using the Jax implementations of the operators for potentially better performance.

Inheritance
__init__(hilbert, terms=None, weights=None, constant=0, cutoff=1e-10, dtype=None)#

Constructs a fermion operator given the single terms (set of creation/annihilation operators) in second quantization formalism.

This class can be initialized in the following form: FermionOperator2nd(hilbert, terms, weights â€¦). The term contains pairs of (idx, dagger), where idx âˆˆ range(hilbert.size) (it identifies an orbital) and dagger is a True/False flag determining if the operator is a creation or destruction operator. A term of the form $$\hat{a}_1^\dagger \hat{a}_2$$ would take the form ((1,1), (2,0)), where (1,1) represents $$\hat{a}_1^\dagger$$ and (2,0) represents $$\hat{a}_2$$. To split up per spin, use the creation and annihilation operators to build the operator.

Parameters:
• hilbert (AbstractHilbert) â€“ hilbert of the resulting FermionOperator2nd object

• terms () â€“ single term operators (see example below)

• weights () â€“ corresponding coefficients of the single term operators (defaults to a list of 1)

• constant (Number) â€“ constant contribution, corresponding to the identity operator * constant (default = 0)

• cutoff (float) â€“ threshold for the weights, if the absolute value of a weight is below the cutoff, itâ€™s discarded.

• dtype () â€“ The datatype to use for the matrix elements. Defaults to double precision if available.

Returns:

A FermionOperator2nd object.

Example

Constructs the fermionic hamiltonian in $$2^{nd}$$ quantization $$(0.5-0.5j)*(a_0^\dagger a_1) + (0.5+0.5j)*(a_2^\dagger a_1)$$.

>>> import netket.experimental as nkx
>>> terms, weights = (((0,1),(1,0)),((2,1),(1,0))), (0.5-0.5j,0.5+0.5j)
>>> hi = nkx.hilbert.SpinOrbitalFermions(3)
>>> op = nkx.operator.FermionOperator2nd(hi, terms, weights)
>>> op
FermionOperator2nd(hilbert=SpinOrbitalFermions(n_orbitals=3), n_operators=2, dtype=complex128)
>>> terms = ("0^ 1", "2^ 1")
>>> op = nkx.operator.FermionOperator2nd(hi, terms, weights)
>>> op
FermionOperator2nd(hilbert=SpinOrbitalFermions(n_orbitals=3), n_operators=2, dtype=complex128)
>>> op.hilbert
SpinOrbitalFermions(n_orbitals=3)
>>> op.hilbert.size
3

Attributes
H#

Returns the Conjugate-Transposed operator

T#

Returns the transposed operator

cutoff#

Threshold for the weights, if the absolute value of a weight is below the cutoff, itâ€™s discarded.

dtype#

The dtype of the operatorâ€™s matrix elements âŸ¨Ïƒ|Ã”|Ïƒâ€™âŸ©.

hilbert#

The hilbert space associated to this observable.

is_hermitian#

Returns true if this operator is hermitian.

max_conn_size#

The maximum number of non zero âŸ¨x|O|xâ€™âŸ© for every x.

operators#

Returns a dictionary with (term, weight) key-value pairs, with terms in tuple notation.

The constant diagonal shift of the operator is associated with a term represented as an empty tuple.

terms#

Returns the list of all terms in the tuple notation.

weights#

Returns the list of the weights correspoding to the operator terms.

Methods
__call__(v)#

Call self as a function.

Return type:

ndarray

Parameters:

v (ndarray)

apply(v)#
Return type:

ndarray

Parameters:

v (ndarray)

collect()#

Returns a guaranteed concrete instance of an operator.

As some operations on operators return lazy wrappers (such as transpose, hermitian conjugateâ€¦), this is used to obtain a guaranteed non-lazy operator.

Return type:

AbstractOperator

conj(*, concrete=False)#
Return type:

AbstractOperator

conjugate(*, concrete=False)#

Returns the complex conjugate of this operator.

This implementation always returns the concrete version of the operator.

copy(*, dtype=None, cutoff=None)#

Creates a deep copy of this operator, potentially changing the dtype of the operator and internal arrays.

Parameters:
• dtype () â€“ Optional new dtype. Must be compatible with the current dtype.

• cutoff â€“ Optional new cutoff.

Returns:

An identical operator that does not reference the internal arrays of the original one.

classmethod from_openfermion(hilbert, of_fermion_operator=None, *, n_orbitals=None, convert_spin_blocks=False, cutoff=1e-10, dtype=None)#

Converts an openfermion FermionOperator into a netket FermionOperator2nd.

The hilbert first argument can be dropped, see __init__ for details and default value. Warning: convention of openfermion.hamiltonians is different from ours: instead of strong spin components as subsequent hilbert state outputs (i.e. the 1/2 spin components of spin-orbit i are stored in locations (2*i, 2*i+1)), we concatenate blocks of definite spin (i.e. locations (i, n_orbitals+i)).

Parameters:
• hilbert (AbstractHilbert) â€“ (optional) hilbert of the resulting FermionOperator2nd object

• of_fermion_operator (openfermion.ops.FermionOperator) â€“ FermionOperator object . More information about those objects can be found in OpenFermionâ€™s documentation

• n_orbitals () â€“ (optional) total number of orbitals in the system, default None means inferring it from the FermionOperator2nd. Argument is ignored when hilbert is given.

• convert_spin_blocks (bool) â€“ whether or not we need to convert the FermionOperator to our convention. Only works if hilbert is provided and if it has spin != 0

• cutoff (float) â€“ threshold for the weights, if the absolute value of a weight is below the cutoff, itâ€™s discarded.

• dtype (Any)

Return type:

FermionOperator2ndBase

get_conn(x)#

Finds the connected elements of the Operator. Starting from a given quantum number x, it finds all other quantum numbers xâ€™ such that the matrix element $$O(x,x')$$ is different from zero. In general there will be several different connected states xâ€™ satisfying this condition, and they are denoted here $$x'(k)$$, for $$k=0,1...N_{\mathrm{connected}}$$.

Parameters:

x (ndarray) â€“ An array of shape (hilbert.size, ) containing the quantum numbers x.

Returns:

The connected states xâ€™ of shape (N_connected,hilbert.size) array: An array containing the matrix elements $$O(x,x')$$ associated to each xâ€™.

Return type:

matrix

Raises:

ValueError â€“ If the given quantum number is not compatible with the hilbert space.

Finds the connected elements of the Operator.

Starting from a given quantum number x, it finds all other quantum numbers xâ€™ such that the matrix element $$O(x,x')$$ is different from zero. In general there will be several different connected states xâ€™ satisfying this condition, and they are denoted here $$x'(k)$$, for $$k=0,1...N_{\mathrm{connected}}$$.

This is a batched version, where x is a matrix of shape (batch_size,hilbert.size).

Parameters:
• x â€“ A matrix of shape (batch_size,hilbert.size) containing the batch of quantum numbers x.

• sections â€“ An array of size (batch_size) useful to unflatten the output of this function. See numpy.split for the meaning of sections.

Returns:

The connected states xâ€™, flattened together in a single matrix. array: An array containing the matrix elements $$O(x,x')$$ associated to each xâ€™.

Return type:

matrix

Finds the connected elements of the Operator.

Starting from a batch of quantum numbers $$x={x_1, ... x_n}$$ of size $$B \times M$$ where $$B$$ size of the batch and $$M$$ size of the hilbert space, finds all states $$y_i^1, ..., y_i^K$$ connected to every $$x_i$$.

Returns a matrix of size $$B \times K_{max} \times M$$ where $$K_{max}$$ is the maximum number of connections for every $$y_i$$.

Parameters:

x (ndarray) â€“ A N-tensor of shape $$(...,hilbert.size)$$ containing the batch/batches of quantum numbers $$x$$.

Returns:

The connected states xâ€™, in a N+1-tensor and an N-tensor containing the matrix elements $$O(x,x')$$ associated to each xâ€™ for every batch.

Return type:

(x_primes, mels)

n_conn(x, out=None)#

Return the number of states connected to x.

Parameters:
• x (matrix) â€“ A matrix of shape (batch_size,hilbert.size) containing the batch of quantum numbers x.

• out (array) â€“ If None an output array is allocated.

Returns:

The number of connected states xâ€™ for each x[i].

Return type:

array

operator_string()#

Return a readable string describing all the operator terms

Return type:

str

reduce(order=True, inplace=True, cutoff=None)#

Prunes the operator by removing all terms with zero weights, grouping, and normal ordering (inplace).

Parameters:
to_dense()#

Returns the dense matrix representation of the operator. Note that, in general, the size of the matrix is exponential in the number of quantum numbers, and this operation should thus only be performed for low-dimensional Hilbert spaces or sufficiently sparse operators.

This method requires an indexable Hilbert space.

Return type:

ndarray

Returns:

The dense matrix representation of the operator as a Numpy array.

to_jax_operator()[source]#

Returns the jax version of this operator, which is an instance of netket.experimental.operator.FermionOperator2ndJax.

Return type:

FermionOperator2ndJax

to_linear_operator()#
to_normal_order()#

Reoder the operators to normal order. Normal ordering corresponds to placing creating operators on the left and annihilation on the right. Then, it places the highest index on the left and lowest index on the right In this ordering, we make sure to account for the anti-commutation of operators. Normal ordering documentation

to_pair_order()#

Reoder the operators to pair order. Pair ordering corresponds to placing first the highest indices on the right, and then making sure the creation operators are on the left and annihilation on the right. In this ordering, we make sure to account for the anti-commutation of operators.

to_qobj()#

Convert the operator to a qutipâ€™s Qobj.

Returns:

A qutip.Qobj object.

to_sparse()#

Returns the sparse matrix representation of the operator. Note that, in general, the size of the matrix is exponential in the number of quantum numbers, and this operation should thus only be performed for low-dimensional Hilbert spaces or sufficiently sparse operators.

This method requires an indexable Hilbert space.

Return type:

csr_matrix

Returns:

The sparse matrix representation of the operator.

transpose(*, concrete=False)#

Returns the transpose of this operator.

For real operators, this is equivalent to complex conjugation. This implementation always returns the concrete version of the operator.