ffsim.qiskit

Code that uses Qiskit, e.g. for constructing quantum circuits.

class ffsim.qiskit.DiagCoulombEvolutionJW(norb, mat, time, *, z_representation=False, label=None)[source]

Bases: Gate

Diagonal Coulomb evolution under the Jordan-Wigner transformation.

The diagonal Coulomb evolution gate has the unitary

\[\exp\left(-i t \sum_{\sigma, \tau, i, j} Z^{(\sigma \tau)}_{ij} n_{\sigma, i} n_{\tau, j} / 2\right)\]

where \(n_{\sigma, i}\) denotes the number operator on orbital \(i\) with spin \(\sigma\), \(Z^{(\sigma \tau)}\) is a real-valued matrix.

This gate assumes that qubits are ordered such that the first norb qubits correspond to the alpha orbitals and the last norb qubits correspond to the beta orbitals.

__init__(norb, mat, time, *, z_representation=False, label=None)[source]

Create new diagonal Coulomb evolution gate.

Parameters:
  • norb (int) – The number of spatial orbitals.

  • 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 to None 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.

  • z_representation (bool) – Whether the input matrices are in the “Z” representation.

  • label (str | None) – The label of the gate.

inverse()[source]

Inverse gate.

class ffsim.qiskit.DiagCoulombEvolutionSpinlessJW(norb, mat, time, *, label=None)[source]

Bases: Gate

Spinless diagonal Coulomb evolution under the Jordan-Wigner transformation.

The spinless diagonal Coulomb evolution gate has the unitary

\[\exp\left(-i t \sum_{i, j} Z^{ij} n_i n_j / 2\right)\]

where \(n_i\) denotes the number operator on orbital \(i\) and \(Z\) is a real symmetric matrix.

__init__(norb, mat, time, *, label=None)[source]

Create new diagonal Coulomb evolution gate.

Parameters:
  • norb (int) – The number of spatial orbitals.

  • mat (ndarray) – The diagonal Coulomb matrix \(Z\). It is assumed to be symmetric, and only its upper triangular entries are used.

  • time (float) – The evolution time.

  • label (str | None) – The label of the gate.

inverse()[source]

Inverse gate.

class ffsim.qiskit.DropNegligible(atol=1e-08)[source]

Bases: TransformationPass

Drop gates with negligible effects.

__init__(atol=1e-08)[source]

Initialize the transpiler pass.

Parameters:

atol (float) – Absolute numerical tolerance for determining whether a gate’s effect is negligible.

run(dag)[source]

Run a pass on the DAGCircuit. This is implemented by the pass developer.

Parameters:

dag (DAGCircuit) – the dag on which the pass is run.

Raises:

NotImplementedError – when this is left unimplemented for a pass.

Return type:

DAGCircuit

class ffsim.qiskit.FfsimSampler(*, default_shots=1024, seed=None)[source]

Bases: BaseSamplerV2

Implementation of the Qiskit Sampler primitive backed by ffsim.

__init__(*, default_shots=1024, seed=None)[source]

Initialize the ffsim sampler.

Parameters:
  • default_shots (int) – The default shots to use if not specified during run.

  • seed (Generator | int | None) – A seed to initialize the pseudorandom number generator. Should be a valid input to np.random.default_rng.

run(pubs, *, shots=None)[source]

Run and collect samples from each pub.

Parameters:
  • pubs (Iterable[Union[QuantumCircuit, Tuple[QuantumCircuit], Tuple[QuantumCircuit, Mapping[Union[Parameter, str, Tuple[Union[Parameter, str], ...]], Union[Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]]]], Tuple[QuantumCircuit, Mapping[Union[Parameter, str, Tuple[Union[Parameter, str], ...]], Union[Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[bool | int | float | complex | str | bytes]]], Optional[Integral]]]]) – An iterable of pub-like objects. For example, a list of circuits or tuples (circuit, parameter_values).

  • shots (int | None) – The total number of shots to sample for each sampler pub that does not specify its own shots. If None, the primitive’s default shots value will be used, which can vary by implementation.

Return type:

PrimitiveJob[PrimitiveResult[SamplerPubResult]]

Returns:

The job object of Sampler’s result.

class ffsim.qiskit.GivensAnsatzOpJW(givens_ansatz_op, *, label=None)[source]

Bases: Gate

Givens rotation ansatz operator under the Jordan-Wigner transformation.

See ffsim.GivensAnsatzOp for a description of this gate’s unitary.

__init__(givens_ansatz_op, *, label=None)[source]

Create a new Givens ansatz operator gate.

