Skip to content

Commit 57dcc7e

Browse files
Merge pull request #3140 from AayushSabharwal/as/optsys-fixes
fix: respect bounds in `modelingtoolkitize`, make bounded variable irreducible
2 parents b7c9316 + 2a3e023 commit 57dcc7e

File tree

5 files changed

+46
-2
lines changed

5 files changed

+46
-2
lines changed

src/systems/optimization/modelingtoolkitize.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,15 @@ function modelingtoolkitize(prob::DiffEqBase.OptimizationProblem;
3333
end
3434
_vars = reshape(_vars, size(prob.u0))
3535
vars = ArrayInterface.restructure(prob.u0, _vars)
36+
if prob.ub !== nothing # lb is also !== nothing
37+
vars = map(vars, prob.lb, prob.ub) do sym, lb, ub
38+
if iszero(lb) && iszero(ub) || isinf(lb) && lb < 0 && isinf(ub) && ub > 0
39+
sym
40+
else
41+
Symbolics.setmetadata(sym, VariableBounds, (lb, ub))
42+
end
43+
end
44+
end
3645
params = if has_p
3746
if p_names === nothing && SciMLBase.has_sys(prob.f)
3847
p_names = Dict(parameter_index(prob.f.sys, sym) => sym

src/systems/optimization/optimizationsystem.jl

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,17 @@ function OptimizationSystem(op, unknowns, ps;
103103
ps′ = value.(ps)
104104
op′ = value(scalarize(op))
105105

106+
irreducible_subs = Dict()
107+
for i in eachindex(unknowns′)
108+
var = unknowns′[i]
109+
if hasbounds(var)
110+
irreducible_subs[var] = irrvar = setirreducible(var, true)
111+
unknowns′[i] = irrvar
112+
end
113+
end
114+
op′ = substitute(op′, irreducible_subs)
115+
constraints = substitute.(constraints, (irreducible_subs,))
116+
106117
if !(isempty(default_u0) && isempty(default_p))
107118
Base.depwarn(
108119
"`default_u0` and `default_p` are deprecated. Use `defaults` instead.",
@@ -113,7 +124,8 @@ function OptimizationSystem(op, unknowns, ps;
113124
throw(ArgumentError("System names must be unique."))
114125
end
115126
defaults = todict(defaults)
116-
defaults = Dict(value(k) => value(v)
127+
defaults = Dict(substitute(value(k), irreducible_subs) => substitute(
128+
value(v), irreducible_subs)
117129
for (k, v) in pairs(defaults) if value(v) !== nothing)
118130

119131
var_to_name = Dict()

src/variables.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ isoutput(x) = isvarkind(VariableOutput, x)
106106
# Before the solvability check, we already have handled IO variables, so
107107
# irreducibility is independent from IO.
108108
isirreducible(x) = isvarkind(VariableIrreducible, x)
109+
setirreducible(x, v) = setmetadata(x, VariableIrreducible, v)
109110
state_priority(x) = convert(Float64, getmetadata(x, VariableStatePriority, 0.0))::Float64
110111

111112
function default_toterm(x)

test/modelingtoolkitize.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,16 @@ sol = solve(prob, BFGS())
6767
sol = solve(prob, Newton())
6868
@test sol.objective < 1e-8
6969

70+
prob = OptimizationProblem(ones(3); lb = [-Inf, 0.0, 1.0], ub = [Inf, 0.0, 2.0]) do u, p
71+
sum(abs2, u)
72+
end
73+
74+
sys = complete(modelingtoolkitize(prob))
75+
@test !ModelingToolkit.hasbounds(unknowns(sys)[1])
76+
@test !ModelingToolkit.hasbounds(unknowns(sys)[2])
77+
@test ModelingToolkit.hasbounds(unknowns(sys)[3])
78+
@test ModelingToolkit.getbounds(unknowns(sys)[3]) == (1.0, 2.0)
79+
7080
## SIR System Regression Test
7181

7282
β = 0.01# infection rate

test/optimizationsystem.jl

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
using ModelingToolkit, SparseArrays, Test, Optimization, OptimizationOptimJL,
2-
OptimizationMOI, Ipopt, AmplNLWriter, Ipopt_jll
2+
OptimizationMOI, Ipopt, AmplNLWriter, Ipopt_jll, SymbolicIndexingInterface
33
using ModelingToolkit: get_metadata
44

55
@testset "basic" begin
@@ -347,3 +347,15 @@ end
347347
prob = @test_nowarn OptimizationProblem(sys, nothing)
348348
@test_nowarn solve(prob, NelderMead())
349349
end
350+
351+
@testset "Bounded unknowns are irreducible" begin
352+
@variables x
353+
@variables y [bounds = (-Inf, Inf)]
354+
@variables z [bounds = (1.0, 2.0)]
355+
obj = x^2 + y^2 + z^2
356+
cons = [y ~ 2x
357+
z ~ 2y]
358+
@mtkbuild sys = OptimizationSystem(obj, [x, y, z], []; constraints = cons)
359+
@test is_variable(sys, z)
360+
@test !is_variable(sys, y)
361+
end

0 commit comments

Comments
 (0)