Skip to content

Commit

Permalink
Switch Nonlinear API to JuMP.GenericNonlinearExpr (#308)
Browse files Browse the repository at this point in the history
* Update to use NonlinearExpr in src

* update optimizer_index for constraints

* Begin updates for docs and tests

* Update datatypes and tests

* Add registration tests

* Added more tests

* Reimplement all tests

* Update nlp types

* added comment

* Update package dependencies

* incorporate `JuMP.flatten`

* fix @rewrite

* Update w/ JuMP

* remove use of `MA.@rewrite`

* Update user defined functions

* Update registration tests

* `flatten` -> `flatten!`

* Update registration tests

* Prepare tests for CI

* fix syntax bug

* test fix

* minor fixes

* Minor doc fix

* minor fix

* Update to JuMP changes

* fix `build_measure`

* Minor fixes

* fix tests

* Update to JuMP's latest release

* Fix doctests

* Another doctest fix

* Fix header link

* Update for NonlinearOperator change (#321)

* test fix

* Add AST mapper

* Update dep test

* fix tests

* minor fixes

* minor test fix

* update to JuMP 1.15

---------

Co-authored-by: Oscar Dowson <[email protected]>
  • Loading branch information
pulsipher and odow authored Sep 15, 2023
1 parent d8f571a commit f0929c6
Show file tree
Hide file tree
Showing 35 changed files with 918 additions and 3,415 deletions.
11 changes: 3 additions & 8 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,28 @@ authors = ["Joshua Pulsipher and Weiqi Zhang"]
version = "0.5.8"

[deps]
AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
FastGaussQuadrature = "442a2c76-b920-505d-bb47-c5924d526838"
JuMP = "4076af6c-e467-56ae-b986-b466b2749572"
LeftChildRightSiblingTrees = "1d6d02ad-be62-4b6b-8a6d-2f90e265016e"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
MutableArithmetics = "d8a4904e-b15c-11e9-3269-09a3773c0cb0"
Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b"

[compat]
AbstractTrees = "0.4"
DataStructures = "0.14.2 - 0.18"
Distributions = "0.19 - 0.25"
FastGaussQuadrature = "0.3.2 - 0.4, 0.5"
JuMP = "1.2"
LeftChildRightSiblingTrees = "0.2"
JuMP = "1.5"
MutableArithmetics = "1"
Reexport = "0.2, 1"
SpecialFunctions = "0.8 - 0.10, 1, 2"
julia = "^1.6"

[extras]
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
Suppressor = "fd094767-a336-5f1f-9728-57cf17d0bbfb"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"

[targets]
test = ["Test", "Random", "Suppressor"]
test = ["Test", "Random", "Suppressor", "Pkg"]
9 changes: 5 additions & 4 deletions docs/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,16 @@ Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"

[compat]
HiGHS = "1"
Distributions = "0.25"
Documenter = "0.27"
InfiniteOpt = "0.5"
JuMP = "^1.11.1"
Ipopt = "1"
Ipopt = "1.4"
HiGHS = "1"
julia = "1.6"
JuMP = "1.15"
Literate = "2.14"
Plots = "1"
julia = "1.6"
SpecialFunctions = "2"
51 changes: 15 additions & 36 deletions docs/src/develop/extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -871,23 +871,19 @@ function _make_expression(
return _make_expression(opt_model, measure_function(expr))
end
# AffExpr/QuadExpr
function _make_expression(opt_model::Model, expr::Union{GenericAffExpr, GenericQuadExpr})
function _make_expression(opt_model::Model, expr::Union{GenericAffExpr, GenericQuadExpr, GenericNonlinearExpr})
return map_expression(v -> _make_expression(opt_model, v), expr)
end
# NLPExpr
function _make_expression(opt_model::Model, expr::NLPExpr)
return add_nonlinear_expression(opt_model, map_nlp_to_ast(v -> _make_expression(opt_model, v), expr))
end
# output
_make_expression (generic function with 8 methods)
_make_expression (generic function with 7 methods)
```
For simplicity in example, above we assume that only `DistributionDomain`s are
used, there are not any `PointVariableRef`s, and all `MeasureRef`s correspond to
expectations. Naturally, a full extension should include checks to enforce that
such assumptions hold. Notice that [`map_expression`](@ref) and
[`map_nlp_to_ast`](@ref) are useful for converting expressions.
such assumptions hold. Notice that [`map_expression`](@ref) is useful for
converting expressions.

Now let's extend [`build_optimizer_model!`](@ref) for `DeterministicModel`s.
Such extensions should build an optimizer model in place and in general should
Expand All @@ -908,13 +904,13 @@ function InfiniteOpt.build_optimizer_model!(
# clear the model for a build/rebuild
determ_model = InfiniteOpt.clear_optimizer_model_build!(model)
# add the registered functions if there are any
add_registered_to_jump(determ_model, model)
# add user-defined nonlinear operators if there are any
add_operators_to_jump(determ_model, model)
# add variables
for vref in all_variables(model)
if index(vref) isa InfiniteVariableIndex
start = NaN # easy hack
start = NaN # simple hack for sake of example
else
start = start_value(vref)
start = isnothing(start) ? NaN : start
Expand All @@ -932,29 +928,14 @@ function InfiniteOpt.build_optimizer_model!(
# add the objective
obj_func = _make_expression(determ_model, objective_function(model))
if obj_func isa NonlinearExpression
set_nonlinear_objective(determ_model, objective_sense(model), obj_func)
else
set_objective(determ_model, objective_sense(model), obj_func)
end
set_objective(determ_model, objective_sense(model), obj_func)
# add the constraints
for cref in all_constraints(model, Union{GenericAffExpr, GenericQuadExpr, NLPExpr})
for cref in all_constraints(model, Union{GenericAffExpr, GenericQuadExpr, GenericNonlinearExpr})
constr = constraint_object(cref)
new_func = _make_expression(determ_model, constr.func)
if new_func isa NonlinearExpression
if constr.set isa MOI.LessThan
ex = :($new_func <= $(constr.set.upper))
elseif constr.set isa MOI.GreaterThan
ex = :($new_func >= $(constr.set.lower))
else # assume it is MOI.EqualTo
ex = :($new_func == $(constr.set.value))
end
new_cref = add_nonlinear_constraint(determ_model, ex)
else
new_constr = build_constraint(error, new_func, constr.set)
new_cref = add_constraint(determ_model, new_constr, name(cref))
end
new_constr = build_constraint(error, new_func, constr.set)
new_cref = add_constraint(determ_model, new_constr, name(cref))
deterministic_data(determ_model).infconstr_to_detconstr[cref] = new_cref
end
Expand All @@ -975,13 +956,11 @@ print(optimizer_model(model))
# output
Min z + y[1] + y[2]
Subject to
2 y[1] - z ≤ 42.0
sin(z) - -1.0 ≥ 0
2 y[1] - z ≤ 42
y[2]² = 1.5
y[1] ≥ 0.0
y[2] ≥ 0.0
subexpression[1] - 0.0 ≥ 0
With NL expressions
subexpression[1]: sin(z) - -1.0
y[1] ≥ 0
y[2] ≥ 0
```
Note that better variable naming could be used with the reformulated infinite
variables. Moreover, in general extensions of [`build_optimizer_model!`](@ref)
Expand Down
4 changes: 2 additions & 2 deletions docs/src/guide/derivative.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ julia> d3 = @∂(q, t^2)
∂/∂t[∂/∂t[q(t)]]
julia> d_expr = @deriv(y * q - 2t, t)
∂/∂t[y(t, ξ)]*q(t) + ∂/∂t[q(t)]*y(t, ξ) - 2
∂/∂t[y(t, ξ)]*q(t) + y(t, ξ)*∂/∂t[q(t)] - 2
```
Thus, we can define derivatives in a variety of forms according to the problem at
hand. The last example even shows how the product rule is correctly applied.
Expand Down Expand Up @@ -216,7 +216,7 @@ defined up above with its alias name `dydt2`. This macro can also tackle complex
expressions using the appropriate calculus such as:
```jldoctest deriv_basic
julia> @deriv(∫(y, ξ) * q, t)
∂/∂t[∫{ξ ∈ [-1, 1]}[y(t, ξ)]]*q(t) + ∂/∂t[q(t)]*∫{ξ ∈ [-1, 1]}[y(t, ξ)]
∂/∂t[∫{ξ ∈ [-1, 1]}[y(t, ξ)]]*q(t) + ∫{ξ ∈ [-1, 1]}[y(t, ξ)]*∂/∂t[q(t)]
```
Thus, demonstrating the convenience of using `@deriv`.

Expand Down
Loading

0 comments on commit f0929c6

Please sign in to comment.