quspin.basis.spinful_fermion_basis_general

class quspin.basis.spinful_fermion_basis_general(N, Nf=None, nf=None, Ns_block_est=None, simple_symm=True, make_basis=True, block_order=None, double_occupancy=True, **blocks)[source]

Bases: spinless_fermion_basis_general

Constructs basis for spinful fermion operators for USER-DEFINED symmetries.

Any unitary symmetry transformation \(Q\) of periodicity \(m_Q\) (\(Q^{m_Q}=1\)) has eigenvalues \(\exp(-2\pi i q/m_Q)\), labelled by an ingeter \(q\in\{0,1,\dots,m_Q-1\}\). These integers \(q\) are used to define the symmetry blocks.

For instance, if \(Q=P\) is parity (reflection), then \(q=0,1\). If \(Q=T\) is translation by one lattice site, then \(q\) labels the mometum blocks in the same fashion as for the …_basis_1d classes.

User-defined symmetries with the spinful_fermion_basis_general class can be programmed in two equivalent ways: simple and advanced.
  • simple symmetry definition (see optional argument simple_symm) uses the pipe symbol, “|”, in the operator string (see site-coupling lists in example below) to distinguish between the spin-up and spin-down species. Suppose we have a system of L sites. In the simple case, the lattice sites are enumerated \(s=(s_0,s_1,\dots,s_{L-1})\) for both spin-up and spin-down. There are two types of operations one can perform on the sites:
    • exchange the labels of two sites: \(s_i \leftrightarrow s_j\) (e.g., translation, parity)

    • invert the fermion spin on a given site: \(s_i\leftrightarrow -(s_j+1)\) (e.g., fermion spin inversion)

  • advanced symmetry definition (see optional argument simple_symm) does NOT use any pipe symbol in the operator string to distinguish between the spin-up and spin-down species. In the advanced case, the sites are enumerated \(s=(s_0,s_1,\dots,s_{L-1}; s_{L},s_{L+1},\dots,s_{2L-1})\), where the first L sites label spin-up, and the last L sites – spin-down. There are two types of operations one can perform on the sites:
    • exchange the labels of two sites: \(s_i \leftrightarrow s_j\) (e.g., translation, parity, fermion spin inversion)

    • invert the fermion population on a given site with appropriate sign flip (see “z” operator string) \(c_j^\dagger\to (-1)^j c_j\): \(s_i\leftrightarrow -(s_j+1)\) (e.g., particle-hole symmetry)

These two operations already comprise a variety of symmetries, including translation, parity (reflection), fermion-spin inversion and particle-hole like symmetries. For specific examples, see below.

The supported operator strings for spinful_fermion_basis_general are:

\[\begin{array}{cccc} \texttt{basis}/\texttt{opstr} & \texttt{"I"} & \texttt{"+"} & \texttt{"-"} & \texttt{"n"} & \texttt{"z"} & \texttt{"x"} & \texttt{"y"} \newline \texttt{spinful_fermion_basis_general}& \hat{1} & \hat c^\dagger & \hat c & \hat c^\dagger c & \hat c^\dagger\hat c - \frac{1}{2} & \hat c + \hat c^\dagger & -i\left( \hat c - \hat c^\dagger\right) \newline \end{array}\]

Notes

  • The definition of the operation \(s_i\leftrightarrow -(s_j+1)\) differs for the simple and advanced cases.

  • For particle-hole symmetry, please use exclusively the operator string “z” (see table), otherwise the automatic symmetry check will raise an error when set to check_symm=True.

  • QuSpin raises a warning to alert the reader when non-commuting symmetries are passed. In such cases, we recommend the user to manually check the combined usage of symmetries by, e.g., comparing the eigenvalues.

  • The fermion operator strings “x” and “y” correspond to real fermions, i.e. Majorana operators (note the sign difference between “y” and the \(\sigma^y\) Pauli matrix, which is convention).

Examples

The code snippets below show how to construct the two-dimensional Fermi-Hubbard model with onsite interactions.

\[H = -J \sum_{\langle ij\rangle,\sigma} c^\dagger_{i\sigma}c_{j\sigma} + \mathrm{h.c.} - \mu\sum_{j,\sigma} n_{j\sigma} + U\sum_j n_{j\uparrow} n_{j\downarrow}\]

The first code snippet demonstrates how to pass simple user-defined symmetries to the spinful_fermion_basis_general constructor. In particular, we do translation invariance and fermion spin inversion.

 1from quspin.basis import spinful_fermion_basis_general  # spin basis constructor
 2import numpy as np  # general math functions
 3
 4#
 5###### define model parameters ######
 6Lx, Ly = 4, 4  # linear dimension of spin 1 2d lattice
 7N_2d = Lx * Ly  # number of sites for spin 1
 8#
 9J = 1.0  # hopping matrix element
