Skip to content

Results are limited to the current section: Application solving tools

Product news

qubosolver.solver

Config-based entry point for building and running QUBO solvers.

Exposes Solver, the single simple entry point for building and running QUBO solvers, along with SolverConfig and its nested configs used to configure it.

All names in this module are re-exported from the top-level qubosolver namespace, so they can be imported directly as e.g. from qubosolver import Solver.

Classes:

ClassicalSolvingConfig(algorithm: Literal['tabu_search', 'simulated_annealing', 'cplex', 'random_sampling'] = 'tabu_search', time_limit: float = float('inf'), max_iter: int = 100, max_bitstrings: int = 1)

A configuration that defines the classical-solving part of a SolverConfig.

Attributes:

  • algorithm (Literal (external)['tabu_search', 'simulated_annealing', 'cplex', 'random_sampling']) –

    Classical solver algorithm. One of:

    • "tabu_search": Tabu search metaheuristic that avoids recently visited solutions.
    • "simulated_annealing": Simulated annealing algorithm that probabilistically accepts worse solutions to escape local minima.
    • "cplex": IBM CPLEX exact solver; requires a valid CPLEX installation and license.
    • "random_sampling": Randomly samples solutions; useful as a baseline or for testing.

    Defaults to "tabu_search".

  • time_limit (float (external)) –

    Maximum runtime in seconds for the classical solve (cplex, simulated annealing, or tabu search). Defaults to float("inf"), meaning no time limit.

  • max_iter (int (external)) –

    Maximum number of iterations to perform for simulated annealing or tabu search.

  • max_bitstrings (int (external)) –

    Maximal number of bitstrings returned as solutions.

Methods:

__post_init__() -> None

Validate algorithm.

Source code in qubosolver/solver/config/solving.py
def __post_init__(self) -> None:
"""Validate `algorithm`."""
if self.algorithm not in get_args(_ClassicalAlgorithm):
raise ValueError(f"Invalid classical algorithm '{self.algorithm}'.")
DriveShapingConfig(algorithm: Literal['local_energy_scale', 'proportional_diagonal', 'bayesian_search'] = 'local_energy_scale', bayesian_search_n_calls: int = 20, proportional_diagonal_kappa: float = 1.0, local_energy_scale_kappa: float = 0.1)

A configuration that defines the drive shaping part of a QuantumSolvingConfig.

Attributes:

  • algorithm (Literal (external)['local_energy_scale', 'proportional_diagonal', 'bayesian_search']) –

    Drive shaping method used. One of:

    • "local_energy_scale": Drive whose peak Rabi frequency scales with the average local physical energy scale; no numerical optimization.
    • "proportional_diagonal": Drive whose amplitude/detuning scale proportionally to the QUBO diagonal; no numerical optimization.
    • "bayesian_search": Drive whose parameters are found via Bayesian search that minimizes the cost function via pulse optimization.

    Defaults to "local_energy_scale".

  • bayesian_search_n_calls (int (external)) –

    Number of calls for the optimization process. Defaults to 20. Note the optimizer accepts a minimal value of 12.

  • proportional_diagonal_kappa (float (external)) –

    Scaling coefficient for the Omega waveform in the proportional-diagonal drive shaper. Defaults to 1.0.

  • local_energy_scale_kappa (float (external)) –

    Scaling coefficient for the Omega waveform in the local-energy-scale drive shaper. Defaults to 0.1.

Methods:

__post_init__() -> None

Validate algorithm.

Source code in qubosolver/solver/config/drive_shaping.py
def __post_init__(self) -> None:
"""Validate `algorithm`."""
if self.algorithm not in get_args(_DriveShapingAlgorithm):
raise ValueError(f"Invalid drive shaping method '{self.algorithm}'.")
EmbeddingConfig(algorithm: Literal['blade', 'greedy_layout'] = 'blade', greedy_layout_lattice: Literal['square', 'triangular'] = 'triangular', blade_steps_per_round: int | None = 200)

A configuration that defines the embedding part of a QuantumSolvingConfig.

