ommx_highs_adapter.adapter

Contents

ommx_highs_adapter.adapter#

Classes#

HighsDiagnosticsAnalyzer

Post-processor for HiGHS diagnostics.

HighsProgressSnapshot

HiGHS MIP solve progress observed from one logging callback.

HighsTerminationReport

HiGHS-side termination summary recorded after model.run().

OMMXHighsAdapter

OMMX Adapter for HiGHS solver.

Module Contents#

class HighsDiagnosticsAnalyzer(diagnostics: Iterable[Any])#

Post-processor for HiGHS diagnostics.

The analyzer accepts either typed diagnostics collected by ommx.adapter.DiagnosticCollector or dictionaries loaded from ommx.experiment.Solve.diagnostics.

property dual_bound: Any#

Return MIP dual bounds indexed by solving time.

property event: Any#

Return progress event names indexed by solving time.

property gap: Any#

Return MIP gaps indexed by solving time.

property ipm_iteration_count: Any#

Return interior-point iteration counts indexed by solving time.

property mip_dual_bound: Any#

Alias for dual_bound.

property mip_gap: Any#

Alias for gap.

property mip_node_count: Any#

Return MIP node counts indexed by solving time.

property mip_primal_bound: Any#

Alias for primal_bound.

property node_count: Any#

Alias for mip_node_count.

property objective_value: Any#

Return objective values indexed by solving time.

property pdlp_iteration_count: Any#

Return PDLP iteration counts indexed by solving time.

property primal_bound: Any#

Return MIP primal bounds indexed by solving time.

property progress_history_df: Any#

Return progress snapshots as a pandas DataFrame indexed by time.

property progress_history_records: list[dict[str, object]]#

Return one dictionary per HiGHS MIP logging callback.

property progress_snapshots: tuple[HighsProgressSnapshot, Ellipsis]#

Typed progress snapshots in the order they were recorded.

property simplex_iteration_count: Any#

Return simplex iteration counts indexed by solving time.

property termination_mip_dual_bound: float | None#

Return the terminal HiGHS MIP dual bound, if present.

property termination_mip_gap: float | None#

Return the terminal HiGHS MIP gap, if present.

property termination_mip_node_count: int | None#

Return the terminal HiGHS MIP node count, if present.

property termination_objective_value: float | None#

Return the terminal objective value, if present.

property termination_result: dict[str, object] | None#

Return the terminal HiGHS report as one dictionary, if present.

property termination_status: str | None#

Return the terminal HiGHS model status, if present.

class HighsProgressSnapshot#

HiGHS MIP solve progress observed from one logging callback.

classmethod from_callback_event(event: Any) HighsProgressSnapshot#
dual_bound: float#

MIP dual bound reported at the callback.

event: str#

HiGHS callback message, currently "MIP logging".

gap: float#

MIP relative gap reported at the callback.

ipm_iteration_count: int#

Interior-point iterations at the callback.

mip_node_count: int#

MIP branch-and-bound nodes processed at the callback.

objective_value: float#

Objective value reported at the callback.

pdlp_iteration_count: int#

PDLP iterations at the callback.

primal_bound: float#

MIP primal bound reported at the callback.

simplex_iteration_count: int#

Simplex iterations at the callback.

solving_time_sec: float#

HiGHS runtime when the callback ran.

class HighsTerminationReport#

HiGHS-side termination summary recorded after model.run().

The HiGHS adapter records this report before decoding the optimized HiGHS model back into an OMMX solution. It is therefore available even when decoding raises an adapter exception such as infeasible or unbounded detection.

classmethod from_model(model: highspy.Highs) HighsTerminationReport#
crossover_iteration_count: int#

Number of crossover iterations after interior-point optimization.

dual_solution_status: int#

HiGHS dual solution status code.

highs_githash: str#

HiGHS git hash reported by highspy.

highs_version: str#

HiGHS version used through highspy.

ipm_iteration_count: int#

Number of interior-point iterations.

max_dual_infeasibility: float#

Maximum dual infeasibility in the final solution.

max_integrality_violation: float#

Maximum integrality violation in the final solution.

max_primal_infeasibility: float#

Maximum primal infeasibility in the final solution.

mip_dual_bound: float#

MIP dual bound reported by HighsInfo.mip_dual_bound.

mip_gap: float#

MIP relative gap reported by HighsInfo.mip_gap.

mip_node_count: int#

Number of MIP branch-and-bound nodes processed by HiGHS.

objective_value: float | None#

Objective value reported by HiGHS, or None when no objective is valid.

pdlp_iteration_count: int#

Number of PDLP iterations.

primal_dual_integral: float#

HiGHS primal-dual integral.

primal_solution_status: int#

HiGHS primal solution status code.

run_time_sec: float#

HiGHS runtime in seconds.

simplex_iteration_count: int#

Number of simplex iterations.

status: str#

HiGHS model status, such as "Optimal" or "Infeasible".

class OMMXHighsAdapter(ommx_instance: Instance, *, verbose: bool = False)#

OMMX Adapter for HiGHS solver.