10U = 2.0  # onsite interaction
11mu = 0.5  # chemical potential
12#
13###### setting up user-defined BASIC symmetry transformations for 2d lattice ######
14s = np.arange(N_2d)  # sites [0,1,2,...,N_2d-1] in simple notation
15x = s % Lx  # x positions for sites
16y = s // Lx  # y positions for sites
17T_x = (x + 1) % Lx + Lx * y  # translation along x-direction
18T_y = x + Lx * ((y + 1) % Ly)  # translation along y-direction
19S = -(s + 1)  # fermion spin inversion in the simple case
20#
21###### setting up bases ######
22basis_2d = spinful_fermion_basis_general(
23    N_2d, Nf=(2, 2), kxblock=(T_x, 0), kyblock=(T_y, 0), sblock=(S, 0)
24)
25#
26###### setting up hamiltonian ######
27# setting up site-coupling lists for simple case
28hopping_left = [[-J, i, T_x[i]] for i in range(N_2d)] + [
29    [-J, i, T_y[i]] for i in range(N_2d)
30]
31hopping_right = [[+J, i, T_x[i]] for i in range(N_2d)] + [
32    [+J, i, T_y[i]] for i in range(N_2d)
33]
34potential = [[-mu, i] for i in range(N_2d)]
35interaction = [[U, i, i] for i in range(N_2d)]
36#
37static = [
38    ["+-|", hopping_left],  # spin up hops to left
39    ["-+|", hopping_right],  # spin up hops to right
40    ["|+-", hopping_left],  # spin down hopes to left
41    ["|-+", hopping_right],  # spin up hops to right
42    ["n|", potential],  # onsite potenial, spin up
43    ["|n", potential],  # onsite potential, spin down
44    ["n|n", interaction],
45]  # spin up-spin down interaction
46# build hamiltonian
47H = hamiltonian(static, [], basis=basis_2d, dtype=np.float64)
48# diagonalise H
49E = H.eigvalsh()

The second code snippet demonstrates how to pass advanced user-defined symmetries to the spinful_fermion_basis_general constructor. Like above, we do translation invariance and fermion spin inversion.

 1from quspin.basis import spinful_fermion_basis_general  # spin basis constructor
 2import numpy as np  # general math functions
 3
 4#
 5###### define model parameters ######
 6Lx, Ly = 4, 4  # linear dimension of spin 1 2d lattice
 7N_2d = Lx * Ly  # number of sites for spin 1
 8#
 9J = 1.0  # hopping matrix element
10U = 2.0  # onsite interaction
11mu = 0.5  # chemical potential
12#
13###### setting up user-defined BASIC symmetry transformations for 2d lattice ######
14# we build the advanced symmetry operations operations by concatenating operations for a single spin species
15x = np.arange(N_2d) % Lx  # x positions for sites for one spin species
16y = np.arange(N_2d) // Lx  # y positions for sites for one spin species
17t_x = (x + 1) % Lx + Lx * y  # translation along x-direction for one spin species
18t_y = x + Lx * ((y + 1) % Ly)  # translation along y-direction for one spin species
19# create the spin-up spin-down combined transformations
20s = np.arange(2 * N_2d)  # sites [0,1,2,...,N_2d-1,...,2*N_2d-1] in advanced notation
21T_x = np.hstack(
22    (t_x, t_x + N_2d)
23)  # translation along x-direction for both spin species
24T_y = np.hstack(
25    (t_y, t_y + N_2d)
26)  # translation along y-direction for both spin species
27S = np.roll(s, N_2d)  # fermion spin inversion in the advanced case
28#
29###### setting up bases ###### (note optional argument simple_symm=False)
30basis_2d = spinful_fermion_basis_general(
31    N_2d,
32    simple_symm=False,
33    Nf=(2, 2),
34    kxblock=(T_x, 0),
35    kyblock=(T_y, 0),
36    sblock=(S, 0),
37)
38#
39###### setting up hamiltonian ######
40# setting up site-coupling lists for advanced case
41hopping_left = [[-J, i, T_x[i]] for i in range(2 * N_2d)] + [
42    [-J, i, T_y[i]] for i in range(2 * N_2d)
43]
44hopping_right = [[+J, i, T_x[i]] for i in range(2 * N_2d)] + [
45    [+J, i, T_y[i]] for i in range(2 * N_2d)
46]
47potential = [[-mu, i] for i in range(2 * N_2d)]
48interaction = [[U, i, i + N_2d] for i in range(N_2d)]
49#
50static = [
51    ["+-", hopping_left],  # spin-up and spin-down hop to left
52    ["-+", hopping_right],  # spin-up and spin-down hop to right
53    ["n", potential],  # onsite potential for spin-up and spin-down
54    ["nn", interaction],
55]  # spin-up spin-down interaction
56# build hamiltonian
57H = hamiltonian(static, [], basis=basis_2d, dtype=np.float64)
58# diagonalise H
59E = H.eigvalsh()

The third code snippet demonstrates how to pass advanced user-defined particle-hole symemtry to the spinful_fermion_basis_general constructor with translational invariance.

 1from quspin.basis import spinful_fermion_basis_general  # spin basis constructor
 2import numpy as np  # general math functions
 3
 4#
 5###### define model parameters ######
 6Lx, Ly = 4, 3  # linear dimension of spin 1 2d lattice
 7N_2d = Lx * Ly  # number of sites for spin 1
 8#
 9J = 1.0  # hopping matrix element
