Skip to content

Commit b051723

Browse files
committed
Large refactoring
* Rename types to remove Nonlinear prefix * Split NonlinearData into Model and Evaluator * Remove set_differentiation_backend
1 parent 1f8a28f commit b051723

File tree

8 files changed

+1018
-871
lines changed

8 files changed

+1018
-871
lines changed

docs/src/submodules/Nonlinear/overview.md

+109-55
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,18 @@ best dealt with by other components of MathOptInterface.
3636
## API overview
3737

3838
The core element of the `Nonlinear` submodule is
39-
[`Nonlinear.NonlinearData`](@ref):
39+
[`Nonlinear.Model`](@ref):
4040
```jldoctest nonlinear_developer
4141
julia> const Nonlinear = MathOptInterface.Nonlinear;
4242
43-
julia> data = Nonlinear.NonlinearData()
44-
NonlinearData with available features:
45-
* :ExprGraph
43+
julia> model = Nonlinear.Model()
44+
A Nonlinear.Model with:
45+
0 objectives
46+
0 parameters
47+
0 expressions
48+
0 constraints
4649
```
47-
[`Nonlinear.NonlinearData`](@ref) is a mutable struct that stores all of the
50+
[`Nonlinear.Model`](@ref) is a mutable struct that stores all of the
4851
nonlinear information added to the model.
4952

5053
### Decision variables
@@ -75,65 +78,126 @@ There are a number of restrictions on the input `Expr`:
7578
Given an input expression, add an expression using
7679
[`Nonlinear.add_expression`](@ref):
7780
```jldoctest nonlinear_developer
78-
julia> expr = Nonlinear.add_expression(data, input)
81+
julia> expr = Nonlinear.add_expression(model, input)
7982
MathOptInterface.Nonlinear.ExpressionIndex(1)
8083
```
8184
The return value, `expr`, is a [`Nonlinear.ExpressionIndex`](@ref) that can
8285
then be interpolated into other input expressions.
8386

87+
Looking again at `model`, we see:
88+
```jldoctest nonlinear_developer
89+
julia> model
90+
A Nonlinear.Model with:
91+
0 objectives
92+
0 parameters
93+
1 expression
94+
0 constraints
95+
```
96+
8497
### [Parameters](@id Nonlinear_Parameters)
8598

8699
In addition to constant literals like `1` or `1.23`, you can create parameters.
87100
Parameters are placeholders whose values can change before passing the
88101
expression to the solver. Create a parameter using
89102
[`Nonlinear.add_parameter`](@ref), which accepts a default value:
90103
```jldoctest nonlinear_developer
91-
julia> p = Nonlinear.add_parameter(data, 1.23)
104+
julia> p = Nonlinear.add_parameter(model, 1.23)
92105
MathOptInterface.Nonlinear.ParameterIndex(1)
93106
```
94107
The return value, `p`, is a [`Nonlinear.ParameterIndex`](@ref) that can then be
95108
interpolated into other input expressions.
96109

110+
Looking again at `model`, we see:
111+
```jldoctest nonlinear_developer
112+
julia> model
113+
A Nonlinear.Model with:
114+
0 objectives
115+
1 parameter
116+
1 expression
117+
0 constraints
118+
```
119+
97120
Update a parameter as follows:
98121
```jldoctest nonlinear_developer
99-
julia> data[p]
122+
julia> model[p]
100123
1.23
101124
102-
julia> data[p] = 4.56
125+
julia> model[p] = 4.56
103126
4.56
104127
105-
julia> data[p]
128+
julia> model[p]
106129
4.56
107130
```
108131

109132
### [Objectives](@id Nonlinear_Objectives)
110133

111134
Set a nonlinear objective using [`Nonlinear.set_objective`](@ref):
112135
```jldoctest nonlinear_developer
113-
julia> Nonlinear.set_objective(data, :($p + $expr + $x))
136+
julia> Nonlinear.set_objective(model, :($p + $expr + $x))
137+
138+
julia> model
139+
A Nonlinear.Model with:
140+
1 objective
141+
1 parameter
142+
1 expression
143+
0 constraints
114144
```
145+
115146
Clear a nonlinear objective by passing `nothing`:
116147
```jldoctest nonlinear_developer
117-
julia> Nonlinear.set_objective(data, nothing)
148+
julia> Nonlinear.set_objective(model, nothing)
149+
150+
julia> model
151+
A Nonlinear.Model with:
152+
0 objectives
153+
1 parameter
154+
1 expression
155+
0 constraints
156+
```
157+
158+
But we'll re-add the objective for later:
159+
```jldoctest nonlinear_developer
160+
julia> Nonlinear.set_objective(model, :($p + $expr + $x));
118161
```
119162

