Fermionic package

Piquasso package for Fermionic quantum computation.

Note

This feature is still experimental.

Basic notations

Let \(f_k\) and \(f_k^\dagger\) denote the Dirac operators. These fulfill the CAR algebra, i.e.,

\[\begin{split}\{ f_i, f_j^\dagger \} &= I \delta_{ij}, \\\\ \{ f_i, f_j \} &= \{ f_i^\dagger, f_j^\dagger \} = 0.\end{split}\]

Let us define \(\mathbf{f}\) as

\[\mathbf{f} = [f_1^\dagger, \dots, f_d^\dagger, f_1, \dots, f_d].\]

The Majorana operators are defined as

\[\begin{split}x_k &:= f_k + f_k^\dagger, \\\\ p_k &:= -i (f_k - f_k^\dagger),\end{split}\]

where \(f_k\) and \(f_k^\dagger\) denote the Dirac operators.

\(\mathbf{m}\) denotes the vector of Majorana operators, i.e.,

\[\mathbf{m} := [x_1, \dots, x_d, p_1, \dots, p_d].\]

Fermionic instructions

Extra instructions specific for Fermionic quantum computing.

class ParentHamiltonian(hamiltonian)

Bases: Preparation

Prepares the fermionic Gaussian state with a specified parent Hamiltonian.

The density matrix is of the form

\[\rho = \frac{e^{\hat{H}}}{\operatorname{Tr} e^{\hat{H}}},\]

where \(\hat{H}\) is the parent Hamiltonian and has the form

\[\begin{split}\hat{H} &= \mathbf{f}^\dagger H \mathbf{f}, \\\\ H &= \begin{bmatrix} - \overline{A} & B \\ - \overline{B} & A \end{bmatrix}. \\\\\end{split}\]

Here, \(A\) is self-adjoint and \(B\) is skew-symmetric.

class GaussianHamiltonian(hamiltonian)

Bases: Gate

Applies a fermionic Gaussian transformation using its quadratic Hamiltonian.

The gate unitary is of the form

\[U = e^{i \hat{H}},\]

where

\[\begin{split}\hat{H} &= \mathbf{f} H \mathbf{f}^\dagger, \\\\ H &= \begin{bmatrix} A & -\overline{B} \\ B & -\overline{A} \end{bmatrix}.\end{split}\]

Here, \(A\) is self-adjoint and \(B\) is skew-symmetric.

class ControlledPhase(phi: float)

Bases: Gate

Controlled-phase gate.

The controlled-phase gate is defined via the unitary operator

\[\text{CPhase}_{ij} (\phi) = \exp \left ( i \phi n_i n_j \right ).\]

Note

This is a non-linear gate, therefore it couldn’t be used with GaussianSimulator.

Note

This is analoguous to the CrossKerr gate in the photonic setting.

Parameters:

phi (float) – The controlled-phase angle.

class IsingXX(phi: float)

Bases: Gate

Ising XX coupling gate.

The Ising XX gate is defined via the unitary operator

\[\text{XX}_{ij} (\phi) = \exp \left ( i \phi X \otimes X \right ) = \cos \phi I + i \sin \phi (X \otimes X).\]

Considering a two-mode system with Majorana operators \(m_1, m_2, m_3, m_4\), \(X \otimes X\) can also be written as

\[X \otimes X = -i m_2 m_3.\]
Parameters:

phi (float) – The rotation angle.

Fermionic Gaussian simulations

This is a package for Fermionic Linear Optics (FLO) or Fermionic Gaussian states.

class GaussianSimulator(d: int, config: Config | None = None, connector: BaseConnector | None = None)

Bases: BuiltinSimulator

Fermionic Gaussian simulator.

Example usage:

passive_hamiltonian = np.array([[1, 2j, 3j], [-2j, 5, 6], [-3j, 6, 7]])

U = expm(1j * passive_hamiltonian)

state_vector = [1, 0, 1]

with pq.Program() as program:
    pq.Q() | pq.StateVector(state_vector)

    pq.Q() | pq.Interferometer(U)

simulator = pq.fermionic.GaussianSimulator(d=3, connector=connector)

state = simulator.execute(program).state
Supported preparations:

Vacuum, StateVector.

Supported gates:

Interferometer, Beamsplitter, Phaseshifter, GaussianHamiltonian.

create_initial_state()

Creates an initial state with no instructions executed.

Note

This is not necessarily a vacuum state.

Returns:

The initial state of the simulation.

Return type:

State

execute(program: Program, shots: int = 1, initial_state: State | None = None) Result

Executes the specified program.

