### Example Diet Problem with MathOptInterface Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/tutorials/latency.md Demonstrates setting up and solving a diet optimization problem using MathOptInterface. Includes options for using bridges and caching optimizers. This example can be used to profile latency. ```julia import GLPK import MathOptInterface as MOI function example_diet(optimizer, bridge) category_data = [ 1800.0 2200.0; 91.0 Inf; 0.0 65.0; 0.0 1779.0 ] cost = [2.49, 2.89, 1.50, 1.89, 2.09, 1.99, 2.49, 0.89, 1.59] food_data = [ 410 24 26 730; 420 32 10 1190; 560 20 32 1800; 380 4 19 270; 320 12 10 930; 320 15 12 820; 320 31 12 1230; 100 8 2.5 125; 330 8 10 180 ] bridge_model = if bridge MOI.instantiate(optimizer; with_bridge_type=Float64) else MOI.instantiate(optimizer) end model = MOI.Utilities.CachingOptimizer( MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()), MOI.Utilities.AUTOMATIC, ) MOI.Utilities.reset_optimizer(model, bridge_model) MOI.set(model, MOI.Silent(), true) nutrition = MOI.add_variables(model, size(category_data, 1)) for (i, v) in enumerate(nutrition) MOI.add_constraint(model, v, MOI.GreaterThan(category_data[i, 1])) MOI.add_constraint(model, v, MOI.LessThan(category_data[i, 2])) end buy = MOI.add_variables(model, size(food_data, 1)) MOI.add_constraint.(model, buy, MOI.GreaterThan(0.0)) MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE) f = MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.(cost, buy), 0.0) MOI.set(model, MOI.ObjectiveFunction{typeof(f)}(), f) for (j, n) in enumerate(nutrition) f = MOI.ScalarAffineFunction( MOI.ScalarAffineTerm.(food_data[:, j], buy), 0.0, ) push!(f.terms, MOI.ScalarAffineTerm(-1.0, n)) MOI.add_constraint(model, f, MOI.EqualTo(0.0)) end MOI.optimize!(model) term_status = MOI.get(model, MOI.TerminationStatus()) @assert term_status == MOI.OPTIMAL MOI.add_constraint( model, MOI.ScalarAffineFunction( MOI.ScalarAffineTerm.(1.0, [buy[end-1], buy[end]]), 0.0, ), MOI.LessThan(6.0), ) MOI.optimize!(model) @assert MOI.get(model, MOI.TerminationStatus()) == MOI.INFEASIBLE return end if length(ARGS) > 0 bridge = get(ARGS, 2, "") != "--no-bridge" println("Running: $(ARGS[1]) $(get(ARGS, 2, ""))") @time example_diet(GLPK.Optimizer, bridge) @time example_diet(GLPK.Optimizer, bridge) exit(0) end ``` -------------------------------- ### Install and Load BenchmarkTools.jl Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/submodules/Benchmarks/overview.md Before using the MOI.Benchmarks submodule, you must install and load the BenchmarkTools.jl package. This is a prerequisite for running any benchmarks. ```julia import Pkg Pkg.add("BenchmarkTools") import BenchmarkTools ``` -------------------------------- ### Initialize GLPK Optimizer Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/tutorials/example.md Initializes the GLPK optimizer for use with MathOptInterface. Ensure GLPK is installed and available. ```julia using GLPK optimizer = GLPK.Optimizer() ``` -------------------------------- ### Install MathOptInterface in dev mode Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/submodules/Test/overview.md Installs the MathOptInterface package in development mode, allowing for local modifications. ```julia julia> ] (@v1.6) pkg> dev MathOptInterface ``` -------------------------------- ### Instantiate Single Bridge Optimizer with Mock Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/tutorials/bridging_constraint.md Example of using `SingleBridgeOptimizer` with `Utilities.MockOptimizer` for unit testing purposes. ```julia mock = Utilities.MockOptimizer( Utilities.UniversalFallback(Utilities.Model{Float64}()), ) bridged_mock = Sign{Float64}(mock) ``` -------------------------------- ### Using SymbolicAD with JuMP Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/submodules/Nonlinear/SymbolicAD.md Set the AutomaticDifferentiationBackend attribute to Nonlinear.SymbolicMode to enable symbolic differentiation with JuMP. This example demonstrates setting up a model with Ipopt and a quadratic objective function. ```julia using JuMP, Ipopt model = Model(Ipopt.Optimizer) set_attribute( model, MOI.AutomaticDifferentiationBackend(), MOI.Nonlinear.SymbolicMode(), ) @variable(model, x[1:2]) @objective(model, Min, (1 - x[1])^2 + 100 * (x[2] - x[1]^2)^2) optimize!(model) ``` -------------------------------- ### Build Nonlinear Optimization Model Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/submodules/Nonlinear/overview.md A complete example demonstrating how to build a nonlinear optimization model in MathOptInterface, including adding variables, setting the objective, creating a nonlinear evaluator, and setting the NLPBlock attribute. ```example import MathOptInterface as MOI function build_model( model::MOI.ModelLike; backend::MOI.Nonlinear.AbstractAutomaticDifferentiation, ) x = MOI.add_variable(model) y = MOI.add_variable(model) MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE) nl_model = MOI.Nonlinear.Model() MOI.Nonlinear.set_objective(nl_model, :($x^2 + $y^2)) evaluator = MOI.Nonlinear.Evaluator(nl_model, backend, [x, y]) MOI.set(model, MOI.NLPBlock(), MOI.NLPBlockData(evaluator)) return end # Replace `model` and `backend` with your optimizer and backend of choice. model = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()) build_model(model; backend = MOI.Nonlinear.SparseReverseMode()) ``` -------------------------------- ### Initialize CachingOptimizer Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/submodules/Utilities/overview.md Initializes a CachingOptimizer with a model cache and a PathOptimizer. The optimizer starts in the EMPTY_OPTIMIZER state. ```jldoctest pathoptimizer julia> model = MOI.Utilities.CachingOptimizer( MOI.Utilities.Model{Float64}(), PathOptimizer{Float64}(), ) MOIU.CachingOptimizer ├ state: EMPTY_OPTIMIZER ├ mode: AUTOMATIC ├ model_cache: MOIU.Model{Float64} │ ├ ObjectiveSense: FEASIBILITY_SENSE │ ├ ObjectiveFunctionType: MOI.ScalarAffineFunction{Float64} │ ├ NumberOfVariables: 0 │ └ NumberOfConstraints: 0 └ optimizer: MOIU.GenericOptimizer{Float64, MOIU.ObjectiveContainer{Float64}, MOIU.VariablesContainer{Float64}, MOIU.VectorOfConstraints{MOI.VectorAffineFunction{Float64}, MOI.Complements}} ├ ObjectiveSense: FEASIBILITY_SENSE ├ ObjectiveFunctionType: MOI.ScalarAffineFunction{Float64} ├ NumberOfVariables: 0 └ NumberOfConstraints: 0 ``` -------------------------------- ### Load MathOptInterface module Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/tutorials/example.md Loads the MathOptInterface module and defines a shorthand alias 'MOI'. This is a common setup step for using MOI. ```julia import MathOptInterface as MOI ``` -------------------------------- ### Set and Get Constraint Name Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/manual/constraints.md Demonstrates setting and getting the `ConstraintName` attribute for a constraint using `set` and `get`. ```julia julia> MOI.set(model, MOI.ConstraintName(), c, "con_c") julia> MOI.get(model, MOI.ConstraintName(), c) "con_c" ``` -------------------------------- ### Initialize CachingOptimizer in Manual Mode Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/submodules/Utilities/overview.md Initializes a CachingOptimizer in MANUAL mode, requiring explicit state management by the user. The optimizer starts in the NO_OPTIMIZER state. ```jldoctest pathoptimizer julia> model = MOI.Utilities.CachingOptimizer( MOI.Utilities.Model{Float64}(), MOI.Utilities.MANUAL, ) MOIU.CachingOptimizer ├ state: NO_OPTIMIZER ``` -------------------------------- ### Non-simplification Example (sin^2 + cos^2) Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/submodules/Nonlinear/SymbolicAD.md Demonstrates that SymbolicAD does not perform complex trigonometric identities like sin(x)^2 + cos(x)^2 = 1. The list of rewrites is intentionally limited. ```jldoctest julia> x = MOI.VariableIndex(1) MOI.VariableIndex(1) julia> sin_x = MOI.ScalarNonlinearFunction(:sin, Any[x]) sin(MOI.VariableIndex(1)) julia> cos_x = MOI.ScalarNonlinearFunction(:cos, Any[x]) cos(MOI.VariableIndex(1)) julia> f = MOI.ScalarNonlinearFunction( :+, Any[ MOI.ScalarNonlinearFunction(:^, Any[sin_x, 2]), MOI.ScalarNonlinearFunction(:^, Any[cos_x, 2]), ], ) +(^(sin(MOI.VariableIndex(1)), (2)), ^(cos(MOI.VariableIndex(1)), (2))) julia> MOI.Nonlinear.SymbolicAD.simplify(f) +(^(sin(MOI.VariableIndex(1)), (2)), ^(cos(MOI.VariableIndex(1)), (2))) ``` -------------------------------- ### Skeleton for a solver's MOI wrapper test file Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/submodules/Test/overview.md This file defines tests for a solver named FooBar, including setup for optimizers, configuration for test parameters, and functions to run all tests. It is intended to be included in a solver's main test file. ```julia # ============================ /test/MOI_wrapper.jl ============================ module TestFooBar import FooBar using Test import MathOptInterface as MOI const OPTIMIZER = MOI.instantiate( MOI.OptimizerWithAttributes(FooBar.Optimizer, MOI.Silent() => true), ) const BRIDGED = MOI.instantiate( MOI.OptimizerWithAttributes(FooBar.Optimizer, MOI.Silent() => true), with_bridge_type = Float64, ) # See the docstring of MOI.Test.Config for other arguments. const CONFIG = MOI.Test.Config( # Modify tolerances as necessary. atol = 1e-6, rtol = 1e-6, # Use MOI.LOCALLY_SOLVED for local solvers. optimal_status = MOI.OPTIMAL, # Pass attributes or MOI functions to `exclude` to skip tests that # rely on this functionality. exclude = Any[MOI.VariableName, MOI.delete], ) """ runtests() This function runs all functions in the this Module starting with `test_`. """ function runtests() for name in names(@__MODULE__; all = true) if startswith("$(name)", "test_") @testset "$(name)" begin getfield(@__MODULE__, name)() end end end end """ test_runtests() This function runs all the tests in MathOptInterface.Test. Pass arguments to `exclude` to skip tests for functionality that is not implemented or that your solver doesn't support. """ function test_runtests() MOI.Test.runtests( BRIDGED, CONFIG, exclude = [ "test_attribute_NumberOfThreads", "test_quadratic_", ], # This argument is useful to prevent tests from failing on future # releases of MOI that add new tests. Don't let this number get too far # behind the current MOI release though. You should periodically check # for new tests to fix bugs and implement new features. exclude_tests_after = v"0.10.5", ) return end """ test_SolverName() You can also write new tests for solver-specific functionality. Write each new test as a function with a name beginning with `test_`. """ function test_SolverName() @test MOI.get(FooBar.Optimizer(), MOI.SolverName()) == "FooBar" return end end # module TestFooBar # This line at tne end of the file runs all the tests! TestFooBar.runtests() ``` -------------------------------- ### Example of Bridge Creating Binary Variables Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/tutorials/bridging_constraint.md Demonstrates how `added_constrained_variable_types` should be defined for a bridge that creates binary variables. ```julia function Bridges.added_constrained_variable_types(::Type{SomeBridge{T}}) where {T} # The bridge only creates binary variables: return Tuple{Type}[(ZeroOne,)] end ``` -------------------------------- ### Add JSONSchema for MOF Tests Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/developer/contributing.md Install the JSONSchema package, which is a test-time dependency required for running specific test files like test/FileFormats/MOF/MOF.jl. ```julia julia> import Pkg; Pkg.add("JSONSchema") ``` -------------------------------- ### Setup mock optimizer for double optimize! test Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/submodules/Test/overview.md Configures a mock optimizer to simulate the behavior of a solver when testing the double optimize! calls. This ensures the test can run even without a real solver. ```julia function setup_test( ::typeof(test_unit_optimize!_twice), model::MOI.Utilities.MockOptimizer, ::Config, ) MOI.Utilities.set_mock_optimize!( model, (mock::MOI.Utilities.MockOptimizer) -> MOIU.mock_optimize!( mock, MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [1.0]), ), ) return end ``` -------------------------------- ### Testing a Constraint Bridge with Custom Options Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/submodules/Bridges/implementation.md Customize bridge testing with `runtests` by specifying `eltype`, `print_inner_model`, `variable_start`, and `constraint_start`. This example tests `GreaterToLessBridge` with `Int` element type. ```julia MOI.Bridges.runtests( MOI.Bridges.Constraint.GreaterToLessBridge, """ variables: x x >= 1 """, """ variables: x ::Int: -1 * x <= -1 """; eltype = Int, print_inner_model = true, variable_start = 2, constraint_start = 2, ) ``` -------------------------------- ### Detect File Type from Filename and Write Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/submodules/FileFormats/overview.md Automatically detects the file type and compression from a filename when creating a MOI.FileFormats.Model. This example demonstrates creating a model with a filename, copying a source model to it, writing to the file, creating another model to read the file, and then cleaning up. ```julia src = MOI.Utilities.Model{Float64}() dest = MOI.FileFormats.Model(filename = "file.cbf.gz") MOI.copy_to(dest, src) MOI.write_to_file(dest, "file.cbf.gz") src_2 = MOI.FileFormats.Model(filename = "file.cbf.gz") MOI.read_from_file(src_2, "file.cbf.gz") rm("file.cbf.gz") # Clean up after ourselves. ``` -------------------------------- ### Testing a Constraint Bridge with runtests Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/submodules/Bridges/implementation.md Use `MOI.Bridges.runtests` to test a constraint bridge. Provide the bridge type, input model, and expected output model as strings. This example uses `GreaterToLessBridge`. ```julia MOI.Bridges.runtests( MOI.Bridges.Constraint.GreaterToLessBridge, """ variables: x x >= 1.0 """, """ variables: x -1.0 * x <= -1.0 """, ) ``` -------------------------------- ### Define Solver-Specific Attribute Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/tutorials/implementing.md Example of defining a custom attribute for a solver, including setting and getting its value. This allows solvers to expose unique functionalities. ```julia struct NumberOfObjectives <: MOI.AbstractModelAttribute end function MOI.set(model::Optimizer, ::NumberOfObjectives, n::Integer) # Code to set NumberOfObjectives return end function MOI.get(model::Optimizer, ::NumberOfObjectives) n = # Code to get NumberOfObjectives return n end ``` -------------------------------- ### Test.setup_test Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/submodules/Test/reference.md Sets up a test environment for a solver. ```APIDOC ## Test.setup_test ### Description Sets up a test environment for a solver. ### Method `setup_test(config::Config, solver)` ### Parameters - `config` (Config) - Configuration object for the tests. - `solver` - The solver to set up. ``` -------------------------------- ### Build MathOptInterface Documentation Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/developer/contributing.md Configure Julia to use the documentation project and then build the documentation using the make.jl script. ```bash $ cd ~/.julia/dev/MathOptInterface $ julia --project=docs ``` -------------------------------- ### Set and get variable name Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/manual/variables.md Variable names can be set and retrieved using `set` and `get` with the `VariableName` attribute. This is useful for identifying variables in the model. ```jldoctest julia> MOI.set(model, MOI.VariableName(), x, "var_x") julia> MOI.get(model, MOI.VariableName(), x) "var_x" ``` -------------------------------- ### Variable attributes Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/manual/variables.md Access and modify attributes of variables using `get` and `set`. ```APIDOC ## Variable attributes The following attributes are available for variables: * `VariableName` * `VariablePrimalStart` * `VariablePrimal` Get and set these attributes using `get` and `set`. ### Method ``` set(model, attribute, variable_index, value) get(model, attribute, variable_index) ``` ### Parameters * **model** (ModelLike) - The model containing the variable. * **attribute** (Variable Attribute) - The attribute to get or set. * **variable_index** (VariableIndex) - The index of the variable. * **value** - The value to set for the attribute (for `set`). ### Example ```julia model = MOI.Utilities.Model{Float64}() x = MOI.add_variable(model) MOI.set(model, MOI.VariableName(), x, "var_x") println(MOI.get(model, MOI.VariableName(), x)) ``` ``` -------------------------------- ### Develop MathOptInterface Package Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/developer/contributing.md Use Pkg.dev to download the MathOptInterface Git repository to the local development directory. ```julia julia> import Pkg julia> Pkg.dev("MathOptInterface") ``` -------------------------------- ### Add Revise Package Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/developer/contributing.md Install the Revise.jl package into your global Julia environment for faster development cycles. ```bash $ julia julia> import Pkg julia> Pkg.add("Revise") ``` -------------------------------- ### Transitioning quadprog function Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/tutorials/mathprogbase.md This snippet shows how to implement the `quadprog` function using JuMP for quadratic programming problems. ```julia using JuMP function quadprog(c, Q, A, rowlb, rowub, lb, ub, solver) N = length(c) model = Model(solver) @variable(model, lb[i] <= x[i=1:N] <= ub[i]) @objective(model, Min, c' * x + 0.5 * x' * Q * x) @constraint(model, rowlb .<= A * x .<= rowub) optimize!(model) return ( status = termination_status(model), objval = objective_value(model), sol = value.(x) ) end ``` -------------------------------- ### Prepare for Changes Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/developer/contributing.md Update your local master branch and create a new branch for your development work. ```bash git checkout master git pull git checkout -b my_new_branch ``` -------------------------------- ### Create MOF Model Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/submodules/FileFormats/overview.md Instantiate a MOI.FileFormats.Model for the MathOptFormat (MOF) file format. ```julia model = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_MOF) ``` -------------------------------- ### Implement Silent attribute for Optimizer Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/tutorials/implementing.md Provides the `get`, `set`, and `supports` methods for the `MOI.Silent` attribute, allowing control over solver verbosity. ```julia function MOI.get(model::Optimizer, ::MOI.Silent) return # true if MOI.Silent is set end function MOI.set(model::Optimizer, ::MOI.Silent, v::Bool) if v # Set a parameter to turn off printing else # Restore the default printing end return end MOI.supports(::Optimizer, ::MOI.Silent) = true ``` -------------------------------- ### Create LP Model Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/submodules/FileFormats/overview.md Instantiate a MOI.FileFormats.Model for the LP file format. ```julia model = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_LP) ``` -------------------------------- ### Package Structure for a MOI Solver Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/tutorials/implementing.md This is the recommended directory and file structure for a new MOI solver package. It includes folders for GitHub actions, code generation, the MOI wrapper, and tests. ```text /.github /workflows ci.yml format_check.yml TagBot.yml /gen gen.jl # Code to wrap the C API /src NewSolver.jl /gen libnewsolver_api.jl libnewsolver_common.jl /MOI_wrapper MOI_wrapper.jl other_files.jl /test runtests.jl /MOI_wrapper MOI_wrapper.jl .gitignore .JuliaFormatter.toml README.md LICENSE.md Project.toml ``` -------------------------------- ### Get Validation Details for Bad MOF Model Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/submodules/FileFormats/overview.md Uses JSONSchema.validate to provide detailed insights into why a MOF model fails validation against the schema. ```jldoctest schema_mof julia> JSONSchema.validate(schema, bad_model) Validation failed: path: [variables][1] instance: JSON.Object{String, Any}("NaMe" => "x") schema key: required schema value: Any["name"] ``` -------------------------------- ### Get Output Dimension of a Function Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/tutorials/manipulating_expressions.md Determines the number of dimensions in the output of a function using `MOI.output_dimension`. This is useful for understanding the structure of vector functions. ```jldoctest julia> MOI.output_dimension(g) 2 ``` -------------------------------- ### Release Checklist Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/developer/checklists.md Use this checklist when making a release of the MathOptInterface repository. It covers basic version updates, documentation changes, and GitHub action tests. ```markdown ## Basic - [ ] `version` field of `Project.toml` has been updated - If a breaking change, increment the MAJOR field and reset others to 0 - If adding new features, increment the MINOR field and reset PATCH to 0 - If adding bug fixes or documentation changes, increment the PATCH field ## Documentation - [ ] Add a new entry to `docs/src/changelog.md`, following existing style ## Tests - [ ] The `solver-tests.yml` GitHub action does not have unexpected failures. To run the action, go to: https://github.com/jump-dev/MathOptInterface.jl/actions/workflows/solver-tests.yml and click "Run workflow" - [ ] If new tests were added, ensure that `MOI.Test.version_added` is implemented. ``` -------------------------------- ### Get Solve Time with Try-Catch Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/manual/solutions.md Safely retrieve the solve time from a model, returning NaN if the attribute is unsupported. This is useful for writing solver-agnostic code. ```julia function get_solve_time(model) try return MOI.get(model, MOI.SolveTimeSec()) catch err if err isa MOI.UnsupportedAttribute return NaN # Solver doesn't support. Return a placeholder value. end rethrow(err) # Something else went wrong. Rethrow the error end end ``` -------------------------------- ### Generate Flame Graph for Latency Analysis Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/tutorials/latency.md Use SnoopCompile and ProfileView to generate a flame graph from the `example_diet` function. This visualizes performance bottlenecks, highlighting non-precompilable code (red flames). ```julia using SnoopCompile tinf = @snoopi_deep example_diet(GLPK.Optimizer, true) using ProfileView ProfileView.view(flamegraph(tinf)) ``` -------------------------------- ### Read and Write to IO Streams Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/submodules/FileFormats/overview.md Demonstrates reading and writing optimization models directly to IO streams using Base.write and Base.read!. Useful for in-memory operations or piping data. ```jldoctest julia> src = MOI.Utilities.Model{Float64}(); julia> dest = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_MPS); julia> MOI.copy_to(dest, src) MathOptInterface.Utilities.IndexMap() julia> io = IOBuffer(); julia> write(io, dest) julia> seekstart(io); julia> src_2 = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_MPS); julia> read!(io, src_2); ``` -------------------------------- ### Get Objective Function Information Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/submodules/Utilities/overview.md Retrieves the objective sense, function type, and the objective function itself from the destination cached model using standard MOI methods. ```julia MOI.get(dest, MOI.ObjectiveSense()) MAX_SENSE::OptimizationSense = 1 julia> F = MOI.get(dest, MOI.ObjectiveFunctionType()) MathOptInterface.ScalarAffineFunction{Float64} julia> F = MOI.get(dest, MOI.ObjectiveFunction{F}()) 0.0 + 1.0 MOI.VariableIndex(1) + 2.0 MOI.VariableIndex(2) - 3.1 MOI.VariableIndex(3) ``` -------------------------------- ### Transitioning linprog function Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/tutorials/mathprogbase.md This snippet shows how to implement the `linprog` function using JuMP, handling linear constraints with different senses. ```julia using JuMP function linprog(c, A, sense, b, l, u, solver) N = length(c) model = Model(solver) @variable(model, l[i] <= x[i=1:N] <= u[i]) @objective(model, Min, c' * x) eq_rows, ge_rows, le_rows = sense .== '=', sense .== '>', sense .== '<' @constraint(model, A[eq_rows, :] * x .== b[eq_rows]) @constraint(model, A[ge_rows, :] * x .>= b[ge_rows]) @constraint(model, A[le_rows, :] * x .<= b[le_rows]) optimize!(model) return ( status = termination_status(model), objval = objective_value(model), sol = value.(x) ) end ``` -------------------------------- ### Adding a New Set Checklist Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/developer/checklists.md Use this checklist when adding a new set to the MathOptInterface repository. It covers basic set definition, utilities, documentation, tests, and MathOptFormat integration. ```markdown ## Basic - [ ] Add a new `AbstractScalarSet` or `AbstractVectorSet` to `src/sets.jl` - [ ] If `isbitstype(S) == false`, implement `Base.copy(set::S)` - [ ] If `isbitstype(S) == false`, implement `Base.:(==)(x::S, y::S)` - [ ] If an `AbstractVectorSet`, implement `dimension(set::S)`, unless the dimension is given by `set.dimension`. - [ ] Ensure the set does not contain references to any variables or constraints ## Utilities - [ ] If an `AbstractVectorSet`, implement `Utilities.set_dot`, unless the dot product between two vectors in the set is equivalent to `LinearAlgebra.dot` - [ ] If an `AbstractVectorSet`, implement `Utilities.set_with_dimension` in `src/Utilities/matrix_of_constraints.jl` - [ ] Add the set to the `@model` macro at the bottom of `src/Utilities.model.jl` ## Documentation - [ ] Add a docstring, which gives the mathematical definition of the set, along with an `## Example` block containing a `jldoctest` - [ ] Add the docstring to `docs/src/reference/standard_form.md` - [ ] Add the set to the relevant table in `docs/src/manual/standard_form.md` ## Tests - [ ] Define a new `_set(::Type{S})` method in `src/Test/test_basic_constraint.jl` and add the name of the set to the list at the bottom of that files - [ ] If the set has any checks in its constructor, add tests to `test/sets.jl` ## MathOptFormat - [ ] Open an issue at `https://github.com/jump-dev/MathOptFormat` to add support for the new set {{ replace with link to the issue }} ## Optional - [ ] Implement `dual_set(::S)` and `dual_set_type(::Type{S})` - [ ] Add new tests to the `Test` submodule exercising your new set - [ ] Add new bridges to convert your set into more commonly used sets ``` -------------------------------- ### Get Variable or Constraint by Name Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/tutorials/implementing.md Implement these methods to retrieve variables or constraints by their string name. Return `nothing` if not found, the index if unique, or throw an error if multiple exist with the same name. ```julia function MOI.get(model::Optimizer, ::Type{MOI.VariableIndex}, name::String) return # The variable named `name`. end function MOI.get(model::Optimizer, ::Type{MOI.ConstraintIndex}, name::String) return # The constraint any type named `name`. end function MOI.get( model::Optimizer, ::Type{MOI.ConstraintIndex{F,S}}, name::String, ) where {F,S} return # The constraint of type F-in-S named `name`. end ``` -------------------------------- ### Run All MathOptInterface Tests Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/developer/contributing.md Execute all tests for the MathOptInterface package using Pkg.test. This recompiles the package. ```julia julia> import Pkg julia> Pkg.test("MathOptInterface") ``` -------------------------------- ### Visualizing Unprecompilable Methods with ProfileView Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/tutorials/latency.md Visualize the results of SnoopCompile using ProfileView to identify methods that cannot be precompiled. A large red bar in the flamegraph indicates a method with precompilation issues. ```julia using ProfileView ProfileView.view(flamegraph(tinf)) ``` -------------------------------- ### Create SDPA Model Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/submodules/FileFormats/overview.md Instantiate a MOI.FileFormats.Model for the SDPA file format. ```julia model = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_SDPA) ``` -------------------------------- ### Profiling Method Inference with SnoopCompile Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/tutorials/latency.md Use SnoopCompile to identify methods that require type inference, indicating potential precompilation issues. This example shows how to capture inference timing for a specific function call. ```julia module MyMOI struct Wrapper{T} inner::T end optimize!(x::Wrapper) = optimize!(x.inner) end # MyMOI module MyOptimizer using ..MyMOI struct Optimizer end MyMOI.optimize!(x::Optimizer) = 1 end # MyOptimizer using SnoopCompile model = MyMOI.Wrapper(MyOptimizer.Optimizer()) julia> tinf = @snoopi_deep MyMOI.optimize!(model) InferenceTimingNode: 0.008256/0.008543 on InferenceFrameInfo for Core.Compiler.Timings.ROOT() with 1 direct children ``` -------------------------------- ### Write MOI Model to MOF File Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/submodules/FileFormats/overview.md Writes an MOI model to a MathOptFormat file. Requires creating a source model, adding a variable, creating a destination MOF model, copying the source to the destination, and then writing the destination to a file. The content of the written file can be printed. ```julia 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") print(read("file.mof.json", String)) ``` -------------------------------- ### Create Baseline Benchmark Results Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/submodules/Benchmarks/overview.md Establish a baseline for benchmark results on a given suite before making changes. This involves creating a benchmark suite, specifying the solver, and saving the initial results to a directory. ```julia # You must load BenchmarkTools.jl to enable MOI.Benchmarks import BenchmarkTools # Replace `SolverPackage` with your choice of solver using SolverPackage import MathOptInterface as MOI suite = MOI.Benchmarks.suite() do SolverPackage.Optimizer() end MOI.Benchmarks.create_baseline( suite, "current"; directory = "/tmp", verbose = true ) ``` -------------------------------- ### Example Expression Representation Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/submodules/Nonlinear/overview.md Constructs an `Expression` object representing the function f(x) = sin(x)^2 + x using the defined `Node` and `Expression` structs. The node ordering follows topological rules. ```julia julia> expr = Expression( [ Node(NODE_CALL_MULTIVARIATE, -1, 1), Node(NODE_CALL_MULTIVARIATE, 1, 2), Node(NODE_CALL_UNIVARIATE, 2, 1), Node(NODE_VARIABLE, 3, 1), Node(NODE_VALUE, 2, 1), Node(NODE_VARIABLE, 1, 1), ], [2.0], ); ``` -------------------------------- ### Adding a New Bridge Checklist Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/developer/checklists.md Use this checklist when adding a new bridge to the MathOptInterface repository. It covers basic bridge definition, tests, documentation, and final touch implementation if needed. ```markdown ## Basic - [ ] Create a new file in `src/Bridges/XXX/bridges` named after the type of the bridge - [ ] Define the bridge, following existing examples. The name of the bridge struct must end in `Bridge` - [ ] Check if your bridge can be a subtype of [`MOI.Bridges.Constraint.SetMapBridge`](@ref) - [ ] Define a new `const` that is a `SingleBridgeOptimizer` wrapping the new bridge. The name of the const must be the name of the bridge, less the `Bridge` suffix - [ ] If the bridge should be enabled by default, add the bridge to `add_all_bridges` at the bottom of `src/Bridges/XXX/XXX.jl` ## Tests - [ ] Create a new file in the appropriate subdirectory of `tests/Bridges/XXX` named after the type of the bridge - [ ] Use `MOI.Bridges.runtests` to test various inputs and outputs of the bridge - [ ] If, after opening the pull request to add the bridge, some lines are not covered by the tests, add additional bridge-specific tests to cover the untested lines. ## Documentation - [ ] Add a docstring which uses the same template as existing bridges. ## Final touch If the bridge depends on run-time values of other variables and constraints in the model: - [ ] Implement `MOI.Utilities.needs_final_touch(::Bridge)` - [ ] Implement `MOI.Utilities.final_touch(::Bridge, ::MOI.ModelLike)` - [ ] Ensure that `final_touch` can be called multiple times in a row ``` -------------------------------- ### Utilities.MockOptimizer Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/submodules/Utilities/reference.md A mock optimizer for testing purposes in MathOptInterface. ```APIDOC ## Utilities.MockOptimizer ### Description A mock optimizer for testing purposes in MathOptInterface. ### Type Utilities.MockOptimizer ``` -------------------------------- ### Create MPS Model Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/submodules/FileFormats/overview.md Instantiate a MOI.FileFormats.Model for the MPS file format. ```julia model = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_MPS) ``` -------------------------------- ### Transitioning mixintprog function Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/tutorials/mathprogbase.md This snippet demonstrates how to implement the `mixintprog` function using JuMP, supporting binary and integer variables. ```julia using JuMP function mixintprog(c, A, rowlb, rowub, vartypes, lb, ub, solver) N = length(c) model = Model(solver) @variable(model, lb[i] <= x[i=1:N] <= ub[i]) for i in 1:N if vartypes[i] == :Bin set_binary(x[i]) elseif vartypes[i] == :Int set_integer(x[i]) end end @objective(model, Min, c' * x) @constraint(model, rowlb .<= A * x .<= rowub) optimize!(model) return ( status = termination_status(model), objval = objective_value(model), sol = value.(x) ) end ``` -------------------------------- ### Enable Full Bridging with `full_bridge_optimizer` Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/submodules/Bridges/overview.md Wrap an optimizer with `Bridges.full_bridge_optimizer` to enable all available bridges. This is the recommended approach for most use cases, providing lazy bridging for unsupported constraints. ```jldoctest julia> inner_optimizer = MOI.Utilities.Model{Float64}() MOIU.Model{Float64} ├ ObjectiveSense: FEASIBILITY_SENSE ├ ObjectiveFunctionType: MOI.ScalarAffineFunction{Float64} ├ NumberOfVariables: 0 └ NumberOfConstraints: 0 julia> optimizer = MOI.Bridges.full_bridge_optimizer(inner_optimizer, Float64) MOIB.LazyBridgeOptimizer{MOIU.Model{Float64}} ├ Variable bridges: none ├ Constraint bridges: none ├ Objective bridges: none └ model: MOIU.Model{Float64} ├ ObjectiveSense: FEASIBILITY_SENSE ├ ObjectiveFunctionType: MOI.ScalarAffineFunction{Float64} ├ NumberOfVariables: 0 └ NumberOfConstraints: 0 ``` -------------------------------- ### Create NL Model Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/submodules/FileFormats/overview.md Instantiate a MOI.FileFormats.Model for the NL file format. ```julia model = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_NL) ``` -------------------------------- ### Add Local Package for Docs Build Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/developer/contributing.md Ensure the current directory's MathOptInterface package is added as a development dependency within the documentation project environment. ```julia julia> import Pkg; Pkg.dev(".") ``` -------------------------------- ### Keyword as Variable Name Handling Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/submodules/FileFormats/LP.md Demonstrates how keywords can be used as variable names and how context is used for disambiguation. This approach differs from Gurobi, which would flag such instances as errors. ```plaintext min st st st >= 0 end ``` ```plaintext min st st st >= 0 end ``` -------------------------------- ### Create CBF Model Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/submodules/FileFormats/overview.md Instantiate a MOI.FileFormats.Model for the Conic Benchmark Format (CBF). ```julia model = MOI.FileFormats.Model(format = MOI.FileFormats.FORMAT_CBF) ``` -------------------------------- ### Run Benchmarking Script Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/perf/time_to_first_solve/README.md Execute the benchmarking script for different solvers. Use the `--no-bridge` option to disable bridging. ```bash cd ~/.julia/dev/MathOptInterface/perf/time_to_first_solve julia --project=. script.jl clp julia --project=. script.jl clp --no-bridge julia --project=. script.jl glpk julia --project=. script.jl glpk --no-bridge ``` -------------------------------- ### Rebuild Documentation with Revise Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/developer/contributing.md Load Revise and execute the docs/make.jl script to build or rebuild the documentation. Re-running include allows for quick updates after changes. ```julia julia> using Revise julia> include("docs/make.jl") ``` -------------------------------- ### Compare Against Baseline Benchmark Results Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/submodules/Benchmarks/overview.md After making changes to a solver wrapper, re-run the benchmark suite and compare the new results against the previously saved baseline. This helps identify performance regressions or improvements. ```julia import BenchmarkTools using SolverPackage import MathOptInterface as MOI suite = MOI.Benchmarks.suite() do SolverPackage.Optimizer() end MOI.Benchmarks.compare_against_baseline( suite, "current"; directory = "/tmp", verbose = true ) ``` -------------------------------- ### Initialize Nonlinear Model Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/submodules/Nonlinear/overview.md Creates a new Nonlinear.Model instance to store nonlinear information. This is the primary data structure for building nonlinear optimization problems. ```julia const Nonlinear = MOI.Nonlinear; model = Nonlinear.Model() ``` -------------------------------- ### Summary for Optimizer Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/tutorials/implementing.md Implement the `Base.summary` method to provide a custom string representation for the `Optimizer` object when it is displayed. ```julia function Base.summary(io::IO, model::Optimizer) return print(io, "NewSolver with the pointer $(model.ptr)") end ``` -------------------------------- ### Clone MathOptInterface Repository Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/developer/contributing.md Clone the MathOptInterface source code from GitHub to a local path using git. ```bash $ cd /some/local/path $ git clone https://github.com/jump-dev/MathOptInterface.jl.git ``` -------------------------------- ### Mapping Discrete and Logical Constraints to MOI Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/manual/constraints.md Illustrates the translation of discrete and logical constraints into MOI function-set pairs. This is useful for understanding how specialized variable types and conditions are represented in MOI. ```text x_i \in \mathbb{Z} | VariableIndex | Integer x_i \in \{0,1\} | VariableIndex | ZeroOne x_i \in \{0\} \cup [l,u] | VariableIndex | Semicontinuous x_i \in \{0\} \cup \{l,l+1,\ldots,u-1,u\} | VariableIndex | Semiintger At most one component of \x can be nonzero | VectorOfVariables | SOS1 At most two components of \x can be nonzero, and if so they must be adjacent components | VectorOfVariables | SOS2 y = 1 \implies a^T x \in S | VectorAffineFunction | Indicator ``` -------------------------------- ### Create a MOI Utilities Model Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/submodules/Utilities/overview.md Instantiate a generic MOI.Utilities.Model with a specified scalar type. This model efficiently supports all MOI functions and sets. ```jldoctest julia> model = MOI.Utilities.Model{Float64}() MOIU.Model{Float64} ├ ObjectiveSense: FEASIBILITY_SENSE ├ ObjectiveFunctionType: MOI.ScalarAffineFunction{Float64} ├ NumberOfVariables: 0 └ NumberOfConstraints: 0 ``` -------------------------------- ### Utilities.latex_formulation Source: https://github.com/jump-dev/mathoptinterface.jl/blob/master/docs/src/submodules/Utilities/reference.md Generates a LaTeX formulation of an optimization problem for printing. ```APIDOC ## Utilities.latex_formulation ### Description Generates a LaTeX formulation of an optimization problem for printing. ### Function Utilities.latex_formulation ```