Skip to content

qubosolver.solver

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 dataclass

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['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) –

    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) –

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

  • max_bitstrings (int) –

    Maximal number of bitstrings returned as solutions.

Methods:

__post_init__

__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 dataclass

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['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) –

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

  • proportional_diagonal_kappa (float) –

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

  • local_energy_scale_kappa (float) –

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

Methods:

__post_init__

__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 dataclass

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['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['square', 'triangular']) –

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

  • blade_steps_per_round (int | None) –

    Maps directly to steps_per_round in qoolqit.embedding.BladeConfig

Methods:

  • __post_init__ –

    Validate algorithm and greedy_layout_lattice.

__post_init__

__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 dataclass

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

Attributes:

max_min_dist_ratio property

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:

  • float –

    The resolved maximum min/max distance ratio.

Solver

Solver(instance: Instance, config: 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

solve() -> 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 dataclass

SolverConfig(config_name: str = '', solving: QuantumSolvingConfig | ClassicalSolvingConfig = 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 property

Access the classical solving configuration directly, without checking solving_mode.

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

Returns:

Raises:

  • ValueError –

    If this configuration is not configured for classical solving.

config_name class-attribute instance-attribute

config_name: str = ''

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

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

preprocessing: bool = True

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

quantum property

Access the quantum solving configuration directly, without checking solving_mode.

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

Returns:

Raises:

  • ValueError –

    If this configuration is not configured for quantum solving.

solving class-attribute instance-attribute

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 property

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

Whether this configuration solves using a quantum or classical approach.

Returns:

Raises:

__repr__

__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