Attributes:

  • algorithm (Literal (external)['blade', 'greedy_layout']) –

    The type of embedding method used to place atoms on the register according to the QUBO problem. One of:

    • "blade": BLADE embedder using graph-theoretic optimization for qubit placement.
    • "greedy_layout": Greedy layout-based embedder that places qubits on a regular lattice.

    Defaults to "blade".

  • greedy_layout_lattice (Literal (external)['square', 'triangular']) –

    Lattice type for the greedy layout embedder method. One of "square" or "triangular". Defaults to "triangular".

  • blade_steps_per_round (int (external) | None) –

    Maps directly to steps_per_round in qoolqit.embedding.BladeConfig (external)

Methods:

  • __post_init__ –

    Validate algorithm and greedy_layout_lattice.

__post_init__() -> None

Validate algorithm and greedy_layout_lattice.

Source code in qubosolver/solver/config/embedding.py
def __post_init__(self) -> None:
"""Validate `algorithm` and `greedy_layout_lattice`."""
if self.algorithm not in get_args(_EmbeddingAlgorithm):
raise ValueError(f"Invalid embedding method '{self.algorithm}'.")
if self.greedy_layout_lattice not in get_args(_GreedyLayoutLattice):
raise ValueError(f"Invalid lattice '{self.greedy_layout_lattice}'.")
QuantumSolvingConfig(embedding: EmbeddingConfig
dataclass
(qubosolver.solver.config.embedding.Config)" href="#qubosolver.solver.EmbeddingConfig">EmbeddingConfig = EmbeddingConfig
dataclass
(qubosolver.solver.config.embedding.Config)" href="#qubosolver.solver.EmbeddingConfig">EmbeddingConfig(), drive_shaping: DriveShapingConfig
dataclass
(qubosolver.solver.config.drive_shaping.Config)" href="#qubosolver.solver.DriveShapingConfig">DriveShapingConfig = DriveShapingConfig
dataclass
(qubosolver.solver.config.drive_shaping.Config)" href="#qubosolver.solver.DriveShapingConfig">DriveShapingConfig(), backend: LocalEmulator (qubosolver.types.backends.LocalEmulator)" href="../qubosolver/#qubosolver.LocalEmulator">LocalEmulator | RemoteEmulator (qubosolver.types.backends.RemoteEmulator)" href="../qubosolver/#qubosolver.RemoteEmulator">RemoteEmulator | qoolqit.execution.QPU = LocalEmulator (qubosolver.types.backends.LocalEmulator)" href="../qubosolver/#qubosolver.LocalEmulator">LocalEmulator(), device: qoolqit.Device = qoolqit.AnalogDeviceWithDMM())

A configuration defines the quantum-solving part of a SolverConfig.

Attributes:

max_min_dist_ratio: float

Maximum allowed ratio between the largest and smallest inter-atom distance.

Derived from the configured device's max_radial_distance / min_distance specs (or inf when the device imposes no such limits).

Returns:

Solver(instance: Instance (qubosolver.Instance)" href="../qubosolver/#qubosolver.Instance">Instance, config: SolverConfig
dataclass
(qubosolver.solver.config.SolverConfig)" href="#qubosolver.solver.SolverConfig">SolverConfig | None = None)

A QUBO solver.

Its concrete solving strategy (quantum or classical) is chosen from SolverConfig at construction time.

Example
from qubosolver import Instance, Solver, SolverConfig
instance = Instance(matrix)
config = SolverConfig()
solver = Solver(instance, config)
solution = solver.solve()

Parameters:

  • instance (Instance) –

    The QUBO problem to solve.

  • config (SolverConfig | None, default: None ) –

    Solver configuration controlling which solving strategy is used and how it behaves.

Methods:

  • solve –

    Solve the QUBO instance.

Source code in qubosolver/solver/solver.py
def __init__(self, instance: Instance, config: SolverConfig | None = None) -> None:
"""Initialize the solver.
Args:
instance: The QUBO problem to solve.
config: Solver configuration controlling which solving strategy
is used and how it behaves.
"""
config = config or SolverConfig()
super().__init__(instance, config)
self._solver: BaseSolver
if self.config.solving_mode == "quantum":
self._solver = _QuboSolverQuantum(instance, config)
else:
self._solver = _QuboSolverClassical(instance, config)
solve() -> Solution
dataclass
(qubosolver.Solution)" href="../qubosolver/#qubosolver.Solution">Solution

Solve the QUBO instance.

Returns:

Source code in qubosolver/solver/solver.py
def solve(self) -> Solution:
"""Solve the QUBO instance.
Returns:
The solution.
"""
return self._solver.solve()
SolverConfig(config_name: str = '', solving: QuantumSolvingConfig
dataclass
(qubosolver.solver.config.solving.QuantumConfig)" href="#qubosolver.solver.QuantumSolvingConfig">QuantumSolvingConfig | ClassicalSolvingConfig
dataclass
(qubosolver.solver.config.solving.ClassicalConfig)" href="#qubosolver.solver.ClassicalSolvingConfig">ClassicalSolvingConfig = QuantumSolvingConfig
dataclass
(qubosolver.solver.config.solving.QuantumConfig)" href="#qubosolver.solver.QuantumSolvingConfig">QuantumSolvingConfig(), postprocessing: bool = True, preprocessing: bool = True)

A configuration instance that defines how a QUBO problem should be solved.

We specify whether to use a quantum or classical approach, which backend to run on, and additional execution parameters.

Methods:

  • __repr__ –

    Return the configuration's name.

Attributes:

classical: ClassicalSolvingConfig
dataclass
(qubosolver.solver.config.solving.ClassicalConfig)" href="#qubosolver.solver.ClassicalSolvingConfig">ClassicalSolvingConfig

Access the classical solving configuration directly, without checking solving_mode.

This also lets type-checkers narrow the type without an explicit isinstance (external) check or cast (external) at the call site.

Returns:

Raises:

config_name class-attribute instance-attribute

Section titled “ config_name class-attribute instance-attribute ”
config_name: str = ''

The name of the current configuration. Defaults to "".

postprocessing class-attribute instance-attribute

Section titled “ postprocessing class-attribute instance-attribute ”
postprocessing: bool = True

Whether we apply post-processing (True) or not (False). Defaults to True.

preprocessing class-attribute instance-attribute

Section titled “ preprocessing class-attribute instance-attribute ”
preprocessing: bool = True

Whether we apply pre-processing (True) or not (False). Defaults to True.

quantum: QuantumSolvingConfig
dataclass
(qubosolver.solver.config.solving.QuantumConfig)" href="#qubosolver.solver.QuantumSolvingConfig">QuantumSolvingConfig

Access the quantum solving configuration directly, without checking solving_mode.

This also lets type-checkers narrow the type without an explicit isinstance (external) check or cast (external) at the call site.

Returns:

Raises:

solving class-attribute instance-attribute

Section titled “ solving class-attribute instance-attribute ”
solving: QuantumSolvingConfig
dataclass
(qubosolver.solver.config.solving.QuantumConfig)" href="#qubosolver.solver.QuantumSolvingConfig">QuantumSolvingConfig | ClassicalSolvingConfig
dataclass
(qubosolver.solver.config.solving.ClassicalConfig)" href="#qubosolver.solver.ClassicalSolvingConfig">ClassicalSolvingConfig = field(default_factory= QuantumSolvingConfig
dataclass
(qubosolver.solver.config.solving.QuantumConfig)" href="#qubosolver.solver.QuantumSolvingConfig">QuantumSolvingConfig)

Whether to solve using a quantum approach (QuantumSolvingConfig) or a classical approach (ClassicalSolvingConfig), together with the configuration of that approach. Defaults to a QuantumSolvingConfig.

solving_mode: Literal['quantum', 'classical']

Whether this configuration solves using a quantum or classical approach.

Returns:

Raises:

__repr__() -> str

Return the configuration's name.

Source code in qubosolver/solver/config/config.py
def __repr__(self) -> str:
"""Return the configuration's name."""
return self.config_name