API reference#
Models#
Choose import jumpy.highs as jp for compiled HiGHS, or
import jumpy.juliacall as jp for JuliaCall. Each provides jp.Model() with no
backend argument and the same expression helpers. Use one interface per
process; native objects cannot cross between their Julia runtimes.
Compiled HiGHS’s jp.Model() includes HiGHS. JuliaCall constructors follow
JuMP’s solver selection:
jp.Model()callsJuMP.Model()and creates a model without a solver.jp.Model(jl.HiGHS.Optimizer)callsJuMP.Model(HiGHS.Optimizer), using the Julia constructor as an optimizer factory.jp.direct_model(jl.HiGHS.Optimizer())callsJuMP.direct_model(HiGHS.Optimizer()), using the supplied optimizer instance.
Install and import the selected solver in the JuliaCall environment first. By default, cached models register GenOpt’s bridges. Direct models add neither a cache nor bridges; their optimizer determines which functions and sets they support. JuliaCall constructors preserve JuMP’s solver-output defaults.
- class jumpy.highs.Model#
A model using the compiled HiGHS library.
- constraint(func, set_=None) ConstraintRef#
Add
constraint(x <= 1)orconstraint(x, jp.MOI.LessThan(1.0)).Comparison syntax forwards the same function and native set to the explicit form. Julia handles simplification and constant normalization.
- constraint_group(con: Constraint) ConstraintRef#
Add a constraint group: one constraint per combination of the values of the iterators appearing in the template.
- Example:
i = m.iterator(range(99)) m.constraint_group(x[i] + x[i + 1] <= 10)
- dual(constraint: ConstraintRef) float#
Query a scalar constraint’s raw MOI dual, not a shadow price.
MIPs normally have no duals; solve a continuous relaxation separately.
- iterator(values) Node#
An index set for constraint groups (a GenOpt iterator).
Used in expressions, it is a symbolic placeholder that GenOpt expands over its values when the group constraint is added.
- lazy_sum(template) Node#
Sum a GenOpt template without expanding its symbolic iterators.
For example,
model.lazy_sum(cost[i] * x[i])retains the repeated expression’s structure instead of consuming a Python iterable.
- parameter(values, name: str | None = None) Parameter#
A vector of constant data, symbolically indexable in templates.
- set_time_limit_sec(seconds: float | None) None#
Set a positive finite solve time limit in seconds, or clear it with None.
- class jumpy.juliacall.Model(optimizer=None, **kwargs)#
A cached JuMP model, optionally initialized with an optimizer factory.
With no factory, the model has no optimizer. Native Julia constructors and Python callables are accepted; keyword arguments are forwarded to JuMP.
- jumpy.juliacall.direct_model(optimizer, **kwargs)#
Wrap
JuMP.direct_model(optimizer)without adding caches or bridges.
Solve time limits#
model.set_time_limit_sec(seconds) sets a positive finite limit in seconds for
either backend. model.unset_time_limit_sec() clears it before the next solve;
model.set_time_limit_sec(None) is equivalent:
model.set_time_limit_sec(60.0)
model.optimize()
model.unset_time_limit_sec()
If the limit is reached, optimize() returns the termination status normally.
Use model.has_values() to check whether a solution is available.
Function-in-set constraints#
Comparison syntax and explicit MOI sets are both supported:
import jumpy.highs as jp
model = jp.Model()
x, y = model.variables(2, lower=0)
model.constraint(x + y, jp.MOI.LessThan(1.0))
model.constraint(x + y >= 0.5)
z = model.variable()
model.constraint(z, jp.MOI.Integer())
The explicit function must be a scalar expression, variable, or number.
Comparisons are shorthand: model.constraint(x <= 1) delegates to
model.constraint(x, jp.MOI.LessThan(1.0)). In either form, a bare variable keeps
MOI’s variable-in-set semantics, including bounds and integrality. Use an
expression such as x + 0 to add an affine row instead of a bound.
Comparisons, variable bounds, and constraint groups all use native MOI sets
internally, just like explicit function-in-set constraints.
jumpy.highs.MOI exposes LessThan(upper), GreaterThan(lower),
EqualTo(value), ZeroOne(), and Integer(). Each creates a native Julia set
behind an opaque Python handle; other constructor names raise a clear error.
jumpy.juliacall.MOI is the actual Julia module, with the chosen optimizer and
its bridges determining which constraints it supports.
Use floating-point bounds such as 1.0 for HiGHS sets; comparison operators
convert numeric bounds to floats automatically.
Symbolic comparisons create constraints, not Python booleans. Using them in
if, membership tests such as x in [y], or chained comparisons such as
0 <= x <= 1 raises TypeError. Add the two bounds separately, and use
identity checks such as any(x is variable for variable in variables) when
checking whether a particular Python variable object is in a collection.
Compiled sets are released automatically. A saved set can be reused across
models of the same interface, even after a model closes. For explicit lifetime
control, call its close() method or use it as a context manager; a closed set
cannot be reused.
Expressions#
model.lazy_sum(template) creates a native GenOpt LazySum, preserving its
expression template and iterators for solvers such as ExaModels. With ExaModels
and MadNLP installed in the JuliaCall environment:
import jumpy.juliacall as jp
from juliacall import Main as jl
jl.seval("using ExaModels, MadNLP")
model = jp.Model(lambda: jl.ExaModels.Optimizer(jl.MadNLP.madnlp))
x = model.variables(3, lower=0)
cost = model.parameter([2, 3, 4])
i = model.iterator(range(3))
model.objective = jp.minimize(model.lazy_sum(cost[i] * x[i]))
The zero-argument Python factory lets JuMP construct the optimizer with its
solver function.
The lazy_sum argument is one symbolic template, not a Python iterable or
generator. With HiGHS, GenOpt lowers affine lazy sums and quadratic lazy-sum
objectives to ordinary solver functions. Python’s built-in sum() remains
available for explicit sums.
Direct model.value(lazy_sum_expression) queries are not currently supported.
Python operators call JuMP’s native arithmetic and keep only opaque references
to the resulting expressions. JuMP determines whether an expression is affine,
quadratic, or nonlinear. HiGHS supports convex quadratic objectives such as
model.objective = jp.minimize((x - 2) ** 2); unsupported functions produce
solver errors.
Integer literals and integer iterator values retain their types. In particular,
x ** 2 uses JuMP’s quadratic arithmetic, while x ** 2.0 is nonlinear.
The compiled interface requires integer literals and integer-only iterators to fit in
Julia’s Int64; out-of-range values raise OverflowError before the C call.
Variable arrays hold native Julia array references. Concrete indices are local
to their array and follow Python’s zero-based and negative-index conventions;
out-of-range indices raise IndexError, even if the model has other arrays.
After optimizing, model.value(x) or model.value(2 * x + 1) queries the
current solution in JuMP directly, without a Python column mapping or solution
cache. Querying variable values before solving raises a backend error.
Expressions must belong to the queried model, and the model must still be open.
Solve results#
model.optimize() returns the native MOI termination status code (1 means
OPTIMAL), including nonoptimal termination such as a time limit or
infeasibility. Check solution availability before querying values:
status = model.optimize()
if model.has_values():
print(model.objective_value())
print(model.value(x))
model.termination_status() queries the current status without solving.
model.has_values() and model.has_duals() query primal and dual result
availability; MIPs normally have no dual solution. model.objective_value()
reads the solver’s objective value rather than reconstructing it in Python.
These queries follow JuMP’s result semantics: modifying the JuliaCall backend’s
cached model invalidates its results, while the direct HiGHS backend leaves
result availability to the solver. Reoptimize after modifying the model before
using its solution; model.value(...) rejects queries until then. Querying an
unavailable objective value raises a backend error.
Constraint groups#
Symbolic indexing creates native GenOpt expression templates.
model.constraint_group(con) delegates to model.constraint(con), which uses
JuMP’s constraint construction and GenOpt’s bridge to expand iterator-based
constraints. There is no separate Python group insertion or classification path.
Constraint references and duals#
model.constraint(...) and model.constraint_group(...) return opaque
jp.ConstraintRef objects owned by the model. Retain a scalar constraint’s
reference to query its dual:
model = jp.Model()
x = model.variable(lower=0)
capacity = model.constraint(x + 0 <= 2)
model.objective = jp.maximize(x)
model.optimize()
assert model.has_duals()
assert model.dual(capacity) == -1.0
These are raw MOI duals, not objective-sense-adjusted shadow prices. A <= row
has a nonpositive dual even under maximization; negate its dual for a
maximization capacity shadow price. Duals describe the continuous problem, and
MIPs normally have no dual solution: solve a separate continuous relaxation
when marginal capacity prices are needed.
References cannot be queried through another or a closed model. Querying before solving or without a dual solution raises a backend error. After modifications, dual availability follows the same JuMP semantics as other result queries above. A generated constraint group has no single scalar dual and is rejected.
- class jumpy.Variable(ops, ref, name: str | None = None)#
An opaque handle to a native JuMP variable.
- class jumpy.VariableVector(ops, ref, count: int, name: str | None = None)#
A native Julia array of variables returned by Model.variables().
Concrete indexing (x[0]) returns a Variable; symbolic indexing (x[i] with an expression) builds a GenOpt template over the same array.
- class jumpy.Parameter(ops, values, name: str | None = None)#
A vector of constant data returned by Model.parameter().
Concrete indexing (costs[0]) returns a float; symbolic indexing (costs[i]) builds a getindex template node over the data vector.
- class jumpy.Node(ops, ref)#
A handle to a Julia expression owned by the model’s backend.
- class jumpy.ConstraintRef(ops, ref)#
An opaque reference to an added scalar constraint or constraint group.
Nonlinear functions#
- jumpy.sin(x)#
- jumpy.cos(x)#
- jumpy.exp(x)#
- jumpy.log(x)#
- jumpy.sqrt(x)#
- jumpy.jp_abs(x)#