Skip to content

Commit af731bf

Browse files
authored
[docs] make the explanation a separate page (#217)
1 parent 0032eb7 commit af731bf

3 files changed

Lines changed: 185 additions & 178 deletions

File tree

docs/make.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Documenter.makedocs(;
1717
),
1818
sitename = "ParametricOptInterface.jl",
1919
authors = "Tomás Gutierrez, and contributors",
20-
pages = ["Home" => "index.md", "reference.md"],
20+
pages = ["Home" => "index.md", "background.md", "reference.md"],
2121
checkdocs = :none,
2222
)
2323

docs/src/background.md

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
# How and why ParametricOptInterface is needed
2+
3+
JuMP and MathOptInterface have support for _parameters_. Parameters are decision
4+
variables that belong to the `Parameter` set. The `Parameter` set is
5+
conceptually similar to the `EqualTo` set, except that solvers may treat a
6+
decision variable constrained to the `Parameter` set as a constant, and they
7+
do not need to add it as a decision variable to the model.
8+
9+
In JuMP, a parameter can be added using the following syntax:
10+
```@repl
11+
using JuMP
12+
model = Model();
13+
@variable(model, p in Parameter(2))
14+
parameter_value(p)
15+
set_parameter_value(p, 3.0)
16+
parameter_value(p)
17+
```
18+
19+
In MathOptInterface, a parameter can be added using the following syntax:
20+
```@repl
21+
import MathOptInterface as MOI
22+
model = MOI.Utilities.Model{Float64}();
23+
p, p_con = MOI.add_constrained_variable(model, MOI.Parameter(2.0))
24+
MOI.get(model, MOI.ConstraintSet(), p_con)
25+
new_set = MOI.Parameter(3.0)
26+
MOI.set(model, MOI.ConstraintSet(), p_con, new_set)
27+
MOI.get(model, MOI.ConstraintSet(), p_con)
28+
```
29+
30+
## Some solvers have native support for parameters
31+
32+
Some solvers have native support for parameters. One example is Ipopt. To
33+
demonstrate, look at the following example. Even though there are two
34+
`@variable` calls, the log of Ipopt shows that it solved a problem with only one
35+
decision variable:
36+
```@repl
37+
using JuMP, Ipopt
38+
model = Model(Ipopt.Optimizer)
39+
@variable(model, x)
40+
@variable(model, p in Parameter(1))
41+
@constraint(model, x + p >= 3)
42+
@objective(model, Min, 2x)
43+
optimize!(model)
44+
```
45+
Internally, Ipopt replaced the parameter `p` with the constant `1.0`, and solved
46+
the problem:
47+
```@repl
48+
using JuMP, Ipopt
49+
model = Model(Ipopt.Optimizer)
50+
@variable(model, x)
51+
@constraint(model, x + 1 >= 3)
52+
@objective(model, Min, 2x)
53+
optimize!(model)
54+
```
55+
56+
## Why parameters are useful
57+
58+
Parameters are most useful when you want to solve a sequence of problems in
59+
which some of the data changes between iterations:
60+
```@repl
61+
using JuMP, Ipopt
62+
model = Model(Ipopt.Optimizer)
63+
set_silent(model)
64+
@variable(model, x)
65+
@variable(model, p in Parameter(1))
66+
@constraint(model, x + p >= 3)
67+
@objective(model, Min, 2x)
68+
solution = Dict{Int,Float64}()
69+
for p_value in 0:5
70+
set_parameter_value(p, p_value)
71+
optimize!(model)
72+
assert_is_solved_and_feasible(model)
73+
solution[p_value] = value(x)
74+
end
75+
solution
76+
```
77+
78+
## Some solvers do not have native support for parameters
79+
80+
Even though solvers like Ipopt support parameters, many solvers do not. One
81+
example is HiGHS. Despite the fact that HiGHS doesn't support parameters, you
82+
can still build and solve a model with parameters:
83+
```@repl index_highs
84+
using JuMP, HiGHS
85+
model = Model(HiGHS.Optimizer)
86+
@variable(model, x)
87+
@variable(model, p in Parameter(1))
88+
@constraint(model, x + p >= 3)
89+
@objective(model, Min, 2x)
90+
optimize!(model)
91+
```
92+
This works because, behind the scenes, the bridges in MathOptInterface rewrote
93+
`p in Parameter(1)` to `p in MOI.EqualTo(1.0)`:
94+
```@repl index_highs
95+
print_active_bridges(model)
96+
```
97+
Thus, HiGHS solved the problem:
98+
```@repl
99+
using JuMP, HiGHS
100+
model = Model(HiGHS.Optimizer)
101+
@variable(model, x)
102+
@variable(model, p == 1)
103+
@constraint(model, x + p >= 3)
104+
@objective(model, Min, 2x)
105+
optimize!(model)
106+
```
107+
108+
The downside to the bridge approach is that it adds a new decision variable with
109+
fixed bounds for every parameter in the problem. Moreover, the bridge approach
110+
does not handle `parameter * variable` terms, because the resulting problem is a
111+
quadratic constraint:
112+
113+
```jldoctest
114+
julia> using JuMP, HiGHS
115+
116+
julia> model = Model(HiGHS.Optimizer);
117+
118+
julia> @variable(model, x);
119+
120+
julia> @variable(model, p in Parameter(1));
121+
122+
julia> @constraint(model, p * x >= 3)
123+
ERROR: Constraints of type MathOptInterface.ScalarQuadraticFunction{Float64}-in-MathOptInterface.GreaterThan{Float64} are not supported by the solver.
124+
125+
If you expected the solver to support your problem, you may have an error in your formulation. Otherwise, consider using a different solver.
126+
127+
The list of available solvers, along with the problem types they support, is available at https://jump.dev/JuMP.jl/stable/installation/#Supported-solvers.
128+
Stacktrace:
129+
[...]
130+
```
131+
132+
## ParametricOptInterface
133+
134+
ParametricOptInterface provides [`Optimizer`](@ref), which is a meta-optimizer
135+
that wraps another optimizer. Instead of adding fixed variables to the model,
136+
POI substitutes out the parameters with their value before passing the
137+
constraint or objective to the inner optimizer. When the parameter value is
138+
changed, POI efficiently modifies the inner optimizer to reflect the new
139+
parameter values.
140+
141+
```@repl
142+
using JuMP, HiGHS
143+
import ParametricOptInterface as POI
144+
model = Model(() -> POI.Optimizer(HiGHS.Optimizer()));
145+
@variable(model, x);
146+
@variable(model, p in Parameter(1));
147+
@constraint(model, x + p >= 3);
148+
@objective(model, Min, 2x);
149+
optimize!(model)
150+
```
151+
Note how HiGHS now solves a problem with one decision variable.
152+
153+
Because POI replaces parameters with their constant value, POI supports
154+
`parameter * variable` terms:
155+
```@repl
156+
using JuMP, HiGHS
157+
import ParametricOptInterface as POI
158+
model = Model(() -> POI.Optimizer(HiGHS.Optimizer()));
159+
@variable(model, x);
160+
@variable(model, p in Parameter(1));
161+
@constraint(model, p * x >= 3)
162+
@objective(model, Min, 2x)
163+
optimize!(model)
164+
```
165+
166+
## When to use ParametricOptInterface
167+
168+
To summarize, you should use ParametricOptInterface when:
169+
170+
* you are using a solver that does not have native support for parameters
171+
* you are solving a single problem for multiple values of the parameters.
172+
173+
For problems with a small number of parameters, and in which the parameters
174+
appear additively in the constraints and the objective, it may be more efficient
175+
to use the bridge approach. In general, you should try with and without POI and
176+
choose the approach which works best for your model.

