Skip to content

Results are limited to the current section: Application solving tools

Product news

Classical Solvers

Classical solvers tackle a QUBO Instance entirely on CPU, without going through the quantum pipeline. Each one is a standalone function under solving, callable directly with the instance and its own set of keyword arguments — no Solver/SolverConfig wiring required. They differ in the trade-off between solution quality, runtime, and whether they need a starting point.

These solvers start from scratch:

  • solving.cplex.solve — exact MIP solve via IBM CPLEX.
  • solving.random_sampling.solve — uniform random sampling baseline.

These solvers take a starting point. Because they accept a starting point, they can also be used to refine a previous solution — for example, post-processing a quantum solver's output:

  • solving.tabu_search.solve — neighborhood search with a tabu memory. See example below.
  • solving.simulated_annealing.solve — stochastic temperature-cooling search.
  • solving.iterative_bitflip_local_search.solve — greedy local search that iteratively flips bits until no single flip improves the solution.
from qubosolver import Instance, solving, matrix, bitstrings, torch_rng, analysis
instance = Instance(
matrix.tensor(
[
[-2.0, 1.0, 0.0, 1.5, 0.0],
[1.0, -1.5, 1.0, 0.0, 0.5],
[0.0, 1.0, -2.0, 1.0, 1.0],
[1.5, 0.0, 1.0, -1.0, 0.5],
[0.0, 0.5, 1.0, 0.5, -1.5],
]
)
)
starts = bitstrings.rand(5, instance.size, rng=torch_rng(15))
solution = solving.tabu_search.solve(instance, starts=starts, time_limit=10.0)
print("Tabu Search solution:")
print(analysis.to_dataframe([solution]))
Tabu Search solution:
labels bitstrings costs counts probs
0 0 10100 -4.0 5 1.0

Run the quantum pipeline (see quantum solving), then try local bitflips for refinement:

from qubosolver import (
Instance,
Solution,
LocalEmulator,
embedding,
drive_shaping,
solving,
matrix,
analysis,
)
import qoolqit
instance = Instance(
matrix.tensor(
[
[-2.0, 1.0, 0.0, 1.5, 0.0],
[1.0, -1.5, 1.0, 0.0, 0.5],
[0.0, 1.0, -2.0, 1.0, 1.0],
[1.5, 0.0, 1.0, -1.0, 0.5],
[0.0, 0.5, 1.0, 0.5, -1.5],
]
)
)
device = qoolqit.AnalogDeviceWithDMM()
backend = LocalEmulator()
register = embedding.blade.embed_for_device(instance, device)
drive = drive_shaping.proportional_diagonal.build_drive(instance, register, device=device, dmm=True)
program = solving.analog_quantum_sampling.compile(register, drive, device)
job = backend.run(program)
quantum_solution = Solution.from_results(job.results(), instance)
print("Quantum solution:")
print(analysis.to_dataframe([quantum_solution]))
# Refine the quantum solution classically.
refined_solution = solving.iterative_bitflip_local_search.solve(instance, starts=quantum_solution)
print("Refined solution:")
print(analysis.to_dataframe([refined_solution]))
Quantum solution:
labels bitstrings costs counts probs
0 0 10100 -4.0 374 0.374
1 0 10001 -3.5 342 0.342
2 0 10101 -3.5 172 0.172
3 0 11001 -2.0 69 0.069
4 0 01001 -2.0 36 0.036
5 0 10000 -2.0 4 0.004
6 0 01011 -2.0 3 0.003
Refined solution:
labels bitstrings costs counts probs
0 0 10100 -4.0 550 0.550
1 0 10001 -3.5 411 0.411
2 0 01010 -2.5 3 0.003
3 0 01001 -2.0 36 0.036

For full parameter details, see the classical solvers API reference.

For the common case, SolverConfig and Solver wrap solver selection through ClassicalSolvingConfig, and (optionally) the initial-solution sampling into a single call:

from qubosolver import (
Instance,
Solver,
SolverConfig,
ClassicalSolvingConfig,
matrix,
analysis,
)
from dataclasses import asdict
import pprint
instance = Instance(
matrix.tensor(
[
[-2.0, 1.0, 0.0, 1.5, 0.0],
[1.0, -1.5, 1.0, 0.0, 0.5],
[0.0, 1.0, -2.0, 1.0, 1.0],
[1.5, 0.0, 1.0, -1.0, 0.5],
[0.0, 0.5, 1.0, 0.5, -1.5],
]
)
)
classical_config = ClassicalSolvingConfig(
algorithm="tabu_search",
# algorithm="simulated_annealing",
# algorithm="cplex",
)
solver_config = SolverConfig(solving=classical_config)
solver = Solver(instance, solver_config)
solution = solver.solve()
print(pprint.pformat(asdict(solver_config.solving)))
print()
print(analysis.to_dataframe([solution]))
{'algorithm': 'tabu_search',
'max_bitstrings': 1,
'max_iter': 100,
'time_limit': inf}
labels bitstrings costs counts probs
0 0 10100 -4.0 1 1.0