@@ -58,7 +58,7 @@ function MTK.JuMPControlProblem(sys::ODESystem, u0map, tspan, pmap;
58
58
f, u0, p = MTK. process_SciMLProblem (ControlFunction, sys, _u0map, pmap;
59
59
t = tspan != = nothing ? tspan[1 ] : tspan, kwargs... )
60
60
61
- model = init_model (sys, tspan[1 ]: dt: tspan[2 ], u0map, u0)
61
+ model = init_model (sys, tspan[1 ]: dt: tspan[2 ], u0map, pmap, u0)
62
62
JuMPControlProblem (f, u0, tspan, p, model, kwargs... )
63
63
end
64
64
@@ -80,22 +80,23 @@ function MTK.InfiniteOptControlProblem(sys::ODESystem, u0map, tspan, pmap;
80
80
f, u0, p = MTK. process_SciMLProblem (ControlFunction, sys, _u0map, pmap;
81
81
t = tspan != = nothing ? tspan[1 ] : tspan, kwargs... )
82
82
83
- model = init_model (sys, tspan[1 ]: dt: tspan[2 ], u0map, u0)
83
+ model = init_model (sys, tspan[1 ]: dt: tspan[2 ], u0map, pmap, u0)
84
84
add_infopt_solve_constraints! (model, sys, pmap)
85
85
InfiniteOptControlProblem (f, u0, tspan, p, model, kwargs... )
86
86
end
87
87
88
- function init_model (sys, tsteps, u0map, u0)
88
+ function init_model (sys, tsteps, u0map, pmap, u0)
89
89
ctrls = MTK. unbound_inputs (sys)
90
90
states = unknowns (sys)
91
91
model = InfiniteModel ()
92
+
92
93
@infinite_parameter (model, t in [tsteps[1 ], tsteps[end ]], num_supports= length (tsteps))
93
94
@variable (model, U[i = 1 : length (states)], Infinite (t))
94
95
@variable (model, V[1 : length (ctrls)], Infinite (t))
95
96
96
97
set_bounds! (model, sys)
97
- add_jump_cost_function! (model, sys)
98
- add_user_constraints! (model, sys)
98
+ add_jump_cost_function! (model, sys, (tsteps[ 1 ], tsteps[ 2 ]), pmap )
99
+ add_user_constraints! (model, sys, pmap )
99
100
100
101
stidxmap = Dict ([v => i for (i, v) in enumerate (states)])
101
102
u0_idxs = has_alg_eqs (sys) ? collect (1 : length (states)) :
@@ -120,63 +121,35 @@ function set_bounds!(model, sys)
120
121
end
121
122
end
122
123
123
- function add_jump_cost_function! (model:: InfiniteModel , sys)
124
+ function add_jump_cost_function! (model:: InfiniteModel , sys, tspan, pmap )
124
125
jcosts = MTK. get_costs (sys)
125
126
consolidate = MTK. get_consolidate (sys)
126
127
if isnothing (jcosts) || isempty (jcosts)
127
128
@objective (model, Min, 0 )
128
129
return
129
130
end
130
- iv = MTK. get_iv (sys)
131
-
132
- stidxmap = Dict ([v => i for (i, v) in enumerate (unknowns (sys))])
133
- cidxmap = Dict ([v => i for (i, v) in enumerate (MTK. unbound_inputs (sys))])
134
-
135
- for st in unknowns (sys)
136
- x = operation (st)
137
- t = only (arguments (st))
138
- idx = stidxmap[x (iv)]
139
- subval = isequal (t, iv) ? model[:U ][idx] : model[:U ][idx](t)
140
- jcosts = map (c -> Symbolics. substitute (c, Dict (x (t) => subval)), jcosts)
141
- end
131
+ jcosts = substitute_jump_vars (model, sys, pmap, jcosts)
142
132
143
- for ct in MTK. unbound_inputs (sys)
144
- p = operation (ct)
145
- t = only (arguments (ct))
146
- idx = cidxmap[p (iv)]
147
- subval = isequal (t, iv) ? model[:V ][idx] : model[:V ][idx](t)
148
- jcosts = map (c -> Symbolics. substitute (c, Dict (p (t) => subval)), jcosts)
133
+ # Substitute integral
134
+ iv = MTK. get_iv (sys)
135
+ jcosts = map (c -> Symbolics. substitute (c, ∫ => Symbolics. Integral (iv in tspan)), jcosts)
136
+ intmap = Dict ()
137
+
138
+ for int in MTK. collect_applied_operators (jcosts, Symbolics. Integral)
139
+ arg = only (arguments (MTK. value (int)))
140
+ lower_bound, upper_bound = (int. domain. domain. left, int. domain. domain. right)
141
+ intmap[int] = InfiniteOpt.∫ (arg, iv; lower_bound, upper_bound)
149
142
end
150
-
143
+ jcosts = map (c -> Symbolics . substitute (c, intmap), jcosts)
151
144
@objective (model, Min, consolidate (jcosts))
152
145
end
153
146
154
- function add_user_constraints! (model:: InfiniteModel , sys)
147
+ function add_user_constraints! (model:: InfiniteModel , sys, pmap )
155
148
conssys = MTK. get_constraintsystem (sys)
156
149
jconstraints = isnothing (conssys) ? nothing : MTK. get_constraints (conssys)
157
150
(isnothing (jconstraints) || isempty (jconstraints)) && return nothing
158
151
159
- iv = MTK. get_iv (sys)
160
- stidxmap = Dict ([v => i for (i, v) in enumerate (unknowns (sys))])
161
- cidxmap = Dict ([v => i for (i, v) in enumerate (MTK. unbound_inputs (sys))])
162
-
163
- for st in unknowns (conssys)
164
- x = operation (st)
165
- t = only (arguments (st))
166
- idx = stidxmap[x (iv)]
167
- subval = isequal (t, iv) ? model[:U ][idx] : model[:U ][idx](t)
168
- jconstraints = map (c -> Symbolics. substitute (c, Dict (x (t) => subval)), jconstraints)
169
- end
170
-
171
- for ct in MTK. unbound_inputs (sys)
172
- p = operation (ct)
173
- t = only (arguments (ct))
174
- idx = cidxmap[p (iv)]
175
- subval = isequal (t, iv) ? model[:V ][idx] : model[:V ][idx](t)
176
- jconstraints = map (
177
- c -> Symbolics. substitute (jconstraints, Dict (p (t) => subval)), jconstriants)
178
- end
179
-
152
+ jconstraints = substitute_jump_vars (model, sys, pmap, jconstraints)
180
153
for (i, cons) in enumerate (jconstraints)
181
154
if cons isa Equation
182
155
@constraint (model, cons. lhs - cons. rhs== 0 , base_name= " user[$i ]" )
@@ -193,31 +166,41 @@ function add_initial_constraints!(model::InfiniteModel, u0, u0_idxs, ts)
193
166
@constraint (model, initial[i in u0_idxs], U[i](ts)== u0[i])
194
167
end
195
168
196
- is_explicit (tableau) = tableau isa DiffEqDevTools. ExplicitRKTableau
197
-
198
- function add_infopt_solve_constraints! (model:: InfiniteModel , sys, pmap)
169
+ function substitute_jump_vars (model, sys, pmap, exprs)
199
170
iv = MTK. get_iv (sys)
200
- t = model[:t ]
171
+ sts = unknowns (sys)
172
+ cts = MTK. unbound_inputs (sys)
201
173
U = model[:U ]
202
174
V = model[:V ]
175
+ # for variables like x(t)
176
+ whole_interval_map = Dict ([[v => U[i] for (i, v) in enumerate (sts)]; [v => V[i] for (i, v) in enumerate (cts)]])
177
+ exprs = map (c -> Symbolics. substitute (c, whole_interval_map), exprs)
178
+
179
+ # for variables like x(1.0)
180
+ x_ops = [MTK. operation (MTK. unwrap (st)) for st in sts]
181
+ c_ops = [MTK. operation (MTK. unwrap (ct)) for ct in cts]
182
+ fixed_t_map = Dict ([[x_ops[i] => U[i] for i in 1 : length (U)]; [c_ops[i] => V[i] for i in 1 : length (V)]])
183
+ exprs = map (c -> Symbolics. substitute (c, fixed_t_map), exprs)
184
+
185
+ exprs = map (c -> Symbolics. substitute (c, Dict (pmap)), exprs)
186
+ exprs
187
+ end
203
188
204
- stmap = Dict ([v => U[i] for (i, v) in enumerate (unknowns (sys))])
205
- ctrlmap = Dict ([v => V[i] for (i, v) in enumerate (MTK. unbound_inputs (sys))])
206
- submap = merge (stmap, ctrlmap, Dict (pmap))
189
+ is_explicit (tableau) = tableau isa DiffEqDevTools. ExplicitRKTableau
207
190
191
+ function add_infopt_solve_constraints! (model:: InfiniteModel , sys, pmap)
208
192
# Differential equations
209
- diff_eqs = diff_equations (sys)
210
- D = Differential (iv)
193
+ U = model[:U ]
194
+ t = model[:t ]
195
+ D = Differential (MTK. get_iv (sys))
211
196
diffsubmap = Dict ([D (U[i]) => ∂ (U[i], t) for i in 1 : length (U)])
212
- for u in unknowns (sys)
213
- diff_eqs = map (e -> Symbolics. substitute (e, submap), diff_eqs)
214
- diff_eqs = map (e -> Symbolics. substitute (e, diffsubmap), diff_eqs)
215
- end
197
+
198
+ diff_eqs = substitute_jump_vars (model, sys, pmap, diff_equations (sys))
199
+ diff_eqs = map (e -> Symbolics. substitute (e, diffsubmap), diff_eqs)
216
200
@constraint (model, D[i = 1 : length (diff_eqs)], diff_eqs[i]. lhs== diff_eqs[i]. rhs)
217
201
218
202
# Algebraic equations
219
- alg_eqs = alg_equations (sys)
220
- alg_eqs = map (e -> Symbolics. substitute (e, submap), alg_eqs)
203
+ alg_eqs = substitute_jump_vars (model, sys, pmap, alg_equations (sys))
221
204
@constraint (model, A[i = 1 : length (alg_eqs)], alg_eqs[i]. lhs== alg_eqs[i]. rhs)
222
205
end
223
206
306
289
`derivative_method` kwarg refers to the method used by InfiniteOpt to compute derivatives. The list of possible options can be found at https://infiniteopt.github.io/InfiniteOpt.jl/stable/guide/derivative/. Defaults to FiniteDifference(Backward()).
307
290
"""
308
291
function DiffEqBase. solve (prob:: InfiniteOptControlProblem , jump_solver;
309
- derivative_method = InfiniteOpt. FiniteDifference (Backward ()))
292
+ derivative_method = InfiniteOpt. FiniteDifference (Backward ()), silent = false )
293
+ model = prob. model
310
294
silent && set_silent (model)
311
- set_derivative_method (prob . model[:t ], derivative_method)
295
+ set_derivative_method (model[:t ], derivative_method)
312
296
_solve (prob, jump_solver, derivative_method)
313
297
end
314
298
0 commit comments