Parameters:
  • givens_ansatz_op (GivensAnsatzOp) – The Givens rotation ansatz operator.

  • label (str | None) – The label of the gate.

class ffsim.qiskit.GivensAnsatzOpSpinlessJW(givens_ansatz_op, *, label=None)[source]

Bases: Gate

Spinless Givens rotation ansatz operator under the Jordan-Wigner transformation.

Like GivensAnsatzOpJW but only acts on a single spin species.

__init__(givens_ansatz_op, *, label=None)[source]

Create a new Givens ansatz operator gate.

Parameters:
  • givens_ansatz_op (GivensAnsatzOp) – The Givens rotation ansatz operator.

  • label (str | None) – The label of the gate.

class ffsim.qiskit.GivensAnsatzOperatorJW(givens_ansatz_operator, *, label=None)[source]

Bases: Gate

Givens rotation ansatz operator under the Jordan-Wigner transformation.

Warning

This class is deprecated. Use ffsim.qiskit.GivensAnsatzOpJW instead.

See ffsim.GivensAnsatzOperator for a description of this gate’s unitary.

__init__(givens_ansatz_operator, *, label=None)[source]

Create a new Givens ansatz operator gate.

Parameters:
  • givens_ansatz_operator (GivensAnsatzOperator) – The Givens rotation ansatz operator.

  • label (str | None) – The label of the gate.

__init_subclass__()

This method is called when a class is subclassed.

The default implementation does nothing. It may be overridden to extend subclasses.

static __new__(*args, **kwargs)
class ffsim.qiskit.GivensAnsatzOperatorSpinlessJW(givens_ansatz_operator, *, label=None)[source]

Bases: Gate

Givens rotation ansatz operator under the Jordan-Wigner transformation, spinless.

Like GivensAnsatzOperatorJW but only acts on a single spin species.

__init__(givens_ansatz_operator, *, label=None)[source]

Create a new Givens ansatz operator gate.

Parameters:
  • givens_ansatz_operator (GivensAnsatzOperator) – The Givens rotation ansatz operator.

  • label (str | None) – The label of the gate.

__init_subclass__()

This method is called when a class is subclassed.

The default implementation does nothing. It may be overridden to extend subclasses.

static __new__(*args, **kwargs)
class ffsim.qiskit.MergeOrbitalRotations(*args, **kwargs)[source]

Bases: TransformationPass

Merge consecutive orbital rotation gates.

run(dag)[source]

Run a pass on the DAGCircuit. This is implemented by the pass developer.

Parameters:

dag (DAGCircuit) – the dag on which the pass is run.

Raises:

NotImplementedError – when this is left unimplemented for a pass.

Return type:

DAGCircuit

class ffsim.qiskit.NumNumAnsatzOpSpinBalancedJW(num_num_ansatz_op, *, label=None)[source]

Bases: Gate

Spin-balanced number-number ansatz under the Jordan-Wigner transformation.

See NumNumAnsatzOpSpinBalanced for a description of this gate’s unitary.

This gate assumes that qubits are ordered such that the first norb qubits correspond to the alpha orbitals and the last norb qubits correspond to the beta orbitals.

__init__(num_num_ansatz_op, *, label=None)[source]

Create a new number-number ansatz operator gate.

Parameters:
  • num_num_ansatz_op (NumNumAnsatzOpSpinBalanced) – The number-number ansatz operator.

  • label (str | None) – The label of the gate.

class ffsim.qiskit.NumOpSumEvolutionJW(norb, coeffs, time, *, label=None)[source]

Bases: Gate

Number operator sum evolution under the Jordan-Wigner transformation.

The number operator sum evolution gate has the unitary

\[\exp\left(-i t \sum_{\sigma, i} \lambda^{(\sigma)}_i n_{\sigma, i}\right)\]

where \(n_{\sigma, i}\) denotes the number operator on orbital \(i\) with spin \(\sigma\) and the \(\lambda_i\) are real numbers.

This gate assumes that qubits are ordered such that the first norb qubits correspond to the alpha orbitals and the last norb qubits correspond to the beta orbitals.

__init__(norb, coeffs, time, *, label=None)[source]

Create new number operator sum evolution gate.

Parameters:
  • norb (int) – The number of spatial orbitals.

  • 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 use None 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.

  • label (str | None) – The label of the gate.

inverse()[source]

Inverse gate.

class ffsim.qiskit.NumOpSumEvolutionSpinlessJW(norb, coeffs, time, *, label=None)[source]

Bases: Gate

Spinless number operator sum evolution under the Jordan-Wigner transformation.

The spinless number operator sum evolution gate has the unitary

\[\exp\left(-i t \sum_{i} \lambda_i n_{i}\right)\]

