Fermion-Qubit Encoding#

Init for encodings.

ferrmion.encode.BravyiKitaev(n_modes: int) TernaryTree[source]#

Create a new tree with the Bravyi-Kitaev encoding.

Parameters:

n_modes (int) – The number of fermionic modes.

Returns:

A ternary tree encoding.

Return type:

TernaryTree

Example

>>> from ferrmion.encode.ternary_tree import BravyiKitaev
>>> bk_tree = BravyiKitaev(3)
class ferrmion.encode.FermionQubitEncoding(n_modes: int, n_qubits: int, vacuum_state: ndarray[tuple[int, ...], dtype[bool]] | None = None)[source]#

Bases: ABC

Fermion Encodings for the Electronic Structure Hamiltonian in symplectic form.

one_e_coeffs#

One electron coefficients.

Type:

NDArray

two_e_coeffs#

Two electron coefficients.

Type:

NDArray

modes#

A set of modes.

Type:

set[int]

n_qubits#

The number of qubits.

Type:

int

default_mode_op_map()#

Get the default mode operator map.

_build_symplectic_matrix()[source]#

Build a symplectic matrix representing terms for each operator in the Hamiltonian.

hartree_fock_state()#

Find the Hartree-Fock state of a majorana string encoding.

_symplectic_to_pauli()[source]#

Convert a symplectic matrix to a Pauli string.

_pauli_to_symplectic()[source]#

Convert a Pauli string to a symplectic matrix.

fill_template()#

Fill a template with Hamiltonian coefficients.

to_symplectic_hamiltonian()#

Output the hamiltonian in symplectic form.

to_qubit_hamiltonian()#

Create qubit representation Hamiltonian.

NOTE: A ‘Y’ pauli operator is mapped to -iXY so a (0+n)**3 term is needed.

Example

>>> from ferrmion.encode.base import FermionQubitEncoding
>>> class DummyEncoding(FermionQubitEncoding):
...     def _build_symplectic_matrix(self):
...         import numpy as np
...         return np.zeros(1), np.zeros((1, 2))
>>> enc = DummyEncoding(2, 2)
>>> enc.n_modes
2
decode(states: ndarray[tuple[int, ...], dtype[bool]]) ndarray[tuple[int, ...], dtype[bool]][source]#

Decode Z-basis states into fermionic occupation vectors.

Decodes all rows of states in a single batch call to the Rust implementation, which processes each annihilation operator across every row before advancing to the next mode.

Parameters:

states – 2D boolean array of shape (n_states, n_qubits).

Returns:

2D boolean array of shape (n_states, n_modes).

Raises:

ValueError – if any state cannot be decoded for this encoding.

property default_mode_op_map: ndarray[tuple[int, ...], dtype[uint64]]#

Create a default mode operator map for the tree.

edge_operator(edge_indices: tuple[int, int], coeff: float | complex64 = np.complex64(1 + 0j), with_conjugate: bool = False) QubitHamiltonian[source]#

Return the edge operator of a pair of modes for this encoding.

Parameters:
  • edge_indices (tuple[int, int]) – The mode index to obtain a number operator for.

  • coeff (float) – Optional complex coefficient

  • with_conjugate (bool) – Return the operator together with its hermitian conjugate.

Example

>>> from ferrmion.encode.ternary_tree import TernaryTree
>>> tree = TernaryTree(4)
>>> tree.edge_operator((0, 1))
encode(fham: FermionHamiltonian) QubitHamiltonian[source]#

Encode a fermionic Hamiltonian into a qubit Hamiltonian.

Parameters:

fham (FermionHamiltonian) – The fermionic Hamiltonian to encode.

Returns:

The encoded qubit Hamiltonian.

Return type:

QubitHamiltonian

encode_annealed(fham: FermionHamiltonian, temperature: int | None = None, initial_guess: list[int] | None = None, coefficient_weighted: bool = True, seed: int | None = None)[source]#

Encode a Hamiltonian, optimising mode enumeration via simulated annealing.

Parameters:
  • fham (FermionHamiltonian) – The fermionic Hamiltonian to encode.

  • temperature (int | None) – Initial annealing temperature. Defaults to fham.n_modes.

  • initial_guess (list[int] | None) – Starting permutation. Defaults to identity.

  • coefficient_weighted (bool) – If True, minimise coefficient-weighted Pauli weight.

  • seed (int | None) – Seed for the RNG driving permutation moves. Defaults to 1017 (the historical hardcoded value) when omitted, so existing callers see no change in behaviour.