120163
### [Constraints](@id Nonlinear_Constraints)
121164

122165
Add a constraint using [`Nonlinear.add_constraint`](@ref):
123166
```jldoctest nonlinear_developer
124-
julia> c = Nonlinear.add_constraint(data, :(1 + sqrt($x) <= 2.0))
167+
julia> c = Nonlinear.add_constraint(model, :(1 + sqrt($x) <= 2.0))
125168
MathOptInterface.Nonlinear.ConstraintIndex(1)
169+
170+
julia> model
171+
A Nonlinear.Model with:
172+
1 objective
173+
1 parameter
174+
1 expression
175+
1 constraint
126176
```
127177
The return value, `c`, is a [`Nonlinear.ConstraintIndex`](@ref) that is a unique
128178
identifier for the constraint. Interval constraints are also supported:
129179
```jldoctest nonlinear_developer
130-
julia> c2 = Nonlinear.add_constraint(data, :(-1.0 <= 1 + sqrt($x) <= 2.0))
180+
julia> c2 = Nonlinear.add_constraint(model, :(-1.0 <= 1 + sqrt($x) <= 2.0))
131181
MathOptInterface.Nonlinear.ConstraintIndex(2)
182+
183+
julia> model
184+
A Nonlinear.Model with:
185+
1 objective
186+
1 parameter
187+
1 expression
188+
2 constraints
132189
```
133190

134191
Delete a constraint using [`Nonlinear.delete`](@ref):
135192
```jldoctest nonlinear_developer
136-
julia> Nonlinear.delete(data, c2)
193+
julia> Nonlinear.delete(model, c2)
194+
195+
julia> model
196+
A Nonlinear.Model with:
197+
1 objective
198+
1 parameter
199+
1 expression
200+
1 constraint
137201
```
138202

139203
### User-defined operators
@@ -150,11 +214,11 @@ Register a univariate user-defined operator using
150214
julia> f(x) = 1 + sin(x)^2
151215
f (generic function with 1 method)
152216
153-
julia> Nonlinear.register_operator(data, :my_f, 1, f)
217+
julia> Nonlinear.register_operator(model, :my_f, 1, f)
154218
```
155219
Now, you can use `:my_f` in expressions:
156220
```jldoctest nonlinear_developer
157-
julia> new_expr = Nonlinear.add_expression(data, :(my_f($x + 1)))
221+
julia> new_expr = Nonlinear.add_expression(model, :(my_f($x + 1)))
158222
MathOptInterface.Nonlinear.ExpressionIndex(2)
159223
```
160224
By default, `Nonlinear` will compute first- and second-derivatives of the
@@ -164,14 +228,14 @@ which compute the respective derivative:
164228
julia> f′(x) = 2 * sin(x) * cos(x)
165229
f′ (generic function with 1 method)
166230
167-
julia> Nonlinear.register_operator(data, :my_f2, 1, f, f′)
231+
julia> Nonlinear.register_operator(model, :my_f2, 1, f, f′)
168232
```
169233
or
170234
```jldoctest nonlinear_developer
171235
julia> f′′(x) = 2 * (cos(x)^2 - sin(x)^2)
172236
f′′ (generic function with 1 method)
173237
174-
julia> Nonlinear.register_operator(data, :my_f3, 1, f, f′, f′′)
238+
julia> Nonlinear.register_operator(model, :my_f3, 1, f, f′, f′′)
175239
```
176240

