Skip to content

Commit f2a167e

Browse files
committed
test quick, init, solution: updated
1 parent 0d3fa6e commit f2a167e

File tree

4 files changed

+145
-88
lines changed

4 files changed

+145
-88
lines changed

test/figures/init/beam.pdf

0 Bytes
Binary file not shown.

test/figures/solution/beam.pdf

52.4 KB
Binary file not shown.

test/runtests.jl

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ problems_to_exclude = [
4040
]
4141
list_of_problems = setdiff(list_of_problems, problems_to_exclude)
4242

43-
list_of_problems = [
44-
:beam
45-
]
43+
# list_of_problems = [
44+
# :beam
45+
# ]
4646

4747
# The list of all the problems to test
4848
const LIST_OF_PROBLEMS = deepcopy(list_of_problems)
@@ -56,13 +56,13 @@ const VERBOSE = true # print or not details during tests
5656
@testset "OptimalControlProblems tests" verbose=VERBOSE showtiming=true begin
5757
for name in (
5858
#:aqua,
59-
# :kwargs,
60-
# :JuMP, # convergence tests for JuMP models
61-
# :OptimalControl, # convergence tests for OptimalControl models
62-
# :OptimalControl_s, # convergence tests for OptimalControl models
59+
:kwargs,
60+
:JuMP, # convergence tests for JuMP models
61+
:OptimalControl, # convergence tests for OptimalControl models
62+
:OptimalControl_s, # convergence tests for OptimalControl models
6363
:init, # comparison between OptimalControl and JuMP: init
64-
# :solution, # comparison between OptimalControl and JuMP: solution
65-
# :quick, # quick comparison: objective rel error only
64+
:solution, # comparison between OptimalControl and JuMP: solution
65+
:quick, # quick comparison: objective rel error only
6666
)
6767
@testset "$(name)" verbose=VERBOSE begin
6868
test_name = Symbol(:test_, name)

test/utils.jl