Returns:

The encoded qubit Hamiltonian with optimised enumeration.

Return type:

QubitHamiltonian

interaction_operator(mode_indices: tuple[int, int, int, int], coeff: float | complex64 = np.complex64(1 + 0j), physicist_notation=True, with_conjugate: bool = False) QubitHamiltonian[source]#

Return an interaction operator of four modes for this encoding.

Parameters:
  • mode_indices (tuple[int, int, int, int]) – The mode index to obtain an interaction operator for.

  • coeff (float) – Optional complex coefficient

  • physicist_notation (bool) – Use Physicist’s notation, Chemist’s if False.

  • with_conjugate (bool) – Return the operator together with its hermitian conjugate.

Example

>>> from ferrmion.encode.ternary_tree import TernaryTree
>>> tree = TernaryTree(4)
>>> tree.interaction_operator((0, 1, 2, 3))
number_operator(mode: int, coeff: float | complex64 = np.complex64(1 + 0j)) QubitHamiltonian[source]#

Return the number operator of a mode for this encoding.

Parameters:
  • mode (int) – The mode index to obtain a number operator for.

  • coeff (float) – Optional complex coefficient

Example

>>> from ferrmion.encode.ternary_tree import TernaryTree
>>> tree = TernaryTree(4)
>>> n_zero = tree.number_operator(0)
to_json() dict[source]#

Serialise the encoding to a JSON-compatible dictionary.

Returns:

Dictionary with "ipowers" and "symplectics" keys.

Return type:

dict

property vacuum_state#

Return the vacuum state.

ferrmion.encode.JKMN(n_modes: int) TernaryTree[source]#

Create a new tree with the JKMN encoding.

The JKMN encoding gives a ternary tree with the minimum Pauli-weight.

Parameters:

n_modes (int) – The number of fermionic modes.

Returns:

A ternary tree encoding.

Return type:

TernaryTree

Example

>>> from ferrmion.encode.ternary_tree import JKMN
>>> min_height_tree = JKMN(3)
ferrmion.encode.JordanWigner(n_modes: int) TernaryTree[source]#

Create a new tree with the Jordan-Wigner encoding.

Parameters:

n_modes (int) – The number of fermionic modes.

Returns:

A ternary tree encoding.

Return type:

TernaryTree

Example

>>> from ferrmion.encode.ternary_tree import JordanWigner
>>> jw_tree = JordanWigner(3)
class ferrmion.encode.MajoranaStringEncoding(ipowers: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], symplectics: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes])[source]#

Bases: FermionQubitEncoding

A fermion-qubit encoding constructed from explicit Majorana string data.

This encoding is defined directly from user-provided i-powers and symplectic matrices, rather than being derived from a tree structure.

class ferrmion.encode.MaxNTO(n_modes)[source]#

Bases: FermionQubitEncoding

k-NTO encoding for fermionic operators.

n_modes#

The number of modes.

Type:

int

_build_symplectic_matrix()[source]#

Build the symplectic matrix for the k-NTO encoding.

ferrmion.encode.ParityEncoding(n_modes: int) TernaryTree[source]#

Create a new tree with the parity encoding.

Parameters:

n_modes (int) – The number of fermionic modes.

Returns:

A ternary tree encoding.

Return type:

TernaryTree

Example

>>> from ferrmion.encode.ternary_tree import ParityEncoding
>>> parity_tree = ParityEncoding(3)
class ferrmion.encode.TernaryTree(n_modes: int, n_qubits: None | int = None, root_node: TTNode = TTNode (root path:'', Qubit Index: None))[source]#

Bases: FermionQubitEncoding

Ternary tree encoding for fermionic operators.

n_modes#

The number of fermionic modes to be encoded.

Type:

int

n_qubits#

The number of qubits in encoded operators.

Type:

int

root#

The root node of the tree.

Type:

TTNode

enumeration_scheme#

The enumeration scheme.

Type:

dict[str, tuple[int, int]] | None

default_mode_op_map()#

Create a default mode operator map for the tree.

default_enumeration_scheme()[source]#

Create a default enumeration scheme for the tree.

as_dict()[source]#

Return the tree structure as a dictionary.

add_node(node_string

str): Add a node to the tree.

branch_pauli_map()#

Create a map from each branch string to a Pauli string.

string_pairs()#

