Skip to content

Commit

Permalink
prepare v0.9.0 (todo: comment local init and its export) (#140)
Browse files Browse the repository at this point in the history
  • Loading branch information
PierreMartinon authored Jul 2, 2024
1 parent 2e7e241 commit d7c21a9
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 78 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "CTDirect"
uuid = "790bbbee-bee9-49ee-8912-a9de031322d5"
authors = ["Olivier Cots <[email protected]>"]
version = "0.8.0"
version = "0.9.0"

[deps]
ADNLPModels = "54578032-b7ea-4c30-94aa-7cbd1cce6c9a"
Expand Down
2 changes: 1 addition & 1 deletion ext/CTSolveExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ function CommonSolve.solve(ocp::OptimalControlModel,
# build discretized OCP
docp = directTranscription(ocp, description, init=init, grid_size=grid_size, time_grid=time_grid)

# solve DOCP
# solve DOCP (NB. init is already embedded in docp)
docp_solution = solve(docp, display=display, print_level=print_level, mu_strategy=mu_strategy, linear_solver=linear_solver; kwargs...)

# build and return OCP solution
Expand Down
3 changes: 1 addition & 2 deletions src/CTDirect.jl
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ export export_OCP_solution
export read_OCP_solution
export OCP_Solution_discrete

export _OptimalControlInit #temp

export _OptimalControlInit #temp, later from CTBase

end
6 changes: 3 additions & 3 deletions src/solve.jl
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
# CTDirect interface

# available methods by order of preference: from top to bottom
algorithmes = ()
algorithmes = add(algorithmes, (:adnlp, :ipopt))
algorithms = ()
algorithms = add(algorithms, (:adnlp, :ipopt))

"""
$(TYPEDSIGNATURES)
Return the list of available methods to solve the optimal control problem.
"""
function available_methods()::Tuple{Tuple{Vararg{Symbol}}}
return algorithmes
return algorithms
end


Expand Down
200 changes: 129 additions & 71 deletions test/suite/initial_guess.jl
Original file line number Diff line number Diff line change
@@ -1,104 +1,162 @@
# goddard max final altitude (all constraint types formulation)
println("Test: initial guess options")
sol0 = solve(goddard, print_level=0)
println("Test: initial guess options\n")

# default init
@testset verbose = true showtiming = true ":default_init" begin
sol = solve(goddard, print_level=0)
@test sol.objective 1.0125 rtol=1e-2
# use 0 iterations to check initial guess, >0 to check cv
maxiter = 0

# test functions
function check_xf(sol, xf)
return xf == sol.state(sol.times[end])
end
function check_uf(sol, uf)
return uf == sol.control(sol.times[end])
end
function check_v(sol, v)
return v == sol.variable
end

# reference solution
@def ocp begin
tf R, variable
t [ 0, tf ], time
x R², state
u R, control
-1 u(t) 1
x(0) == [ 0, 0 ]
x(tf) == [ 1, 0 ]
0.05 tf Inf
(t) == [ x₂(t), u(t) ]
tf min
end
sol0 = solve(ocp, print_level=0)

# constant initial guess
x_const = [1.05, 0.2, 0.8]
x_const = [0.5, 0.2]
u_const = 0.5
v_const = 0.15

@testset verbose = true showtiming = true ":constant_init_x :compact" begin
sol = solve(goddard, print_level=0, init=(state=x_const,))
@test sol.objective 1.0125 rtol=1e-2
end
@testset verbose = true showtiming = true ":constant_init_u :compact" begin
sol = solve(goddard, print_level=0, init=(control=u_const,))
@test sol.objective 1.0125 rtol=1e-2
end
@testset verbose = true showtiming = true ":constant_init_v :compact" begin
sol = solve(goddard, print_level=0, init=(variable=v_const,))
@test sol.objective 1.0125 rtol=1e-2
end
@testset verbose = true showtiming = true ":constant_init_xu :compact" begin
sol = solve(goddard, print_level=0, init=(state=x_const, control=u_const))
@test sol.objective 1.0125 rtol=1e-2
end
@testset verbose = true showtiming = true ":constant_init_xv :compact" begin
sol = solve(goddard, print_level=0, init=(state=x_const, variable=v_const))
@test sol.objective 1.0125 rtol=1e-2
end
@testset verbose = true showtiming = true ":constant_init_uv :compact" begin
sol = solve(goddard, print_level=0, init=(control=u_const, variable=v_const))
@test sol.objective 1.0125 rtol=1e-2
end
# functional initial guess
x_func = t->[t^2, sqrt(t)]
u_func = t->(cos(10*t)+1)*0.5

# interpolated initial gues
x_vec = [[0, 0], [1, 2], [5, -1]]
x_matrix = [0 0; 1 2; 5 -1]
u_vec = [0, 0.3, .1]


@testset verbose = true showtiming = true ":constant_init_xuv :compact" begin
sol = solve(goddard, print_level=0, init=(state=x_const, control=u_const, variable=v_const))
@test sol.objective 1.0125 rtol=1e-2
#################################################
# 1 Pass initial guess to all-in-one solve call

# 1.a default initial guess
@testset verbose = true showtiming = true ":default_init" begin
sol = solve(ocp, print_level=0, max_iter=maxiter)
@test(check_xf(sol, [0.1, 0.1]) && check_uf(sol, 0.1) && check_v(sol, 0.1))
end

# functional initial guess
x_func = t->[1+t^2, sqrt(t), 1-t]
u_func = t->(cos(t)+1)*0.5
# 1.b constant initial guess
@testset verbose = true showtiming = true ":constant_x" begin
sol = solve(ocp, print_level=0, init=(state=x_const,), max_iter=maxiter)
@test(check_xf(sol, x_const))
end
@testset verbose = true showtiming = true ":constant_u" begin
sol = solve(ocp, print_level=0, init=(control=u_const,), max_iter=maxiter)
@test(check_uf(sol, u_const))
end
@testset verbose = true showtiming = true ":constant_v" begin
sol = solve(ocp, print_level=0, init=(variable=v_const,), max_iter=maxiter)
@test(check_v(sol, v_const))
end
@testset verbose = true showtiming = true ":constant_xu" begin
sol = solve(ocp, print_level=0, init=(state=x_const, control=u_const), max_iter=maxiter)
@test(check_xf(sol, x_const) && check_uf(sol, u_const))
end
@testset verbose = true showtiming = true ":constant_xv" begin
sol = solve(ocp, print_level=0, init=(state=x_const, variable=v_const), max_iter=maxiter)
@test(check_xf(sol, x_const) && check_v(sol, v_const))
end
@testset verbose = true showtiming = true ":constant_uv" begin
sol = solve(ocp, print_level=0, init=(control=u_const, variable=v_const), max_iter=maxiter)
@test(check_uf(sol, u_const) && check_v(sol, v_const))
end
@testset verbose = true showtiming = true ":constant_xuv" begin
sol = solve(ocp, print_level=0, init=(state=x_const, control=u_const, variable=v_const), max_iter=maxiter)
@test(check_xf(sol, x_const) && check_uf(sol, u_const) && check_v(sol, v_const))
end

@testset verbose = true showtiming = true ":functional_init_x :compact" begin
sol = solve(goddard, print_level=0, init=(state=x_func,))
@test sol.objective 1.0125 rtol=1e-2
# 1. functional initial guess
@testset verbose = true showtiming = true ":functional_x" begin
sol = solve(ocp, print_level=0, init=(state=x_func,), max_iter=maxiter)
@test(check_xf(sol, x_func(sol.times[end])))
end
@testset verbose = true showtiming = true ":functional_init_u :compact" begin
sol = solve(goddard, print_level=0, init=(control=u_func,))
@test sol.objective 1.0125 rtol=1e-2
@testset verbose = true showtiming = true ":functional_u" begin
sol = solve(ocp, print_level=0, init=(control=u_func,), max_iter=maxiter)
@test(check_uf(sol, u_func(sol.times[end])))
end

@testset verbose = true showtiming = true ":functional_init_xu :compact" begin
sol = solve(goddard, print_level=0, init=(state=x_func, control=u_func))
@test sol.objective 1.0125 rtol=1e-2
@testset verbose = true showtiming = true ":functional_xu" begin
sol = solve(ocp, print_level=0, init=(state=x_func, control=u_func), max_iter=maxiter)
@test(check_xf(sol, x_func(sol.times[end])) && check_uf(sol, u_func(sol.times[end])))
end

@testset verbose = true showtiming = true ":mixed_init :compact" begin
sol = solve(goddard, print_level=0, init=(state=x_func, control=u_const))
@test sol.objective 1.0125 rtol=1e-2
# 1.d interpolated initial guess
t_vec = [0, .1, v_const]
@testset verbose = true showtiming = true ":vector_txu :constant_v" begin
sol = solve(ocp, print_level=0, init=(time=t_vec, state=x_vec, control=u_vec, variable=v_const), max_iter=maxiter)
@test(check_xf(sol, x_vec[end]) && check_uf(sol, u_vec[end]) && check_v(sol, v_const))
end
t_matrix = [0 .1 v_const]
@testset verbose = true showtiming = true ":matrix_t :vector_xu :constant_v" begin
sol = solve(ocp, print_level=0, init=(time=t_matrix, state=x_vec, control=u_vec, variable=v_const), max_iter=maxiter)
@test(check_xf(sol, x_vec[end]) && check_uf(sol, u_vec[end]) && check_v(sol, v_const))
end
@testset verbose = true showtiming = true ":matrix_x :vector_tu :constant_v" begin
sol = solve(ocp, print_level=0, init=(time=t_vec, state=x_matrix, control=u_vec, variable=v_const), max_iter=maxiter)
@test(check_xf(sol, x_vec[end]) && check_uf(sol, u_vec[end]) && check_v(sol, v_const))
end

@testset verbose = true showtiming = true ":warm_start :compact" begin
sol = solve(goddard, print_level=0, init=sol0)
@test sol.objective 1.0125 rtol=1e-2
# 1.e mixed initial guess
@testset verbose = true showtiming = true ":vector_tx :functional_u :constant_v" begin
sol = solve(ocp, print_level=0, init=(time=t_vec, state=x_vec, control=u_func, variable=v_const), max_iter=maxiter)
@test(check_xf(sol, x_vec[end]) && check_uf(sol, u_func(sol.times[end])) && check_v(sol, v_const))
end

# set initial guess in DOCP
docp = directTranscription(goddard)
# 1.f warm start
@testset verbose = true showtiming = true ":warm_start" begin
sol = solve(ocp, print_level=0, init=sol0, max_iter=maxiter)
@test(check_xf(sol, sol.state(sol.times[end])) && check_uf(sol, sol.control(sol.times[end])) && check_v(sol, sol.variable))
end

@testset verbose = true showtiming = true ":DOCPInit_mixed :compact" begin
setInitialGuess(docp, (state=x_func, control=u_const))
dsol = solve(docp, print_level=0)
#################################################
# 2 Setting the initial guess at the DOCP level
docp = directTranscription(ocp)
# mixed init
setInitialGuess(docp, (time=t_vec, state=x_vec, control=u_func, variable=v_const))
dsol = solve(docp, print_level=0, max_iter=maxiter)
@testset verbose = true showtiming = true ":docp_mixed_init" begin
sol = OCPSolutionFromDOCP(docp, dsol)
@test sol.objective 1.0125 rtol=1e-2
@test(check_xf(sol, x_vec[end]) && check_uf(sol, u_func(sol.times[end])) && check_v(sol, v_const))
end

@testset verbose = true showtiming = true ":DOCPInit_warm_start :compact" begin
# warm start
@testset verbose = true showtiming = true ":docp_warm_start" begin
setInitialGuess(docp, sol0)
dsol = solve(docp, print_level=0)
dsol = solve(docp, print_level=0, max_iter=maxiter)
sol = OCPSolutionFromDOCP(docp, dsol)
@test sol.objective 1.0125 rtol=1e-2
@test(check_xf(sol, sol.state(sol.times[end])) && check_uf(sol, sol.control(sol.times[end])) && check_v(sol, sol.variable))
end

# pass initial guess to solve
#################################################
# 3 Passing the initial guess to solve call
setInitialGuess(docp, ()) # reset init in docp

@testset verbose = true showtiming = true ":solve_mixed_init :compact" begin
dsol = solve(docp, init=(state=x_func, control=u_const), print_level=0)
# mixed init
@testset verbose = true showtiming = true ":docp_solve_mixed_init" begin
dsol = solve(docp, init=(time=t_vec, state=x_vec, control=u_func, variable=v_const), print_level=0, max_iter=maxiter)
sol = OCPSolutionFromDOCP(docp, dsol)
@test sol.objective 1.0125 rtol=1e-2
@test(check_xf(sol, x_vec[end]) && check_uf(sol, u_func(sol.times[end])) && check_v(sol, v_const))
end

@testset verbose = true showtiming = true ":solve_warm_start :compact" begin
dsol = solve(docp, init=sol0, print_level=0)
# warm start
@testset verbose = true showtiming = true ":docp_solve_warm_start" begin
dsol = solve(docp, init=sol0, print_level=0, max_iter=maxiter)
sol = OCPSolutionFromDOCP(docp, dsol)
@test sol.objective 1.0125 rtol=1e-2
@test(check_xf(sol, sol.state(sol.times[end])) && check_uf(sol, sol.control(sol.times[end])) && check_v(sol, sol.variable))
end

0 comments on commit d7c21a9

Please sign in to comment.