Python API reference
This page documents the supported public Python API for JijZept Solver.
- solve(instance, *, options=None, time_limit=_UNSET, gap_limit=_UNSET, num_threads=_UNSET, presolve=_UNSET, verbosity=_UNSET, display_frequency=_UNSET, initial_state=None, interrupter=None)
Solve an OMMX optimization problem instance.
This function supports Ctrl+C interruption when running on the Python main thread. When interrupted, it returns the best solution found so far (feasible or infeasible, if any) with a warning, or raises KeyboardInterrupt if there is nothing to return. When called from a non-main thread (e.g. a server worker thread), the solver runs without SIGINT integration: it cannot be interrupted this way; pass an
interrupterfor programmatic interruption instead.Option precedence, lowest to highest: solver defaults,
options, then the convenience arguments below. SeeSolveOptionsfor every available option.- Parallelism (
num_threads): num_threadsis the total number of solver threads, including the main search thread. One thread always runs the main branch-and-bound search (relaxation solves, propagation, cutting planes, and built-in heuristics). From 6 threads on, one more thread, the root LP thread, is reserved for the first LP relaxation at the root node: the main search solves it with the dual simplex method while the root LP thread solves the same LP with an interior-point method, and the first of the two to finish with a usable result is used. Both methods run at the same time only when that LP has 10,000 to 5,000,000 nonzero coefficients and the process uses at most 75% of the physical memory (current thresholds); otherwise the dual simplex method runs alone. Either way the root LP thread is not given to a worker, and every later LP is solved by the main search alone. The remaining threads run concurrent search workers. The main search and the workers cooperate through a shared pool of best-known solutions: a worker publishes every improving solution it finds (reported as a new incumbent by the main search) and may restart from solutions published by others.Automatic (
None, the default): about half of the logical CPU cores are used, with a minimum of 2. From 12 logical cores on this is 6 threads or more, so the root LP thread is reserved too.num_threads=1: no concurrent workers run, which makes runs reproducible. The LP relaxation and sub-MIP solves inside the main search may still use more than one CPU core.num_threads=N(N >= 2): up toN - 1workers are started (N - 2from 6 threads on, because of the root LP thread), chosen by problem class in a fixed priority order (one thread each):An exact-search worker: an independent complete search over the full problem.
A staged general-heuristics pipeline that runs hill climbing, then simulated annealing, then exact search over subproblems (linear problems only).
Up to two further independent exact-search workers (linear problems only).
Additional simulated-annealing and hill-climbing workers.
For problems with a quadratic objective, only the workers that handle quadratic terms natively are started (exact search, simulated annealing, hill climbing).
The worker lineup per problem class is finite, so raising
num_threadsbeyond it adds no further parallelism (for linear problems currently at most 8 threads in total are used: the main search, the root LP thread, and six workers). This setting governs the solve phase only; presolve threading is controlled separately bypresolve_threads.
- Parameters:
instance (Any) – The OMMX Instance to solve.
options (jijzept_solver.core.SolveOptions | None) – SolveOptions with detailed solver settings (default None = solver defaults).
time_limit (float | None) – Time limit in seconds. Passing None explicitly selects “no time limit” (overriding options); omitted = no opinion (default: no time limit).
gap_limit (float) – Relative optimality gap tolerance, e.g. 0.01 for 1% (default 0.0001). None is not accepted.
num_threads (int | None) – Total number of solver threads, counting the main search thread (minimum 1). See the “Parallelism” section above for how threads are allocated. Passing None explicitly selects automatic (overriding options); omitted = no opinion (default: automatic = about half of the logical CPU cores, minimum 2).
presolve (bool) – Enable presolve (default True). None is not accepted.
verbosity (int) – Verbosity level: 0 = quiet, 1 = normal, 2 = verbose (default 1). None is not accepted.
display_frequency (int) – Display progress every N nodes, 0 = disabled (default 10). None is not accepted.
initial_state (Any) –
Optional initial solution (default None), as an
ommx.v1.State, an ID dictionary{id: value}, or a portable named dictionary{(name, (i, ...)): value}or{name: {(i, ...): value}}. Scalars use the empty tuple(). Named dictionaries are resolved against this instance before presolve, so IDs may differ from those of a previous session. Names and subscripts must identify exactly one current decision variable; unknown or ambiguous entries raise ValueError. Do not mix dictionary forms. Subscripts must be integer tuples, and dictionary values must be finite real numbers (not bool). Existing State objects retain their existing behavior.Missing variables: filled with solver defaults (0 if in bounds, lower otherwise;
lower.ceil()for integers).Extra IDs (not in the instance): silently ignored. Unknown named variables are rejected to catch stale names and typos.
Out-of-bounds values: clamped.
* Recommendation: use a solution generated in the same environment * Presolve behavior (especially dual reductions) can vary across platforms (CPU architecture, OS, native library build). An initial_state created on one environment (e.g., a development machine) may not work effectively when used on another environment (e.g., a production machine), due to differences in presolve decisions between environments. To avoid this, when using initial_state, prefer using a solution generated by JijZept Solver in the same environment.
interrupter (jijzept_solver.core.Interrupter | None) – Optional Interrupter for stopping the solve from another thread (default None). After
interrupter.interrupt()the solver stops at the next check: solve() returns the best solution found so far (without a warning), or raises NoSolutionError withstatus == "UserInterrupt"when there is nothing to return. A stopped solve() cannot be continued: the search state is released when solve() returns, so a later call starts over. One-shot: create a fresh instance per solve; passing an already-interrupted one stops immediately.
- Returns:
The OMMX Solution. When no feasible solution was found within the limits, the best infeasible solution the solver encountered (smallest total constraint violation) is returned with
solution.feasible == False. Always checksolution.feasiblebefore using the values.- Raises:
KeyboardInterrupt – If interrupted by Ctrl+C before any solution (feasible or infeasible) was found. Ctrl+C interruption is available only when solve() runs on the Python main thread.
NoSolutionError – If the solver found no solution at all to return for the termination status. A subclass of RuntimeError; the termination status name is available as the
statusattribute (e.g."Infeasible","TimeLimit").RuntimeError – If an internal error occurs during solving.
ValueError – If the input instance or an option value is invalid.
pyo3_runtime.PanicException – If the solver core panics on the calling thread (a bug — please report it). The process itself survives. Note this is a
BaseExceptionsubclass, so a plainexcept Exceptiondoes not catch it.
- Return type:
Any
- Parallelism (
- class SolveOptions
Options for solve().
Every constructor argument defaults to None, meaning “not set”: the solver default is used. Instances are immutable; derive modified copies with with_overrides.
Seven options default to “no limit” / “automatic”: time_limit, node_limit, solution_limit, num_threads, min_efficacy, max_cuts_per_round, and orthogonality_threshold. For these, passing None to with_overrides explicitly selects that behavior, overriding any value from a lower layer such as an options file.
- with_overrides(**kwargs)
Return a copy with the given options set on top of this object.
Keyword names and values match the constructor arguments. Passing None explicitly selects the unlimited/automatic behavior for time_limit, node_limit, solution_limit, num_threads, min_efficacy, max_cuts_per_round, orthogonality_threshold; None is rejected for every other option.
- Parameters:
kwargs (Any)
- Return type:
- to_dict(changed_only=False)
Return the options as a dict.
With changed_only=True only explicitly set options are included; otherwise every option appears with its effective value (the set value or the solver default). An explicit None (unlimited/automatic, set via with_overrides) is omitted from the changed_only dict, exactly as in a file written by to_file: it selects the same behavior as the default.
- Parameters:
changed_only (bool)
- Return type:
Any
- to_file(path)
Write the explicitly set options (only those) to a TOML file.
- Parameters:
path (str | os.PathLike | pathlib.Path)
- Return type:
None
- static from_file(path)
Load options from a TOML file.
- Parameters:
path (str | os.PathLike | pathlib.Path)
- Return type:
- static write_template(path)
Write a template TOML file listing every option with its default value.
- Parameters:
path (str | os.PathLike | pathlib.Path)
- Return type:
None