42
42
Convert an ODESystem representing an optimal control system into a JuMP model
43
43
for solving using optimization. Must provide either `dt`, the timestep between collocation
44
44
points (which, along with the timespan, determines the number of points), or directly
45
- provide the number of points as `nsteps `.
45
+ provide the number of points as `steps `.
46
46
47
47
The optimization variables:
48
48
- a vector-of-vectors U representing the unknowns as an interpolation array
@@ -61,7 +61,7 @@ function MTK.JuMPDynamicOptProblem(sys::ODESystem, u0map, tspan, pmap;
61
61
f, u0, p = MTK. process_SciMLProblem (ODEInputFunction, sys, _u0map, pmap;
62
62
t = tspan != = nothing ? tspan[1 ] : tspan, kwargs... )
63
63
64
- pmap = MTK . todict (pmap)
64
+ pmap = Dict {Any, Any} (pmap)
65
65
steps, is_free_t = MTK. process_tspan (tspan, dt, steps)
66
66
model = init_model (sys, tspan, steps, u0map, pmap, u0; is_free_t)
67
67
@@ -87,7 +87,7 @@ function MTK.InfiniteOptDynamicOptProblem(sys::ODESystem, u0map, tspan, pmap;
87
87
f, u0, p = MTK. process_SciMLProblem (ODEInputFunction, sys, _u0map, pmap;
88
88
t = tspan != = nothing ? tspan[1 ] : tspan, kwargs... )
89
89
90
- pmap = MTK . todict (pmap)
90
+ pmap = Dict {Any, Any} (pmap)
91
91
steps, is_free_t = MTK. process_tspan (tspan, dt, steps)
92
92
model = init_model (sys, tspan, steps, u0map, pmap, u0; is_free_t)
93
93
@@ -103,21 +103,25 @@ function init_model(sys, tspan, steps, u0map, pmap, u0; is_free_t = false)
103
103
104
104
if is_free_t
105
105
(ts_sym, te_sym) = tspan
106
+ MTK. symbolic_type (ts_sym) != = MTK. NotSymbolic () && error (" Free initial time problems are not currently supported." )
106
107
@variable (model, tf, start= pmap[te_sym])
108
+ set_lower_bound (tf, ts_sym)
107
109
hasbounds (te_sym) && begin
108
110
lo, hi = getbounds (te_sym)
109
111
set_lower_bound (tf, lo)
110
112
set_upper_bound (tf, hi)
111
113
end
112
- pmap[ts_sym] = 0
113
- pmap[te_sym] = 1
114
+ pmap[te_sym] = model[:tf ]
114
115
tspan = (0 , 1 )
115
116
end
116
117
117
118
@infinite_parameter (model, t in [tspan[1 ], tspan[2 ]], num_supports= steps)
118
119
@variable (model, U[i = 1 : length (states)], Infinite (t), start= u0[i])
119
120
c0 = MTK. value .([pmap[c] for c in ctrls])
120
121
@variable (model, V[i = 1 : length (ctrls)], Infinite (t), start= c0[i])
122
+ for (i, ct) in enumerate (ctrls)
123
+ pmap[ct] = model[:V ][i]
124
+ end
121
125
122
126
set_jump_bounds! (model, sys, pmap)
123
127
add_jump_cost_function! (model, sys, (tspan[1 ], tspan[2 ]), pmap; is_free_t)
@@ -131,6 +135,13 @@ function init_model(sys, tspan, steps, u0map, pmap, u0; is_free_t = false)
131
135
return model
132
136
end
133
137
138
+ """
139
+ Modify the pmap by replacing controls with V[i](t), and tf with the model's final time variable for free final time problems.
140
+ """
141
+ function modified_pmap (model, sys, pmap)
142
+ pmap = Dict {Any, Any} (pmap)
143
+ end
144
+
134
145
function set_jump_bounds! (model, sys, pmap)
135
146
U = model[:U ]
136
147
for (i, u) in enumerate (unknowns (sys))
@@ -158,7 +169,7 @@ function add_jump_cost_function!(model::InfiniteModel, sys, tspan, pmap; is_free
158
169
@objective (model, Min, 0 )
159
170
return
160
171
end
161
- jcosts = substitute_jump_vars (model, sys, pmap, jcosts)
172
+ jcosts = substitute_jump_vars (model, sys, pmap, jcosts; is_free_t )
162
173
tₛ = is_free_t ? model[:tf ] : 1
163
174
164
175
# Substitute integral
@@ -186,13 +197,14 @@ function add_user_constraints!(model::InfiniteModel, sys, pmap; is_free_t = fals
186
197
for u in MTK. get_unknowns (conssys)
187
198
x = MTK. operation (u)
188
199
t = only (arguments (u))
189
- MTK. symbolic_type (t) === NotSymbolic () &&
190
- error (" Provided specific time constraint in a free final time problem. This is not supported by the JuMP/InfiniteOpt collocation solvers. The offending variable is $u ." )
200
+ if (MTK. symbolic_type (t) === MTK. NotSymbolic ())
201
+ error (" Provided specific time constraint in a free final time problem. This is not supported by the JuMP/InfiniteOpt collocation solvers. The offending variable is $u . Specific-time constraints can only be specified at the beginning or end of the timespan." )
202
+ end
191
203
end
192
204
end
193
205
194
206
auxmap = Dict ([u => MTK. default_toterm (MTK. value (u)) for u in unknowns (conssys)])
195
- jconstraints = substitute_jump_vars (model, sys, pmap, jconstraints; auxmap)
207
+ jconstraints = substitute_jump_vars (model, sys, pmap, jconstraints; auxmap, is_free_t )
196
208
197
209
# Substitute to-term'd variables
198
210
for (i, cons) in enumerate (jconstraints)
@@ -211,28 +223,33 @@ function add_initial_constraints!(model::InfiniteModel, u0, u0_idxs, ts)
211
223
@constraint (model, initial[i in u0_idxs], U[i](ts)== u0[i])
212
224
end
213
225
214
- function substitute_jump_vars (model, sys, pmap, exprs; auxmap = Dict ())
226
+ function substitute_jump_vars (model, sys, pmap, exprs; auxmap = Dict (), is_free_t = false )
215
227
iv = MTK. get_iv (sys)
216
228
sts = unknowns (sys)
217
229
cts = MTK. unbound_inputs (sys)
218
230
U = model[:U ]
219
231
V = model[:V ]
232
+ x_ops = [MTK. operation (MTK. unwrap (st)) for st in sts]
233
+ c_ops = [MTK. operation (MTK. unwrap (ct)) for ct in cts]
234
+
220
235
exprs = map (c -> Symbolics. fixpoint_sub (c, auxmap), exprs)
236
+ exprs = map (c -> Symbolics. fixpoint_sub (c, Dict (pmap)), exprs)
237
+ if is_free_t
238
+ tf = model[:tf ]
239
+ free_t_map = Dict ([[x (tf) => U[i](1 ) for (i, x) in enumerate (x_ops)]; [c (tf) => V[i](1 ) for (i, c) in enumerate (c_ops)]])
240
+ exprs = map (c -> Symbolics. fixpoint_sub (c, free_t_map), exprs)
241
+ end
221
242
222
243
# for variables like x(t)
223
244
whole_interval_map = Dict ([[v => U[i] for (i, v) in enumerate (sts)];
224
245
[v => V[i] for (i, v) in enumerate (cts)]])
225
246
exprs = map (c -> Symbolics. fixpoint_sub (c, whole_interval_map), exprs)
226
247
227
248
# for variables like x(1.0)
228
- x_ops = [MTK. operation (MTK. unwrap (st)) for st in sts]
229
- c_ops = [MTK. operation (MTK. unwrap (ct)) for ct in cts]
230
249
fixed_t_map = Dict ([[x_ops[i] => U[i] for i in 1 : length (U)];
231
250
[c_ops[i] => V[i] for i in 1 : length (V)]])
232
251
233
252
exprs = map (c -> Symbolics. fixpoint_sub (c, fixed_t_map), exprs)
234
-
235
- exprs = map (c -> Symbolics. fixpoint_sub (c, Dict (pmap)), exprs)
236
253
exprs
237
254
end
238
255
@@ -246,8 +263,12 @@ function add_infopt_solve_constraints!(model::InfiniteModel, sys, pmap; is_free_
246
263
diffsubmap = Dict ([D (U[i]) => ∂ (U[i], t) for i in 1 : length (U)])
247
264
tₛ = is_free_t ? model[:tf ] : 1
248
265
266
+ @show diff_equations (sys)
267
+ @show pmap
249
268
diff_eqs = substitute_jump_vars (model, sys, pmap, diff_equations (sys))
269
+ @show diff_eqs
250
270
diff_eqs = map (e -> Symbolics. substitute (e, diffsubmap), diff_eqs)
271
+ @show diff_eqs
251
272
@constraint (model, D[i = 1 : length (diff_eqs)], diff_eqs[i]. lhs== tₛ * diff_eqs[i]. rhs)
252
273
253
274
# Algebraic equations
0 commit comments