MathOptInterface.jl

repository·master·Indexed 19 days ago

https://github.com/jump-dev/mathoptinterface.jl

An abstraction layer for mathematical optimization solvers that provides a standardized data structure and interface to facilitate interoperability between different optimization tools and solvers.

Tokens
49.5K
Snippets
130
Records
205
Agent score
67%

What's inside MathOptInterface.jl

  1. Overview of MathOptInterface

    master
    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.
  2. What is MathOptInterface?

    master

    MathOptInterface.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:

    1. Writing software interfaces to solvers.
    2. 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.

  3. Nonlinear Programming (NLP) Interface in MathOptInterface

    master
    MathOptInterface 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.
  4. Use the FileFormats submodule to read and write models

    master

    The FileFormats submodule allows you to read and write MathOptInterface models using specific file formats. You must interact with a FileFormats.Model object, which acts as a container for the model data in a specific format.

    To use it, you typically:

    1. Create a FileFormats.Model specifying the format.
    2. Use MOI.copy_to(dest, src) to move data from a standard model into the file-format model.
    3. Use MOI.write_to_file(dest, "filename") to save it, or MOI.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")
  5. Read and write MOI models using FileFormats

    master

    The FileFormats submodule 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 Model type (e.g., FileFormats.LP.Model) used for specific parsing or generation tasks.

  6. How SymbolicAD works and when to use it

    master

    The MathOptInterface.Nonlinear.SymbolicAD submodule 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 SymbolicAD if:

    • 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.

  7. Implement a SetMap bridge for constraints or variables

    master

    If 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 the SetMapBridge pattern.

    To implement this:

    1. Subtype Bridges.Constraint.SetMapBridge for constraint reformulations.
    2. Subtype Bridges.Variable.SetMapBridge for variable reformulations.
    3. Implement the API defined in the respective type's docstring.
  8. Use Callbacks in MathOptInterface

    master

    MathOptInterface (MOI) provides a callback mechanism to interact with a solver during its execution. You can implement custom logic by defining types that inherit from AbstractCallback or AbstractSubmittable. The primary way to trigger callback logic is via the submit function, 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)
  9. Configure Automatic-differentiation (AD) backends

    master

    MathOptInterface supports various automatic-differentiation strategies through the Nonlinear.Evaluator interface. 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.
  10. Fix latency by resolving lack of method ownership

    master

    Latency 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.Utilities wraps external Optimizer types.

    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-while loop pattern to ensure the call is compiled without polluting the module's namespace:

    1. Use let ... end to keep variables local.
    2. Use while true ... break end to 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
  11. How Models and Optimizers work together in MathOptInterface

    master

    MathOptInterface (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). A ModelLike object 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 a ModelLike object and interact with the resulting solutions.

    In MOI terminology, model refers to a generic ModelLike instance, and optimizer refers to a generic AbstractOptimizer instance.

  12. How unbounded problems are represented via dual infeasibility

    master

    In 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_INFEASIBLE instead of UNBOUNDED.

    A certificate of dual infeasibility is an improving ray d. For a minimization problem, this ray satisfies a_0ᵀ d < 0. For a maximization problem, it satisfies a_0ᵀ d > 0.

    When a solver provides a certificate of dual infeasibility, the following fields are populated:

    • TerminationStatus is DUAL_INFEASIBLE.
    • PrimalStatus is INFEASIBILITY_CERTIFICATE.
    • VariablePrimal contains the vector d.
    • ConstraintPrimal contains the values A_i d.
    • ObjectiveValue contains the value a_0ᵀ d (the objective value at d, ignoring the constant b_0).