Skip to content

Commit e314197

Browse files
authored
Merge pull request #1799 from ValentinKaisermayer/vk-ineq-support
Adds support for inequalities
2 parents 01f1412 + 42eec2b commit e314197

File tree

9 files changed

+652
-219
lines changed

9 files changed

+652
-219
lines changed

docs/Project.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@ BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
33
DifferentialEquations = "0c46a032-eb83-5123-abaf-570d42b7fbaa"
44
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
55
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
6-
Optimization = "7f7a1694-90dd-40f0-9382-eb1efda571ba"
76
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
87
ModelingToolkit = "961ee093-0014-501f-94e3-6117800e7a78"
98
NonlinearSolve = "8913a72c-1f9b-4ce2-8d82-65094dcecaec"
109
Optim = "429524aa-4258-5aef-a3af-852621145aeb"
10+
Optimization = "7f7a1694-90dd-40f0-9382-eb1efda571ba"
11+
OptimizationOptimJL = "36348300-93cb-4f02-beb5-3c3902f8871e"
1112
OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed"
1213
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
1314
Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7"

docs/src/systems/OptimizationSystem.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ OptimizationSystem
88

99
## Composition and Accessor Functions
1010

11-
- `get_eqs(sys)` or `equations(sys)`: The equation to be minimized.
11+
- `get_op(sys)` or `objective(sys)`: The objective to be minimized.
1212
- `get_states(sys)` or `states(sys)`: The set of states for the optimization.
1313
- `get_ps(sys)` or `parameters(sys)`: The parameters for the optimization.
14+
- `get_constraints(sys)` or `constraints(sys)`: The constraints for the optimization.
1415

1516
## Transformations
1617

docs/src/tutorials/optimization.md

Lines changed: 70 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,85 @@
11
# Modeling Optimization Problems
22

