SolverConfig – Solver Configuration Reference
The SolverConfig
class defines how a QUBO problem should be solved — specifying whether to use a quantum or classical approach, which backend to run on, and additional execution parameters.
This configuration is passed into any solver (e.g., QuboSolver
) and guides its behavior.
Note that SolverConfig
uses four other configuration objects: 'BackendConfig', EmbeddingConfig
, ClassicalConfig
and PulseShapingConfig
.
Besides ClassicalConfig
, the other configurations represents different parts of the solver when using a quantum approach:
Fields for SolverConfig
Section titled “Fields for SolverConfig”Generic parameters
Section titled “Generic parameters”Field | Type | Description |
---|---|---|
config_name |
str |
The name of the current configuration |
use_quantum |
bool |
Whether to solve using a quantum approach (True ) such as QAA or VQA or a classical approach (False ). |
backend_config |
BackendConfig |
Backend part configuration of the solver. |
n_calls |
int | None |
Number of optimization rounds taken to find the best set of parameters for the optimization process inside VQA. The minimum value is 20. Note the optimizer accepts a minimal value of 12. |
embedding |
EmbeddingConfig |
Embedding part configuration of the solver. |
pulse_shaping |
PulseShapingConfig |
Pulse-shaping part configuration of the solver. |
classical |
ClassicalConfig |
Classical part configuration of the solver. |
num_shots |
int |
Number of samples when using a quantum device. Defaults to 500. |
Backend configuration
Section titled “Backend configuration”The backend configuration part (the backend_config
field) is set via the BackendConfig
class. It defines how we will run our quantum programs (via a local emulator, or via remote connection).
Field | Type | Description |
---|---|---|
backend |
BackendType |
(optional) Which backend to use (e.g., 'qutip' , 'emu_mps' , 'emu_sv' , 'remote_qpu' , 'remote_emumps' ). |
device |
NamedDevice | DeviceType | None |
(optional) If None , the backend will pick a reasonable device. If DeviceType , choose a device by its capabilities, e.g. DeviceType.DIGITAL_ANALOG . If NamedDevice , requiest a specific device. Only remote backends make use of NamedDevice . |
project_id |
str |
(optional) Project ID for accessing remote Pasqal services. Only used for remote backends. |
username |
str |
(optional) Username for Pasqal Cloud authentication. Only used for remote backends. |
password |
str |
(optional) Password for Pasqal Cloud authentication. Only used for remote backends. |
Embedding configuration
Section titled “Embedding configuration”When solving with a quantum approach, we need to define an embedding method, that is how we define the geometry (register) of atoms based on the QUBO instance and compatibility with a device.
The embedding configuration part (the embedding
field of SolverConfig
) can be divided into two groups of parameters.
Method parameter
Section titled “Method parameter”Field | Type | Description |
---|---|---|
embedding_method |
str | EmbedderType | Type[BaseEmbedder] |
The type of embedding method used to place atoms on the register according to the QUBO problem. (e.g., 'blade', 'greedy', but we can also create our own custom embedding method). |
draw_steps |
bool |
Show generated graph at each step of the optimization. Defaults to False. |
BLaDE embedding parameters
Section titled “BLaDE embedding parameters”Field | Type | Description |
---|---|---|
blade_dimensions |
list[int] |
A list of dimension degrees to explore one after the other (default is [5, 4, 3, 2, 2, 2]). |
starting_positions |
torch.Tensor |
The starting parameters according to the specified dimensions. |
blade_steps_per_round |
int | None |
The number of steps for each layer of dimension for the BLaDE embedder method. Defaults to 200. |
Greedy embedding parameters
Section titled “Greedy embedding parameters”We made available a greedy embedding method (given a fixed lattice or layout, it will defines the register to minimize the incremental mismatch between the logical QUBO matrix Q and the physical device interactions), whose related fields are:
Field | Type | Description |
---|---|---|
layout_greedy_embedder |
str | LayoutType | None |
Type of layout to run the greedy embedder method on (e.g., 'SquareLatticeLayout', 'TriangularLatticeLayout'). |
traps |
int | None |
The number of traps on the register. |
spacing |
int | None |
The minimum distance between atoms. |
density |
int | None |
The estimated density of the QUBO matrix for the greedy algorithm. |
Pulse Shaping configuration
Section titled “Pulse Shaping configuration”Quantum devices can be programmed by specifying a sequence of pulses.
The pulse shaping configuration part (the pulse_shaping
field of SolverConfig
) is set via the PulseShapingConfig
class, and defines how the pulse parameters are constructed (in an adiabatic fashion, via optimization, ...).
Field | Type | Description |
---|---|---|
pulse_shaping_method |
str | PulseType | Type[BasePulseShaper] |
The type of pulse-shaping method used (e.g., 'adiabatic', 'optimized'). |
initial_omega_parameters |
list[float] |
The list of initial amplitude parameters ( floating numbers) to be used in the first round of optimization. |
initial_detuning_parameters |
list[float] |
The list of global detuning parameters ( floating numbers) to be used in the first round of optimization. |
re_execute_opt_pulse |
bool |
Whether to re-run the optimal pulse sequence. |
custom_qubo_cost |
callable | None |
To apply a different qubo cost evaluation than the default. Must be defined as: def custom_qubo_cost(bitstring: str, QUBO: torch.Tensor) -> float . |
custom_objective_fn |
callable | None |
Change the bayesian optimization objective. Instead of using the best cost (best_cost ) out of the samples, one can change the objective for an average, or any function out of the form cost_eval = custom_objective_fn(bitstrings, counts, probabilities, costs, best_cost, best_bitstring) |
callback_objective |
callable | None |
Apply a callback during bayesian optimization. Only accepts one input dictionary created during optimization d = {"x": x, "cost_eval": cost_eval} hence should be defined as: def callback_fn(d: dict) -> None: . |
Classical solver configuration
Section titled “Classical solver configuration”For the classical solver, its configuration can be set via the ClassicalConfig
class:
Field | Type | Description |
---|---|---|
classical_solver_type |
str |
Classical solver type. |
cplex_maxtime |
float |
CPLEX maximum runtime. |
cplex_log_path |
str |
CPLEX logging path. |
max_iter |
int |
Maximum number of iterations to perform for simulated annealing or tabu search. |
sa_initial_temp |
float |
Starting temperature (controls exploration). |
sa_final_temp |
float |
Minimum temperature threshold for stopping. |
sa_alpha |
float |
Cooling rate - should be slightly below 1 (e.g., 0.95–0.99). |
tabu_x0 |
torch.Tensor | None |
The initial binary solution tensor. |
tabu_tenure |
int |
Number of iterations a move (bit flip) remains tabu. |
tabu_max_no_improve |
int |
Maximum number of consecutive iterations without improvement before termination. |
Pre-Post processing parameters
Section titled “Pre-Post processing parameters”We can also apply preprocessing of the QUBO instance (to reduce it to another smaller instance) or postprocessing the solution after solving.
Field | Type | Description |
---|---|---|
do_postprocessing |
bool |
Whether we apply post-processing (True ) or not (False ). |
do_preprocessing |
bool |
Whether we apply pre-processing (True ) or not (False ). |
Example
Section titled “Example”The SolverConfig
is designed in such way that all parameters have a default value which fulfilled the minimum required configuration to execute the necessary steps to solve a QUBO.
All the parameters are Optional
which allows for running SolverConfig
without specifying any parameter:
from qubosolver.config import SolverConfigfrom qoolqit._solvers.types import BackendType, DeviceTypefrom qubosolver.qubo_types import EmbedderType
config = SolverConfig()config.print_specs()
config_name: ''use_quantum: Falsebackend: qutipdevice: DeviceType.DIGITAL_ANALOG_DEVICEproject_id: ''username: ''password: ''n_calls: 20embedding: {'embedding_method': <EmbedderType.GREEDY: 'greedy'>, 'layout_greedy_embedder': <LayoutType.SQUARE: <class 'pulser.register.special_layouts.SquareLatticeLayout'>>, 'draw_steps': False, 'traps': 1, 'spacing': 5.0, 'density': None}pulse_shaping: {'pulse_shaping_method': <PulseType.ADIABATIC: 'adiabatic'>, 'initial_omega_parameters': [5.0, 10.0, 5.0,], 'initial_detuning_parameters': [-10.0, 0.0, 10.0], 're_execute_opt_pulse': False}classical: {'classical_solver_type': 'cplex', 'cplex_maxtime': 600.0, 'cplex_log_path': 'solver.log'}do_postprocessing: Falsedo_preprocessing: False
from qubosolver import QUBOInstancefrom qubosolver.config import SolverConfig, EmbeddingConfig, BackendConfigfrom qoolqit._solvers.types import DeviceType
coefficients = [[0, 1, 2], [1, 0, 3], [2, 3, 0]]instance = QUBOInstance(coefficients=coefficients)
embedding_config = EmbeddingConfig(embedding_method="greedy", traps=instance.size)backend_config = BackendConfig(backend="qutip", device=DeviceType.DIGITAL_ANALOG_DEVICE,)
config = SolverConfig( config_name="my_config", use_quantum=True, backend_config = backend_config, embedding = embedding_config,)
Equivalently, one can instantiate a SolverConfig
simply using the keyword arguments of the other configs via the SolverConfig.from_kwargs
method:
from qubosolver import QUBOInstancefrom qoolqit._solvers.types import DeviceTypefrom qubosolver.config import SolverConfig
coefficients = [[0, 1, 2], [1, 0, 3], [2, 3, 0]]instance = QUBOInstance(coefficients=coefficients)
config = SolverConfig.from_kwargs( config_name="my_config", use_quantum=True, backend="qutip", device=DeviceType.ANALOG_DEVICE, embedding_method="greedy", traps=instance.size)