where \(n_i\) denotes the number operator on orbital \(i\) and the \(\lambda_i\) are real numbers.

__init__(norb, coeffs, time, *, label=None)[source]

Create new number operator sum evolution gate.

Parameters:
  • norb (int) – The number of spatial orbitals.

  • coeffs (ndarray) – The coefficients of the linear combination.

  • time (float) – The evolution time.

  • label (str | None) – The label of the gate.

inverse()[source]

Inverse gate.

class ffsim.qiskit.OrbitalRotationJW(norb, orbital_rotation, *, label=None, validate=True, rtol=1e-05, atol=1e-08)[source]

Bases: Gate

Orbital rotation under the Jordan-Wigner transformation.

An orbital rotation maps creation operators as

\[a^\dagger_{\sigma, i} \mapsto \sum_{j} U_{ji} a^\dagger_{\sigma, j}\]

where \(U\) is a unitary matrix. This is equivalent to applying the transformation given by

\[\prod_{\sigma} \exp\left(\sum_{ij} \log(U)_{ij} a^\dagger_{\sigma, i} a_{\sigma, j}\right)\]

This gate assumes that qubits are ordered such that the first norb qubits correspond to the alpha orbitals and the last norb qubits correspond to the beta orbitals.

__init__(norb, orbital_rotation, *, label=None, validate=True, rtol=1e-05, atol=1e-08)[source]

Create new orbital rotation gate.

Parameters:
  • norb (int) – The number of spatial orbitals.

  • orbital_rotation (ndarray | tuple[ndarray | None, ndarray | None]) – 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 use None for one of the values in the pair to indicate that no operation should be applied to that spin sector.

  • label (str | None) – The label of the gate.

  • validate (bool) – Whether to check that the input orbital rotation(s) is unitary and raise an error if it isn’t.

  • rtol (float) – Relative numerical tolerance for input validation.

  • atol (float) – Absolute numerical tolerance for input validation.

Raises:

ValueError – The input matrix is not unitary.

inverse()[source]

Inverse gate.

class ffsim.qiskit.OrbitalRotationSpinlessJW(norb, orbital_rotation, *, label=None, validate=True, rtol=1e-05, atol=1e-08)[source]

Bases: Gate

Orbital rotation under the Jordan-Wigner transformation, spinless version.

Like OrbitalRotationJW but only acts on a single spin species.

__init__(norb, orbital_rotation, *, label=None, validate=True, rtol=1e-05, atol=1e-08)[source]

Create new orbital rotation gate.

Parameters:
  • norb (int) – The number of spatial orbitals.

  • orbital_rotation (ndarray) – The orbital rotation.

  • label (str | None) – The label of the gate.

  • validate (bool) – Whether to check that the input orbital rotation(s) is unitary and raise an error if it isn’t.

  • rtol (float) – Relative numerical tolerance for input validation.

  • atol (float) – Absolute numerical tolerance for input validation.

Raises:

ValueError – The input matrix is not unitary.

inverse()[source]

Inverse gate.

ffsim.qiskit.PRE_INIT = <qiskit.transpiler.passmanager.PassManager object>

Pass manager recommended for the Qiskit transpiler pre_init stage.

See pre_init_passes() for a description of the transpiler passes included in this pass manager.

class ffsim.qiskit.PrepareHartreeFockJW(norb, nelec, label=None)[source]

Bases: Gate

Gate that prepares the Hartree-Fock state (under JWT) from the all zeros state.

This gate assumes the Jordan-Wigner transformation (JWT).

This gate is meant to be applied to the all zeros state. It decomposes simply as a sequence of X gates that prepares the Hartree-Fock electronic configuration.

This gate assumes that qubits are ordered such that the first norb qubits correspond to the alpha orbitals and the last norb qubits correspond to the beta orbitals.

__init__(norb, nelec, label=None)[source]

Create new Hartree-Fock state preparation gate.

Parameters:
  • norb (int) – The number of spatial orbitals.

  • nelec (tuple[int, int]) – The number of alpha and beta electrons.

  • label (str | None) – The label of the gate.

class ffsim.qiskit.PrepareHartreeFockSpinlessJW(norb, nelec, label=None)[source]

Bases: Gate

Prepare the Hartree-Fock state (under JWT) from the zero state, spinless.

Like PrepareHartreeFockJW but only acts on a single spin species.

__init__(norb, nelec, label=None)[source]

Create new Hartree-Fock state preparation gate.

Parameters:
  • norb (int) – The number of spatial orbitals.

  • nelec (int) – The number of electrons.

  • label (str | None) – The label of the gate.

