qemcmc.model

Submodules

Classes

EnergyModel

A base class for energy models for a classical energy function over n spins,

ModelMaker

Utility class for constructing standard Ising energy models used in simulations and experiments.

ConstraintModel

A subclass of EnergyModel that incorporates a constraint function to define valid configurations.

Package Contents

class qemcmc.model.EnergyModel(n: int, couplings: List[numpy.ndarray] = [], name: str = None, cost_function_signs: list = [-1, -1], model_type: str = 'ising')[source]

A base class for energy models for a classical energy function over n spins, defined by arbitrary-order coupling tensors.

Parameters:
  • n – Number of spins

  • couplings – List of numpy arrays representing interaction tensors. A 1D array encodes linear terms, a 2D array encodes pairwise terms (expected symmetric), and higher-rank tensors encode higher-order interactions.

  • name – Optional label for the model (used in plotting / logging).

  • cost_function_signs – Sign convention(s) used by downstream components (e.g. proposal/acceptance conventions). For example, [-1, -1] for linear and quadratic terms.

  • model_type (str) – Type of model, either ‘ising’ or ‘binary’. This determines how the binary states are interpreted and how the energy is calculated. ‘ising’ models use spin values {-1, +1}, while ‘binary’ models use binary values {0, 1}.

Notes

  • Energies are computed by mapping binary states {0,1} to spin values {-1,+1} internally.

  • Brute-force methods such as get_all_energies scale as O(2^n) and are intended only for small systems.

n
n_spins
couplings = []
name = None
alphas
lowest_energy = None
normalised_couplings
cost_function_signs
initial_state = []
get_initial_states(num_initial_states: int)[source]

Generates a list of random initial states.

Parameters:

num_initial_states – The number of initial states to generate.

Returns:

A list of random initial states.

Return type:

list

get_ground_state(num_reads=100, num_batches=10)[source]

Finds an approximate ground state using Simulated Annealing.

calculate_energy(state, couplings, cost_function_signs)[source]

Calculate the energy of a given state for an arbitrary-order Ising/binary model.

Parameters:
  • state (array-like (str, list, tuple, np.array)) – State configuration. Can be: - Binary: “011”, [0,1,1], (0,1,1), etc. - Spin: [-1,1,1], (-1,1,1), etc.

  • couplings (list of numpy arrays) – List of coupling tensors where: - 1D arrays represent linear terms (h_i) - 2D arrays represent quadratic terms (J_ij) - 3D arrays represent cubic terms, etc.

Returns:

float

Return type:

Total energy of the state

get_subgroup_couplings(subgroup: List[int], current_state: str, coupling_weights: List[float] = None)[source]

Calculates local couplings for a subgroup of spins.

Spins outside the specified subgroup are treated as frozen constants, and their values are absorbed into the couplings of the subgroup. This is useful for calculating local effective Hamiltonians.

Parameters:
  • subgroup (List[int]) – A list of indices of the spins in the subgroup.

  • current_state (str) – The current state of the full system, as a binary string.

  • coupling_weights (List[float], optional) – Optional weights for the couplings. This can be used to effectively remove certain couplings from the proposal (e.g., constraints) by setting their weight to 0. It is important not to normalize the couplings after applying these weights.

Returns:

A new list of coupling tensors for the subgroup.

Return type:

List[np.ndarray]

Notes

It might seem off to do the reweighting at this point, but here are reasons why I [SF] did it! Basically, when you get the subgroup couplings, the terms jumble up, so the returned local coupling list necessarily does not respect the order etc. of the different terms in the original.

calculate_alpha(n: int, couplings: list = None, eps: float = 1e-15) numpy.ndarray[source]

Compute alpha = sqrt(n) / sqrt(sum of squares of UNIQUE coupling coefficients), assuming coupling tensors are symmetric representations.

Any non-symmetric 2-body input raises ValueError.

Parameters:
  • n (int) – Number of spins.

  • couplings (list[np.ndarray], optional) – Couplings to use. Defaults to self.couplings if not provided.

  • eps (float) – Small threshold to avoid division by zero.

Returns:

An array of normalising factors for each term in the couplings list.

Return type:

np.ndarray

get_energy(state: str) float[source]

Returns the energy of a given state

get_all_energies() numpy.ndarray[source]

Calculate the energies for all possible spin states. This method generates all possible spin states for the system and calculates the energy for each state.

Returns:

An array containing the energies of all possible spin states.

Return type:

np.ndarray

get_lowest_energies(num_states: int, return_configurations: bool = False) Tuple[numpy.ndarray, numpy.ndarray][source]

Retrieve the lowest energy states and their degeneracies. This method computes all possible energies and then finds the specified number of lowest energy states along with their degeneracies.

Parameters:
  • (int) (num_states)

  • (bool) (return_configurations)

Returns:

  • The first array contains the lowest energy values.

  • The second array contains the degeneracies of the corresponding energy values.

Return type:

Tuple[np.ndarray, np.ndarray]

Notes

This method is intended for small instances due to its brute-force nature, which is extremely memory intensive and slow.

