diff --git a/test/figures/init/balanced_field.pdf b/test/figures/init/balanced_field.pdf new file mode 100644 index 00000000..b9b1a6ae Binary files /dev/null and b/test/figures/init/balanced_field.pdf differ diff --git a/test/figures/init/beam.pdf b/test/figures/init/beam.pdf index 8e88dc9b..2af1bf7c 100644 Binary files a/test/figures/init/beam.pdf and b/test/figures/init/beam.pdf differ diff --git a/test/figures/init/brachistochrone.pdf b/test/figures/init/brachistochrone.pdf new file mode 100644 index 00000000..37665e61 Binary files /dev/null and b/test/figures/init/brachistochrone.pdf differ diff --git a/test/figures/init/bryson_denham.pdf b/test/figures/init/bryson_denham.pdf new file mode 100644 index 00000000..04659efc Binary files /dev/null and b/test/figures/init/bryson_denham.pdf differ diff --git a/test/figures/init/chain.pdf b/test/figures/init/chain.pdf index 261dfc8f..b8a20a99 100644 Binary files a/test/figures/init/chain.pdf and b/test/figures/init/chain.pdf differ diff --git a/test/figures/init/dielectrophoretic_particle.pdf b/test/figures/init/dielectrophoretic_particle.pdf index 3bb12164..8fdc7c9b 100644 Binary files a/test/figures/init/dielectrophoretic_particle.pdf and b/test/figures/init/dielectrophoretic_particle.pdf differ diff --git a/test/figures/init/double_oscillator.pdf b/test/figures/init/double_oscillator.pdf index 0beae3b9..d492b928 100644 Binary files a/test/figures/init/double_oscillator.pdf and b/test/figures/init/double_oscillator.pdf differ diff --git a/test/figures/init/ducted_fan.pdf b/test/figures/init/ducted_fan.pdf index 9eeb6874..b1323784 100644 Binary files a/test/figures/init/ducted_fan.pdf and b/test/figures/init/ducted_fan.pdf differ diff --git a/test/figures/init/electric_vehicle.pdf b/test/figures/init/electric_vehicle.pdf index ece37f31..6e0ee7a2 100644 Binary files a/test/figures/init/electric_vehicle.pdf and b/test/figures/init/electric_vehicle.pdf differ diff --git a/test/figures/init/glider.pdf b/test/figures/init/glider.pdf index 651a08ad..1412fb59 100644 Binary files a/test/figures/init/glider.pdf and b/test/figures/init/glider.pdf differ diff --git a/test/figures/init/insurance.pdf b/test/figures/init/insurance.pdf index a8783283..1423bc6f 100644 Binary files a/test/figures/init/insurance.pdf and b/test/figures/init/insurance.pdf differ diff --git a/test/figures/init/jackson.pdf b/test/figures/init/jackson.pdf index 9ea1725c..b7bef258 100644 Binary files a/test/figures/init/jackson.pdf and b/test/figures/init/jackson.pdf differ diff --git a/test/figures/init/mountain_car.pdf b/test/figures/init/mountain_car.pdf new file mode 100644 index 00000000..3bb9fcf5 Binary files /dev/null and b/test/figures/init/mountain_car.pdf differ diff --git a/test/figures/init/robbins.pdf b/test/figures/init/robbins.pdf index 09d7d91c..ed4792e8 100644 Binary files a/test/figures/init/robbins.pdf and b/test/figures/init/robbins.pdf differ diff --git a/test/figures/init/robot.pdf b/test/figures/init/robot.pdf index 04a2597e..03aba3e6 100644 Binary files a/test/figures/init/robot.pdf and b/test/figures/init/robot.pdf differ diff --git a/test/figures/init/rocket.pdf b/test/figures/init/rocket.pdf index 54f39f5a..ce90aa70 100644 Binary files a/test/figures/init/rocket.pdf and b/test/figures/init/rocket.pdf differ diff --git a/test/figures/init/space_shuttle.pdf b/test/figures/init/space_shuttle.pdf index 26c9d610..7137bfdf 100644 Binary files a/test/figures/init/space_shuttle.pdf and b/test/figures/init/space_shuttle.pdf differ diff --git a/test/figures/init/steering.pdf b/test/figures/init/steering.pdf index ef5b95a5..df0487e6 100644 Binary files a/test/figures/init/steering.pdf and b/test/figures/init/steering.pdf differ diff --git a/test/figures/init/vanderpol.pdf b/test/figures/init/vanderpol.pdf index 81eb1ce5..de8657f8 100644 Binary files a/test/figures/init/vanderpol.pdf and b/test/figures/init/vanderpol.pdf differ diff --git a/test/figures/solution/balanced_field.pdf b/test/figures/solution/balanced_field.pdf new file mode 100644 index 00000000..a92f5029 Binary files /dev/null and b/test/figures/solution/balanced_field.pdf differ diff --git a/test/figures/solution/beam.pdf b/test/figures/solution/beam.pdf index c42556a1..55815f94 100644 Binary files a/test/figures/solution/beam.pdf and b/test/figures/solution/beam.pdf differ diff --git a/test/figures/solution/brachistochrone.pdf b/test/figures/solution/brachistochrone.pdf new file mode 100644 index 00000000..e8cf9ecd Binary files /dev/null and b/test/figures/solution/brachistochrone.pdf differ diff --git a/test/figures/solution/bryson_denham.pdf b/test/figures/solution/bryson_denham.pdf new file mode 100644 index 00000000..710dcb8f Binary files /dev/null and b/test/figures/solution/bryson_denham.pdf differ diff --git a/test/figures/solution/chain.pdf b/test/figures/solution/chain.pdf index f8a1c12a..b161be75 100644 Binary files a/test/figures/solution/chain.pdf and b/test/figures/solution/chain.pdf differ diff --git a/test/figures/solution/dielectrophoretic_particle.pdf b/test/figures/solution/dielectrophoretic_particle.pdf index 8575fe1d..d7cf5f2b 100644 Binary files a/test/figures/solution/dielectrophoretic_particle.pdf and b/test/figures/solution/dielectrophoretic_particle.pdf differ diff --git a/test/figures/solution/double_oscillator.pdf b/test/figures/solution/double_oscillator.pdf index 787ac9d4..e8edb7c2 100644 Binary files a/test/figures/solution/double_oscillator.pdf and b/test/figures/solution/double_oscillator.pdf differ diff --git a/test/figures/solution/ducted_fan.pdf b/test/figures/solution/ducted_fan.pdf index 22258a0b..71e3cf56 100644 Binary files a/test/figures/solution/ducted_fan.pdf and b/test/figures/solution/ducted_fan.pdf differ diff --git a/test/figures/solution/electric_vehicle.pdf b/test/figures/solution/electric_vehicle.pdf index c586681b..5cb93cc6 100644 Binary files a/test/figures/solution/electric_vehicle.pdf and b/test/figures/solution/electric_vehicle.pdf differ diff --git a/test/figures/solution/glider.pdf b/test/figures/solution/glider.pdf index 4803cb35..4bae1c13 100644 Binary files a/test/figures/solution/glider.pdf and b/test/figures/solution/glider.pdf differ diff --git a/test/figures/solution/insurance.pdf b/test/figures/solution/insurance.pdf index 3b41638a..7c2a96b1 100644 Binary files a/test/figures/solution/insurance.pdf and b/test/figures/solution/insurance.pdf differ diff --git a/test/figures/solution/jackson.pdf b/test/figures/solution/jackson.pdf index 2294a7e6..086e267f 100644 Binary files a/test/figures/solution/jackson.pdf and b/test/figures/solution/jackson.pdf differ diff --git a/test/figures/solution/mountain_car.pdf b/test/figures/solution/mountain_car.pdf new file mode 100644 index 00000000..40571c63 Binary files /dev/null and b/test/figures/solution/mountain_car.pdf differ diff --git a/test/figures/solution/robbins.pdf b/test/figures/solution/robbins.pdf index 41a9b7d1..be11a71a 100644 Binary files a/test/figures/solution/robbins.pdf and b/test/figures/solution/robbins.pdf differ diff --git a/test/figures/solution/robot.pdf b/test/figures/solution/robot.pdf index 5f3563d9..7dbc3cac 100644 Binary files a/test/figures/solution/robot.pdf and b/test/figures/solution/robot.pdf differ diff --git a/test/figures/solution/rocket.pdf b/test/figures/solution/rocket.pdf index dafebb92..b8b43230 100644 Binary files a/test/figures/solution/rocket.pdf and b/test/figures/solution/rocket.pdf differ diff --git a/test/figures/solution/space_shuttle.pdf b/test/figures/solution/space_shuttle.pdf index 8ea5b5dd..b40d12ec 100644 Binary files a/test/figures/solution/space_shuttle.pdf and b/test/figures/solution/space_shuttle.pdf differ diff --git a/test/figures/solution/steering.pdf b/test/figures/solution/steering.pdf index af57b7fe..53b260dd 100644 Binary files a/test/figures/solution/steering.pdf and b/test/figures/solution/steering.pdf differ diff --git a/test/figures/solution/vanderpol.pdf b/test/figures/solution/vanderpol.pdf index 2024087d..0c7453e5 100644 Binary files a/test/figures/solution/vanderpol.pdf and b/test/figures/solution/vanderpol.pdf differ diff --git a/test/test_JuMP.jl b/test/test_JuMP.jl index f668397c..18d7cf7b 100644 --- a/test/test_JuMP.jl +++ b/test/test_JuMP.jl @@ -2,78 +2,82 @@ function test_JuMP() for f in LIST_OF_PROBLEMS @testset "$(f)" verbose=VERBOSE begin - grid_size = metadata(f)[:grid_size] + try + grid_size = metadata(f)[:grid_size] - # do we keep or remove the problem from the list - keep_problem = true + # do we keep or remove the problem from the list + keep_problem = true - # - DEBUG && println("\n", "┌─ ", string(f), " (JuMP)") - DEBUG && println("│") + # + DEBUG && println("\n", "┌─ ", string(f), " (JuMP)") + DEBUG && println("│") - # Set up the model - nlp = OptimalControlProblems.eval(f)(JuMPBackend(); grid_size=grid_size) - set_optimizer(nlp, Ipopt.Optimizer) - set_silent(nlp) - set_optimizer_attribute(nlp, "tol", TOL) - set_optimizer_attribute(nlp, "max_iter", MAX_ITER) - set_optimizer_attribute(nlp, "mu_strategy", MU_STRATEGY) - set_optimizer_attribute(nlp, "linear_solver", "mumps") - set_optimizer_attribute(nlp, "max_wall_time", MAX_WALL_TIME) - set_optimizer_attribute(nlp, "sb", SB) + # Set up the model + nlp = OptimalControlProblems.eval(f)(JuMPBackend(); grid_size=grid_size) + set_optimizer(nlp, Ipopt.Optimizer) + set_silent(nlp) + set_optimizer_attribute(nlp, "tol", TOL) + set_optimizer_attribute(nlp, "max_iter", MAX_ITER) + set_optimizer_attribute(nlp, "mu_strategy", MU_STRATEGY) + set_optimizer_attribute(nlp, "linear_solver", "mumps") + set_optimizer_attribute(nlp, "max_wall_time", MAX_WALL_TIME) + set_optimizer_attribute(nlp, "sb", SB) - # check existence of required metadata - nlp_keys = keys(object_dictionary(nlp)) - @test :time_grid ∈ nlp_keys - @test :state_components ∈ nlp_keys - @test :costate_components ∈ nlp_keys - @test :control_components ∈ nlp_keys - @test :variable_components ∈ nlp_keys + # check existence of required metadata + nlp_keys = keys(object_dictionary(nlp)) + @test :time_grid ∈ nlp_keys + @test :state_components ∈ nlp_keys + @test :costate_components ∈ nlp_keys + @test :control_components ∈ nlp_keys + @test :variable_components ∈ nlp_keys - # check if the keys from the components names exists - components = [ - :state_components, - :costate_components, - :control_components, - :variable_components, - ] - for c in components - if !(isnothing(nlp[c])) - for e in nlp[c] - @test Symbol(e) ∈ nlp_keys + # check if the keys from the components names exists + components = [ + :state_components, + :costate_components, + :control_components, + :variable_components, + ] + for c in components + if !(isnothing(nlp[c])) + for e in nlp[c] + @test Symbol(e) ∈ nlp_keys + end end end - end - # Solve the model - print(" First solve: "); - @time optimize!(nlp) - print(" Second solve: "); - @time optimize!(nlp) + # Solve the model + print(" First solve: "); + @time optimize!(nlp) + print(" Second solve: "); + @time optimize!(nlp) - # Infos - DEBUG && println("│") - DEBUG && print( - "│ termination_status: ", - termination_status(nlp), - ", objective: ", - objective_value(nlp), - ", iterations: ", - barrier_iterations(nlp), - ) + # Infos + DEBUG && println("│") + DEBUG && print( + "│ termination_status: ", + termination_status(nlp), + ", objective: ", + objective_value(nlp), + ", iterations: ", + barrier_iterations(nlp), + ) - # Test - res = @my_test_broken termination_status(nlp) == MOI.LOCALLY_SOLVED - keep_problem = keep_problem && res - DEBUG && res && println(", \033[1;32mPass\033[0m") - DEBUG && !res && println(", \033[1;31mFail\033[0m") - DEBUG && println("│") - DEBUG && println("└─") + # Test + res = @my_test_broken termination_status(nlp) == MOI.LOCALLY_SOLVED + keep_problem = keep_problem && res + DEBUG && res && println(", \033[1;32mPass\033[0m") + DEBUG && !res && println(", \033[1;31mFail\033[0m") + DEBUG && println("│") + DEBUG && println("└─") - # do we keep or remove the problem from the list - if !keep_problem - global LIST_OF_PROBLEMS_FINAL - LIST_OF_PROBLEMS_FINAL = setdiff(LIST_OF_PROBLEMS_FINAL, [f]) + # do we keep or remove the problem from the list + if !keep_problem + global LIST_OF_PROBLEMS_FINAL + LIST_OF_PROBLEMS_FINAL = setdiff(LIST_OF_PROBLEMS_FINAL, [f]) + end + catch e + handle_solver_error(e, f) end end end diff --git a/test/test_OptimalControl.jl b/test/test_OptimalControl.jl index 58fb5c94..65bdd880 100644 --- a/test/test_OptimalControl.jl +++ b/test/test_OptimalControl.jl @@ -11,50 +11,54 @@ function test_OptimalControl() for f in LIST_OF_PROBLEMS @testset "$(f)" verbose=VERBOSE begin - grid_size = metadata(f)[:grid_size] - - # do we keep or remove the problem from the list - keep_problem = true - - # - DEBUG && println("\n", "┌─ ", string(f), " (OptimalControl)") - DEBUG && println("│") - - # Set up the model - docp = OptimalControlProblems.eval(f)( - OptimalControlBackend(); grid_size=grid_size - ) - nlp = nlp_model(docp) - - # Solve the model - print(" First solve: "); - @time sol = NLPModelsIpopt.ipopt(nlp; options_ipopt...) - print(" Second solve: "); - @time sol = NLPModelsIpopt.ipopt(nlp; options_ipopt...) - - # Infos - DEBUG && println("│") - DEBUG && print( - "│ sol.status: ", - sol.status, - ", objective: ", - sol.objective, - ", iterations: ", - sol.iter, - ) - - # Test - res = @my_test_broken (sol.status == :first_order || sol.status == :acceptable) - keep_problem = keep_problem && res - DEBUG && res && println(", \033[1;32mPass\033[0m") - DEBUG && !res && println(", \033[1;31mFail\033[0m") - DEBUG && println("│") - DEBUG && println("└─") - - # do we keep or remove the problem from the list - if !keep_problem - global LIST_OF_PROBLEMS_FINAL - LIST_OF_PROBLEMS_FINAL = setdiff(LIST_OF_PROBLEMS_FINAL, [f]) + try + grid_size = metadata(f)[:grid_size] + + # do we keep or remove the problem from the list + keep_problem = true + + # + DEBUG && println("\n", "┌─ ", string(f), " (OptimalControl)") + DEBUG && println("│") + + # Set up the model + docp = OptimalControlProblems.eval(f)( + OptimalControlBackend(); grid_size=grid_size + ) + nlp = nlp_model(docp) + + # Solve the model + print(" First solve: "); + @time sol = NLPModelsIpopt.ipopt(nlp; options_ipopt...) + print(" Second solve: "); + @time sol = NLPModelsIpopt.ipopt(nlp; options_ipopt...) + + # Infos + DEBUG && println("│") + DEBUG && print( + "│ sol.status: ", + sol.status, + ", objective: ", + sol.objective, + ", iterations: ", + sol.iter, + ) + + # Test + res = @my_test_broken (sol.status == :first_order || sol.status == :acceptable) + keep_problem = keep_problem && res + DEBUG && res && println(", \033[1;32mPass\033[0m") + DEBUG && !res && println(", \033[1;31mFail\033[0m") + DEBUG && println("│") + DEBUG && println("└─") + + # do we keep or remove the problem from the list + if !keep_problem + global LIST_OF_PROBLEMS_FINAL + LIST_OF_PROBLEMS_FINAL = setdiff(LIST_OF_PROBLEMS_FINAL, [f]) + end + catch e + handle_solver_error(e, f) end end end diff --git a/test/test_OptimalControl_s.jl b/test/test_OptimalControl_s.jl index f6f2c567..07777fd3 100644 --- a/test/test_OptimalControl_s.jl +++ b/test/test_OptimalControl_s.jl @@ -12,50 +12,54 @@ function test_OptimalControl_s() for f in LIST_OF_PROBLEMS @testset "$(f)" verbose=VERBOSE begin - grid_size = metadata(f)[:grid_size] - - # do we keep or remove the problem from the list - keep_problem = true - - # - DEBUG && println("\n", "┌─ ", string(f), " (OptimalControl_s)") - DEBUG && println("│") - - # Set up the model - docp = OptimalControlProblems.eval(Symbol(f, :_s))( - OptimalControlBackend(), :madnlp, :exa; grid_size=grid_size - ) - nlp = nlp_model(docp) - - # Solve the model - print(" First solve: "); - @time sol = madnlp(nlp; options_madnlp...) - print(" Second solve: "); - @time sol = madnlp(nlp; options_madnlp...) - - # Infos - DEBUG && println("│") - DEBUG && print( - "│ sol.status: ", - sol.status, - ", objective: ", - sol.objective, - ", iterations: ", - sol.iter, - ) - - # Test - res = @my_test_broken (sol.status == MadNLP.SOLVE_SUCCEEDED) #:first_order || sol.status == :acceptable) - keep_problem = keep_problem && res - DEBUG && res && println(", \033[1;32mPass\033[0m") - DEBUG && !res && println(", \033[1;31mFail\033[0m") - DEBUG && println("│") - DEBUG && println("└─") - - # do we keep or remove the problem from the list - if !keep_problem - global LIST_OF_PROBLEMS_FINAL - LIST_OF_PROBLEMS_FINAL = setdiff(LIST_OF_PROBLEMS_FINAL, [f]) + try + grid_size = metadata(f)[:grid_size] + + # do we keep or remove the problem from the list + keep_problem = true + + # + DEBUG && println("\n", "┌─ ", string(f), " (OptimalControl_s)") + DEBUG && println("│") + + # Set up the model + docp = OptimalControlProblems.eval(Symbol(f, :_s))( + OptimalControlBackend(), :madnlp, :exa; grid_size=grid_size + ) + nlp = nlp_model(docp) + + # Solve the model + print(" First solve: "); + @time sol = madnlp(nlp; options_madnlp...) + print(" Second solve: "); + @time sol = madnlp(nlp; options_madnlp...) + + # Infos + DEBUG && println("│") + DEBUG && print( + "│ sol.status: ", + sol.status, + ", objective: ", + sol.objective, + ", iterations: ", + sol.iter, + ) + + # Test + res = @my_test_broken (sol.status == MadNLP.SOLVE_SUCCEEDED) #:first_order || sol.status == :acceptable) + keep_problem = keep_problem && res + DEBUG && res && println(", \033[1;32mPass\033[0m") + DEBUG && !res && println(", \033[1;31mFail\033[0m") + DEBUG && println("│") + DEBUG && println("└─") + + # do we keep or remove the problem from the list + if !keep_problem + global LIST_OF_PROBLEMS_FINAL + LIST_OF_PROBLEMS_FINAL = setdiff(LIST_OF_PROBLEMS_FINAL, [f]) + end + catch e + handle_solver_error(e, f) end end end diff --git a/test/test_quick.jl b/test/test_quick.jl index 0b3bb3cb..f1070715 100644 --- a/test/test_quick.jl +++ b/test/test_quick.jl @@ -32,91 +32,95 @@ function test_quick() grid_size = metadata(f)[:grid_size] @testset "$(string(f)) (objective)" verbose=VERBOSE begin - DEBUG && println("\n", "┌─ ", string(f)) - DEBUG && println("│") - - ############### JuMP ############### - nlp = OptimalControlProblems.eval(f)(JuMPBackend(); grid_size=grid_size) - set_optimizer(nlp, Ipopt.Optimizer) - set_silent(nlp) - set_optimizer_attribute(nlp, "tol", TOL) - set_optimizer_attribute(nlp, "max_iter", MAX_ITER) - set_optimizer_attribute(nlp, "mu_strategy", MU_STRATEGY) - set_optimizer_attribute(nlp, "linear_solver", "mumps") - set_optimizer_attribute(nlp, "max_wall_time", MAX_WALL_TIME) - set_optimizer_attribute(nlp, "sb", SB) - optimize!(nlp) - o_jp = objective_value(nlp) - - ########## OptimalControl ########## - docp = OptimalControlProblems.eval(f)( - OptimalControlBackend(); grid_size=grid_size - ) - nlp = nlp_model(docp) - nlp_sol = NLPModelsIpopt.ipopt(nlp; kwargs_ipopt...) - sol = build_OCP_solution(docp, nlp_sol) - o_oc = objective(sol) - - ########## OptimalControl_s ########## - docp = OptimalControlProblems.eval(Symbol(f, :_s))( - OptimalControlBackend(), :madnlp, :exa; grid_size=grid_size - ) - nlp = nlp_model(docp) - ocp = ocp_model(docp) - nlp_sol = madnlp(nlp; kwargs_madnlp...) - sol = build_OCP_solution(docp, nlp_sol) - o_os = objective(sol) - - ############### TEST ############### - DEBUG && println("├─ objective") - DEBUG && println("│") - DEBUG && println("│ o_jp = ", o_jp) - DEBUG && println("│ o_oc = ", o_oc) - DEBUG && println("│ o_os = ", o_os) - DEBUG && println("│") - - # comparison JuMP and OptimalControl - A = o_oc - B = o_jp - - o_di = abs(A-B) - o_bd = max(0.5*(abs(A) + abs(B))*ε_rel_objective, ε_abs_objective) - max_r_err = max(max_r_err, o_di/(0.5*(abs(A) + abs(B)))) - - DEBUG && println("│ JuMP vs OptimalControl") - DEBUG && println("│") - DEBUG && println("│ r_err = ", o_di/(0.5*(abs(A) + abs(B)))) - DEBUG && println("│ a_err = ", o_di) - DEBUG && println("│ bound = ", o_bd) - - res = @my_test_broken o_di < o_bd - - DEBUG && res && println("│ \033[1;32mTest Passed\033[0m") - DEBUG && !res && println("│ \033[1;31mTest Failed\033[0m") - DEBUG && println("│") - - # comparison JuMP and OptimalControl_s - A = o_os - B = o_jp - - o_di = abs(A-B) - o_bd = max(0.5*(abs(A) + abs(B))*ε_rel_objective, ε_abs_objective) - max_r_err = max(max_r_err, o_di/(0.5*(abs(A) + abs(B)))) - - DEBUG && println("│ JuMP vs OptimalControl_s") - DEBUG && println("│") - DEBUG && println("│ r_err = ", o_di/(0.5*(abs(A) + abs(B)))) - DEBUG && println("│ a_err = ", o_di) - DEBUG && println("│ bound = ", o_bd) - - res = @my_test_broken o_di < o_bd - - DEBUG && res && println("│ \033[1;32mTest Passed\033[0m") - DEBUG && !res && println("│ \033[1;31mTest Failed\033[0m") - DEBUG && println("│") - - # - DEBUG && println("└─") + try + DEBUG && println("\n", "┌─ ", string(f)) + DEBUG && println("│") + + ############### JuMP ############### + nlp = OptimalControlProblems.eval(f)(JuMPBackend(); grid_size=grid_size) + set_optimizer(nlp, Ipopt.Optimizer) + set_silent(nlp) + set_optimizer_attribute(nlp, "tol", TOL) + set_optimizer_attribute(nlp, "max_iter", MAX_ITER) + set_optimizer_attribute(nlp, "mu_strategy", MU_STRATEGY) + set_optimizer_attribute(nlp, "linear_solver", "mumps") + set_optimizer_attribute(nlp, "max_wall_time", MAX_WALL_TIME) + set_optimizer_attribute(nlp, "sb", SB) + optimize!(nlp) + o_jp = objective_value(nlp) + + ########## OptimalControl ########## + docp = OptimalControlProblems.eval(f)( + OptimalControlBackend(); grid_size=grid_size + ) + nlp = nlp_model(docp) + nlp_sol = NLPModelsIpopt.ipopt(nlp; kwargs_ipopt...) + sol = build_OCP_solution(docp, nlp_sol) + o_oc = objective(sol) + + ########## OptimalControl_s ########## + docp = OptimalControlProblems.eval(Symbol(f, :_s))( + OptimalControlBackend(), :madnlp, :exa; grid_size=grid_size + ) + nlp = nlp_model(docp) + ocp = ocp_model(docp) + nlp_sol = madnlp(nlp; kwargs_madnlp...) + sol = build_OCP_solution(docp, nlp_sol) + o_os = objective(sol) + + ############### TEST ############### + DEBUG && println("├─ objective") + DEBUG && println("│") + DEBUG && println("│ o_jp = ", o_jp) + DEBUG && println("│ o_oc = ", o_oc) + DEBUG && println("│ o_os = ", o_os) + DEBUG && println("│") + + # comparison JuMP and OptimalControl + A = o_oc + B = o_jp + + o_di = abs(A-B) + o_bd = max(0.5*(abs(A) + abs(B))*ε_rel_objective, ε_abs_objective) + max_r_err = max(max_r_err, o_di/(0.5*(abs(A) + abs(B)))) + + DEBUG && println("│ JuMP vs OptimalControl") + DEBUG && println("│") + DEBUG && println("│ r_err = ", o_di/(0.5*(abs(A) + abs(B)))) + DEBUG && println("│ a_err = ", o_di) + DEBUG && println("│ bound = ", o_bd) + + res = @my_test_broken o_di < o_bd + + DEBUG && res && println("│ \033[1;32mTest Passed\033[0m") + DEBUG && !res && println("│ \033[1;31mTest Failed\033[0m") + DEBUG && println("│") + + # comparison JuMP and OptimalControl_s + A = o_os + B = o_jp + + o_di = abs(A-B) + o_bd = max(0.5*(abs(A) + abs(B))*ε_rel_objective, ε_abs_objective) + max_r_err = max(max_r_err, o_di/(0.5*(abs(A) + abs(B)))) + + DEBUG && println("│ JuMP vs OptimalControl_s") + DEBUG && println("│") + DEBUG && println("│ r_err = ", o_di/(0.5*(abs(A) + abs(B)))) + DEBUG && println("│ a_err = ", o_di) + DEBUG && println("│ bound = ", o_bd) + + res = @my_test_broken o_di < o_bd + + DEBUG && res && println("│ \033[1;32mTest Passed\033[0m") + DEBUG && !res && println("│ \033[1;31mTest Failed\033[0m") + DEBUG && println("│") + + # + DEBUG && println("└─") + catch e + handle_solver_error(e, f) + end end end diff --git a/test/utils.jl b/test/utils.jl index e85cdb4e..43fd9782 100644 --- a/test/utils.jl +++ b/test/utils.jl @@ -56,6 +56,50 @@ macro my_test_broken(e) end) end +""" +handle_solver_error(e::Exception, problem_name::Symbol) + +Handle solver exceptions during tests. Marks certain expected exceptions (like DomainError) +as broken tests, while rethrowing unexpected exceptions. + +# Arguments + +- `e::Exception`: The exception that was caught. +- `problem_name::Symbol`: The name of the problem being tested. + +# Returns + +- `::Nothing`: Marks the test as broken for expected exceptions, or rethrows for unexpected ones. + +# Example + +```julia-repl +julia> try + # solver code that might throw DomainError + catch e + handle_solver_error(e, :my_problem) + end +``` +""" +function handle_solver_error(e::Exception, problem_name::Symbol) + # List of exception types that should be marked as broken instead of errored + expected_solver_errors = (DomainError,) + + if isa(e, expected_solver_errors) + # Mark as broken test + @test false broken=true + DEBUG && println("│ \033[1;33mSolver error (broken): ", typeof(e), "\033[0m") + DEBUG && println("└─") + + # Remove from final list + global LIST_OF_PROBLEMS_FINAL + LIST_OF_PROBLEMS_FINAL = setdiff(LIST_OF_PROBLEMS_FINAL, [problem_name]) + else + # Unexpected error: rethrow to make the test fail properly + rethrow(e) + end +end + """ comparison(; max_iter, test_name) @@ -263,6 +307,7 @@ function comparison(; max_iter, test_name) grid_size = metadata(f)[:grid_size] # get default number of steps @testset "$(string(f)) ($(string(test_name)))" verbose=VERBOSE begin + try DEBUG && println("\n┌─ ", string(f), " (", string(test_name), ")") DEBUG && println("│") @@ -636,6 +681,10 @@ function comparison(; max_iter, test_name) # save figure savefig(plt, joinpath(figdir, "$f" * ".pdf")) + + catch e + handle_solver_error(e, f) + end end# end testset end # end for end