class ffsim.qiskit.PrepareSlaterDeterminantJW(norb, occupied_orbitals, orbital_rotation=None, *, label=None, validate=True, rtol=1e-05, atol=1e-08)[source]

Bases: Gate

Gate that prepares a Slater determinant (under JWT) from the all zeros state.

This gate assumes the Jordan-Wigner transformation (JWT).

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 (computational basis state). The reason this gate exists (when OrbitalRotationJW already exists) is that the preparation of a Slater determinant has a more optimized circuit than a generic orbital rotation.

This gate is meant to be applied to the all zeros state. Its behavior when applied to any other state is not guaranteed. The global phase of the prepared state may be arbitrary.

This gate assumes that qubits are ordered such that the first norb qubits correspond to the alpha orbitals and the last norb qubits correspond to the beta orbitals.

Reference: arXiv:1711.05395

__init__(norb, occupied_orbitals, orbital_rotation=None, *, label=None, validate=True, rtol=1e-05, atol=1e-08)[source]

Create new Slater determinant preparation gate.

Parameters:
  • norb (int) – The number of spatial orbitals.

  • occupied_orbitals (tuple[Sequence[int], Sequence[int]]) – The occupied orbitals in the electonic 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 use None for one of the values in the pair to indicate that no operation should be applied to that spin sector.

  • label (str | None) – The label of the gate.

  • validate (bool) – Whether to check that the input orbital rotation(s) is unitary and raise an error if it isn’t.

  • rtol (float) – Relative numerical tolerance for input validation.

  • atol (float) – Absolute numerical tolerance for input validation.

Raises:

ValueError – The input orbital rotation matrix is not unitary.

class ffsim.qiskit.PrepareSlaterDeterminantSpinlessJW(norb, occupied_orbitals, orbital_rotation=None, *, label=None, validate=True, rtol=1e-05, atol=1e-08)[source]

Bases: Gate

Prepare a Slater determinant (under JWT) from the zero state, spinless version.

Like PrepareSlaterDeterminantJW but only acts on a single spin species.

__init__(norb, occupied_orbitals, orbital_rotation=None, *, label=None, validate=True, rtol=1e-05, atol=1e-08)[source]

Create new Slater determinant preparation gate.

Parameters:
  • norb (int) – The number of spatial orbitals.

  • occupied_orbitals (Sequence[int]) – The occupied orbitals in the electonic configuration.

  • orbital_rotation (ndarray | None) – The optional orbital rotation.

  • label (str | None) – The label of the gate.

  • validate (bool) – Whether to check that the input orbital rotation(s) is unitary and raise an error if it isn’t.

  • rtol (float) – Relative numerical tolerance for input validation.

  • atol (float) – Absolute numerical tolerance for input validation.

Raises:

ValueError – The input orbital rotation matrix is not unitary.

class ffsim.qiskit.SimulateTrotterDiagCoulombSplitOpJW(hamiltonian, time, *, n_steps=1, order=0, label=None)[source]

Bases: Gate

Split operator Trotter evolution of diagonal Coulomb Hamiltonian, Jordan-Wigner.

This gate assumes that qubits are ordered such that the first norb qubits correspond to the alpha orbitals and the last norb qubits correspond to the beta orbitals.

__init__(hamiltonian, time, *, n_steps=1, order=0, label=None)[source]

Create diagonal Coulomb split-operator Trotter evolution gate.

Parameters:
  • norb – The number of spatial orbitals.

  • hamiltonian (DiagonalCoulombHamiltonian) – The Hamiltonian.

  • time (float) – The evolution time.

  • n_steps (int) – The number of Trotter steps.

  • order (int) – The order of the Trotter decomposition.

  • label (str | None) – The label of the gate.

class ffsim.qiskit.SimulateTrotterDoubleFactorizedJW(hamiltonian, time, *, n_steps=1, order=0, label=None)[source]

Bases: Gate

Trotter time evolution of double-factorized Hamiltonian, Jordan-Wigner.

This gate assumes that qubits are ordered such that the first norb qubits correspond to the alpha orbitals and the last norb qubits correspond to the beta orbitals.

__init__(hamiltonian, time, *, n_steps=1, order=0, label=None)[source]

Create double-factorized Trotter evolution gate.

Parameters:
  • norb – The number of spatial orbitals.

  • hamiltonian (DoubleFactorizedHamiltonian) – The Hamiltonian.

  • time (float) – The evolution time.

  • n_steps (int) – The number of Trotter steps.

  • order (int) – The order of the Trotter decomposition.

  • label (str | None) – The label of the gate.