find_lowest_values(arr: numpy.ndarray, num_values: int = 5)[source]

Find the lowest unique values in an array and their degeneracies.

Parameters:
  • (np.ndarray) (arr)

  • (int (num_values)

  • optional) (The number of lowest unique values to find. Defaults to 5.)

Returns:

  • lowest_values (np.ndarray): The lowest unique values in the array.

  • degeneracy (np.ndarray): The counts of each of the lowest unique values.

Return type:

Tuple[lowest_values (np.ndarray), degeneracy (np.ndarray)]

get_lowest_energy()[source]

Calculate and return the lowest energy from all possible energies. This method uses a brute force approach to find the lowest energy, making it extremely memory intensive and slow. It is recommended to use this method only for small instances.

Returns:

float

Return type:

The lowest energy value.

Notes

If the lowest energy has already been calculated and stored in self.lowest_energy, it will return that value directly to save computation time.

get_boltzmann_factor(state: str, beta: float = 1.0) float[source]

Get un-normalised boltzmann probability of a given state

Parameters:
  • state (str) – configuration of spins for which probability is to be calculated

  • beta (float) – inverse temperature (1/T) at which the probability is to be calculated.

Return type:

float corresponding to the un-normalised boltzmann probability of the given state.

get_boltzmann_factor_from_energy(E, beta: float = 1.0) float[source]

Get un-normalized Boltzmann probability for a given energy.

Parameters:
  • E (float) – Energy for which the Boltzmann factor is to be calculated.

  • beta (float) – Inverse temperature (1/T) at which the probability is to be calculated.

Returns:

The un-normalized Boltzmann probability for the given energy.

Return type:

float

class qemcmc.model.ModelMaker(n_spins: int, model_type: str, name: str, cost_function_signs: list = [-1, -1])[source]

Utility class for constructing standard Ising energy models used in simulations and experiments.

This class constructs predefined random energy models used for testing and experimentation. Depending on the chosen model_type, it generates coupling tensors and initialises an EnergyModel instance.

name
n_spins
cost_function_signs
make_fully_connected_ising()[source]
make_fully_connected_binary()[source]

Transforms the existing Ising couplings into an mathematically equivalent QUBO model via s = 2x - 1.

class qemcmc.model.ConstraintModel(n: int, constraint_couplings: list[numpy.ndarray], constraint_signs: list[float], couplings: list[numpy.ndarray], constraint_func: Callable[[str], bool], **kwargs)[source]

Bases: qemcmc.model.energy_model.EnergyModel

A subclass of EnergyModel that incorporates a constraint function to define valid configurations.

The constraint function takes a state as input and returns True if the state is valid (satisfies the constraint) and False otherwise. The energy of invalid states is set to infinity, effectively excluding them from the Boltzmann distribution.

Parameters:
  • n (int) – Number of spins in the model.

  • constraint_couplings (list[np.ndarray]) – List of coupling tensors (numpy arrays) defining the constraint.

  • constraint_signs (list[float]) – Sign convention(s) for the constraint couplings.

  • couplings (list[np.ndarray]) – List of coupling tensors (numpy arrays) defining the energy function.

  • constraint_func (Callable[[str], bool]) – A function that takes a state (string representation of spin configuration) and returns True if the state satisfies the constraint, and False otherwise.

  • name (str, optional) – Optional label for the model (used in plotting / logging).

  • cost_function_signs (list[float], optional) – Sign convention(s) used by downstream components (e.g. proposal/acceptance conventions).

  • model_type (str, optional) – Type of model, either ‘ising’ or ‘binary’. This determines how the binary states are interpreted and how the energy is calculated. ‘ising’ models use spin values {-1, +1}, while ‘binary’ models use binary values {0, 1}.

Notes

  • The energy of any state that does not satisfy the constraint is set to infinity, which means such states will have zero probability in the Boltzmann distribution.

  • This class can be used to model systems with hard constraints on the configurations, such as certain combinatorial optimization problems or physical systems with forbidden states.

constraint_func
get_initial_states

Generates a list of random initial states.

Parameters:

num_initial_states – The number of initial states to generate.

Returns:

A list of random initial states.

Return type:

list

constraint_couplings
constraint_signs
constraint_coupling_alphas
normalised_couplings
total_couplings
get_initial_states_constraint(num_initial_states: int)[source]

Generates a list of random initial states that satisfy the constraint function.

Parameters:

num_initial_states – The number of initial states to generate.

Returns:

A list of random initial states that are valid according to the constraint.

Return type:

list

get_constraint_energy(state: str) float[source]

Calculate the energy contribution from the constraint couplings for a given state.

Parameters:

state (str) – The state for which to calculate the constraint energy.

Returns:

The energy contribution from the constraint couplings for the given state.

Return type:

float

get_total_energy(state: str) float[source]

Calculate the total energy of a given state, including both the regular energy and the constraint energy.

Parameters:

state (str) – The state for which to calculate the total energy.

Returns:

The total energy of the given state, including contributions from both the regular couplings and the constraint couplings.

Return type:

float