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 interrupter for programmatic interruption instead.

Option precedence, lowest to highest: solver defaults, options, then the convenience arguments below. See SolveOptions for every available option.

Parallelism (num_threads):

num_threads is 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 to N - 1 workers are started (N - 2 from 6 threads on, because of the root LP thread), chosen by problem class in a fixed priority order (one thread each):

    1. An exact-search worker: an independent complete search over the full problem.

    2. A staged general-heuristics pipeline that runs hill climbing, then simulated annealing, then exact search over subproblems (linear problems only).

    3. Up to two further independent exact-search workers (linear problems only).

    4. 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_threads beyond 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 by presolve_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 with status == "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 check solution.feasible before 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 status attribute (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 BaseException subclass, so a plain except Exception does not catch it.

Return type:

Any

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.

property time_limit: float | None
Return type:

float | None

property node_limit: int | None
Return type:

int | None

property solution_limit: int | None
Return type:

int | None

property gap_limit: float
Return type:

float

property abs_gap_limit: float
Return type:

float

property verbosity: int
Return type:

int

property display_frequency: int
Return type:

int

property num_threads: int | None
Return type:

int | None

property branching: str
Return type:

str

property min_reliable: int
Return type:

int

property max_sb_candidates: int
Return type:

int

property node_selector: str
Return type:

str

property presolve: bool
Return type:

bool

property presolve_mode: str
Return type:

str

property presolve_dual_reductions: str
Return type:

str

property presolve_threads: int
Return type:

int

property presolve_seed: int
Return type:

int

property no_rounding: bool
Return type:

bool

property no_shifting: bool
Return type:

bool

property enable_int_shifting: bool
Return type:

bool

property enable_random_rounding: bool
Return type:

bool

property enable_zi_rounding: bool
Return type:

bool

property enable_fractional_diving: bool
Return type:

bool

property enable_feasibility_pump: bool
Return type:

bool

property no_rins: bool
Return type:

bool

property no_rens: bool
Return type:

bool

property no_warm_start: bool
Return type:

bool

property no_lp: bool
Return type:

bool

property lp_presolve: bool
Return type:

bool

property enable_alns: bool
Return type:

bool

property alns_max_iter: int
Return type:

int

property alns_time_limit: float
Return type:

float

property alns_patience: int
Return type:

int

property no_root_tightening: bool
Return type:

bool

property no_root_rc_fixing: bool
Return type:

bool

property no_root_sb_init: bool
Return type:

bool

property root_max_tightening_rounds: int
Return type:

int

property root_min_bound_improvement: float
Return type:

float

property root_sb_candidates: int
Return type:

int

property root_max_separation_rounds: int
Return type:

int

property root_min_cut_efficacy: float
Return type:

float

property root_max_cuts_per_round: int
Return type:

int

property root_max_cut_similarity: float
Return type:

float

property root_min_dual_improvement: float
Return type:

float

property root_max_idle_rounds: int
Return type:

int

property cut_selector: str
Return type:

str

property min_efficacy: float | None
Return type:

float | None

property max_cuts_per_round: int | None
Return type:

int | None

property orthogonality_threshold: float | None
Return type:

float | None

property no_miqp_initial_heuristic: bool
Return type:

bool

property miqp_initial_heuristic_num_iters: int
Return type:

int

property miqp_initial_heuristic_time_limit_msec_per_iter: int
Return type:

int

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:

SolveOptions

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:

SolveOptions

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