10U = 2.0  # onsite interaction
11#
12###### setting up user-defined BASIC symmetry transformations for 2d lattice ######
13# we build the advanced symmetry operations operations by concatenating operations for a single spin species
14x = np.arange(N_2d) % Lx  # x positions for sites for one spin species
15y = np.arange(N_2d) // Lx  # y positions for sites for one spin species
16t_x = (x + 1) % Lx + Lx * y  # translation along x-direction for one spin species
17t_y = x + Lx * ((y + 1) % Ly)  # translation along y-direction for one spin species
18# create the spin-up spin-down combined transformations
19s = np.arange(2 * N_2d)  # sites [0,1,2,...,N_2d-1,...,2*N_2d-1] in advanced notation
20T_x = np.hstack(
21    (t_x, t_x + N_2d)
22)  # translation along x-direction for both spin species
23T_y = np.hstack(
24    (t_y, t_y + N_2d)
25)  # translation along y-direction for both spin species
26PH = -(s + 1)  # particle-hole in the advanced case
27#
28###### setting up bases ###### (note optional argument simple_symm=False)
29# basis_2d=spinful_fermion_basis_general(N_2d,simple_symm=False,Nf=(2,2),kxblock=(T_x,0),kyblock=(T_y,0))
30basis_2d = spinful_fermion_basis_general(
31    N_2d,
32    simple_symm=False,
33    Nf=(6, 6),
34    kxblock=(T_x, 0),
35    kyblock=(T_y, 0),
36    phblock=(PH, 0),
37)
38#
39###### setting up hamiltonian ######
40# setting up site-coupling lists for advanced case
41hopping_left = [[-J, i, T_x[i]] for i in range(2 * N_2d)] + [
42    [-J, i, T_y[i]] for i in range(2 * N_2d)
43]
44hopping_right = [[+J, i, T_x[i]] for i in range(2 * N_2d)] + [
45    [+J, i, T_y[i]] for i in range(2 * N_2d)
46]
47interaction = [[U, i, i + N_2d] for i in range(N_2d)]
48#
49static = [
50    ["+-", hopping_left],  # spin-up and spin-down hop to left
51    ["-+", hopping_right],  # spin-up and spin-down hop to right
52    ["zz", interaction],
53]  # spin-up spin-down interaction
54# build hamiltonian
55H = hamiltonian(static, [], basis=basis_2d, dtype=np.float64)
56# diagonalise H
57E = H.eigsh(k=10, which="SA", return_eigenvectors=False)
58print(E)
__init__(N, Nf=None, nf=None, Ns_block_est=None, simple_symm=True, make_basis=True, block_order=None, double_occupancy=True, **blocks)[source]

Intializes the spinful_fermion_basis_general object (basis for fermionic operators).

Parameters:
L: int

Length of chain/number of sites.

Nf: tuple(int), optional

Number of fermions in chain. Can be tupe of integers or list of tuples of integers [(Nup,Ndown),…] to specify one or more particle sectors.

nf: float, optional

Density of fermions in chain (fermions per site).

Ns_block_est: int, optional

Overwrites the internal estimate of the size of the reduced Hilbert space for the given symmetries. This can be used to help conserve memory if the exact size of the H-space is known ahead of time.

simple_symm: bool, optional

Flags whidh toggles the setting for the types of mappings and operator strings the basis will use. See this tutorial for more details.

make_basis: bool, optional

Boolean to control whether to make the basis. Allows the use to use some functionality of the basis constructor without constructing the entire basis.

double_occupancy: bool, optional

Boolean to toggle the presence of doubly-occupied sites (both a spin up and a spin-down fermion present on the same lattice site) in the basis. Default is double_occupancy=True, for which doubly-occupied states are present.

block_order: list of strings, optional

A list of strings containing the names of the symmetry blocks which specifies the order in which the symmetries will be applied to the state when calculating the basis. The first element in the list is applied to the state first followed by the second element, etc. If the list is not specificed the ordering is such that the symmetry with the largest cycle is the first, followed by the second largest, etc.

**blocks: optional

keyword arguments which pass the symmetry generator arrays. For instance:

>>> basis(...,kxblock=(Q,q),...)

The keys of the symmetry sector, e.g. kxblock, can be chosen arbitrarily by the user. The values are tuples where the first entry contains the symmetry transformation \(Q\) acting on the lattice sites (see class example), and the second entry is an integer \(q\) to label the symmetry sector.

Methods

Op(opstr, indx, J, dtype)

Constructs operator from a site-coupling list and an operator string in a lattice basis.

Op_bra_ket(opstr, indx, J, dtype, ket_states)

Finds bra states which connect given ket states by operator from a site-coupling list and an operator string.

Op_shift_sector(other_basis, op_list, v_in)

Applies symmetry non-conserving operator to state in symmetry-reduced basis.

__init__(N[, Nf, nf, Ns_block_est, ...])

Intializes the spinful_fermion_basis_general object (basis for fermionic operators).

check_hermitian(static, dynamic)

Checks operator string lists for hermiticity of the combined operator.

check_pcon(static, dynamic)

Checks operator string lists for particle number (magnetisation) conservartion of the combined operator.

check_symm(static, dynamic)

Checks operator string lists for the required symmetries of the combined operator.

ent_entropy(state[, sub_sys_A, density, ...])

Calculates entanglement entropy of subsystem A and the corresponding reduced density matrix

expanded_form([static, dynamic])

Splits up operator strings containing "x" and "y" into operator combinations of "+" and "-".

get_amp(states[, out, amps, mode])

Computes the rescale factor of state amplitudes between the symmetry-reduced and full basis.

get_proj(dtype[, pcon])

Calculates transformation/projector from symmetry-reduced basis to full (symmetry-free) basis.

get_vec(v0[, sparse, pcon])

DEPRECATED (cf project_from).

index(up_state, down_state)

Finds the index of user-defined Fock state in spinful fermion basis.

