MathOptAI.jl v1.0 is released
releases ·Author: Oscar Dowson, Gökhan Kof, Robert Parker
We’re pleased to announce the v1.0 release of MathOptAI.jl, a library for embedding trained machine learning predictors into JuMP and ExaModels.
MathOptAI.jl was developed as part of our collaboration with Los Alamos National Laboratory.
You can find more information about MathOptAI.jl by reading the documentation, reading our paper, or by watching the talk Robby gave about MathOptAI.jl at JuMP-dev 2025.
Here’s an example of MathOptAI.jl in action:
using JuMP, MathOptAI, Flux
predictor = Flux.Chain(Flux.Dense(28^2 => 32, Flux.relu), Flux.Dense(32 => 10), Flux.softmax);
model = Model();
@variable(model, 0 <= x[1:28^2] <= 1);
y, formulation = MathOptAI.add_predictor(model, predictor, x);
The return y is a vector of JuMP decision variables that represents the
relationship y = predictor(x). Behind the scenes, MathOptAI.jl adds new
decision variables and constraints to model to enforce the relationship.
MathOptAI.jl supports adding predictors from a range of machine learning libraries, including Flux.jl, Lux.jl, and PyTorch.
Different embeddings
MathOptAI.jl supports three different ways of embedding neural networks:
- the full-space formulation adds new variables and constraints for each layer in the neural network. This is the default.
- the reduced-space formulation embeds
predictor(x)as a large nonlinear expression (usingJuMP.@expression) without adding any new variables or constraints. Pass; reduced_space = truetoadd_predictorto enable this formulation. - the gray-box formulation uses
MOI.VectorNonlinearOracleto add the constraintpredictor(x) - y == 0and automatically sets up callbacks to evaluate the function, gradient, and Hessian ofpredictor(x). Pass; gray_box = truetoadd_predictorto enable this formulation.
The gray-box formulation is particularly useful when combined with PyTorch. Given
a trained PyTorch model, use torch.save(model, "filename.pt") to save the model
structure and weights to disk. Then, from Julia do:
using JuMP, MathOptAI, PythonCall, Ipopt
model = Model(Ipopt.Optimizer)
@variable(model, x[1:10])
predictor = MathOptAI.PytorchModel("filename.pt")
y, _ = MathOptAI.add_predictor(
model, predictor, x; gray_box = true, device = "cuda")
Behind the scenes, MathOptAI.jl co-ordinates the Julia-Python communication, and the oracles related to the predictor will be evaluated on the GPU. The gray-box formulation enables MathOptAI.jl to embed very large neural networks into a JuMP model becuase we never represent the predictor algebraically.
Input Convex Neural Networks
A unique feature of MathOptAI is it’s support for input convex neural networks, which Gökhan Kof has been working on as part of the 2026 Google Summer of Code.
Input Convex Neural Networks are predictors where predictor(x) is a convex
function with respect to x. This enables the embedding y >= predictor(x),
which can be simpler to implement than the strict y == predictor(x).
As one example, ReLU can be implemented as an epigraph formulation with a
non-negative variable y >= 0 and the inequality constraint y - x >= 0
(MathOptAI.ReLUEpigraph),
instead of the non-smooth nonlinear constraint y = max(0, x)
(MathOptAI.ReLU),
or MIP formulations like MathOptAI.ReLUSOS1.
Find out more by reading Input Convex Neural Networks with Flux.jl.
How are you using MathOptAI?
If you use MathOptAI.jl, we’d love to hear about it. The best way to get in touch is by opening an issue. Tell us how you used the library, or suggest new predictors and features that we should add.