Return the pair of branch strings which correspond to each node.

_build_symplectic_matrix()[source]#

Build the symplectic matrix for the tree.

Simple Example:
>>> from ferrmion.encode.ternary_tree import TernaryTree
>>> tree = TernaryTree(4)
>>> tree.add_node('x')
>>> tree.enumeration_scheme = tree.default_enumeration_scheme()
>>> tree.as_dict()
Advanced Usage:
>>> from ferrmion.encode.ternary_tree import TernaryTree
>>> tree = TernaryTree(4)
>>> jordan_wigner = tree.JW()
>>> bravyi_kitaev = tree.BK()
>>> parity = tree.Parity()
>>> minimum_height_tree = tree.JKMN()
BK() TernaryTree[source]#

Alias for Bravyi-Kitaev encoding.

Example

>>> from ferrmion.encode.ternary_tree import TernaryTree
>>> bk_tree = TernaryTree(3).BK()
BravyiKitaev() TernaryTree[source]#

Create a new tree with the Bravyi-Kitaev encoding.

Parameters:

n_modes (int) – The number of fermionic modes.

Returns:

A ternary tree encoding.

Return type:

TernaryTree

Example

>>> from ferrmion.encode.ternary_tree import TernaryTree
>>> bk_tree = TernaryTree(3).BravyiKitaev()
JKMN() TernaryTree[source]#

Create a new tree with the JKMN encoding.

The JKMN encoding gives a ternary tree with the minimum Pauli-weight.

Example

>>> from ferrmion.encode.ternary_tree import TernaryTree
>>> min_height_tree = TernaryTree(3).JKMN()
JW() TernaryTree[source]#

Alias for Jordan-Wigner encoding.

Example

>>> from ferrmion.encode.ternary_tree import TernaryTree
>>> jw_tree = TernaryTree(3).JW()
JordanWigner() TernaryTree[source]#

Create a new tree with the Jordan-Wigner encoding.

Example

>>> from ferrmion.encode.ternary_tree import TernaryTree
>>> jw_tree = TernaryTree(3).JordanWigner()
ParityEncoding() TernaryTree[source]#

Create a new tree with the parity encoding.

Example

>>> from ferrmion.encode.ternary_tree import TernaryTree
>>> parity_tree = TernaryTree(3).ParityEncoding()
add_node(node_string: str) TernaryTree[source]#

Add a node to the tree.

Parameters:

node_string (str) – The string representation of the node.

Returns:

The tree with the node added.

Return type:

TernaryTree

Example

>>> from ferrmion.encode.ternary_tree import TernaryTree
>>> tree = TernaryTree(3)
>>> tree.add_node('x')
as_dict()[source]#

Return the tree structure as a dictionary.

property branch_pauli_map: dict[str, str]#

Create a map from each branch string to a Pauli string.

Returns:

A dictionary of all branch strings with their corresponding Pauli strings.

Return type:

dict[str, str]

Example

>>> from ferrmion.encode.ternary_tree import TernaryTree
>>> tree = TernaryTree(3)
>>> tree.add_node('x')
>>> tree.add_node('xz')
>>> tree.branch_pauli_map
{'xx': 'XXI',
'xzx': 'XZX',
'y': 'YII',
'xy': 'XYI',
'xzz': 'XZZ',
'xzy': 'XZY',
'z': 'ZII'}
default_enumeration_scheme() dict[str, tuple[int, int]][source]#

Create a default enumeration scheme for the tree.

Note

The tuple is organised as (modes, qubits).

Example

>>> from ferrmion.encode.ternary_tree import TernaryTree
>>> tree = TernaryTree(3).JW()
>>> tree.default_enumeration_scheme()
{"": (0,0), "z": (1,1), "zz": (2,2)}
encode_topphatt(fham: FermionHamiltonian, parallelize: bool = True, heuristic: str = 'min_weight', seed: int | None = None) QubitHamiltonian[source]#

Encode a Hamiltonian, using TOPP-HATT optimisation.

Parameters:
  • fham – The FermionHamiltonian to encode.

  • parallelize – Whether to parallelize the encoding.

  • heuristic – Node-selection strategy. One of "min_weight" (evaluate every active node and keep the lowest Pauli weight), "x_first" (lowest-indexed active node), "z_first" (highest-indexed active node — the default), or "random" (uniformly random active node using seed).

  • seed – RNG seed for heuristic="random". Ignored otherwise; defaults to 0 when omitted.