177241
#### Multivariate operators
@@ -182,11 +246,11 @@ Register a multivariate user-defined operator using
182246
julia> g(x...) = x[1]^2 + x[1] * x[2] + x[2]^2
183247
g (generic function with 1 method)
184248
185-
julia> Nonlinear.register_operator(data, :my_g, 2, g)
249+
julia> Nonlinear.register_operator(model, :my_g, 2, g)
186250
```
187251
Now, you can use `:my_f` in expressions:
188252
```jldoctest nonlinear_developer
189-
julia> new_expr = Nonlinear.add_expression(data, :(my_g($x + 1, $x)))
253+
julia> new_expr = Nonlinear.add_expression(model, :(my_g($x + 1, $x)))
190254
MathOptInterface.Nonlinear.ExpressionIndex(3)
191255
```
192256
By default, `Nonlinear` will compute the gradient of the registered
@@ -200,7 +264,7 @@ julia> function ∇g(ret, x...)
200264
end
201265
∇g (generic function with 1 method)
202266
203-
julia> Nonlinear.register_operator(data, :my_g2, 2, g, ∇g)
267+
julia> Nonlinear.register_operator(model, :my_g2, 2, g, ∇g)
204268
```
205269

206270
### [MathOptInterface](@id Nonlinear_MOI_interface)
@@ -209,57 +273,47 @@ MathOptInterface communicates the nonlinear portion of an optimization problem
209273
to solvers using concrete subtypes of [`AbstractNLPEvaluator`](@ref), which
210274
implement the [Nonlinear programming](@ref) API.
211275

212-
[`Nonlinear.NonlinearData`](@ref) is a subtype of [`AbstractNLPEvaluator`](@ref),
213-
but the functions of the [Nonlinear programming](@ref) API that it implements
214-
depends upon the chosen [`Nonlinear.AbstractAutomaticDifferentiation`](@ref
215-
backend.
276+
Create an [`AbstractNLPEvaluator`](@ref) from [`Nonlinear.Model`](@ref) using
277+
[`Nonlinear.Evaluator`](@ref).
278+
279+
[`Nonlinear.Evaluator`](@ref) requires an
280+
[`Nonlinear.AbstractAutomaticDifferentiation`](@ref) backend and an ordered list
281+
of the variables that are included in the model.
216282

217283
There following backends are available to choose from within MOI, although other
218284
packages may add more options by sub-typing
219285
[`Nonlinear.AbstractAutomaticDifferentiation`](@ref):
220286
* [`Nonlinear.ExprGraphOnly`](@ref)
221287

222-
Set the differentiation backend using
223-
`Nonlinear.set_differentiation_backend`](@ref).
224-
225-
If we set [`Nonlinear.ExprGraphOnly`](@ref), then we get access to `:ExprGraph`:
226288
```jldoctest nonlinear_developer
227-
julia> Nonlinear.set_differentiation_backend(
228-
data,
229-
Nonlinear.ExprGraphOnly(),
230-
[x],
231-
)
232-
233-
julia> data
234-
NonlinearData with available features:
289+
julia> evaluator = Nonlinear.Evaluator(model, Nonlinear.ExprGraphOnly(), [x])
290+
Nonlinear.Evaluator with available features:
235291
* :ExprGraph
236292
```
237-
238-
[`Nonlinear.set_differentiation_backend`](@ref) requires an ordered list of the
239-
variables that are included in the model. This order corresponds to the order of
240-
the primal decision vector `x` which is passed to the various functions in MOI's
241-
nonlinear API.
293+
The functions of the [Nonlinear programming](@ref) API implemented by
294+
[`Nonlinear.Evaluator`](@ref) depends upon the chosen
295+
[`Nonlinear.AbstractAutomaticDifferentiation`](@ref backend.
242296

243297
The `:ExprGraph` feature means we can call [`objective_expr`](@ref) and
244298
[`constraint_expr`](@ref) to retrieve the expression graph of the problem.
245299
However, we cannot call gradient terms such as
246300
[`eval_objective_gradient`](@ref) because [`Nonlinear.ExprGraphOnly`](@ref) does
247301
not have the capability to differentiate a nonlinear expression.
248302

249-
Instead of passing [`AbstractNLPEvaluator`](@ref)s directly to solvers,
303+
Instead of passing [`Nonlinear.Evaluator`](@ref) directly to solvers,
250304
MathOptInterface instead passes an [`NLPBlockData`](@ref), which wraps an
251-
[`AbstractNLPEvaluator`](@ref) and includes other information such as constraint
305+
[`Nonlinear.Evaluator`](@ref) and includes other information such as constraint
252306
bounds and whether the evaluator has a nonlinear objective. Create an
253-
`NLPBlockData`](@ref) as follows:
307+
[`NLPBlockData`](@ref) as follows:
254308
```jldoctest nonlinear_developer
255-
julia> MOI.NLPBlockData(data);
309+
julia> MOI.NLPBlockData(evaluator);
256310
```
257311