3-
```julia
4-
using ModelingToolkit, Optimization, OptimizationOptimJL
3+
## Rosenbrock Function in 2D
4+
Let's solve the classical _Rosenbrock function_ in two dimensions.
55

6-
@variables x y
7-
@parameters a b
6+
First, we need to make some imports.
7+
```@example rosenbrock_2d
8+
using ModelingToolkit, Optimization, OptimizationOptimJL
9+
```
10+
Now we can define our optimization problem.
11+
```@example rosenbrock_2d
12+
@variables begin
13+
x, [bounds = (-2.0, 2.0)]
14+
y, [bounds = (-1.0, 3.0)]
15+
end
16+
@parameters a = 1 b = 1
817
loss = (a - x)^2 + b * (y - x^2)^2
9-
@named sys = OptimizationSystem(loss,[x,y],[a,b])
18+
@named sys = OptimizationSystem(loss, [x, y], [a, b])
19+
```
1020

21+
A visualization of the objective function is depicted below.
22+
```@eval
23+
using Plots
24+
x = -2:0.01:2
25+
y = -1:0.01:3
26+
contour(x, y, (x,y) -> (1 - x)^2 + 100 * (y - x^2)^2, fill=true, color=:viridis, ratio=:equal, xlims=(-2, 2))
27+
```
28+
29+
### Explanation
30+
Every optimization problem consists of a set of _optimization variables_. In this case we create two variables. Additionally we assign _box constraints_ for each of them. In the next step we create two parameters for the problem with `@parameters`. While it is not needed to do this it makes it easier to `remake` the problem later with different values for the parameters. The _objective function_ is specified as well and finally everything is used to construct an `OptimizationSystem`.
31+
32+
## Building and Solving the Optimization Problem
33+
Next the actual `OptimizationProblem` can be created. At this stage an initial guess `u0` for the optimization variables needs to be provided via map, using the symbols from before. Concrete values for the parameters of the system can also be provided or changed. However, if the parameters have default values assigned they are used automatically.
34+
```@example rosenbrock_2d
1135
u0 = [
12-
x=>1.0
13-
y=>2.0
36+
x => 1.0
37+
y => 2.0
1438
]
1539
p = [
16-
a => 6.0
17-
b => 7.0
40+
a => 1.0
41+
b => 100.0
42+
]
43+
44+
prob = OptimizationProblem(sys, u0, p, grad=true, hess=true)
45+
solve(prob, GradientDescent())
46+
```
47+
48+
## Rosenbrock Function with Constraints
49+
```@example rosenbrock_2d_cstr
50+
using ModelingToolkit, Optimization, OptimizationOptimJL
51+
52+
@variables begin
53+
x, [bounds = (-2.0, 2.0)]
54+
y, [bounds = (-1.0, 3.0)]
55+
end
56+
@parameters a = 1 b = 100
57+
loss = (a - x)^2 + b * (y - x^2)^2
58+
cons = [
59+
x^2 + y^2 ≲ 1,
1860
]
61+
@named sys = OptimizationSystem(loss, [x, y], [a, b], constraints = cons)
62+
u0 = [
63+
x => 1.0
64+
y => 2.0
65+
]
66+
prob = OptimizationProblem(sys, u0, grad=true, hess=true)
67+
solve(prob, IPNewton())
68+
```
1969

20-
prob = OptimizationProblem(sys,u0,p,grad=true,hess=true)
21-
solve(prob,Newton())
70+
A visualization of the objective function and the inequality constraint is depicted below.
71+
```@eval
72+
using Plots
73+
x = -2:0.01:2
74+
y = -1:0.01:3
75+
contour(x, y, (x,y) -> (1 - x)^2 + 100 * (y - x^2)^2, fill=true, color=:viridis, ratio=:equal, xlims=(-2, 2))
76+
contour!(x, y, (x, y) -> x^2 + y^2, levels=[1], color=:lightblue, line=4)
2277
```
2378

79+
### Explanation
80+
Equality and inequality constraints can be added to the `OptimizationSystem`. An equality constraint can be specified via and `Equation`, e.g., `x^2 + y^2 ~ 1`. While inequality constraints via an `Inequality`, e.g., `x^2 + y^2 ≲ 1`. The syntax is here `\lesssim` and `\gtrsim`.
81+
82+
## Nested Systems
2483
Needs more text but it's super cool and auto-parallelizes and sparsifies too.
2584
Plus you can hierarchically nest systems to have it generate huge
2685
optimization problems.

src/ModelingToolkit.jl

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,15 @@ import Graphs: SimpleDiGraph, add_edge!, incidence_matrix
6767
for fun in [:toexpr]
6868
@eval begin
6969
function $fun(eq::Equation; kw...)
70-
Expr(:(=), $fun(eq.lhs; kw...), $fun(eq.rhs; kw...))
70+
Expr(:call, :(==), $fun(eq.lhs; kw...), $fun(eq.rhs; kw...))
71+
end
72+
73+
function $fun(ineq::Inequality; kw...)
74+
if ineq.relational_op == Symbolics.leq
75+
Expr(:call, :(<=), $fun(ineq.lhs; kw...), $fun(ineq.rhs; kw...))
76+
else
77+
Expr(:call, :(>=), $fun(ineq.lhs; kw...), $fun(ineq.rhs; kw...))
78+
end
7179
end
7280

7381
$fun(eqs::AbstractArray; kw...) = map(eq -> $fun(eq; kw...), eqs)
@@ -86,6 +94,7 @@ abstract type AbstractTimeDependentSystem <: AbstractSystem end
8694
abstract type AbstractTimeIndependentSystem <: AbstractSystem end
8795
abstract type AbstractODESystem <: AbstractTimeDependentSystem end
8896
abstract type AbstractMultivariateSystem <: AbstractSystem end
97+
abstract type AbstractOptimizationSystem <: AbstractTimeIndependentSystem end
8998

9099
"""
91100
$(TYPEDSIGNATURES)
@@ -139,6 +148,7 @@ include("systems/jumps/jumpsystem.jl")
139148
include("systems/nonlinear/nonlinearsystem.jl")
140149
include("systems/nonlinear/modelingtoolkitize.jl")
141150

151+
include("systems/optimization/constraints_system.jl")
142152
include("systems/optimization/optimizationsystem.jl")
143153

144154
include("systems/pde/pdesystem.jl")
@@ -179,7 +189,7 @@ export OptimizationProblem, OptimizationProblemExpr, constraints
179189
export AutoModelingToolkit
180190
export SteadyStateProblem, SteadyStateProblemExpr
181191
export JumpProblem, DiscreteProblem
182-
export NonlinearSystem, OptimizationSystem
192+
export NonlinearSystem, OptimizationSystem, ConstraintsSystem
183193
export alias_elimination, flatten
184194
export connect, @connector, Connection, Flow, Stream, instream
185195
export isinput, isoutput, getbounds, hasbounds, isdisturbance, istunable, getdist, hasdist,
@@ -192,7 +202,7 @@ export Equation, ConstrainedEquation
192202
export Term, Sym
193203
export SymScope, LocalScope, ParentScope, GlobalScope
194204
export independent_variables, independent_variable, states, parameters, equations, controls,
195-
observed, structure, full_equations
205+
observed, structure, full_equations, objective
196206
export structural_simplify, expand_connections, linearize, linearization_function
197207
export DiscreteSystem, DiscreteProblem
198208

src/constants.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,15 @@ macro constants(xs...)
3232
xs,
3333
toconstant) |> esc
3434
end
35+
36+
"""
37+
Substitute all `@constants` in the given expression
38+
"""
39+
function subs_constants(eqs)
40+
consts = collect_constants(eqs)
41+
if !isempty(consts)
42+
csubs = Dict(c => getdefault(c) for c in consts)
43+
eqs = substitute(eqs, csubs)
44+
end
45+
return eqs
46+
end

0 commit comments

Comments
 (0)