Lines changed: 136 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ julia> comparison(max_iter=100, test_name=:solution)
7979
"""
8080
function comparison(; max_iter, test_name)
8181

82+
test_tag(res) = res ? "\033[1;32mPASS\033[0m" : "\033[1;31mFAIL\033[0m"
83+
8284
#
8385
available_test_names = [:init, :solution, :iter1]
8486
test_name available_test_names ||
@@ -97,6 +99,9 @@ function comparison(; max_iter, test_name)
9799
ε_rel_control = 1e-1
98100
ε_abs_control = 1e-6
99101

102+
ε_rel_variable = 1e-1
103+
ε_abs_variable = 1e-6
104+
100105
# options_ipopt for solvers
101106
options_ipopt = Dict(
102107
:print_level => 0,
@@ -117,6 +122,96 @@ function comparison(; max_iter, test_name)
117122
:linear_solver => MumpsSolver,
118123
)
119124

125+
#
126+
function test_L2_i(i, times, A, B, A_name, B_name; ε_abs, ε_rel)
127+
yi_oc, yi_jp = [B[k][i] for k in eachindex(times)], [A[k][i] for k in eachindex(times)]
128+
L2_di = L2_norm(times, yi_oc - yi_jp)
129+
L2_bd = max(0.5*(L2_norm(times, yi_oc)+L2_norm(times, yi_jp))*ε_rel, ε_abs)
130+
res = @my_test_broken L2_di < L2_bd
131+
r_err = L2_di / (0.5*(L2_norm(times, yi_oc)+L2_norm(times, yi_jp)))
132+
DEBUG && @printf("│ → %s vs %s: r_err=%.3e a_err=%.3e bound=%.3e %s\n", A_name, B_name, r_err, L2_di, L2_bd, test_tag(res))
133+
return res
134+
end
135+
136+
function test_L2_i(i, times, A, B, A_name, B_name, keep_problem; ε_abs, ε_rel)
137+
res = test_L2_i(i, times, A, B, A_name, B_name; ε_abs=ε_abs, ε_rel=ε_rel)
138+
return keep_problem && res
139+
end
140+
141+
#
142+
function test_abs(A, B, A_name, B_name; ε_abs, ε_rel)
143+
tf_di = abs(A - B)
144+
tf_bd = max(0.5*(A+B)*ε_rel, ε_abs)
145+
res = @my_test_broken tf_di < tf_bd
146+
r_err = tf_di / (0.5*(A+B))
147+
DEBUG && @printf("│ → %s: %.3e %s: %.3e r_err=%.3e a_err=%.3e bound=%.3e %s\n", A_name, A, B_name, B, r_err, tf_di, tf_bd, test_tag(res))
148+
return res
149+
end
150+
151+
function test_abs(A, B, A_name, B_name, keep_problem; ε_abs, ε_rel)
152+
res = test_abs(A, B, A_name, B_name; ε_abs=ε_abs, ε_rel=ε_rel)
153+
return res && keep_problem
154+
end
155+
156+
function test_abs(A, B, A_name, B_name, keep_problem, test_grid_ok; ε_abs, ε_rel)
157+
res = test_abs(A, B, A_name, B_name; ε_abs=ε_abs, ε_rel=ε_rel)
158+
return res && keep_problem, res && test_grid_ok
159+
end
160+
161+
function test_abs_i(i, A, B, A_name, B_name; ε_abs, ε_rel)
162+
return test_abs(A[i], B[i], A_name, B_name; ε_abs, ε_rel)
163+
end
164+
165+
function test_abs_i(i, A, B, A_name, B_name, keep_problem; ε_abs, ε_rel)
166+
return test_abs(A[i], B[i], A_name, B_name, keep_problem; ε_abs, ε_rel)
167+
end
168+
169+
#
170+
function test_int(A, B, A_name, B_name)
171+
res = @my_test_broken A == B
172+
DEBUG && @printf("│ → %s: %d %s: %d %s\n", A_name, A, B_name, B, test_tag(res))
173+
return res
174+
end
175+
176+
function test_int(A, B, A_name, B_name, keep_problem)
177+
res = test_int(A, B, A_name, B_name)
178+
return res && keep_problem
179+
end
180+
181+
function test_int(A, B, A_name, B_name, keep_problem, test_grid_ok)
182+
res = test_int(A, B, A_name, B_name)
183+
return res && keep_problem, res && test_grid_ok
184+
end
185+
186+
#
187+
function test_length(A, B, A_name, B_name)
188+
return test_int(length(A), length(B), A_name, B_name)
189+
end
190+
191+
function test_length(A, B, A_name, B_name, keep_problem, test_grid_ok)
192+
res = test_length(A, B, A_name, B_name)
193+
return res && keep_problem, res && test_grid_ok
194+
end
195+
196+
#
197+
function test_grid_max_error(A, B, A_name, B_name, keep_problem, test_grid_ok)
198+
ti_di_max, ti_bd_max, itera_max = 0, NaN, 0
199+
for i in eachindex(B)
200+
ti_di = B[i] - A[i]
201+
ti_bd = max(0.5*(abs(B[i])+abs(A[i]))*ε_rel_grid, ε_abs_grid)
202+
res = @my_test_broken abs(ti_di) < ti_bd
203+
keep_problem = keep_problem && res
204+
test_grid_ok = test_grid_ok && res
205+
if abs(ti_di) abs(ti_di_max)
206+
ti_di_max, ti_bd_max, itera_max = ti_di, ti_bd, i
207+
end
208+
end
209+
r_err = abs(ti_di_max)/(0.5*(abs(B[itera_max])+abs(A[itera_max])))
210+
res = r_err<1.0
211+
DEBUG && @printf("│ → %s vs %s: iter=%d r_err=%.3e a_err=%.3e bound=%.3e %s\n", A_name, B_name, itera_max, r_err, abs(ti_di_max), ti_bd_max, test_tag(res))
212+
return keep_problem && res, test_grid_ok && res
213+
end
214+
120215
# we loop over the problems
121216
for f in LIST_OF_PROBLEMS
122217
N = metadata[f][:N] # get default N
@@ -148,6 +243,8 @@ function comparison(; max_iter, test_name)
148243
i_jp = iterations(f, nlp_jp)
149244
v_jp = variable(f, nlp_jp)
150245
p_jp = costate(f, nlp_jp).(t_jp)
246+
nb_var_jp = num_variables(nlp_jp)
247+
nb_con_jp = num_constraints(nlp_jp; count_variable_in_set_constraints=false)
151248

152249
########## OptimalControl ##########
153250
docp = OptimalControlProblems.eval(f)(OptimalControlBackend(); N=N)
@@ -161,6 +258,8 @@ function comparison(; max_iter, test_name)
161258
o_oc = objective(sol_oc)
162259
i_oc = iterations(sol_oc)
163260
v_oc = variable(sol_oc)
261+
nb_var_oc = get_nvar(nlp_oc)
262+
nb_con_oc = get_ncon(nlp_oc)
164263

165264
########## OptimalControl_s ##########
166265
docp = OptimalControlProblems.eval(Symbol(f, :_s))(OptimalControlBackend(), :madnlp, :exa; N=N)
@@ -174,65 +273,49 @@ function comparison(; max_iter, test_name)
174273
o_os = objective(sol_os)
175274
i_os = iterations(sol_os)
176275
v_os = variable(sol_os)
276+
nb_var_os = get_nvar(nlp_os)
277+
nb_con_os = get_ncon(nlp_os)
177278

178279
########## Iterations ##########
179-
DEBUG && println("├─ Iterations → JP: ", i_jp, ", OC: ", i_oc, ", OS: ", i_os)
280+
DEBUG && @printf("├─ Iterations\n")
281+
DEBUG && @printf("│ → JP: %d OC: %d OS: %d\n", i_jp, i_oc, i_os)
180282

181283
keep_problem = true
182284

183285
########## Variables / Constraints ##########
184286
@testset "nlp" verbose=VERBOSE begin
185-
nb_var_oc, nb_var_jp = get_nvar(nlp_oc), num_variables(nlp_jp)
186-
res = @my_test_broken nb_var_oc == nb_var_jp
187-
keep_problem = keep_problem && res
188-
DEBUG && @printf("├─ Variables → OC: %d JP: %d %s\n", nb_var_oc, nb_var_jp,
189-
res ? "\033[1;32mPASS\033[0m" : "\033[1;31mFAIL\033[0m")
190-
191-
nb_con_oc = get_ncon(nlp_oc)
192-
nb_con_jp = num_constraints(nlp_jp; count_variable_in_set_constraints=false)
193-
res = @my_test_broken nb_con_oc == nb_con_jp
194-
keep_problem = keep_problem && res
195-
DEBUG && @printf("├─ Constraints → OC: %d JP: %d %s\n", nb_con_oc, nb_con_jp,
196-
res ? "\033[1;32mPASS\033[0m" : "\033[1;31mFAIL\033[0m")
287+
DEBUG && @printf("├─ Variables\n")
288+
keep_problem = test_int(nb_var_jp, nb_var_oc, "JP", "OC", keep_problem)
289+
keep_problem = test_int(nb_var_jp, nb_var_os, "JP", "OS", keep_problem)
290+
291+
DEBUG && @printf("├─ Constraints\n")
292+
keep_problem = test_int(nb_con_jp, nb_con_oc, "JP", "OC", keep_problem)
293+
keep_problem = test_int(nb_con_jp, nb_con_os, "JP", "OS", keep_problem)
197294
end
198295

199296
########## Time Grid ##########
200297
test_grid_ok = true
201298
@testset "grid" verbose=VERBOSE begin
299+
300+
# ----------------------------
202301
# final time
203-
tf_di = abs(t_oc[end] - t_jp[end])
204-
tf_bd = max(0.5*(t_oc[end]+t_jp[end])*ε_rel_grid, ε_abs_grid)
205-
res = @my_test_broken tf_di < tf_bd
206-
r_err = tf_di / (0.5*(t_oc[end]+t_jp[end]))
207-
DEBUG && @printf("├─ Final time → OC: %.3e JP: %.3e\n", t_oc[end], t_jp[end])
208-
DEBUG && @printf("│ r_err=%.3e a_err=%.3e bound=%.3e %s\n",
209-
r_err, tf_di, tf_bd,
210-
res ? "\033[1;32mPASS\033[0m" : "\033[1;31mFAIL\033[0m")
302+
DEBUG && @printf("├─ Final time\n")
303+
keep_problem, test_grid_ok = test_abs(t_jp[end], t_oc[end], "JP", "OC", keep_problem, test_grid_ok; ε_abs=ε_abs_grid, ε_rel=ε_rel_grid)
304+
keep_problem, test_grid_ok = test_abs(t_jp[end], t_os[end], "JP", "OS", keep_problem, test_grid_ok; ε_abs=ε_abs_grid, ε_rel=ε_rel_grid)
211305

306+
# ----------------------------
212307
# length of the grids
213-
res = @my_test_broken length(t_oc) == length(t_jp)
214-
keep_problem = keep_problem && res
215-
test_grid_ok = test_grid_ok && res
216-
DEBUG && @printf("├─ Grid length → OC: %d JP: %d %s\n", length(t_oc), length(t_jp),
217-
res ? "\033[1;32mPASS\033[0m" : "\033[1;31mFAIL\033[0m")
308+
DEBUG && @printf("├─ Grid length\n")
309+
keep_problem, test_grid_ok = test_length(t_jp, t_oc, "JP", "OC", keep_problem, test_grid_ok)
310+
keep_problem, test_grid_ok = test_length(t_jp, t_os, "JP", "OS", keep_problem, test_grid_ok)
218311

312+
# ----------------------------
219313
# max error
220314
if test_grid_ok
221-
ti_di_max, ti_bd_max, itera_max = 0, NaN, 0
222-
for i in eachindex(t_oc)
223-
ti_di = t_oc[i] - t_jp[i]
224-
ti_bd = max(0.5*(abs(t_oc[i])+abs(t_jp[i]))*ε_rel_grid, ε_abs_grid)
225-
res = @my_test_broken abs(ti_di) < ti_bd
226-
keep_problem = keep_problem && res
227-
test_grid_ok = test_grid_ok && res
228-
if abs(ti_di) abs(ti_di_max)
229-
ti_di_max, ti_bd_max, itera_max = ti_di, ti_bd, i
230-
end
231-
end
232-
r_err = abs(ti_di_max)/(0.5*(abs(t_oc[itera_max])+abs(t_jp[itera_max])))
233-
DEBUG && @printf("├─ Grid max error → iter=%d r_err=%.3e a_err=%.3e bound=%.3e %s\n",
234-
itera_max, r_err, abs(ti_di_max), ti_bd_max,
235-
r_err<1.0 ? "\033[1;32mPASS\033[0m" : "\033[1;31mFAIL\033[0m")
315+
DEBUG && @printf("├─ Grid max error\n")
316+
keep_problem, test_grid_ok = test_grid_max_error(t_jp, t_oc, "JP", "OC", keep_problem, test_grid_ok)
317+
keep_problem, test_grid_ok = test_grid_max_error(t_jp, t_os, "JP", "OS", keep_problem, test_grid_ok)
318+
236319
end
237320
end
238321

@@ -241,16 +324,10 @@ function comparison(; max_iter, test_name)
241324
@testset "state" verbose=VERBOSE begin
242325
DEBUG && println("├─ States")
243326
for i in eachindex(x_vars)
327+
DEBUG && @printf("│ %-6s\n", x_vars[i])
244328
@testset "$(x_vars[i])" verbose=VERBOSE begin
245-
xi_oc, xi_jp = [x_oc[k][i] for k in eachindex(t_oc)], [x_jp[k][i] for k in eachindex(t_jp)]
246-
L2_di = L2_norm(t_oc, xi_oc - xi_jp)
247-
L2_bd = max(0.5*(L2_norm(t_oc, xi_oc)+L2_norm(t_oc, xi_jp))*ε_rel_state, ε_abs_state)
248-
res = @my_test_broken L2_di < L2_bd
249-
keep_problem = keep_problem && res
250-
r_err = L2_di / (0.5*(L2_norm(t_oc, xi_oc)+L2_norm(t_oc, xi_jp)))
251-
DEBUG && @printf("│ %-6s r_err=%.3e a_err=%.3e bound=%.3e %s\n",
252-
x_vars[i], r_err, L2_di, L2_bd,
253-
res ? "\033[1;32mPASS\033[0m" : "\033[1;31mFAIL\033[0m")
329+
keep_problem = test_L2_i(i, t_jp, x_jp, x_oc, "JP", "OC", keep_problem; ε_abs=ε_abs_state, ε_rel=ε_rel_state)
330+
keep_problem = test_L2_i(i, t_jp, x_jp, x_os, "JP", "OS", keep_problem; ε_abs=ε_abs_state, ε_rel=ε_rel_state)
254331
end
255332
end
256333
end
@@ -261,16 +338,10 @@ function comparison(; max_iter, test_name)
261338
@testset "control" verbose=VERBOSE begin
262339
DEBUG && println("├─ Controls")
263340
for i in eachindex(u_vars)
341+
DEBUG && @printf("│ %-6s\n", u_vars[i])
264342
@testset "$(u_vars[i])" verbose=VERBOSE begin
265-
ui_oc, ui_jp = [u_oc[k][i] for k in eachindex(t_oc)], [u_jp[k][i] for k in eachindex(t_jp)]
266-
L2_di = L2_norm(t_oc, ui_oc - ui_jp)
267-
L2_bd = max(0.5*(L2_norm(t_oc, ui_oc)+L2_norm(t_oc, ui_jp))*ε_rel_control, ε_abs_control)
268-
res = @my_test_broken L2_di < L2_bd
269-
keep_problem = keep_problem && res
270-
r_err = L2_di / (0.5*(L2_norm(t_oc, ui_oc)+L2_norm(t_oc, ui_jp)))
271-
DEBUG && @printf("│ %-6s r_err=%.3e a_err=%.3e bound=%.3e %s\n",
272-
u_vars[i], r_err, L2_di, L2_bd,
273-
res ? "\033[1;32mPASS\033[0m" : "\033[1;31mFAIL\033[0m")
343+
keep_problem = test_L2_i(i, t_jp, u_jp, u_oc, "JP", "OC", keep_problem; ε_abs=ε_abs_control, ε_rel=ε_rel_control)
344+
keep_problem = test_L2_i(i, t_jp, u_jp, u_os, "JP", "OS", keep_problem; ε_abs=ε_abs_control, ε_rel=ε_rel_control)
274345
end
275346
end
276347
end
@@ -281,32 +352,20 @@ function comparison(; max_iter, test_name)
281352
@testset "variable" verbose=VERBOSE begin
282353
DEBUG && println("├─ Variables")
283354
for i in eachindex(v_vars)
355+
DEBUG && @printf("│ %-6s\n", v_vars[i])
284356
@testset "$(v_vars[i])" verbose=VERBOSE begin
285-
vi_oc, vi_jp = v_oc[i], v_jp[i]
286-
vi_di = abs(vi_oc-vi_jp)
287-
vi_bd = max(0.5*(abs(vi_oc)+abs(vi_jp))*ε_rel_control, ε_abs_control)
288-
res = @my_test_broken vi_di < vi_bd
289-
keep_problem = keep_problem && res
290-
r_err = vi_di / (0.5*(abs(vi_oc)+abs(vi_jp)))
291-
DEBUG && @printf("│ %-6s r_err=%.3e a_err=%.3e bound=%.3e %s\n",
292-
v_vars[i], r_err, vi_di, vi_bd,
293-
res ? "\033[1;32mPASS\033[0m" : "\033[1;31mFAIL\033[0m")
357+
keep_problem = test_abs_i(i, v_jp, v_oc, "JP", "OC", keep_problem; ε_abs=ε_abs_variable, ε_rel=ε_rel_variable)
358+
keep_problem = test_abs_i(i, v_jp, v_os, "JP", "OS", keep_problem; ε_abs=ε_abs_variable, ε_rel=ε_rel_variable)
294359
end
295360
end
296361
end
297362
end
298363

299364
########## Objective ##########
365+
DEBUG && println("├─ Objective")
300366
@testset "objective" verbose=VERBOSE begin
301-
o_di = abs(o_oc-o_jp)
302-
o_bd = max(0.5*(abs(o_oc)+abs(o_jp))*ε_rel_objective, ε_abs_objective)
303-
res = @my_test_broken o_di < o_bd
304-
keep_problem = keep_problem && res
305-
r_err = o_di / (0.5*(abs(o_oc)+abs(o_jp)))
306-
DEBUG && println("├─ Objective")
307-
DEBUG && @printf("│ r_err=%.3e a_err=%.3e bound=%.3e %s\n",
308-
r_err, o_di, o_bd,
309-
res ? "\033[1;32mPASS\033[0m" : "\033[1;31mFAIL\033[0m")
367+
keep_problem = test_abs(o_jp, o_oc, "JP", "OC", keep_problem; ε_abs=ε_abs_objective, ε_rel=ε_rel_objective)
368+
keep_problem = test_abs(o_jp, o_os, "JP", "OS", keep_problem; ε_abs=ε_abs_objective, ε_rel=ε_rel_objective)
310369
end
311370

312371
DEBUG && println("└─")
@@ -362,9 +421,7 @@ function comparison(; max_iter, test_name)
362421
control_style=(color=color, legend=:none),
363422
path_style=(color=color, legend=:none),
364423
dual_style=(color=color, legend=:none),
365-
size=(900, 220*(n+m)),
366424
label=labelOC,
367-
leftmargin=20mm,
368425
)
369426
for i in 2:n
370427
plot!(plt[i]; legend=:none)

0 commit comments

Comments
 (0)