258312
## Expression-graph representation
259313

260-
[`Nonlinear.NonlinearData`](@ref) stores nonlinear expressions in
261-
[`Nonlinear.NonlinearExpression`](@ref)s. This section explains the design of
262-
the expression graph datastructure in [`Nonlinear.NonlinearExpression`](@ref).
314+
[`Nonlinear.Model`](@ref) stores nonlinear expressions in
315+
[`Nonlinear.Expression`](@ref)s. This section explains the design of
316+
the expression graph datastructure in [`Nonlinear.Expression`](@ref).
263317

264318
Given a nonlinear function like `f(x) = sin(x)^2 + x`, a conceptual aid for
265319
thinking about the graph representation of the expression is to convert it into
@@ -350,7 +404,7 @@ julia> struct Node
350404
index::Int
351405
end
352406
353-
julia> struct NonlinearExpression
407+
julia> struct Expression
354408
nodes::Vector{Node}
355409
values::Vector{Float64}
356410
end
@@ -368,7 +422,7 @@ The `.parent` field of each node is the integer index of the parent node in
368422

369423
Therefore, we can represent our function as:
370424
```jldoctest expr_graph
371-
julia> expr = NonlinearExpression(
425+
julia> expr = Expression(
372426
[
373427
Node(NODE_CALL_MULTIVARIATE, 1, -1),
374428
Node(NODE_CALL_MULTIVARIATE, 2, 1),
@@ -399,8 +453,8 @@ evaluates all children nodes before their parent.
399453

400454
### The design in practice
401455

402-
In practice, `Node` and `NonlinearExpression` are exactly [`Nonlinear.Node`](@ref)
403-
and [`Nonlinear.NonlinearExpression`](@ref). However, [`Nonlinear.NodeType`](@ref)
456+
In practice, `Node` and `Expression` are exactly [`Nonlinear.Node`](@ref)
457+
and [`Nonlinear.Expression`](@ref). However, [`Nonlinear.NodeType`](@ref)
404458
has more fields to account for comparison operators such as `:>=` and `:<=`,
405459
logic operators such as `:&&` and `:||`, nonlinear parameters, and nested
406460
subexpressions.
@@ -412,6 +466,6 @@ operators and a vector of comparison operators. In addition to
412466
[`Nonlinear.DEFAULT_MULTIVARIATE_OPERATORS`](@ref), you can register
413467
user-defined functions using [`Nonlinear.register_operator`](@ref).
414468

415-
[`Nonlinear.NonlinearData`](@ref) is a struct that stores the
469+
[`Nonlinear.Model`](@ref) is a struct that stores the
416470
[`Nonlinear.OperatorRegistry`](@ref), as well as a list of parameters and
417471
subexpressions in the model.

docs/src/submodules/Nonlinear/reference.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ More information can be found in the [Nonlinear](@ref nonlinear_developers)
1313
section of the manual.
1414

1515
```@docs
16-
Nonlinear.NonlinearData
16+
Nonlinear.Model
1717
```
1818

1919
## [Expressions](@id nonlinear_api_expressions)
@@ -66,18 +66,18 @@ Nonlinear.eval_comparison_function
6666
## Automatic-differentiation backends
6767

6868
```@docs
69+
Nonlinear.Evaluator
6970
Nonlinear.AbstractAutomaticDifferentiation
7071
Nonlinear.ExprGraphOnly
71-
Nonlinear.set_differentiation_backend
7272
```
7373

7474
## Data-structure
7575

7676
```@docs
7777
Nonlinear.Node
7878
Nonlinear.NodeType
79-
Nonlinear.NonlinearExpression
80-
Nonlinear.NonlinearConstraint
79+
Nonlinear.Expression
80+
Nonlinear.Constraint
8181
Nonlinear.adjacency_matrix
8282
Nonlinear.parse_expression
8383
Nonlinear.convert_to_expr

0 commit comments

Comments
 (0)