JuMP.jl Documentation

repository·master·Indexed 25 days ago

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

JuMP is a domain-specific modeling language for mathematical optimization embedded in Julia. It provides a high-level algebraic interface to formulate optimization problems using macros like @variable, @objective, and @constraint, and solves them via MathOptInterface.jl (MOI), an abstraction layer that provides a solver-independent interface to various underlying optimization solvers.

Tokens
42.6K
Snippets
110
Records
222
Agent score
71%

What's inside JuMP.jl

  1. What is JuMP?

    master

    JuMP is a domain-specific modeling language for mathematical optimization embedded in Julia. It allows users to formulate and solve various problem classes, including:

    • Linear programs
    • Integer programs
    • Conic programs
    • Semidefinite programs
    • Constrained nonlinear programs

    To use JuMP, you typically pair it with a solver (such as Ipopt) and use JuMP's macros to define variables, constraints, and objectives.

    using JuMP, Ipopt
    
    function solve_constrained_least_squares_regression(A::Matrix, b::Vector)
        m, n = size(A)
        model = Model(Ipopt.Optimizer)
        set_silent(model)
        @variable(model, x[1:n])
        @variable(model, residuals[1:m])
        @constraint(model, residuals == A * x - b)
        @constraint(model, sum(x) == 1)
        @objective(model, Min, sum(residuals.^2))
        optimize!(model)
        return value.(x)
    end
    
    A, b = rand(10, 3), rand(10)
    x = solve_constrained_least_squares_regression(A, b)
  2. Overview of JuMP.jl

    master
    JuMP is a domain-specific modeling language for mathematical optimization embedded in Julia. It allows users to formulate and solve optimization problems using various solvers within the Julia ecosystem.
  3. Use solver-independent callbacks in JuMP

    master

    JuMP provides a solver-independent way to implement three types of callbacks to modify the solve process: lazy constraints, user-cuts, and heuristic solutions.

    Supported Solvers:

    • CPLEX
    • GLPK
    • Gurobi
    • SCIP (Note: SCIP does not support lazy constraints)
    • Xpress

    Important Restrictions: During a callback, you must not use standard JuMP API calls like @constraint or set_lower_bound. Doing so results in undefined behavior (errors, incorrect solutions, or segfaults). You should only use functions explicitly allowed in the callback documentation, such as callback_node_status, callback_value, and MOI.submit with specific callback types.

    To query information, you are limited to:

    • callback_node_status(cb_data, model): Returns an MOI.CallbackNodeStatusCode indicating if the current primal solution is integer feasible.
    • callback_value(cb_data, x): Returns the current primal solution value of a variable.
  4. What is MathOptInterface?

    master

    MathOptInterface (MOI) is an abstraction layer that provides a solver-independent interface to mathematical optimization solvers. It allows users to interact with different solvers through a unified API.

    MOI consists of three main components:

    1. Solver-independent API: Abstracts operations like adding/deleting variables and constraints, setting parameters, and querying results.
    2. Automatic rewriting system: Uses equivalent formulations of constraints to bridge differences between solvers.
    3. Utilities: Manages how and when models are copied to solvers (e.g., via CachingOptimizer).
  5. What is an algebraic modeling language?

    master

    An algebraic modeling language (AML) simplifies the translation between a user's mathematical (algebraic) formulation and the standard form required by optimization solvers.

    An AML consists of two main parts:

    1. A domain-specific language for users to write problems in algebraic form (e.g., using sums, inequalities, and sets).
    2. A converter that translates that algebraic form into the specific API and data structures required by a solver.

    JuMP provides the algebraic interface, while it uses MathOptInterface.jl (MOI) to abstract the differences between various solvers, allowing you to change solvers without rewriting your model.

  6. How JuMP extensions work via weak dependencies

    master
    Some JuMP extensions use Julia's weak dependency feature (available in Julia v1.9+). These extensions are automatically activated only when both JuMP and the specific extension package are loaded into your current scope using using or import. This allows JuMP to provide extended functionality seamlessly without requiring you to explicitly install every possible extension.
  7. Understanding JuMP's symbolic algebra capabilities

    master

    JuMP provides a basic framework for symbolic simplification and differentiation.

    Key characteristics:

    • Limited Scope: The tools are purposefully limited and are not intended to replace a dedicated Computer Algebraic System (CAS).
    • Performance: Runtime performance is not a primary design consideration for these symbolic operations.
    • Recommendation: If you require advanced symbolic manipulation or encounter limitations with JuMP's built-in functions, use a purpose-built CAS such as Symbolics.jl.
  8. How to use solvers that expect environments

    master

    Some solvers require positional arguments (like license paths or sub-solver configurations). For these, pass a zero-argument function to the Model constructor that returns the optimizer instance.

    import HiGHS
    import MultiObjectiveAlgorithms as MOA
    
    # Pass a function that returns the configured optimizer
    model = Model(() -> MOA.Optimizer(HiGHS.Optimizer))
  9. When not to use JuMP for complicated Julia functions

    master

    JuMP is not designed for optimizing arbitrary, complicated Julia functions (e.g., optimizing an ODE from DifferentialEquations.jl or tuning a neural network from Flux.jl).

    If your goal is to optimize a general Julia function, consider these alternatives:

    • Optim.jl
    • Optimization.jl
    • NLPModels.jl
    • Nonconvex.jl
  10. Explore the JLL artifact structure

    master

    Before overriding a binary, you must identify the location and structure of the existing JLL artifact. You can find the artifact directory using the .artifact_dir property of the JLL package.

    Common directory structures include:

    • lib/: Contains dynamic libraries (e.g., libecos.dylib).
    • bin/: Contains executables (e.g., cbc).
    • include/: Contains header files.
    • share/ or logs/: Other metadata or support files.
    using ECOS_jll
    # Get the path to the current artifact
    ECOS_jll.artifact_dir
    
    # Inspect the contents
    readdir(ECOS_jll.artifact_dir)
    readdir(joinpath(ECOS_jll.artifact_dir, "lib"))
  11. Avoid bugs when initializing arrays of expressions

    master

    When creating arrays of expressions (like AffExpr), avoid using zeros(AffExpr, n) or broadcasting x .= 0. Because JuMP implements zero(AffExpr) as a single shared instance, modifying one element in such an array using add_to_expression! will modify all elements in the array.

    Recommended approach: Use a list comprehension to create unique instances for each index.

    Incorrect (Shared instances):

    x = zeros(AffExpr, 2)
    add_to_expression!(x[1], 1.1) # Modifies both x[1] and x[2]

    Correct (Unique instances):

    x = [zero(AffExpr) for _ in 1:2]
    add_to_expression!(x[1], 1.1) # Modifies only x[1]