Skip to content

Commit 008ed71

Browse files
authored
[docs] clarify that new sets must not contain references to variables (#2901)
1 parent e9ea5c5 commit 008ed71

File tree

4 files changed

+93
-4
lines changed

4 files changed

+93
-4
lines changed

docs/make.jl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,11 @@ const _PAGES = [
8383
"API Reference" => "submodules/Test/reference.md",
8484
],
8585
],
86-
"Developer Docs" =>
87-
["developer/checklists.md", "developer/contributing.md"],
86+
"Developer Docs" => [
87+
"developer/checklists.md",
88+
"developer/contributing.md",
89+
"developer/defining_a_new_set.md",
90+
],
8891
"Release notes" => "release_notes.md",
8992
]
9093

docs/src/developer/checklists.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ Use this checklist when adding a new set to the MathOptInterface repository.
4242
- [ ] If `isbitstype(S) == false`, implement `Base.:(==)(x::S, y::S)`
4343
- [ ] If an `AbstractVectorSet`, implement `dimension(set::S)`, unless the
4444
dimension is given by `set.dimension`.
45+
- [ ] Ensure the set does not contain references to any variables or constraints
4546
4647
## Utilities
4748
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
```@meta
2+
CurrentModule = MathOptInterface
3+
DocTestSetup = quote
4+
import MathOptInterface as MOI
5+
end
6+
DocTestFilters = [r"MathOptInterface|MOI"]
7+
```
8+
9+
# Defining a new set
10+
11+
The easiest way to extend the behavior of MathOptInterface is to design a new
12+
set. The purpose of this tutorial is to explain how to define a new set and some
13+
of the associated nuances.
14+
15+
Defining a new function is an order of magnitude (if not two) harder than
16+
defining a new set. Don't consider it as an option unless you have already tried
17+
to support your behavior as a set.
18+
19+
As a motivation for this tutorial, we consider the _LinMax_ constraint type,
20+
which appears often in constraint programming:
21+
```math
22+
t = \max(f_1(x), f_2(x), \ldots, f_N(x))
23+
```
24+
25+
The first step to design a new set for MathOptInterface is to define the
26+
mathematical relationship you want to model as a _function-in-set_ $f(x) \in S$.
27+
28+
Your initial thought for representing the _LinMax_ constraint in MathOptInterface
29+
may be to represent it as:
30+
```math
31+
F(x) \in LinMax(t)
32+
```
33+
where $F(x)$ is the vector-valued function created by concatenating the $f_i$
34+
functions. This formulation violates a basic rule of MathOptInterface:
35+
36+
!!! rule
37+
Sets cannot contain references to decision variables or other constraints.
38+
39+
Instead, we could model the _LinMax_ constraint as:
40+
```math
41+
[t, f_1(x), f_2(x), \ldots, f_N(x)] \in LinMax(N+1)
42+
```
43+
44+
In the language of MathOptInterface, this is a [`AbstractVectorFunction`](@ref)
45+
in the `LinMax` set of dimension $N+1$. The type of the function depends on the
46+
types of the component scalar functions, with a special convention that the
47+
first element in the function is interpretable as a [`VariableIndex`](@ref)
48+
`t`.
49+
50+
Now `LinMax` can be trivially defined as a new [`AbstractVectorSet`](@ref):
51+
```jldoctest define_new_set
52+
julia> import MathOptInterface as MOI
53+
54+
julia> struct LinMax <: MOI.AbstractVectorSet
55+
dimension::Int
56+
end
57+
```
58+
and it can immediately be used in MathOptInterface:
59+
```jldoctest define_new_set
60+
julia> model = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}());
61+
62+
julia> t = MOI.VariableIndex(1);
63+
64+
julia> x = MOI.VariableIndex.(2:3);
65+
66+
julia> F = 1.0 .* x .+ 2.0;
67+
68+
julia> g = MOI.Utilities.operate(vcat, Float64, t, F...);
69+
70+
julia> MOI.add_constraint(model, g, LinMax(3))
71+
MathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64}, LinMax}(1)
72+
73+
julia> print(model)
74+
Feasibility
75+
76+
Subject to:
77+
78+
VectorAffineFunction{Float64}-in-LinMax
79+
┌ ┐
80+
│0.0 + 1.0 v[1]│
81+
│2.0 + 1.0 v[2]│
82+
│2.0 + 1.0 v[3]│
83+
└ ┘ ∈ LinMax(3)
84+
```

docs/src/manual/standard_form.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ where:
2222
* the sets ``\mathcal{S}_1, \ldots, \mathcal{S}_m`` are specified by
2323
[`AbstractSet`](@ref) objects
2424

25+
An important design consideration is that the sets are independent of the
26+
decision variables.
27+
2528
!!! tip
2629
For more information on this standard form, read [our paper](https://arxiv.org/abs/2002.03447).
2730

@@ -43,8 +46,6 @@ The function types implemented in MathOptInterface.jl are:
4346
| [`VectorQuadraticFunction`](@ref) | A vector of scalar-valued quadratic functions. |
4447
| [`VectorNonlinearFunction`](@ref) | ``f(x)``, where ``f`` is a vector-valued nonlinear function. |
4548

46-
Extensions for nonlinear programming are present but not yet well documented.
47-
4849
## One-dimensional sets
4950

5051
The one-dimensional set types implemented in MathOptInterface.jl are:

0 commit comments

Comments
 (0)