inplace_Op(v_in, op_list, dtype[, ...])

Calculates the action of an operator on a state.

int_to_state(state[, bracket_notation])

Finds string representation of a state defined in integer representation.

make([Ns_block_est, N_p])

Creates the entire basis by calling the basis constructor.

make_basis_blocks([N_p])

Creates/modifies the bounds for representatives based on prefix tages.

normalization(states[, out])

Computes normalization of basis states.

partial_trace(state[, sub_sys_A, ...])

Calculates reduced density matrix, through a partial trace of a quantum state in a lattice basis.

project_from(v0[, sparse, pcon])

Transforms state from symmetry-reduced basis to full (symmetry-free) basis.

project_to(v0[, sparse, pcon])

Transforms state from full (symmetry-free) basis to symmetry-reduced basis.

representative(states[, out, return_g, ...])

Maps states to their representatives under the basis symmetries.

state_to_int(state)

Finds integer representation of a state defined in string format.

Attributes

N

number of sites the basis is constructed with.

Ns

number of states in the Hilbert space.

blocks

contains the quantum numbers (blocks) for the symmetry sectors.

description

information about basis object.

dtype

data type of basis state integers.

noncommuting_bits

list of bits that represent sites that do not commute along with the phase required from commuting sites

operators

set of available operator strings.

sps

number of states per site (ie, the on-site Hilbert space dimension).

states

basis states stored in their integer representation.

property N

number of sites the basis is constructed with.

Type:

int

property Ns

number of states in the Hilbert space.

Type:

int

Op(opstr, indx, J, dtype)

Constructs operator from a site-coupling list and an operator string in a lattice basis.

Parameters:
opstrstr

Operator string in the lattice basis format. For instance:

>>> opstr = "zz"
indxlist(int)

List of integers to designate the sites the lattice basis operator is defined on. For instance:

>>> indx = [2,3]
Jscalar

Coupling strength.

dtype‘type’

Data type (e.g. numpy.float64) to construct the operator with.

Returns:
tuple
(ME,row,col), where
  • numpy.ndarray(scalar): ME: matrix elements of type dtype.

  • numpy.ndarray(int): row: row indices of matrix representing the operator in the lattice basis,

    such that row[i] is the row index of ME[i].

  • numpy.ndarray(int): col: column index of matrix representing the operator in the lattice basis,

    such that col[i] is the column index of ME[i].

Examples

>>> J = 1.41
>>> indx = [2,3]
>>> opstr = "zz"
>>> dtype = np.float64
>>> ME, row, col = Op(opstr,indx,J,dtype)
Op_bra_ket(opstr, indx, J, dtype, ket_states, reduce_output=True)[source]

Finds bra states which connect given ket states by operator from a site-coupling list and an operator string.

Given a set of ket states \(|s\rangle\), the function returns the bra states \(\langle s'|\) which connect to them through an operator, together with the corresponding matrix elements.

Parameters:
opstrstr

Operator string in the lattice basis format. For instance:

>>> opstr = "zz"
indxlist(int)

List of integers to designate the sites the lattice basis operator is defined on. For instance:

>>> indx = [2,3]
Jscalar

Coupling strength.

dtype‘type’

Data type (e.g. numpy.float64) to construct the matrix elements with.

ket_statesnumpy.ndarray(int)

Ket states in integer representation. Must be of same data type as basis.

reduce_output: bool, optional

If set to False, the returned arrays have the same size as ket_states; If set to True zeros are purged.

Returns:
tuple
(ME,bra,ket), where
  • numpy.ndarray(scalar): ME: matrix elements of type dtype, which connects the ket and bra states.

  • numpy.ndarray(int): bra: bra states, obtained by applying the matrix representing the operator in the lattice basis,

    to the ket states, such that bra[i] corresponds to ME[i] and connects to ket[i].

  • numpy.ndarray(int): ket: ket states, such that ket[i] corresponds to ME[i] and connects to bra[i].

Notes

  • Similar to Op but instead of returning the matrix indices (row,col), it returns the states (bra,ket) in integer representation.

  • Does NOT require the full basis (see basis optional argument make_basis).

  • If a state from ket_states does not have a non-zero matrix element, it is removed from the returned list. See otional argument reduce_output.

Examples

>>> J = 1.41
>>> indx = [2,3]
>>> opstr = "zz"
>>> dtype = np.float64
>>> ME, bra, ket = Op_bra_ket(opstr,indx,J,dtype,ket_states)
Op_shift_sector(other_basis, op_list, v_in, v_out=None, dtype=None)[source]

Applies symmetry non-conserving operator to state in symmetry-reduced basis.

An operator, which does not conserve a symmetry, induces a change in the quantum number of a state defined in the corresponding symmetry sector. Hence, when the operator is applied on a quantum state, the state shifts the symmetry sector. Op_shift_sector() handles this automatically.

NOTE: One has to make sure that (i) the operator moves the state between the two sectors, and (ii) the two bases objects have the same symmetries. This function will not give the correct results otherwise.

Formally equivalent to:

>>> P1 = basis_sector_1.get_proj(np.complex128) # projector between full and initial basis
>>> P2 = basis_sector_2.get_proj(np.complex128) # projector between full and target basis
>>> v_in_full = P1.dot(v_in) # go from initial basis to to full basis
>>> v_out_full = basis_full.inplace_Op(v_in_full,op_list,np.complex128) # apply Op
>>> v_out = P2.T.conj().dot(v_out_full) # project to target basis
Parameters:
other_basisbasis object

basis_general object for the initial symmetry sector. Must be the same basis class type as the basis whose instance is Op_shift_sector() (i.e. the basis in basis.Op_shift_sector()).

op_listlist

Operator string list which defines the operator to apply. Follows the format [[“z”,[i],Jz[i]] for i in range(L)], [“x”,[i],Jx[j]] for j in range(L)],…].