This adapter translates OMMX optimization problems (ommx.Instance) into HiGHS-compatible formats and converts HiGHS solutions back to OMMX format (ommx.Solution).

Translation Specifications#

Decision Variables#

The adapter handles the following translations for decision variables:

ID Management:

  • OMMX: Variables managed by IDs (non-sequential integers)

  • HiGHS: Variables managed by array indices (0-based sequential)

  • Mapping maintained internally for bidirectional conversion

Variable Types:

OMMX Type

HiGHS Type

Bounds

DecisionVariable.BINARY

HighsVarType.kInteger

[0, 1]

DecisionVariable.INTEGER

HighsVarType.kInteger

[var.bound.lower, var.bound.upper]

DecisionVariable.CONTINUOUS

HighsVarType.kContinuous

[var.bound.lower, var.bound.upper]

DecisionVariable.SEMI_INTEGER

Not supported (support planned)

-

DecisionVariable.SEMI_CONTINUOUS

Not supported (support planned)

-

Note: Semi-integer and semi-continuous variables are planned for future support but are currently unsupported. Using these variable types will raise an OMMXHighsAdapterError.

Constraints#

Supported Function Types:

  • Constant functions (ommx.Function.constant)

  • Linear functions (ommx.Function.linear)

Constraint Types:

OMMX Constraint

Mathematical Form

HiGHS Constraint

Constraint.EQUAL_TO_ZERO

f(x) = 0

const_expr == 0

Constraint.LESS_THAN_OR_EQUAL_TO_ZERO

f(x) ≤ 0

const_expr <= 0

Constant Constraint Handling:

  • Equality: Skip if |constant| ≤ 1e-10, error if |constant| > 1e-10

  • Inequality: Skip if constant ≤ 1e-10, error if constant > 1e-10

Constraint ID Management:

  • OMMX constraint IDs converted to HiGHS constraint names via str(constraint.id)

Objective Function#

Optimization Direction:

OMMX Direction

HiGHS Method

Instance.MINIMIZE

model.minimize(...)

Instance.MAXIMIZE

model.maximize(...)

Function Types:

  • Constant objectives: Processing skipped

  • Linear objectives: Converted to HiGHS linear expressions

Solution Decoding#

Variable Values: Extracted from HiGHS solution.col_value using maintained ID mapping

Optimality Status: Set to OPTIMALITY_OPTIMAL when HiGHS returns kOptimal

Dual Variables: Extracted from solution.row_dual for constraints

Error Handling#

Unsupported Features:

  • Quadratic functions (HiGHS supports linear problems only)

  • Semi-integer variables (DecisionVariable.SEMI_INTEGER, kind=4) - support planned

  • Semi-continuous variables (DecisionVariable.SEMI_CONTINUOUS, kind=5) - support planned

  • Constraint types other than EQUAL_TO_ZERO/LESS_THAN_OR_EQUAL_TO_ZERO

Solver Status Mapping:

HiGHS Status

Exception

kInfeasible

InfeasibleDetected

kUnbounded

UnboundedDetected

kNotset

OMMXHighsAdapterError

Limitations#

  1. Linear problems only (no quadratic constraints or objectives)

  2. Constraint forms limited to equality (= 0) and inequality (≤ 0)

  3. Variable types limited to Binary, Integer, and Continuous

    • Semi-integer (SEMI_INTEGER) support is planned but not yet implemented

    • Semi-continuous (SEMI_CONTINUOUS) support is planned but not yet implemented

Examples#

>>> from ommx_highs_adapter import OMMXHighsAdapter
>>> from ommx import Instance, DecisionVariable
>>>
>>> # Define problem
>>> x = DecisionVariable.binary(0)
>>> y = DecisionVariable.integer(1, lower=0, upper=10)
>>> instance = Instance.from_components(
...     decision_variables=[x, y],
...     objective=2*x + 3*y,
...     constraints={0: x + y <= 5},
...     sense=Instance.MAXIMIZE,
... )
>>>
>>> # Solve
>>> solution = OMMXHighsAdapter.solve(instance)
>>> print(f"Optimal value: {solution.objective}")
Optimal value: 15.0
>>> print(f"Variables: {solution.state.entries}")
Variables: {0: 0.0, 1: 5.0}
decode(data: highspy.Highs) Solution#

Convert an optimized HiGHS model back to an OMMX Solution.

This method translates HiGHS solver results into OMMX format, including variable values, optimality status, and dual variable information.

Parameters#
datahighspy.Highs

The HiGHS model that has been optimized. Must be the same model returned by solver_input property.

Returns#
Solution

Complete OMMX solution containing: - Variable values mapped back to original OMMX IDs - Constraint evaluations and feasibility status - Optimality information from HiGHS - Dual variables for linear constraints

Raises#
OMMXHighsAdapterError

If the model has not been optimized yet

InfeasibleDetected

If HiGHS determined the problem is infeasible

UnboundedDetected

If HiGHS determined the problem is unbounded

Notes#

This method should only be used after solving the model with HiGHS. Any modifications to the HiGHS model structure after creation may make the decoding process incompatible.

