MathOptInterface.jl
repository·master·Indexed 19 days ago
https://github.com/jump-dev/mathoptinterface.jlAn abstraction layer for mathematical optimization solvers that provides a standardized data structure and interface to facilitate interoperability between different optimization tools and solvers.
What's inside MathOptInterface.jl
- MathOptInterface is an abstraction layer designed for mathematical optimization solvers. It provides a standardized data structure and interface that allows different optimization tools and solvers to communicate using a common language, facilitating interoperability within the mathematical optimization ecosystem.
What is MathOptInterface?
masterMathOptInterface.jl (MOI) is an abstraction layer that provides a unified interface to mathematical optimization solvers. It is designed so that users and developers do not need to interact with multiple solver-specific APIs.
Target Audience: This project is intended for developers who are:
- Writing software interfaces to solvers.
- Writing modeling languages that use the MathOptInterface API.
Note for Problem Solvers: If you are looking to solve optimization problems rather than build solver interfaces or modeling languages, you should use a higher-level modeling interface such as JuMP or Convex.jl instead of using MOI directly.
Nonlinear Programming (NLP) Interface in MathOptInterface
masterMathOptInterface provides a standardized interface for Nonlinear Programming (NLP) solvers. This interface allows users to define nonlinear problems through specific types for evaluators, block data, and bounds, and provides a suite of functions to compute objectives, constraints, gradients, Jacobians, and Hessians.Use the FileFormats submodule to read and write models
masterThe
FileFormatssubmodule allows you to read and write MathOptInterface models using specific file formats. You must interact with aFileFormats.Modelobject, which acts as a container for the model data in a specific format.To use it, you typically:
- Create a
FileFormats.Modelspecifying the format. - Use
MOI.copy_to(dest, src)to move data from a standard model into the file-format model. - Use
MOI.write_to_file(dest, "filename")to save it, orMOI.read_from_file(dest, "filename")to load it.
# Writing a model src = MOI.Utilities.Model{Float64}(); MOI.add_variable(src); dest = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_MOF); MOI.copy_to(dest, src) MOI.write_to_file(dest, "file.mof.json") # Reading a model dest = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_MOF); MOI.read_from_file(dest, "file.mof.json")- Create a
Read and write MOI models using FileFormats
masterThe
FileFormatssubmodule provides functions to serialize MathOptInterface (MOI) models to and from various standard file formats. This allows you to export a model constructed in Julia to a file or import an existing optimization model file into an MOI model object.Supported formats include:
- CBF (
FORMAT_CBF) - LP (
FORMAT_LP) - MOF (
FORMAT_MOF) - MPS (
FORMAT_MPS) - NL (
FORMAT_NL) - REW (
FORMAT_REW) - SDPA (
FORMAT_SDPA) - Automatic Detection (
FORMAT_AUTOMATIC)
Each format typically has a corresponding
Modeltype (e.g.,FileFormats.LP.Model) used for specific parsing or generation tasks.- CBF (
How SymbolicAD works and when to use it
masterThe
MathOptInterface.Nonlinear.SymbolicADsubmodule provides tools for computing symbolic derivatives of nonlinear optimization problems.When to use it
Symbolic differentiation is most effective for large-scale models with many repetitive constraints (e.g., a model with 10,000 constraints that all follow the same functional form like
sin(x[i])). In these cases, it is faster to compute one symbolic derivative and evaluate it for all instances rather than differentiating every unique expression.When to avoid it
Avoid
SymbolicADif:- The model has a very large number of unique constraints (which increases the symbolic differentiation workload).
- The nonlinear functions contain a very large number of nonlinear terms (which makes the symbolic derivative itself expensive to compute).
In such cases, the default
MOI.Nonlinear.SparseReverseMode(sparse reverse mode automatic differentiation) is generally preferred.Implement a SetMap bridge for constraints or variables
masterIf you are implementing a bridge where a reformulation follows the pattern
f(x) ∈ F$\to$g(x) ∈ G(where no new variables or constraints are added, only the function and set are mapped), use theSetMapBridgepattern.To implement this:
- Subtype
Bridges.Constraint.SetMapBridgefor constraint reformulations. - Subtype
Bridges.Variable.SetMapBridgefor variable reformulations. - Implement the API defined in the respective type's docstring.
- Subtype
Use Callbacks in MathOptInterface
masterMathOptInterface (MOI) provides a callback mechanism to interact with a solver during its execution. You can implement custom logic by defining types that inherit from
AbstractCallbackorAbstractSubmittable. The primary way to trigger callback logic is via thesubmitfunction, which allows you to pass submittable objects (like constraints or cuts) back to the solver.import MathOptInterface as MOI # Implementation involves defining types that follow the MOI callback interface # and using MOI.submit(callback, submittable)Configure Automatic-differentiation (AD) backends
masterMathOptInterface supports various automatic-differentiation strategies through the
Nonlinear.Evaluatorinterface. Key backend types include:Nonlinear.AbstractAutomaticDifferentiation: The base type for AD backends.Nonlinear.ExprGraphOnly: AD based on expression graphs.Nonlinear.SparseReverseMode: Sparse reverse-mode AD.Nonlinear.SymbolicMode: Symbolic differentiation mode.
Fix latency by resolving lack of method ownership
masterLatency often occurs when a method is called using a mix of structs and methods from different modules, meaning no single module "owns" the method and it cannot be precompiled. This is common in MOI when
MOI.Utilitieswraps externalOptimizertypes.To fix this, you can create a "back-edge" by forcing the external module to call the specific MOI method during its own initialization. Use a specific
let-whileloop pattern to ensure the call is compiled without polluting the module's namespace:- Use
let ... endto keep variables local. - Use
while true ... break endto force Julia to compile the inner loop rather than interpreting it.
This effectively designates the external module as the owner of the method, allowing it to be precompiled.
module MyOptimizer using ..MyMOI struct Optimizer end MyMOI.optimize!(x::Optimizer) = 1 # Fix: Force compilation of the specific method to create a back-edge let while true model = MyMOI.Wrapper(Optimizer()) MyMOI.optimize(model) break end end end- Use
How Models and Optimizers work together in MathOptInterface
masterMathOptInterface (MOI) separates the specification of an optimization problem from the process of solving it.
ModelLike: An object that implements the model API used to specify an optimization problem (e.g., adding variables and constraints). AModelLikeobject can exist independently of a solver and may be stored in memory or a file format.AbstractOptimizer: An object that provides the methods to solve aModelLikeobject and interact with the resulting solutions.
In MOI terminology,
modelrefers to a genericModelLikeinstance, andoptimizerrefers to a genericAbstractOptimizerinstance.How unbounded problems are represented via dual infeasibility
masterIn MathOptInterface, a problem is considered unbounded if a feasible primal solution exists but the dual is infeasible. Because solvers often prove dual infeasibility before finding a primal solution, MathOptInterface uses the status
DUAL_INFEASIBLEinstead ofUNBOUNDED.A certificate of dual infeasibility is an improving ray
d. For a minimization problem, this ray satisfiesa_0ᵀ d < 0. For a maximization problem, it satisfiesa_0ᵀ d > 0.When a solver provides a certificate of dual infeasibility, the following fields are populated:
TerminationStatusisDUAL_INFEASIBLE.PrimalStatusisINFEASIBILITY_CERTIFICATE.VariablePrimalcontains the vectord.ConstraintPrimalcontains the valuesA_i d.ObjectiveValuecontains the valuea_0ᵀ d(the objective value atd, ignoring the constantb_0).