docs/src/index.md

Lines changed: 8 additions & 177 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# ParametricOptInterface.jl
22

33
[ParametricOptInterface.jl](https://github.com/jump-dev/ParametricOptInterface.jl)
4-
is a package that adds parameters to models in JuMP and MathOptInterface.
4+
is a package for managing parameters in JuMP and MathOptInterface.
55

66
## License
77

@@ -24,7 +24,7 @@ Use ParametricOptInterface with JuMP by following this brief example:
2424
```@repl
2525
using JuMP, HiGHS
2626
import ParametricOptInterface as POI
27-
model = Model(() -> POI.Optimizer(HiGHS.Optimizer()))
27+
model = Model(() -> POI.Optimizer(HiGHS.Optimizer))
2828
@variable(model, x)
2929
@variable(model, p in Parameter(1))
3030
@constraint(model, p * x + p >= 3)
@@ -36,181 +36,6 @@ optimize!(model)
3636
value(x)
3737
```
3838

39-
## How and why ParametricOptInterface is needed
40-
41-
JuMP and MathOptInterface have support for _parameters_. Parameters are decision
42-
variables that belong to the `Parameter` set. The `Parameter` set is
43-
conceptually similar to the `EqualTo` set, except that solvers may treat a
44-
decision variable constrained to the `Parameter` set as a constant, and they
45-
need not add it as a decision variable to the model.
46-
47-
In JuMP, a parameter can be added using the following syntax:
48-
```@repl
49-
using JuMP
50-
model = Model();
51-
@variable(model, p in Parameter(2))
52-
parameter_value(p)
53-
set_parameter_value(p, 3.0)
54-
parameter_value(p)
55-
```
56-
57-
In MathOptInterface, a parameter can be added using the following syntax:
58-
```@repl
59-
import MathOptInterface as MOI
60-
model = MOI.Utilities.Model{Float64}();
61-
p, p_con = MOI.add_constrained_variable(model, MOI.Parameter(2.0))
62-
MOI.get(model, MOI.ConstraintSet(), p_con)
63-
new_set = MOI.Parameter(3.0)
64-
MOI.set(model, MOI.ConstraintSet(), p_con, new_set)
65-
MOI.get(model, MOI.ConstraintSet(), p_con)
66-
```
67-
68-
### Some solvers have native support for parameters
69-
70-
Some solvers have native support for parameters. example is Ipopt. To
71-
demonstrate, look at the following example. Even though there are two
72-
`@variable` calls, the log of Ipopt shows that it solved a problem with only one
73-
decision variable:
74-
```@repl
75-
using JuMP, Ipopt
76-
model = Model(Ipopt.Optimizer)
77-
@variable(model, x)
78-
@variable(model, p in Parameter(1))
79-
@constraint(model, x + p >= 3)
80-
@objective(model, Min, 2x)
81-
optimize!(model)
82-
```
83-
Internally, Ipopt replaced the parameter `p` with the constant `1.0`, and solved
84-
the problem:
85-
```@repl
86-
using JuMP, Ipopt
87-
model = Model(Ipopt.Optimizer)
88-
@variable(model, x)
89-
@constraint(model, x + 1 >= 3)
90-
@objective(model, Min, 2x)
91-
optimize!(model)
92-
```
93-
94-
Parameters are most useful when you want to solve a sequence of problems in
95-
which some of the data changes between iterations:
96-
```@repl
97-
using JuMP, Ipopt
98-
model = Model(Ipopt.Optimizer)
99-
set_silent(model)
100-
@variable(model, x)
101-
@variable(model, p in Parameter(1))
102-
@constraint(model, x + p >= 3)
103-
@objective(model, Min, 2x)
104-
solution = Dict{Int,Float64}()
105-
for p_value in 0:5
106-
set_parameter_value(p, p_value)
107-
optimize!(model)
108-
assert_is_solved_and_feasible(model)
109-
solution[p_value] = value(x)
110-
end
111-
solution
112-
```
113-
114-
### Some solvers do not have native support for parameters
115-
116-
Even though solvers like Ipopt support parameters, many solvers do not. One
117-
example is HiGHS. Despite the fact that HiGHS doesn't support parameters, you
118-
can still build and solve a model with parameters:
119-
```@repl index_highs
120-
using JuMP, HiGHS
121-
model = Model(HiGHS.Optimizer)
122-
@variable(model, x)
123-
@variable(model, p in Parameter(1))
124-
@constraint(model, x + p >= 3)
125-
@objective(model, Min, 2x)
126-
optimize!(model)
127-
```
128-
This works because, behind the scenes, the bridges in MathOptInterface rewrote
129-
`p in Parameter(1)` to `p in MOI.EqualTo(1.0)`:
130-
```@repl index_highs
131-
print_active_bridges(model)
132-
```
133-
Thus, HiGHS solved the problem:
134-
```@repl
135-
using JuMP, HiGHS
136-
model = Model(HiGHS.Optimizer)
137-
@variable(model, x)
138-
@variable(model, p == 1)
139-
@constraint(model, x + p >= 3)
140-
@objective(model, Min, 2x)
141-
optimize!(model)
142-
```
143-
144-
The downside to the bridge approach is that it adds a new decision variable with
145-
fixed bounds for every parameter in the problem. Moreover, the bridge approach
146-
does not handle `parameter * variable` terms, because the resulting problem is a
147-
quadratic constraint:
148-
149-
```jldoctest
150-
julia> using JuMP, HiGHS
151-
152-
julia> model = Model(HiGHS.Optimizer);
153-
154-
julia> @variable(model, x);
155-
156-
julia> @variable(model, p in Parameter(1));
157-
158-
julia> @constraint(model, p * x >= 3)
159-
ERROR: Constraints of type MathOptInterface.ScalarQuadraticFunction{Float64}-in-MathOptInterface.GreaterThan{Float64} are not supported by the solver.
160-
161-
If you expected the solver to support your problem, you may have an error in your formulation. Otherwise, consider using a different solver.
162-
163-
The list of available solvers, along with the problem types they support, is available at https://jump.dev/JuMP.jl/stable/installation/#Supported-solvers.
164-
Stacktrace:
165-
[...]
166-
```
167-
168-
### ParametricOptInterface
169-
170-
ParametricOptInterface provides [`Optimizer`](@ref), which is a meta-optimizer
171-
that wraps another optimizer. Instead of adding fixed variables to the model,
172-
POI substitutes out the parameters with their value before passing the
173-
constraint or objective to the inner optimizer. When the parameter value is
174-
changed, POI efficiently modifies the inner optimizer to reflect the new
175-
parameter values.
176-
177-
```@repl
178-
using JuMP, HiGHS
179-
import ParametricOptInterface as POI
180-
model = Model(() -> POI.Optimizer(HiGHS.Optimizer()));
181-
@variable(model, x);
182-
@variable(model, p in Parameter(1));
183-
@constraint(model, x + p >= 3);
184-
@objective(model, Min, 2x);
185-
optimize!(model)
186-
```
187-
Note how HiGHS now solves a problem with one decision variable.
188-
189-
Because POI replaces parameters with their constant value, POI supports
190-
`parameter * variable` terms:
191-
```@repl
192-
using JuMP, HiGHS
193-
import ParametricOptInterface as POI
194-
model = Model(() -> POI.Optimizer(HiGHS.Optimizer()));
195-
@variable(model, x);
196-
@variable(model, p in Parameter(1));
197-
@constraint(model, p * x >= 3)
198-
@objective(model, Min, 2x)
199-
optimize!(model)
200-
```
201-
202-
## When to use ParametricOptInterface
203-
204-
You should use ParametricOptInterface when:
205-
206-
* you are using a solver that does not have native support for parameters
207-
* you are solving a single problem for multiple values of the parameters.
208-
209-
For problems with a small number of parameters, and in which the parameters
210-
appear additively in the constraints and the objective, it may be more efficient
211-
to use the bridge approach. In general, you should try with and without POI and
212-
choose the approach which works best for your model.
213-
21439
## The dual of a parameter
21540

21641
In some applications you may need the dual of a parameter. The dual can be
@@ -243,6 +68,12 @@ optimize!(model)
24368
reduced_cost(p)
24469
```
24570

71+
Note that, even though ParametricOptInterface supports querying the dual of a
72+
parameter, this is not true in general. For example, Ipopt does not support
73+
querying the dual of a parameter. Moreover, the dual is available only if all of
74+
the parameters appear additively in the model; the dual is not available if
75+
there are multiplicative parameters.
76+
24677
## Variable bounds
24778

24879
An ambiguity arises when the user writes a model like:

0 commit comments

Comments
 (0)