Parameters:
  • program (Program) – The program to execute.

  • initial_state (State, optional) – A state to execute the instructions on. Defaults to the state created by create_initial_state().

  • shots (int, optional) – The number of times the program should execute. Defaults to 1.

Raises:

InvalidParameter – When shots is not a positive integer.

Returns:

The result of the simulation containing the resulting state and samples if any measurement is specified in program.

Return type:

Result

execute_instructions(instructions: List[Instruction], initial_state: State | None = None, shots: int = 1) Result

Executes the specified instruction list.

Parameters:
  • instructions (List[Instruction]) – The instructions to execute.

  • initial_state (State, optional) – A state to execute the instructions on. Defaults to the state created by create_initial_state().

  • shots (int, optional) – The number of times the program should be execute. Defaults to 1.

Raises:

InvalidParameter – When shots is not a positive integer.

Returns:

The result of the simulation containing the resulting state and samples if any measurement is specified in instructions.

Return type:

Result

validate(program: Program) None

Validates the specified program.

Raises:
  • InvalidInstruction – When invalid instructions are defined in the program.

  • InvalidSimulation – When the instructions are valid, but the simulator couldn’t execute the specified program.

Parameters:

program (Program) – The program to validate.

class GaussianState(d: int, connector: BaseConnector, config: Config | None = None)

Bases: State

A fermionic Gaussian state.

property d

The number of modes.

property covariance_matrix

The covariance matrix. A fermionic Gaussian state can be fully characterized by its covariance matrix defined by

\[\Sigma_{ij} := -i \operatorname{Tr} (\rho [\mathbf{m}_i, \mathbf{m}_j]) / 2.\]

The covariance matrix is a real-valued, skew-symmetric matrix.

property correlation_matrix

The correlation matrix in the Dirac basis.

The correlation matrix is defined by

\[\begin{split}\Gamma := \begin{bmatrix} \Gamma^{f^\dagger f} & \Gamma^{f^\dagger f^\dagger} \\ \Gamma^{f f} & \Gamma^{f f^\dagger} \end{bmatrix},\end{split}\]

where \(\Gamma_{i,j}^{f^\dagger f} = \langle f_i^\dagger f_j \rangle\) and \(\Gamma_{i,j}^{f f} = \langle f_i f_j \rangle\).

By CAR, we know that \(\Gamma_{i,j}^{f^\dagger f} = - \overline{\Gamma_{i,j}^{f f^\dagger }}\) and \(\Gamma_{i,j}^{f f} = I - \overline{\Gamma_{i,j}^{f^\dagger f^\dagger }}\)

The correlation matrix is a self-adjoint matrix.

property maj_correlation_matrix

The correlation matrix in the Majorana operator basis.

validate()

Validates the state.

property fock_probabilities: np.ndarray

Returns the particle detection probabilities.

Note

The ordering of the Fock basis is increasing with particle numbers, and in each particle number conserving subspace, lexicographic ordering is used.

Returns:

The particle detection probabilities.

Return type:

numpy.ndarray

get_particle_detection_probability(occupation_number: np.ndarray) float

Returns the particle number detection probability using the occupation number specified as a parameter.

Parameters:

occupation_number (tuple) – Tuple of natural numbers representing the number of particles in each mode.

Returns:

The probability of detection.

Return type:

float

mean_particle_numbers(modes)

Returns the mean particle numbers on the specified modes.

get_parent_hamiltonian()

Calculates the parent Hamiltonian.

When the correlation matrix is not singular, the density matrix is

\[\rho = e^{\hat{H}} / \operatorname{Tr} e^{\hat{H}},\]

where \(\hat{H}\) is the parent hamiltonian (see get_parent_hamiltonian()) given by

\[ \begin{align}\begin{aligned}\begin{split}\hat{H} = \mathbf{f}^\dagger H \mathbf{f}, \\\\\end{split}\\\begin{split}H = \begin{bmatrix} A & -\overline{B} \\ B & -\overline{A} \end{bmatrix}.\end{split}\end{aligned}\end{align} \]

where \(A^\dagger = A\) and \(B^T = - B\).

Raises:

PiquassoException – When the correlation matrix is singular.

property density_matrix: np.ndarray

Density matrix in the lexicographic ordering.

When applicable, the density matrix is just

\[\rho = e^{\hat{H}} / \operatorname{Tr} e^{\hat{H}},\]

where \(\hat{H}\) is the parent hamiltonian (see get_parent_hamiltonian()) given by

\[\begin{split}\hat{H} = \mathbf{f}^\dagger H \mathbf{f}, \\\\ H = \begin{bmatrix} A & -\overline{B} \\ B & -\overline{A} \end{bmatrix}.\end{split}\]

