Optimizations#

Enumeration#

Init for enumeration optimizations.

ferrmion.optimize.enumeration.anneal_enumerations(template: dict, one_e_coeffs: ndarray, two_e_coeffs: ndarray, temperature: float | None = None, initial_guess=typing.Union[collections.abc.Buffer, numpy._typing._array_like._SupportsArray[numpy.dtype[typing.Any]], numpy._typing._nested_sequence._NestedSequence[numpy._typing._array_like._SupportsArray[numpy.dtype[typing.Any]]], bool, int, float, complex, str, bytes, numpy._typing._nested_sequence._NestedSequence[bool | int | float | complex | str | bytes], NoneType], coefficient_weighted: bool = False)[source]#

Optimise mode enumeration using simulated annealing.

Parameters:
  • template (dict) – Encoding template dictionary.

  • one_e_coeffs (np.ndarray) – One-electron coefficient matrix.

  • two_e_coeffs (np.ndarray) – Two-electron coefficient matrix.

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

  • initial_guess (ArrayLike | None) – Starting permutation. Defaults to identity.

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

ferrmion.optimize.enumeration.lambda_plus_mu(n_modes: int, evaluate: partial[list[float]], pop_size: int, ngen: int) ndarray[tuple[int, ...], dtype[_ScalarType_co]][source]#

Reorder modes using lambda+mu evolutionary algorithm.

The values of lambda and mu are both set to half of the population size. With some tinkering this seems to work well.

Parameters:
  • n_modes (int) – The number of modes in the system.

  • evaluate (partial[list[float]]) – A partial function which acts as the cost function. This should take a list of integers (mode labels) as input and output a list of floats.

  • pop_size (int) – The size of the initial population.

  • ngen (int) – The number of generations to evolve.

Returns:

The best mode ordering found.

Return type:

NDArray

Example

>>> import numpy as np
>>> from functools import partial
>>> from ferrmion.optimize.enumeration.evolutionary import lambda_plus_mu
>>> def dummy_eval(x): return [sum(x)]
>>> evaluate = partial(dummy_eval)
>>> lambda_plus_mu(3, evaluate, pop_size=10, ngen=2)

Ternary Tree#

Hamiltonian-Adaptive Ternary Tree construction.

The greedy tree construction runs in native Rust (ferrmion.core.hatt); this module exposes a thin Python wrapper that takes a FermionHamiltonian and returns a fully-populated TernaryTree.

ferrmion.optimize.hatt.hamiltonian_adaptive_ternary_tree(fham: FermionHamiltonian, n_modes: int) TernaryTree[source]#

Construct an adaptive ternary tree from a fermionic Hamiltonian.

The tree is built greedily so the resulting qubit Hamiltonian has low Pauli weight. The construction runs in native Rust (ferrmion.core.hatt()).

Parameters:
  • fham (FermionHamiltonian) – The Hamiltonian whose terms drive the greedy Pauli-weight minimisation.

  • n_modes (int) – Number of fermionic modes in the system.

Returns:

The constructed tree with pauli_weight populated.

Return type:

TernaryTree

Bonsai Algorithm.

ferrmion.optimize.bonsai.bonsai_algorithm(graph: PyGraph, homogenous: bool = False, max_nodes: None | int = None) TernaryTree[source]#

Create a TernaryTree encoding using the Bonsai Algorithm.

Parameters:
  • graph (rx.PyGraph) – A RustworkX graph of device qubit-connectivity.

  • homogenous (bool) – “homogenous” labelling if true, else “heterogenous”

  • max_nodes (int) – Maximum number of nodes to include in output tree.

Returns:

A ternary tree encoding.

Return type:

TernaryTree

Reduced entanglement Ternary Tree.

ferrmion.optimize.rett.reduced_entanglement_ternary_tree(mutual_information: ndarray[tuple[int, ...], dtype[_ScalarType_co]], cutoff: float = 0.5, max_branches: int | None = None, squash: bool = False) TernaryTree[source]#

Creates the reduced entanglement TernaryTree.

Parameters:
  • mutual_information (NDArray) – A 2D array of mode mutual information.

  • cutoff (float | None) – The average MI between spatial orbitals.

  • max_branches (int) – The maximum allowed number of Parity branches.

  • squash (bool) – Whether to squash the mutual_information from spin-orbit form to spinless.

Returns:

A new ternary tree.

Return type:

TernaryTree

Note

Assumes that the MI matrix gives MI between spinless spatial orbitals So that each block of four contains [[aa, ab], [ba,bb]]

Example

>>> import numpy as np
>>> from ferrmion.optimize.rett import reduced_entanglement_tree
>>> mi = 0.5 * np.random.random((6,6))
>>> mi = mi + mi.T
>>> tree = reduced_entanglement_tree(mi)
>>> tree.as_dict()
Advanced example (with options):
>>> tree = reduced_entanglement_tree(mi, cutoff=0.1, max_branches=2, squash=False)

Huffman-code Ternary Tree.

ferrmion.optimize.huffman.huffman_ternary_tree(one_e_coeffs: ndarray[tuple[int, ...], dtype[float]], two_e_coeffs: ndarray[tuple[int, ...], dtype[float]]) TernaryTree[source]#

Creates a Huffman-code Ternary Tree.

Li, Q. S., Liu, H. Y., Wang, Q., Wu, Y. C., & Guo, G. P. (2025). Huffman-Code-based Ternary Tree Transformation. Chinese Physics Letters.

http://iopscience.iop.org/article/10.1088/0256-307X/42/10/100001

Note: Only vaccum-preserving Huffman-trees are currently supported.

Parameters:
  • one_e_coeffs (np.ndarray) – One electron coefficients.

  • two_e_coeffs (np.ndarray) – Two electron coefficients.

Returns:

A Huffman-code ternary tree.

Return type:

TernaryTree