From 1b32def01e3397565b9b386146fa921d85dd196b Mon Sep 17 00:00:00 2001 From: odow Date: Wed, 10 Mar 2021 14:23:29 +1300 Subject: [PATCH 1/5] More documentation changes to manual --- docs/make.jl | 2 + docs/src/index.md | 8 +- docs/src/manual/basic_usage.md | 238 --------------------------------- docs/src/manual/constraints.md | 13 +- docs/src/manual/example.md | 132 ++++++++++++++++++ docs/src/manual/variables.md | 41 ++++++ 6 files changed, 187 insertions(+), 247 deletions(-) create mode 100644 docs/src/manual/example.md create mode 100644 docs/src/manual/variables.md diff --git a/docs/make.jl b/docs/make.jl index 8e68e2677b..513b95d9cf 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -25,10 +25,12 @@ makedocs( ], "Manual" => [ "manual/standard_form.md", + "manual/variables.md", "manual/constraints.md", "manual/status.md", "manual/modification.md", "manual/basic_usage.md", + "manual/example.md", "manual/implementing.md", ], "API Reference" => "reference/reference.md", diff --git a/docs/src/index.md b/docs/src/index.md index 2f28e12af1..aaf24d6cae 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -1,11 +1,13 @@ -# MathOptInterface - !!! warning This documentation is still under construction. If you need help with JuMP, read the [JuMP documentation](https://jump.dev/JuMP.jl/stable/) instead. If you are writing a solver interface and need help with MOI, join the [developer chatroom](https://gitter.im/JuliaOpt/JuMP-dev) and ask away! +# MathOptInterface + +# What is MathOptInterface? + [MathOptInterface.jl](https://github.com/jump-dev/MathOptInterface.jl) (MOI) is an abstraction layer designed to provide a unified interface to mathematical optimization solvers so that users do not need to understand multiple @@ -36,7 +38,7 @@ you know where to look for certain things. submodules within MOI. These submodules are not required to interface a solver with MOI, but they make the job much easier. -## Citing JuMP +## Citing MathOptInterface A [paper describing the design and features of MathOptInterface](https://arxiv.org/abs/2002.03447) is available on [arXiv](https://arxiv.org). diff --git a/docs/src/manual/basic_usage.md b/docs/src/manual/basic_usage.md index d2d2210237..4730ebb597 100644 --- a/docs/src/manual/basic_usage.md +++ b/docs/src/manual/basic_usage.md @@ -50,37 +50,6 @@ Models are constructed by The way the problem is solved by the optimimizer is controlled by [`AbstractOptimizerAttribute`](@ref)s, see [Solver-specific attributes](@ref). -## Add a variable - -All variables in MOI are scalar variables. New scalar variables are created with -[`add_variable`](@ref) or [`add_variables`](@ref), which return a [`VariableIndex`](@ref) -or `Vector{VariableIndex}` respectively. [`VariableIndex`](@ref) objects are -type-safe wrappers around integers that refer to a variable in a particular -model. - -!!! note - The integer does not necessarily corresond to the column inside an - optimizer! - -One uses [`VariableIndex`](@ref) objects to set and get variable attributes. For -example, the [`VariablePrimalStart`](@ref) attribute is used to provide an -initial starting point for a variable or collection of variables: -```julia -v = MOI.add_variable(model) -MOI.set(model, MOI.VariablePrimalStart(), v, 10.5) -v2 = MOI.add_variables(model, 3) -MOI.set(model, MOI.VariablePrimalStart(), v2, [1.3, 6.8, -4.6]) -``` - -## Delete a variable - -Delete a variable using -[`delete(::ModelLike, ::VariableIndex)`](@ref MathOptInterface.delete(::MathOptInterface.ModelLike, ::MathOptInterface.Index)). - -!!! warning - Not all `ModelLike` models support deleting variables. A - [`DeleteNotAllowed`](@ref) error is thrown if this is not supported. - ## Functions MOI defines six functions as listed in the definition of the [Standard form problem](@ref). @@ -152,210 +121,3 @@ constraints, we can ask the solver to solve the model by calling ```julia MOI.optimize!(optimizer) ``` - -The optimization procedure may terminate for a number of reasons. The -[`TerminationStatus`](@ref) attribute of the optimizer returns a -[`TerminationStatusCode`](@ref) object which explains why the solver stopped. -The termination statuses distinguish between proofs of optimality, -infeasibility, local convergence, limits, and termination because of something -unexpected like invalid problem data or failure to converge. A typical usage of -the [`TerminationStatus`](@ref) attribute is as follows: -```julia -status = MOI.get(optimizer, TerminationStatus()) -if status == MOI.OPTIMAL - # Ok, we solved the problem! -else - # Handle other cases. -end -``` - -After checking the [`TerminationStatus`](@ref), one should typically check -[`ResultCount`](@ref). This attribute returns the number of results that the -solver has available to return. *A result is defined as a primal-dual pair, -but either the primal or the dual may be missing from the result.* While the -`OPTIMAL` termination status normally implies that at least one result is -available, other statuses do not. For example, in the case of infeasiblity, a -solver may return no result or a proof of infeasibility. The [`ResultCount`](@ref) -attribute distinguishes between these two cases. - -The [`PrimalStatus`](@ref) and [`DualStatus`](@ref) attributes return a -[`ResultStatusCode`](@ref) that indicates if that component of the result -is present (i.e., not `NO_SOLUTION`) and explains how to interpret the result. - -If `PrimalStatus` is not `NO_SOLUTION`, then the primal may be retrieved with -the [`VariablePrimal`](@ref) attribute: -```julia -MOI.get(optimizer, VariablePrimal(), x) -``` - -If `x` is a [`VariableIndex`](@ref) then the function call returns a scalar, and -if `x` is a `Vector{VariableIndex}` then the call returns a vector of scalars. -`VariablePrimal()` is equivalent to `VariablePrimal(1)`, i.e., the variable -primal vector of the first result. Use `VariablePrimal(N)` to access the `N`th -result. - -See also the attributes [`ConstraintPrimal`](@ref), and [`ConstraintDual`](@ref). - -See [Duality](@ref) for a discussion of the MOI conventions for primal-dual -pairs and certificates. - -!!! note - We omit discussion of how to handle multiple results, i.e., when - `ResultCount` is greater than 1. This is supported in the API but not yet - implemented in any solver. - -### Common status situations - -The sections below describe how to interpret typical or interesting status cases -for three common classes of solvers. The example cases are illustrative, not -comprehensive. Solver wrappers may provide additional information on -how the solver's statuses map to MOI statuses. - -`?` in the tables indicate that multiple different values are possible. - -#### Primal-dual convex solver - -Linear programming and conic optimization solvers fall into this category. - -| What happened? | `TerminationStatus()` | `ResultCount()` | `PrimalStatus()` | `DualStatus()` | -| --------------------------------------- | --------------------- | --------------- | ------------------------------------------- | ------------------------------------------- | -| Proved optimality | `OPTIMAL` | 1 | `FEASIBLE_POINT` | `FEASIBLE_POINT` | -| Proved infeasible | `INFEASIBLE` | 1 | `NO_SOLUTION` | `INFEASIBILITY_CERTIFICATE` | -| Optimal within relaxed tolerances | `ALMOST_OPTIMAL` | 1 | `FEASIBLE_POINT` or `ALMOST_FEASIBLE_POINT` | `FEASIBLE_POINT` or `ALMOST_FEASIBLE_POINT` | -| Detected an unbounded ray of the primal | `DUAL_INFEASIBLE` | 1 | `INFEASIBILITY_CERTIFICATE` | `NO_SOLUTION` | -| Stall | `SLOW_PROGRESS` | 1 | ? | ? | - -#### Global branch-and-bound solvers - -Mixed-integer programming solvers fall into this category. - -| What happened? | `TerminationStatus()` | `ResultCount()` | `PrimalStatus()` | `DualStatus()` | -| ------------------------------------------------ | ------------------------- | --------------- | ------------------ | -------------- | -| Proved optimality | `OPTIMAL` | 1 | `FEASIBLE_POINT` | `NO_SOLUTION` | -| Presolve detected infeasibility or unboundedness | `INFEASIBLE_OR_UNBOUNDED` | 0 | `NO_SOLUTION` | `NO_SOLUTION` | -| Proved infeasibility | `INFEASIBLE` | 0 | `NO_SOLUTION` | `NO_SOLUTION` | -| Timed out (no solution) | `TIME_LIMIT` | 0 | `NO_SOLUTION` | `NO_SOLUTION` | -| Timed out (with a solution) | `TIME_LIMIT` | 1 | `FEASIBLE_POINT` | `NO_SOLUTION` | -| `CPXMIP_OPTIMAL_INFEAS` | `ALMOST_OPTIMAL` | 1 | `INFEASIBLE_POINT` | `NO_SOLUTION` | - -[`CPXMIP_OPTIMAL_INFEAS`](https://www.ibm.com/support/knowledgecenter/en/SSSA5P_12.6.1/ilog.odms.cplex.help/refcallablelibrary/macros/CPXMIP_OPTIMAL_INFEAS.html) -is a CPLEX status that indicates that a preprocessed problem was solved to -optimality, but the solver was unable to recover a feasible solution to the -original problem. - -#### Local search solvers - -Nonlinear programming solvers fall into this category. It also includes -non-global tree search solvers like -[Juniper](https://github.com/lanl-ansi/Juniper.jl). - -| What happened? | `TerminationStatus()` | `ResultCount()` | `PrimalStatus()` | `DualStatus()` | -| ------------------------------------------------------ | --------------------------------- | --------------- | ------------------ | ---------------- | -| Converged to a stationary point | `LOCALLY_SOLVED` | 1 | `FEASIBLE_POINT` | `FEASIBLE_POINT` | -| Completed a non-global tree search (with a solution) | `LOCALLY_SOLVED` | 1 | `FEASIBLE_POINT` | `FEASIBLE_POINT` | -| Converged to an infeasible point | `LOCALLY_INFEASIBLE` | 1 | `INFEASIBLE_POINT` | ? | -| Completed a non-global tree search (no solution found) | `LOCALLY_INFEASIBLE` | 0 | `NO_SOLUTION` | `NO_SOLUTION` | -| Iteration limit | `ITERATION_LIMIT` | 1 | ? | ? | -| Diverging iterates | `NORM_LIMIT` or `OBJECTIVE_LIMIT` | 1 | ? | ? | - - -## A complete example: solving a knapsack problem - -We first need to select a solver supporting the given problem (see -[`supports`](@ref) and [`supports_constraint`](@ref)). In this example, we -want to solve a binary-constrained knapsack problem: -`max c'x: w'x <= C, x binary`. Suppose we choose GLPK: -```julia -using GLPK -optimizer = GLPK.Optimizer() -``` -We first define the constants of the problem: -```jldoctest knapsack; setup = :(optimizer = MOI.Utilities.MockOptimizer(MOI.Utilities.Model{Float64}()); MOI.Utilities.set_mock_optimize!(optimizer, mock -> MOI.Utilities.mock_optimize!(mock, ones(3)))) -c = [1.0, 2.0, 3.0] -w = [0.3, 0.5, 1.0] -C = 3.2 - -# output - -3.2 -``` -We create the variables of the problem and set the objective function: -```jldoctest knapsack -x = MOI.add_variables(optimizer, length(c)) -MOI.set( - optimizer, - MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(), - MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.(c, x), 0.0), -) -MOI.set(optimizer, MOI.ObjectiveSense(), MOI.MAX_SENSE) - -# output - -``` - -We add the knapsack constraint and integrality constraints: -```jldoctest knapsack -MOI.add_constraint( - optimizer, - MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.(w, x), 0.0), - MOI.LessThan(C), -) -for x_i in x - MOI.add_constraint(optimizer, MOI.SingleVariable(x_i), MOI.ZeroOne()) -end - -# output - -``` - -We are all set! We can now call [`optimize!`](@ref) and wait for the solver to -find the solution: -```jldoctest knapsack -MOI.optimize!(optimizer) - -# output - -``` - -The first thing to check after optimization is why the solver stopped, e.g., -did it stop because of a time limit or did it stop because it found the optimal -solution? -```jldoctest knapsack -MOI.get(optimizer, MOI.TerminationStatus()) - -# output - - -OPTIMAL::TerminationStatusCode = 1 -``` - -It found the optimal solution! Now let's see what is that solution. -```jldoctest knapsack -MOI.get(optimizer, MOI.PrimalStatus()) - -# output - -FEASIBLE_POINT::ResultStatusCode = 1 -``` - -What is its objective value? -```jldoctest knapsack -MOI.get(optimizer, MOI.ObjectiveValue()) - -# output - -6.0 -``` - -And what is the value of the variables `x`? -```jldoctest knapsack -MOI.get(optimizer, MOI.VariablePrimal(), x) - -# output - -3-element Array{Float64,1}: - 1.0 - 1.0 - 1.0 -``` - diff --git a/docs/src/manual/constraints.md b/docs/src/manual/constraints.md index eccd33d5d8..303c70b989 100644 --- a/docs/src/manual/constraints.md +++ b/docs/src/manual/constraints.md @@ -9,6 +9,8 @@ DocTestFilters = [r"MathOptInterface|MOI"] # Constraints +## Add a constraint + All constraints are specified with [`add_constraint`](@ref) by restricting the output of some function to a set. The interface allows an arbitrary combination of functions and sets, but of course solvers may decide to support only a small @@ -85,7 +87,7 @@ MOI.add_constraint( [TODO Describe ConstraintIndex objects.] -### Constraints by function-set pairs +## Constraints by function-set pairs Below is a list of common constraint types and how they are represented as function-set pairs in MOI. In the notation below, ``x`` is a vector of @@ -94,7 +96,7 @@ scalar constants, ``a, b`` are constant vectors, `A` is a constant matrix and ``\mathbb{R}_+`` (resp. ``\mathbb{R}_-``) is the set of nonnegative (resp. nonpositive) real numbers. -#### Linear constraints +### Linear constraints | Mathematical Constraint | MOI Function | MOI Set | |-------------------------------|------------------------------|----------------| @@ -133,7 +135,7 @@ allow the solver to return separate dual multipliers for the two bounds, while the former will allow the solver to return only a single dual for the interval constraint. -#### Conic constraints +### Conic constraints | Mathematical Constraint | MOI Function | MOI Set | |---------------------------------------------------------------|------------------------------|------------------------------------| @@ -151,7 +153,7 @@ where ``\mathcal{E}`` is the exponential cone (see [`ExponentialCone`](@ref)), ``A`` is an affine map that outputs symmetric matrices and ``B`` is an affine map that outputs square matrices. -#### Quadratic constraints +### Quadratic constraints | Mathematical Constraint | MOI Function | MOI Set | |-------------------------------|------------------------------|-------------------------------| @@ -160,8 +162,7 @@ where ``\mathcal{E}`` is the exponential cone (see [`ExponentialCone`](@ref)), | ``x^TQx + a^Tx + b = 0`` | `ScalarQuadraticFunction` | `EqualTo` | | Bilinear matrix inequality | `VectorQuadraticFunction` | `PositiveSemidefiniteCone...` | - -#### Discrete and logical constraints +### Discrete and logical constraints | Mathematical Constraint | MOI Function | MOI Set | |--------------------------------------------------------------------------------------------|------------------------|------------------------------------| diff --git a/docs/src/manual/example.md b/docs/src/manual/example.md new file mode 100644 index 0000000000..77d2e4d136 --- /dev/null +++ b/docs/src/manual/example.md @@ -0,0 +1,132 @@ +```@meta +CurrentModule = MathOptInterface +DocTestSetup = quote + using MathOptInterface + const MOI = MathOptInterface +end +DocTestFilters = [r"MathOptInterface|MOI"] +``` + +# A complete example: solving a knapsack problem + +In this example, we want to solve a binary-constrained knapsack problem: +```math +\begin{aligned} +\max \; & c^\top x \\ +s.t. \; & w^\top x \le C \\ + & x_i \in \{0,1\},\quad \forall i=1,\ldots,n +\end{aligned} +``` + +As an optimizer, we choose GLPK: +```julia +using GLPK +optimizer = GLPK.Optimizer() +``` + +## Define the data + +We first define the constants of the problem: +```jldoctest knapsack; setup = :(optimizer = MOI.Utilities.MockOptimizer(MOI.Utilities.Model{Float64}()); MOI.Utilities.set_mock_optimize!(optimizer, mock -> MOI.Utilities.mock_optimize!(mock, ones(3)))) +julia> c = [1.0, 2.0, 3.0] +3-element Array{Float64,1}: + 1.0 + 2.0 + 3.0 + +julia> w = [0.3, 0.5, 1.0] +3-element Array{Float64,1}: + 0.3 + 0.5 + 1.0 + +julia> C = 3.2 +3.2 +``` + +## Add the variables + +```jldoctest knapsack +julia> x = MOI.add_variables(optimizer, length(c)); +``` + +## [Set the objective](@id set_objective_example) + +```jldoctest knapsack +julia> MOI.set( + optimizer, + MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(), + MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.(c, x), 0.0), + ); + +julia> MOI.set(optimizer, MOI.ObjectiveSense(), MOI.MAX_SENSE) +MAX_SENSE::OptimizationSense = 1 +``` + +## Add the constraints + +We add the knapsack constraint and integrality constraints: +```jldoctest knapsack +julia> MOI.add_constraint( + optimizer, + MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.(w, x), 0.0), + MOI.LessThan(C), + ); +``` + +Add integrality constraints: +```jldoctest knapsack +julia> for x_i in x + MOI.add_constraint(optimizer, MOI.SingleVariable(x_i), MOI.ZeroOne()) + end +``` + +## Optimize the model + +```jldoctest knapsack +julia> MOI.optimize!(optimizer) +``` + +## Understand why the solver stopped + +The first thing to check after optimization is why the solver stopped, e.g., +did it stop because of a time limit or did it stop because it found the optimal +solution? +```jldoctest knapsack +julia> MOI.get(optimizer, MOI.TerminationStatus()) +OPTIMAL::TerminationStatusCode = 1 +``` +Looks like we found an optimal solution! + +## Understand what solution was returned + + +```jldoctest knapsack +julia> MOI.get(optimizer, MOI.ResultCount()) +1 + +julia> MOI.get(optimizer, MOI.PrimalStatus()) +FEASIBLE_POINT::ResultStatusCode = 1 + +julia> MOI.get(optimizer, MOI.DualStatus()) +NO_SOLUTION::ResultStatusCode = 0 +``` + +## Query the objective + +What is its objective value? +```jldoctest knapsack +julia> MOI.get(optimizer, MOI.ObjectiveValue()) +6.0 +``` + +## Query the primal solution + +And what is the value of the variables `x`? +```jldoctest knapsack +julia> MOI.get(optimizer, MOI.VariablePrimal(), x) +3-element Array{Float64,1}: + 1.0 + 1.0 + 1.0 +``` diff --git a/docs/src/manual/variables.md b/docs/src/manual/variables.md new file mode 100644 index 0000000000..03e07cdc5c --- /dev/null +++ b/docs/src/manual/variables.md @@ -0,0 +1,41 @@ +```@meta +CurrentModule = MathOptInterface +DocTestSetup = quote + using MathOptInterface + const MOI = MathOptInterface +end +DocTestFilters = [r"MathOptInterface|MOI"] +``` + +# Variables + +## Add a variable + +All variables in MOI are scalar variables. New scalar variables are created with +[`add_variable`](@ref) or [`add_variables`](@ref), which return a [`VariableIndex`](@ref) +or `Vector{VariableIndex}` respectively. [`VariableIndex`](@ref) objects are +type-safe wrappers around integers that refer to a variable in a particular +model. + +!!! note + The integer does not necessarily corresond to the column inside an + optimizer! + +One uses [`VariableIndex`](@ref) objects to set and get variable attributes. For +example, the [`VariablePrimalStart`](@ref) attribute is used to provide an +initial starting point for a variable or collection of variables: +```julia +v = MOI.add_variable(model) +MOI.set(model, MOI.VariablePrimalStart(), v, 10.5) +v2 = MOI.add_variables(model, 3) +MOI.set(model, MOI.VariablePrimalStart(), v2, [1.3, 6.8, -4.6]) +``` + +## Delete a variable + +Delete a variable using +[`delete(::ModelLike, ::VariableIndex)`](@ref MathOptInterface.delete(::MathOptInterface.ModelLike, ::MathOptInterface.Index)). + +!!! warning + Not all `ModelLike` models support deleting variables. A + [`DeleteNotAllowed`](@ref) error is thrown if this is not supported. From 55a74e6727ce3f9dde4f3eb4ad73aa58d2c5097a Mon Sep 17 00:00:00 2001 From: odow Date: Wed, 10 Mar 2021 18:19:48 +1300 Subject: [PATCH 2/5] Update constraints documentation --- docs/src/manual/constraints.md | 134 ++++++++++++++++----------------- 1 file changed, 67 insertions(+), 67 deletions(-) diff --git a/docs/src/manual/constraints.md b/docs/src/manual/constraints.md index 303c70b989..cc95af98a4 100644 --- a/docs/src/manual/constraints.md +++ b/docs/src/manual/constraints.md @@ -11,81 +11,81 @@ DocTestFilters = [r"MathOptInterface|MOI"] ## Add a constraint -All constraints are specified with [`add_constraint`](@ref) by restricting the -output of some function to a set. The interface allows an arbitrary combination -of functions and sets, but of course solvers may decide to support only a small -number of combinations. - -For example, linear programming solvers should support, at least, combinations -of affine functions with the [`LessThan`](@ref) and [`GreaterThan`](@ref) sets. -These are simply linear constraints. [`SingleVariable`](@ref) functions combined -with these same sets are used to specify upper- and lower-bounds on variables. - -The code example below encodes the linear optimization problem: -```math -\begin{align} -& \max_{x \in \mathbb{R}^2} & 3x_1 + 2x_2 & -\\ -& \;\;\text{s.t.} & x_1 + x_2 &\le 5 -\\ -&& x_1 & \ge 0 -\\ -&&x_2 & \ge -1 -\end{align} +Use [`add_constraint`](@ref) to add a single constraint. + +```jldoctest constraints; setup=:(model = MOI.Utilities.Model{Float64}(); x = MOI.add_variables(model, 2)) +julia> c = MOI.add_constraint(model, MOI.VectorOfVariables(x), MOI.Nonnegatives(2)) +MathOptInterface.ConstraintIndex{MathOptInterface.VectorOfVariables,MathOptInterface.Nonnegatives}(1) ``` -```julia -x = MOI.add_variables(model, 2) -MOI.set( - model, - MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(), - MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.([3.0, 2.0], x), 0.0), -) -MOI.set(model, MOI.ObjectiveSense(), MAX_SENSE) -MOI.add_constraint( - model, - MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.(1.0, x), 0.0), - MOI.LessThan(5.0), -) -MOI.add_constraint(model, MOI.SingleVariable(x[1]), MOI.GreaterThan(0.0)) -MOI.add_constraint(model, MOI.SingleVariable(x[2]), MOI.GreaterThan(-1.0)) +[`add_constraint`](@ref) returns a [`ConstraintIndex`](@ref) type, which should +be used to refer to the added constraint in other calls. + +Check if a [`ConstraintIndex`](@ref) is valid using [`is_valid`](@ref). + +```jldoctest constraints +julia> MOI.is_valid(model, c) +true ``` -Besides scalar-valued functions in scalar-valued sets, it's also possible to use -vector-valued functions and sets. - -The code example below encodes the convex optimization problem: -```math -\begin{align} -& \max_{x,y,z \in \mathbb{R}} & y + z & -\\ -& \;\;\text{s.t.} & 3x &= 2 -\\ -&& x & \ge \lVert (y,z) \rVert_2 -\end{align} +Use [`add_constraints`](@ref) to add a number of constraints of the same type. + +```jldoctest; setup=:(model = MOI.Utilities.Model{Float64}(); x = MOI.add_variables(model, 2)) +julia> c = MOI.add_constraints( + model, + [MOI.SingleVariable(x[1]), MOI.SingleVariable(x[2])], + [MOI.GreaterThan(0.0), MOI.GreaterThan(1.0)] + ) +2-element Array{MathOptInterface.ConstraintIndex{MathOptInterface.SingleVariable,MathOptInterface.GreaterThan{Float64}},1}: + MathOptInterface.ConstraintIndex{MathOptInterface.SingleVariable,MathOptInterface.GreaterThan{Float64}}(1) + MathOptInterface.ConstraintIndex{MathOptInterface.SingleVariable,MathOptInterface.GreaterThan{Float64}}(2) +``` +This time, a vector of [`ConstraintIndex`](@ref) are returned. + +Use [`supports_constraint`](@ref) to check if the model supports adding a +constraint type. +```jldoctest; setup=:(model = MOI.Utilities.Model{Float64}()) +julia> MOI.supports_constraint( + model, + MOI.SingleVariable, + MOI.GreaterThan{Float64}, + ) +true ``` -```julia -x,y,z = MOI.add_variables(model, 3) -MOI.set( - model, - MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(), - MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.(1.0, [y, z]), 0.0), -) -MOI.set(model, ObjectiveSense(), MAX_SENSE) -MOI.add_constraint( - model, - MOI.VectorAffineFunction( - [MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(3.0, x))], [-2.0] - ), - MOI.Zeros(1), -) -MOI.add_constraint( - model, MOI.VectorOfVariables([x, y, z]), MOI.SecondOrderCone(3) -) +## Delete a constraint + +Use [`delete`](@ref) to delete a constraint. + +```jldoctest constraints +julia> MOI.delete(model, c) + +julia> MOI.is_valid(model, c) +false ``` -[TODO Describe ConstraintIndex objects.] +## Constraint attributes + +The following attributes are available for constraints + +* [`ConstraintName`](@ref) +* [`ConstraintPrimalStart`](@ref) +* [`ConstraintDualStart`](@ref) +* [`ConstraintPrimal`](@ref) +* [`ConstraintDual`](@ref) +* [`ConstraintBasisStatus`](@ref) +* [`ConstraintFunction`](@ref) +* [`CanonicalConstraintFunction`](@ref) +* [`ConstraintSet`](@ref) + +Get and set these attributes using [`get`(@ref) and [`set`](@ref). + +```jldoctest constraints +julia> MOI.set(model, MOI.ConstraintName(), c, "con_c") + +julia> MOI.get(model, MOI.ConstraintName(), c) +con_c +``` ## Constraints by function-set pairs From 00e808092fb6580993094b722ac74d1c4982ba1b Mon Sep 17 00:00:00 2001 From: odow Date: Wed, 10 Mar 2021 20:31:49 +1300 Subject: [PATCH 3/5] Update variable docs --- docs/src/manual/variables.md | 66 ++++++++++++++++++++++++++---------- 1 file changed, 48 insertions(+), 18 deletions(-) diff --git a/docs/src/manual/variables.md b/docs/src/manual/variables.md index 03e07cdc5c..a168878e70 100644 --- a/docs/src/manual/variables.md +++ b/docs/src/manual/variables.md @@ -11,31 +11,61 @@ DocTestFilters = [r"MathOptInterface|MOI"] ## Add a variable -All variables in MOI are scalar variables. New scalar variables are created with -[`add_variable`](@ref) or [`add_variables`](@ref), which return a [`VariableIndex`](@ref) -or `Vector{VariableIndex}` respectively. [`VariableIndex`](@ref) objects are -type-safe wrappers around integers that refer to a variable in a particular -model. +Use [`add_variable`](@ref) to add a single variable. -!!! note - The integer does not necessarily corresond to the column inside an - optimizer! +```jldoctest variables; setup=:(model = MOI.Utilities.Model{Float64}(); ) +julia> x = MOI.add_variable(mode) +MathOptInterface.VariableIndex(1) +``` +[`add_variable`](@ref) returns a [`VariableIndex`](@ref) type, which should be +used to refer to the added variable in other calls. + +Check if a [`VariableIndex`](@ref) is valid using [`is_valid`](@ref). +```jldoctest variables +julia> MOI.is_valid(model, x) +true +``` -One uses [`VariableIndex`](@ref) objects to set and get variable attributes. For -example, the [`VariablePrimalStart`](@ref) attribute is used to provide an -initial starting point for a variable or collection of variables: -```julia -v = MOI.add_variable(model) -MOI.set(model, MOI.VariablePrimalStart(), v, 10.5) -v2 = MOI.add_variables(model, 3) -MOI.set(model, MOI.VariablePrimalStart(), v2, [1.3, 6.8, -4.6]) +Use [`add_variables`](@ref) to add a number of variables. +```jldoctest variables +julia> y = MOI.add_variables(model, 2) +2-element Array{MathOptInterface.VariableIndex,1}: + MathOptInterface.VariableIndex(2) + MathOptInterface.VariableIndex(3) ``` +!!! warning + The integer does not necessarily corresond to the column inside an + optimizer! + ## Delete a variable -Delete a variable using -[`delete(::ModelLike, ::VariableIndex)`](@ref MathOptInterface.delete(::MathOptInterface.ModelLike, ::MathOptInterface.Index)). +Delete a variable using [`delete`](@ref). + +```jldoctest variables +julia> MOI.delete(model, x) + +julia> MOI.is_valid(model, x) +false +``` !!! warning Not all `ModelLike` models support deleting variables. A [`DeleteNotAllowed`](@ref) error is thrown if this is not supported. + +## Variable attributes + +The following attributes are available for variables + +* [`VariableName`](@ref) +* [`VariablePrimalStart`](@ref) +* [`VariablePrimal`](@ref) + +Get and set these attributes using [`get`(@ref) and [`set`](@ref). + +```jldoctest constraints +julia> MOI.set(model, MOI.VariableName(), x, "var_x") + +julia> MOI.get(model, MOI.VariableName(), x) +var_x +``` From bdc51ddc5a748e4f8fd877ac917d2bfd7cfaa7e7 Mon Sep 17 00:00:00 2001 From: odow Date: Mon, 15 Mar 2021 10:10:11 +1300 Subject: [PATCH 4/5] More restructuring --- docs/make.jl | 5 +- docs/src/manual/basic_usage.md | 123 ------------------ docs/src/manual/constraints.md | 6 +- docs/src/manual/example.md | 6 +- .../manual/{standard_form.md => models.md} | 33 ++++- docs/src/manual/{status.md => solutions.md} | 52 ++++---- docs/src/manual/variables.md | 8 +- 7 files changed, 76 insertions(+), 157 deletions(-) delete mode 100644 docs/src/manual/basic_usage.md rename docs/src/manual/{standard_form.md => models.md} (86%) rename docs/src/manual/{status.md => solutions.md} (84%) diff --git a/docs/make.jl b/docs/make.jl index 513b95d9cf..9accfbf267 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -24,12 +24,11 @@ makedocs( "background/duality.md", ], "Manual" => [ - "manual/standard_form.md", + "manual/models.md", "manual/variables.md", "manual/constraints.md", - "manual/status.md", + "manual/solutions.md", "manual/modification.md", - "manual/basic_usage.md", "manual/example.md", "manual/implementing.md", ], diff --git a/docs/src/manual/basic_usage.md b/docs/src/manual/basic_usage.md deleted file mode 100644 index 4730ebb597..0000000000 --- a/docs/src/manual/basic_usage.md +++ /dev/null @@ -1,123 +0,0 @@ -```@meta -CurrentModule = MathOptInterface -DocTestSetup = quote - using MathOptInterface - const MOI = MathOptInterface -end -DocTestFilters = [r"MathOptInterface|MOI"] -``` - -# Basic usage - -!!! note - MOI does not export functions, but for brevity we often omit qualifying - names with the MOI module. Best practice is to have - ```julia - using MathOptInterface - const MOI = MathOptInterface - ``` - and prefix all MOI methods with `MOI.` in user code. If a name is also - available in base Julia, we always explicitly use the module prefix, for - example, with `MOI.get`. - -## The ModelLike and AbstractOptimizer APIs - -The most significant part of MOI is the definition of the **model API** that is -used to specify an instance of an optimization problem (e.g., by adding -variables and constraints). Objects that implement the model API should inherit -from the [`ModelLike`](@ref) abstract type. - -Notably missing from the model API is the method to solve an optimization -problem. `ModelLike` objects may store an instance (e.g., in memory or backed by -a file format) without being linked to a particular solver. In addition to the -model API, MOI defines [`AbstractOptimizer`](@ref). - -*Optimizers* (or solvers) implement the model API (inheriting from `ModelLike`) -and additionally provide methods to solve the model. - -!!! info - Throughout the rest of the manual, `model` is used as a generic `ModelLike`, - and `optimizer` is used as a generic `AbstractOptimizer`. - -Models are constructed by -* adding variables using [`add_variable`](@ref) (or [`add_variables`](@ref)), - see [Add a variable](@ref); -* setting an objective sense and function using [`set`](@ref), - see [Setting an objective](@ref); -* and adding constraints using [`add_constraint`](@ref) (or - [`add_constraints`](@ref)), see [Constraints](@ref). - -The way the problem is solved by the optimimizer is controlled by -[`AbstractOptimizerAttribute`](@ref)s, see [Solver-specific attributes](@ref). - -## Functions - -MOI defines six functions as listed in the definition of the [Standard form problem](@ref). -The simplest function is [`SingleVariable`](@ref), defined as: -```julia -struct SingleVariable <: AbstractFunction - variable::VariableIndex -end -``` - -If `v` is a [`VariableIndex`](@ref) object, then `SingleVariable(v)` is simply -the scalar-valued function from the complete set of variables in a model that -returns the value of variable `v`. One may also call this function a coordinate -projection, which is more useful for defining constraints than as an objective -function. - -A more interesting function is [`ScalarAffineFunction`](@ref), defined as: -```julia -struct ScalarAffineFunction{T} <: AbstractScalarFunction - terms::Vector{ScalarAffineTerm{T}} - constant::T -end -``` - -The [`ScalarAffineTerm`](@ref) struct defines a variable-coefficient pair: -```julia -struct ScalarAffineTerm{T} - coefficient::T - variable_index::VariableIndex -end -``` - -If `x` is a vector of `VariableIndex` objects, then -```julia -MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.([5.0, -2.3], [x[1], x[2]]), 1.0) -``` -represents the function ``5 x_1 - 2.3 x_2 + 1``. - -!!! note - `MOI.ScalarAffineTerm.([5.0, -2.3], [x[1], x[2]])` is a shortcut for - `[MOI.ScalarAffineTerm(5.0, x[1]), MOI.ScalarAffineTerm(-2.3, x[2])]`. This - is Julia's broadcast syntax in action, and is used quite often. - -### Setting an objective - -Objective functions are assigned to a model by setting the [`ObjectiveFunction`](@ref) -attribute. The [`ObjectiveSense`](@ref) attribute is used for setting the -optimization sense. For example, -```julia -x = MOI.add_variables(model, 2) -MOI.set( - model, - MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(), - MOI.ScalarAffineFunction( - MOI.ScalarAffineTerm.([5.0, -2.3], [x[1], x[2]]), 1.0), - ) -MOI.set(model, MOI.ObjectiveSense(), MIN_SENSE) -``` -sets the objective to the function just discussed in the minimization sense. - -See [Functions and function modifications](@ref) for the complete list of -functions. - -## Solving and retrieving the results - -Once an optimizer is loaded with the objective function and all of the -constraints, we can ask the solver to solve the model by calling -[`optimize!`](@ref). -```julia -MOI.optimize!(optimizer) -``` diff --git a/docs/src/manual/constraints.md b/docs/src/manual/constraints.md index cc95af98a4..2b89a3c8f7 100644 --- a/docs/src/manual/constraints.md +++ b/docs/src/manual/constraints.md @@ -66,7 +66,7 @@ false ## Constraint attributes -The following attributes are available for constraints +The following attributes are available for constraints: * [`ConstraintName`](@ref) * [`ConstraintPrimalStart`](@ref) @@ -78,13 +78,13 @@ The following attributes are available for constraints * [`CanonicalConstraintFunction`](@ref) * [`ConstraintSet`](@ref) -Get and set these attributes using [`get`(@ref) and [`set`](@ref). +Get and set these attributes using [`get`](@ref) and [`set`](@ref). ```jldoctest constraints julia> MOI.set(model, MOI.ConstraintName(), c, "con_c") julia> MOI.get(model, MOI.ConstraintName(), c) -con_c +"con_c" ``` ## Constraints by function-set pairs diff --git a/docs/src/manual/example.md b/docs/src/manual/example.md index 77d2e4d136..c6cf54e65c 100644 --- a/docs/src/manual/example.md +++ b/docs/src/manual/example.md @@ -60,9 +60,13 @@ julia> MOI.set( ); julia> MOI.set(optimizer, MOI.ObjectiveSense(), MOI.MAX_SENSE) -MAX_SENSE::OptimizationSense = 1 ``` +!!! tip + `MOI.ScalarAffineTerm.(c, x)` is a shortcut for + `[MOI.ScalarAffineTerm(c[i], x[i]) for i = 1:3]`. This is Julia's broadcast + syntax in action, and is used quite often throughout MOI. + ## Add the constraints We add the knapsack constraint and integrality constraints: diff --git a/docs/src/manual/standard_form.md b/docs/src/manual/models.md similarity index 86% rename from docs/src/manual/standard_form.md rename to docs/src/manual/models.md index e4600da18f..70bc02541d 100644 --- a/docs/src/manual/standard_form.md +++ b/docs/src/manual/models.md @@ -7,7 +7,38 @@ end DocTestFilters = [r"MathOptInterface|MOI"] ``` -# Standard form problem +# Models + +The most significant part of MOI is the definition of the **model API** that is +used to specify an instance of an optimization problem (e.g., by adding +variables and constraints). Objects that implement the model API should inherit +from the [`ModelLike`](@ref) abstract type. + +Notably missing from the model API is the method to solve an optimization +problem. `ModelLike` objects may store an instance (e.g., in memory or backed by +a file format) without being linked to a particular solver. In addition to the +model API, MOI defines [`AbstractOptimizer`](@ref). + +*Optimizers* (or solvers) implement the model API (inheriting from `ModelLike`) +and additionally provide methods to solve the model. + +!!! info + Throughout the rest of the manual, `model` is used as a generic `ModelLike`, + and `optimizer` is used as a generic `AbstractOptimizer`. + +!!! tip + MOI does not export functions, but for brevity we often omit qualifying + names with the MOI module. Best practice is to have + ```julia + using MathOptInterface + const MOI = MathOptInterface + ``` + and prefix all MOI methods with `MOI.` in user code. If a name is also + available in base Julia, we always explicitly use the module prefix, for + example, with `MOI.get`. + +## Standard form problem + MathOptInterface represents optimization problems in the standard form: ```math diff --git a/docs/src/manual/status.md b/docs/src/manual/solutions.md similarity index 84% rename from docs/src/manual/status.md rename to docs/src/manual/solutions.md index 6cdeb63272..620d921ee7 100644 --- a/docs/src/manual/status.md +++ b/docs/src/manual/solutions.md @@ -7,7 +7,16 @@ end DocTestFilters = [r"MathOptInterface|MOI"] ``` -# Statuses +# Solutions + +## Solving and retrieving the results + +Once an optimizer is loaded with the objective function and all of the +constraints, we can ask the solver to solve the model by calling +[`optimize!`](@ref). +```julia +MOI.optimize!(optimizer) +``` ## Why did the solver stop? @@ -38,33 +47,32 @@ available, other statuses do not. For example, in the case of infeasiblity, a solver may return no result or a proof of infeasibility. The [`ResultCount`](@ref) attribute distinguishes between these two cases. -## What solution did the solver return? +## Primal solutions -The [`PrimalStatus`](@ref) and [`DualStatus`](@ref) attributes return a -[`ResultStatusCode`](@ref) that indicates if that component of the result -is present (i.e., not `NO_SOLUTION`) and explains how to interpret the result. +Use the [`PrimalStatus`](@ref) optimizer attribute to return a +[`ResultStatusCode`](@ref) describing the status of the primal solution. -If `PrimalStatus` is not `NO_SOLUTION`, then the primal may be retrieved with -the [`VariablePrimal`](@ref) attribute: -```julia -MOI.get(optimizer, VariablePrimal(), x) -``` +Common returns are described below in the [Common status situations](@ref) +section. + +Query the primal solution using the [`VariablePrimal`](@ref) and +[`ConstraintPrimal`](@ref) attributes. + +Query the objective function value using the [`ObjectiveValue`](@ref) attribute. + +## Dual solutions -If `x` is a [`VariableIndex`](@ref) then the function call returns a scalar, and -if `x` is a `Vector{VariableIndex}` then the call returns a vector of scalars. -`VariablePrimal()` is equivalent to `VariablePrimal(1)`, i.e., the variable -primal vector of the first result. Use `VariablePrimal(N)` to access the `N`th -result. +!!! warning + See [Duality](@ref) for a discussion of the MOI conventions for primal-dual + pairs and certificates. -See also the attributes [`ConstraintPrimal`](@ref), and [`ConstraintDual`](@ref). +Use the [`DualStatus`](@ref) optimizer attribute to return a +[`ResultStatusCode`](@ref) describing the status of the dual solution. -See [Duality](@ref) for a discussion of the MOI conventions for primal-dual -pairs and certificates. +Query the dual solution using the [`ConstraintDual`](@ref) attribute. -!!! note - We omit discussion of how to handle multiple results, i.e., when - `ResultCount` is greater than 1. This is supported in the API but not yet - implemented in any solver. +Query the dual objective function value using the [`DualObjectiveValue`](@ref) +attribute. ## Common status situations diff --git a/docs/src/manual/variables.md b/docs/src/manual/variables.md index a168878e70..d57b2e2f56 100644 --- a/docs/src/manual/variables.md +++ b/docs/src/manual/variables.md @@ -14,7 +14,7 @@ DocTestFilters = [r"MathOptInterface|MOI"] Use [`add_variable`](@ref) to add a single variable. ```jldoctest variables; setup=:(model = MOI.Utilities.Model{Float64}(); ) -julia> x = MOI.add_variable(mode) +julia> x = MOI.add_variable(model) MathOptInterface.VariableIndex(1) ``` [`add_variable`](@ref) returns a [`VariableIndex`](@ref) type, which should be @@ -55,7 +55,7 @@ false ## Variable attributes -The following attributes are available for variables +The following attributes are available for variables: * [`VariableName`](@ref) * [`VariablePrimalStart`](@ref) @@ -63,9 +63,9 @@ The following attributes are available for variables Get and set these attributes using [`get`(@ref) and [`set`](@ref). -```jldoctest constraints +```jldoctest variables julia> MOI.set(model, MOI.VariableName(), x, "var_x") julia> MOI.get(model, MOI.VariableName(), x) -var_x +"var_x" ``` From acc034365bddd5e4c8c244bd8710d4609caf0087 Mon Sep 17 00:00:00 2001 From: odow Date: Mon, 15 Mar 2021 10:47:23 +1300 Subject: [PATCH 5/5] Refactor reference --- docs/make.jl | 12 +- docs/src/manual/models.md | 154 +-------- docs/src/manual/standard_form.md | 155 +++++++++ docs/src/reference/callbacks.md | 46 +++ docs/src/reference/constraints.md | 42 +++ docs/src/reference/errors.md | 78 +++++ docs/src/reference/models.md | 102 ++++++ docs/src/reference/modification.md | 19 ++ docs/src/reference/nonlinear.md | 44 +++ docs/src/reference/reference.md | 509 ---------------------------- docs/src/reference/standard_form.md | 127 +++++++ docs/src/reference/variables.md | 39 +++ 12 files changed, 673 insertions(+), 654 deletions(-) create mode 100644 docs/src/manual/standard_form.md create mode 100644 docs/src/reference/callbacks.md create mode 100644 docs/src/reference/constraints.md create mode 100644 docs/src/reference/errors.md create mode 100644 docs/src/reference/models.md create mode 100644 docs/src/reference/modification.md create mode 100644 docs/src/reference/nonlinear.md delete mode 100644 docs/src/reference/reference.md create mode 100644 docs/src/reference/standard_form.md create mode 100644 docs/src/reference/variables.md diff --git a/docs/make.jl b/docs/make.jl index 9accfbf267..d7862fb8d9 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -24,6 +24,7 @@ makedocs( "background/duality.md", ], "Manual" => [ + "manual/standard_form.md", "manual/models.md", "manual/variables.md", "manual/constraints.md", @@ -32,7 +33,16 @@ makedocs( "manual/example.md", "manual/implementing.md", ], - "API Reference" => "reference/reference.md", + "API Reference" => [ + "reference/standard_form.md", + "reference/models.md", + "reference/variables.md", + "reference/constraints.md", + "reference/modification.md", + "reference/nonlinear.md", + "reference/callbacks.md", + "reference/errors.md", + ], "Submodules" => [ "Benchmarks" => [ "Overview" => "submodules/Benchmarks/overview.md", diff --git a/docs/src/manual/models.md b/docs/src/manual/models.md index 70bc02541d..346b6881ba 100644 --- a/docs/src/manual/models.md +++ b/docs/src/manual/models.md @@ -37,150 +37,16 @@ and additionally provide methods to solve the model. available in base Julia, we always explicitly use the module prefix, for example, with `MOI.get`. -## Standard form problem +## Attributes +Attributes can be set in different ways: -MathOptInterface represents optimization problems in the standard form: -```math -\begin{align} - & \min_{x \in \mathbb{R}^n} & f_0(x) - \\ - & \;\;\text{s.t.} & f_i(x) & \in \mathcal{S}_i & i = 1 \ldots m -\end{align} -``` -where: -* the functions ``f_0, f_1, \ldots, f_m`` are specified by - [`AbstractFunction`](@ref) objects -* the sets ``\mathcal{S}_1, \ldots, \mathcal{S}_m`` are specified by - [`AbstractSet`](@ref) objects - -!!! tip - For more information on this standard form, read [our paper](https://arxiv.org/pdf/2002.03447.pdf). - -MOI defines some commonly used functions and sets, but the interface is -extensible to other sets recognized by the solver. - -## Functions - -The function types implemented in MathOptInterface.jl are: - -* [`SingleVariable`](@ref): ``x_j``, i.e., projection onto a single coordinate - defined by a variable index ``j``. -* [`VectorOfVariables`](@ref): projection onto multiple coordinates (i.e., - extracting a subvector). -* [`ScalarAffineFunction`](@ref): ``a^T x + b``, where ``a`` is a vector and - ``b`` scalar. -* [`VectorAffineFunction`](@ref): ``A x + b``, where ``A`` is a matrix and - ``b`` is a vector. -* [`ScalarQuadraticFunction`](@ref): ``\frac{1}{2} x^T Q x + a^T x + b``, - where ``Q`` is a symmetric matrix, ``a`` is a vector, and ``b`` is a constant. -* [`VectorQuadraticFunction`](@ref): a vector of scalar-valued quadratic - functions. - -Extensions for nonlinear programming are present but not yet well documented. - -## One-dimensional sets - -The one-dimensional set types implemented in MathOptInterface.jl are: - -* [`LessThan(upper)`](@ref MathOptInterface.LessThan): - ``\{ x \in \mathbb{R} : x \le \mbox{upper} \}`` -* [`GreaterThan(lower)`](@ref MathOptInterface.GreaterThan): - ``\{ x \in \mathbb{R} : x \ge \mbox{lower} \}`` -* [`EqualTo(value)`](@ref MathOptInterface.GreaterThan): - ``\{ x \in \mathbb{R} : x = \mbox{value} \}`` -* [`Interval(lower, upper)`](@ref MathOptInterface.Interval): - ``\{ x \in \mathbb{R} : x \in [\mbox{lower},\mbox{upper}] \}`` -* [`Integer()`](@ref MathOptInterface.Integer): ``\mathbb{Z}`` -* [`ZeroOne()`](@ref MathOptInterface.ZeroOne): ``\{ 0, 1 \}`` -* [`Semicontinuous(lower,upper)`](@ref MathOptInterface.Semicontinuous): - ``\{ 0\} \cup [lower,upper]`` -* [`Semiinteger(lower,upper)`](@ref MathOptInterface.Semiinteger): - ``\{ 0\} \cup \{lower,lower+1,\ldots,upper-1,upper\}`` - -## Vector cones - -The vector-valued set types implemented in MathOptInterface.jl are: - -* [`Reals(dimension)`](@ref MathOptInterface.Reals): - ``\mathbb{R}^\mbox{dimension}`` -* [`Zeros(dimension)`](@ref MathOptInterface.Zeros): ``0^\mbox{dimension}`` -* [`Nonnegatives(dimension)`](@ref MathOptInterface.Nonnegatives): - ``\{ x \in \mathbb{R}^\mbox{dimension} : x \ge 0 \}`` -* [`Nonpositives(dimension)`](@ref MathOptInterface.Nonpositives): - ``\{ x \in \mathbb{R}^\mbox{dimension} : x \le 0 \}`` -* [`SecondOrderCone(dimension)`](@ref MathOptInterface.SecondOrderCone): - ``\{ (t,x) \in \mathbb{R}^\mbox{dimension} : t \ge \lVert x \rVert_2 \}`` -* [`RotatedSecondOrderCone(dimension)`](@ref MathOptInterface.RotatedSecondOrderCone): - ``\{ (t,u,x) \in \mathbb{R}^\mbox{dimension} : 2tu \ge \lVert x \rVert_2^2, t,u \ge 0 \}`` -* [`ExponentialCone()`](@ref MathOptInterface.ExponentialCone): - ``\{ (x,y,z) \in \mathbb{R}^3 : y \exp (x/y) \le z, y > 0 \}`` -* [`DualExponentialCone()`](@ref MathOptInterface.DualExponentialCone): - ``\{ (u,v,w) \in \mathbb{R}^3 : -u \exp (v/u) \le exp(1) w, u < 0 \}`` -* [`GeometricMeanCone(dimension)`](@ref MathOptInterface.GeometricMeanCone): - ``\{ (t,x) \in \mathbb{R}^{n+1} : x \ge 0, t \le \sqrt[n]{x_1 x_2 \cdots x_n} \}`` - where ``n`` is ``dimension - 1`` -* [`PowerCone(exponent)`](@ref MathOptInterface.PowerCone): - ``\{ (x,y,z) \in \mathbb{R}^3 : x^\mbox{exponent} y^{1-\mbox{exponent}} \ge |z|, x,y \ge 0 \}`` -* [`DualPowerCone(exponent)`](@ref MathOptInterface.DualPowerCone): - ``\{ (u,v,w) \in \mathbb{R}^3 : \frac{u}{\mbox{exponent}}^\mbox{exponent}\frac{v}{1-\mbox{exponent}}^{1-\mbox{exponent}} \ge |w|, u,v \ge 0 \}`` -* [`NormOneCone(dimension)`](@ref MathOptInterface.NormOneCone): -``\{ (t,x) \in \mathbb{R}^\mbox{dimension} : t \ge \lVert x \rVert_1 = \sum_i \lvert x_i \rvert \}`` -* [`NormInfinityCone(dimension)`](@ref MathOptInterface.NormInfinityCone): - ``\{ (t,x) \in \mathbb{R}^\mbox{dimension} : t \ge \lVert x \rVert_\infty = \max_i \lvert x_i \rvert \}`` -* [`RelativeEntropyCone(dimension)`](@ref MathOptInterface.RelativeEntropyCone): - ``\{ (u, v, w) \in \mathbb{R}^\mbox{dimension} : u \ge \sum_i w_i \log (\frac{w_i}{v_i}), v_i \ge 0, w_i \ge 0 \}`` - -## Matrix cones - -The matrix-valued set types implemented in MathOptInterface.jl are: - -* [`RootDetConeTriangle(dimension)`](@ref MathOptInterface.RootDetConeTriangle): - ``\{ (t,X) \in \mathbb{R}^{1+\mbox{dimension}(1+\mbox{dimension})/2} : t \le det(X)^{1/\mbox{dimension}}, X \mbox{is the upper triangle of a PSD matrix} \}`` -* [`RootDetConeSquare(dimension)`](@ref MathOptInterface.RootDetConeSquare): - ``\{ (t,X) \in \mathbb{R}^{1+\mbox{dimension}^2} : t \le \det(X)^{1/\mbox{dimension}}, X \mbox{is a PSD matrix} \}`` - -* [`PositiveSemidefiniteConeTriangle(dimension)`](@ref MathOptInterface.PositiveSemidefiniteConeTriangle): - ``\{ X \in \mathbb{R}^{\mbox{dimension}(\mbox{dimension}+1)/2} : X \mbox{is the upper triangle of a PSD matrix} \}`` -* [`PositiveSemidefiniteConeSquare(dimension)`](@ref MathOptInterface.PositiveSemidefiniteConeSquare): - ``\{ X \in \mathbb{R}^{\mbox{dimension}^2} : X \mbox{is a PSD matrix} \}`` - -* [`LogDetConeTriangle(dimension)`](@ref MathOptInterface.LogDetConeTriangle): - ``\{ (t,u,X) \in \mathbb{R}^{2+\mbox{dimension}(1+\mbox{dimension})/2} : t \le u\log(\det(X/u)), X \mbox{is the upper triangle of a PSD matrix}, u > 0 \}`` -* [`LogDetConeSquare(dimension)`](@ref MathOptInterface.LogDetConeSquare): - ``\{ (t,u,X) \in \mathbb{R}^{2+\mbox{dimension}^2} : t \le u \log(\det(X/u)), X \mbox{is a PSD matrix}, u > 0 \}`` - -* [`NormSpectralCone(row_dim, column_dim)`](@ref MathOptInterface.NormSpectralCone): - ``\{ (t, X) \in \mathbb{R}^{1 + \mbox{row_dim} \times \mbox{column_dim}} : t \ge \sigma_1(X), X \mbox{is a matrix with row_dim rows and column_dim columns} \}`` -* [`NormNuclearCone(row_dim, column_dim)`](@ref MathOptInterface.NormNuclearCone): - ``\{ (t, X) \in \mathbb{R}^{1 + \mbox{row_dim} \times \mbox{column_dim}} : t \ge \sum_i \sigma_i(X), X \mbox{is a matrix with row_dim rows and column_dim columns} \}`` - -Some of these cones can take two forms: `XXXConeTriangle` and `XXXConeSquare`. - -In `XXXConeTriangle` sets, the matrix is assumed to be symmetric, and the -elements are provided by a vector, in which the entries of the upper-right -triangular part of the matrix are given column by column (or equivalently, the -entries of the lower-left triangular part are given row by row). - -In `XXXConeSquare` sets, the entries of the matrix are given column by column -(or equivalently, row by row), and the matrix is constrained to be symmetric. As -an example, given a 2-by-2 matrix of variables `X` and a one-dimensional -variable `t`, we can specify a root-det constraint as -`[t, X11, X12, X22] ∈ RootDetConeTriangle` or -`[t, X11, X12, X21, X22] ∈ RootDetConeSquare`. - -We provide both forms to enable flexibility for solvers who may natively support -one or the other. Transformations between `XXXConeTriangle` and `XXXConeSquare` -are handled by bridges, which removes the chance of conversion mistakes by users -or solver developers. - -## Multi-dimensional sets with combinatorial structure +* it is either set when the model is created like [`SolverName`](@ref) and + [`RawSolver`](@ref), +* or explicitly when the model is copied like [`ObjectiveSense`](@ref), +* or implicitly, e.g., [`NumberOfVariables`](@ref) is implicitly set by + [`add_variable`](@ref) and [`ConstraintFunction`](@ref) is implicitly set by + [`add_constraint`](@ref). +* or it is set to contain the result of the optimization during + [`optimize!`](@ref) like [`VariablePrimal`](@ref). -* [`SOS1(weights)`](@ref MathOptInterface.SOS1): - A special ordered set of Type I. -* [`SOS2(weights)`](@ref MathOptInterface.SOS2): - A special ordered set of Type II. -* [`IndicatorSet(set)`](@ref MathOptInterface.IndicatorSet): - A set to specify indicator constraints. -* [`Complements`](@ref MathOptInterface.Complements): - A set for mixed complementarity constraints. diff --git a/docs/src/manual/standard_form.md b/docs/src/manual/standard_form.md new file mode 100644 index 0000000000..e4600da18f --- /dev/null +++ b/docs/src/manual/standard_form.md @@ -0,0 +1,155 @@ +```@meta +CurrentModule = MathOptInterface +DocTestSetup = quote + using MathOptInterface + const MOI = MathOptInterface +end +DocTestFilters = [r"MathOptInterface|MOI"] +``` + +# Standard form problem + +MathOptInterface represents optimization problems in the standard form: +```math +\begin{align} + & \min_{x \in \mathbb{R}^n} & f_0(x) + \\ + & \;\;\text{s.t.} & f_i(x) & \in \mathcal{S}_i & i = 1 \ldots m +\end{align} +``` +where: +* the functions ``f_0, f_1, \ldots, f_m`` are specified by + [`AbstractFunction`](@ref) objects +* the sets ``\mathcal{S}_1, \ldots, \mathcal{S}_m`` are specified by + [`AbstractSet`](@ref) objects + +!!! tip + For more information on this standard form, read [our paper](https://arxiv.org/pdf/2002.03447.pdf). + +MOI defines some commonly used functions and sets, but the interface is +extensible to other sets recognized by the solver. + +## Functions + +The function types implemented in MathOptInterface.jl are: + +* [`SingleVariable`](@ref): ``x_j``, i.e., projection onto a single coordinate + defined by a variable index ``j``. +* [`VectorOfVariables`](@ref): projection onto multiple coordinates (i.e., + extracting a subvector). +* [`ScalarAffineFunction`](@ref): ``a^T x + b``, where ``a`` is a vector and + ``b`` scalar. +* [`VectorAffineFunction`](@ref): ``A x + b``, where ``A`` is a matrix and + ``b`` is a vector. +* [`ScalarQuadraticFunction`](@ref): ``\frac{1}{2} x^T Q x + a^T x + b``, + where ``Q`` is a symmetric matrix, ``a`` is a vector, and ``b`` is a constant. +* [`VectorQuadraticFunction`](@ref): a vector of scalar-valued quadratic + functions. + +Extensions for nonlinear programming are present but not yet well documented. + +## One-dimensional sets + +The one-dimensional set types implemented in MathOptInterface.jl are: + +* [`LessThan(upper)`](@ref MathOptInterface.LessThan): + ``\{ x \in \mathbb{R} : x \le \mbox{upper} \}`` +* [`GreaterThan(lower)`](@ref MathOptInterface.GreaterThan): + ``\{ x \in \mathbb{R} : x \ge \mbox{lower} \}`` +* [`EqualTo(value)`](@ref MathOptInterface.GreaterThan): + ``\{ x \in \mathbb{R} : x = \mbox{value} \}`` +* [`Interval(lower, upper)`](@ref MathOptInterface.Interval): + ``\{ x \in \mathbb{R} : x \in [\mbox{lower},\mbox{upper}] \}`` +* [`Integer()`](@ref MathOptInterface.Integer): ``\mathbb{Z}`` +* [`ZeroOne()`](@ref MathOptInterface.ZeroOne): ``\{ 0, 1 \}`` +* [`Semicontinuous(lower,upper)`](@ref MathOptInterface.Semicontinuous): + ``\{ 0\} \cup [lower,upper]`` +* [`Semiinteger(lower,upper)`](@ref MathOptInterface.Semiinteger): + ``\{ 0\} \cup \{lower,lower+1,\ldots,upper-1,upper\}`` + +## Vector cones + +The vector-valued set types implemented in MathOptInterface.jl are: + +* [`Reals(dimension)`](@ref MathOptInterface.Reals): + ``\mathbb{R}^\mbox{dimension}`` +* [`Zeros(dimension)`](@ref MathOptInterface.Zeros): ``0^\mbox{dimension}`` +* [`Nonnegatives(dimension)`](@ref MathOptInterface.Nonnegatives): + ``\{ x \in \mathbb{R}^\mbox{dimension} : x \ge 0 \}`` +* [`Nonpositives(dimension)`](@ref MathOptInterface.Nonpositives): + ``\{ x \in \mathbb{R}^\mbox{dimension} : x \le 0 \}`` +* [`SecondOrderCone(dimension)`](@ref MathOptInterface.SecondOrderCone): + ``\{ (t,x) \in \mathbb{R}^\mbox{dimension} : t \ge \lVert x \rVert_2 \}`` +* [`RotatedSecondOrderCone(dimension)`](@ref MathOptInterface.RotatedSecondOrderCone): + ``\{ (t,u,x) \in \mathbb{R}^\mbox{dimension} : 2tu \ge \lVert x \rVert_2^2, t,u \ge 0 \}`` +* [`ExponentialCone()`](@ref MathOptInterface.ExponentialCone): + ``\{ (x,y,z) \in \mathbb{R}^3 : y \exp (x/y) \le z, y > 0 \}`` +* [`DualExponentialCone()`](@ref MathOptInterface.DualExponentialCone): + ``\{ (u,v,w) \in \mathbb{R}^3 : -u \exp (v/u) \le exp(1) w, u < 0 \}`` +* [`GeometricMeanCone(dimension)`](@ref MathOptInterface.GeometricMeanCone): + ``\{ (t,x) \in \mathbb{R}^{n+1} : x \ge 0, t \le \sqrt[n]{x_1 x_2 \cdots x_n} \}`` + where ``n`` is ``dimension - 1`` +* [`PowerCone(exponent)`](@ref MathOptInterface.PowerCone): + ``\{ (x,y,z) \in \mathbb{R}^3 : x^\mbox{exponent} y^{1-\mbox{exponent}} \ge |z|, x,y \ge 0 \}`` +* [`DualPowerCone(exponent)`](@ref MathOptInterface.DualPowerCone): + ``\{ (u,v,w) \in \mathbb{R}^3 : \frac{u}{\mbox{exponent}}^\mbox{exponent}\frac{v}{1-\mbox{exponent}}^{1-\mbox{exponent}} \ge |w|, u,v \ge 0 \}`` +* [`NormOneCone(dimension)`](@ref MathOptInterface.NormOneCone): +``\{ (t,x) \in \mathbb{R}^\mbox{dimension} : t \ge \lVert x \rVert_1 = \sum_i \lvert x_i \rvert \}`` +* [`NormInfinityCone(dimension)`](@ref MathOptInterface.NormInfinityCone): + ``\{ (t,x) \in \mathbb{R}^\mbox{dimension} : t \ge \lVert x \rVert_\infty = \max_i \lvert x_i \rvert \}`` +* [`RelativeEntropyCone(dimension)`](@ref MathOptInterface.RelativeEntropyCone): + ``\{ (u, v, w) \in \mathbb{R}^\mbox{dimension} : u \ge \sum_i w_i \log (\frac{w_i}{v_i}), v_i \ge 0, w_i \ge 0 \}`` + +## Matrix cones + +The matrix-valued set types implemented in MathOptInterface.jl are: + +* [`RootDetConeTriangle(dimension)`](@ref MathOptInterface.RootDetConeTriangle): + ``\{ (t,X) \in \mathbb{R}^{1+\mbox{dimension}(1+\mbox{dimension})/2} : t \le det(X)^{1/\mbox{dimension}}, X \mbox{is the upper triangle of a PSD matrix} \}`` +* [`RootDetConeSquare(dimension)`](@ref MathOptInterface.RootDetConeSquare): + ``\{ (t,X) \in \mathbb{R}^{1+\mbox{dimension}^2} : t \le \det(X)^{1/\mbox{dimension}}, X \mbox{is a PSD matrix} \}`` + +* [`PositiveSemidefiniteConeTriangle(dimension)`](@ref MathOptInterface.PositiveSemidefiniteConeTriangle): + ``\{ X \in \mathbb{R}^{\mbox{dimension}(\mbox{dimension}+1)/2} : X \mbox{is the upper triangle of a PSD matrix} \}`` +* [`PositiveSemidefiniteConeSquare(dimension)`](@ref MathOptInterface.PositiveSemidefiniteConeSquare): + ``\{ X \in \mathbb{R}^{\mbox{dimension}^2} : X \mbox{is a PSD matrix} \}`` + +* [`LogDetConeTriangle(dimension)`](@ref MathOptInterface.LogDetConeTriangle): + ``\{ (t,u,X) \in \mathbb{R}^{2+\mbox{dimension}(1+\mbox{dimension})/2} : t \le u\log(\det(X/u)), X \mbox{is the upper triangle of a PSD matrix}, u > 0 \}`` +* [`LogDetConeSquare(dimension)`](@ref MathOptInterface.LogDetConeSquare): + ``\{ (t,u,X) \in \mathbb{R}^{2+\mbox{dimension}^2} : t \le u \log(\det(X/u)), X \mbox{is a PSD matrix}, u > 0 \}`` + +* [`NormSpectralCone(row_dim, column_dim)`](@ref MathOptInterface.NormSpectralCone): + ``\{ (t, X) \in \mathbb{R}^{1 + \mbox{row_dim} \times \mbox{column_dim}} : t \ge \sigma_1(X), X \mbox{is a matrix with row_dim rows and column_dim columns} \}`` +* [`NormNuclearCone(row_dim, column_dim)`](@ref MathOptInterface.NormNuclearCone): + ``\{ (t, X) \in \mathbb{R}^{1 + \mbox{row_dim} \times \mbox{column_dim}} : t \ge \sum_i \sigma_i(X), X \mbox{is a matrix with row_dim rows and column_dim columns} \}`` + +Some of these cones can take two forms: `XXXConeTriangle` and `XXXConeSquare`. + +In `XXXConeTriangle` sets, the matrix is assumed to be symmetric, and the +elements are provided by a vector, in which the entries of the upper-right +triangular part of the matrix are given column by column (or equivalently, the +entries of the lower-left triangular part are given row by row). + +In `XXXConeSquare` sets, the entries of the matrix are given column by column +(or equivalently, row by row), and the matrix is constrained to be symmetric. As +an example, given a 2-by-2 matrix of variables `X` and a one-dimensional +variable `t`, we can specify a root-det constraint as +`[t, X11, X12, X22] ∈ RootDetConeTriangle` or +`[t, X11, X12, X21, X22] ∈ RootDetConeSquare`. + +We provide both forms to enable flexibility for solvers who may natively support +one or the other. Transformations between `XXXConeTriangle` and `XXXConeSquare` +are handled by bridges, which removes the chance of conversion mistakes by users +or solver developers. + +## Multi-dimensional sets with combinatorial structure + +* [`SOS1(weights)`](@ref MathOptInterface.SOS1): + A special ordered set of Type I. +* [`SOS2(weights)`](@ref MathOptInterface.SOS2): + A special ordered set of Type II. +* [`IndicatorSet(set)`](@ref MathOptInterface.IndicatorSet): + A set to specify indicator constraints. +* [`Complements`](@ref MathOptInterface.Complements): + A set for mixed complementarity constraints. diff --git a/docs/src/reference/callbacks.md b/docs/src/reference/callbacks.md new file mode 100644 index 0000000000..435c79a46e --- /dev/null +++ b/docs/src/reference/callbacks.md @@ -0,0 +1,46 @@ +```@meta +CurrentModule = MathOptInterface +DocTestSetup = quote + using MathOptInterface + const MOI = MathOptInterface +end +DocTestFilters = [r"MathOptInterface|MOI"] +``` + +# Callbacks + +```@docs +AbstractCallback +AbstractSubmittable +submit +``` + +## Attributes + +```@docs +CallbackNodeStatus +CallbackNodeStatusCode +CallbackVariablePrimal +``` + +## Lazy constraints + +```@docs +LazyConstraintCallback +LazyConstraint +``` + +## User cuts + +```@docs +UserCutCallback +UserCut +``` + +## Heuristic solutions + +```@docs +HeuristicCallback +HeuristicSolutionStatus +HeuristicSolution +``` diff --git a/docs/src/reference/constraints.md b/docs/src/reference/constraints.md new file mode 100644 index 0000000000..c2122ea6dc --- /dev/null +++ b/docs/src/reference/constraints.md @@ -0,0 +1,42 @@ +```@meta +CurrentModule = MathOptInterface +DocTestSetup = quote + using MathOptInterface + const MOI = MathOptInterface +end +DocTestFilters = [r"MathOptInterface|MOI"] +``` + +# [Constraints](@id constraints_ref) + +## Types + +```@docs +ConstraintIndex +``` + +## Functions + +```@docs +is_valid(::ModelLike,::ConstraintIndex) +add_constraint +add_constraints +transform +supports_constraint +``` + +## Attributes + +```@docs +AbstractConstraintAttribute +ConstraintName +ConstraintPrimalStart +ConstraintDualStart +ConstraintPrimal +ConstraintDual +ConstraintBasisStatus +BasisStatusCode +ConstraintFunction +CanonicalConstraintFunction +ConstraintSet +``` diff --git a/docs/src/reference/errors.md b/docs/src/reference/errors.md new file mode 100644 index 0000000000..ea9818a763 --- /dev/null +++ b/docs/src/reference/errors.md @@ -0,0 +1,78 @@ +```@meta +CurrentModule = MathOptInterface +DocTestSetup = quote + using MathOptInterface + const MOI = MathOptInterface +end +DocTestFilters = [r"MathOptInterface|MOI"] +``` + +# Errors + +When an MOI call fails on a model, precise errors should be thrown when possible +instead of simply calling `error` with a message. The docstrings for the +respective methods describe the errors that the implementation should thrown in +certain situations. This error-reporting system allows code to distinguish +between internal errors (that should be shown to the user) and unsupported +operations which may have automatic workarounds. + +When an invalid index is used in an MOI call, an [`InvalidIndex`](@ref) should +be thrown: +```@docs +InvalidIndex +``` + +As discussed in [JuMP mapping](@ref), for scalar constraint with a nonzero +function constant, a [`ScalarFunctionConstantNotZero`](@ref) exception may be +thrown: +```@docs +ScalarFunctionConstantNotZero +``` + +Some [`SingleVariable`](@ref) constraints cannot be combined on the same +variable: +```@docs +LowerBoundAlreadySet +UpperBoundAlreadySet +``` + +As discussed in [`AbstractCallback`](@ref), trying to [`get`](@ref) attributes +inside a callback may throw: +```@docs +OptimizeInProgress +``` + +Trying to submit the wrong type of [`AbstractSubmittable`](@ref) inside an +[`AbstractCallback`](@ref) (e.g., a [`UserCut`](@ref) inside a +[`LazyConstraintCallback`](@ref)) will throw: +```@docs +InvalidCallbackUsage +``` + +The rest of the errors defined in MOI fall in two categories represented by the +following two abstract types: +```@docs +UnsupportedError +NotAllowedError +``` + +The different [`UnsupportedError`](@ref) and [`NotAllowedError`](@ref) are the +following errors: +```@docs +UnsupportedAttribute +SetAttributeNotAllowed +AddVariableNotAllowed +UnsupportedConstraint +AddConstraintNotAllowed +ModifyConstraintNotAllowed +ModifyObjectiveNotAllowed +DeleteNotAllowed +UnsupportedSubmittable +SubmitNotAllowed +``` + +Note that setting the [`ConstraintFunction`](@ref) of a [`SingleVariable`] +constraint is not allowed: +```@docs +SettingSingleVariableFunctionNotAllowed +``` diff --git a/docs/src/reference/models.md b/docs/src/reference/models.md new file mode 100644 index 0000000000..a8009726c2 --- /dev/null +++ b/docs/src/reference/models.md @@ -0,0 +1,102 @@ +```@meta +CurrentModule = MathOptInterface +DocTestSetup = quote + using MathOptInterface + const MOI = MathOptInterface +end +DocTestFilters = [r"MathOptInterface|MOI"] +``` + +# Models + +## Attribute interface + +```@docs +is_set_by_optimize +is_copyable +get +get! +set +supports +``` + +## Model interface + +```@docs +ModelLike +is_empty +empty! +write_to_file +read_from_file +copy_to +``` + +## Model attributes + +```@docs +AbstractModelAttribute +Name +ObjectiveFunction +ObjectiveFunctionType +ObjectiveSense +NumberOfVariables +ListOfVariableIndices +ListOfConstraints +NumberOfConstraints +ListOfConstraintIndices +ListOfOptimizerAttributesSet +ListOfModelAttributesSet +ListOfVariableAttributesSet +ListOfConstraintAttributesSet +``` + +## Optimizer interface + +```@docs +AbstractOptimizer +OptimizerWithAttributes +optimize! +instantiate +``` + +## Optimizer attributes + +```@docs +AbstractOptimizerAttribute +SolverName +Silent +TimeLimitSec +RawParameter +NumberOfThreads +RawSolver +``` + +List of attributes useful for optimizers + +```@docs +TerminationStatus +TerminationStatusCode +PrimalStatus +DualStatus +ResultStatusCode +RawStatusString +ResultCount +ObjectiveValue +DualObjectiveValue +ObjectiveBound +RelativeGap +SolveTime +SimplexIterations +BarrierIterations +NodeCount +``` + +### Conflict Status + +```@docs +compute_conflict! +ConflictStatus +ConflictStatusCode +ConstraintConflictStatus +ConflictParticipationStatusCode +``` diff --git a/docs/src/reference/modification.md b/docs/src/reference/modification.md new file mode 100644 index 0000000000..abb08f534c --- /dev/null +++ b/docs/src/reference/modification.md @@ -0,0 +1,19 @@ +```@meta +CurrentModule = MathOptInterface +DocTestSetup = quote + using MathOptInterface + const MOI = MathOptInterface +end +DocTestFilters = [r"MathOptInterface|MOI"] +``` + +# Modifications + +```@docs +modify +AbstractFunctionModification +ScalarConstantChange +VectorConstantChange +ScalarCoefficientChange +MultirowChange +``` diff --git a/docs/src/reference/nonlinear.md b/docs/src/reference/nonlinear.md new file mode 100644 index 0000000000..04a954f470 --- /dev/null +++ b/docs/src/reference/nonlinear.md @@ -0,0 +1,44 @@ +```@meta +CurrentModule = MathOptInterface +DocTestSetup = quote + using MathOptInterface + const MOI = MathOptInterface +end +DocTestFilters = [r"MathOptInterface|MOI"] +``` + +# Nonlinear programming + +## Types +```@docs +AbstractNLPEvaluator +NLPBoundsPair +NLPBlockData +``` + +## Attributes + +```@docs +NLPBlock +NLPBlockDual +NLPBlockDualStart +``` + +## Functions + +```@docs +initialize +features_available +eval_objective +eval_constraint +eval_objective_gradient +jacobian_structure +hessian_lagrangian_structure +eval_constraint_jacobian +eval_constraint_jacobian_product +eval_constraint_jacobian_transpose_product +eval_hessian_lagrangian +eval_hessian_lagrangian_product +objective_expr +constraint_expr +``` diff --git a/docs/src/reference/reference.md b/docs/src/reference/reference.md deleted file mode 100644 index 8909b730e4..0000000000 --- a/docs/src/reference/reference.md +++ /dev/null @@ -1,509 +0,0 @@ -```@meta -CurrentModule = MathOptInterface -DocTestSetup = quote - using MathOptInterface - const MOI = MathOptInterface - - # For compatibility with both Julia 1.0.5 and 1.5.2 - # Upon the Julia LTS version becoming 1.6, these imports could be dropped, - # and all ScalarAffineTerm and VariableIndex instances in doctests below - # could be replaced with MOI.ScalarAffineTerm and MOI.VariableIndex - # Check discussion at PR 1184: https://github.com/jump-dev/MathOptInterface.jl/pull/1184#discussion_r515300914 - import MathOptInterface.ScalarAffineTerm - import MathOptInterface.VariableIndex -end -DocTestFilters = [r"MathOptInterface|MOI"] -``` - -# API Reference - -[Some introduction to API. List basic standalone methods.] - -## Attributes - -List of attribute categories. - -```@docs -AbstractOptimizerAttribute -AbstractModelAttribute -AbstractVariableAttribute -AbstractConstraintAttribute -``` - -Attributes can be set in different ways: - -* it is either set when the model is created like [`SolverName`](@ref) and - [`RawSolver`](@ref), -* or explicitly when the model is copied like [`ObjectiveSense`](@ref), -* or implicitly, e.g., [`NumberOfVariables`](@ref) is implicitly set by - [`add_variable`](@ref) and [`ConstraintFunction`](@ref) is implicitly set by - [`add_constraint`](@ref). -* or it is set to contain the result of the optimization during - [`optimize!`](@ref) like [`VariablePrimal`](@ref). - -The following functions allow to distinguish between some of these different -categories: -```@docs -is_set_by_optimize -is_copyable -``` - -Functions for getting and setting attributes. - -```@docs -get -get! -set -supports -``` - -### Submit - -Objects may be submitted to an optimizer using [`submit`](@ref). -```@docs -AbstractSubmittable -submit -``` - -List of submittables - -```@docs -LazyConstraint -HeuristicSolutionStatus -HeuristicSolution -UserCut -``` - -## Model Interface - -```@docs -ModelLike -is_empty -empty! -write_to_file -read_from_file -``` - -Copying - -```@docs -copy_to -``` - -List of model attributes - -```@docs -Name -ObjectiveSense -NumberOfVariables -ListOfVariableIndices -ListOfConstraints -NumberOfConstraints -ListOfConstraintIndices -ListOfOptimizerAttributesSet -ListOfModelAttributesSet -ListOfVariableAttributesSet -ListOfConstraintAttributesSet -``` - -## Optimizers - -```@docs -AbstractOptimizer -optimize! -OptimizerWithAttributes -instantiate -``` - -List of optimizers attributes - -```@docs -SolverName -Silent -TimeLimitSec -RawParameter -NumberOfThreads -``` - -List of attributes useful for optimizers - - -```@docs -RawSolver -ResultCount -ObjectiveFunction -ObjectiveFunctionType -ObjectiveValue -DualObjectiveValue -ObjectiveBound -RelativeGap -SolveTime -SimplexIterations -BarrierIterations -NodeCount -TerminationStatus -RawStatusString -PrimalStatus -DualStatus -``` - -Attributes relating to solver callbacks: - -```@docs -AbstractCallback -LazyConstraintCallback -HeuristicCallback -UserCutCallback -CallbackNodeStatus -CallbackNodeStatusCode -CallbackVariablePrimal -``` -### Termination Status - -The `TerminationStatus` attribute indicates why the optimizer stopped executing. -The value of the attribute is of type `TerminationStatusCode`. - -```@docs -TerminationStatusCode -``` - -### Conflict Status - -The `ConflictStatus` attribute indicates why the conflict finder stopped executing. -The value of the attribute is of type `ConflictStatusCode`. - -```@docs -compute_conflict! -ConflictStatus -ConflictStatusCode -ConstraintConflictStatus -ConflictParticipationStatusCode -``` - -### Result Status - -The `PrimalStatus` and `DualStatus` attributes indicate how to interpret the result returned by the solver. -The value of the attribute is of type `ResultStatusCode`. - -```@docs -ResultStatusCode -``` - -## Variables and Constraints - -### Basis Status - -The `BasisStatus` attribute of a constraint describes its status with respect to -a basis, if one is known. The value of the attribute is of type -`BasisStatusCode`. - -```@docs -BasisStatusCode -``` - -### Index types - -```@docs -VariableIndex -ConstraintIndex -is_valid -throw_if_not_valid -delete(::ModelLike, ::Index) -delete(::ModelLike, ::Vector{<:Index}) -``` - -### Variables - -*Free variables* are the variables created with [`add_variable`](@ref) or -[`add_variables`](@ref) while *constrained variables* are -the variables created with [`add_constrained_variable`](@ref) or -[`add_constrained_variables`](@ref). Adding constrained variables instead of -constraining free variables with [`add_constraint`](@ref) allows -[variable bridges](@ref variable_bridges) to be used. -Note further that free variables that are constrained with -[`add_constraint`](@ref) may be copied by [`copy_to`](@ref) with -[`add_constrained_variable`](@ref) or [`add_constrained_variables`](@ref) by the -[`Utilities.CachingOptimizer`](@ref). -More precisely, the attributes do not distinguish constraints on variables -created with `add_constrained_variable(s)` or `add_variable(s)`/`add_constraint`. -When the model is copied, if a variable is constrained in several sets, -the implementation of [`copy_to`](@ref) can determine whether it is added -using [`add_variable`](@ref) or [`add_constrained_variable`](@ref) with one -of the sets. The rest of the constraints on the variables are added -with [`add_constraint`](@ref). For deleting, see [Index types](@ref). - -```@docs -add_variable -add_variables -add_constrained_variable -add_constrained_variables -supports_add_constrained_variable -supports_add_constrained_variables -``` - -List of attributes associated with variables. [category AbstractVariableAttribute] -Calls to `get` and `set` should include as an argument a single `VariableIndex` or a vector of `VariableIndex` objects. - -```@docs -VariableName -VariablePrimalStart -VariablePrimal -``` - -### [Constraints](@id constraints_ref) - -Functions for adding and modifying constraints. - -```@docs -is_valid(::ModelLike,::ConstraintIndex) -add_constraint -add_constraints -transform -supports_constraint -``` - -List of attributes associated with constraints. [category AbstractConstraintAttribute] -Calls to `get` and `set` should include as an argument a single `ConstraintIndex` or a vector of `ConstraintIndex{F,S}` objects. - -```@docs -ConstraintName -ConstraintPrimalStart -ConstraintDualStart -ConstraintPrimal -ConstraintDual -ConstraintBasisStatus -ConstraintFunction -CanonicalConstraintFunction -ConstraintSet -``` - -Note that setting the [`ConstraintFunction`](@ref) of a [`SingleVariable`] -constraint is not allowed: -```@docs -SettingSingleVariableFunctionNotAllowed -``` - -## Functions and function modifications - -List of recognized functions. -```@docs -AbstractFunction -AbstractVectorFunction -SingleVariable -VectorOfVariables -ScalarAffineTerm -ScalarAffineFunction -VectorAffineTerm -VectorAffineFunction -ScalarQuadraticTerm -ScalarQuadraticFunction -VectorQuadraticTerm -VectorQuadraticFunction -``` - -Functions for getting and setting properties of functions. - -```@docs -output_dimension -constant(f::Union{ScalarAffineFunction, ScalarQuadraticFunction}) -constant(f::Union{VectorAffineFunction, VectorQuadraticFunction}) -constant(f::SingleVariable, ::DataType) -constant(f::VectorOfVariables, T::DataType) -``` - -## Sets - -All sets are subtypes of [`AbstractSet`](@ref) and they should either be scalar -or vector sets. -```@docs -AbstractSet -AbstractScalarSet -AbstractVectorSet -``` - -Functions for getting properties of sets. -```@docs -dimension -dual_set -dual_set_type -constant(s::EqualTo) -supports_dimension_update -update_dimension -``` - -### Scalar sets - -List of recognized scalar sets. -```@docs -GreaterThan -LessThan -EqualTo -Interval -Integer -ZeroOne -Semicontinuous -Semiinteger -``` - -### Vector sets - -List of recognized vector sets. -```@docs -Reals -Zeros -Nonnegatives -Nonpositives -NormInfinityCone -NormOneCone -SecondOrderCone -RotatedSecondOrderCone -GeometricMeanCone -ExponentialCone -DualExponentialCone -PowerCone -DualPowerCone -RelativeEntropyCone -NormSpectralCone -NormNuclearCone -SOS1 -SOS2 -IndicatorSet -Complements -``` - -### Matrix sets - -Matrix sets are vectorized in order to be subtypes of -[`AbstractVectorSet`](@ref). For sets of symmetric matrices, storing both the -`(i, j)` and `(j, i)` elements is redundant so there exists the -[`AbstractSymmetricMatrixSetTriangle`](@ref) set to represent only the -vectorization of the upper triangular part of the matrix. When the matrix -of expressions constrained to be in the set is not symmetric and hence -the `(i, j)` and `(j, i)` elements should be constrained to be symmetric, -the [`AbstractSymmetricMatrixSetSquare`](@ref) set can be used. The -[`Bridges.Constraint.SquareBridge`](@ref) can transform a set from the square -form to the [`triangular_form`](@ref) by adding appropriate constraints if -the `(i, j)` and `(j, i)` expressions are different. -```@docs -AbstractSymmetricMatrixSetTriangle -AbstractSymmetricMatrixSetSquare -side_dimension -triangular_form -``` -List of recognized matrix sets. -```@docs -PositiveSemidefiniteConeTriangle -PositiveSemidefiniteConeSquare -LogDetConeTriangle -LogDetConeSquare -RootDetConeTriangle -RootDetConeSquare -``` - -## Modifications - -Functions for modifying objective and constraint functions. - -```@docs -modify -AbstractFunctionModification -ScalarConstantChange -VectorConstantChange -ScalarCoefficientChange -MultirowChange -``` - -## Nonlinear programming (NLP) - -### Attributes - -```@docs -NLPBlock -NLPBoundsPair -NLPBlockData -NLPBlockDual -NLPBlockDualStart -``` -### NLP evaluator methods - -```@docs -AbstractNLPEvaluator -initialize -features_available -eval_objective -eval_constraint -eval_objective_gradient -jacobian_structure -hessian_lagrangian_structure -eval_constraint_jacobian -eval_constraint_jacobian_product -eval_constraint_jacobian_transpose_product -eval_hessian_lagrangian -eval_hessian_lagrangian_product -objective_expr -constraint_expr -``` - -## Errors - -When an MOI call fails on a model, precise errors should be thrown when possible -instead of simply calling `error` with a message. The docstrings for the -respective methods describe the errors that the implementation should thrown in -certain situations. This error-reporting system allows code to distinguish -between internal errors (that should be shown to the user) and unsupported -operations which may have automatic workarounds. - -When an invalid index is used in an MOI call, an [`InvalidIndex`](@ref) should -be thrown: -```@docs -InvalidIndex -``` - -As discussed in [JuMP mapping](@ref), for scalar constraint with a nonzero -function constant, a [`ScalarFunctionConstantNotZero`](@ref) exception may be -thrown: -```@docs -ScalarFunctionConstantNotZero -``` - -Some [`SingleVariable`](@ref) constraints cannot be combined on the same -variable: -```@docs -LowerBoundAlreadySet -UpperBoundAlreadySet -``` - -As discussed in [`AbstractCallback`](@ref), trying to [`get`](@ref) attributes -inside a callback may throw: -```@docs -OptimizeInProgress -``` - -Trying to submit the wrong type of [`AbstractSubmittable`](@ref) inside an -[`AbstractCallback`](@ref) (e.g., a [`UserCut`](@ref) inside a -[`LazyConstraintCallback`](@ref)) will throw: -```@docs -InvalidCallbackUsage -``` - -The rest of the errors defined in MOI fall in two categories represented by the -following two abstract types: -```@docs -UnsupportedError -NotAllowedError -``` - -The different [`UnsupportedError`](@ref) and [`NotAllowedError`](@ref) are the -following errors: -```@docs -UnsupportedAttribute -SetAttributeNotAllowed -AddVariableNotAllowed -UnsupportedConstraint -AddConstraintNotAllowed -ModifyConstraintNotAllowed -ModifyObjectiveNotAllowed -DeleteNotAllowed -UnsupportedSubmittable -SubmitNotAllowed -``` diff --git a/docs/src/reference/standard_form.md b/docs/src/reference/standard_form.md new file mode 100644 index 0000000000..d3ad803b4f --- /dev/null +++ b/docs/src/reference/standard_form.md @@ -0,0 +1,127 @@ +```@meta +CurrentModule = MathOptInterface +DocTestSetup = quote + using MathOptInterface + const MOI = MathOptInterface +end +DocTestFilters = [r"MathOptInterface|MOI"] +``` + +# Standard form + +## Functions + +```@docs +AbstractFunction +AbstractVectorFunction +SingleVariable +VectorOfVariables +ScalarAffineTerm +ScalarAffineFunction +VectorAffineTerm +VectorAffineFunction +ScalarQuadraticTerm +ScalarQuadraticFunction +VectorQuadraticTerm +VectorQuadraticFunction +``` + +### Utilities + +```@docs +output_dimension +constant(f::Union{ScalarAffineFunction, ScalarQuadraticFunction}) +constant(f::Union{VectorAffineFunction, VectorQuadraticFunction}) +constant(f::SingleVariable, ::DataType) +constant(f::VectorOfVariables, T::DataType) +``` + +## Sets + +```@docs +AbstractSet +AbstractScalarSet +AbstractVectorSet +``` + +### Utilities + +```@docs +dimension +dual_set +dual_set_type +constant(s::EqualTo) +supports_dimension_update +update_dimension +``` + +## Scalar sets + +List of recognized scalar sets. +```@docs +GreaterThan +LessThan +EqualTo +Interval +Integer +ZeroOne +Semicontinuous +Semiinteger +``` + +## Vector sets + +List of recognized vector sets. +```@docs +Reals +Zeros +Nonnegatives +Nonpositives +NormInfinityCone +NormOneCone +SecondOrderCone +RotatedSecondOrderCone +GeometricMeanCone +ExponentialCone +DualExponentialCone +PowerCone +DualPowerCone +RelativeEntropyCone +NormSpectralCone +NormNuclearCone +SOS1 +SOS2 +IndicatorSet +Complements +``` + +## Matrix sets + +Matrix sets are vectorized in order to be subtypes of +[`AbstractVectorSet`](@ref). For sets of symmetric matrices, storing both the +`(i, j)` and `(j, i)` elements is redundant so there exists the +[`AbstractSymmetricMatrixSetTriangle`](@ref) set to represent only the +vectorization of the upper triangular part of the matrix. When the matrix +of expressions constrained to be in the set is not symmetric and hence +the `(i, j)` and `(j, i)` elements should be constrained to be symmetric, +the [`AbstractSymmetricMatrixSetSquare`](@ref) set can be used. The +[`Bridges.Constraint.SquareBridge`](@ref) can transform a set from the square +form to the [`triangular_form`](@ref) by adding appropriate constraints if +the `(i, j)` and `(j, i)` expressions are different. + +```@docs +AbstractSymmetricMatrixSetTriangle +AbstractSymmetricMatrixSetSquare +side_dimension +triangular_form +``` + +List of recognized matrix sets. +```@docs +PositiveSemidefiniteConeTriangle +PositiveSemidefiniteConeSquare +LogDetConeTriangle +LogDetConeSquare +RootDetConeTriangle +RootDetConeSquare +``` diff --git a/docs/src/reference/variables.md b/docs/src/reference/variables.md new file mode 100644 index 0000000000..6e0d8a5bc9 --- /dev/null +++ b/docs/src/reference/variables.md @@ -0,0 +1,39 @@ +```@meta +CurrentModule = MathOptInterface +DocTestSetup = quote + using MathOptInterface + const MOI = MathOptInterface +end +DocTestFilters = [r"MathOptInterface|MOI"] +``` + +# Variables + +## Types + +```@docs +VariableIndex +``` + +## Functions + +```@docs +add_variable +add_variables +add_constrained_variable +add_constrained_variables +supports_add_constrained_variable +supports_add_constrained_variables +is_valid(::ModelLike,::VariableIndex) +delete(::ModelLike, ::VariableIndex) +delete(::ModelLike, ::Vector{VariableIndex}) +``` + +## Attributes + +```@docs +AbstractVariableAttribute +VariableName +VariablePrimalStart +VariablePrimal +```