ffsim¶
ffsim is a software library for fast simulation of fermionic quantum circuits.
- class ffsim.BitstringType(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)[source]¶
Bases:
Enum
Enumeration for indicating the data type of bitstrings.
- String:
[“0101”, “0110”]
- Integer:
[5, 6]
- Bit array:
- [[False, True, False, True],
[False, True, True, False]]
- BIT_ARRAY = 3¶
Bit array.
- INT = 2¶
Integer.
- STRING = 1¶
String.
- class ffsim.DiagonalCoulombHamiltonian(one_body_tensor, diag_coulomb_mats, constant=0.0)[source]¶
Bases:
object
A diagonal Coulomb Hamiltonian.
A Hamiltonian of the form
\[H = \sum_{\sigma, pq} h_{pq} a^\dagger_{\sigma, p} a_{\sigma, q} + \frac12 \sum_{\sigma \tau, pq} V_{(\sigma \tau), pq} n_{\sigma, p} n_{\tau, q} + \text{constant}.\]where \(n_{\sigma, p} = a_{\sigma, p}^\dagger a_{\sigma, p}\) is the number operator on orbital \(p\) with spin \(\sigma\).
Here \(h_{pq}\) is called the one-body tensor and \(V_{(\sigma \tau), pq}\) are called the diagonal Coulomb matrices. The brackets indicate that \(V_{(\sigma \tau)}\) is a circulant matrix, which satisfies \(V_{\alpha\alpha}=V_{\beta\beta}\) and \(V_{\alpha\beta}=V_{\beta\alpha}\).
- one_body_tensor¶
The one-body tensor \(h\).
- Type:
np.ndarray
- diag_coulomb_mats¶
The diagonal Coulomb matrices \(V_{(\sigma \tau)}\), given as a pair of Numpy arrays specifying independent coefficients for alpha-alpha and alpha-beta interactions (in that order).
- Type:
np.ndarray
- constant¶
The constant.
- Type:
float
- static from_fermion_operator(op)[source]¶
Convert a FermionOperator to a DiagonalCoulombHamiltonian.
- Return type:
- property norb: int¶
The number of spatial orbitals.
- class ffsim.DoubleFactorizedHamiltonian(one_body_tensor, diag_coulomb_mats, orbital_rotations, constant=0.0, z_representation=False)[source]¶
Bases:
object
A Hamiltonian in the double-factorized representation.
The double-factorized form of the molecular Hamiltonian is
\[H = \sum_{\sigma, pq} \kappa_{pq} a^\dagger_{\sigma, p} a_{\sigma, q} + \frac12 \sum_t \sum_{\sigma\tau, ij} Z^{(t)}_{ij} n^{(t)}_{\sigma, i} n^{(t)}_{\tau, j} + \text{constant}'.\]where
\[n^{(t)}_{\sigma, i} = \sum_{pq} U^{(t)}_{pi} a^\dagger_{\sigma, p} a_{\sigma, q} U^{(t)}_{qi}.\]Here each \(U^{(t)}\) is a unitary matrix and each \(Z^{(t)}\) is a real symmetric matrix.
“Z” representation
The “Z” representation of the double factorization is an alternative representation that sometimes yields simpler quantum circuits.
Under the Jordan-Wigner transformation, the number operators take the form
\[n^{(t)}_{\sigma, i} = \frac{(1 - z^{(t)}_{\sigma, i})}{2}\]where \(z^{(t)}_{\sigma, i}\) is the Pauli Z operator in the rotated basis. The “Z” representation is obtained by rewriting the two-body part in terms of these Pauli Z operators and updating the one-body term as appropriate:
\[H = \sum_{\sigma, pq} \kappa'_{pq} a^\dagger_{\sigma, p} a_{\sigma, q} + \frac18 \sum_t \sum_{\sigma\tau, ij}^* Z^{(t)}_{ij} z^{(t)}_{\sigma, i} z^{(t)}_{\tau, j} + \text{constant}''\]where the asterisk denotes summation over indices \(\sigma\tau, ij\) where \(\sigma \neq \tau\) or \(i \neq j\).
References
Low rank representations for quantum simulation of electronic structure
Quantum Filter Diagonalization with Double-Factorized Hamiltonians
- one_body_tensor¶
The one-body tensor \(\kappa\).
- Type:
np.ndarray
- diag_coulomb_mats¶
The diagonal Coulomb matrices.
- Type:
np.ndarray
- orbital_rotations¶
The orbital rotations.
- Type:
np.ndarray
- constant¶
The constant.
- Type:
float
- z_representation¶
Whether the Hamiltonian is in the “Z” representation rather than the “number” representation.
- Type:
bool
- static from_molecular_hamiltonian(hamiltonian, *, z_representation=False, tol=1e-08, max_vecs=None, optimize=False, method='L-BFGS-B', callback=None, options=None, diag_coulomb_indices=None, cholesky=True)[source]¶
Initialize a DoubleFactorizedHamiltonian from a MolecularHamiltonian.
This function takes as input a
MolecularHamiltonian
, which stores a one-body tensor, two-body tensor, and constant. It performs a double-factorized decomposition of the two-body tensor and computes a new one-body tensor and constant, and returns aDoubleFactorizedHamiltonian
storing the results.See
DoubleFactorizedHamiltonian
for a description of the z_representation argument. Seeffsim.linalg.double_factorized()
for a description of the rest of the arguments.- Parameters:
hamiltonian (
MolecularHamiltonian
) – The Hamiltonian whose double-factorized representation to compute.z_representation (
bool
) – Whether to use the “Z” representation of the decomposition.tol (
float
) – Tolerance for error in the decomposition. The error is defined as the maximum absolute difference between an element of the original tensor and the corresponding element of the reconstructed tensor.max_vecs (
int
|None
) – An optional limit on the number of terms to keep in the decomposition of the two-body tensor. This argument overridestol
.optimize (
bool
) – Whether to optimize the tensors returned by the decomposition.method (
str
) – The optimization method. See the documentation of scipy.optimize.minimize for possible values.callback – Callback function for the optimization. See the documentation of scipy.optimize.minimize for usage.
options (
dict
|None
) – Options for the optimization. See the documentation of scipy.optimize.minimize for usage.diag_coulomb_indices (
list
[tuple
[int
,int
]] |None
) – Allowed indices for nonzero values of the diagonal Coulomb matrices. Matrix entries corresponding to indices not in this list will be set to zero. This list should contain only upper trianglular indices, i.e., pairs \((i, j)\) where \(i \leq j\). Passing a list with lower triangular indices will raise an error. This parameter is only used if optimize is set to True.cholesky (
bool
) – Whether to perform the factorization using a modified Cholesky decomposition. If False, a full eigenvalue decomposition is used instead, which can be much more expensive. This argument is ignored if optimize is set to True.
- Return type:
- Returns:
The double-factorized Hamiltonian.
- property norb: int¶
The number of spatial orbitals.
- to_molecular_hamiltonian()[source]¶
Convert the DoubleFactorizedHamiltonian to a MolecularHamiltonian.
- to_number_representation()[source]¶
Return the Hamiltonian in the “number” representation.
- Return type:
- class ffsim.FermionAction(action: bool, spin: bool, orb: int)[source]¶
Bases:
NamedTuple
A fermionic action.
-
action:
bool
¶ Alias for field number 0
-
orb:
int
¶ Alias for field number 2
-
spin:
bool
¶ Alias for field number 1
-
action:
- class ffsim.FermionOperator(coeffs)¶
Bases:
object
A fermionic operator.
A FermionOperator represents a linear combination of products of fermionic creation and annihilation operators. Initialize a FermionOperator by passing a dictionary mapping the terms in the linear combination to their associated coefficients. FermionOperators Can be added, subtracted, and multiplied, and they support multiplication and division by scalars. When multiplying by a scalar, the scalar should go on the left side of the multiplication operator, e.g.
scalar * op
, notop * scalar
.See How to use the FermionOperator class for an explanation of how to use this class.
Example:
# Note: Since FermionOperator is an unordered mapping, the order of # the terms in the print outputs below may vary between runs. import ffsim op1 = ffsim.FermionOperator( { (ffsim.cre_a(0), ffsim.des_a(3)): 0.5, (ffsim.cre_a(3), ffsim.des_a(0)): -0.25, (ffsim.cre_b(1), ffsim.des_b(5), ffsim.cre_a(4)): 1 + 1j, } ) print(2 * op1) # prints # FermionOperator({ # (cre_b(1), des_b(5), cre_a(4)): 2+2j, # (cre_a(3), des_a(0)): -0.5, # (cre_a(0), des_a(3)): 1 # }) op2 = ffsim.FermionOperator( { (ffsim.cre_b(2),): 1j, (ffsim.des_a(3), ffsim.des_b(3)): -0.25, } ) print(op1 + op2) # prints # FermionOperator({ # (cre_a(3), des_a(0)): -0.25, # (cre_b(2)): 0+1j, # (des_a(3), des_b(3)): -0.25, # (cre_b(1), des_b(5), cre_a(4)): 1+1j, # (cre_a(0), des_a(3)): 0.5 # }) print(op1 * op2) # prints # FermionOperator({ # (cre_b(1), des_b(5), cre_a(4), cre_b(2)): -1+1j, # (cre_a(0), des_a(3), des_a(3), des_b(3)): -0.125, # (cre_a(3), des_a(0), des_a(3), des_b(3)): 0.0625, # (cre_b(1), des_b(5), cre_a(4), des_a(3), des_b(3)): -0.25-0.25j, # (cre_a(0), des_a(3), cre_b(2)): 0+0.5j, # (cre_a(3), des_a(0), cre_b(2)): 0-0.25j # })
- Parameters:
coeffs (dict[tuple[tuple[bool, bool, int], ...], complex]) – The coefficients of the operator.
- conserves_particle_number()¶
Return whether the operator conserves particle number.
- Returns:
True if the operator conserves particle number, False otherwise.
- Return type:
bool
- conserves_spin_z()¶
Return whether the operator conserves the Z component of spin.
- Returns:
True if the operator conserves the Z component of spin, False otherwise.
- Return type:
bool
- many_body_order()¶
Return the many-body order of the operator.
The many-body order is defined as the length of the longest term contained in the operator.
- Returns:
The many-body order of the operator.
- Return type:
int
- normal_ordered()¶
Return the normal ordered form of the operator.
The normal ordered form of an operator is an equivalent operator in which each term has been reordered into a canonical ordering. In each term of a normal-ordered fermion operator, the operators comprising the term appear from left to right in descending lexicographic order by (action, spin, orb). That is, all creation operators appear before all annihilation operators; within creation/annihilation operators, spin beta operators appear before spin alpha operators, and larger orbital indices appear before smaller orbital indices.
- Returns:
The normal-ordered fermion operator.
- Return type:
- class ffsim.GivensAnsatzOp(norb, interaction_pairs, thetas, phis, phase_angles)[source]¶
Bases:
object
A Givens rotation ansatz operator.
The Givens rotation ansatz consists of a sequence of Givens rotations followed by a layer of single-orbital phase gates.
Note that this ansatz does not implement any interactions between spin alpha and spin beta orbitals.
- norb¶
The number of spatial orbitals.
- Type:
int
- interaction_pairs¶
The orbital pairs to apply the Givens rotations to.
- Type:
list[tuple[int, int]]
- thetas¶
The angles for the Givens rotations.
- Type:
np.ndarray
- phis¶
The optional phase angles for the Givens rotations.
- Type:
np.ndarray | None
- phase_angles¶
The optional phase angles for the layer of single-orbital phase gates.
- Type:
np.ndarray | None
- static from_orbital_rotation(orbital_rotation)[source]¶
Initialize the operator from an orbital rotation.
- Parameters:
orbital_rotation (
ndarray
) – The orbital rotation.- Return type:
- static from_parameters(params, norb, interaction_pairs, with_phis=True, with_phase_angles=True)[source]¶
Initialize the operator from a real-valued parameter vector.
- Parameters:
params (
ndarray
) – The real-valued parameter vector.norb (
int
) – The number of spatial orbitals.interaction_pairs (
list
[tuple
[int
,int
]]) – The orbital pairs to apply the Givens rotation gates to.with_phis (
bool
) – Whether to include complex phases for the Givens rotations.with_phase_angles (
bool
) – Whether to include a layer of single-orbital phase gates.
- Return type:
- static n_params(norb, interaction_pairs, with_phis=True, with_phase_angles=True)[source]¶
Return the number of parameters of an ansatz with given settings.
- Parameters:
norb (
int
) – The number of spatial orbitals.interaction_pairs (
list
[tuple
[int
,int
]]) – The orbital pairs to apply the Givens rotation gates to.with_phis (
bool
) – Whether to include complex phases for the Givens rotations.with_phase_angles (
bool
) – Whether to include a layer of single-orbital phase gates.
- Return type:
int
- class ffsim.GivensAnsatzOperator(norb, interaction_pairs, thetas)[source]¶
Bases:
object
A Givens rotation ansatz operator.
Warning
This class is deprecated. Use
ffsim.GivensAnsatzOp
instead.The Givens rotation ansatz consists of a sequence of Givens rotations.
Note that this ansatz does not implement any interactions between spin alpha and spin beta orbitals.
- norb¶
The number of spatial orbitals.
- Type:
int
- interaction_pairs¶
The orbital pairs to apply the Givens rotations to.
- Type:
list[tuple[int, int]]
- thetas¶
The angles for the Givens rotations.
- Type:
np.ndarray
- static from_parameters(params, norb, interaction_pairs)[source]¶
Initialize the operator from a real-valued parameter vector.
- Parameters:
params (
ndarray
) – The real-valued parameter vector.norb (
int
) – The number of spatial orbitals.interaction_pairs (
list
[tuple
[int
,int
]]) – The orbital pairs to apply the Givens rotation gates to.
- Return type:
- class ffsim.HopGateAnsatzOperator(norb, interaction_pairs, thetas, final_orbital_rotation=None)[source]¶
Bases:
object
A hop gate ansatz operator.
The hop gate ansatz consists of a sequence of hop gates.
Note that this ansatz does not implement any interactions between spin alpha and spin beta orbitals. It was designed to be used with entanglement forging.
- norb¶
The number of spatial orbitals.
- Type:
int
- interaction_pairs¶
The orbital pairs to apply the hop gates to.
- Type:
list[tuple[int, int]]
- thetas¶
The rotation angles for the hop gates.
- Type:
np.ndarray
- final_orbital_rotation¶
An optional final orbital rotation to append to the ansatz, used to optimize the orbital basis.
- Type:
np.ndarray
- static from_parameters(params, norb, interaction_pairs, with_final_orbital_rotation=False)[source]¶
Initialize the operator from a real-valued parameter vector.
- Parameters:
params (
ndarray
) – The real-valued parameter vector.norb (
int
) – The number of spatial orbitals.interaction_pairs (
list
[tuple
[int
,int
]]) – The orbital pairs to apply the hop gates to.with_final_orbital_rotation (
bool
) – Whether to include a final orbital rotation in the ansatz operator.
- Return type:
- class ffsim.MolecularData(core_energy, one_body_integrals, two_body_integrals, norb, nelec, atom=None, basis=None, spin=None, symmetry=None, mo_coeff=None, mo_occ=None, active_space=None, hf_energy=None, hf_mo_coeff=None, hf_mo_occ=None, mp2_energy=None, mp2_t2=None, ccsd_energy=None, ccsd_t1=None, ccsd_t2=None, cisd_energy=None, cisd_vec=None, sci_energy=None, sci_vec=None, fci_energy=None, fci_vec=None, dipole_integrals=None, orbital_symmetries=None)[source]¶
Bases:
object
Class for storing molecular data.
- core_energy¶
The core energy.
- Type:
float
- one_body_integrals¶
The one-body integrals.
- Type:
np.ndarray
- two_body_integrals¶
The two-body integrals in compressed format.
- Type:
np.ndarray
- norb¶
The number of spatial orbitals.
- Type:
int
- nelec¶
The number of alpha and beta electrons.
- Type:
tuple[int, int]
- atom¶
The coordinates of the atoms in the molecule.
- Type:
list[tuple[str, tuple[float, float, float]]] | None
- basis¶
The basis set, e.g. “sto-6g”.
- Type:
str | None
- spin¶
The spin of the molecule.
- Type:
int | None
- symmetry¶
The symmetry of the molecule.
- Type:
str | None
- mo_coeff¶
Molecular orbital coefficients in the AO basis.
- Type:
np.ndarray | None
- mo_occ¶
Molecular orbital occupancies.
- Type:
np.ndarray | None
- active_space¶
The molecular orbitals included in the active space.
- Type:
list[int] | None
- hf_energy¶
The Hartree-Fock energy.
- Type:
float | None
- hf_mo_coeff¶
Hartree-Fock canonical orbital coefficients in the AO basis.
- Type:
np.ndarray | None
- hf_mo_occ¶
Hartree-Fock canonical orbital occupancies.
- Type:
np.ndarray | None
- mp2_energy¶
The MP2 energy.
- Type:
float | None
- mp2_t2¶
The MP2 t2 amplitudes.
- Type:
np.ndarray | tuple[np.ndarray, np.ndarray, np.ndarray] | None
- ccsd_energy¶
The CCSD energy.
- Type:
float | None
- ccsd_t1¶
The CCSD t1 amplitudes.
- Type:
np.ndarray | tuple[np.ndarray, np.ndarray] | None
- ccsd_t2¶
The CCSD t2 amplitudes.
- Type:
np.ndarray | tuple[np.ndarray, np.ndarray, np.ndarray] | None
- cisd_energy¶
The CISD energy.
- Type:
float | None
- cisd_vec¶
The CISD state vector.
- Type:
np.ndarray | None
- sci_energy¶
The SCI energy.
- Type:
float | None
- sci_vec¶
The SCI state vector coefficients, spin alpha strings, and spin beta strings.
- Type:
tuple[np.ndarray, np.ndarray, np.ndarray] | None
- fci_energy¶
The FCI energy.
- Type:
float | None
- fci_vec¶
The FCI state vector.
- Type:
np.ndarray | None
- dipole_integrals¶
The dipole integrals.
- Type:
np.ndarray | None
- orbital_symmetries¶
The orbital symmetries.
- Type:
list[str] | None
- static from_fcidump(file)[source]¶
Initialize a MolecularData from an FCIDUMP file.
- Parameters:
file (
str
|bytes
|PathLike
) – The FCIDUMP file path.- Return type:
- static from_json(file, compression=None)[source]¶
Load a MolecularData from a (possibly compressed) JSON file.
- Parameters:
file (
str
|bytes
|PathLike
) – The file path to read from.compression (
str
|None
) – The compression algorithm, if any, which was used to compress the file. Options:"gzip"
,"bz2"
,"lzma"
.
- Return type:
Returns: The MolecularData object.
- static from_mole(molecule, active_space=None, scf_func=<function RHF>)[source]¶
Initialize a MolecularData object from a PySCF molecule.
Warning
This method is deprecated. Instead, pass an SCF object directly to
from_scf()
.- Parameters:
molecule (
Mole
) – The molecule.active_space (
Iterable
[int
] |None
) – An optional list of orbitals to use for the active space.scf_func – The PySCF SCF function to use for the Hartree-Fock calculation.
- Return type:
- static from_scf(hartree_fock, active_space=None)[source]¶
Initialize a MolecularData object from a Hartree-Fock calculation.
- Parameters:
hartree_fock (
SCF
) – The Hartree-Fock object.active_space (
Iterable
[int
] |None
) – An optional list of orbitals to use for the active space.
- Return type:
- property hamiltonian: MolecularHamiltonian¶
The Hamiltonian defined by the molecular data.
- property mole: Mole¶
The PySCF Mole class for this molecular data.
- run_ccsd(t1=None, t2=None, *, store_t1=False, store_t2=False)[source]¶
Run CCSD and store results.
- Return type:
None
- property scf: SCF¶
A PySCF SCF class for this molecular data.
- to_fcidump(file)[source]¶
Save data to disk in FCIDUMP format.
Note
The FCIDUMP format does not retain all information stored in the MolecularData object. To serialize a MolecularData object losslessly, use the
to_json()
method to save to JSON format.- Parameters:
file (
str
|bytes
|PathLike
) – The file path to save to.- Return type:
None
- class ffsim.MolecularHamiltonian(one_body_tensor, two_body_tensor, constant=0.0)[source]¶
Bases:
object
A molecular Hamiltonian.
A Hamiltonian of the form
\[H = \sum_{\sigma, pq} h_{pq} a^\dagger_{\sigma, p} a_{\sigma, q} + \frac12 \sum_{\sigma \tau, pqrs} h_{pqrs} a^\dagger_{\sigma, p} a^\dagger_{\tau, r} a_{\tau, s} a_{\sigma, q} + \text{constant}.\]Here \(h_{pq}\) is called the one-body tensor and \(h_{pqrs}\) is called the two-body tensor.
- one_body_tensor¶
The one-body tensor.
- Type:
np.ndarray
- two_body_tensor¶
The two-body tensor.
- Type:
np.ndarray
- constant¶
The constant.
- Type:
float
- static from_fcidump(file)[source]¶
Initialize a MolecularHamiltonian from an FCIDUMP file.
Warning
This function is deprecated. Instead, use MolecularData.from_fcidump and then access the hamiltonian attribute of the returned MolecularData.
- Parameters:
file (
str
|bytes
|PathLike
) – The FCIDUMP file path.- Return type:
- property norb: int¶
The number of spatial orbitals.
- rotated(orbital_rotation)[source]¶
Return the Hamiltonian in a rotated orbital basis.
Given an orbital rotation \(\mathcal{U}\), returns the operator
\[\mathcal{U} H \mathcal{U}^\dagger\]where \(H\) is the original Hamiltonian.
- Parameters:
orbital_rotation (
ndarray
) – The orbital rotation.- Return type:
- Returns:
The rotated Hamiltonian.
- class ffsim.NumNumAnsatzOpSpinBalanced(norb, interaction_pairs, thetas)[source]¶
Bases:
object
A number-number interaction ansatz operator.
The number-number interaction ansatz consists of a sequence of number-number interactions.
- norb¶
The number of spatial orbitals.
- Type:
int
- interaction_pairs¶
The orbital pairs to apply the number-number interactions to.
- Type:
list[tuple[int, int]]
- thetas¶
The angles for the number-number interactions.
- Type:
np.ndarray
- static from_diag_coulomb_mats(diag_coulomb_mats)[source]¶
Initialize the operator from a diagonal Coulomb matrix.
- Parameters:
diag_coulomb_mats (
tuple
[ndarray
,ndarray
] |ndarray
) – The diagonal Coulomb matrices. Should be a pair of matrices, with the first matrix representing same-spin interactions and the second matrix representing different-spin interactions.- Return type:
- static from_parameters(params, norb, interaction_pairs)[source]¶
Initialize the operator from a real-valued parameter vector.
- Parameters:
params (
ndarray
) – The real-valued parameter vector.norb (
int
) – The number of spatial orbitals.interaction_pairs (
tuple
[list
[tuple
[int
,int
]],list
[tuple
[int
,int
]]]) – The orbital pairs to apply the number-number interactions to.
- Return type:
- static n_params(interaction_pairs)[source]¶
Return the number of parameters of an ansatz with given settings.
- Parameters:
interaction_pairs (
list
[tuple
[int
,int
]]) – The orbital pairs to apply the number-number interactions to.- Return type:
int
- class ffsim.ProductStateSum(coeffs: np.ndarray, states: list[tuple[np.ndarray, np.ndarray]])[source]¶
Bases:
NamedTuple
A linear combination of product states.
Given a ProductStateSum
prod_state_sum
, the full state vector can be reconstructed assum( coeff * np.kron(vec_a, vec_b) for coeff, (vec_a, vec_b) in zip( prod_state_sum.coeffs, prod_state_sum.states ) )
-
coeffs:
ndarray
¶ Alias for field number 0
-
states:
list
[tuple
[ndarray
,ndarray
]]¶ Alias for field number 1
-
coeffs:
- class ffsim.RealUCJOperator(diag_coulomb_mats_alpha_alpha, diag_coulomb_mats_alpha_beta, orbital_rotations, final_orbital_rotation=None)[source]¶
Bases:
object
Real-valued unitary cluster Jastrow operator.
Warning
The RealUCJOperator class is deprecated. Use
ffsim.UCJOpSpinBalanced
instead.A real-valued unitary cluster Jastrow (UCJ) operator has the form
\[\prod_{k = 1}^L \mathcal{W_k^*} e^{i \mathcal{-J}_k} \mathcal{W_k}^T \mathcal{W_k} e^{i \mathcal{J}_k} \mathcal{W_k^\dagger}\]where each \(\mathcal{W_k}\) is an orbital rotation and each \(\mathcal{J}\) is a diagonal Coulomb operator of the form
\[\mathcal{J} = \frac12\sum_{ij,\sigma \tau} \mathbf{J}^{\sigma \tau}_{ij} n_{i,\sigma} n_{j,\tau}.\]In order that the operator commutes with the total spin Z operator, we enforce that \(\mathbf{J}^{\alpha\alpha} = \mathbf{J}^{\beta\beta}\) and \(\mathbf{J}^{\alpha\beta} = \mathbf{J}^{\beta\alpha}\). As a result, we have two sets of matrices for describing the diagonal Coulomb operators: “alpha-alpha” matrices containing coefficients for terms involving the same spin, and “alpha-beta” matrices containing coefficients for terms involving different spins.
To support variational optimization of the orbital basis, an optional final orbital rotation can be included in the operator, to be performed at the end.
- diag_coulomb_mats_alpha_alpha¶
The “alpha-alpha” diagonal Coulomb matrices.
- diag_coulomb_mats_alpha_beta¶
The “alpha-beta” diagonal Coulomb matrices.
- orbital_rotations¶
The orbital rotations.
- final_orbital_rotation¶
The optional final orbital rotation.
- static from_parameters(params, *, norb, n_reps, alpha_alpha_indices=None, alpha_beta_indices=None, with_final_orbital_rotation=False)[source]¶
Initialize the real UCJ operator from a real-valued parameter vector.
- Parameters:
params (
ndarray
) – The real-valued parameter vector.norb (
int
) – The number of spatial orbitals.n_reps (
int
) – The number of ansatz repetitions (\(L\) from the docstring of this class).alpha_alpha_indices (
list
[tuple
[int
,int
]] |None
) – Allowed indices for nonzero values of the “alpha-alpha” diagonal Coulomb matrices (see the docstring of this class). If not specified, all matrix entries are allowed to be nonzero. This list should contain only upper trianglular indices, i.e., pairs \((i, j)\) where \(i \leq j\). Passing a list with lower triangular indices will raise an error.alpha_beta_indices (
list
[tuple
[int
,int
]] |None
) – Allowed indices for nonzero values of the “alpha-beta” diagonal Coulomb matrices (see the docstring of this class). If not specified, all matrix entries are allowed to be nonzero. This list should contain only upper trianglular indices, i.e., pairs \((i, j)\) where \(i \leq j\). Passing a list with lower triangular indices will raise an error.with_final_orbital_rotation (
bool
) – Whether to include a final orbital rotation in the operator.
- Return type:
- Returns:
The real UCJ operator constructed from the given parameters.
- Raises:
ValueError – alpha_alpha_indices contains lower triangular indices.
ValueError – alpha_beta_indices contains lower triangular indices.
- static from_t_amplitudes(t2, *, t1=None, n_reps=None, tol=1e-08)[source]¶
Initialize the real UCJ operator from t2 (and optionally t1) amplitudes.
- Return type:
- static n_params(norb, n_reps, *, alpha_alpha_indices=None, alpha_beta_indices=None, with_final_orbital_rotation=False)[source]¶
Return the number of parameters of an ansatz with given settings.
- Return type:
int
- property n_reps¶
The number of ansatz repetitions.
- property norb¶
The number of spatial orbitals.
- to_parameters(*, alpha_alpha_indices=None, alpha_beta_indices=None)[source]¶
Convert the real UCJ operator to a real-valued parameter vector.
If alpha_alpha_indices or alpha_beta_indices is specified, the returned parameter vector will incorporate only the diagonal Coulomb matrix entries corresponding to the given indices, so the original operator will not be recoverable from the parameter vector.
- Parameters:
alpha_alpha_indices (
list
[tuple
[int
,int
]] |None
) – Allowed indices for nonzero values of the “alpha-alpha” diagonal Coulomb matrices (see the docstring of this class). If not specified, all matrix entries are allowed to be nonzero. This list should contain only upper trianglular indices, i.e., pairs \((i, j)\) where \(i \leq j\). Passing a list with lower triangular indices will raise an error.alpha_beta_indices (
list
[tuple
[int
,int
]] |None
) – Allowed indices for nonzero values of the “alpha-beta” diagonal Coulomb matrices (see the docstring of this class). If not specified, all matrix entries are allowed to be nonzero. This list should contain only upper trianglular indices, i.e., pairs \((i, j)\) where \(i \leq j\). Passing a list with lower triangular indices will raise an error.
- Return type:
ndarray
- Returns:
The real-valued parameter vector.
- Raises:
ValueError – alpha_alpha_indices contains lower triangular indices.
ValueError – alpha_beta_indices contains lower triangular indices.
- class ffsim.SingleFactorizedHamiltonian(one_body_tensor, one_body_squares, constant=0.0)[source]¶
Bases:
object
A Hamiltonian in the single-factorized representation.
The single-factorized form of the molecular Hamiltonian is
\[H = \sum_{\sigma, pq} \kappa_{pq} a^\dagger_{\sigma, p} a_{\sigma, q} + \frac12 \sum_{t=1}^L \left(\mathcal{M}^{(t)}\right)^2 + \text{constant}'.\]Here each \(\mathcal{M}^{(t)}\) is a one-body operator:
\[\mathcal{M}^{(t)} = \sum_{\sigma, pq} M^{(t)}_{pq} a^\dagger_{\sigma, p} a_{\sigma, q}\]where each \(M^{(t)}\) is a Hermitian matrix.
- one_body_tensor¶
The one-body tensor \(\kappa\).
- Type:
np.ndarray
- one_body_squares¶
The one-body tensors \(M^{(t)}\) whose squares are summed in the Hamiltonian.
- Type:
np.ndarray
- constant¶
The constant.
- Type:
float
- expectation_product_state(vec, norb, nelec)[source]¶
Return expectation value with respect to a product state.
- Parameters:
vec (
tuple
[ndarray
,ndarray
]) – The product state, as a pair (vec_a, vec_b) containing the alpha and beta components of the state.norb (
int
) – The number of spatial orbitals.nelec (
tuple
[int
,int
]) – The number of alpha and beta electrons.
- Return type:
float
- static from_molecular_hamiltonian(hamiltonian, *, tol=1e-08, max_vecs=None, cholesky=True)[source]¶
Initialize a SingleFactorizedHamiltonian from a MolecularHamiltonian.
The number of terms in the decomposition depends on the allowed error threshold. A larger error threshold leads to a smaller number of terms. Furthermore, the max_vecs parameter specifies an optional upper bound on the number of terms.
Note: Currently, only real-valued two-body tensors are supported.
- Parameters:
hamiltonian (
MolecularHamiltonian
) – The Hamiltonian whose single-factorized representation to compute.tol (
float
) – Tolerance for error in the decomposition. The error is defined as the maximum absolute difference between an element of the original tensor and the corresponding element of the reconstructed tensor.max_vecs (
int
|None
) – An optional limit on the number of terms to keep in the decomposition of the two-body tensor. This argument overridestol
.cholesky (
bool
) – Whether to perform the factorization using a modified Cholesky decomposition. If False, a full eigenvalue decomposition is used instead, which can be much more expensive.
- Return type:
- Returns:
The single-factorized Hamiltonian.
- property norb: int¶
The number of spatial orbitals.
- reduced_matrix_product_states(vecs, norb, nelec)[source]¶
Return reduced matrix within a subspace spanned by some product states.
Given a list of product states \(\{\lvert \alpha_i, \beta_i \rangle\}\), returns the matrix M where \(M_{ij} = \langle \alpha_i, \beta_i \rvert H \lvert \alpha_j, \beta_j \rangle\).
- Parameters:
vecs (
Sequence
[tuple
[ndarray
,ndarray
]]) – The product states, as a list of pairs (vec_a, vec_b) containing the alpha and beta components of each state.norb (
int
) – The number of spatial orbitals.nelec (
tuple
[int
,int
]) – The number of alpha and beta electrons.
- Return type:
ndarray
- Returns:
The reduced matrix.
- class ffsim.Spin(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)[source]¶
Bases:
Flag
Enumeration for indicating alpha, beta, or both spins.
- ALPHA = 1¶
Use this to indicate spin alpha.
- ALPHA_AND_BETA = 3¶
Use this to indicate both spin alpha and spin beta.
- BETA = 2¶
Use this to indicate spin beta.
- class ffsim.StateVector(vec, norb, nelec)[source]¶
Bases:
object
A state vector in the FCI representation.
- vec¶
Array of state vector coefficients.
- norb¶
The number of spatial orbitals.
- nelec¶
Either a single integer representing the number of fermions for a spinless system, or a pair of integers storing the numbers of spin alpha and spin beta fermions.
- class ffsim.SupportsApplyUnitary(*args, **kwargs)[source]¶
Bases:
Protocol
An object that can apply a unitary transformation to a vector.
- class ffsim.SupportsApproximateEquality(*args, **kwargs)[source]¶
Bases:
Protocol
An object that can be compared approximately.
- class ffsim.SupportsDiagonal(*args, **kwargs)[source]¶
Bases:
Protocol
A linear operator whose diagonal entries can be returned.
- class ffsim.SupportsFermionOperator(*args, **kwargs)[source]¶
Bases:
Protocol
An object that can be converted to a FermionOperator.
- class ffsim.SupportsLinearOperator(*args, **kwargs)[source]¶
Bases:
Protocol
An object that can be converted to a SciPy LinearOperator.
- class ffsim.SupportsTrace(*args, **kwargs)[source]¶
Bases:
Protocol
A linear operator whose trace can be computed.
- class ffsim.UCJOpSpinBalanced(diag_coulomb_mats, orbital_rotations, final_orbital_rotation=None, validate=True, rtol=1e-05, atol=1e-08)[source]¶
Bases:
object
A spin-balanced unitary cluster Jastrow operator.
A unitary cluster Jastrow (UCJ) operator has the form
\[\prod_{k = 1}^L \mathcal{U}_k e^{i \mathcal{J}_k} \mathcal{U}_k^\dagger\]where each \(\mathcal{U_k}\) is an orbital rotation and each \(\mathcal{J}\) is a diagonal Coulomb operator of the form
\[\mathcal{J} = \frac12\sum_{\sigma \tau, ij} \mathbf{J}^{(\sigma \tau)}_{ij} n_{\sigma, i} n_{\tau, j}.\]For the spin-balanced operator, we require that \(\mathbf{J}^{(\alpha \alpha)} = \mathbf{J}^{(\beta \beta)}\) and \(\mathbf{J}^{(\alpha \beta)} = \mathbf{J}^{(\beta \alpha)}\). Therefore, each diagonal Coulomb operator is described by 2 matrices, \(\mathbf{J}^{(\alpha \alpha)}\) and \(\mathbf{J}^{(\alpha \beta)}\), and both of these matrices are symmetric. Furthermore, each orbital rotation is described by a single matrix because the same orbital rotation is applied to both spin alpha and spin beta. The number of terms \(L\) is referred to as the number of ansatz repetitions and is accessible via the n_reps attribute.
To support variational optimization of the orbital basis, an optional final orbital rotation can be included in the operator, to be performed at the end.
- diag_coulomb_mats¶
The diagonal Coulomb matrices, as a Numpy array of shape (n_reps, 2, norb, norb) The last two axes index the rows and columns of the matrices, and the third from last axis, which has 2 dimensions, indexes the spin interaction type of the matrix: alpha-alpha, and then alpha-beta. The first axis indexes the ansatz repetitions.
- Type:
np.ndarray
- orbital_rotations¶
The orbital rotations, as a Numpy array of shape (n_reps, norb, norb).
- Type:
np.ndarray
- final_orbital_rotation¶
The optional final orbital rotation, as a Numpy array of shape (norb, norb).
- Type:
np.ndarray | None
- static from_parameters(params, *, norb, n_reps, interaction_pairs=None, with_final_orbital_rotation=False)[source]¶
Initialize the UCJ operator from a real-valued parameter vector.
- Parameters:
params (
ndarray
) – The real-valued parameter vector.norb (
int
) – The number of spatial orbitals.n_reps (
int
) – The number of ansatz repetitions.interaction_pairs (
tuple
[list
[tuple
[int
,int
]] |None
,list
[tuple
[int
,int
]] |None
] |None
) – Optional restrictions on allowed orbital interactions for the diagonal Coulomb operators. If specified, interaction_pairs should be a pair of lists, for alpha-alpha and alpha-beta interactions, in that order. Either list can be substituted withNone
to indicate no restrictions on interactions. Each list should contain pairs of integers representing the orbitals that are allowed to interact. These pairs can also be interpreted as indices of diagonal Coulomb matrix entries that are allowed to be nonzero. Each integer pair must be upper triangular, that is, of the form \((i, j)\) where \(i \leq j\).with_final_orbital_rotation (
bool
) – Whether to include a final orbital rotation in the operator.
- Return type:
- Returns:
The UCJ operator constructed from the given parameters.
- Raises:
ValueError – The number of parameters passed did not match the number expected based on the function inputs.
ValueError – Interaction pairs list contained duplicate interactions.
ValueError – Interaction pairs list contained lower triangular pairs.
- static from_t_amplitudes(t2, *, t1=None, n_reps=None, interaction_pairs=None, tol=1e-08)[source]¶
Initialize the UCJ operator from t2 (and optionally t1) amplitudes.
Performs a double-factorization of the t2 amplitudes and constructs the ansatz repetitions from the terms of the decomposition, up to an optionally specified number of ansatz repetitions. Terms are included in decreasing order of the absolute value of the corresponding eigenvalue in the factorization.
- Parameters:
t2 (
ndarray
) – The t2 amplitudes.t1 (
ndarray
|None
) – The t1 amplitudes.n_reps (
int
|None
) – The number of ansatz repetitions. If not specified, then it is set to the number of terms resulting from the double-factorization of the t2 amplitudes. If the specified number of repetitions is larger than the number of terms resulting from the double-factorization, then the ansatz is padded with additional identity operators up to the specified number of repetitions.interaction_pairs (
tuple
[list
[tuple
[int
,int
]] |None
,list
[tuple
[int
,int
]] |None
] |None
) – Optional restrictions on allowed orbital interactions for the diagonal Coulomb operators. If specified, interaction_pairs should be a pair of lists, for alpha-alpha and alpha-beta interactions, in that order. Either list can be substituted withNone
to indicate no restrictions on interactions. Each list should contain pairs of integers representing the orbitals that are allowed to interact. These pairs can also be interpreted as indices of diagonal Coulomb matrix entries that are allowed to be nonzero. Each integer pair must be upper triangular, that is, of the form \((i, j)\) where \(i \leq j\).tol (
float
) – Tolerance for error in the double-factorized decomposition of the t2 amplitudes. The error is defined as the maximum absolute difference between an element of the original tensor and the corresponding element of the reconstructed tensor.
- Return type:
- Returns:
The UCJ operator with parameters initialized from the t2 amplitudes.
- Raises:
ValueError – Interaction pairs list contained duplicate interactions.
ValueError – Interaction pairs list contained lower triangular pairs.
- static n_params(norb, n_reps, *, interaction_pairs=None, with_final_orbital_rotation=False)[source]¶
Return the number of parameters of an ansatz with given settings.
- Parameters:
n_reps (
int
) – The number of ansatz repetitions.interaction_pairs (
tuple
[list
[tuple
[int
,int
]] |None
,list
[tuple
[int
,int
]] |None
] |None
) – Optional restrictions on allowed orbital interactions for the diagonal Coulomb operators. If specified, interaction_pairs should be a pair of lists, for alpha-alpha and alpha-beta interactions, in that order. Either list can be substituted withNone
to indicate no restrictions on interactions. Each list should contain pairs of integers representing the orbitals that are allowed to interact. These pairs can also be interpreted as indices of diagonal Coulomb matrix entries that are allowed to be nonzero. Each integer pair must be upper triangular, that is, of the form \((i, j)\) where \(i \leq j\).with_final_orbital_rotation (
bool
) – Whether to include a final orbital rotation in the operator.
- Return type:
int
- Returns:
The number of parameters of the ansatz.
- Raises:
ValueError – Interaction pairs list contained duplicate interactions.
ValueError – Interaction pairs list contained lower triangular pairs.
- property n_reps¶
The number of ansatz repetitions.
- property norb¶
The number of spatial orbitals.
- to_parameters(*, interaction_pairs=None)[source]¶
Convert the UCJ operator to a real-valued parameter vector.
Note
If interaction_pairs is specified, the returned parameter vector will incorporate only the diagonal Coulomb matrix entries corresponding to the specified interactions, so the original operator will not be recoverable from the parameter vector.
- Parameters:
interaction_pairs (
tuple
[list
[tuple
[int
,int
]] |None
,list
[tuple
[int
,int
]] |None
] |None
) – Optional restrictions on allowed orbital interactions for the diagonal Coulomb operators. If specified, interaction_pairs should be a pair of lists, for alpha-alpha and alpha-beta interactions, in that order. Either list can be substituted withNone
to indicate no restrictions on interactions. Each list should contain pairs of integers representing the orbitals that are allowed to interact. These pairs can also be interpreted as indices of diagonal Coulomb matrix entries that are allowed to be nonzero. Each integer pair must be upper triangular, that is, of the form \((i, j)\) where \(i \leq j\).- Return type:
ndarray
- Returns:
The real-valued parameter vector.
- Raises:
ValueError – Interaction pairs list contained duplicate interactions.
ValueError – Interaction pairs list contained lower triangular pairs.
- class ffsim.UCJOpSpinUnbalanced(diag_coulomb_mats, orbital_rotations, final_orbital_rotation=None, validate=True, rtol=1e-05, atol=1e-08)[source]¶
Bases:
object
A spin-unbalanced unitary cluster Jastrow operator.
A unitary cluster Jastrow (UCJ) operator has the form
\[\prod_{k = 1}^L \mathcal{U}_k e^{i \mathcal{J}_k} \mathcal{U}_k^\dagger\]where each \(\mathcal{U_k}\) is an orbital rotation and each \(\mathcal{J}\) is a diagonal Coulomb operator of the form
\[\mathcal{J} = \frac12\sum_{\sigma \tau, ij} \mathbf{J}^{(\sigma \tau)}_{ij} n_{\sigma, i} n_{\tau, j}.\]Since \(\mathbf{J}^{(\sigma \tau)}_{ij} = \mathbf{J}^{(\tau \sigma)}_{ji}\), each diagonal Coulomb operator requires 3 matrices for its description: \(\mathbf{J}^{(\alpha \alpha)}\), \(\mathbf{J}^{(\alpha \beta)}\), and \(\mathbf{J}^{(\beta \beta)}\). The number of terms \(L\) is referred to as the number of ansatz repetitions and is accessible via the n_reps attribute.
To support variational optimization of the orbital basis, an optional final orbital rotation can be included in the operator, to be performed at the end.
- diag_coulomb_mats¶
The diagonal Coulomb matrices, as a Numpy array of shape (n_reps, 3, norb, norb) The last two axes index the rows and columns of the matrices, and the third from last axis, which has 3 dimensions, indexes the spin interaction type of the matrix: alpha-alpha, alpha-beta, and beta-beta (in that order). The first axis indexes the ansatz repetitions.
- Type:
np.ndarray
- orbital_rotations¶
The orbital rotations, as a Numpy array of shape (n_reps, 2, norb, norb). The last two axes index the rows and columns of the orbital rotations, and the third from last axis, which has 2 dimensions, indexes the spin sector of the orbital rotation: first alpha, then beta. The first axis indexes the ansatz repetitions.
- Type:
np.ndarray
- final_orbital_rotation¶
The optional final orbital rotation, as a Numpy array of shape (2, norb, norb). This can be viewed as a list of two orbital rotations, the first one for spin alpha and the second one for spin beta.
- Type:
np.ndarray | None
- static from_parameters(params, *, norb, n_reps, interaction_pairs=None, with_final_orbital_rotation=False)[source]¶
Initialize the UCJ operator from a real-valued parameter vector.
- Parameters:
params (
ndarray
) – The real-valued parameter vector.norb (
int
) – The number of spatial orbitals.n_reps (
int
) – The number of ansatz repetitions.interaction_pairs (
tuple
[list
[tuple
[int
,int
]] |None
,list
[tuple
[int
,int
]] |None
,list
[tuple
[int
,int
]] |None
] |None
) – Optional restrictions on allowed orbital interactions for the diagonal Coulomb operators. If specified, interaction_pairs should be a tuple of 3 lists, for alpha-alpha, alpha-beta, and beta-beta interactions, in that order. Any list can be substituted withNone
to indicate no restrictions on interactions. Each list should contain pairs of integers representing the orbitals that are allowed to interact. These pairs can also be interpreted as indices of diagonal Coulomb matrix entries that are allowed to be nonzero. For the alpha-alpha and beta-beta interactions, each integer pair must be upper triangular, that is, of the form \((i, j)\) where \(i \leq j\).with_final_orbital_rotation (
bool
) – Whether to include a final orbital rotation in the operator.
- Return type:
- Returns:
The UCJ operator constructed from the given parameters.
- Raises:
ValueError – The number of parameters passed did not match the number expected based on the function inputs.
ValueError – Interaction pairs list contained duplicate interactions.
ValueError – Interaction pairs list for alpha-alpha or beta-beta interactions contained lower triangular pairs.
- static from_t_amplitudes(t2, *, t1=None, n_reps=None, interaction_pairs=None, tol=1e-08)[source]¶
Initialize the UCJ operator from t2 (and optionally t1) amplitudes.
Performs a double-factorization of the t2 amplitudes and constructs the ansatz repetitions from the terms of the decomposition, up to an optionally specified number of repetitions. Terms are included in decreasing order of the magnitude of the corresponding singular value in the factorization.
- Parameters:
t2 (
tuple
[ndarray
,ndarray
,ndarray
]) – The t2 amplitudes. This should be a tuple of 3 Numpy arrays, (t2aa, t2ab, t2bb), containing the alpha-alpha, alpha-beta, and beta-beta t2 amplitudes.t1 (
tuple
[ndarray
,ndarray
] |None
) – The t1 amplitudes. This should be a pair of Numpy arrays, (t1a, t1b), containing the alpha and beta t1 amplitudes.n_reps (
int
|tuple
[int
,int
] |None
) – The number of ansatz repetitions. You can pass a single integer or a pair of integers. If a single integer, terms from the alpha-beta t2 amplitudes are used before including any terms from the alpha-alpha and beta-beta t2 amplitudes. If a pair of integers, then the first integer specifies the number of terms to use from the alpha-beta t2 amplitudes, and the second integer specifies the number of terms to use from the alpha-alpha and beta-beta t2 amplitudes. If not specified, then it is set to the number of terms resulting from the double-factorization of the t2 amplitudes. If the specified number of repetitions is larger than the number of terms resulting from the double-factorization, then the ansatz is padded with additional identity operators up to the specified number of repetitions.interaction_pairs (
tuple
[list
[tuple
[int
,int
]] |None
,list
[tuple
[int
,int
]] |None
,list
[tuple
[int
,int
]] |None
] |None
) – Optional restrictions on allowed orbital interactions for the diagonal Coulomb operators. If specified, interaction_pairs should be a tuple of 3 lists, for alpha-alpha, alpha-beta, and beta-beta interactions, in that order. Any list can be substituted withNone
to indicate no restrictions on interactions. Each list should contain pairs of integers representing the orbitals that are allowed to interact. These pairs can also be interpreted as indices of diagonal Coulomb matrix entries that are allowed to be nonzero. For the alpha-alpha and beta-beta interactions, each integer pair must be upper triangular, that is, of the form \((i, j)\) where \(i \leq j\).tol (
float
) – Tolerance for error in the double-factorized decomposition of the t2 amplitudes. The error is defined as the maximum absolute difference between an element of the original tensor and the corresponding element of the reconstructed tensor.
- Return type:
- Returns:
The UCJ operator with parameters initialized from the t2 amplitudes.
- Raises:
ValueError – Interaction pairs list contained duplicate interactions.
ValueError – Interaction pairs list for alpha-alpha or beta-beta interactions contained lower triangular pairs.
- static n_params(norb, n_reps, *, interaction_pairs=None, with_final_orbital_rotation=False)[source]¶
Return the number of parameters of an ansatz with given settings.
- Parameters:
n_reps (
int
) – The number of ansatz repetitions.interaction_pairs (
tuple
[list
[tuple
[int
,int
]] |None
,list
[tuple
[int
,int
]] |None
,list
[tuple
[int
,int
]] |None
] |None
) – Optional restrictions on allowed orbital interactions for the diagonal Coulomb operators. If specified, interaction_pairs should be a tuple of 3 lists, for alpha-alpha, alpha-beta, and beta-beta interactions, in that order. Any list can be substituted withNone
to indicate no restrictions on interactions. Each list should contain pairs of integers representing the orbitals that are allowed to interact. These pairs can also be interpreted as indices of diagonal Coulomb matrix entries that are allowed to be nonzero. For the alpha-alpha and beta-beta interactions, each integer pair must be upper triangular, that is, of the form \((i, j)\) where \(i \leq j\).with_final_orbital_rotation (
bool
) – Whether to include a final orbital rotation in the operator.
- Return type:
int
- Returns:
The number of parameters of the ansatz.
- Raises:
ValueError – Interaction pairs list contained duplicate interactions.
ValueError – Interaction pairs list for alpha-alpha or beta-beta interactions contained lower triangular pairs.
- property n_reps¶
The number of ansatz repetitions.
- property norb¶
The number of spatial orbitals.
- to_parameters(interaction_pairs=None)[source]¶
Convert the UCJ operator to a real-valued parameter vector.
Note
If interaction_pairs is specified, the returned parameter vector will incorporate only the diagonal Coulomb matrix entries corresponding to the specified interactions, so the original operator will not be recoverable from the parameter vector.
- Parameters:
interaction_pairs (
tuple
[list
[tuple
[int
,int
]] |None
,list
[tuple
[int
,int
]] |None
,list
[tuple
[int
,int
]] |None
] |None
) – Optional restrictions on allowed orbital interactions for the diagonal Coulomb operators. If specified, interaction_pairs should be a tuple of 3 lists, for alpha-alpha, alpha-beta, and beta-beta interactions, in that order. Any list can be substituted withNone
to indicate no restrictions on interactions. Each list should contain pairs of integers representing the orbitals that are allowed to interact. These pairs can also be interpreted as indices of diagonal Coulomb matrix entries that are allowed to be nonzero. For the alpha-alpha and beta-beta interactions, each integer pair must be upper triangular, that is, of the form \((i, j)\) where \(i \leq j\).- Return type:
ndarray
- Returns:
The real-valued parameter vector.
- Raises:
ValueError – Interaction pairs list contained duplicate interactions.
ValueError – Interaction pairs list for alpha-alpha or beta-beta interactions contained lower triangular pairs.
- class ffsim.UCJOpSpinless(diag_coulomb_mats, orbital_rotations, final_orbital_rotation=None, validate=True, rtol=1e-05, atol=1e-08)[source]¶
Bases:
object
A spinless unitary cluster Jastrow operator.
A spinless unitary cluster Jastrow (UCJ) operator has the form
\[\prod_{k = 1}^L \mathcal{U}_k e^{i \mathcal{J}_k} \mathcal{U}_k^\dagger\]where each \(\mathcal{U_k}\) is an orbital rotation and each \(\mathcal{J}\) is a diagonal Coulomb operator of the form
\[\mathcal{J} = \frac12\sum_{ij} \mathbf{J}_{ij} n_{i} n_{j}.\]where mathbf{J} is a real symmetric matrix. The number of terms \(L\) is referred to as the number of ansatz repetitions and is accessible via the n_reps attribute.
To support variational optimization of the orbital basis, an optional final orbital rotation can be included in the operator, to be performed at the end.
- diag_coulomb_mats¶
The diagonal Coulomb matrices, as a Numpy array of shape (n_reps, norb, norb)
- Type:
np.ndarray
- orbital_rotations¶
The orbital rotations, as a Numpy array of shape (n_reps, norb, norb).
- Type:
np.ndarray
- final_orbital_rotation¶
The optional final orbital rotation, as a Numpy array of shape (norb, norb).
- Type:
np.ndarray | None
- static from_parameters(params, *, norb, n_reps, interaction_pairs=None, with_final_orbital_rotation=False)[source]¶
Initialize the UCJ operator from a real-valued parameter vector.
- Parameters:
params (
ndarray
) – The real-valued parameter vector.norb (
int
) – The number of spatial orbitals.n_reps (
int
) – The number of ansatz repetitions.interaction_pairs (
list
[tuple
[int
,int
]] |None
) – Optional restrictions on allowed orbital interactions for the diagonal Coulomb operators. If specified, interaction_pairs should be a list of integer pairs representing the orbitals that are allowed to interact. These pairs can also be interpreted as indices of diagonal Coulomb matrix entries that are allowed to be nonzero. Each integer pair must be upper triangular, that is, of the form \((i, j)\) where \(i \leq j\).with_final_orbital_rotation (
bool
) – Whether to include a final orbital rotation in the operator.
- Return type:
- Returns:
The UCJ operator constructed from the given parameters.
- Raises:
ValueError – The number of parameters passed did not match the number expected based on the function inputs.
ValueError – Interaction pairs list contained duplicate interactions.
ValueError – Interaction pairs list contained lower triangular pairs.
- static from_t_amplitudes(t2, *, t1=None, n_reps=None, interaction_pairs=None, tol=1e-08)[source]¶
Initialize the UCJ operator from t2 (and optionally t1) amplitudes.
Performs a double-factorization of the t2 amplitudes and constructs the ansatz repetitions from the terms of the decomposition, up to an optionally specified number of ansatz repetitions. Terms are included in decreasing order of the absolute value of the corresponding eigenvalue in the factorization.
- Parameters:
t2 (
ndarray
) – The t2 amplitudes.t1 (
ndarray
|None
) – The t1 amplitudes.n_reps (
int
|None
) – The number of ansatz repetitions. If not specified, then it is set to the number of terms resulting from the double-factorization of the t2 amplitudes. If the specified number of repetitions is larger than the number of terms resulting from the double-factorization, then the ansatz is padded with additional identity operators up to the specified number of repetitions.interaction_pairs (
list
[tuple
[int
,int
]] |None
) – Optional restrictions on allowed orbital interactions for the diagonal Coulomb operators. If specified, interaction_pairs should be a list of integer pairs representing the orbitals that are allowed to interact. These pairs can also be interpreted as indices of diagonal Coulomb matrix entries that are allowed to be nonzero. Each integer pair must be upper triangular, that is, of the form \((i, j)\) where \(i \leq j\).tol (
float
) – Tolerance for error in the double-factorized decomposition of the t2 amplitudes. The error is defined as the maximum absolute difference between an element of the original tensor and the corresponding element of the reconstructed tensor.
- Return type:
- Returns:
The UCJ operator with parameters initialized from the t2 amplitudes.
- Raises:
ValueError – Interaction pairs list contained duplicate interactions.
ValueError – Interaction pairs list contained lower triangular pairs.
- static n_params(norb, n_reps, *, interaction_pairs=None, with_final_orbital_rotation=False)[source]¶
Return the number of parameters of an ansatz with given settings.
- Parameters:
n_reps (
int
) – The number of ansatz repetitions.interaction_pairs (
list
[tuple
[int
,int
]] |None
) – Optional restrictions on allowed orbital interactions for the diagonal Coulomb operators. If specified, interaction_pairs should be a list of integer pairs representing the orbitals that are allowed to interact. These pairs can also be interpreted as indices of diagonal Coulomb matrix entries that are allowed to be nonzero. Each integer pair must be upper triangular, that is, of the form \((i, j)\) where \(i \leq j\).with_final_orbital_rotation (
bool
) – Whether to include a final orbital rotation in the operator.
- Return type:
int
- Returns:
The number of parameters of the ansatz.
- Raises:
ValueError – Interaction pairs list contained duplicate interactions.
ValueError – Interaction pairs list contained lower triangular pairs.
- property n_reps¶
The number of ansatz repetitions.
- property norb¶
The number of spatial orbitals.
- to_parameters(*, interaction_pairs=None)[source]¶
Convert the UCJ operator to a real-valued parameter vector.
Note
If interaction_pairs is specified, the returned parameter vector will incorporate only the diagonal Coulomb matrix entries corresponding to the specified interactions, so the original operator will not be recoverable from the parameter vector.
- Parameters:
interaction_pairs (
list
[tuple
[int
,int
]] |None
) – Optional restrictions on allowed orbital interactions for the diagonal Coulomb operators. If specified, interaction_pairs should be a list of integer pairs representing the orbitals that are allowed to interact. These pairs can also be interpreted as indices of diagonal Coulomb matrix entries that are allowed to be nonzero. Each integer pair must be upper triangular, that is, of the form \((i, j)\) where \(i \leq j\).- Return type:
ndarray
- Returns:
The real-valued parameter vector.
- Raises:
ValueError – Interaction pairs list contained duplicate interactions.
ValueError – Interaction pairs list contained lower triangular pairs.
- class ffsim.UCJOperator(diag_coulomb_mats_alpha_alpha, diag_coulomb_mats_alpha_beta, orbital_rotations, final_orbital_rotation=None)[source]¶
Bases:
object
A unitary cluster Jastrow operator.
Warning
The UCJOperator class is deprecated. Use
ffsim.UCJOpSpinBalanced
instead.A unitary cluster Jastrow (UCJ) operator has the form
\[\prod_{k = 1}^L \mathcal{W}_k e^{i \mathcal{J}_k} \mathcal{W}_k^\dagger\]where each \(\mathcal{W_k}\) is an orbital rotation and each \(\mathcal{J}\) is a diagonal Coulomb operator of the form
\[\mathcal{J} = \frac12\sum_{\sigma \tau, ij} \mathbf{J}^{\sigma \tau}_{ij} n_{\sigma, i} n_{\tau, j}.\]In order that the operator commutes with the total spin Z operator, we enforce that \(\mathbf{J}^{\alpha\alpha} = \mathbf{J}^{\beta\beta}\) and \(\mathbf{J}^{\alpha\beta} = \mathbf{J}^{\beta\alpha}\). As a result, we have two sets of matrices for describing the diagonal Coulomb operators: “alpha-alpha” matrices containing coefficients for terms involving the same spin, and “alpha-beta” matrices containing coefficients for terms involving different spins.
To support variational optimization of the orbital basis, an optional final orbital rotation can be included in the operator, to be performed at the end.
- diag_coulomb_mats_alpha_alpha¶
The “alpha-alpha” diagonal Coulomb matrices.
- Type:
np.ndarray
- diag_coulomb_mats_alpha_beta¶
The “alpha-beta” diagonal Coulomb matrices.
- Type:
np.ndarray
- orbital_rotations¶
The orbital rotations.
- Type:
np.ndarray
- final_orbital_rotation¶
The optional final orbital rotation.
- Type:
np.ndarray
- static from_parameters(params, *, norb, n_reps, alpha_alpha_indices=None, alpha_beta_indices=None, with_final_orbital_rotation=False)[source]¶
Initialize the UCJ operator from a real-valued parameter vector.
- Parameters:
params (
ndarray
) – The real-valued parameter vector.norb (
int
) – The number of spatial orbitals.n_reps (
int
) – The number of ansatz repetitions (\(L\) from the docstring of this class).alpha_alpha_indices (
list
[tuple
[int
,int
]] |None
) – Allowed indices for nonzero values of the “alpha-alpha” diagonal Coulomb matrices (see the docstring of this class). If not specified, all matrix entries are allowed to be nonzero. This list should contain only upper trianglular indices, i.e., pairs \((i, j)\) where \(i \leq j\). Passing a list with lower triangular indices will raise an error.alpha_beta_indices (
list
[tuple
[int
,int
]] |None
) – Allowed indices for nonzero values of the “alpha-beta” diagonal Coulomb matrices (see the docstring of this class). If not specified, all matrix entries are allowed to be nonzero. This list should contain only upper trianglular indices, i.e., pairs \((i, j)\) where \(i \leq j\). Passing a list with lower triangular indices will raise an error.with_final_orbital_rotation (
bool
) – Whether to include a final orbital rotation in the operator.
- Return type:
- Returns:
The UCJ operator constructed from the given parameters.
- Raises:
ValueError – alpha_alpha_indices contains lower triangular indices.
ValueError – alpha_beta_indices contains lower triangular indices.
- static from_t_amplitudes(t2, *, t1=None, n_reps=None, tol=1e-08)[source]¶
Initialize the UCJ operator from t2 (and optionally t1) amplitudes.
- Return type:
- static n_params(norb, n_reps, *, alpha_alpha_indices=None, alpha_beta_indices=None, with_final_orbital_rotation=False)[source]¶
Return the number of parameters of an ansatz with given settings.
- Return type:
int
- property n_reps¶
The number of ansatz repetitions.
- property norb¶
The number of spatial orbitals.
- to_parameters(*, alpha_alpha_indices=None, alpha_beta_indices=None)[source]¶
Convert the UCJ operator to a real-valued parameter vector.
If alpha_alpha_indices or alpha_beta_indices is specified, the returned parameter vector will incorporate only the diagonal Coulomb matrix entries corresponding to the given indices, so the original operator will not be recoverable from the parameter vector.
- Parameters:
alpha_alpha_indices (
list
[tuple
[int
,int
]] |None
) – Allowed indices for nonzero values of the “alpha-alpha” diagonal Coulomb matrices (see the docstring of this class). If not specified, all matrix entries are allowed to be nonzero. This list should contain only upper trianglular indices, i.e., pairs \((i, j)\) where \(i \leq j\). Passing a list with lower triangular indices will raise an error.alpha_beta_indices (
list
[tuple
[int
,int
]] |None
) – Allowed indices for nonzero values of the “alpha-beta” diagonal Coulomb matrices (see the docstring of this class). If not specified, all matrix entries are allowed to be nonzero. This list should contain only upper trianglular indices, i.e., pairs \((i, j)\) where \(i \leq j\). Passing a list with lower triangular indices will raise an error.
- Return type:
ndarray
- Returns:
The real-valued parameter vector.
- Raises:
ValueError – alpha_alpha_indices contains lower triangular indices.
ValueError – alpha_beta_indices contains lower triangular indices.
- ffsim.addresses_to_strings(addresses, norb, nelec, concatenate=True, bitstring_type=BitstringType.INT)[source]¶
Convert state vector addresses to bitstrings.
Example:
import ffsim norb = 3 nelec = (2, 1) dim = ffsim.dim(norb, nelec) strings = ffsim.addresses_to_strings(range(5), norb, nelec) print(strings) # prints [11, 19, 35, 13, 21] strings = ffsim.addresses_to_strings( range(5), norb, nelec, bitstring_type=ffsim.BitstringType.STRING ) print(strings) # prints ['001011', '010011', '100011', '001101', '010101'] strings = ffsim.addresses_to_strings( range(5), norb, nelec, bitstring_type=ffsim.BitstringType.BIT_ARRAY ) print(strings) # prints # [[False False True False True True] # [False True False False True True] # [ True False False False True True] # [False False True True False True] # [False True False True False True]]
- Parameters:
addresses (
Sequence
[int
] |ndarray
) – The state vector addresses to convert to bitstrings.norb (
int
) – The number of spatial orbitals.nelec (
int
|tuple
[int
,int
]) – Either a single integer representing the number of fermions for a spinless system, or a pair of integers storing the numbers of spin alpha and spin beta fermions.bitstring_type (
BitstringType
) – The desired type of bitstring output.concatenate (
bool
) – Whether to concatenate the spin-alpha and spin-beta parts of the bitstrings. If True, then a single list of concatenated bitstrings is returned. The strings are concatenated in the order \(s_b s_a\), that is, the alpha string appears on the right. If False, then two lists are returned,(strings_a, strings_b)
. Note that the list of alpha strings appears first, that is, on the left. In the spinless case (when nelec is an integer), this argument is ignored.
- Returns:
The bitstrings. The type of the output depends on bitstring_type and concatenate.
- ffsim.apply_diag_coulomb_evolution(vec, mat, time, norb, nelec, *, orbital_rotation=None, z_representation=False, copy=True)[source]¶
Apply time evolution by a (rotated) diagonal Coulomb operator.
Applies
\[\mathcal{U} \exp\left(-i t \sum_{\sigma, \tau, i, j} Z^{(\sigma \tau)}_{ij} n_{\sigma, i} n_{\tau, j} / 2\right) \mathcal{U}^\dagger\]where \(n_{\sigma, i}\) denotes the number operator on orbital \(i\) with spin \(\sigma\), \(Z^{(\sigma \tau)}\) is a real-valued matrix, and \(\mathcal{U}\) is an optional orbital rotation.
- Parameters:
vec (
ndarray
) – The state vector to be transformed.mat (
ndarray
|tuple
[ndarray
|None
,ndarray
|None
,ndarray
|None
]) – The diagonal Coulomb matrix \(Z\). You can pass either a single Numpy array specifying the coefficients to use for all spin interactions, or you can pass a tuple of three Numpy arrays specifying independent coefficients for alpha-alpha, alpha-beta, and beta-beta interactions (in that order). If passing a tuple, you can set a tuple element toNone
to indicate the absence of interactions of that type. The alpha-alpha and beta-beta matrices are assumed to be symmetric, and only their upper triangular entries are used.time (
float
) – The evolution time.norb (
int
) – The number of spatial orbitals.nelec (
int
|tuple
[int
,int
]) – Either a single integer representing the number of fermions for a spinless system, or a pair of integers storing the numbers of spin alpha and spin beta fermions.orbital_rotation (
ndarray
|tuple
[ndarray
|None
,ndarray
|None
] |None
) – The optional orbital rotation. You can pass either a single Numpy array specifying the orbital rotation to apply to both spin sectors, or you can pass a pair of Numpy arrays specifying independent orbital rotations for spin alpha and spin beta. If passing a pair, you can useNone
for one of the values in the pair to indicate that no operation should be applied to that spin sector.z_representation (
bool
) – Whether the input matrices are in the “Z” representation.copy (
bool
) –Whether to copy the vector before operating on it.
If copy=True then this function always returns a newly allocated vector and the original vector is left untouched.
If copy=False then this function may still return a newly allocated vector, but the original vector may have its data overwritten. It is also possible that the original vector is returned, modified in-place.
- Return type:
ndarray
- Returns:
The evolved state vector.
- ffsim.apply_fsim_gate(vec, theta, phi, target_orbs, norb, nelec, spin=<Spin.ALPHA_AND_BETA: 3>, *, copy=True)[source]¶
Apply an fSim gate.
An fSim gate consists of a tunneling interaction followed by a number-number interaction (note the negative sign convention for the angles):
\[\begin{split}\begin{align} \text{fSim}&(\theta, \phi, (p, q)) = \text{NN}(-\phi, (p, q)) \text{T}(-\theta, (p, q)) \\ &= \prod_\sigma \exp\left(-i \phi a^\dagger_{\sigma, p} a_{\sigma, p} a^\dagger_{\sigma, q} a_{\sigma, q}\right) \exp\left(-i \theta (a^\dagger_{\sigma, p} a_{\sigma, q} + a^\dagger_{\sigma, q} a_{\sigma, p})\right) \end{align}\end{split}\]Under the Jordan-Wigner transform, this gate has the following matrix when applied to neighboring qubits:
\[\begin{split}\begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & \cos(\theta) & -i \sin(\theta) & 0\\ 0 & -i \sin(\theta) & \cos(\theta) & 0\\ 0 & 0 & 0 & e^{-i \phi} \\ \end{pmatrix}\end{split}\]- Parameters:
vec (
ndarray
) – The state vector to be transformed.theta (
float
) – The rotation angle for the tunneling interaction.phi (
float
) – The phase angle for the number-number interaction.target_orbs (
tuple
[int
,int
]) – The orbitals (p, q) to interact.norb (
int
) – The number of spatial orbitals.nelec (
int
|tuple
[int
,int
]) – Either a single integer representing the number of fermions for a spinless system, or a pair of integers storing the numbers of spin alpha and spin beta fermions.spin (
Spin
) –Choice of spin sector(s) to act on.
To act on only spin alpha, pass
ffsim.Spin.ALPHA
.To act on only spin beta, pass
ffsim.Spin.BETA
.To act on both spin alpha and spin beta, pass
ffsim.Spin.ALPHA_AND_BETA
(this is the default value).
copy (
bool
) –Whether to copy the vector before operating on it.
If copy=True then this function always returns a newly allocated vector and the original vector is left untouched.
If copy=False then this function may still return a newly allocated vector, but the original vector may have its data overwritten. It is also possible that the original vector is returned, modified in-place.
- Return type:
ndarray
- ffsim.apply_fswap_gate(vec, target_orbs, norb, nelec, spin=<Spin.ALPHA_AND_BETA: 3>, *, copy=True)[source]¶
Apply an FSWAP gate.
The FSWAP gate swaps two orbitals. It is represented by the operator
\[\text{FSWAP}(p, q) = 1 + a^\dagger_p a_q + a^\dagger_q a_p - a_p^\dagger a_p - a_q^\dagger a_q\]Under the Jordan-Wigner transform, this gate has the following matrix when applied to neighboring qubits:
\[\begin{split}\begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & -1 \\ \end{pmatrix}\end{split}\]- Parameters:
vec (
ndarray
) – The state vector to be transformed.target_orbs (
tuple
[int
,int
]) – The orbitals (p, q) to swap.norb (
int
) – The number of spatial orbitals.nelec (
int
|tuple
[int
,int
]) – Either a single integer representing the number of fermions for a spinless system, or a pair of integers storing the numbers of spin alpha and spin beta fermions.spin (
Spin
) – Choice of spin sector(s) to act on.copy (
bool
) –Whether to copy the vector before operating on it.
- If copy=True then this function always returns a newly allocated
vector and the original vector is left untouched.
- If copy=False then this function may still return a newly allocated
vector, but the original vector may have its data overwritten. It is also possible that the original vector is returned, modified in-place.
- Return type:
ndarray
- ffsim.apply_givens_rotation(vec, theta, target_orbs, norb, nelec, spin=<Spin.ALPHA_AND_BETA: 3>, *, phi=0.0, copy=True)[source]¶
Apply a Givens rotation gate.
The Givens rotation gate is
\[\text{G}(\theta, \varphi, (p, q)) = \prod_{\sigma} \exp\left(i\varphi a^\dagger_{\sigma, p} a_{\sigma, p}\right) \exp\left(\theta (a^\dagger_{\sigma, p} a_{\sigma, q} - a^\dagger_{\sigma, q} a_{\sigma, p})\right) \exp\left(-i\varphi a^\dagger_{\sigma, p} a_{\sigma, p}\right)\]Under the Jordan-Wigner transform, this gate has the following matrix when applied to neighboring qubits:
\[\begin{split}\begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & \cos(\theta) & -e^{-i\varphi}\sin(\theta) & 0\\ 0 & e^{i\varphi}\sin(\theta) & \cos(\theta) & 0\\ 0 & 0 & 0 & 1 \\ \end{pmatrix}\end{split}\]- Parameters:
vec (
ndarray
) – The state vector to be transformed.theta (
float
) – The rotation angle.target_orbs (
tuple
[int
,int
]) – The orbitals (p, q) to rotate.norb (
int
) – The number of spatial orbitals.nelec (
int
|tuple
[int
,int
]) – Either a single integer representing the number of fermions for a spinless system, or a pair of integers storing the numbers of spin alpha and spin beta fermions.spin (
Spin
) –Choice of spin sector(s) to act on.
To act on only spin alpha, pass
ffsim.Spin.ALPHA
.To act on only spin beta, pass
ffsim.Spin.BETA
.To act on both spin alpha and spin beta, pass
ffsim.Spin.ALPHA_AND_BETA
(this is the default value).
phi (
float
) – The optional phase angle.copy (
bool
) –Whether to copy the vector before operating on it.
If copy=True then this function always returns a newly allocated vector and the original vector is left untouched.
If copy=False then this function may still return a newly allocated vector, but the original vector may have its data overwritten. It is also possible that the original vector is returned, modified in-place.
- Return type:
ndarray
- ffsim.apply_hop_gate(vec, theta, target_orbs, norb, nelec, spin=<Spin.ALPHA_AND_BETA: 3>, *, copy=True)[source]¶
Apply a hop gate.
A “hop gate” is a Givens rotation gate followed by a number-number interaction with angle pi:
\[\begin{split}\begin{align} \text{Hop}&(\theta, (p, q)) = \text{NN}(\pi, (p, q)) \text{G}(\theta, (p, q)) \\ &= \prod_{\sigma} \exp\left(i \theta a^\dagger_{\sigma, p} a_{\sigma, p} a^\dagger_{\sigma, q} a_{\sigma, q}\right) \exp\left(\theta (a^\dagger_{\sigma, p} a_{\sigma, q} - a^\dagger_{\sigma, q} a_{\sigma, p})\right) \end{align}\end{split}\]Under the Jordan-Wigner transform, this gate has the following matrix when applied to neighboring qubits:
\[\begin{split}\begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & \cos(\theta) & -\sin(\theta) & 0\\ 0 & \sin(\theta) & \cos(\theta) & 0\\ 0 & 0 & 0 & -1 \\ \end{pmatrix}\end{split}\]- Parameters:
vec (
ndarray
) – The state vector to be transformed.theta (
float
) – The rotation angle.target_orbs (
tuple
[int
,int
]) – The orbitals (p, q) to interact.norb (
int
) – The number of spatial orbitals.nelec (
int
|tuple
[int
,int
]) – Either a single integer representing the number of fermions for a spinless system, or a pair of integers storing the numbers of spin alpha and spin beta fermions.spin (
Spin
) –Choice of spin sector(s) to act on.
To act on only spin alpha, pass
ffsim.Spin.ALPHA
.To act on only spin beta, pass
ffsim.Spin.BETA
.To act on both spin alpha and spin beta, pass
ffsim.Spin.ALPHA_AND_BETA
(this is the default value).
copy (
bool
) –Whether to copy the vector before operating on it.
If copy=True then this function always returns a newly allocated vector and the original vector is left untouched.
If copy=False then this function may still return a newly allocated vector, but the original vector may have its data overwritten. It is also possible that the original vector is returned, modified in-place.
- Return type:
ndarray
- ffsim.apply_num_interaction(vec, theta, target_orb, norb, nelec, spin=<Spin.ALPHA_AND_BETA: 3>, *, copy=True)[source]¶
Apply a number interaction gate.
The number interaction gate is
\[\text{N}(\theta, p) = \prod_{\sigma} \exp\left(i \theta a^\dagger_{\sigma, p} a_{\sigma, p}\right)\]- Parameters:
vec (
ndarray
) – The state vector to be transformed.theta (
float
) – The rotation angle.target_orb (
int
) – The orbital on which to apply the interaction.norb (
int
) – The number of spatial orbitals.nelec (
int
|tuple
[int
,int
]) – Either a single integer representing the number of fermions for a spinless system, or a pair of integers storing the numbers of spin alpha and spin beta fermions.spin (
Spin
) –Choice of spin sector(s) to act on.
To act on only spin alpha, pass
ffsim.Spin.ALPHA
.To act on only spin beta, pass
ffsim.Spin.BETA
.To act on both spin alpha and spin beta, pass
ffsim.Spin.ALPHA_AND_BETA
(this is the default value).
copy (
bool
) –Whether to copy the vector before operating on it.
If copy=True then this function always returns a newly allocated vector and the original vector is left untouched.
If copy=False then this function may still return a newly allocated vector, but the original vector may have its data overwritten. It is also possible that the original vector is returned, modified in-place.
- Return type:
ndarray
- ffsim.apply_num_num_interaction(vec, theta, target_orbs, norb, nelec, spin=<Spin.ALPHA_AND_BETA: 3>, *, copy=True)[source]¶
Apply a number-number interaction gate.
The number-number interaction gate is
\[\text{NN}(\theta, (p, q)) = \prod_{\sigma} \exp\left(i \theta a^\dagger_{\sigma, p} a_{\sigma, p} a^\dagger_{\sigma, q} a_{\sigma, q}\right)\]- Parameters:
vec (
ndarray
) – The state vector to be transformed.theta (
float
) – The rotation angle.target_orbs (
tuple
[int
,int
]) – The orbitals (p, q) to interact.norb (
int
) – The number of spatial orbitals.nelec (
int
|tuple
[int
,int
]) – Either a single integer representing the number of fermions for a spinless system, or a pair of integers storing the numbers of spin alpha and spin beta fermions.spin (
Spin
) –Choice of spin sector(s) to act on.
To act on only spin alpha, pass
ffsim.Spin.ALPHA
.To act on only spin beta, pass
ffsim.Spin.BETA
.To act on both spin alpha and spin beta, pass
ffsim.Spin.ALPHA_AND_BETA
(this is the default value).
copy (
bool
) –Whether to copy the vector before operating on it.
If copy=True then this function always returns a newly allocated vector and the original vector is left untouched.
If copy=False then this function may still return a newly allocated vector, but the original vector may have its data overwritten. It is also possible that the original vector is returned, modified in-place.
- ffsim.apply_num_op_prod_interaction(vec, theta, target_orbs, norb, nelec, *, copy=True)[source]¶
Apply interaction gate for product of number operators.
The gate is
\[\text{NP}(\theta, (S_\alpha, S_\beta)) = \exp\left(i \theta \prod_{p \in S_\alpha} a^\dagger_{\alpha, p} a_{\alpha, p} \prod_{p \in S_\beta} a^\dagger_{\beta, p} a_{\beta, p} \right)\]- Parameters:
vec (
ndarray
) – The state vector to be transformed.theta (
float
) – The rotation angle.target_orbs (
tuple
[Sequence
[int
],Sequence
[int
]]) – A pair of lists of integers giving the orbitals on which to apply the interaction. The first list specifies the alpha orbitals and the second list specifies the beta orbitals.norb (
int
) – The number of spatial orbitals.nelec (
tuple
[int
,int
]) – The number of alpha and beta electrons.copy (
bool
) –Whether to copy the vector before operating on it.
If copy=True then this function always returns a newly allocated vector and the original vector is left untouched.
If copy=False then this function may still return a newly allocated vector, but the original vector may have its data overwritten. It is also possible that the original vector is returned, modified in-place.
- ffsim.apply_num_op_sum_evolution(vec, coeffs, time, norb, nelec, *, orbital_rotation=None, copy=True)[source]¶
Apply time evolution by a (rotated) linear combination of number operators.
Applies
\[\mathcal{U} \exp\left(-i t \sum_{\sigma, i} \lambda^{(\sigma)}_i n_{\sigma, i}\right) \mathcal{U}^\dagger\]where \(n_{\sigma, i}\) denotes the number operator on orbital \(i\) with spin \(\sigma\), the \(\lambda_i\) are real numbers, and \(\mathcal{U}\) is an optional orbital rotation.
- Parameters:
vec (
ndarray
) – The state vector to be transformed.coeffs (
ndarray
|tuple
[ndarray
|None
,ndarray
|None
]) – The coefficients of the linear combination. You can pass either a single Numpy array specifying the coefficients to apply to both spin sectors, or you can pass a pair of Numpy arrays specifying independent coefficients for spin alpha and spin beta. If passing a pair, you can useNone
for one of the values in the pair to indicate that no operation should be applied to that spin sector.time (
float
) – The evolution time.norb (
int
) – The number of spatial orbitals.nelec (
int
|tuple
[int
,int
]) – Either a single integer representing the number of fermions for a spinless system, or a pair of integers storing the numbers of spin alpha and spin beta fermions.orbital_rotation (
ndarray
|tuple
[ndarray
|None
,ndarray
|None
] |None
) – The optional orbital rotation. You can pass either a single Numpy array specifying the orbital rotation to apply to both spin sectors, or you can pass a pair of Numpy arrays specifying independent orbital rotations for spin alpha and spin beta. If passing a pair, you can useNone
for one of the values in the pair to indicate that no operation should be applied to that spin sector.copy (
bool
) –Whether to copy the vector before operating on it.
If copy=True then this function always returns a newly allocated vector and the original vector is left untouched.
If copy=False then this function may still return a newly allocated vector, but the original vector may have its data overwritten. It is also possible that the original vector is returned, modified in-place.
- Return type:
ndarray
- Returns:
The evolved state vector.
- ffsim.apply_on_site_interaction(vec, theta, target_orb, norb, nelec, *, copy=True)[source]¶
Apply an on-site interaction gate.
The on-site interaction gate is
\[\text{OS}(\theta, p) = \exp\left(i \theta a^\dagger_{\alpha, p} a_{\alpha, p} a^\dagger_{\beta, p} a_{\beta, p}\right)\]- Parameters:
vec (
ndarray
) – The state vector to be transformed.theta (
float
) – The rotation angle.target_orb (
int
) – The orbital on which to apply the interaction.norb (
int
) – The number of spatial orbitals.nelec (
tuple
[int
,int
]) – The number of alpha and beta electrons.copy (
bool
) –Whether to copy the vector before operating on it.
If copy=True then this function always returns a newly allocated vector and the original vector is left untouched.
If copy=False then this function may still return a newly allocated vector, but the original vector may have its data overwritten. It is also possible that the original vector is returned, modified in-place.
- ffsim.apply_orbital_rotation(vec, mat, norb, nelec, *, copy=True)[source]¶
Apply an orbital rotation to a vector.
An orbital rotation maps creation operators as
\[a^\dagger_{\sigma, i} \mapsto \sum_{j} U^{(\sigma)}_{ji} a^\dagger_{\sigma, j}\]where \(U^{(\sigma)}\) is a unitary matrix representing the action of the orbital rotation on spin sector \(\sigma\). This is equivalent to applying the transformation given by
\[\prod_{\sigma} \exp\left(\sum_{ij} \log(U^{(\sigma)})_{ij} a^\dagger_{\sigma, i} a_{\sigma, j}\right)\]- Parameters:
vec (
ndarray
) – The state vector to be transformed.mat (
ndarray
|tuple
[ndarray
|None
,ndarray
|None
]) – The unitary matrix \(U\) describing the orbital rotation. You can pass either a single Numpy array specifying the orbital rotation to apply to both spin sectors, or you can pass a pair of Numpy arrays specifying independent orbital rotations for spin alpha and spin beta. If passing a pair, you can useNone
for one of the values in the pair to indicate that no operation should be applied to that spin sector.norb (
int
) – The number of spatial orbitals.nelec (
int
|tuple
[int
,int
]) – Either a single integer representing the number of fermions for a spinless system, or a pair of integers storing the numbers of spin alpha and spin beta fermions.copy (
bool
) –Whether to copy the vector before operating on it.
If copy=True then this function always returns a newly allocated vector and the original vector is left untouched.
If copy=False then this function may still return a newly allocated vector, but the original vector may have its data overwritten. It is also possible that the original vector is returned, modified in-place.
- Return type:
ndarray
- Returns:
The rotated vector.
- ffsim.apply_tunneling_interaction(vec, theta, target_orbs, norb, nelec, spin=<Spin.ALPHA_AND_BETA: 3>, *, copy=True)[source]¶
Apply a tunneling interaction gate.
The tunneling interaction gate is
\[\text{T}(\theta, (p, q)) = \prod_\sigma \exp\left(i \theta (a^\dagger_{\sigma, p} a_{\sigma, q} + a^\dagger_{\sigma, q} a_{\sigma, p})\right)\]Under the Jordan-Wigner transform, this gate has the following matrix when applied to neighboring qubits:
\[\begin{split}\begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & \cos(\theta) & i \sin(\theta) & 0\\ 0 & i \sin(\theta) & \cos(\theta) & 0\\ 0 & 0 & 0 & 1 \\ \end{pmatrix}\end{split}\]- Parameters:
vec (
ndarray
) – The state vector to be transformed.theta (
float
) – The rotation angle.target_orbs (
tuple
[int
,int
]) – The orbitals (p, q) on which to apply the interaction.norb (
int
) – The number of spatial orbitals.nelec (
int
|tuple
[int
,int
]) – Either a single integer representing the number of fermions for a spinless system, or a pair of integers storing the numbers of spin alpha and spin beta fermions.spin (
Spin
) –Choice of spin sector(s) to act on.
To act on only spin alpha, pass
ffsim.Spin.ALPHA
.To act on only spin beta, pass
ffsim.Spin.BETA
.To act on both spin alpha and spin beta, pass
ffsim.Spin.ALPHA_AND_BETA
(this is the default value).
copy (
bool
) –Whether to copy the vector before operating on it.
If copy=True then this function always returns a newly allocated vector and the original vector is left untouched.
If copy=False then this function may still return a newly allocated vector, but the original vector may have its data overwritten. It is also possible that the original vector is returned, modified in-place.
- Return type:
ndarray
- ffsim.apply_unitary(vec, obj, norb, nelec, copy=True)[source]¶
Apply a unitary transformation to a vector.
- Parameters:
vec (
ndarray
) – The vector to apply the unitary transformation to.obj (
Any
) – The object with a unitary effect.norb (
int
) – The number of spatial orbitals.nelec (
int
|tuple
[int
,int
]) – Either a single integer representing the number of fermions for a spinless system, or a pair of integers storing the numbers of spin alpha and spin beta fermions.copy (
bool
) –Whether to copy the vector before operating on it.
If copy=True then this function always returns a newly allocated vector and the original vector is left untouched.
If copy=False then this function may still return a newly allocated vector, but the original vector may have its data overwritten. It is also possible that the original vector is returned, modified in-place.
- Return type:
ndarray
- Returns:
The transformed vector.
- ffsim.approx_eq(obj, other, rtol=1e-05, atol=1e-08)[source]¶
Return whether two objects are approximately equal.
See the documentation of np.isclose for the interpretation of the tolerance parameters
rtol
andatol
.- Parameters:
obj (
Any
) – The first object.other (
Any
) – The object to compare to.rtol (
float
) – Relative numerical tolerance.atol (
float
) – Absolute numerical tolerance.
- Return type:
bool
- Returns:
True if the objects are approximately equal up to the specified tolerance, and False otherwise.
- ffsim.cre(spin, orb)[source]¶
Create a fermion.
- Parameters:
spin (
bool
) – The spin of the orbital. False = alpha, True = beta.orb (
int
) – The index of the orbital to act on.
- Return type:
- ffsim.cre_a(orb)[source]¶
Create a fermion with spin alpha.
- Parameters:
orb (
int
) – The index of the orbital to act on.- Return type:
- ffsim.cre_b(orb)[source]¶
Create a fermion with spin beta.
- Parameters:
orb (
int
) – The index of the orbital to act on.- Return type:
- ffsim.des(spin, orb)[source]¶
Destroy a fermion.
- Parameters:
spin (
bool
) – The spin of the orbital. False = alpha, True = beta.orb (
int
) – The index of the orbital to act on.
- Return type:
- ffsim.des_a(orb)[source]¶
Destroy a fermion with spin alpha.
- Parameters:
orb (
int
) – The index of the orbital to act on.- Return type:
- ffsim.des_b(orb)[source]¶
Destroy a fermion with spin beta.
- Parameters:
orb (
int
) – The index of the orbital to act on.- Return type:
- ffsim.diag(obj, norb, nelec)[source]¶
Return the diagonal entries of the linear operator.
- Return type:
float
- ffsim.dim(norb, nelec)[source]¶
Get the dimension of the FCI space.
- Parameters:
norb (
int
) – The number of spatial orbitals.nelec (
int
|tuple
[int
,int
]) – Either a single integer representing the number of fermions for a spinless system, or a pair of integers storing the numbers of spin alpha and spin beta fermions.
- Return type:
int
- Returns:
The dimension of the FCI space.
- ffsim.dims(norb, nelec)[source]¶
Get the dimensions of the FCI space.
- Parameters:
norb (
int
) – The number of spatial orbitals.nelec (
tuple
[int
,int
]) – The number of alpha and beta electrons.
- Return type:
tuple
[int
,int
]- Returns:
A pair of integers (dim_a, dim_b) representing the dimensions of the alpha- and beta- FCI space.
- ffsim.expectation_one_body_power(one_rdm, one_body_tensor, power=1)[source]¶
Expectation of power of one-body operator w.r.t. a Slater determinant.
A one-body operator \(O\) has the form
\[O = \sum_{pq} M_{pq} a_p^\dagger a_q.\]This function takes the matrix \(M\) as its first argument. Let \(\lvert \psi \rangle\) be the Slater determinant. Then this function returns the quantity
\[\langle \psi \rvert O^k \lvert \psi \rangle.\]- Note: Unlike most functions in ffsim, the inputs to this function are specified
in terms of spin-orbitals, not spatial orbitals. In other words, the one-rdm and the one-body tensors should have the same shape, and all orbitals are treated on an equal footing. The 1-RDM passed here should not be spin-summed, and the one-body tensors should be expanded when compared to the usual one-body tensors elsewhere in ffsim, i.e., scipy.linalg.block_diag(one_body_tensor, one_body_tensor).
- Parameters:
one_rdm (
ndarray
) – The one-body reduced density matrix of the Slater determinant.one_body_tensor (
ndarray
) – The one-body operator.power (
int
) – The power.
- Return type:
complex
- Returns:
The expectation value.
- ffsim.expectation_one_body_product(one_rdm, one_body_tensors)[source]¶
Expectation of product of one-body operators w.r.t. a Slater determinant.
A one-body operator \(O\) has the form
\[O = \sum_{pq} M_{pq} a_p^\dagger a_q.\]This function takes a list of the matrices \(M\) as its first argument. Let \((O_1, O_2, \dots O_k)\) be the list of one-body operators, and \(\lvert \psi \rangle\) be the Slater determinant. Then this function returns the quantity
\[\langle \psi \rvert O_1 O_2 \dots O_k \lvert \psi \rangle.\]- Note: Unlike most functions in ffsim, the inputs to this function are specified
in terms of spin-orbitals, not spatial orbitals. In other words, the one-rdm and the one-body tensors should have the same shape, and all orbitals are treated on an equal footing. The 1-RDM passed here should not be spin-summed, and the one-body tensors should be expanded when compared to the usual one-body tensors elsewhere in ffsim, i.e., scipy.linalg.block_diag(one_body_tensor, one_body_tensor).
- Parameters:
one_rdm (
ndarray
) – The one-body reduced density matrix of the Slater determinant.one_body_tensors (
Sequence
[ndarray
]) – The matrices for the one-body operators.
- Return type:
complex
- Returns:
The expectation value.
- ffsim.fermi_hubbard_1d(norb, tunneling, interaction, *, chemical_potential=0, nearest_neighbor_interaction=0, periodic=False)[source]¶
One-dimensional Fermi-Hubbard model Hamiltonian.
The Hamiltonian for the one-dimensional Fermi-Hubbard model with \(N\) spatial orbitals is given by
\[H = -t \sum_{\sigma, \braket{pq}} (a^\dagger_{\sigma, p} a_{\sigma, q} + a^\dagger_{\sigma, q} a_{\sigma, p}) + U \sum_p n_{\alpha, p} n_{\beta, p} - \mu \sum_p (n_{\alpha, p} + n_{\beta, p}) + V \sum_{\sigma \tau, \braket{pq}} n_{\sigma, p} n_{\tau, q}\]where \(n_{\sigma, p} = a_{\sigma, p}^\dagger a_{\sigma, p}\) is the number operator on orbital \(p\) with spin \(\sigma\) and the index \(\braket{pq}\) runs over pairs of orbitals \(p\) and \(q\) that are connected on the line. If periodic boundary conditions are chosen, then the first and last orbitals are connected. More explicitly:
For open boundary conditions, \(\braket{pq}\) runs over pairs \((p, p + 1)\) for \(p = 1, \ldots, N - 1\).
For periodic boundary conditions, \(\braket{pq}\) runs over pairs \((p, p + 1 \bmod N)\) for \(p = 1, \ldots, N\).
In the case that \(N = 2\), using periodic boundary conditions will cause the connection between the two vertices to be counted twice, forming a “ring with two edges”.
References
- Parameters:
norb (
int
) – The number of spatial orbitals \(N\).tunneling (
float
) – The tunneling amplitude \(t\).interaction (
float
) – The onsite interaction strength \(U\).chemical_potential (
float
) – The chemical potential \(\mu\).nearest_neighbor_interaction (
float
) – The nearest-neighbor interaction strength \(V\).periodic (
bool
) – Whether to use periodic boundary conditions.
- Return type:
- Returns:
The one-dimensional Fermi-Hubbard model Hamiltonian.
- ffsim.fermi_hubbard_2d(norb_x, norb_y, tunneling, interaction, *, chemical_potential=0, nearest_neighbor_interaction=0, periodic=False, periodic_x=False, periodic_y=False)[source]¶
Two-dimensional Fermi-Hubbard model Hamiltonian on a square lattice.
The Hamiltonian for the two-dimensional Fermi-Hubbard model on a square lattice with \(N_x\) columns and \(N_y\) rows is given by
\[H = -t \sum_{\sigma, \braket{pq}} (a^\dagger_{\sigma, p} a_{\sigma, q} + a^\dagger_{\sigma, q} a_{\sigma, p}) + U \sum_p n_{\alpha, p} n_{\beta, p} - \mu \sum_p (n_{\alpha, p} + n_{\beta, p}) + V \sum_{\sigma \tau, \braket{pq}} n_{\sigma, p} n_{\tau, q}\]where \(n_{\sigma, p} = a_{\sigma, p}^\dagger a_{\sigma, p}\) is the number operator on orbital \(p\) with spin \(\sigma\) and the index \(\braket{pq}\) runs over pairs of orbitals \(p\) and \(q\) that are connected on the lattice. If periodic boundary conditions are chosen, then orbitals in the first and last columns are connected, as are orbitals in the first and last rows, so that the square lattice forms a torus. In the case that one of the dimensions has size 2, using periodic boundary conditions will cause the connection along that dimension to be counted twice.
References
- Parameters:
norb_x (
int
) – The number of spatial orbitals in the x-direction \(N_x\).norb_y (
int
) – The number of spatial orbitals in the y-direction \(N_y\).tunneling (
float
) – The tunneling amplitude \(t\).interaction (
float
) – The onsite interaction strength \(U\).chemical_potential (
float
) – The chemical potential \(\mu\).nearest_neighbor_interaction (
float
) – The nearest-neighbor interaction strength \(V\).periodic (
bool
) – Whether to use periodic boundary conditions in all dimensions. This argument overrides the periodic_x and periodic_y arguments.periodic_x (
bool
) – Whether to use periodic boundary conditions in the X dimension.periodic_y (
bool
) – Whether to use periodic boundary conditions in the Y dimension.
- Return type:
- Returns:
The two-dimensional Fermi-Hubbard model Hamiltonian.
- ffsim.fermion_operator(obj)[source]¶
Return a FermionOperator representing the object.
- Parameters:
obj (
Any
) – The object to convert to a LinearOperator.- Return type:
- Returns:
A FermionOperator representing the object.
- ffsim.hartree_fock_state(norb, nelec)[source]¶
Return the Hartree-Fock state.
- Parameters:
norb (
int
) – The number of spatial orbitals.nelec (
int
|tuple
[int
,int
]) – Either a single integer representing the number of fermions for a spinless system, or a pair of integers storing the numbers of spin alpha and spin beta fermions.
- Return type:
ndarray
- Returns:
The Hartree-Fock state as a state vector.
- ffsim.indices_to_strings(indices, norb, nelec, concatenate=True, bitstring_type=BitstringType.STRING)[source]¶
Convert state vector indices to bitstrings.
Warning
This function is deprecated. Use
ffsim.addresses_to_strings
instead.Example:
import ffsim norb = 3 nelec = (2, 1) dim = ffsim.dim(norb, nelec) ffsim.indices_to_strings(range(dim), norb, nelec) # output: # ['001011', # '010011', # '100011', # '001101', # '010101', # '100101', # '001110', # '010110', # '100110']
- Parameters:
indices (
Sequence
[int
] |ndarray
) – The state vector indices to convert to bitstrings.norb (
int
) – The number of spatial orbitals.nelec (
int
|tuple
[int
,int
]) – Either a single integer representing the number of fermions for a spinless system, or a pair of integers storing the numbers of spin alpha and spin beta fermions.bitstring_type (
BitstringType
) – The desired type of bitstring output.concatenate (
bool
) – Whether to concatenate the spin-alpha and spin-beta parts of the bitstrings. If True, then a single list of concatenated bitstrings is returned. The strings are concatenated in the order \(s_b s_a\), that is, the alpha string appears on the right. If False, then two lists are returned,(strings_a, strings_b)
. Note that the list of alpha strings appears first, that is, on the left. In the spinless case (when nelec is an integer), this argument is ignored.
- ffsim.init_cache(norb, nelec)[source]¶
Initialize cached objects.
Call this function to prepare ffsim for performing operations with given values of norb and nelec. Typically there is no need to call this function, but it should be called before benchmarking to avoid counting the cost of initializing cached lookup tables.
- Parameters:
norb (
int
) – The number of spatial orbitals.nelec (
tuple
[int
,int
]) – The number of alpha and beta electrons.
- Return type:
None
- ffsim.linear_operator(obj, norb, nelec)[source]¶
Return a SciPy LinearOperator representing the object.
- Parameters:
obj (
Any
) – The object to convert to a LinearOperator.norb (
int
) – The number of spatial orbitals.nelec (
tuple
[int
,int
]) – The number of alpha and beta electrons.
- Return type:
LinearOperator
- Returns:
A Scipy LinearOperator representing the object.
- ffsim.multireference_state(hamiltonian, ansatz_operator, reference_occupations, norb, nelec, root=0)[source]¶
Compute multireference energy and state.
- Parameters:
hamiltonian (
LinearOperator
|SupportsLinearOperator
) – The Hamiltonian.ansatz_operator (
SupportsApplyUnitary
) – The ansatz operator.reference_occupations (
Sequence
[tuple
[Sequence
[int
],Sequence
[int
]]]) – The orbital occupations of the reference states.norb (
int
) – The number of spatial orbitals.nelec (
tuple
[int
,int
]) – The number of alpha and beta electrons.root (
int
) – The index of the desired eigenvector. Defaults to 0, which yields the lowest-energy state.
- Return type:
tuple
[float
,ndarray
]- Returns:
The energy of the multireference state, and the state itself.
- ffsim.multireference_state_prod(hamiltonian, ansatz_operator, reference_occupations, norb, nelec, root=0, tol=1e-08)[source]¶
Compute multireference state for a product ansatz operator.
- Parameters:
hamiltonian (
MolecularHamiltonian
|SingleFactorizedHamiltonian
) – The Hamiltonian.ansatz_operator (
tuple
[SupportsApplyUnitary
,SupportsApplyUnitary
]) – The alpha and beta parts of the ansatz operator.reference_occupations (
Sequence
[tuple
[Sequence
[int
],Sequence
[int
]]]) – The orbital occupations of the reference states.norb (
int
) – The number of spatial orbitals.nelec (
tuple
[int
,int
]) – The number of alpha and beta electrons.root (
int
) – The index of the desired eigenvector. Defaults to 0, which yields the lowest-energy state.tol (
float
) – Numerical tolerance to use for the single factorization of the molecular Hamiltonian. If the input is already a SingleFactorizedHamiltonian, this argument is ignored.
- Return type:
tuple
[float
,ProductStateSum
]- Returns:
The energy of the multireference state, and the state itself.
- ffsim.number_operator(orb, spin=<Spin.ALPHA_AND_BETA: 3>)[source]¶
Occupation number operator.
The occupation number operator for orbital \(p\) is defined as
\[n_p = \sum_\sigma a^\dagger_{\sigma, p} a_{\sigma, p}\]- Parameters:
orb (
int
) – The orbital.spin (
Spin
) –Choice of spin sector(s) to act on.
To act on only spin alpha, pass
ffsim.Spin.ALPHA
.To act on only spin beta, pass
ffsim.Spin.BETA
.To act on both spin alpha and spin beta, pass
ffsim.Spin.ALPHA_AND_BETA
(this is the default value).
- Return type:
- Returns:
The number operator acting on the specified orbital and spin sector(s).
- ffsim.one_hot(shape, index, *, dtype=<class 'complex'>)[source]¶
Return an array of all zeros except for a one at a specified index.
Warning
This function is deprecated. Use
ffsim.linalg.one_hot()
instead.- Parameters:
shape (
int
|tuple
[int
,...
]) – The desired shape of the array.index – The index at which to place a one.
- Returns:
The one-hot vector.
- ffsim.rdm(vec, norb, nelec, rank=1, spin_summed=True, reordered=True, return_lower_ranks=True)[source]¶
Return the reduced density matrix (RDM) or matrices of a state vector.
Warning
This function is deprecated. Use
ffsim.rdms()
instead.The rank 1 RDM is defined as follows:
rdm1[p, q] = ⟨p+ q⟩
The definition of higher-rank RDMs depends on the
reordered
argument, which defaults to True.reordered = True
The reordered RDMs are defined as follows:
rdm2[p, q, r, s] = ⟨p+ r+ s q⟩ rdm3[p, q, r, s, t, u] = ⟨p+ r+ t+ u s q⟩ rdm4[p, q, r, s, t, u, v, w] = ⟨p+ r+ t+ v+ w u s q⟩
reordered = False
If reordered is set to False, the RDMs are defined as follows:
rdm2[p, q, r, s] = ⟨p+ q r+ s⟩ rdm3[p, q, r, s, t, u] = ⟨p+ q r+ s t+ u⟩ rdm4[p, q, r, s, t, u, v, w] = ⟨p+ q r+ s t+ u v+ w⟩
Note
Currently, only ranks 1 and 2 are supported.
- Parameters:
vec (
ndarray
) – The state vector whose reduced density matrix is desired.norb (
int
) – The number of spatial orbitals.nelec (
tuple
[int
,int
]) – The number of alpha and beta electrons.rank (
int
) – The rank of the reduced density matrix.spin_summed (
bool
) – Whether to sum over the spin index.reordered (
bool
) – Whether to reorder the indices of the reduced density matrix.return_lower_ranks (
bool
) – Whether to return lower rank RDMs in addition to the specified rank. If True, then this function returns all RDMs up to and including the specified rank, in increasing order of rank. For example, if rank=2 then a tuple (rdm1, rdm2) is returned.
- Return type:
ndarray
|tuple
[ndarray
,...
]- Returns:
The reduced density matrix or matrices. If return_lower_ranks is False, then a single matrix is returned. If return_lower_ranks is True, then a rank-length tuple of matrices is returned, containing the RDMs up to the specified rank in increasing order of rank.
- ffsim.rdms(vec, norb, nelec, *, rank=1, spin_summed=False, reorder=True)[source]¶
Return the spin-separated reduced density matrices of a state vector.
The rank 1 RDM is defined as follows:
rdm1[p, q] = ⟨p+ q⟩
The definition of higher-rank RDMs depends on the
reorder
argument, which defaults to True.reorder = True
The reordered RDMs are defined as follows:
rdm2[p, q, r, s] = ⟨p+ r+ s q⟩ rdm3[p, q, r, s, t, u] = ⟨p+ r+ t+ u s q⟩ rdm4[p, q, r, s, t, u, v, w] = ⟨p+ r+ t+ v+ w u s q⟩
reorder = False
If reorder is set to False, the RDMs are defined as follows:
rdm2[p, q, r, s] = ⟨p+ q r+ s⟩ rdm3[p, q, r, s, t, u] = ⟨p+ q r+ s t+ u⟩ rdm4[p, q, r, s, t, u, v, w] = ⟨p+ q r+ s t+ u v+ w⟩
Note
Currently, only ranks 1 and 2 are supported.
- Parameters:
vec (
ndarray
) – The state vector whose reduced density matrix is desired.norb (
int
) – The number of spatial orbitals.nelec (
tuple
[int
,int
]) – The number of alpha and beta electrons.rank (
int
) – The rank of the reduced density matrix.spin_summed (
bool
) – Whether to return the “spin-summed” RDMs.reorder (
bool
) – Whether to reorder the indices of the reduced density matrix.
- Return type:
ndarray
|tuple
[ndarray
,...
]- Returns:
The reduced density matrices. All RDMs up to and including the specified rank are returned, in increasing order of rank. For example, if rank=2 then a tuple (rdm1, rdm2) is returned. The 1-RDMs are: (alpha-alpha, beta-beta). The spin-summed 1-RDM is alpha-alpha + alpha-beta. The 2-RDMs are: (alpha-alpha, alpha-beta, beta-beta). The spin-summed 2-RDM is alpha-alpha + alpha-beta + beta-alpha + beta-beta.
- ffsim.sample_slater_determinant(rdm, norb, nelec, *, orbs=None, shots=1, concatenate=True, bitstring_type=BitstringType.STRING, seed=None)[source]¶
Collect samples of electronic configurations from a Slater determinant.
The Slater determinant is defined by its one-body reduced density matrix (RDM). The sampler uses a determinantal point process to auto-regressively produce uncorrelated samples.
This sampling strategy is known as determinantal point processes <https://arxiv.org/abs/1207.6083>
- Parameters:
rdm (
ndarray
|tuple
[ndarray
,ndarray
]) – The one-body reduced density matrix that defines the Slater determinant This is either a single Numpy array specifying the 1-RDM of a spin-polarized system, or a pair of Numpy arrays where each element of the pair contains the 1-RDM for each spin sector.norb (
int
) – The number of spatial orbitals.nelec (
int
|tuple
[int
,int
]) – Either a single integer representing the number of fermions for a spinless system, or a pair of integers storing the numbers of spin alpha and spin beta fermions.shots (
int
) – The number of bitstrings to sample.concatenate (
bool
) – Whether to concatenate the spin-alpha and spin-beta parts of the bitstrings. If True, then a single list of concatenated bitstrings is returned. The strings are concatenated in the order \(s_b s_a\), that is, the alpha string appears on the right. If False, then two lists are returned,(strings_a, strings_b)
. Note that the list of alpha strings appears first, that is, on the left. In the spinless case (when nelec is an integer), this argument is ignored.bitstring_type (
BitstringType
) – The desired type of bitstring output.seed (
Generator
|int
|None
) – A seed to initialize the pseudorandom number generator. Should be a valid input tonp.random.default_rng
.
- Return type:
Sequence
[int
] |Sequence
[str
] |ndarray
- Returns:
A 2D Numpy array with samples of electronic configurations. Each row is a sample.
- ffsim.sample_state_vector(vec, *, norb=None, nelec=None, orbs=None, shots=1, concatenate=True, bitstring_type=BitstringType.STRING, seed=None)[source]¶
Sample bitstrings from a state vector.
- Parameters:
vec (
ndarray
|StateVector
) – The state vector to sample from.norb (
int
|None
) – The number of spatial orbitals.nelec (
int
|tuple
[int
,int
] |None
) – Either a single integer representing the number of fermions for a spinless system, or a pair of integers storing the numbers of spin alpha and spin beta fermions.orbs (
Sequence
[int
] |tuple
[Sequence
[int
],Sequence
[int
]] |None
) – The spin-orbitals to sample. In the spinless case (when nelec is an integer), this is a list of integers ranging from0
tonorb
. In the spinful case, this is a pair of lists of such integers, with the first list storing the spin-alpha orbitals and the second list storing the spin-beta orbitals. If not specified, then all spin-orbitals are sampled.shots (
int
) – The number of bitstrings to sample.concatenate (
bool
) – Whether to concatenate the spin-alpha and spin-beta parts of the bitstrings. If True, then a single list of concatenated bitstrings is returned. The strings are concatenated in the order \(s_b s_a\), that is, the alpha string appears on the right. If False, then two lists are returned,(strings_a, strings_b)
. Note that the list of alpha strings appears first, that is, on the left. In the spinless case (when nelec is an integer), this argument is ignored.bitstring_type (
BitstringType
) – The desired type of bitstring output.seed (
Generator
|int
|None
) – A seed to initialize the pseudorandom number generator. Should be a valid input tonp.random.default_rng
.
- Returns:
The sampled bitstrings, as a list of strings of length shots.
- Raises:
TypeError – When passing vec as a Numpy array, norb and nelec must be specified.
TypeError – When passing vec as a StateVector, norb and nelec must both be None.
- ffsim.simulate_qdrift_double_factorized(vec, hamiltonian, time, *, norb, nelec, n_steps=1, symmetric=False, probabilities='norm', one_rdm=None, n_samples=1, seed=None)[source]¶
Double-factorized Hamiltonian simulation via qDRIFT.
- Parameters:
vec (
ndarray
) – The state vector to evolve.hamiltonian (
DoubleFactorizedHamiltonian
) – The Hamiltonian.time (
float
) – The evolution time.nelec (
tuple
[int
,int
]) – The number of alpha and beta electrons.n_steps (
int
) – The number of Trotter steps.probabilities (
str
|ndarray
) – The sampling method to use, or else an explicit array of probabilities. If specifying a string, the following options are supported: - “norm”: Sample each term with probability proportional to its spectral norm. - “uniform”: Sample each term with uniform probability. - “optimal”: Sample with probabilities optimized for a given initial state. The “optimal” method requires the one-body reduced density matrix of the initial state to be specified. It returns optimal probabilities whenever the initial state is completely characterized by this reduced density matrix, i.e., it is a Slater determinant.one_rdm (
ndarray
|None
) – The one-body reduced density matrix of the initial state.n_samples (
int
) – The number of qDRIFT trajectories to sample.seed – A seed to initialize the pseudorandom number generator. Should be a valid input to
np.random.default_rng
.
- Return type:
ndarray
- Returns:
A Numpy array representing the final state of the simulation. The shape of the array depends on the
n_samples
argument. Ifn_samples=1
then it is just a state vector, a one-dimensional array. Otherwise, it is a two-dimensional array of shape(n_samples, dim)
wheredim
is the dimension of the state vector.
- ffsim.simulate_trotter_diag_coulomb_split_op(vec, hamiltonian, time, *, norb, nelec, n_steps=1, order=0, copy=True)[source]¶
Diagonal Coulomb Hamiltonian simulation using split-operator method.
- Parameters:
vec (
ndarray
) – The state vector to evolve.hamiltonian (
DiagonalCoulombHamiltonian
) – The Hamiltonian.time (
float
) – The evolution time.norb (
int
) – The number of spatial orbitals.nelec (
tuple
[int
,int
]) – The number of alpha and beta electrons.n_steps (
int
) – The number of Trotter steps.order (
int
) – The order of the Trotter decomposition.copy (
bool
) –Whether to copy the vector before operating on it.
If copy=True then this function always returns a newly allocated vector and the original vector is left untouched.
If copy=False then this function may still return a newly allocated vector, but the original vector may have its data overwritten. It is also possible that the original vector is returned, modified in-place.
- Return type:
ndarray
- Returns:
The final state of the simulation.
- ffsim.simulate_trotter_double_factorized(vec, hamiltonian, time, *, norb, nelec, n_steps=1, order=0, copy=True)[source]¶
Double-factorized Hamiltonian simulation using Trotter-Suzuki formula.
- Parameters:
vec (
ndarray
) – The state vector to evolve.hamiltonian (
DoubleFactorizedHamiltonian
) – The Hamiltonian.time (
float
) – The evolution time.norb (
int
) – The number of spatial orbitals.nelec (
tuple
[int
,int
]) – The number of alpha and beta electrons.n_steps (
int
) – The number of Trotter steps.order (
int
) – The order of the Trotter decomposition.copy (
bool
) –Whether to copy the vector before operating on it.
If copy=True then this function always returns a newly allocated vector and the original vector is left untouched.
If copy=False then this function may still return a newly allocated vector, but the original vector may have its data overwritten. It is also possible that the original vector is returned, modified in-place.
- Return type:
ndarray
- Returns:
The final state of the simulation.
- ffsim.slater_determinant(norb, occupied_orbitals, orbital_rotation=None)[source]¶
Return a Slater determinant.
A Slater determinant is a state of the form
\[\mathcal{U} \lvert x \rangle,\]where \(\mathcal{U}\) is an orbital rotation and \(\lvert x \rangle\) is an electronic configuration.
- Parameters:
norb (
int
) – The number of spatial orbitals.occupied_orbitals (
Sequence
[int
] |tuple
[Sequence
[int
],Sequence
[int
]]) – The occupied orbitals in the electronic configuration. This is either a list of integers specifying spinless orbitals, or a pair of lists, where the first list specifies the spin alpha orbitals and the second list specifies the spin beta orbitals.orbital_rotation (
ndarray
|tuple
[ndarray
|None
,ndarray
|None
] |None
) – The optional orbital rotation. You can pass either a single Numpy array specifying the orbital rotation to apply to both spin sectors, or you can pass a pair of Numpy arrays specifying independent orbital rotations for spin alpha and spin beta. If passing a pair, you can useNone
for one of the values in the pair to indicate that no operation should be applied to that spin sector.
- Return type:
ndarray
- Returns:
The Slater determinant as a state vector.
- ffsim.slater_determinant_rdm(norb, occupied_orbitals, orbital_rotation=None, rank=1, spin_summed=True)[source]¶
Return the reduced density matrix of a Slater determinant.
Warning
This function is deprecated. Use
ffsim.slater_determinant_rdms()
instead.Note
Currently, only rank 1 is supported.
- Parameters:
norb (
int
) – The number of spatial orbitals.occupied_orbitals (
tuple
[Sequence
[int
],Sequence
[int
]]) – The occupied orbitals in the electronic configuration. This is a pair of lists of integers, where the first list specifies the spin alpha orbitals and the second list specifies the spin beta orbitals.orbital_rotation (
ndarray
|tuple
[ndarray
|None
,ndarray
|None
] |None
) – The optional orbital rotation. You can pass either a single Numpy array specifying the orbital rotation to apply to both spin sectors, or you can pass a pair of Numpy arrays specifying independent orbital rotations for spin alpha and spin beta. If passing a pair, you can useNone
for one of the values in the pair to indicate that no operation should be applied to that spin sector.rank (
int
) – The rank of the reduced density matrix. I.e., rank 1 corresponds to the one-particle RDM, rank 2 corresponds to the 2-particle RDM, etc.spin_summed (
bool
) – Whether to sum over the spin index.
- Return type:
ndarray
- Returns:
The reduced density matrix of the Slater determinant.
- ffsim.slater_determinant_rdms(norb, occupied_orbitals, orbital_rotation=None, *, rank=1)[source]¶
Return the reduced density matrices of a Slater determinant.
Note
Currently, only rank 1 is supported.
- Parameters:
norb (
int
) – The number of spatial orbitals.occupied_orbitals (
Sequence
[int
] |tuple
[Sequence
[int
],Sequence
[int
]]) – The occupied orbitals in the electronic configuration. This is either a list of integers specifying spinless orbitals, or a pair of lists, where the first list specifies the spin alpha orbitals and the second list specifies the spin beta orbitals.orbital_rotation (
ndarray
|tuple
[ndarray
|None
,ndarray
|None
] |None
) – The optional orbital rotation. You can pass either a single Numpy array specifying the orbital rotation to apply to both spin sectors, or you can pass a pair of Numpy arrays specifying independent orbital rotations for spin alpha and spin beta. If passing a pair, you can useNone
for one of the values in the pair to indicate that no operation should be applied to that spin sector.rank (
int
) – The rank of the reduced density matrix. I.e., rank 1 corresponds to the one-particle RDM, rank 2 corresponds to the 2-particle RDM, etc.
- Return type:
ndarray
- Returns:
The reduced density matrices of the Slater determinant. All RDMs up to and including the specified rank are returned, in increasing order of rank. For example, if rank=2 then a tuple (rdm1, rdm2) is returned. The representation of an RDM depends on whether occupied_orbitals is a sequence of integers (spinless case), or a pair of such sequences (spinful case). In the spinless case, the full RDM is returned. In the spinful case, each RDM is represented as a stacked Numpy array of sub-RDMs. For example, the 1-RDMs are: (alpha-alpha, alpha-beta), and the 2-RDMs are: (alpha-alpha, alpha-beta, beta-beta).
- ffsim.spin_square(fcivec, norb, nelec)[source]¶
Expectation value of spin squared operator on a state vector.
- ffsim.strings_to_addresses(strings, norb, nelec)[source]¶
Convert bitstrings to state vector addresses.
Example:
import numpy as np import ffsim norb = 3 nelec = (2, 1) dim = ffsim.dim(norb, nelec) addresses = ffsim.strings_to_addresses( [ 0b001011, 0b010101, 0b100101, 0b010110, 0b100110, ], norb, nelec, ) print(addresses) # prints [0 4 5 7 8] addresses = ffsim.strings_to_addresses( [ "001011", "010101", "100101", "010110", "100110", ], norb, nelec, ) print(addresses) # prints [0 4 5 7 8] addresses = ffsim.strings_to_addresses( np.array( [ [False, False, True, False, True, True], [False, True, False, True, False, True], [True, False, False, True, False, True], [False, True, False, True, True, False], [True, False, False, True, True, False], ] ), norb, nelec, ) print(addresses) # prints [0 4 5 7 8]
- Parameters:
strings (
Sequence
[int
] |Sequence
[str
] |ndarray
) – The bitstrings to convert to state vector addresses. Can be a list of strings, a list of integers, or a Numpy array of bits.norb (
int
) – The number of spatial orbitals.nelec (
int
|tuple
[int
,int
]) – Either a single integer representing the number of fermions for a spinless system, or a pair of integers storing the numbers of spin alpha and spin beta fermions.
- Return type:
ndarray
- Returns:
The state vector addresses, as a Numpy array of integers.
- ffsim.strings_to_indices(strings, norb, nelec)[source]¶
Convert bitstrings to state vector indices. :rtype:
ndarray
Warning
This function is deprecated. Use
ffsim.strings_to_addresses
instead.Example:
import ffsim norb = 3 nelec = (2, 1) dim = ffsim.dim(norb, nelec) ffsim.strings_to_indices( [ "001011", "010011", "100011", "001101", "010101", "100101", "001110", "010110", "100110", ], norb, nelec, ) # output: # array([0, 1, 2, 3, 4, 5, 6, 7, 8], dtype=int32)