What’s New
1 Optyx v1.3.2
Theme: Correctness, reliability, and maintenance
This patch release strengthens the existing v1.3 API without introducing a new solver abstraction.
- Solver caches and warm starts are guarded by the current variable layout.
- SLSQP candidates are checked for finite values, bounds, constraints, and stationarity before they can be reported as optimal; invalid candidates can be retried with
trust-constr. Solution.is_feasiblenow requires measured feasibility evidence, exposed asconstraint_violation,feasibility_tolerance, andfeasibility_checked.- Polynomial degree analysis consistently handles parameters, products,
NarySum, andNaryProduct. - Scalar, vector, and matrix variable bounds and domains are validated early.
- Conflicting variables that share a name are rejected with an actionable error.
- Changes to
Variable.objare reflected in the next LP or MILP solve. - Solves no longer mutate the process-wide warning handler.
Problem.summary()includes matrix constraint rows in equality and inequality totals.- Obsolete SciPy compatibility code and stale source helpers were removed, and the source tree passes Pyright without warnings.
2 Optyx v1.3.1
This release reduced construction and solve overhead for large vector-backed models while preserving the public API.
- Lazy
VectorVariablemetadata avoids unnecessary scalar materialization. - Single-vector NLP objectives compile through a contiguous vector layout.
- Solution value dictionaries are materialized only when accessed.
See the project changelog for the complete release record.
3 Optyx v1.3.0
Theme: Scalable Expressions, Vectorized Gradients, Sparse Computation, Basic MIP, Modeling Convenience
This release addresses critical scalability limitations discovered in v1.2.x benchmarks and adds major new capabilities.
3.1 Mixed-Integer Linear Programming (MILP)
Optyx now supports integer and binary decision variables, automatically routing problems with discrete variables to the MILP solver (SciPy’s HiGHS backend via scipy.optimize.milp()).
BinaryVariable()andIntegerVariable()constructor aliasesVectorVariable(domain="binary")andVectorVariable(domain="integer")for vectorized discrete variablesSolution.mip_gapandSolution.best_boundfor optimality reporting- Domain validation enforces correct bounds for binary variables
- Clear error when attempting unsupported MIQP (quadratic + integer)
See the Integer Programming tutorial and the Mine Equipment MILP example.
3.2 Vectorized Gradients & Scalability
Cold-start performance for quadratic programs has been dramatically improved through automatic vectorized gradient detection.
| Problem | Cold Overhead vs SciPy | Warm Overhead vs SciPy |
|---|---|---|
| CQP n=500 | 2.2x | 1.2x |
| CQP n=1,000 | 1.8x | 1.2x |
| CQP n=5,000 | 1.1x | 1.0x |
VectorGradientPatterndetects expressions with vectorizable gradient structure (∇f = Ax + b)NarySum/NaryProductflatten deep loop-built trees to O(1) depthVectorBinaryOppreserves vector structure for element-wise operations
See the Benchmarks and the Performance & Scaling guide.
3.3 Sparse Computation
Large-scale LPs with 100,000+ variables are now practical.
Problem.subject_to(A @ x <= b)supports matrix blocks directly, withas_matrix(...)for sparse coefficient matricesas_matrix(storage="auto" | "dense" | "sparse")gives explicit control over matrix-block storage, with automatic CSR conversion for large low-density dense arrays- Sparse Jacobian compilation reduces memory from O(m×n) to O(nnz)
- Sparse constrained NLPs now bias toward
trust-constrsooner, lazily compiling the batched sparse Jacobian only when that solver path is actually used - n=100,000 LP with 1% density constraint matrix solves end-to-end
3.4 Modeling Convenience
VariableDict— dict-indexed variables keyed by strings, with.prod()and.sum(subset)aggregation. See the VariableDict tutorial.Expression.between(lb, ub)— range constraints in one callsubject_to()accepts generators —prob.subject_to(x[i] >= 0 for i in range(n))Problemcontext manager —with Problem() as p: ...Problem.reset()— clear solver cache and warm-start stateProblem.remove_constraint()— incremental model modification- Warm starts — re-solves automatically use the previous solution
- Bounds correctness fix — variable bounds are never cached, enabling fix-and-dive patterns
3.5 Solver Callbacks & Termination
SolverProgressdataclass with iteration, objective, violation, elapsed time, and current xcallback=parameter onsolve()— returnTrueto stop earlytime_limit=parameter onsolve()— wall-clock budgetSolverStatus.TERMINATEDfor callback-initiated stops
See the Solver Callbacks example.
3.6 Serialization & I/O
Problem.write("model.lp")— export to LP format (linear and quadratic objectives, constraints, bounds, integer/binary sections)Solution.to_dict()andSolution.to_json()— solution serialization for logging and auditing
See the LP Export example.
3.7 Per-Element Array Bounds & Fancy Indexing
- Array bounds on
VectorVariable:VectorVariable("x", 3, lb=np.array([0, 0.5, 0.2])) - Fancy indexing:
x[[0, 2, 5]]returns a subset vector expression
See the Vector Variables tutorial.