v_inarray_like, (other_basis.Ns,…)

Initial state to apply the symmetry non-conserving operator on. Must have the same length as other_basis.Ns.

v_outarray_like, (basis.Ns,…), optional

Optional array to write the result for the final/target state in.

dtypenumpy dtype for matrix elements, optional

Data type (e.g. numpy.float64) to construct the operator with.

Returns:
(basis.Ns, ) numpy.ndarray

Array containing the state v_out in the current basis, i.e. the basis in basis.Op_shift_sector().

Notes

  • particularly useful when computing correlation functions.

  • supports parallelization to multiple states listed in the columns of v_in.

  • the user is strongly advised to use the code under “Formally equivalent” above to check the results of this function for small system sizes.

Examples

>>> v_out = basis.Op_shift_sector(initial_basis, op_list, v_in)
>>> print(v_out.shape, basis.Ns, v_in.shape, initial_basis.Ns)
property blocks

contains the quantum numbers (blocks) for the symmetry sectors.

Type:

dict

check_hermitian(static, dynamic)

Checks operator string lists for hermiticity of the combined operator.

Parameters:
static: list

Static operators formatted to be passed into the static argument of the hamiltonian class.

dynamic: list

Dynamic operators formatted to be passed into the dynamic argument of the hamiltonian class.

check_pcon(static, dynamic)

Checks operator string lists for particle number (magnetisation) conservartion of the combined operator.

Parameters:
static: list

Static operators formatted to be passed into the static argument of the hamiltonian class.

dynamic: list

Dynamic operators formatted to be passed into the dynamic argument of the hamiltonian class.

check_symm(static, dynamic)

Checks operator string lists for the required symmetries of the combined operator.

Parameters:
static: list

Static operators formatted to be passed into the static argument of the hamiltonian class.

dynamic: list

Dynamic operators formatted to be passed into the dynamic argument of the hamiltonian class.

property description

information about basis object.

Type:

str

property dtype

data type of basis state integers.

Type:

numpy.dtype

ent_entropy(state, sub_sys_A=None, density=True, subsys_ordering=True, return_rdm=None, enforce_pure=False, return_rdm_EVs=False, sparse=False, alpha=1.0, sparse_diag=True, maxiter=None, svd_solver=None, svd_kwargs=None)[source]

Calculates entanglement entropy of subsystem A and the corresponding reduced density matrix

Parameters:
stateobj

State of the quantum system. Can be either one of:

  • numpy.ndarray [shape (Ns,)]: pure state (default).

  • numpy.ndarray [shape (Ns,Ns)]: density matrix (DM).

  • dict(‘V_states’,V_states) [shape (Ns,Nvecs)]: collection of Nvecs states stored in the columns of V_states.

sub_sys_Atuple/list, optional