The dual variables are extracted from HiGHS’s row_dual and mapped to OMMX constraints based on their order. Only constraints with valid dual information will have the dual_variable field set.

Examples#
>>> from ommx_highs_adapter import OMMXHighsAdapter
>>> from ommx import Instance, DecisionVariable
>>>
>>> x = DecisionVariable.binary(0)
>>> instance = Instance.from_components(
...     decision_variables=[x],
...     objective=x,
...     constraints={},
...     sense=Instance.MAXIMIZE,
... )
>>>
>>> adapter = OMMXHighsAdapter(instance)
>>> model = adapter.solver_input
>>> model.run()  
<...>
>>> solution = adapter.decode(model)
>>> solution.objective
1.0
decode_to_state(data: highspy.Highs) State#

Extract variable values from an optimized HiGHS model as an OMMX State.

Parameters#
datahighspy.Highs

The optimized HiGHS model

Returns#
State

OMMX state containing variable values mapped to original OMMX IDs

Raises#
OMMXHighsAdapterError

If the model has not been optimized

InfeasibleDetected

If the model is infeasible

UnboundedDetected

If the model is unbounded

Examples#
>>> from ommx_highs_adapter import OMMXHighsAdapter
>>> from ommx import Instance, DecisionVariable
>>>
>>> x1 = DecisionVariable.integer(1, lower=0, upper=5)
>>> instance = Instance.from_components(
...     decision_variables=[x1],
...     objective=x1,
...     constraints={},
...     sense=Instance.MINIMIZE,
... )
>>> adapter = OMMXHighsAdapter(instance)
>>> model = adapter.solver_input
>>> model.run()  
<...>
>>> state = adapter.decode_to_state(model)
>>> state.entries
{1: 0.0}
classmethod solve(ommx_instance: Instance, *, verbose: bool = False, diagnostics: DiagnosticsSink | None = None) Solution#

Solve an OMMX optimization problem using HiGHS solver.

This method provides a convenient interface for solving optimization problems without needing to manually instantiate the adapter. It handles the complete workflow: translation to HiGHS format, solving, and result conversion.

Parameters#
ommx_instanceInstance

The OMMX optimization problem to solve. Must satisfy HiGHS adapter requirements: linear objective function (constant or linear terms only), linear constraints (constant or linear terms only), variables of type Binary, Integer, or Continuous only (Semi-integer and Semi-continuous support is planned but not yet implemented), and constraints of type EQUAL_TO_ZERO or LESS_THAN_OR_EQUAL_TO_ZERO only.

verbosebool, default=False

If True, enable HiGHS’s console logging for debugging

Returns#
Solution

The solution containing: - Variable values in solution.state.entries - Objective value in solution.objective - Constraint evaluations in solution.constraints - Optimality status in solution.optimality - Dual variables (if available) in constraint.dual_variable

Raises#
InfeasibleDetected

When the optimization problem has no feasible solution

UnboundedDetected

When the optimization problem is unbounded

OMMXHighsAdapterError

When the problem contains unsupported features or HiGHS encounters an error

Examples#

Knapsack Problem

>>> from ommx import Instance, DecisionVariable, Solution
>>> from ommx_highs_adapter import OMMXHighsAdapter
>>>
>>> p = [10, 13, 18, 32, 7, 15]  # profits
>>> w = [11, 15, 20, 35, 10, 33]  # weights
>>> x = [DecisionVariable.binary(i) for i in range(6)]
>>> instance = Instance.from_components(
...     decision_variables=x,
...     objective=sum(p[i] * x[i] for i in range(6)),
...     constraints={0: sum(w[i] * x[i] for i in range(6)) <= 47},
...     sense=Instance.MAXIMIZE,
... )
>>>
>>> solution = OMMXHighsAdapter.solve(instance)
>>> sorted([(id, value) for id, value in solution.state.entries.items()])
[(0, 1.0), (1, 0.0), (2, 0.0), (3, 1.0), (4, 0.0), (5, 0.0)]
>>> solution.feasible
True
>>> assert solution.optimality == Solution.OPTIMAL
>>> solution.objective
42.0

Infeasible Problem

>>> x = DecisionVariable.integer(0, upper=3, lower=0)
>>> instance = Instance.from_components(
...     decision_variables=[x],
...     objective=x,
...     constraints={0: x >= 4},  # Impossible: x ≤ 3 and x ≥ 4
...     sense=Instance.MAXIMIZE,
... )
>>> OMMXHighsAdapter.solve(instance)  
Traceback (most recent call last):
    ...
ommx.adapter.InfeasibleDetected: Model was infeasible
ADDITIONAL_CAPABILITIES: frozenset[AdditionalCapability]#
property solver_input: highspy.Highs#

The HiGHS model generated from the OMMX instance.

Returns#
highspy.Highs

The HiGHS model ready for optimization. This model contains: - Decision variables translated from OMMX IDs to HiGHS indices - Constraints converted to HiGHS linear expressions - Objective function set according to optimization direction