where \(A^\dagger = A\) and \(B^T = - B\).

Note

The density matrix is returned in matrix form here. This will probably change in the future to tensor form.

reduced(modes)

Reduces the state to a subsystem on the specified modes.

get_majorana_monomial_expectation_value(indices)

Calculates Majorana monomial expectation values using Wick’s theorem.

The monomial indices are understood in the xxpp-ordering.

Parameters:

indices – Indices of the Majorana operators in any order with possible with possible multiplicities.

get_parity_operator_expectation_value()

Calculates the expectation value of the parity operator.

The parity operator is defined as

\[P = i^d m_1 \dots m_{2d} = i^d x_1 \dots x_d p_1 \dots p_d.\]
copy() State

Returns an exact copy of this state.

Returns:

An exact copy of this state.

Return type:

State

overlap(other)

Calculates the overlap between two fermionic Gaussian states.

The overlap is the Hilbert-Schmidt inner product of the density matrices.

Fermionic Fock space-based simulators

This is a package for Fock space-based simulations of fermionic states.

class PureFockState(d: int, connector: BaseConnector, config: Config | None = None)

Bases: State

A fermionic pure Fock state.

property state_vector

The state vector of the quantum state.

Warning

The primary ordering of the Fock basis is by number of particles, and the secondary is anti-lexicographic.

Example for 3 modes:

\[\ket{000}, \ket{100}, \ket{010}, \ket{001}, \ket{200}, \ket{110}, \ket{101}, \ket{020}, \ket{011}, \ket{002}, \dots\]

This is in contrast with density_matrix(), where the primary ordering is lexicographic.

property d

The number of modes.

property fock_probabilities: np.ndarray

Returns the particle detection probabilities.

Note

The ordering of the Fock basis is increasing with particle numbers, and in each particle number conserving subspace, lexicographic ordering is used.

Returns:

The particle detection probabilities.

Return type:

numpy.ndarray

property fock_probabilities_map: dict
property norm: float
get_particle_detection_probability(occupation_number)

Returns the particle number detection probability using the occupation number specified as a parameter.

Parameters:

occupation_number (tuple) – Tuple of natural numbers representing the number of particles in each mode.

Returns:

The probability of detection.

Return type:

float

validate()

Validates the state.

property density_matrix
copy() State

Returns an exact copy of this state.

Returns:

An exact copy of this state.

Return type:

State

class PureFockSimulator(d: int, config: Config | None = None, connector: BaseConnector | None = None)

Bases: BuiltinSimulator

Fermionic pure Fock state simulator.

Example usage:

U = scipy.stats.unitary_group.rvs(4)

with pq.Program() as program:
    pq.Q() | pq.StateVector([0, 0, 1, 1]) / np.sqrt(2)
    pq.Q() | pq.StateVector([1, 1, 0, 0]) / np.sqrt(2)
    pq.Q() | pq.Interferometer(U)

simulator = pq.fermionic.PureFockSimulator(
    d=4, config=pq.Config(cutoff=4 + 1)
)

state = simulator.execute(program).state
Supported preparations:

Vacuum, StateVector.

Supported gates:

Interferometer.

create_initial_state()

Creates an initial state with no instructions executed.

Note

This is not necessarily a vacuum state.

Returns:

The initial state of the simulation.

Return type:

State

execute(program: Program, shots: int = 1, initial_state: State | None = None) Result

Executes the specified program.

Parameters:
  • program (Program) – The program to execute.

  • initial_state (State, optional) – A state to execute the instructions on. Defaults to the state created by create_initial_state().

  • shots (int, optional) – The number of times the program should execute. Defaults to 1.

Raises:

InvalidParameter – When shots is not a positive integer.

Returns:

The result of the simulation containing the resulting state and samples if any measurement is specified in program.

Return type:

Result

execute_instructions(instructions: List[Instruction], initial_state: State | None = None, shots: int = 1) Result

Executes the specified instruction list.

Parameters:
  • instructions (List[Instruction]) – The instructions to execute.

  • initial_state (State, optional) – A state to execute the instructions on. Defaults to the state created by create_initial_state().

  • shots (int, optional) – The number of times the program should be execute. Defaults to 1.

Raises:

InvalidParameter – When shots is not a positive integer.

Returns:

The result of the simulation containing the resulting state and samples if any measurement is specified in instructions.

Return type:

Result

validate(program: Program) None

Validates the specified program.

Raises:
  • InvalidInstruction – When invalid instructions are defined in the program.

  • InvalidSimulation – When the instructions are valid, but the simulator couldn’t execute the specified program.

Parameters:

program (Program) – The program to validate.