Defines the sites contained in subsystem A [by python convention the first site of the chain is labelled j=0]. Depending on the usage of simple/advanced notations the input is different:

  • Simple notation: The format is (spin_up_subsys,spin_down_subsys) where the tuple spin_up_subsys and spin_down_subsys are lists (see example below). Default is tuple(range(N//2),range(N//2)) with N the number of physical lattice sites (e.g. sites which both species of fermions can occupy).

  • Advanced notation: The format is a list, the labeling of the up spins are sites 0 - (N-1) while the down spins are on sites N - (2N - 1).

return_rdmstr, optional

Toggles returning the reduced DM. Can be tierh one of:

  • “A”: returns reduced DM of subsystem A.

  • “B”: returns reduced DM of subsystem B.

  • “both”: returns reduced DM of both A and B subsystems.

enforce_purebool, optional

Whether or not to assume state is a colelction of pure states or a mixed density matrix, if it is a square array. Default is False.

subsys_orderingbool, optional

Whether or not to reorder the sites in sub_sys_A in ascending order. Default is True.

sparsebool, optional

Whether or not to return a sparse DM. Default is False.

return_rdm_EVsbool, optional

Whether or not to return the eigenvalues of rthe educed DM. If return_rdm is specified, the eigenvalues of the corresponding DM are returned. If return_rdm is NOT specified, the spectrum of rdm_A is returned by default. Default is False.

alphafloat, optional

Renyi \(\alpha\) parameter for the entanglement entropy. Default is \(\alpha=1\):

\[S_\mathrm{ent}(\alpha) = \frac{1}{1-\alpha}\log \mathrm{tr}_{A} \left( \mathrm{tr}_{A^c} \vert\psi\rangle\langle\psi\vert \right)^\alpha\]

Note: The logarithm used is the natural logarithm (base e).

sparse_diagbool, optional

When sparse=True, this flag enforces the use of scipy.sparse.linalg.eigsh() to calculate the eigenvaues of the reduced DM.

maxiterint, optional

Specifies the number of iterations for Lanczos diagonalisation. Look up documentation for scipy.sparse.linalg.eigsh().

svd_solverobject, optional

Specifies the svd solver to be used, e.g. numpy.linalg.svd or scipy.linalg.svd, or a custom solver. Effective when enforce_pure=True or sparse=False.

svd_kwargsdict, optional

Specifies additional arguments for svd_solver.

Returns:
dict
Dictionary with following keys, depending on input parameters:
  • “Sent_A”: entanglement entropy of subsystem A (default).

  • “Sent_B”: entanglement entropy of subsystem B.

  • “p_A”: singular values of reduced DM of subsystem A (default).

  • “p_B”: singular values of reduced DM of subsystem B.

  • “rdm_A”: reduced DM of subsystem A.

  • “rdm_B”: reduced DM of subsystem B.

Notes

Algorithm is based on both partial tracing and sigular value decomposition (SVD), optimised for speed.

Examples

>>> sub_sys_A_up=range(basis.L//2) # subsystem for spin-up fermions
>>> sub_sys_A_down=range(basis.L//2+1) # subsystem for spin-down fermions
>>> subsys_A=(sub_sys_A_up,sub_sys_A_down)
>>> state=1.0/np.sqrt(basis.Ns)*np.ones(basis.Ns) # infinite temperature state
>>> ent_entropy(state,sub_sys_A=subsys_A,return_rdm="A",enforce_pure=False,return_rdm_EVs=False,
>>>                             sparse=False,alpha=1.0,sparse_diag=True,subsys_ordering=True)
expanded_form(static=[], dynamic=[])

Splits up operator strings containing “x” and “y” into operator combinations of “+” and “-”. This function is useful for higher spin hamiltonians where “x” and “y” operators are not appropriate operators.

Parameters:
static: list

Static operators formatted to be passed into the static argument of the hamiltonian class.

dynamic: list

Dynamic operators formatted to be passed into the dynamic argument of the hamiltonian class.

Returns:
tuple
(static, dynamic), where
  • list: static: operator strings with “x” and “y” expanded into “+” and “-”, formatted to

    be passed into the static argument of the hamiltonian class.

  • list: dynamic: operator strings with “x” and “y” expanded into “+” and “-”, formatted to

    be passed into the dynamic argument of the hamiltonian class.

Notes

This function works with the tensor_basis and other basis which use the “|” symbol in the opstr.

Examples

>>> static = [["xx",[[1.0,0,1]]],["yy",[[1.0,0,1]]]]
>>> dynamic = [["y",[[1.0,0]],lambda t: t,[]]]
>>> expanded_form(static,dynamic)
get_amp(states, out=None, amps=None, mode='representative')

Computes the rescale factor of state amplitudes between the symmetry-reduced and full basis.

Given a quantum state \(s\) and a state amplitude in the full basis \(\psi_s\), its representative (under the symemtries) \(r(s)\) with a corresponding amplitude \(\psi^\text{sym}_r\), the function computes the ratio \(C\), defined as

\[\psi_s = C\psi_r^\text{sym}\]
Parameters:
statesarray_like(int)

Fock-basis (z-basis) states to find the amplitude rescale factor \(C\) of. States are stored in integer representations.

outnumpy.ndarray(float), optional

variable to store the rescale factors \(C\) of the states in. Must be a real or complex-valued numpy.ndarray of the same shape as states.

ampsnumpy.ndarray(float), optional

array of amplitudes to rescale by the amplitude factor \(C\) (see mode). Updated in-place. Must be a real or complex-valued numpy.ndarray of the same shape as states.

modestring, optional
  • if mode=’representative’ (default), then the function assumes that
    1. states already contains representatives (i.e. states in the symmetry-reduced basis);

    2. amps (if passed) are amplitudes in the symmetry-reduced basis (\(\psi_r^\text{symm}\)). The function will update amps in-place to \(\psi_s\).

  • if mode=’full_basis’, then the function assumes that
    1. states contains full-basis states (the funciton will compute the corresponding representatives);

    2. amps (if passed) are amplitudes in the full basis (\(\psi_s\)). The function will update amps in-place to \(\psi_r^\text{symm}\);

      Note: the function will also update the variable states in place with the corresponding representatives.

Returns:
array_like(float)

amplitude rescale factor \(C\) (see expression above).

Notes

  • Particularly useful when a given operation cannot be carried away in the symmetry-reduced basis in a straightforward manner.

  • To transform an entire state from a symmetry-reduced basis to the full (symmetry-free) basis, use the basis.get_vec() function.

  • Returns zero, if the state passed to the function is not part of the symmetry-reduced basis.

  • If amps is passed, the user has to make sure that the input data in amps correspond to the states.

  • The function assumes that states comply with the particle conservation symmetry the basis was constructed with.

Examples

>>> C = get_amp(states,out=None,amps=None,mode='representative')
get_proj(dtype, pcon=False)

Calculates transformation/projector from symmetry-reduced basis to full (symmetry-free) basis.

Parameters:
dtype‘type’

Data type (e.g. numpy.float64) to construct the projector with.

pconbool, optional

Whether or not to return the projector to the particle number (magnetisation) conserving basis (useful in bosonic/single particle systems). Default is pcon=False.

Returns:
scipy.sparse.csc_matrix

Transformation/projector between the symmetry-reduced and the full basis.

Notes

  • particularly useful when a given operation canot be carried out in the symmetry-reduced basis in a straightforward manner.

  • see also Op_shift_sector().

Examples

>>> P = get_proj(np.float64,pcon=False)
>>> print(P.shape)
get_vec(v0, sparse=True, pcon=False)

DEPRECATED (cf project_from). Transforms state from symmetry-reduced basis to full (symmetry-free) basis.

Notes

This function is deprecated. Use project_from() instead; see also the inverse function project_to().

index(up_state, down_state)[source]

Finds the index of user-defined Fock state in spinful fermion basis.

Parameters:
up_statestr

string which define the Fock state for the spin up fermions.

down_statestr

string which define the Fock state for the spin down fermions.

Returns:
int

Position of the Fock state in the spinful_fermion_basis_1d.

Notes

Particularly useful for defining initial Fock states through a unit vector in the direction specified by index().

Examples

>>> s_up = "".join("1" for i in range(2)) + "".join("0" for i in range(2))
>>> s_down = "".join("0" for i in range(2)) + "".join("1" for i in range(2))
>>> print( basis.index(s_up,s_down) )
inplace_Op(v_in, op_list, dtype, transposed=False, conjugated=False, a=1.0, v_out=None)

Calculates the action of an operator on a state.

Parameters:
v_inarray_like

state (or states stored in columns) to act on with the operator.

op_listlist

Operator string list which defines the operator to apply. Follows the format [[“z”,[i],Jz[i]] for i in range(L)], [“x”,[i],Jx[j]] for j in range(L)],…].

dtype‘type’

Data type (e.g. numpy.float64) to construct the operator with.

transposedbool, optional

if True this function will act with the trasposed operator.

conjugatedbool, optional

if True this function will act with the conjugated operator.

ascalar, optional

value to rescale resulting vector after performing the action of the operators. Same as rescaling all couplings by value a.

v_outarray_like

output array, must be the same shape as v_in and must match the type of the output.

Returns:
numpy.ndarray
  • if v_out is not None, this function modifies v_out inplace and returns it.

Notes

This function works with the tensor_basis and other basis which use the “|” symbol in the opstr.

Examples

>>> J = 1.41
>>> indx = [2,3]
>>> opstr = "zz"
>>> dtype = np.float64
>>> op_list=[[opstr,indx,J]]
>>> ME, row, col = inplace_Op(op_list,dtype)
int_to_state(state, bracket_notation=True)[source]

Finds string representation of a state defined in integer representation.

Parameters:
stateint

Defines the Fock state in integer representation in underlying lattice basis.

bracket_notationbool, optional

Toggles whether to return the state in |str> notation.

Returns:
str

String corresponding to the Fock state in the lattice basis.

Notes

This function is the inverse of state_to_int.

Examples

>>> s = basis[0] # pick state from basis set
>>> s_str = basis.int_to_state(s)
>>> print(s_str)
make(Ns_block_est=None, N_p=None)

Creates the entire basis by calling the basis constructor.

Parameters:
Ns_block_est: int, optional

Overwrites the internal estimate of the size of the reduced Hilbert space for the given symmetries. This can be used to help conserve memory if the exact size of the H-space is known ahead of time.

N_p: int, optional

number of bits to use in the prefix label used to generate blocks for searching positions of representatives.

Returns:
int

Total number of states in the (symmetry-reduced) Hilbert space.

Notes

The memory stored in the basis grows exponentially as exactly \(2^{N_p+1}\). The default behavior is to use N_p such that the size of the stored information for the representative bounds is approximately as large as the basis. This is not as effective for basis which small particle numbers as the blocks have very uneven sizes. To not use the blocks just set N_p=0.

Examples

>>> N, Nup = 8, 4
>>> basis=spin_basis_general(N,Nup=Nup,make_basis=False)
>>> print(basis)
>>> basis.make()
>>> print(basis)
make_basis_blocks(N_p=None)

Creates/modifies the bounds for representatives based on prefix tages.

Parameters:
N_p: int, optional

number of bits to use in the prefix label used to generate blocks for searching positions of representatives.

Notes

The memory stored in the basis grows exponentially as exactly \(2^{N_p+1}\). The default behavior is to use N_p such that the size of the stored information for the representative bounds is approximately as large as the basis. This is not as effective for basis which small particle numbers as the blocks have very uneven sizes. To not use the blocks just set N_p=0.

Examples

>>> N, Nup = 8, 4
>>> basis=spin_basis_general(N,Nup=Nup,make_basis=False)
>>> print(basis)
>>> basis.make()
>>> print(basis)
property noncommuting_bits

list of bits that represent sites that do not commute along with the phase required from commuting sites

Type:

list

normalization(states, out=None)

Computes normalization of basis states.

Parameters:
statesarray_like(int)

Fock-basis (z-basis) states to find the normalizations of. States are stored in integer representations.

outnumpy.ndarray(unsigned int), optional

variable to store the normalizations of the states in. Must be a numpy.ndarray of datatype unsigned int (e.g. numpy.uint16), and same shape as states.

Returns:
array_like(int)

normalizations of states for the given (symmetry-reduced) basis.

Notes

  • Returns zero, if the state is not part of the symmetry-reduced basis.

  • The normalizations can be used to compute matrix elements in the symmetry-reduced basis.

Examples

>>> basis=spin_basis_general(N,Nup=Nup,make_basis=False)
>>> s = 17
>>> norm_s = basis.normalization(s)
>>> print(s,norm_s)
property operators

set of available operator strings.

Type:

set

partial_trace(state, sub_sys_A=None, subsys_ordering=True, return_rdm='A', enforce_pure=False, sparse=False)

Calculates reduced density matrix, through a partial trace of a quantum state in a lattice basis.

Parameters:
stateobj

State of the quantum system. Can be either one of:

  • numpy.ndarray [shape (Ns,)]: pure state (default).

  • numpy.ndarray [shape (Ns,Ns)]: density matrix (DM).

sub_sys_Atuple/list, optional

Defines the sites contained in subsystem A [by python convention the first site of the chain is labelled j=0]. Default is tuple(range(N//2)) with N the number of lattice sites.

return_rdmstr, optional

Toggles returning the reduced DM. Can be tierh one of:

  • “A”: returns reduced DM of subsystem A.

  • “B”: returns reduced DM of subsystem B.

  • “both”: returns reduced DM of both A and B subsystems.

subsys_orderingbool, optional

Whether or not to reorder the sites in sub_sys_A in ascending order. Default is True.

enforce_purebool, optional

Whether or not to assume state is a colelction of pure states or a mixed density matrix, if it is a square array. Default is False.

sparsebool, optional

Whether or not to return a sparse DM. Default is False.

Returns:
numpy.ndarray

Density matrix associated with state. Depends on optional arguments.

Notes

This function can also be applied to trace out operators/observables defined by the input state, in which case one has to additionally normalize the final output by the Hilbert space dimension of the traced-out space. However, if an operator is defined in a symmetry-reduced basis, there is a caveat. In such a case, one has to:
  1. use the basis.get_proj() function to lift the operator to the full basis;

  2. apply basis.partial_trace();

  3. repeat this procedure for all symmetry sectors, and sum up the resulting reduced operators [this is becauce one has to add in the information about how the operator acts on the full Hilbert space].

Examples

>>> partial_trace(state,sub_sys_A=tuple(range(basis.N//2),return_rdm="A",enforce_pure=False,sparse=False,subsys_ordering=True)
project_from(v0, sparse=True, pcon=False)

Transforms state from symmetry-reduced basis to full (symmetry-free) basis.

Parameters:
v0numpy.ndarray

Contains in its columns the states in the symmetry-reduced basis.

sparsebool, optional

Whether or not the output should be in sparse format. Default is True.

pconbool, optional

Whether or not to return the output in the particle number (magnetisation) conserving basis (useful in bosonic/single particle systems). Default is pcon=False.

Returns:
numpy.ndarray

Array containing the state v0 in the full basis.

Notes

  • particularly useful when a given operation cannot be carried out in the symmetry-reduced basis in a straightforward manner.

  • supports parallelisation to multiple states listed in the columns.

  • inverse function to project_to.

Examples

>>> v_full = project_from(v0)
>>> print(v_full.shape, v0.shape)
project_to(v0, sparse=True, pcon=False)

Transforms state from full (symmetry-free) basis to symmetry-reduced basis.

Parameters:
v0numpy.ndarray

Contains in its columns the states in the full (symmetry-free) basis.

sparsebool, optional

Whether or not the output should be in sparse format. Default is True.

pconbool, optional

Whether or not to return the output in the particle number (magnetisation) conserving basis (useful in bosonic/single particle systems). Default is pcon=False.

Returns:
numpy.ndarray

Array containing the state v0 in the symmetry-reduced basis.

Notes

  • particularly useful when a given operation cannot be carried out in the full basis.

  • supports parallelisation to multiple states listed in the columns.

  • inverse function to project_from.

Examples

>>> v_symm = project_to(v0)
>>> print(v_symm.shape, v0.shape)
representative(states, out=None, return_g=False, return_sign=False)

Maps states to their representatives under the basis symmetries.

Parameters:
statesarray_like(int)

Fock-basis (z-basis) states to find the representatives of. States are stored in integer representations.

outnumpy.ndarray(int), optional

variable to store the representative states in. Must be a numpy.ndarray of same datatype as basis, and same shape as states.

return_gbool, optional

if set to True, the function also returns the integer g corresponding to the number of times each basis symmetry needs to be applied to a given state to obtain its representative.

return_signbool, optional

if set to True, the function returns the sign of the representative relative to the original state (nontrivial only for fermionic bases).

Returns:
tuple

( representatives, g_array, sign_array ) * array_like(int): representatives: Representatives under basis symmetries, corresponding to states. * array_like(int): g_array of size (number of states, number of symmetries). Requires return_g=True. Contains integers corresponding to the number of times each basis symmetry needs to be applied to a given state to obtain its representative. * array_like(int): sign_array of size (number of states,). Requires return_sign=True. Contains sign of the representative relative to the original state (nontrivial only for fermionic bases).

Examples

>>> basis=spin_basis_general(N,Nup=Nup,make_basis=False)
>>> s = 17
>>> r = basis.representative(s)
>>> print(s,r)
property sps

number of states per site (ie, the on-site Hilbert space dimension).

Type:

int

state_to_int(state)[source]

Finds integer representation of a state defined in string format.

Parameters:
statestr

Defines the Fock state with number of particles (spins) per site in underlying lattice basis.

Returns:
int

Integer corresponding to the Fock state in the lattice basis.

Notes

This function is the einverse of int_to_state.

Examples

>>> s_str = "111000" # pick state from basis set
>>> s = basis.state_to_int(s_str)
>>> print(s)
property states

basis states stored in their integer representation.

Type:

numpy.ndarray(int)