class ffsim.qiskit.UCJOpSpinBalancedJW(ucj_op, *, label=None)[source]

Bases: Gate

Spin-balanced UCJ operator under the Jordan-Wigner transformation.

See ffsim.UCJOpSpinBalanced for a description of this gate’s unitary.

This gate assumes that qubits are ordered such that the first norb qubits correspond to the alpha orbitals and the last norb qubits correspond to the beta orbitals.

__init__(ucj_op, *, label=None)[source]

Create a new spin-balanced unitary cluster Jastrow (UCJ) gate.

Parameters:
  • ucj_op (UCJOpSpinBalanced) – The UCJ operator.

  • label (str | None) – The label of the gate.

class ffsim.qiskit.UCJOpSpinUnbalancedJW(ucj_op, *, label=None)[source]

Bases: Gate

Spin-unbalanced UCJ operator under the Jordan-Wigner transformation.

See ffsim.UCJOpSpinUnbalanced for a description of this gate’s unitary.

This gate assumes that qubits are ordered such that the first norb qubits correspond to the alpha orbitals and the last norb qubits correspond to the beta orbitals.

__init__(ucj_op, *, label=None)[source]

Create a new spin-unbalanced unitary cluster Jastrow (UCJ) gate.

Parameters:
  • ucj_op (UCJOpSpinUnbalanced) – The UCJ operator.

  • label (str | None) – The label of the gate.

class ffsim.qiskit.UCJOpSpinlessJW(ucj_op, *, label=None)[source]

Bases: Gate

Spinless UCJ operator under the Jordan-Wigner transformation.

See ffsim.UCJOpSpinless for a description of this gate’s unitary.

__init__(ucj_op, *, label=None)[source]

Create a new spinless unitary cluster Jastrow (UCJ) gate.

Parameters:
  • ucj_op (UCJOpSpinless) – The UCJ operator.

  • label (str | None) – The label of the gate.

class ffsim.qiskit.UCJOperatorJW(ucj_operator, *, label=None)[source]

Bases: Gate

Unitary cluster Jastrow operator under the Jordan-Wigner transformation.

Warning

This class is deprecated. Use ffsim.qiskit.UCJOpSpinBalancedJW instead.

See ffsim.UCJOperator for a description of this gate’s unitary.

This gate assumes that qubits are ordered such that the first norb qubits correspond to the alpha orbitals and the last norb qubits correspond to the beta orbitals.

__init__(ucj_operator, *, label=None)[source]

Create a new unitary cluster Jastrow (UCJ) gate.

Parameters:
  • ucj_operator (UCJOperator) – The UCJ operator.

  • label (str | None) – The label of the gate.

__init_subclass__()

This method is called when a class is subclassed.

The default implementation does nothing. It may be overridden to extend subclasses.

static __new__(*args, **kwargs)
ffsim.qiskit.ffsim_vec_to_qiskit_vec(vec, norb, nelec)[source]

Convert an ffsim state vector to a Qiskit state vector.

Parameters:
  • vec (ndarray) – A state vector in ffsim/PySCF format. It should be a one-dimensional vector of length comb(norb, n_alpha) * comb(norb, n_beta).

  • 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

ffsim.qiskit.final_state_vector(circuit)[source]

Return the final state vector of a fermionic quantum circuit.

Parameters:

circuit (QuantumCircuit) – The circuit composed of fermionic gates.

Return type:

StateVector

Returns:

The final state vector that results from applying the circuit to the vacuum state.

ffsim.qiskit.jordan_wigner(op, n_qubits=None)[source]

Jordan-Wigner transformation.

Transform a fermion operator to a qubit operator using the Jordan-Wigner transformation.

Parameters:
  • op (FermionOperator) – The fermion operator to transform.

  • n_qubits (int | None) – The number of qubits to include in the output qubit operator. If not specified, the minimum number of qubits needed to accommodate the fermion operator will be used. Must be non-negative.

Return type:

SparsePauliOp

Returns:

The qubit operator as a Qiskit SparsePauliOp.

Raises:
  • ValueError – Number of qubits was negative.

  • ValueError – Number of qubits was not enough to accommodate the fermion operator.

ffsim.qiskit.pre_init_passes()[source]

Yield transpiler passes recommended for the Qiskit transpiler pre_init stage.

The following transpiler passes are yielded: :rtype: Iterator[BasePass]

ffsim.qiskit.qiskit_vec_to_ffsim_vec(vec, norb, nelec)[source]

Convert a Qiskit state vector to an ffsim state vector.

Parameters:
  • vec (ndarray) – A state vector in Qiskit format. It should be a one-dimensional vector of length 2 ** (2 * norb).

  • 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