Returns:

The encoded QubitHamiltonian.

property enumeration_scheme: dict[str, tuple[int, int]]#

Get the enumeration scheme for the tree.

Note

The tuple is organised as (modes, qubits).

Example

>>> from ferrmion.encode.ternary_tree import TernaryTree
>>> tree = TernaryTree(3).JW()
>>> tree.enumeration_scheme
{"": (0,0), "z": (1,1), "zz": (2,2)}
flatpack() TTFlatpack[source]#

Create a TTFlatpack from the tree, which can be saved or passed to rust functions.

Node children are represented by their qubit index (an int that also appears as the first element of some flatpack entry). Leaf children with a known Majorana index are encoded as majorana_index + max_node_index + 1, which is strictly greater than every node qubit index (including when the Majorana index is 0) and can therefore never be confused with a node. Leaves without a known Majorana index are represented as None.

Returns:

list[tuple[int, tuple[int | None, int | None, int | None]]]

Example

>>> TernaryTree(4).JW().flatpack()
>>> [(0, (4, 5,1)), (1, (6,7,2)), (2, (8,9,3)), (3, (10,11,4))]
classmethod from_flatpack(flatpack: TTFlatpack) TernaryTree[source]#

Construct a TernaryTree from a TTFlatpack.

Parameters:

flatpack – The flatpack representation of the tree.

Returns:

A new TernaryTree instance.

Raises:

TypeError – If the flatpack is invalid.

hartree_fock_state(fermionic_hf_state: ndarray[tuple[int, ...], dtype[bool]], mode_op_map: ndarray[tuple[int, ...], dtype[uint64]] | list[int] | None = None)[source]#

Find the Hartree-Fock state of a majorana string encoding.

This function calls to the rust implementatin in src/lib.rs. It assumes that the vacuum state is a single state vector, though the HF state may not be The global phase so that the first component state has 0 phase.

Parameters:
  • fermionic_hf_state (NDArray[int]) – An array of mode occupations.

  • mode_op_map (dict[int, int]) – An array mapping modes to pairs of majorana strings mode_op_map[i]=j => i -> (2j,2j+1)

Returns:

The Hartree-Fock ground state in computational basis.

Return type:

NDArray

property string_pairs: dict[str | int, tuple[str, str]]#

Return the pair of branch strings which correspond to each node.

Returns:

A dictionary of all node labels, j, with branch strings (2j, 2j+1).

Return type:

dict[str, tuple(str,str)]

Example

>>> from ferrmion.encode.ternary_tree import TernaryTree
>>> tree = TernaryTree(3)
>>> tree.add_node('x')
>>> tree.add_node('xz')
>>> tree.string_pairs
{'': ('xzz', 'y'), 'x': ('xx', 'xy'), 'xz': ('xzx', 'xzy')}
ferrmion.encode.bravyi_kitaev(fham: FermionHamiltonian) QubitHamiltonian[source]#

Naive Bravyi-Kitaev Encoding.

Parameters:

fham (FermionHamiltonian) – Hamiltonian to encode.

Returns:

Encoded Hamiltonian.

Return type:

QubitHamiltonian

ferrmion.encode.bravyi_kitaev_annealed(fham: FermionHamiltonian, temperature: int | None = None, initial_guess: list[int] | None = None, coefficient_weighted: bool = True, seed: int | None = None) QubitHamiltonian[source]#

TOPP-HATT optimised Bravyi-Kitaev Encoding.

Parameters:
  • fham (FermionHamiltonian) – Hamiltonian to encode.

  • temperature (Optional[int]) – Initial annealing temperature.

  • initial_guess (Optional[list[int]]) – Initial mode enumeration.

  • coefficient_weighted (bool) – True to minimise coefficient Pauli-weight.

  • seed (Optional[int]) – Seed for the annealing RNG. Defaults to 1017 when omitted, preserving prior behaviour.

Returns:

Encoded Hamiltonian.

Return type:

QubitHamiltonian

ferrmion.encode.bravyi_kitaev_topphatt(fham: FermionHamiltonian) QubitHamiltonian[source]#

TOPP-HATT optimised Bravyi-Kitaev Encoding.

Parameters:

fham (FermionHamiltonian) – Hamiltonian to encode.

Returns:

Encoded Hamiltonian.

Return type:

QubitHamiltonian

ferrmion.encode.jkmn(fham: FermionHamiltonian) QubitHamiltonian[source]#

Naive Jiang-Kalev-Mruczkiewicz-Neven Encoding.

Parameters:

fham (FermionHamiltonian) – Hamiltonian to encode.

Returns:

Encoded Hamiltonian.

Return type:

QubitHamiltonian

ferrmion.encode.jkmn_annealed(fham: FermionHamiltonian, temperature: int | None = None, initial_guess: list[int] | None = None, coefficient_weighted: bool = True, seed: int | None = None) QubitHamiltonian[source]#

TOPP-HATT optimised Jiang-Kalev-Mruczkiewicz-Neven Encoding.

Parameters:
  • fham (FermionHamiltonian) – Hamiltonian to encode.

  • temperature (Optional[int]) – Initial annealing temperature.

  • initial_guess (Optional[list[int]]) – Initial mode enumeration.

  • coefficient_weighted (bool) – True to minimise coefficient Pauli-weight.

  • seed (Optional[int]) – Seed for the annealing RNG. Defaults to 1017 when omitted, preserving prior behaviour.

Returns:

Encoded Hamiltonian.

Return type:

QubitHamiltonian

ferrmion.encode.jkmn_topphatt(fham: FermionHamiltonian) QubitHamiltonian[source]#

TOPP-HATT optimised Jiang-Kalev-Mruczkiewicz-Neven Encoding.

Parameters:

fham (FermionHamiltonian) – Hamiltonian to encode.

Returns:

Encoded Hamiltonian.

Return type:

QubitHamiltonian

ferrmion.encode.jordan_wigner(fham: FermionHamiltonian) QubitHamiltonian[source]#

Naive Jordan-Wigner Encoding.

Parameters:

fham (FermionHamiltonian) – Hamiltonian to encode.

Returns:

Encoded Hamiltonian.

Return type:

QubitHamiltonian

ferrmion.encode.jordan_wigner_annealed(fham: FermionHamiltonian, temperature: int | None = None, initial_guess: list[int] | None = None, coefficient_weighted: bool = True, seed: int | None = None) QubitHamiltonian[source]#

TOPP-HATT optimised Jordan-Wigner Encoding.

Parameters:
  • fham (FermionHamiltonian) – Hamiltonian to encode.

  • temperature (Optional[int]) – Initial annealing temperature.

  • initial_guess (Optional[list[int]]) – Initial mode enumeration.

  • coefficient_weighted (bool) – True to minimise coefficient Pauli-weight.

  • seed (Optional[int]) – Seed for the annealing RNG. Defaults to 1017 when omitted, preserving prior behaviour.

Returns:

Encoded Hamiltonian.

Return type:

QubitHamiltonian

ferrmion.encode.jordan_wigner_topphatt(fham: FermionHamiltonian) QubitHamiltonian[source]#

TOPP-HATT optimised Jordan-Wigner Encoding.

Parameters:

fham (FermionHamiltonian) – Hamiltonian to encode.

Returns:

Encoded Hamiltonian.

Return type:

QubitHamiltonian

ferrmion.encode.parity(fham: FermionHamiltonian) QubitHamiltonian[source]#

Naive Parity Encoding.

Parameters:

fham (FermionHamiltonian) – Hamiltonian to encode.

Returns:

Encoded Hamiltonian.

Return type:

QubitHamiltonian

ferrmion.encode.parity_annealed(fham: FermionHamiltonian, temperature: int | None = None, initial_guess: list[int] | None = None, coefficient_weighted: bool = True, seed: int | None = None) QubitHamiltonian[source]#

TOPP-HATT optimised Parity Encoding.

Parameters:
  • fham (FermionHamiltonian) – Hamiltonian to encode.

  • temperature (Optional[int]) – Initial annealing temperature.

  • initial_guess (Optional[list[int]]) – Initial mode enumeration.

  • coefficient_weighted (bool) – True to minimise coefficient Pauli-weight.

  • seed (Optional[int]) – Seed for the annealing RNG. Defaults to 1017 when omitted, preserving prior behaviour.

Returns:

Encoded Hamiltonian.

Return type:

QubitHamiltonian

ferrmion.encode.parity_topphatt(fham: FermionHamiltonian) QubitHamiltonian[source]#

TOPP-HATT optimised Parity Encoding.

Parameters:

fham (FermionHamiltonian) – Hamiltonian to encode.

Returns:

Encoded Hamiltonian.

Return type:

QubitHamiltonian