From 7c76c71fc387177bdc048c0f5a786387cdf8abde Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Caillau Date: Fri, 9 Aug 2024 18:52:02 +0200 Subject: [PATCH 01/33] first commit --- src/onepass.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/onepass.jl b/src/onepass.jl index d3a1aaed..0e561537 100644 --- a/src/onepass.jl +++ b/src/onepass.jl @@ -489,4 +489,4 @@ macro def(ocp, e, log=false) catch ex :( throw($ex) ) # can be caught by user end -end +end \ No newline at end of file From 968ae6e888dc80e18011b057a6033e5ab23f0018 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Caillau Date: Thu, 29 Aug 2024 20:40:00 +0200 Subject: [PATCH 02/33] __wrap(code, ...) everywhere --- src/onepass.jl | 44 ++++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/src/onepass.jl b/src/onepass.jl index 0e561537..d8e8b434 100644 --- a/src/onepass.jl +++ b/src/onepass.jl @@ -84,7 +84,7 @@ parse!(p, ocp, e; log=false) = begin :( [$names] ∈ R^$n, state ) => p_state!(p, ocp, a, n; components_names=names, log) :( ($names) ∈ R^$m, control ) => p_control!(p, ocp, a, m; components_names=names, log) :( [$names] ∈ R^$m, control ) => p_control!(p, ocp, a, m; components_names=names, log) - _ => p_alias!(p, ocp, a, e1; log) # alias + _ => p_alias!(p, ocp, a, e1; log) # alias end # variable :( $v ∈ R^$q, variable ) => p_variable!(p, ocp, v, q; log) @@ -172,13 +172,14 @@ p_variable!(p, ocp, v, q; components_names=nothing, log=false) = begin for i ∈ 1:qq p.aliases[Symbol(v, ctindices(i))] = :( $v[$i] ) end for i ∈ 1:9 p.aliases[Symbol(v, ctupperscripts(i))] = :( $v^$i ) end if (isnothing(components_names)) - __wrap(:( variable!($ocp, $q, $vv) ), p.lnum, p.line) + code = :( variable!($ocp, $q, $vv) ) else qq==length(components_names.args) || return __throw("the number of variable components must be $qq", p.lnum, p.line) for i ∈ 1:qq p.aliases[components_names.args[i]] = :( $v[$i] ) end ss = QuoteNode(string.(components_names.args)) - __wrap(:( variable!($ocp, $q, $vv, $ss) ), p.lnum, p.line) + code = :( variable!($ocp, $q, $vv, $ss) ) end + return __wrap(code, p.lnum, p.line) end p_alias!(p, ocp, a, e; log=false) = begin @@ -188,7 +189,8 @@ p_alias!(p, ocp, a, e; log=false) = begin ee = QuoteNode(e) for i ∈ 1:9 p.aliases[Symbol(a, ctupperscripts(i))] = :( $a^$i ) end p.aliases[a] = e - __wrap(:( LineNumberNode(0, "alias: " * string($aa) * " = " * string($ee)) ), p.lnum, p.line) + code = :( LineNumberNode(0, "alias: " * string($aa) * " = " * string($ee)) ) + return __wrap(code, p.lnum, p.line) end p_time!(p, ocp, t, t0, tf; log=false) = begin @@ -222,7 +224,7 @@ p_time!(p, ocp, t, t0, tf; log=false) = begin _ => return __throw("bad time declaration", p.lnum, p.line) end end - __wrap(code, p.lnum, p.line) + return __wrap(code, p.lnum, p.line) end p_state!(p, ocp, x, n; components_names=nothing, log=false) = begin @@ -235,13 +237,14 @@ p_state!(p, ocp, x, n; components_names=nothing, log=false) = begin for i ∈ 1:9 p.aliases[Symbol(x, ctupperscripts(i))] = :( $x^$i ) end p.aliases[Symbol(Unicode.normalize(string(x,"̇")))] = :( ∂($x) ) if (isnothing(components_names)) - __wrap(:( state!($ocp, $n, $xx) ), p.lnum, p.line) + code = :( state!($ocp, $n, $xx) ) else nn==length(components_names.args) || return __throw("the number of state components must be $nn", p.lnum, p.line) for i ∈ 1:nn p.aliases[components_names.args[i]] = :( $x[$i] ) end ss = QuoteNode(string.(components_names.args)) - __wrap(:( state!($ocp, $n, $xx, $ss) ), p.lnum, p.line) + code = :( state!($ocp, $n, $xx, $ss) ) end + return __wrap(code, p.lnum, p.line) end p_control!(p, ocp, u, m; components_names=nothing, log=false) = begin @@ -253,13 +256,14 @@ p_control!(p, ocp, u, m; components_names=nothing, log=false) = begin for i ∈ 1:mm p.aliases[Symbol(u, ctindices(i))] = :( $u[$i] ) end for i ∈ 1:9 p.aliases[Symbol(u, ctupperscripts(i))] = :( $u^$i ) end if (isnothing(components_names)) - __wrap(:( control!($ocp, $m, $uu) ), p.lnum, p.line) + code = :( control!($ocp, $m, $uu) ) else mm==length(components_names.args) || return __throw("the number of control components must be $mm", p.lnum, p.line) for i ∈ 1:mm p.aliases[components_names.args[i]] = :( $u[$i] ) end ss = QuoteNode(string.(components_names.args)) - __wrap(:( control!($ocp, $m, $uu, $ss) ), p.lnum, p.line) + code = :( control!($ocp, $m, $uu, $ss) ) end + return __wrap(code, p.lnum, p.line) end p_constraint!(p, ocp, e1, e2, e3, label=gensym(); log=false) = begin @@ -335,7 +339,7 @@ p_constraint!(p, ocp, e1, e2, e3, label=gensym(); log=false) = begin end end _ => return __throw("bad constraint declaration", p.lnum, p.line) end - __wrap(code, p.lnum, p.line) + return __wrap(code, p.lnum, p.line) end p_dynamics!(p, ocp, x, t, e, label=nothing; log=false) = begin @@ -353,12 +357,13 @@ p_dynamics!(p, ocp, x, t, e, label=nothing; log=false) = begin p.t_dep = p.t_dep || has(e, t) gs = gensym() args = [ ]; __t_dep(p) && push!(args, p.t); push!(args, xt, ut); __v_dep(p) && push!(args, p.v) - __wrap(quote + code = quote function $gs($(args...)) $e end dynamics!($ocp, $gs) - end, p.lnum, p.line) + end + return __wrap(code, p.lnum, p.line) end p_lagrange!(p, ocp, e, type; log=false) = begin @@ -373,12 +378,13 @@ p_lagrange!(p, ocp, e, type; log=false) = begin ttype = QuoteNode(type) gs = gensym() args = [ ]; __t_dep(p) && push!(args, p.t); push!(args, xt, ut); __v_dep(p) && push!(args, p.v) - __wrap(quote + code = quote function $gs($(args...)) $e end objective!($ocp, :lagrange, $gs, $ttype) - end, p.lnum, p.line) + end + return __wrap(code, p.lnum, p.line) end p_mayer!(p, ocp, e, type; log=false) = begin @@ -394,12 +400,13 @@ p_mayer!(p, ocp, e, type; log=false) = begin e = replace_call(e, p.x, p.tf, xf) ttype = QuoteNode(type) args = [ x0, xf ]; __v_dep(p) && push!(args, p.v) - __wrap(quote + code = quote function $gs($(args...)) $e end objective!($ocp, :mayer, $gs, $ttype) - end, p.lnum, p.line) + end + return __wrap(code, p.lnum, p.line) end p_bolza!(p, ocp, e1, e2, type; log=false) = begin @@ -422,7 +429,7 @@ p_bolza!(p, ocp, e1, e2, type; log=false) = begin p.t_dep = p.t_dep || has(e2, p.t) args2 = [ ]; __t_dep(p) && push!(args2, p.t); push!(args2, xt, ut); __v_dep(p) && push!(args2, p.v) ttype = QuoteNode(type) - __wrap(quote + code = quote function $gs1($(args1...)) $e1 end @@ -430,7 +437,8 @@ p_bolza!(p, ocp, e1, e2, type; log=false) = begin $e2 end objective!($ocp, :bolza, $gs1, $gs2, $ttype) - end, p.lnum, p.line) + end + return __wrap(code, p.lnum, p.line) end """ From 2341da6fd108a529d99f5226676cd7f3669836c7 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Caillau Date: Fri, 30 Aug 2024 23:12:52 +0200 Subject: [PATCH 03/33] added in_place info --- src/CTBase.jl | 9 ++++--- src/optimal_control_model-getters.jl | 7 ++++++ src/optimal_control_model-setters.jl | 6 +++-- src/optimal_control_model-type.jl | 1 + test/test_model.jl | 37 ++++++++++++++++++++++++++++ 5 files changed, 55 insertions(+), 5 deletions(-) diff --git a/src/CTBase.jl b/src/CTBase.jl index 426362b5..3a1517d6 100644 --- a/src/CTBase.jl +++ b/src/CTBase.jl @@ -26,7 +26,7 @@ import ForwardDiff using Interpolations: linear_interpolation, Line, Interpolations # for default interpolation using MLStyle # pattern matching using Parameters # @with_kw: to have default values in struct -using Printf # to print an Opt imalControlModel +using Printf # to print an OptimalControlModel using DataStructures # OrderedDict for aliases using Unicode # unicode primitives using PrettyTables # to print a table @@ -259,8 +259,11 @@ export Model export __OCPModel # redirection to Model to avoid confusion with other Model functions from other packages. Due to @def macro export variable!, time!, constraint!, dynamics!, objective!, state!, control!, remove_constraint!, model_expression! -export is_autonomous, is_fixed, is_time_independent, is_time_dependent, is_min, is_max +export is_autonomous, is_fixed +export is_time_independent, is_time_dependent +export is_min, is_max export is_variable_dependent, is_variable_independent +export is_in_place export nlp_constraints!, constraints, constraints_labels, constraint export has_free_final_time, has_free_initial_time, has_lagrange_cost, has_mayer_cost export dim_control_constraints, dim_state_constraints, dim_mixed_constraints, dim_path_constraints @@ -313,4 +316,4 @@ export @def export ct_repl, ct_repl_update_model isdefined(Base, :active_repl) && ct_repl() -end +end \ No newline at end of file diff --git a/src/optimal_control_model-getters.jl b/src/optimal_control_model-getters.jl index b7c74285..6b49cb70 100644 --- a/src/optimal_control_model-getters.jl +++ b/src/optimal_control_model-getters.jl @@ -570,6 +570,13 @@ is_variable_independent(ocp::OptimalControlModel) = !is_variable_dependent(ocp) """ $(TYPEDSIGNATURES) +Return `true` if functions defining the ocp are in-place. Return nothing if this information has not yet been set. +""" +is_in_place(ocp::OptimalControlModel) = ocp.in_place + +""" +$(TYPEDSIGNATURES) + Return `true` if the model has been defined with free initial time. """ has_free_initial_time(ocp::OptimalControlModel) = (typeof(initial_time(ocp)) == Index) diff --git a/src/optimal_control_model-setters.jl b/src/optimal_control_model-setters.jl index 0f8f3c99..e6fbd384 100644 --- a/src/optimal_control_model-setters.jl +++ b/src/optimal_control_model-setters.jl @@ -36,11 +36,13 @@ julia> ocp = Model(autonomous=false, variable=true) - If the time dependence of the model is defined as nonautonomous, then, the dynamics function, the lagrange cost and the path constraints must be defined as functions of time and state, and possibly control. If the model is defined as autonomous, then, the dynamics function, the lagrange cost and the path constraints must be defined as functions of state, and possibly control. """ -function Model(; autonomous::Bool = true, variable::Bool = false) +function Model(; autonomous::Bool = true, variable::Bool = false, in_place::Bool = false) time_dependence = autonomous ? Autonomous : NonAutonomous variable_dependence = variable ? NonFixed : Fixed + ocp = OptimalControlModel{time_dependence, variable_dependence}() + ocp.in_place = in_place - return OptimalControlModel{time_dependence, variable_dependence}() + return ocp end """ diff --git a/src/optimal_control_model-type.jl b/src/optimal_control_model-type.jl index 65aff302..a7489c44 100644 --- a/src/optimal_control_model-type.jl +++ b/src/optimal_control_model-type.jl @@ -41,6 +41,7 @@ $(TYPEDFIELDS) dim_control_range::Union{Dimension, Nothing} = nothing dim_state_range::Union{Dimension, Nothing} = nothing dim_variable_range::Union{Dimension, Nothing} = nothing + in_place::Union{Bool, Nothing} = nothing end # ---------------------------------------------------------------------- diff --git a/test/test_model.jl b/test/test_model.jl index 4e3bb619..c640642e 100644 --- a/test/test_model.jl +++ b/test/test_model.jl @@ -1,6 +1,43 @@ function test_model() # 30 55 185 ∅ = Vector{Real}() + @testset "is_in_place" begin + ocp = Model() + @test !is_in_place(ocp) + ocp = Model(; in_place = false) + @test !is_in_place(ocp) + ocp = Model(; in_place = true) + @test is_in_place(ocp) + + ocp = Model(; autonomous = true, variable = true) + @test !is_in_place(ocp) + ocp = Model(; autonomous = true, variable = true, in_place = false) + @test !is_in_place(ocp) + ocp = Model(; autonomous = true, variable = true, in_place = true) + @test is_in_place(ocp) + + ocp = Model(; autonomous = false, variable = true) + @test !is_in_place(ocp) + ocp = Model(; autonomous = false, variable = true, in_place = false) + @test !is_in_place(ocp) + ocp = Model(; autonomous = false, variable = true, in_place = true) + @test is_in_place(ocp) + + ocp = Model(; autonomous = true, variable = false) + @test !is_in_place(ocp) + ocp = Model(; autonomous = true, variable = false, in_place = false) + @test !is_in_place(ocp) + ocp = Model(; autonomous = true, variable = false, in_place = true) + @test is_in_place(ocp) + + ocp = Model(; autonomous = false, variable = false) + @test !is_in_place(ocp) + ocp = Model(; autonomous = false, variable = false, in_place = false) + @test !is_in_place(ocp) + ocp = Model(; autonomous = false, variable = false, in_place = true) + @test is_in_place(ocp) + end + @testset "variable!" begin ocp = Model(variable = false) From 75f8af2fe129639b769c79a076c3a731ca7bdf7f Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Caillau Date: Mon, 2 Sep 2024 16:55:01 +0200 Subject: [PATCH 04/33] =?UTF-8?q?added=20in=20place=20=CE=BE!(val,=20t,=20?= =?UTF-8?q?u,=20v)=20#=20nonlinear=20control=20constraints;=20added=20li?= =?UTF-8?q?=20=3D=20=CE=BEs[i]=20in=20out=20of=20place=20version=20to=20te?= =?UTF-8?q?st?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/optimal_control_model-getters.jl | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/optimal_control_model-getters.jl b/src/optimal_control_model-getters.jl index 6b49cb70..598aece4 100644 --- a/src/optimal_control_model-getters.jl +++ b/src/optimal_control_model-getters.jl @@ -39,6 +39,7 @@ function nlp_constraints!(ocp::OptimalControlModel) ξf = Vector{ControlConstraint}() ξl = Vector{ctNumber}() ξu = Vector{ctNumber}() + ξs = Vector{Int64}() ηf = Vector{StateConstraint}() ηl = Vector{ctNumber}() ηu = Vector{ctNumber}() @@ -63,14 +64,14 @@ function nlp_constraints!(ocp::OptimalControlModel) for (_, c) ∈ constraints(ocp) @match c begin - (type, f::BoundaryConstraint, lb, ub) && if type ∈ [:initial, :final, :boundary] - end => begin + (type, f::BoundaryConstraint, lb, ub) && if type ∈ [:initial, :final, :boundary] end => begin push!(ϕf, f) append!(ϕl, lb) append!(ϕu, ub) end (:control, f::ControlConstraint, lb, ub) => begin push!(ξf, f) + push!(ξs, length(lb)) append!(ξl, lb) append!(ξu, ub) end @@ -109,6 +110,7 @@ function nlp_constraints!(ocp::OptimalControlModel) end @assert length(ξl) == length(ξu) + @assert length(ξf) == length(ξs) @assert length(ηl) == length(ηu) @assert length(ψl) == length(ψu) @assert length(ϕl) == length(ϕu) @@ -123,13 +125,23 @@ function nlp_constraints!(ocp::OptimalControlModel) j = 1 for i ∈ 1:length(ξf) vali = ξf[i](t, u, v) - li = length(vali) + li = ξs[i] # could be length(vali) val[j:(j + li - 1)] .= vali # .= also allows scalar value for vali j = j + li end return val end + function ξ!(val, t, u, v) # nonlinear control constraints (in place) + j = 1 + for i ∈ 1:length(ξf) + li = ξs[i] + ξf[i](val[j:(j + li - 1)], t, u, v) + j = j + li + end + return nothing + end + function η(t, x, v) # nonlinear state constraints dim = length(ηl) val = zeros(ctNumber, dim) From cc62bd257c0d7c360f65da19085f7a08c6b4d149 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Caillau Date: Mon, 2 Sep 2024 17:29:47 +0200 Subject: [PATCH 05/33] added in place for all fun (= nonlinear) constraints --- src/optimal_control_model-getters.jl | 99 ++++++++++++++++++++++++---- 1 file changed, 85 insertions(+), 14 deletions(-) diff --git a/src/optimal_control_model-getters.jl b/src/optimal_control_model-getters.jl index 598aece4..2b650eeb 100644 --- a/src/optimal_control_model-getters.jl +++ b/src/optimal_control_model-getters.jl @@ -37,27 +37,38 @@ function nlp_constraints!(ocp::OptimalControlModel) __check_all_set(ocp) ξf = Vector{ControlConstraint}() + ξs = Vector{Int64}() ξl = Vector{ctNumber}() ξu = Vector{ctNumber}() - ξs = Vector{Int64}() + ηf = Vector{StateConstraint}() + ηs = Vector{Int64}() ηl = Vector{ctNumber}() ηu = Vector{ctNumber}() + ψf = Vector{MixedConstraint}() + ψs = Vector{Int64}() ψl = Vector{ctNumber}() ψu = Vector{ctNumber}() + ϕf = Vector{BoundaryConstraint}() + ϕs = Vector{Int64}() ϕl = Vector{ctNumber}() ϕu = Vector{ctNumber}() + θf = Vector{VariableConstraint}() + θs = Vector{Int64}() θl = Vector{ctNumber}() θu = Vector{ctNumber}() + uind = Vector{Int}() ul = Vector{ctNumber}() uu = Vector{ctNumber}() + xind = Vector{Int}() xl = Vector{ctNumber}() xu = Vector{ctNumber}() + vind = Vector{Int}() vl = Vector{ctNumber}() vu = Vector{ctNumber}() @@ -66,6 +77,7 @@ function nlp_constraints!(ocp::OptimalControlModel) @match c begin (type, f::BoundaryConstraint, lb, ub) && if type ∈ [:initial, :final, :boundary] end => begin push!(ϕf, f) + push!(ϕs, length(lb)) append!(ϕl, lb) append!(ϕu, ub) end @@ -82,6 +94,7 @@ function nlp_constraints!(ocp::OptimalControlModel) end (:state, f::StateConstraint, lb, ub) => begin push!(ηf, f) + push!(ηs, length(lb)) append!(ηl, lb) append!(ηu, ub) end @@ -92,11 +105,13 @@ function nlp_constraints!(ocp::OptimalControlModel) end (:mixed, f::MixedConstraint, lb, ub) => begin push!(ψf, f) + push!(ψs, length(lb)) append!(ψl, lb) append!(ψu, ub) end (:variable, f::VariableConstraint, lb, ub) => begin push!(θf, f) + push!(θs, length(lb)) append!(θl, lb) append!(θu, ub) end @@ -112,9 +127,13 @@ function nlp_constraints!(ocp::OptimalControlModel) @assert length(ξl) == length(ξu) @assert length(ξf) == length(ξs) @assert length(ηl) == length(ηu) + @assert length(ηf) == length(ηs) @assert length(ψl) == length(ψu) + @assert length(ψf) == length(ψs) @assert length(ϕl) == length(ϕu) + @assert length(ϕf) == length(ϕs) @assert length(θl) == length(θu) + @assert length(θf) == length(θs) @assert length(ul) == length(uu) @assert length(xl) == length(xu) @assert length(vl) == length(vu) @@ -124,8 +143,8 @@ function nlp_constraints!(ocp::OptimalControlModel) val = zeros(ctNumber, dim) j = 1 for i ∈ 1:length(ξf) + li = ξs[i] vali = ξf[i](t, u, v) - li = ξs[i] # could be length(vali) val[j:(j + li - 1)] .= vali # .= also allows scalar value for vali j = j + li end @@ -147,53 +166,93 @@ function nlp_constraints!(ocp::OptimalControlModel) val = zeros(ctNumber, dim) j = 1 for i ∈ 1:length(ηf) + li = ηs[i] vali = ηf[i](t, x, v) - li = length(vali) val[j:(j + li - 1)] .= vali # .= also allows scalar value for vali j = j + li end return val end + function η!(val, t, x, v) # nonlinear state constraints (in place) + j = 1 + for i ∈ 1:length(ηf) + li = ηs[i] + ηf[i](val[j:(j + li - 1)], t, x, v) + j = j + li + end + return nothing + end + function ψ(t, x, u, v) # nonlinear mixed constraints dim = length(ψl) val = zeros(ctNumber, dim) j = 1 for i ∈ 1:length(ψf) + li = ψs[i] vali = ψf[i](t, x, u, v) - li = length(vali) val[j:(j + li - 1)] .= vali # .= also allows scalar value for vali j = j + li end return val end + function ψ!(val, t, x, u, v) # nonlinear mixed constraints (in place) + j = 1 + for i ∈ 1:length(ψf) + li = ψs[i] + ψf[i](val[j:(j + li - 1)], t, x, u, v) + j = j + li + end + return nothing + end + function ϕ(x0, xf, v) # nonlinear boundary constraints dim = length(ϕl) val = zeros(ctNumber, dim) j = 1 for i ∈ 1:length(ϕf) + li = ϕs[i] vali = ϕf[i](x0, xf, v) - li = length(vali) val[j:(j + li - 1)] .= vali # .= also allows scalar value for vali j = j + li end return val end + function ϕ!(val, x0, xf, v) # nonlinear boundary constraints + j = 1 + for i ∈ 1:length(ϕf) + li = ϕs[i] + ϕf[i](val[j:(j + li - 1)], x0, xf, v) + j = j + li + end + return nothing + end + function θ(v) # nonlinear variable constraints dim = length(θl) val = zeros(ctNumber, dim) j = 1 for i ∈ 1:length(θf) + li = θs[i] vali = θf[i](v) - li = length(vali) val[j:(j + li - 1)] .= vali # .= also allows scalar value for vali j = j + li end return val end + function θ!(val, v) # nonlinear variable constraints + j = 1 + for i ∈ 1:length(θf) + li = θs[i] + θf[i](val[j:(j + li - 1)], v) + j = j + li + end + return nothing + end + ocp.dim_control_constraints = length(ξl) ocp.dim_state_constraints = length(ηl) ocp.dim_mixed_constraints = length(ψl) @@ -203,14 +262,26 @@ function nlp_constraints!(ocp::OptimalControlModel) ocp.dim_state_range = length(xl) ocp.dim_variable_range = length(vl) - return (ξl, ξ, ξu), - (ηl, η, ηu), - (ψl, ψ, ψu), - (ϕl, ϕ, ϕu), - (θl, θ, θu), - (ul, uind, uu), - (xl, xind, xu), - (vl, vind, vu) + if is_in_place(ocp) + res = (ξl, ξ!, ξu), + (ηl, η!, ηu), + (ψl, ψ!, ψu), + (ϕl, ϕ!, ϕu), + (θl, θ!, θu), + (ul, uind, uu), + (xl, xind, xu), + (vl, vind, vu) + else + res = (ξl, ξ, ξu), + (ηl, η, ηu), + (ψl, ψ, ψu), + (ϕl, ϕ, ϕu), + (θl, θ, θu), + (ul, uind, uu), + (xl, xind, xu), + (vl, vind, vu) + end + return res end """ From 5a7ed3ae20b10c0f17d234738e82474cc7e248dc Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Caillau Date: Thu, 5 Sep 2024 18:25:32 +0200 Subject: [PATCH 06/33] added in place types; to be tested --- src/CTBase.jl | 2 + src/functions.jl | 291 +++++++++++++++++++++++++++ src/optimal_control_model-getters.jl | 127 +++++++----- src/optimal_control_model-setters.jl | 51 +++-- src/optimal_control_model-type.jl | 6 +- src/types.jl | 34 +++- 6 files changed, 436 insertions(+), 75 deletions(-) diff --git a/src/CTBase.jl b/src/CTBase.jl index 3a1517d6..63949d47 100644 --- a/src/CTBase.jl +++ b/src/CTBase.jl @@ -251,7 +251,9 @@ export set_AD_backend # functions export Hamiltonian, HamiltonianVectorField, VectorField export Mayer, Lagrange, Dynamics, ControlLaw, FeedbackControl, Multiplier +export Mayer!, Lagrange!, Dynamics! export BoundaryConstraint, StateConstraint, ControlConstraint, MixedConstraint, VariableConstraint +export BoundaryConstraint!, StateConstraint!, ControlConstraint!, MixedConstraint!, VariableConstraint! # model export OptimalControlModel diff --git a/src/functions.jl b/src/functions.jl index 21fe3c23..d45dac55 100644 --- a/src/functions.jl +++ b/src/functions.jl @@ -17,6 +17,11 @@ function BoundaryConstraint(f::Function; variable::Bool = false) return BoundaryConstraint{variable_dependence}(f) end +function BoundaryConstraint!(f!::Function; variable::Bool = false) + variable_dependence = variable ? NonFixed : Fixed + return BoundaryConstraint!{variable_dependence}(f!) +end + """ $(TYPEDSIGNATURES) @@ -36,6 +41,12 @@ function BoundaryConstraint(f::Function, dependencies::DataType...) return BoundaryConstraint{variable_dependence}(f) end +function BoundaryConstraint!(f!::Function, dependencies::DataType...) + __check_dependencies(dependencies) + variable_dependence = NonFixed ∈ dependencies ? NonFixed : Fixed + return BoundaryConstraint!{variable_dependence}(f!) +end + """ $(TYPEDSIGNATURES) @@ -66,6 +77,18 @@ function (F::BoundaryConstraint{NonFixed})(x0::State, xf::State, v::Variable)::c return F.f(x0, xf, v) end +function (F::BoundaryConstraint!{Fixed})(r::ctVector, x0::State, xf::State)::Nothing + return F.f!(r, x0, xf) +end + +function (F::BoundaryConstraint!{Fixed})(r::ctVector, x0::State, xf::State, v::Variable)::Nothing + return F.f!(r, x0, xf) +end + +function (F::BoundaryConstraint!{NonFixed})(r::ctVector, x0::State, xf::State, v::Variable)::Nothing + return F.f!(r, x0, xf, v) +end + # -------------------------------------------------------------------------------------------------- """ @@ -85,6 +108,11 @@ function Mayer(f::Function; variable::Bool = false) return Mayer{variable_dependence}(f) end +function Mayer!(f!::Function; variable::Bool = false) + variable_dependence = variable ? NonFixed : Fixed + return Mayer!{variable_dependence}(f!) +end + """ $(TYPEDSIGNATURES) @@ -104,6 +132,12 @@ function Mayer(f::Function, dependencies::DataType...) return Mayer{variable_dependence}(f) end +function Mayer!(f!::Function, dependencies::DataType...) + __check_dependencies(dependencies) + variable_dependence = NonFixed ∈ dependencies ? NonFixed : Fixed + return Mayer!{variable_dependence}(f!) +end + """ $(TYPEDSIGNATURES) @@ -134,6 +168,18 @@ function (F::Mayer{NonFixed})(x0::State, xf::State, v::Variable)::ctNumber return F.f(x0, xf, v) end +function (F::Mayer!{Fixed})(r::ctVector, x0::State, xf::State)::Nothing + return F.f!(r, x0, xf) +end + +function (F::Mayer!{Fixed})(r::ctVector, x0::State, xf::State, v::Variable)::Nothing + return F.f!(r, x0, xf) +end + +function (F::Mayer!{NonFixed})(r::ctVector, x0::State, xf::State, v::Variable)::Nothing + return F.f!(r, x0, xf, v) +end + # -------------------------------------------------------------------------------------------------- # Hamiltonian """ @@ -672,6 +718,12 @@ function Lagrange(f::Function; autonomous::Bool = true, variable::Bool = false) return Lagrange{time_dependence, variable_dependence}(f) end +function Lagrange!(f!::Function; autonomous::Bool = true, variable::Bool = false) + time_dependence = autonomous ? Autonomous : NonAutonomous + variable_dependence = variable ? NonFixed : Fixed + return Lagrange!{time_dependence, variable_dependence}(f!) +end + """ $(TYPEDSIGNATURES) @@ -700,6 +752,13 @@ function Lagrange(f::Function, dependencies::DataType...) return Lagrange{time_dependence, variable_dependence}(f) end +function Lagrange!(f!::Function, dependencies::DataType...) + __check_dependencies(dependencies) + time_dependence = NonAutonomous ∈ dependencies ? NonAutonomous : Autonomous + variable_dependence = NonFixed ∈ dependencies ? NonFixed : Fixed + return Lagrange!{time_dependence, variable_dependence}(f!) +end + """ $(TYPEDSIGNATURES) @@ -775,6 +834,40 @@ function (F::Lagrange{NonAutonomous, NonFixed})( return F.f(t, x, u, v) end +function (F::Lagrange!{Autonomous, Fixed})(r::ctVector, x::State, u::Control)::Nothing + return F.f!(r, x, u) +end + +function (F::Lagrange!{Autonomous, Fixed})(r::ctVector, t::Time, x::State, u::Control, v::Variable)::Nothing + return F.f!(r, x, u) +end + +function (F::Lagrange!{Autonomous, NonFixed})(r::ctVector, x::State, u::Control, v::Variable)::Nothing + return F.f!(r, x, u, v) +end + +function (F::Lagrange!{Autonomous, NonFixed})(r::ctVector, t::Time, x::State, u::Control, v::Variable)::Nothing + return F.f!(r, x, u, v) +end + +function (F::Lagrange!{NonAutonomous, Fixed})(r::ctVector, t::Time, x::State, u::Control)::Nothing + return F.f!(r, t, x, u) +end + +function (F::Lagrange!{NonAutonomous, Fixed})(r::ctVector, t::Time, x::State, u::Control, v::Variable)::Nothing + return F.f!(r, t, x, u) +end + +function (F::Lagrange!{NonAutonomous, NonFixed})( + r::ctVector, + t::Time, + x::State, + u::Control, + v::Variable, +)::Nothing + return F.f!(r, t, x, u, v) +end + # -------------------------------------------------------------------------------------------------- """ @@ -796,6 +889,12 @@ function Dynamics(f::Function; autonomous::Bool = true, variable::Bool = false) return Dynamics{time_dependence, variable_dependence}(f) end +function Dynamics!(f!::Function; autonomous::Bool = true, variable::Bool = false) + time_dependence = autonomous ? Autonomous : NonAutonomous + variable_dependence = variable ? NonFixed : Fixed + return Dynamics!{time_dependence, variable_dependence}(f!) +end + """ $(TYPEDSIGNATURES) @@ -821,6 +920,13 @@ function Dynamics(f::Function, dependencies::DataType...) return Dynamics{time_dependence, variable_dependence}(f) end +function Dynamics!(f!::Function, dependencies::DataType...) + __check_dependencies(dependencies) + time_dependence = NonAutonomous ∈ dependencies ? NonAutonomous : Autonomous + variable_dependence = NonFixed ∈ dependencies ? NonFixed : Fixed + return Dynamics!{time_dependence, variable_dependence}(f!) +end + """ $(TYPEDSIGNATURES) @@ -883,6 +989,40 @@ function (F::Dynamics{NonAutonomous, NonFixed})( return F.f(t, x, u, v) end +function (F::Dynamics!{Autonomous, Fixed})(r::ctVector, x::State, u::Control)::Nothing + return F.f!(r, x, u) +end + +function (F::Dynamics!{Autonomous, Fixed})(r::ctVector, t::Time, x::State, u::Control, v::Variable)::Nothing + return F.f!(r, x, u) +end + +function (F::Dynamics!{Autonomous, NonFixed})(r::ctVector, x::State, u::Control, v::Variable)::Nothing + return F.f!(r, x, u, v) +end + +function (F::Dynamics!{Autonomous, NonFixed})(r::ctVector, t::Time, x::State, u::Control, v::Variable)::Nothing + return F.f!(r, x, u, v) +end + +function (F::Dynamics!{NonAutonomous, Fixed})(r::ctVector, t::Time, x::State, u::Control)::Nothing + return F.f!(r, t, x, u) +end + +function (F::Dynamics!{NonAutonomous, Fixed})(r::ctVector, t::Time, x::State, u::Control, v::Variable)::Nothing + return F.f!(r, t, x, u) +end + +function (F::Dynamics!{NonAutonomous, NonFixed})( + r::ctVector, + t::Time, + x::State, + u::Control, + v::Variable, +)::Nothing + return F.f!(r, t, x, u, v) +end + # -------------------------------------------------------------------------------------------------- """ @@ -904,6 +1044,12 @@ function StateConstraint(f::Function; autonomous::Bool = true, variable::Bool = return StateConstraint{time_dependence, variable_dependence}(f) end +function StateConstraint!(f!::Function; autonomous::Bool = true, variable::Bool = false) + time_dependence = autonomous ? Autonomous : NonAutonomous + variable_dependence = variable ? NonFixed : Fixed + return StateConstraint!{time_dependence, variable_dependence}(f!) +end + """ $(TYPEDSIGNATURES) @@ -929,6 +1075,13 @@ function StateConstraint(f::Function, dependencies::DataType...) return StateConstraint{time_dependence, variable_dependence}(f) end +function StateConstraint!(f!::Function, dependencies::DataType...) + __check_dependencies(dependencies) + time_dependence = NonAutonomous ∈ dependencies ? NonAutonomous : Autonomous + variable_dependence = NonFixed ∈ dependencies ? NonFixed : Fixed + return StateConstraint!{time_dependence, variable_dependence}(f!) +end + """ $(TYPEDSIGNATURES) @@ -990,6 +1143,34 @@ function (F::StateConstraint{NonAutonomous, NonFixed})(t::Time, x::State, v::Var return F.f(t, x, v) end +function (F::StateConstraint!{Autonomous, Fixed})(r::ctVector, x::State)::Nothing + return F.f!(r, x) +end + +function (F::StateConstraint!{Autonomous, Fixed})(r::ctVector, t::Time, x::State, v::Variable)::Nothing + return F.f!(r, x) +end + +function (F::StateConstraint!{Autonomous, NonFixed})(r::ctVector, x::State, v::Variable)::Nothing + return F.f!(r, x, v) +end + +function (F::StateConstraint!{Autonomous, NonFixed})(r::ctVector, t::Time, x::State, v::Variable)::Nothing + return F.f!(r, x, v) +end + +function (F::StateConstraint!{NonAutonomous, Fixed})(r::ctVector, t::Time, x::State)::Nothing + return F.f!(r, t, x) +end + +function (F::StateConstraint!{NonAutonomous, Fixed})(r::ctVector, t::Time, x::State, v::Variable)::Nothing + return F.f!(r, t, x) +end + +function (F::StateConstraint!{NonAutonomous, NonFixed})(r::ctVector, t::Time, x::State, v::Variable)::Nothing + return F.f!(r, t, x, v) +end + # -------------------------------------------------------------------------------------------------- """ @@ -1012,6 +1193,12 @@ function ControlConstraint(f::Function; autonomous::Bool = true, variable::Bool return ControlConstraint{time_dependence, variable_dependence}(f) end +function ControlConstraint!(f!::Function; autonomous::Bool = true, variable::Bool = false) + time_dependence = autonomous ? Autonomous : NonAutonomous + variable_dependence = variable ? NonFixed : Fixed + return ControlConstraint!{time_dependence, variable_dependence}(f!) +end + """ $(TYPEDSIGNATURES) @@ -1035,6 +1222,13 @@ function ControlConstraint(f::Function, dependencies::DataType...) return ControlConstraint{time_dependence, variable_dependence}(f) end +function ControlConstraint!(f!::Function, dependencies::DataType...) + __check_dependencies(dependencies) + time_dependence = NonAutonomous ∈ dependencies ? NonAutonomous : Autonomous + variable_dependence = NonFixed ∈ dependencies ? NonFixed : Fixed + return ControlConstraint!{time_dependence, variable_dependence}(f!) +end + """ $(TYPEDSIGNATURES) @@ -1094,6 +1288,34 @@ function (F::ControlConstraint{NonAutonomous, NonFixed})(t::Time, u::Control, v: return F.f(t, u, v) end +function (F::ControlConstraint!{Autonomous, Fixed})(r::ctVector, u::Control)::Nothing + return F.f!(r, u) +end + +function (F::ControlConstraint!{Autonomous, Fixed})(r::ctVector, t::Time, u::Control, v::Variable)::Nothing + return F.f!(r, u) +end + +function (F::ControlConstraint!{Autonomous, NonFixed})(r::ctVector, u::Control, v::Variable)::Nothing + return F.f!(u, v) +end + +function (F::ControlConstraint!{Autonomous, NonFixed})(r::ctVector, t::Time, u::Control, v::Variable)::Nothing + return F.f!(r, u, v) +end + +function (F::ControlConstraint!{NonAutonomous, Fixed})(r::ctVector, t::Time, u::Control)::Nothing + return F.f!(r, t, u) +end + +function (F::ControlConstraint!{NonAutonomous, Fixed})(r::ctVector, t::Time, u::Control, v::Variable)::Nothing + return F.f!(r, t, u) +end + +function (F::ControlConstraint!{NonAutonomous, NonFixed})(r::ctVector, t::Time, u::Control, v::Variable)::Nothing + return F.f!(r, t, u, v) +end + # -------------------------------------------------------------------------------------------------- """ @@ -1115,6 +1337,12 @@ function MixedConstraint(f::Function; autonomous::Bool = true, variable::Bool = return MixedConstraint{time_dependence, variable_dependence}(f) end +function MixedConstraint!(f!::Function; autonomous::Bool = true, variable::Bool = false) + time_dependence = autonomous ? Autonomous : NonAutonomous + variable_dependence = variable ? NonFixed : Fixed + return MixedConstraint!{time_dependence, variable_dependence}(f!) +end + """ $(TYPEDSIGNATURES) @@ -1140,6 +1368,13 @@ function MixedConstraint(f::Function, dependencies::DataType...) return MixedConstraint{time_dependence, variable_dependence}(f) end +function MixedConstraint!(f!::Function, dependencies::DataType...) + __check_dependencies(dependencies) + time_dependence = NonAutonomous ∈ dependencies ? NonAutonomous : Autonomous + variable_dependence = NonFixed ∈ dependencies ? NonFixed : Fixed + return MixedConstraint!{time_dependence, variable_dependence}(f!) +end + """ $(TYPEDSIGNATURES) @@ -1223,6 +1458,58 @@ function (F::MixedConstraint{NonAutonomous, NonFixed})( return F.f(t, x, u, v) end +function (F::MixedConstraint!{Autonomous, Fixed})(r::ctVector, x::State, u::Control)::Nothing + return F.f!(r, x, u) +end + +function (F::MixedConstraint!{Autonomous, Fixed})( + r::ctVector, + t::Time, + x::State, + u::Control, + v::Variable, +)::Nothing + return F.f!(r, x, u) +end + +function (F::MixedConstraint!{Autonomous, NonFixed})(r::ctVector, x::State, u::Control, v::Variable)::Nothing + return F.f!(r, x, u, v) +end + +function (F::MixedConstraint!{Autonomous, NonFixed})( + r::ctVector, + t::Time, + x::State, + u::Control, + v::Variable, +)::Nothing + return F.f!(r, x, u, v) +end + +function (F::MixedConstraint!{NonAutonomous, Fixed})(r::ctVector, t::Time, x::State, u::Control)::Nothing + return F.f!(r, t, x, u) +end + +function (F::MixedConstraint!{NonAutonomous, Fixed})( + r::ctVector, + t::Time, + x::State, + u::Control, + v::Variable, +)::Nothing + return F.f!(r, t, x, u) +end + +function (F::MixedConstraint!{NonAutonomous, NonFixed})( + r::ctVector, + t::Time, + x::State, + u::Control, + v::Variable, +)::Nothing + return F.f!(r, t, x, u, v) +end + # -------------------------------------------------------------------------------------------------- """ @@ -1240,6 +1527,10 @@ function (F::VariableConstraint)(v::Variable)::ctVector return F.f(v) end +function (F::VariableConstraint!)(r::ctVector, v::Variable)::Nothing + return F.f!(r, v) +end + # -------------------------------------------------------------------------------------------------- """ diff --git a/src/optimal_control_model-getters.jl b/src/optimal_control_model-getters.jl index 2b650eeb..66385a86 100644 --- a/src/optimal_control_model-getters.jl +++ b/src/optimal_control_model-getters.jl @@ -1,6 +1,8 @@ # ---------------------------------------------------------------------- # -# Interaction with the Model that get data. Getters. +# Model getters. +# +# todo: use copyto! instead of r[:] = view(u, rg) in nlp_constraints! # """ @@ -17,7 +19,8 @@ Return a 6-tuple of tuples: - `(xl, xind, xu)` are state linear constraints of a subset of indices - `(vl, vind, vu)` are variable linear constraints of a subset of indices -and update information about constraints dimensions of `ocp`. +and update information about constraints dimensions of `ocp`. Functions `ξ`, `η`, `ψ`, `ϕ`, `θ` are used to evaluate the constraints at given time and state, control, or variable values. These functions are in place when the problem is +defined as in place, that is when `is_in_place(ocp)`. !!! note @@ -36,27 +39,33 @@ function nlp_constraints!(ocp::OptimalControlModel) # we check if the dimensions and times have been set __check_all_set(ocp) - ξf = Vector{ControlConstraint}() + ControlConstraint_ = is_in_place(ocp) ? ControlConstraint! : ControlConstraint + StateConstraint_ = is_in_place(ocp) ? StateConstraint! : StateConstraint + MixedConstraint_ = is_in_place(ocp) ? MixedConstraint! : MixedConstraint + BoundaryConstraint_ = is_in_place(ocp) ? BoundaryConstraint! : BoundaryConstraint + VariableConstraint_ = is_in_place(ocp) ? VariableConstraint! : VariableConstraint + + ξf = Vector{ControlConstraint_}() ξs = Vector{Int64}() ξl = Vector{ctNumber}() ξu = Vector{ctNumber}() - ηf = Vector{StateConstraint}() + ηf = Vector{StateConstraint_}() ηs = Vector{Int64}() ηl = Vector{ctNumber}() ηu = Vector{ctNumber}() - ψf = Vector{MixedConstraint}() + ψf = Vector{MixedConstraint_}() ψs = Vector{Int64}() ψl = Vector{ctNumber}() ψu = Vector{ctNumber}() - ϕf = Vector{BoundaryConstraint}() + ϕf = Vector{BoundaryConstraint_}() ϕs = Vector{Int64}() ϕl = Vector{ctNumber}() ϕu = Vector{ctNumber}() - θf = Vector{VariableConstraint}() + θf = Vector{VariableConstraint_}() θs = Vector{Int64}() θl = Vector{ctNumber}() θu = Vector{ctNumber}() @@ -75,13 +84,13 @@ function nlp_constraints!(ocp::OptimalControlModel) for (_, c) ∈ constraints(ocp) @match c begin - (type, f::BoundaryConstraint, lb, ub) && if type ∈ [:initial, :final, :boundary] end => begin + (type, f::BoundaryConstraint_, lb, ub) && if type ∈ [:initial, :final, :boundary] end => begin push!(ϕf, f) push!(ϕs, length(lb)) append!(ϕl, lb) append!(ϕu, ub) end - (:control, f::ControlConstraint, lb, ub) => begin + (:control, f::ControlConstraint_, lb, ub) => begin push!(ξf, f) push!(ξs, length(lb)) append!(ξl, lb) @@ -92,7 +101,7 @@ function nlp_constraints!(ocp::OptimalControlModel) append!(ul, lb) append!(uu, ub) end - (:state, f::StateConstraint, lb, ub) => begin + (:state, f::StateConstraint_, lb, ub) => begin push!(ηf, f) push!(ηs, length(lb)) append!(ηl, lb) @@ -103,13 +112,13 @@ function nlp_constraints!(ocp::OptimalControlModel) append!(xl, lb) append!(xu, ub) end - (:mixed, f::MixedConstraint, lb, ub) => begin + (:mixed, f::MixedConstraint_, lb, ub) => begin push!(ψf, f) push!(ψs, length(lb)) append!(ψl, lb) append!(ψu, ub) end - (:variable, f::VariableConstraint, lb, ub) => begin + (:variable, f::VariableConstraint_, lb, ub) => begin push!(θf, f) push!(θs, length(lb)) append!(θl, lb) @@ -155,7 +164,7 @@ function nlp_constraints!(ocp::OptimalControlModel) j = 1 for i ∈ 1:length(ξf) li = ξs[i] - ξf[i](val[j:(j + li - 1)], t, u, v) + ξf[i](view(val, j:(j + li - 1)), t, u, v) j = j + li end return nothing @@ -178,7 +187,7 @@ function nlp_constraints!(ocp::OptimalControlModel) j = 1 for i ∈ 1:length(ηf) li = ηs[i] - ηf[i](val[j:(j + li - 1)], t, x, v) + ηf[i](view(val, j:(j + li - 1)), t, x, v) j = j + li end return nothing @@ -201,7 +210,7 @@ function nlp_constraints!(ocp::OptimalControlModel) j = 1 for i ∈ 1:length(ψf) li = ψs[i] - ψf[i](val[j:(j + li - 1)], t, x, u, v) + ψf[i](view(val, j:(j + li - 1)), t, x, u, v) j = j + li end return nothing @@ -224,7 +233,7 @@ function nlp_constraints!(ocp::OptimalControlModel) j = 1 for i ∈ 1:length(ϕf) li = ϕs[i] - ϕf[i](val[j:(j + li - 1)], x0, xf, v) + ϕf[i](view(val, j:(j + li - 1)), x0, xf, v) j = j + li end return nothing @@ -247,7 +256,7 @@ function nlp_constraints!(ocp::OptimalControlModel) j = 1 for i ∈ 1:length(θf) li = θs[i] - θf[i](val[j:(j + li - 1)], v) + θf[i](view(val, j:(j + li - 1)), v) j = j + li end return nothing @@ -262,26 +271,20 @@ function nlp_constraints!(ocp::OptimalControlModel) ocp.dim_state_range = length(xl) ocp.dim_variable_range = length(vl) - if is_in_place(ocp) - res = (ξl, ξ!, ξu), - (ηl, η!, ηu), - (ψl, ψ!, ψu), - (ϕl, ϕ!, ϕu), - (θl, θ!, θu), - (ul, uind, uu), - (xl, xind, xu), - (vl, vind, vu) - else - res = (ξl, ξ, ξu), - (ηl, η, ηu), - (ψl, ψ, ψu), - (ϕl, ϕ, ϕu), - (θl, θ, θu), - (ul, uind, uu), - (xl, xind, xu), - (vl, vind, vu) - end - return res + ξ_ = is_in_place(ocp) ? ξ! : ξ + η_ = is_in_place(ocp) ? η! : η + ψ_ = is_in_place(ocp) ? ψ! : ψ + ϕ_ = is_in_place(ocp) ? ϕ! : ϕ + θ_ = is_in_place(ocp) ? θ! : θ + + return (ξl, ξ_, ξu), + (ηl, η_, ηu), + (ψl, ψ_, ψu), + (ϕl, ϕ_, ϕu), + (θl, θ_, θu), + (ul, uind, uu), + (xl, xind, xu), + (vl, vind, vu) end """ @@ -324,41 +327,59 @@ function constraint( label::Symbol, ) where {T <: TimeDependence, V <: VariableDependence} con = ocp.constraints[label] + BoundaryConstraint_ = is_in_place(ocp) ? BoundaryConstraint! : BoundaryConstraint + ControlConstraint_ = is_in_place(ocp) ? ControlConstraint! : ControlConstraint + StateConstraint_ = is_in_place(ocp) ? StateConstraint! : StateConstraint + MixedConstraint_ = is_in_place(ocp) ? MixedConstraint! : MixedConstraint + VariableConstraint_ = is_in_place(ocp) ? VariableConstraint! : VariableConstraint + @match con begin - (:initial, f::BoundaryConstraint, _, _) => return f - (:final, f::BoundaryConstraint, _, _) => return f - (:boundary, f::BoundaryConstraint, _, _) => return f - (:control, f::ControlConstraint, _, _) => return f + (:initial, f::BoundaryConstraint_, _, _) => return f + (:final, f::BoundaryConstraint_, _, _) => return f + (:boundary, f::BoundaryConstraint_, _, _) => return f + (:control, f::ControlConstraint_, _, _) => return f (:control, rg, _, _) => begin C = @match ocp begin - ::OptimalControlModel{Autonomous, Fixed} => ControlConstraint(u -> u[rg], T, V) - ::OptimalControlModel{Autonomous, NonFixed} => + ::OptimalControlModel{Autonomous, Fixed} => is_in_place(ocp) ? + ControlConstraint!((r, u) -> (r[:] = view(u, rg); nothing), T, V) : + ControlConstraint(u -> u[rg], T, V) + ::OptimalControlModel{Autonomous, NonFixed} => is_in_place(ocp) ? + ControlConstraint!((r, u, v) -> (r[:] = view(u, rg); nothing), T, V) : ControlConstraint((u, v) -> u[rg], T, V) - ::OptimalControlModel{NonAutonomous, Fixed} => + ::OptimalControlModel{NonAutonomous, Fixed} => is_in_place(ocp) ? + ControlConstraint!((r, t, u) -> (r[:] = view(u, rg); nothing), T, V) : ControlConstraint((t, u) -> u[rg], T, V) - ::OptimalControlModel{NonAutonomous, NonFixed} => + ::OptimalControlModel{NonAutonomous, NonFixed} => is_in_place(ocp) ? + ControlConstraint!((r, t, u, v) -> (r[:] = view(u, rg); nothing), T, V) : ControlConstraint((t, u, v) -> u[rg], T, V) _ => nothing end return C end - (:state, f::StateConstraint, _, _) => return f + (:state, f::StateConstraint_, _, _) => return f (:state, rg, _, _) => begin S = @match ocp begin - ::OptimalControlModel{Autonomous, Fixed} => StateConstraint(x -> x[rg], T, V) - ::OptimalControlModel{Autonomous, NonFixed} => + ::OptimalControlModel{Autonomous, Fixed} => is_in_place(ocp) ? + StateConstraint!((r, x) -> (r[:] = view(x, rg); nothing), T, V) : + StateConstraint(x -> x[rg], T, V) + ::OptimalControlModel{Autonomous, NonFixed} => is_in_place(ocp) ? + StateConstraint!((r, x, v) -> (r[:] = view(x, rg); nothing), T, V) : StateConstraint((x, v) -> x[rg], T, V) - ::OptimalControlModel{NonAutonomous, Fixed} => + ::OptimalControlModel{NonAutonomous, Fixed} => is_in_place(ocp) ? + StateConstraint!((r, t, x) -> (r[:] = view(x, rg); nothing), T, V) : StateConstraint((t, x) -> x[rg], T, V) - ::OptimalControlModel{NonAutonomous, NonFixed} => + ::OptimalControlModel{NonAutonomous, NonFixed} => is_in_place(ocp) ? + StateConstraint!((r, t, x, v) -> (r[:] = view(x, rg); nothing), T, V) : StateConstraint((t, x, v) -> x[rg], T, V) _ => nothing end return S end - (:mixed, f::MixedConstraint, _, _) => return f - (:variable, f::VariableConstraint, _, _) => return f - (:variable, rg, _, _) => return VariableConstraint(v -> v[rg]) + (:mixed, f::MixedConstraint_, _, _) => return f + (:variable, f::VariableConstraint_, _, _) => return f + (:variable, rg, _, _) => return ( is_in_place(ocp) ? + VariableConstraint!((r, v) -> (r[:] = view(v, rg); nothing), T, V) : + VariableConstraint(v -> v[rg], T, V) ) _ => error("Internal error") end end diff --git a/src/optimal_control_model-setters.jl b/src/optimal_control_model-setters.jl index def1afb5..70d0fcc0 100644 --- a/src/optimal_control_model-setters.jl +++ b/src/optimal_control_model-setters.jl @@ -2,8 +2,8 @@ # # Interaction with the Model that affect it. Setters / Constructors. # - -# todo: use design pattern to generate functions in nlp_constraints! +# todo: use copyto! instead of r[:] = view(x0, rg) +# """ $(TYPEDSIGNATURES) @@ -69,13 +69,13 @@ julia> ocp = Model(Autonomous, NonFixed) """ function Model( - dependencies::DataType..., + dependencies::DataType...; in_place::Bool = false, )::OptimalControlModel{<:TimeDependence, <:VariableDependence} # some checkings: __check_dependencies(dependencies) time_dependence = NonAutonomous ∈ dependencies ? NonAutonomous : Autonomous variable_dependence = NonFixed ∈ dependencies ? NonFixed : Fixed - return OptimalControlModel{time_dependence, variable_dependence}() + return OptimalControlModel{time_dependence, variable_dependence}(; in_place = in_place) end """ @@ -636,11 +636,21 @@ function constraint!( # set the constraint fun_rg = @match type begin :initial => - V == Fixed ? BoundaryConstraint((x0, xf) -> x0[rg], V) : - BoundaryConstraint((x0, xf, v) -> x0[rg], V) + if is_in_place(ocp) + V == Fixed ? BoundaryConstraint!((r, x0, xf) -> (r[:] = view(x0, rg); nothing), V) : + BoundaryConstraint!((r, x0, xf, v) -> (r[:] = view(x0, rg); nothing), V) + else + V == Fixed ? BoundaryConstraint((x0, xf) -> x0[rg], V) : + BoundaryConstraint((x0, xf, v) -> x0[rg], V) + end :final => - V == Fixed ? BoundaryConstraint((x0, xf) -> xf[rg], V) : - BoundaryConstraint((x0, xf, v) -> xf[rg], V) + if is_in_place(ocp) + V == Fixed ? BoundaryConstraint!((r, x0, xf) -> (r[:] = view(xf, rg); nothing), V) : + BoundaryConstraint!((r, x0, xf, v) -> (r[:] = view(xf, rg); nothing), V) + else + V == Fixed ? BoundaryConstraint((x0, xf) -> xf[rg], V) : + BoundaryConstraint((x0, xf, v) -> xf[rg], V) + end :control || :state || :variable => rg _ => throw( IncorrectArgument( @@ -656,15 +666,15 @@ function constraint!( (::Nothing, ::Function, ::ctVector, ::ctVector) => begin # set the constraint if type == :boundary - ocp.constraints[label] = (type, BoundaryConstraint(f, V), lb, ub) + ocp.constraints[label] = (type, BoundaryConstraint_(f, V), lb, ub) elseif type == :control - ocp.constraints[label] = (type, ControlConstraint(f, T, V), lb, ub) + ocp.constraints[label] = (type, ControlConstraint_(f, T, V), lb, ub) elseif type == :state - ocp.constraints[label] = (type, StateConstraint(f, T, V), lb, ub) + ocp.constraints[label] = (type, StateConstraint_(f, T, V), lb, ub) elseif type == :mixed - ocp.constraints[label] = (type, MixedConstraint(f, T, V), lb, ub) + ocp.constraints[label] = (type, MixedConstraint_(f, T, V), lb, ub) elseif type == :variable - ocp.constraints[label] = (type, VariableConstraint(f), lb, ub) + ocp.constraints[label] = (type, VariableConstraint_(f), lb, ub) else throw( IncorrectArgument( @@ -709,7 +719,8 @@ function dynamics!( __check_all_set(ocp) __is_dynamics_set(ocp) && throw(UnauthorizedCall("the dynamics has already been set.")) - ocp.dynamics = Dynamics(f, T, V) + Dynamics_ = is_in_place(ocp) ? Dynamics! : Dynamics + ocp.dynamics = Dynamics_(f, T, V) return nothing end @@ -760,10 +771,12 @@ function objective!( ocp.criterion = criterion # set the objective + Mayer_ = is_in_place(ocp) ? Mayer! : Mayer + Lagrange_ = is_in_place(ocp) ? Lagrange! : Lagrange if type == :mayer - ocp.mayer = Mayer(f, V) + ocp.mayer = Mayer_(f, V) elseif type == :lagrange - ocp.lagrange = Lagrange(f, T, V) + ocp.lagrange = Lagrange_(f, T, V) else throw( IncorrectArgument( @@ -819,9 +832,11 @@ function objective!( ocp.criterion = criterion # set the objective + Mayer_ = is_in_place(ocp) ? Mayer! : Mayer + Lagrange_ = is_in_place(ocp) ? Lagrange! : Lagrange if type == :bolza - ocp.mayer = Mayer(g, V) - ocp.lagrange = Lagrange(f⁰, T, V) + ocp.mayer = Mayer_(g, V) + ocp.lagrange = Lagrange_(f⁰, T, V) else throw( IncorrectArgument( diff --git a/src/optimal_control_model-type.jl b/src/optimal_control_model-type.jl index a7489c44..230cfffe 100644 --- a/src/optimal_control_model-type.jl +++ b/src/optimal_control_model-type.jl @@ -28,10 +28,10 @@ $(TYPEDFIELDS) variable_dimension::Union{Dimension, Nothing} = nothing variable_components_names::Union{Vector{String}, Nothing} = nothing variable_name::Union{String, Nothing} = nothing - lagrange::Union{Lagrange, Nothing} = nothing - mayer::Union{Mayer, Nothing} = nothing + lagrange::Union{Lagrange, Lagrange!, Nothing} = nothing + mayer::Union{Mayer, Mayer!, Nothing} = nothing criterion::Union{Symbol, Nothing} = nothing - dynamics::Union{Dynamics, Nothing} = nothing + dynamics::Union{Dynamics, Dynamics!, Nothing} = nothing constraints::Dict{Symbol, Tuple{Vararg{Any}}} = Dict{Symbol, Tuple{Vararg{Any}}}() dim_control_constraints::Union{Dimension, Nothing} = nothing dim_state_constraints::Union{Dimension, Nothing} = nothing diff --git a/src/types.jl b/src/types.jl index 82f76797..2c88d640 100644 --- a/src/types.jl +++ b/src/types.jl @@ -57,6 +57,10 @@ struct BoundaryConstraint{variable_dependence} f::Function end +struct BoundaryConstraint!{variable_dependence} + f!::Function +end + """ $(TYPEDEF) @@ -107,6 +111,10 @@ struct Mayer{variable_dependence} f::Function end +struct Mayer!{variable_dependence} + f!::Function +end + """ $(TYPEDEF) @@ -117,7 +125,7 @@ abstract type AbstractHamiltonian{time_dependence, variable_dependence} end """ $(TYPEDEF) -Abstract type for vectorfields. +Abstract type for vector fields. """ abstract type AbstractVectorField{time_dependence, variable_dependence} end @@ -508,6 +516,10 @@ struct Lagrange{time_dependence, variable_dependence} f::Function end +struct Lagrange!{time_dependence, variable_dependence} + f!::Function +end + """ $(TYPEDEF) @@ -580,6 +592,10 @@ struct Dynamics{time_dependence, variable_dependence} f::Function end +struct Dynamics!{time_dependence, variable_dependence} + f!::Function +end + """ $(TYPEDEF) @@ -658,6 +674,10 @@ struct StateConstraint{time_dependence, variable_dependence} f::Function end +struct StateConstraint!{time_dependence, variable_dependence} + f!::Function +end + """ $(TYPEDEF) @@ -730,6 +750,10 @@ struct ControlConstraint{time_dependence, variable_dependence} f::Function end +struct ControlConstraint!{time_dependence, variable_dependence} + f!::Function +end + """ $(TYPEDEF) @@ -810,6 +834,10 @@ struct MixedConstraint{time_dependence, variable_dependence} f::Function end +struct MixedConstraint!{time_dependence, variable_dependence} + f!::Function +end + """ $(TYPEDEF) @@ -851,6 +879,10 @@ struct VariableConstraint f::Function end +struct VariableConstraint! + f!::Function +end + """ $(TYPEDEF) From 09785e090096c100abed5f9ea74f4b99e9f40dbe Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Caillau Date: Thu, 5 Sep 2024 18:41:48 +0200 Subject: [PATCH 07/33] added missing Types_ = is_in_place(oc p) ? ... in constraint\! --- src/optimal_control_model-setters.jl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/optimal_control_model-setters.jl b/src/optimal_control_model-setters.jl index 70d0fcc0..a11d8724 100644 --- a/src/optimal_control_model-setters.jl +++ b/src/optimal_control_model-setters.jl @@ -634,6 +634,12 @@ function constraint!( ) end # set the constraint + BoundaryConstraint_ = is_in_place(ocp) ? BoundaryConstraint! : BoundaryConstraint + ControlConstraint_ = is_in_place(ocp) ? ControlConstraint! : ControlConstraint + StateConstraint_ = is_in_place(ocp) ? StateConstraint! : StateConstraint + MixedConstraint_ = is_in_place(ocp) ? MixedConstraint! : MixedConstraint + VariableConstraint_ = is_in_place(ocp) ? VariableConstraint! : VariableConstraint + fun_rg = @match type begin :initial => if is_in_place(ocp) From 8dd6f029cb9127db6b590dd7ce2a5b012a286cc2 Mon Sep 17 00:00:00 2001 From: Olivier Cots Date: Thu, 5 Sep 2024 21:22:13 +0200 Subject: [PATCH 08/33] fix unit tests --- src/optimal_control_model-getters.jl | 4 ++-- src/optimal_control_model-setters.jl | 15 ++++++++------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/optimal_control_model-getters.jl b/src/optimal_control_model-getters.jl index 66385a86..27112331 100644 --- a/src/optimal_control_model-getters.jl +++ b/src/optimal_control_model-getters.jl @@ -378,8 +378,8 @@ function constraint( (:mixed, f::MixedConstraint_, _, _) => return f (:variable, f::VariableConstraint_, _, _) => return f (:variable, rg, _, _) => return ( is_in_place(ocp) ? - VariableConstraint!((r, v) -> (r[:] = view(v, rg); nothing), T, V) : - VariableConstraint(v -> v[rg], T, V) ) + VariableConstraint!((r, v) -> (r[:] = view(v, rg); nothing)) : + VariableConstraint(v -> v[rg]) ) _ => error("Internal error") end end diff --git a/src/optimal_control_model-setters.jl b/src/optimal_control_model-setters.jl index a11d8724..cd146a44 100644 --- a/src/optimal_control_model-setters.jl +++ b/src/optimal_control_model-setters.jl @@ -633,13 +633,8 @@ function constraint!( ), ) end - # set the constraint - BoundaryConstraint_ = is_in_place(ocp) ? BoundaryConstraint! : BoundaryConstraint - ControlConstraint_ = is_in_place(ocp) ? ControlConstraint! : ControlConstraint - StateConstraint_ = is_in_place(ocp) ? StateConstraint! : StateConstraint - MixedConstraint_ = is_in_place(ocp) ? MixedConstraint! : MixedConstraint - VariableConstraint_ = is_in_place(ocp) ? VariableConstraint! : VariableConstraint + # set the constraint fun_rg = @match type begin :initial => if is_in_place(ocp) @@ -669,7 +664,13 @@ function constraint!( ocp.constraints[label] = (type, fun_rg, lb, ub) end - (::Nothing, ::Function, ::ctVector, ::ctVector) => begin + (::Nothing, ::Function, ::ctVector, ::ctVector) => begin + BoundaryConstraint_ = is_in_place(ocp) ? BoundaryConstraint! : BoundaryConstraint + ControlConstraint_ = is_in_place(ocp) ? ControlConstraint! : ControlConstraint + StateConstraint_ = is_in_place(ocp) ? StateConstraint! : StateConstraint + MixedConstraint_ = is_in_place(ocp) ? MixedConstraint! : MixedConstraint + VariableConstraint_ = is_in_place(ocp) ? VariableConstraint! : VariableConstraint + # set the constraint if type == :boundary ocp.constraints[label] = (type, BoundaryConstraint_(f, V), lb, ub) From 53e0521e4e28a04bce1e4da4b73ce6cc8f564984 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Caillau Date: Thu, 5 Sep 2024 22:38:08 +0200 Subject: [PATCH 09/33] moved Type_ defs. at the beginning of constraint\! --- src/optimal_control_model-setters.jl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/optimal_control_model-setters.jl b/src/optimal_control_model-setters.jl index cd146a44..38e8a856 100644 --- a/src/optimal_control_model-setters.jl +++ b/src/optimal_control_model-setters.jl @@ -572,6 +572,12 @@ function constraint!( (typeof(rg) <: Int) && (rg = Index(rg)) # core + BoundaryConstraint_ = is_in_place(ocp) ? BoundaryConstraint! : BoundaryConstraint + ControlConstraint_ = is_in_place(ocp) ? ControlConstraint! : ControlConstraint + StateConstraint_ = is_in_place(ocp) ? StateConstraint! : StateConstraint + MixedConstraint_ = is_in_place(ocp) ? MixedConstraint! : MixedConstraint + VariableConstraint_ = is_in_place(ocp) ? VariableConstraint! : VariableConstraint + @match (rg, f, lb, ub) begin (::Nothing, ::Nothing, ::ctVector, ::ctVector) => begin if type ∈ [:initial, :final, :state] @@ -665,13 +671,7 @@ function constraint!( end (::Nothing, ::Function, ::ctVector, ::ctVector) => begin - BoundaryConstraint_ = is_in_place(ocp) ? BoundaryConstraint! : BoundaryConstraint - ControlConstraint_ = is_in_place(ocp) ? ControlConstraint! : ControlConstraint - StateConstraint_ = is_in_place(ocp) ? StateConstraint! : StateConstraint - MixedConstraint_ = is_in_place(ocp) ? MixedConstraint! : MixedConstraint - VariableConstraint_ = is_in_place(ocp) ? VariableConstraint! : VariableConstraint - - # set the constraint + # set the constraint if type == :boundary ocp.constraints[label] = (type, BoundaryConstraint_(f, V), lb, ub) elseif type == :control From 6b5e28ea2307700d7d9369629b89aa452caccc71 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Caillau Date: Fri, 6 Sep 2024 10:16:18 +0200 Subject: [PATCH 10/33] scalar range --- src/optimal_control_model-setters.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/optimal_control_model-setters.jl b/src/optimal_control_model-setters.jl index 38e8a856..dd0aab5f 100644 --- a/src/optimal_control_model-setters.jl +++ b/src/optimal_control_model-setters.jl @@ -569,7 +569,7 @@ function constraint!( q = variable_dimension(ocp) # range - (typeof(rg) <: Int) && (rg = Index(rg)) + (typeof(rg) <: Int) && (rg = Index(rg)) # todo: scalar range # core BoundaryConstraint_ = is_in_place(ocp) ? BoundaryConstraint! : BoundaryConstraint @@ -581,7 +581,7 @@ function constraint!( @match (rg, f, lb, ub) begin (::Nothing, ::Nothing, ::ctVector, ::ctVector) => begin if type ∈ [:initial, :final, :state] - rg = n == 1 ? Index(1) : 1:n + rg = n == 1 ? Index(1) : 1:n # todo: scalar range txt = "the lower bound `lb`, the upper bound `ub` and the value `val` must be of dimension $n" elseif type == :control rg = m == 1 ? Index(1) : 1:m From 670d3fbbdb56cd88730a46a1e4043fc675d8773f Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Caillau Date: Fri, 6 Sep 2024 10:59:20 +0200 Subject: [PATCH 11/33] treated scalar case with r[:] .= __view(..., rg) --- src/optimal_control_model-getters.jl | 20 +++++++++----------- src/optimal_control_model-setters.jl | 10 ++++------ src/utils.jl | 24 +++++++++++++++++++++++- 3 files changed, 36 insertions(+), 18 deletions(-) diff --git a/src/optimal_control_model-getters.jl b/src/optimal_control_model-getters.jl index 27112331..1ff464c7 100644 --- a/src/optimal_control_model-getters.jl +++ b/src/optimal_control_model-getters.jl @@ -2,8 +2,6 @@ # # Model getters. # -# todo: use copyto! instead of r[:] = view(u, rg) in nlp_constraints! -# """ $(TYPEDSIGNATURES) @@ -341,16 +339,16 @@ function constraint( (:control, rg, _, _) => begin C = @match ocp begin ::OptimalControlModel{Autonomous, Fixed} => is_in_place(ocp) ? - ControlConstraint!((r, u) -> (r[:] = view(u, rg); nothing), T, V) : + ControlConstraint!((r, u) -> (r[:] .= __view(u, rg); nothing), T, V) : ControlConstraint(u -> u[rg], T, V) ::OptimalControlModel{Autonomous, NonFixed} => is_in_place(ocp) ? - ControlConstraint!((r, u, v) -> (r[:] = view(u, rg); nothing), T, V) : + ControlConstraint!((r, u, v) -> (r[:] .= __view(u, rg); nothing), T, V) : ControlConstraint((u, v) -> u[rg], T, V) ::OptimalControlModel{NonAutonomous, Fixed} => is_in_place(ocp) ? - ControlConstraint!((r, t, u) -> (r[:] = view(u, rg); nothing), T, V) : + ControlConstraint!((r, t, u) -> (r[:] .= __view(u, rg); nothing), T, V) : ControlConstraint((t, u) -> u[rg], T, V) ::OptimalControlModel{NonAutonomous, NonFixed} => is_in_place(ocp) ? - ControlConstraint!((r, t, u, v) -> (r[:] = view(u, rg); nothing), T, V) : + ControlConstraint!((r, t, u, v) -> (r[:] .= __view(u, rg); nothing), T, V) : ControlConstraint((t, u, v) -> u[rg], T, V) _ => nothing end @@ -360,16 +358,16 @@ function constraint( (:state, rg, _, _) => begin S = @match ocp begin ::OptimalControlModel{Autonomous, Fixed} => is_in_place(ocp) ? - StateConstraint!((r, x) -> (r[:] = view(x, rg); nothing), T, V) : + StateConstraint!((r, x) -> (r[:] .= __view(x, rg); nothing), T, V) : StateConstraint(x -> x[rg], T, V) ::OptimalControlModel{Autonomous, NonFixed} => is_in_place(ocp) ? - StateConstraint!((r, x, v) -> (r[:] = view(x, rg); nothing), T, V) : + StateConstraint!((r, x, v) -> (r[:] .= __view(x, rg); nothing), T, V) : StateConstraint((x, v) -> x[rg], T, V) ::OptimalControlModel{NonAutonomous, Fixed} => is_in_place(ocp) ? - StateConstraint!((r, t, x) -> (r[:] = view(x, rg); nothing), T, V) : + StateConstraint!((r, t, x) -> (r[:] .= __view(x, rg); nothing), T, V) : StateConstraint((t, x) -> x[rg], T, V) ::OptimalControlModel{NonAutonomous, NonFixed} => is_in_place(ocp) ? - StateConstraint!((r, t, x, v) -> (r[:] = view(x, rg); nothing), T, V) : + StateConstraint!((r, t, x, v) -> (r[:] .= __view(x, rg); nothing), T, V) : StateConstraint((t, x, v) -> x[rg], T, V) _ => nothing end @@ -378,7 +376,7 @@ function constraint( (:mixed, f::MixedConstraint_, _, _) => return f (:variable, f::VariableConstraint_, _, _) => return f (:variable, rg, _, _) => return ( is_in_place(ocp) ? - VariableConstraint!((r, v) -> (r[:] = view(v, rg); nothing)) : + VariableConstraint!((r, v) -> (r[:] .= __view(v, rg); nothing)) : VariableConstraint(v -> v[rg]) ) _ => error("Internal error") end diff --git a/src/optimal_control_model-setters.jl b/src/optimal_control_model-setters.jl index dd0aab5f..2519d462 100644 --- a/src/optimal_control_model-setters.jl +++ b/src/optimal_control_model-setters.jl @@ -2,8 +2,6 @@ # # Interaction with the Model that affect it. Setters / Constructors. # -# todo: use copyto! instead of r[:] = view(x0, rg) -# """ $(TYPEDSIGNATURES) @@ -644,16 +642,16 @@ function constraint!( fun_rg = @match type begin :initial => if is_in_place(ocp) - V == Fixed ? BoundaryConstraint!((r, x0, xf) -> (r[:] = view(x0, rg); nothing), V) : - BoundaryConstraint!((r, x0, xf, v) -> (r[:] = view(x0, rg); nothing), V) + V == Fixed ? BoundaryConstraint!((r, x0, xf) -> (r[:] .= __view(x0, rg); nothing), V) : + BoundaryConstraint!((r, x0, xf, v) -> (r[:] .= __view(x0, rg); nothing), V) else V == Fixed ? BoundaryConstraint((x0, xf) -> x0[rg], V) : BoundaryConstraint((x0, xf, v) -> x0[rg], V) end :final => if is_in_place(ocp) - V == Fixed ? BoundaryConstraint!((r, x0, xf) -> (r[:] = view(xf, rg); nothing), V) : - BoundaryConstraint!((r, x0, xf, v) -> (r[:] = view(xf, rg); nothing), V) + V == Fixed ? BoundaryConstraint!((r, x0, xf) -> (r[:] .= __view(xf, rg); nothing), V) : + BoundaryConstraint!((r, x0, xf, v) -> (r[:] .= __view(xf, rg); nothing), V) else V == Fixed ? BoundaryConstraint((x0, xf) -> xf[rg], V) : BoundaryConstraint((x0, xf, v) -> xf[rg], V) diff --git a/src/utils.jl b/src/utils.jl index 2af577ad..98d1f347 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -198,7 +198,6 @@ Return `expand(matrix2vec(x, 1))` """ expand(x::Matrix{<:ctNumber}) = expand(matrix2vec(x, 1)) -# transform a Matrix{<:ctNumber} to a Vector{<:Vector{<:ctNumber}} """ $(TYPEDSIGNATURES) @@ -225,3 +224,26 @@ function matrix2vec( end return y end + +""" +$(TYPEDSIGNATURES) + +Adapt `view` to treat uniformly scalars. + +**Note.** Throws an error if `rg` is not one (or `Index(1)`). +""" +__view(x::Number, rg) = x[rg] + +""" +$(TYPEDSIGNATURES) + +Adapt `view` to treat uniformly scalars. +""" +__view(x::AbstractVector, rg::Integer) = x[rg] + +""" +$(TYPEDSIGNATURES) + +Adapt `view` to treat uniformly scalars. +""" +__view(x::AbstractVector, rg::AbstractRange) = view(x, rg) # Allows StepRange \ No newline at end of file From 0ae0f8d5fa6e05cacb7427242c88e8a9399c3faa Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Caillau Date: Fri, 6 Sep 2024 11:59:46 +0200 Subject: [PATCH 12/33] added to_out_place in utils --- src/utils.jl | 16 +++++++++++++++- test/test_utils.jl | 19 ++++++++++++++++++- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/utils.jl b/src/utils.jl index 98d1f347..6536d712 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -246,4 +246,18 @@ $(TYPEDSIGNATURES) Adapt `view` to treat uniformly scalars. """ -__view(x::AbstractVector, rg::AbstractRange) = view(x, rg) # Allows StepRange \ No newline at end of file +__view(x::AbstractVector, rg::AbstractRange) = view(x, rg) # Allows StepRange + +""" +$(TYPEDSIGNATURES) + +Tranform in place function to out of place. Pass the result size and type (default = `Float64`). +""" +function to_out_of_place(f!, n; T = Float64) + function f(x...) + r = zeros(T, n) + f!(r, x...) + return r + end + return f +end \ No newline at end of file diff --git a/test/test_utils.jl b/test/test_utils.jl index a2dc236f..f3e0ef97 100644 --- a/test/test_utils.jl +++ b/test/test_utils.jl @@ -78,4 +78,21 @@ function test_utils() @test CTBase.ctupperscripts(019) == "¹⁹" @test CTBase.ctupperscripts(109) == "¹⁰⁹" end -end + + @testset "to_out_of_place" begin + + function f1!(r, x) + r[1] = x + r[2] = x + 1 + return nothing + end + @test to_out_of_place(f1!, 2)(1.0) == [1.0, 2.0] + + function f2!(r, x, y) + r[:] = x + y + return nothing + end + @test to_out_of_place(f2!, 1; T = Int32)(1, 2) == 3 + + end +end \ No newline at end of file From 3f974acdf9957c7121c1e889446bf0ef5c5f428c Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Caillau Date: Fri, 6 Sep 2024 12:10:06 +0200 Subject: [PATCH 13/33] added to_out_place in utils --- src/utils.jl | 7 ++++++- test/test_utils.jl | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/utils.jl b/src/utils.jl index 6536d712..4fb84d86 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -260,4 +260,9 @@ function to_out_of_place(f!, n; T = Float64) return r end return f -end \ No newline at end of file +end + +# Adapt getters to test in place +#__constraint(ocp, x...) = retrieve con length(lb) from dict; is_in_place(ocp) ? to_out_of_place(ocp, n)) : ocp + +""" \ No newline at end of file diff --git a/test/test_utils.jl b/test/test_utils.jl index f3e0ef97..5aa75145 100644 --- a/test/test_utils.jl +++ b/test/test_utils.jl @@ -86,13 +86,13 @@ function test_utils() r[2] = x + 1 return nothing end - @test to_out_of_place(f1!, 2)(1.0) == [1.0, 2.0] + @test CTBase.to_out_of_place(f1!, 2)(1.0) == [1.0, 2.0] function f2!(r, x, y) r[:] = x + y return nothing end - @test to_out_of_place(f2!, 1; T = Int32)(1, 2) == 3 + @test CTBase.to_out_of_place(f2!, 1; T = Int32)(1, 2) == 3 end end \ No newline at end of file From cdcead8a6a40c07c7406a7bd2dde8cb5a1ef1e27 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Caillau Date: Fri, 6 Sep 2024 12:18:47 +0200 Subject: [PATCH 14/33] added to_out_place in utils --- src/utils.jl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/utils.jl b/src/utils.jl index 4fb84d86..208a8609 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -263,6 +263,5 @@ function to_out_of_place(f!, n; T = Float64) end # Adapt getters to test in place -#__constraint(ocp, x...) = retrieve con length(lb) from dict; is_in_place(ocp) ? to_out_of_place(ocp, n)) : ocp - -""" \ No newline at end of file +#function __constraint(ocp, x...) +#retrieve con length(lb) from dict; is_in_place(ocp) ? to_out_of_place(ocp, n)) : ocp \ No newline at end of file From 5b017034da7ee1bdb9f968f4c42106355924a5f8 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Caillau Date: Fri, 6 Sep 2024 12:51:05 +0200 Subject: [PATCH 15/33] fixed utils test + updated tests in onepass with __ --- src/CTBase.jl | 13 +- src/utils.jl | 17 +- test/test_onepass.jl | 372 +++++++++++++++++++++---------------------- test/test_utils.jl | 2 +- 4 files changed, 207 insertions(+), 197 deletions(-) diff --git a/src/CTBase.jl b/src/CTBase.jl index 63949d47..8a230266 100644 --- a/src/CTBase.jl +++ b/src/CTBase.jl @@ -11,7 +11,6 @@ $(EXPORTS) """ module CTBase -# using import Base using DocStringExtensions using DifferentiationInterface: @@ -23,18 +22,18 @@ using DifferentiationInterface: prepare_gradient, prepare_jacobian import ForwardDiff -using Interpolations: linear_interpolation, Line, Interpolations # for default interpolation -using MLStyle # pattern matching +using Interpolations: linear_interpolation, Line, Interpolations # For default interpolation +using MLStyle # Pattern matching using Parameters # @with_kw: to have default values in struct -using Printf # to print an OptimalControlModel +using Printf # To print an OptimalControlModel using DataStructures # OrderedDict for aliases -using Unicode # unicode primitives -using PrettyTables # to print a table +using Unicode # Unicode primitives +using PrettyTables # To print a table using ReplMaker using MacroTools: @capture, postwalk, striplines using LinearAlgebra -# to suppress ambiguities +# To suppress ambiguities using SparseArrays, StaticArrays # -------------------------------------------------------------------------------------------------- diff --git a/src/utils.jl b/src/utils.jl index 208a8609..8487e245 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -252,16 +252,27 @@ __view(x::AbstractVector, rg::AbstractRange) = view(x, rg) # Allows StepRange $(TYPEDSIGNATURES) Tranform in place function to out of place. Pass the result size and type (default = `Float64`). +Return a scalar when the result has size one. """ function to_out_of_place(f!, n; T = Float64) function f(x...) r = zeros(T, n) f!(r, x...) - return r + return n == 1 ? r[1] : r end return f end # Adapt getters to test in place -#function __constraint(ocp, x...) -#retrieve con length(lb) from dict; is_in_place(ocp) ? to_out_of_place(ocp, n)) : ocp \ No newline at end of file +function __constraint(ocp, label) + if is_in_place(ocp) + n = length(constraints(ocp)[label][3]) # Size of lb + return to_out_of_place(constraint(ocp, label), n) + else + return constraint(ocp, label) + end +end + +__dynamics(ocp) = is_in_place(ocp) ? to_out_of_place(dynamics(ocp), state_dimension(ocp)) : dynamics(ocp) +__lagrange(ocp) = is_in_place(ocp) ? to_out_of_place(lagrange(ocp), 1) : lagrange(ocp) +__mayer(ocp) = is_in_place(ocp) ? to_out_of_place(mayer(ocp), 1) : mayer(ocp) \ No newline at end of file diff --git a/test/test_onepass.jl b/test/test_onepass.jl index f90bcbb4..2da41455 100644 --- a/test/test_onepass.jl +++ b/test/test_onepass.jl @@ -31,7 +31,7 @@ function test_onepass() d = 4 x = 10 u = 20 - @test dynamics(o)(x, u) == x + u + b + 3 + d + @test __dynamics(o)(x, u) == x + u + b + 3 + d end @testset "log" begin @@ -116,10 +116,10 @@ function test_onepass() x0 = 2 * x xf = 3 * x u = 3 - @test constraint(o, :eq1)(x0, xf) == x0[1] - @test constraint(o, Symbol("♡"))(x0, xf) == x0[2] - @test dynamics(o)(x, u) == [x[2], (x[1] + 2x[2])^2] - @test lagrange(o)(x, u) == u^2 + x[1] + @test __constraint(o, :eq1)(x0, xf) == x0[1] + @test __constraint(o, Symbol("♡"))(x0, xf) == x0[2] + @test __dynamics(o)(x, u) == [x[2], (x[1] + 2x[2])^2] + @test __lagrange(o)(x, u) == u^2 + x[1] @def o begin t ∈ [0, 1], time @@ -135,10 +135,10 @@ function test_onepass() x0 = 2 * x xf = 3 * x u = 3 - @test constraint(o, :eq1)(x0, xf) == x0[1] - @test constraint(o, Symbol("♡"))(x0, xf) == x0[2] - @test dynamics(o)(x, u) == [x[2], (x[1] + 2x[2])^2] - @test lagrange(o)(x, u) == u^2 + x[1] + @test __constraint(o, :eq1)(x0, xf) == x0[1] + @test __constraint(o, Symbol("♡"))(x0, xf) == x0[2] + @test __dynamics(o)(x, u) == [x[2], (x[1] + 2x[2])^2] + @test __lagrange(o)(x, u) == u^2 + x[1] @def o begin t ∈ [0, 1], time @@ -156,10 +156,10 @@ function test_onepass() xf = 3 * x u = 3 c = [u, 0] - @test constraint(o, :eq1)(x0, xf) == x0[1] - @test constraint(o, Symbol("♡"))(x0, xf) == x0[2] - @test dynamics(o)(x, c) == [x[2], (x[1] + 2x[2])^2] - @test lagrange(o)(x, c) == u^2 + x[1] + @test __constraint(o, :eq1)(x0, xf) == x0[1] + @test __constraint(o, Symbol("♡"))(x0, xf) == x0[2] + @test __dynamics(o)(x, c) == [x[2], (x[1] + 2x[2])^2] + @test __lagrange(o)(x, c) == u^2 + x[1] @def o begin t ∈ [0, 1], time @@ -171,7 +171,7 @@ function test_onepass() @test control_dimension(o) == 2 x = [1, 2, 3] u = [-1, 2] - @test dynamics(o)(x, u) == [x[1] + 2u[2], 2x[3], x[1] + u[2]] + @test __dynamics(o)(x, u) == [x[1] + 2u[2], 2x[3], x[1] + u[2]] t0 = 0.0 tf = 0.1 @@ -542,7 +542,7 @@ function test_onepass() @test control_dimension(o) == 2 x = [1, 2, 3] u = [-1, 2] - @test dynamics(o)(x, u) == [x[1] + 2u[2], 2x[3], x[1] + u[2]] + @test __dynamics(o)(x, u) == [x[1] + 2u[2], 2x[3], x[1] + u[2]] @def o begin z ∈ R², variable s ∈ [0, z₁], time @@ -556,7 +556,7 @@ function test_onepass() z = [5, 6] y = [1, 2, 3, 4] w = 9 - @test dynamics(o)(y, w, z) == [y[1], y[3]^2 + w + z[1], 0, 0] + @test __dynamics(o)(y, w, z) == [y[1], y[3]^2 + w + z[1], 0, 0] @def o begin z ∈ R², variable @@ -571,7 +571,7 @@ function test_onepass() z = [5, 6] y = [1, 2, 3, 4] w = 9 - @test_throws MethodError dynamics(o)(y, w, z) + @test_throws MethodError __dynamics(o)(y, w, z) @def o begin z ∈ R², variable @@ -588,7 +588,7 @@ function test_onepass() y0 = y yf = 3y0 ww = 19 - @test dynamics(o)(y, ww, z) == [y[1] + ww^2 + y[4]^3 + z[2], y[3]^2, 0, 0] + @test __dynamics(o)(y, ww, z) == [y[1] + ww^2 + y[4]^3 + z[2], y[3]^2, 0, 0] @def o begin z ∈ R², variable @@ -606,8 +606,8 @@ function test_onepass() y0 = y yf = 3y0 w = 11 - @test_throws MethodError dynamics(o)(y, w, z) - @test mayer(o)(y0, yf, z) == y0[1] + y0[4]^3 + z[2] + yf[2] + @test_throws MethodError __dynamics(o)(y, w, z) + @test __mayer(o)(y0, yf, z) == y0[1] + y0[4]^3 + z[2] + yf[2] end # --------------------------------------------------------------- @@ -628,7 +628,7 @@ function test_onepass() tf = 2 x0 = [1, 2] xf = [3, 4] - @test constraint(o, :eq1)(x0, xf, tf) == x0[1] + (xf[1] + 2xf[2]^3) - tf^2 + @test __constraint(o, :eq1)(x0, xf, tf) == x0[1] + (xf[1] + 2xf[2]^3) - tf^2 n = 11 m = 6 @@ -652,17 +652,17 @@ function test_onepass() end x = Vector{Float64}(1:n) u = 2 * Vector{Float64}(1:m) - @test constraint(o, :eq1)(x) == x[1] - @test constraint(o, :eq2)(x) == x - @test constraint(o, :eq3)(x) == x[1:2] - @test constraint(o, :eq4)(x) == x[1:2:4] - @test constraint(o, :eq5)(x) == x[2]^2 - @test constraint(o, :eq6)(u) == u - @test constraint(o, :eq7)(u) == u[1:2] - @test constraint(o, :eq8)(u) == u[1:2:4] - @test constraint(o, :eq9)(u) == u[2]^2 - @test constraint(o, :eq10)(x, u) == u[1] * x[1:2] - @test constraint(o, :eq11)(x, u) == u[1] * x[1:2] .^ 3 + @test __constraint(o, :eq1)(x) == x[1] + @test __constraint(o, :eq2)(x) == x + @test __constraint(o, :eq3)(x) == x[1:2] + @test __constraint(o, :eq4)(x) == x[1:2:4] + @test __constraint(o, :eq5)(x) == x[2]^2 + @test __constraint(o, :eq6)(u) == u + @test __constraint(o, :eq7)(u) == u[1:2] + @test __constraint(o, :eq8)(u) == u[1:2:4] + @test __constraint(o, :eq9)(u) == u[2]^2 + @test __constraint(o, :eq10)(x, u) == u[1] * x[1:2] + @test __constraint(o, :eq11)(x, u) == u[1] * x[1:2] .^ 3 n = 11 m = 6 @@ -689,17 +689,17 @@ function test_onepass() z = 3 * Vector{Float64}(1:2) x = Vector{Float64}(1:n) u = 2 * Vector{Float64}(1:m) - @test constraint(o, :eq1)(x, z) == x[1] - @test constraint(o, :eq2)(x, z) == x - @test constraint(o, :eq3)(x, z) == x[1:2] - [z[1], 1] - @test constraint(o, :eq4)(x, z) == x[1:2:4] - @test constraint(o, :eq5)(x, z) == x[2]^2 - @test constraint(o, :eq6)(u, z) == u - @test constraint(o, :eq7)(u, z) == u[1:2] - @test constraint(o, :eq8)(u, z) == u[1:2:4] - @test constraint(o, :eq9)(u, z) == u[2]^2 - @test constraint(o, :eq10)(x, u, z) == u[1] * x[1:2] + z + f() - @test constraint(o, :eq11)(x, u, z) == u[1] * x[1:2] .^ 3 + z + @test __constraint(o, :eq1)(x, z) == x[1] + @test __constraint(o, :eq2)(x, z) == x + @test __constraint(o, :eq3)(x, z) == x[1:2] - [z[1], 1] + @test __constraint(o, :eq4)(x, z) == x[1:2:4] + @test __constraint(o, :eq5)(x, z) == x[2]^2 + @test __constraint(o, :eq6)(u, z) == u + @test __constraint(o, :eq7)(u, z) == u[1:2] + @test __constraint(o, :eq8)(u, z) == u[1:2:4] + @test __constraint(o, :eq9)(u, z) == u[2]^2 + @test __constraint(o, :eq10)(x, u, z) == u[1] * x[1:2] + z + f() + @test __constraint(o, :eq11)(x, u, z) == u[1] * x[1:2] .^ 3 + z @def o begin t ∈ [0, 1], time @@ -719,10 +719,10 @@ function test_onepass() x0 = 2 * x xf = 3 * x u = 3 - @test constraint(o, :eq1)(x0, xf) == x0[1] - @test constraint(o, Symbol("♡"))(x0, xf) == x0[2] - @test dynamics(o)(x, u) == [x[2], (x[1] + 2x[2])^2] - @test lagrange(o)(x, u) == u^2 + x[1] + @test __constraint(o, :eq1)(x0, xf) == x0[1] + @test __constraint(o, Symbol("♡"))(x0, xf) == x0[2] + @test __dynamics(o)(x, u) == [x[2], (x[1] + 2x[2])^2] + @test __lagrange(o)(x, u) == u^2 + x[1] @def o begin t ∈ [0, 1], time @@ -740,10 +740,10 @@ function test_onepass() x0 = 2 * x xf = 3 * x u = 3 - @test constraint(o, :eq1)(x0, xf) == x0[1] - @test constraint(o, Symbol("♡"))(x0, xf) == x0[2] - @test dynamics(o)(x, u) == [x[2], (x[1] + 2x[2])^2] - @test lagrange(o)(x, u) == u^2 + x[1] + @test __constraint(o, :eq1)(x0, xf) == x0[1] + @test __constraint(o, Symbol("♡"))(x0, xf) == x0[2] + @test __dynamics(o)(x, u) == [x[2], (x[1] + 2x[2])^2] + @test __lagrange(o)(x, u) == u^2 + x[1] @def o begin z ∈ R², variable @@ -763,10 +763,10 @@ function test_onepass() xf = 3 * [1, 2] u = 3 z = [4, 5] - @test constraint(o, :eq1)(x0, xf, z) == x0[1] - @test constraint(o, Symbol("♡"))(x0, xf, z) == x0[2] - @test dynamics(o)(x, u, z) == [x[2], (x[1] + 2x[2])^2 + z[1]] - @test lagrange(o)(x, u, z) == u^2 + z[2] * x[1] + @test __constraint(o, :eq1)(x0, xf, z) == x0[1] + @test __constraint(o, Symbol("♡"))(x0, xf, z) == x0[2] + @test __dynamics(o)(x, u, z) == [x[2], (x[1] + 2x[2])^2 + z[1]] + @test __lagrange(o)(x, u, z) == u^2 + z[2] * x[1] @def o begin t ∈ [0, 1], time @@ -783,10 +783,10 @@ function test_onepass() xf = [4, 5] x = [1, 2] u = 3 - @test constraint(o, :eq1)(x0, xf) == x0[1]^2 + xf[2] - @test constraint(o, Symbol("♡"))(x0, xf) == x0[2] - @test dynamics(o)(x, u) == [x[2], x[1]^2] - @test lagrange(o)(x, u) == u^2 + x[1] + @test __constraint(o, :eq1)(x0, xf) == x0[1]^2 + xf[2] + @test __constraint(o, Symbol("♡"))(x0, xf) == x0[2] + @test __dynamics(o)(x, u) == [x[2], x[1]^2] + @test __lagrange(o)(x, u) == u^2 + x[1] @def o begin z ∈ R, variable @@ -805,10 +805,10 @@ function test_onepass() x = [1, 2] u = 3 z = 4 - @test constraint(o, :eq1)(x0, xf, z) == x0[1] - z - @test constraint(o, Symbol("♡"))(x0, xf, z) == x0[2] - @test dynamics(o)(x, u, z) == [x[2], x[1]^2 + z] - @test lagrange(o)(x, u, z) == u^2 + z * x[1] + @test __constraint(o, :eq1)(x0, xf, z) == x0[1] - z + @test __constraint(o, Symbol("♡"))(x0, xf, z) == x0[2] + @test __dynamics(o)(x, u, z) == [x[2], x[1]^2 + z] + @test __lagrange(o)(x, u, z) == u^2 + z * x[1] @def o begin z ∈ R, variable @@ -828,11 +828,11 @@ function test_onepass() x = [1, 2] u = 3 z = 4 - @test constraint(o, :eq1)(x0, xf, z) == x0[1] - z - @test constraint(o, :eq2)(x0, xf, z) == xf[2]^2 - @test constraint(o, Symbol("♡"))(x0, xf, z) == x0 - @test dynamics(o)(x, u, z) == [x[2], x[1]^2 + z] - @test lagrange(o)(x, u, z) == u^2 + z * x[1] + @test __constraint(o, :eq1)(x0, xf, z) == x0[1] - z + @test __constraint(o, :eq2)(x0, xf, z) == xf[2]^2 + @test __constraint(o, Symbol("♡"))(x0, xf, z) == x0 + @test __dynamics(o)(x, u, z) == [x[2], x[1]^2 + z] + @test __lagrange(o)(x, u, z) == u^2 + z * x[1] @def o begin z ∈ R, variable @@ -852,11 +852,11 @@ function test_onepass() x = [1, 2] u = 3 z = 4 - @test constraint(o, :eq1)(x0, xf, z) == x0[1] - z - @test constraint(o, :eq2)(x0, xf, z) == xf[2]^2 - @test constraint(o, :eq3)(x0, xf, z) == x0 - @test dynamics(o)(x, u, z) == [x[2], x[1]^2 + z] - @test lagrange(o)(x, u, z) == u^2 + z * x[1] + @test __constraint(o, :eq1)(x0, xf, z) == x0[1] - z + @test __constraint(o, :eq2)(x0, xf, z) == xf[2]^2 + @test __constraint(o, :eq3)(x0, xf, z) == x0 + @test __dynamics(o)(x, u, z) == [x[2], x[1]^2 + z] + @test __lagrange(o)(x, u, z) == u^2 + z * x[1] @test constraints(o)[:eq1][3] == 0 @test constraints(o)[:eq1][4] == 1 @test constraints(o)[:eq2][3] == 0 @@ -894,20 +894,20 @@ function test_onepass() u = 4 v = [5, 6] z = v[1] + 2v[2] - @test constraint(o, :eq1)(x0, xf, v) == x0 - v[1] - @test constraint(o, :eq2)(x0, xf, v) == xf - v[1] - @test constraint(o, :eq3)(x0, xf, v) == x0 - v[1] - @test constraint(o, :eq4)(x0, xf, v) == xf - v[1] - @test constraint(o, :eq5)(x0, xf, v) == x0 + xf - v[2] - @test constraint(o, :eq6)(x0, xf, v) == x0 + xf - v[2] - @test constraint(o, :eq7)(x, v) == x - v[1] - @test constraint(o, :eq9)(x, v) == x - z - @test constraint(o, :eq10)(u, v) == u - z - @test constraint(o, :eq11)(x, u, v) == x + u - z - @test constraint(o, :eq12)(v) == v[1] - @test constraint(o, :eq13)(v) == v[1] - @test constraint(o, :eq14)(v) == v[1] + 2v[2] - @test constraint(o, :eq15)(v) == v[1] + 2v[2] + @test __constraint(o, :eq1)(x0, xf, v) == x0 - v[1] + @test __constraint(o, :eq2)(x0, xf, v) == xf - v[1] + @test __constraint(o, :eq3)(x0, xf, v) == x0 - v[1] + @test __constraint(o, :eq4)(x0, xf, v) == xf - v[1] + @test __constraint(o, :eq5)(x0, xf, v) == x0 + xf - v[2] + @test __constraint(o, :eq6)(x0, xf, v) == x0 + xf - v[2] + @test __constraint(o, :eq7)(x, v) == x - v[1] + @test __constraint(o, :eq9)(x, v) == x - z + @test __constraint(o, :eq10)(u, v) == u - z + @test __constraint(o, :eq11)(x, u, v) == x + u - z + @test __constraint(o, :eq12)(v) == v[1] + @test __constraint(o, :eq13)(v) == v[1] + @test __constraint(o, :eq14)(v) == v[1] + 2v[2] + @test __constraint(o, :eq15)(v) == v[1] + 2v[2] @def o begin v ∈ R, variable @@ -1573,9 +1573,9 @@ function test_onepass() 0 1 ] - @test constraint(o, :eq1)(x0, xf) == x0 - @test dynamics(o)(x, u) == A * x + B * u - @test lagrange(o)(x, u) == 0.5u^2 + @test __constraint(o, :eq1)(x0, xf) == x0 + @test __dynamics(o)(x, u) == A * x + B * u + @test __lagrange(o)(x, u) == 0.5u^2 @test criterion(o) == :min t0 = 0 @@ -1601,9 +1601,9 @@ function test_onepass() 0 1 ] - @test constraint(o, :eq1)(x0, xf) == x0 - @test dynamics(o)(x, u) == A * x + B * u - @test lagrange(o)(x, u) == -0.5u^2 + @test __constraint(o, :eq1)(x0, xf) == x0 + @test __dynamics(o)(x, u) == A * x + B * u + @test __lagrange(o)(x, u) == -0.5u^2 @test criterion(o) == :min t0 = 0 @@ -1629,9 +1629,9 @@ function test_onepass() 0 1 ] - @test constraint(o, :eq1)(x0, xf) == x0 - @test dynamics(o)(x, u) == A * x + B * u - @test lagrange(o)(x, u) == 0.5u^2 + @test __constraint(o, :eq1)(x0, xf) == x0 + @test __dynamics(o)(x, u) == A * x + B * u + @test __lagrange(o)(x, u) == 0.5u^2 @test criterion(o) == :min t0 = 0 @@ -1657,9 +1657,9 @@ function test_onepass() 0 1 ] - @test constraint(o, :eq1)(x0, xf) == x0 - @test dynamics(o)(x, u) == A * x + B * u - @test lagrange(o)(x, u) == 0.5u^2 + @test __constraint(o, :eq1)(x0, xf) == x0 + @test __dynamics(o)(x, u) == A * x + B * u + @test __lagrange(o)(x, u) == 0.5u^2 @test criterion(o) == :min t0 = 0 @@ -1685,9 +1685,9 @@ function test_onepass() 0 1 ] - @test constraint(o, :eq1)(x0, xf) == x0 - @test dynamics(o)(x, u) == A * x + B * u - @test lagrange(o)(x, u) == -0.5u^2 + @test __constraint(o, :eq1)(x0, xf) == x0 + @test __dynamics(o)(x, u) == A * x + B * u + @test __lagrange(o)(x, u) == -0.5u^2 @test criterion(o) == :min t0 = 0 @@ -1713,9 +1713,9 @@ function test_onepass() 0 1 ] - @test constraint(o, :eq1)(x0, xf) == x0 - @test dynamics(o)(x, u) == A * x + B * u - @test lagrange(o)(x, u) == (-0.5 + tf) * u^2 + @test __constraint(o, :eq1)(x0, xf) == x0 + @test __dynamics(o)(x, u) == A * x + B * u + @test __lagrange(o)(x, u) == (-0.5 + tf) * u^2 @test criterion(o) == :min t0 = 0 @@ -1767,9 +1767,9 @@ function test_onepass() 0 1 ] - @test constraint(o, :eq1)(x0, xf) == x0 - @test dynamics(o)(x, u) == A * x + B * u - @test lagrange(o)(x, u) == 0.5u^2 + @test __constraint(o, :eq1)(x0, xf) == x0 + @test __dynamics(o)(x, u) == A * x + B * u + @test __lagrange(o)(x, u) == 0.5u^2 @test criterion(o) == :max t0 = 0 @@ -1795,9 +1795,9 @@ function test_onepass() 0 1 ] - @test constraint(o, :eq1)(x0, xf) == x0 - @test dynamics(o)(x, u) == A * x + B * u - @test lagrange(o)(x, u) == -0.5u^2 + @test __constraint(o, :eq1)(x0, xf) == x0 + @test __dynamics(o)(x, u) == A * x + B * u + @test __lagrange(o)(x, u) == -0.5u^2 @test criterion(o) == :max t0 = 0 @@ -1823,9 +1823,9 @@ function test_onepass() 0 1 ] - @test constraint(o, :eq1)(x0, xf) == x0 - @test dynamics(o)(x, u) == A * x + B * u - @test lagrange(o)(x, u) == 0.5u^2 + @test __constraint(o, :eq1)(x0, xf) == x0 + @test __dynamics(o)(x, u) == A * x + B * u + @test __lagrange(o)(x, u) == 0.5u^2 @test criterion(o) == :max t0 = 0 @@ -1851,9 +1851,9 @@ function test_onepass() 0 1 ] - @test constraint(o, :eq1)(x0, xf) == x0 - @test dynamics(o)(x, u) == A * x + B * u - @test lagrange(o)(x, u) == 0.5u^2 + @test __constraint(o, :eq1)(x0, xf) == x0 + @test __dynamics(o)(x, u) == A * x + B * u + @test __lagrange(o)(x, u) == 0.5u^2 @test criterion(o) == :max t0 = 0 @@ -1879,9 +1879,9 @@ function test_onepass() 0 1 ] - @test constraint(o, :eq1)(x0, xf) == x0 - @test dynamics(o)(x, u) == A * x + B * u - @test lagrange(o)(x, u) == -0.5u^2 + @test __constraint(o, :eq1)(x0, xf) == x0 + @test __dynamics(o)(x, u) == A * x + B * u + @test __lagrange(o)(x, u) == -0.5u^2 @test criterion(o) == :max # ----------------------------------- @@ -1948,8 +1948,8 @@ function test_onepass() u = 2 x0 = 3 xf = 4 - @test mayer(o)(x0, xf) == x0 + 3xf - @test lagrange(o)(x, u) == x + u + @test __mayer(o)(x0, xf) == x0 + 3xf + @test __lagrange(o)(x, u) == x + u @test criterion(o) == :min @def o begin @@ -1962,8 +1962,8 @@ function test_onepass() u = 2 x0 = 3 xf = 4 - @test mayer(o)(x0, xf) == x0 + 2xf - @test lagrange(o)(x, u) == x + u + @test __mayer(o)(x0, xf) == x0 + 2xf + @test __lagrange(o)(x, u) == x + u @test criterion(o) == :min @def o begin @@ -1976,8 +1976,8 @@ function test_onepass() u = 2 x0 = 3 xf = 4 - @test mayer(o)(x0, xf) == x0 + 2xf - @test lagrange(o)(x, u) == 2(x + u) + @test __mayer(o)(x0, xf) == x0 + 2xf + @test __lagrange(o)(x, u) == 2(x + u) @test criterion(o) == :min @def o begin @@ -1990,8 +1990,8 @@ function test_onepass() u = 2 x0 = 3 xf = 4 - @test mayer(o)(x0, xf) == x0 + 2xf - @test lagrange(o)(x, u) == -(x + u) + @test __mayer(o)(x0, xf) == x0 + 2xf + @test __lagrange(o)(x, u) == -(x + u) @test criterion(o) == :min @def o begin @@ -2004,8 +2004,8 @@ function test_onepass() u = 2 x0 = 3 xf = 4 - @test mayer(o)(x0, xf) == x0 + 2xf - @test lagrange(o)(x, u) == -2(x + u) + @test __mayer(o)(x0, xf) == x0 + 2xf + @test __lagrange(o)(x, u) == -2(x + u) @test criterion(o) == :min @test_throws ParsingError @def o begin @@ -2035,8 +2035,8 @@ function test_onepass() u = 2 x0 = 3 xf = 4 - @test mayer(o)(x0, xf) == x0 + 5xf - @test lagrange(o)(x, u) == x + u + @test __mayer(o)(x0, xf) == x0 + 5xf + @test __lagrange(o)(x, u) == x + u @test criterion(o) == :max @def o begin @@ -2049,8 +2049,8 @@ function test_onepass() u = 2 x0 = 3 xf = 4 - @test mayer(o)(x0, xf) == x0 + 2xf - @test lagrange(o)(x, u) == 2(x + u) + @test __mayer(o)(x0, xf) == x0 + 2xf + @test __lagrange(o)(x, u) == 2(x + u) @test criterion(o) == :max @def o begin @@ -2063,8 +2063,8 @@ function test_onepass() u = 2 x0 = 3 xf = 4 - @test mayer(o)(x0, xf) == x0 + 2xf - @test lagrange(o)(x, u) == -(x + u) + @test __mayer(o)(x0, xf) == x0 + 2xf + @test __lagrange(o)(x, u) == -(x + u) @test criterion(o) == :max @def o begin @@ -2077,8 +2077,8 @@ function test_onepass() u = 2 x0 = 3 xf = 4 - @test mayer(o)(x0, xf) == x0 + 2xf - @test lagrange(o)(x, u) == -2(x + u) + @test __mayer(o)(x0, xf) == x0 + 2xf + @test __lagrange(o)(x, u) == -2(x + u) @test criterion(o) == :max @test_throws ParsingError @def o begin @@ -2108,8 +2108,8 @@ function test_onepass() u = 2 x0 = 3 xf = 4 - @test mayer(o)(x0, xf) == x0 + 2xf - @test lagrange(o)(x, u) == x + u + @test __mayer(o)(x0, xf) == x0 + 2xf + @test __lagrange(o)(x, u) == x + u @test criterion(o) == :min @def o begin @@ -2122,8 +2122,8 @@ function test_onepass() u = 2 x0 = 3 xf = 4 - @test mayer(o)(x0, xf) == x0 + 2xf - @test lagrange(o)(x, u) == 2(x + u) + @test __mayer(o)(x0, xf) == x0 + 2xf + @test __lagrange(o)(x, u) == 2(x + u) @test criterion(o) == :min @def o begin @@ -2136,8 +2136,8 @@ function test_onepass() u = 2 x0 = 3 xf = 4 - @test mayer(o)(x0, xf) == -(x0 + 2xf) - @test lagrange(o)(x, u) == x + u + @test __mayer(o)(x0, xf) == -(x0 + 2xf) + @test __lagrange(o)(x, u) == x + u @test criterion(o) == :min @def o begin @@ -2150,8 +2150,8 @@ function test_onepass() u = 2 x0 = 3 xf = 4 - @test mayer(o)(x0, xf) == -(x0 + 2xf) - @test lagrange(o)(x, u) == 2(x + u) + @test __mayer(o)(x0, xf) == -(x0 + 2xf) + @test __lagrange(o)(x, u) == 2(x + u) @test criterion(o) == :min @test_throws ParsingError @def o begin @@ -2181,8 +2181,8 @@ function test_onepass() u = 2 x0 = 3 xf = 4 - @test mayer(o)(x0, xf) == x0 + 2xf - @test lagrange(o)(x, u) == x + u + @test __mayer(o)(x0, xf) == x0 + 2xf + @test __lagrange(o)(x, u) == x + u @test criterion(o) == :max @def o begin @@ -2195,8 +2195,8 @@ function test_onepass() u = 2 x0 = 3 xf = 4 - @test mayer(o)(x0, xf) == x0 + 2xf - @test lagrange(o)(x, u) == 2(x + u) + @test __mayer(o)(x0, xf) == x0 + 2xf + @test __lagrange(o)(x, u) == 2(x + u) @test criterion(o) == :max @def o begin @@ -2209,8 +2209,8 @@ function test_onepass() u = 2 x0 = 3 xf = 4 - @test mayer(o)(x0, xf) == -(x0 + 2xf) - @test lagrange(o)(x, u) == x + u + @test __mayer(o)(x0, xf) == -(x0 + 2xf) + @test __lagrange(o)(x, u) == x + u @test criterion(o) == :max @def o begin @@ -2223,8 +2223,8 @@ function test_onepass() u = 2 x0 = 3 xf = 4 - @test mayer(o)(x0, xf) == -(x0 + 2xf) - @test lagrange(o)(x, u) == 2(x + u) + @test __mayer(o)(x0, xf) == -(x0 + 2xf) + @test __lagrange(o)(x, u) == 2(x + u) @test criterion(o) == :max @test_throws ParsingError @def o begin @@ -2258,7 +2258,7 @@ function test_onepass() y0 = [1, 2, 3, 4] yf = 2 * [1, 2, 3, 4] @test is_min(o) - @test mayer(o)(y0, yf) == y0[3] + yf[4] + @test __mayer(o)(y0, yf) == y0[3] + yf[4] @def o begin s ∈ [0, 1], time @@ -2271,7 +2271,7 @@ function test_onepass() y0 = [1, 2, 3, 4] yf = 2 * [1, 2, 3, 4] @test is_max(o) - @test mayer(o)(y0, yf) == y0[3] + yf[4] + @test __mayer(o)(y0, yf) == y0[3] + yf[4] @def o begin z ∈ R^2, variable @@ -2286,7 +2286,7 @@ function test_onepass() y0 = [1, 2, 3, 4] yf = 2 * [1, 2, 3, 4] @test is_min(o) - @test mayer(o)(y0, yf, z) == y0[3] + yf[4] + z[2] + @test __mayer(o)(y0, yf, z) == y0[3] + yf[4] + z[2] @def o begin z ∈ R², variable @@ -2304,8 +2304,8 @@ function test_onepass() y0 = y yf = 3y0 w = 7 - @test dynamics(o)(y, w, z) == [y[1] + w^2 + y[4]^3 + z[2], y[3]^2, 0, 0] - @test mayer(o)(y0, yf, z) == y0[3] + yf[4] + z[2] + @test __dynamics(o)(y, w, z) == [y[1] + w^2 + y[4]^3 + z[2], y[3]^2, 0, 0] + @test __mayer(o)(y0, yf, z) == y0[3] + yf[4] + z[2] @def o begin z ∈ R², variable @@ -2323,8 +2323,8 @@ function test_onepass() y0 = y yf = 3y0 w = 7 - @test dynamics(o)(y, w, z) == [y[1] + w^2 + y[4]^3 + z[2], y[3]^2, 0, 0] - @test mayer(o)(y0, yf, z) == y0[3] + yf[4] + z[2] + @test __dynamics(o)(y, w, z) == [y[1] + w^2 + y[4]^3 + z[2], y[3]^2, 0, 0] + @test __mayer(o)(y0, yf, z) == y0[3] + yf[4] + z[2] @def o begin z ∈ R², variable @@ -2339,7 +2339,7 @@ function test_onepass() z = [5, 6] y0 = y yf = 3y0 - @test mayer(o)(y0, yf, z) == y0[1] + y0[4]^3 + z[2] + yf[2] + @test __mayer(o)(y0, yf, z) == y0[1] + y0[4]^3 + z[2] + yf[2] @def o begin z ∈ R², variable @@ -2357,8 +2357,8 @@ function test_onepass() y0 = y yf = 3y0 w = 11 - @test dynamics(o)(y, w, z) == [y[1] + w^2 + y[4]^3 + z[2], y[3]^2, 0, 0] - @test_throws UndefVarError mayer(o)(y0, yf, z) + @test __dynamics(o)(y, w, z) == [y[1] + w^2 + y[4]^3 + z[2], y[3]^2, 0, 0] + @test_throws UndefVarError __mayer(o)(y0, yf, z) end # --------------------------------------------------------------- @@ -2382,7 +2382,7 @@ function test_onepass() d = 4 x = 10 u = 20 - @test dynamics(o)(x, u) == x + u + b + 3 + d + @test __dynamics(o)(x, u) == x + u + b + 3 + d end # --------------------------------------------------------------- @@ -2486,9 +2486,9 @@ function test_onepass() 0 1 ] - @test constraint(o, :eq1)(x0, xf) == x0 - @test dynamics(o)(x, u) == A * x + B * u - @test lagrange(o)(x, u) == 0.5u^2 + @test __constraint(o, :eq1)(x0, xf) == x0 + @test __dynamics(o)(x, u) == A * x + B * u + @test __lagrange(o)(x, u) == 0.5u^2 @test criterion(o) == :min @def o begin @@ -2510,12 +2510,12 @@ function test_onepass() x = [1, 2] u = 3 z = 4 - @test constraint(o, :eq1)(x0, xf, z) == x0[1] - z - @test constraint(o, :eq2)(x0, xf, z) == xf[2]^2 - @test constraint(o, Symbol("♡"))(x0, xf, z) == x0 - @test constraint(o, :eq3)(z) == z - @test dynamics(o)(x, u, z) == [x[2], x[1]^2 + z] - @test lagrange(o)(x, u, z) == u^2 + z * x[1] + @test __constraint(o, :eq1)(x0, xf, z) == x0[1] - z + @test __constraint(o, :eq2)(x0, xf, z) == xf[2]^2 + @test __constraint(o, Symbol("♡"))(x0, xf, z) == x0 + @test __constraint(o, :eq3)(z) == z + @test __dynamics(o)(x, u, z) == [x[2], x[1]^2 + z] + @test __lagrange(o)(x, u, z) == u^2 + z * x[1] @def o begin z in R, variable @@ -2536,12 +2536,12 @@ function test_onepass() x = [1, 2] u = 3 z = 4 - @test constraint(o, :eq1)(x0, xf, z) == x0[1] - z - @test constraint(o, :eq2)(x0, xf, z) == xf[2]^2 - @test constraint(o, Symbol("♡"))(x0, xf, z) == x0 - @test constraint(o, :eq3)(z) == z - @test dynamics(o)(x, u, z) == [x[2], x[1]^2 + z] - @test lagrange(o)(x, u, z) == u^2 + z * x[1] + @test __constraint(o, :eq1)(x0, xf, z) == x0[1] - z + @test __constraint(o, :eq2)(x0, xf, z) == xf[2]^2 + @test __constraint(o, Symbol("♡"))(x0, xf, z) == x0 + @test __constraint(o, :eq3)(z) == z + @test __dynamics(o)(x, u, z) == [x[2], x[1]^2 + z] + @test __lagrange(o)(x, u, z) == u^2 + z * x[1] @def o begin z in R^2, variable @@ -2564,11 +2564,11 @@ function test_onepass() x = [1, 2] u = [3, 0] z = [4, 1] - @test constraint(o, :eq1)(x0, xf, z) == x0[1] - z[1] - @test constraint(o, :eq2)(x0, xf, z) == xf[2]^2 - @test constraint(o, Symbol("♡"))(x0, xf, z) == x0 - @test constraint(o, :eq3)(z) == z[1] - @test dynamics(o)(x, u, z) == [x[2], x[1]^2 + z[1]] - @test lagrange(o)(x, u, z) == u[1]^2 + z[1] * x[1] + @test __constraint(o, :eq1)(x0, xf, z) == x0[1] - z[1] + @test __constraint(o, :eq2)(x0, xf, z) == xf[2]^2 + @test __constraint(o, Symbol("♡"))(x0, xf, z) == x0 + @test __constraint(o, :eq3)(z) == z[1] + @test __dynamics(o)(x, u, z) == [x[2], x[1]^2 + z[1]] + @test __lagrange(o)(x, u, z) == u[1]^2 + z[1] * x[1] end end diff --git a/test/test_utils.jl b/test/test_utils.jl index 5aa75145..cc917e79 100644 --- a/test/test_utils.jl +++ b/test/test_utils.jl @@ -89,7 +89,7 @@ function test_utils() @test CTBase.to_out_of_place(f1!, 2)(1.0) == [1.0, 2.0] function f2!(r, x, y) - r[:] = x + y + r[:] .= x + y return nothing end @test CTBase.to_out_of_place(f2!, 1; T = Int32)(1, 2) == 3 From 23fbaa8988d64b06255d88fe982044a8c329f907 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Caillau Date: Fri, 6 Sep 2024 13:56:06 +0200 Subject: [PATCH 16/33] fix: exported __constraint et al used for test --- src/CTBase.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CTBase.jl b/src/CTBase.jl index 8a230266..b151fc67 100644 --- a/src/CTBase.jl +++ b/src/CTBase.jl @@ -275,6 +275,7 @@ export control_dimension, control_components_names, control_name export state_dimension, state_components_names, state_name export variable_dimension, variable_components_names, variable_name export lagrange, mayer, criterion, dynamics +export __constraint, __lagrange, __mayer, __criterion, __dynamics # todo: remove after in place tests # solution export OptimalControlSolution From fc22616238d1535ffba4dc333643c6c0ec43ae86 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Caillau Date: Fri, 6 Sep 2024 15:53:47 +0200 Subject: [PATCH 17/33] fix in exports --- src/CTBase.jl | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/CTBase.jl b/src/CTBase.jl index b151fc67..bdccaf49 100644 --- a/src/CTBase.jl +++ b/src/CTBase.jl @@ -228,7 +228,7 @@ include("repl.jl") include("init.jl") include("print.jl") -# numeric types +# Numeric types export ctNumber, ctVector, Time, Times, TimesDisc export States, Costates, Controls, State, Costate, Control, Variable, Dimension, Index @@ -236,10 +236,10 @@ export DState, DCostate export TimeDependence, Autonomous, NonAutonomous export VariableDependence, NonFixed, Fixed -# description +# Description export Description, add, getFullDescription, remove -# exceptions +# Exceptions export CTException, ParsingError, AmbiguousDescription, IncorrectMethod export IncorrectArgument, IncorrectOutput, NotImplemented, UnauthorizedCall export ExtensionError @@ -247,17 +247,17 @@ export ExtensionError # AD export set_AD_backend -# functions +# Functions export Hamiltonian, HamiltonianVectorField, VectorField export Mayer, Lagrange, Dynamics, ControlLaw, FeedbackControl, Multiplier export Mayer!, Lagrange!, Dynamics! export BoundaryConstraint, StateConstraint, ControlConstraint, MixedConstraint, VariableConstraint export BoundaryConstraint!, StateConstraint!, ControlConstraint!, MixedConstraint!, VariableConstraint! -# model +# Model export OptimalControlModel export Model -export __OCPModel # redirection to Model to avoid confusion with other Model functions from other packages. Due to @def macro +export __OCPModel # todo: to be updated, redirection to Model to avoid confusion with other Model functions from other packages. Due to @def macro export variable!, time!, constraint!, dynamics!, objective!, state!, control!, remove_constraint!, model_expression! export is_autonomous, is_fixed @@ -275,9 +275,9 @@ export control_dimension, control_components_names, control_name export state_dimension, state_components_names, state_name export variable_dimension, variable_components_names, variable_name export lagrange, mayer, criterion, dynamics -export __constraint, __lagrange, __mayer, __criterion, __dynamics # todo: remove after in place tests +export __constraint, __lagrange, __mayer, __dynamics # todo: remove after in place tests -# solution +# Solution export OptimalControlSolution export time_grid, control, state, variable, costate, objective export state_discretized, control_discretized, costate_discretized @@ -299,13 +299,13 @@ export control_constraints!, export state_constraints!, mult_state_constraints!, mult_state_box_lower!, mult_state_box_upper! export mixed_constraints!, mult_mixed_constraints! -# initialization +# Initialization export OptimalControlInit -# utils +# Utils export ctgradient, ctjacobian, ctinterpolate, ctindices, ctupperscripts -# differential geometry +# Differential geometry export Lie, @Lie, Poisson, HamiltonianLift, AbstractHamiltonian, Lift, ⋅, ∂ₜ # ctparser_utils From 4bf88fc63e911d1ffc49a97d19e742de6d5397e6 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Caillau Date: Fri, 6 Sep 2024 17:01:12 +0200 Subject: [PATCH 18/33] updated test_model with __getters --- src/CTBase.jl | 1 + src/onepass.jl | 19 +++-- test/test_goddard.jl | 2 +- test/test_model.jl | 164 +++++++++++++++++++++---------------------- test/test_plot.jl | 2 +- 5 files changed, 99 insertions(+), 89 deletions(-) diff --git a/src/CTBase.jl b/src/CTBase.jl index bdccaf49..a822da9f 100644 --- a/src/CTBase.jl +++ b/src/CTBase.jl @@ -313,6 +313,7 @@ export replace_call, constraint_type # onepass export @def +export @__def # todo: remove after in place tests # repl export ct_repl, ct_repl_update_model diff --git a/src/onepass.jl b/src/onepass.jl index 41c49f6d..324a32e6 100644 --- a/src/onepass.jl +++ b/src/onepass.jl @@ -608,7 +608,16 @@ macro def(e) esc(code) end -macro def(ocp, e, log = false) +macro __def(e) # todo: remove after in place test + ocp = gensym() + code = quote + @def $ocp $e false true # Force in place + $ocp + end + esc(code) +end + +macro def(ocp, e, log = false, in_place = false) # todo: default to in_place try p0 = ParsingInfo() parse!(p0, ocp, e; log = false) # initial pass to get the dependencies (time and variable) @@ -617,10 +626,10 @@ macro def(ocp, e, log = false) p.v = p0.v code = parse!(p, ocp, e; log = log) init = @match (__t_dep(p), __v_dep(p)) begin - (false, false) => :($ocp = __OCPModel()) - (true, false) => :($ocp = __OCPModel(autonomous = false)) - (false, true) => :($ocp = __OCPModel(variable = true)) - _ => :($ocp = __OCPModel(autonomous = false, variable = true)) + (false, false) => :($ocp = __OCPModel(; in_place = $in_place)) + (true, false) => :($ocp = __OCPModel(autonomous = false; in_place = $in_place)) + (false, true) => :($ocp = __OCPModel(variable = true; in_place = $in_place)) + _ => :($ocp = __OCPModel(autonomous = false, variable = true; in_place = $in_place)) end ee = QuoteNode(e) code = Expr(:block, init, code, :($ocp.model_expression = $ee; $ocp)) diff --git a/test/test_goddard.jl b/test/test_goddard.jl index 3bac4ad4..65cb1ed8 100644 --- a/test/test_goddard.jl +++ b/test/test_goddard.jl @@ -53,5 +53,5 @@ test_goddard() = begin x = x0 u = 2 tf = 1 - @test dynamics(ocp)(x, u, tf) == F0(x) + u * F1(x) + @test __dynamics(ocp)(x, u, tf) == F0(x) + u * F1(x) end diff --git a/test/test_model.jl b/test/test_model.jl index 29a34447..b0cd0515 100644 --- a/test/test_model.jl +++ b/test/test_model.jl @@ -781,8 +781,8 @@ function test_model() # 30 55 185 ) constraint!(ocp, :initial, lb = 0, ub = 0, label = :c0) constraint!(ocp, :final, lb = 1, ub = 1, label = :cf) - @test constraint(ocp, :c0)(12, ∅) == 12 - @test constraint(ocp, :cf)(∅, 12) == 12 + @test __constraint(ocp, :c0)(12, ∅) == 12 + @test __constraint(ocp, :cf)(∅, 12) == 12 ocp = Model() time!(ocp; t0 = 0, tf = 1) @@ -790,8 +790,8 @@ function test_model() # 30 55 185 control!(ocp, 1) constraint!(ocp, :initial, lb = [0, 1], ub = [0, 1], label = :c0) constraint!(ocp, :final, lb = [1, 2], ub = [1, 2], label = :cf) - @test constraint(ocp, :c0)([12, 13], ∅) == [12, 13] - @test constraint(ocp, :cf)(∅, [12, 13]) == [12, 13] + @test __constraint(ocp, :c0)([12, 13], ∅) == [12, 13] + @test __constraint(ocp, :cf)(∅, [12, 13]) == [12, 13] # constraint already exists ocp = Model() @@ -812,13 +812,13 @@ function test_model() # 30 55 185 xf = 1 constraint!(ocp, :initial, rg = 1, lb = x0, ub = x0, label = :c0) constraint!(ocp, :final, rg = 1, lb = xf, ub = xf, label = :cf) - @test constraint(ocp, :c0)(x, ∅) == x - @test constraint(ocp, :cf)(∅, x) == x + @test __constraint(ocp, :c0)(x, ∅) == x + @test __constraint(ocp, :cf)(∅, x) == x constraint!(ocp, :initial, rg = 1, lb = x0, ub = x0, label = :c00) constraint!(ocp, :final, rg = 1, lb = xf, ub = xf, label = :cff) - @test constraint(ocp, :c00)(x, ∅) == x - @test constraint(ocp, :cff)(∅, x) == x + @test __constraint(ocp, :c00)(x, ∅) == x + @test __constraint(ocp, :cff)(∅, x) == x ocp = Model() time!(ocp; t0 = 0, tf = 1) @@ -853,8 +853,8 @@ function test_model() # 30 55 185 xf = [1, 2] constraint!(ocp, :initial, rg = 1:2, lb = x0, ub = x0, label = :c0) constraint!(ocp, :final, rg = 1:2, lb = xf, ub = xf, label = :cf) - @test constraint(ocp, :c0)(x, ∅) == x[1:2] - @test constraint(ocp, :cf)(∅, x) == x[1:2] + @test __constraint(ocp, :c0)(x, ∅) == x[1:2] + @test __constraint(ocp, :cf)(∅, x) == x[1:2] # constraint already exists ocp = Model() @@ -874,10 +874,10 @@ function test_model() # 30 55 185 constraint!(ocp, :final, lb = 1, ub = 2, label = :cf) constraint!(ocp, :control, lb = 0, ub = 1, label = :cu) constraint!(ocp, :state, lb = 0, ub = 1, label = :cs) - @test constraint(ocp, :c0)(12, ∅) == 12 - @test constraint(ocp, :cf)(∅, 12) == 12 - @test constraint(ocp, :cu)(12) == 12 - @test constraint(ocp, :cs)(12) == 12 + @test __constraint(ocp, :c0)(12, ∅) == 12 + @test __constraint(ocp, :cf)(∅, 12) == 12 + @test __constraint(ocp, :cu)(12) == 12 + @test __constraint(ocp, :cs)(12) == 12 ocp = Model() time!(ocp; t0 = 0, tf = 1) @@ -887,10 +887,10 @@ function test_model() # 30 55 185 constraint!(ocp, :final, lb = [1, 2], ub = [2, 3], label = :cf) constraint!(ocp, :control, lb = [0, 1], ub = [1, 2], label = :cu) constraint!(ocp, :state, lb = [0, 1], ub = [1, 2], label = :cs) - @test constraint(ocp, :c0)([12, 13], ∅) == [12, 13] - @test constraint(ocp, :cf)(∅, [12, 13]) == [12, 13] - @test constraint(ocp, :cu)([12, 13]) == [12, 13] - @test constraint(ocp, :cs)([12, 13]) == [12, 13] + @test __constraint(ocp, :c0)([12, 13], ∅) == [12, 13] + @test __constraint(ocp, :cf)(∅, [12, 13]) == [12, 13] + @test __constraint(ocp, :cu)([12, 13]) == [12, 13] + @test __constraint(ocp, :cs)([12, 13]) == [12, 13] # constraint already exists ocp = Model() @@ -910,10 +910,10 @@ function test_model() # 30 55 185 constraint!(ocp, :final, rg = 1, lb = 1, ub = 2, label = :cf) constraint!(ocp, :control, rg = 1, lb = 0, ub = 1, label = :cu) constraint!(ocp, :state, rg = 1, lb = 0, ub = 1, label = :cs) - @test constraint(ocp, :c0)(12, ∅) == 12 - @test constraint(ocp, :cf)(∅, 12) == 12 - @test constraint(ocp, :cu)(12) == 12 - @test constraint(ocp, :cs)(12) == 12 + @test __constraint(ocp, :c0)(12, ∅) == 12 + @test __constraint(ocp, :cf)(∅, 12) == 12 + @test __constraint(ocp, :cu)(12) == 12 + @test __constraint(ocp, :cs)(12) == 12 ocp = Model() time!(ocp; t0 = 0, tf = 1) @@ -960,10 +960,10 @@ function test_model() # 30 55 185 constraint!(ocp, :final, rg = 1:2, lb = [1, 2], ub = [2, 3], label = :cf) constraint!(ocp, :control, rg = 1:2, lb = [0, 1], ub = [1, 2], label = :cu) constraint!(ocp, :state, rg = 1:2, lb = [0, 1], ub = [1, 2], label = :cs) - @test constraint(ocp, :c0)([12, 13], ∅) == [12, 13] - @test constraint(ocp, :cf)(∅, [12, 13]) == [12, 13] - @test constraint(ocp, :cu)([12, 13]) == [12, 13] - @test constraint(ocp, :cs)([12, 13]) == [12, 13] + @test __constraint(ocp, :c0)([12, 13], ∅) == [12, 13] + @test __constraint(ocp, :cf)(∅, [12, 13]) == [12, 13] + @test __constraint(ocp, :cu)([12, 13]) == [12, 13] + @test __constraint(ocp, :cs)([12, 13]) == [12, 13] # constraint already exists ocp = Model() @@ -983,10 +983,10 @@ function test_model() # 30 55 185 constraint!(ocp, :control, f = u -> u, lb = 0, ub = 0, label = :cu) constraint!(ocp, :state, f = x -> x, lb = 0, ub = 0, label = :cs) constraint!(ocp, :mixed, f = (x, u) -> x + u, lb = 1, ub = 1, label = :cm) - @test constraint(ocp, :cb)(12, 13) == 12 + 13 - @test constraint(ocp, :cu)(12) == 12 - @test constraint(ocp, :cs)(12) == 12 - @test constraint(ocp, :cm)(12, 13) == 12 + 13 + @test __constraint(ocp, :cb)(12, 13) == 12 + 13 + @test __constraint(ocp, :cu)(12) == 12 + @test __constraint(ocp, :cs)(12) == 12 + @test __constraint(ocp, :cm)(12, 13) == 12 + 13 ocp = Model() time!(ocp; t0 = 0, tf = 1) @@ -996,10 +996,10 @@ function test_model() # 30 55 185 constraint!(ocp, :control, f = u -> u[1], lb = 0, ub = 0, label = :cu) constraint!(ocp, :state, f = x -> x[1], lb = 0, ub = 0, label = :cs) constraint!(ocp, :mixed, f = (x, u) -> x[1] + u[1], lb = 1, ub = 1, label = :cm) - @test constraint(ocp, :cb)([13, 14], [16, 17]) == 13 + 16 - @test constraint(ocp, :cu)([12, 13]) == 12 - @test constraint(ocp, :cs)([12, 13]) == 12 - @test constraint(ocp, :cm)([12, 13], [14, 15]) == 12 + 14 + @test __constraint(ocp, :cb)([13, 14], [16, 17]) == 13 + 16 + @test __constraint(ocp, :cu)([12, 13]) == 12 + @test __constraint(ocp, :cs)([12, 13]) == 12 + @test __constraint(ocp, :cm)([12, 13], [14, 15]) == 12 + 14 ocp = Model() time!(ocp; t0 = 0, tf = 1) @@ -1023,10 +1023,10 @@ function test_model() # 30 55 185 ub = [0, 0], label = :cm, ) - @test constraint(ocp, :cb)([13, 14, 15], [17, 18, 19]) == [13 + 17, 14 + 18] - @test constraint(ocp, :cu)([12, 13, 14]) == [12, 13] - @test constraint(ocp, :cs)([12, 13, 14]) == [12, 13] - @test constraint(ocp, :cm)([12, 13, 14], [15, 16, 17]) == [12 + 15, 13 + 16] + @test __constraint(ocp, :cb)([13, 14, 15], [17, 18, 19]) == [13 + 17, 14 + 18] + @test __constraint(ocp, :cu)([12, 13, 14]) == [12, 13] + @test __constraint(ocp, :cs)([12, 13, 14]) == [12, 13] + @test __constraint(ocp, :cm)([12, 13, 14], [15, 16, 17]) == [12 + 15, 13 + 16] # constraint already exists ocp = Model() @@ -1053,10 +1053,10 @@ function test_model() # 30 55 185 constraint!(ocp, :control, f = u -> u, lb = 0, ub = 1, label = :cu) constraint!(ocp, :state, f = x -> x, lb = 0, ub = 1, label = :cs) constraint!(ocp, :mixed, f = (x, u) -> x + u, lb = 1, ub = 1, label = :cm) - @test constraint(ocp, :cb)(12, 13) == 12 + 13 - @test constraint(ocp, :cu)(12) == 12 - @test constraint(ocp, :cs)(12) == 12 - @test constraint(ocp, :cm)(12, 13) == 12 + 13 + @test __constraint(ocp, :cb)(12, 13) == 12 + 13 + @test __constraint(ocp, :cu)(12) == 12 + @test __constraint(ocp, :cs)(12) == 12 + @test __constraint(ocp, :cm)(12, 13) == 12 + 13 ocp = Model() time!(ocp; t0 = 0, tf = 1) @@ -1066,10 +1066,10 @@ function test_model() # 30 55 185 constraint!(ocp, :control, f = u -> u[1], lb = 0, ub = 1, label = :cu) constraint!(ocp, :state, f = x -> x[1], lb = 0, ub = 1, label = :cs) constraint!(ocp, :mixed, f = (x, u) -> x[1] + u[1], lb = 1, ub = 1, label = :cm) - @test constraint(ocp, :cb)([13, 14], [16, 17]) == 13 + 16 - @test constraint(ocp, :cu)([12, 13]) == 12 - @test constraint(ocp, :cs)([12, 13]) == 12 - @test constraint(ocp, :cm)([12, 13], [14, 15]) == 12 + 14 + @test __constraint(ocp, :cb)([13, 14], [16, 17]) == 13 + 16 + @test __constraint(ocp, :cu)([12, 13]) == 12 + @test __constraint(ocp, :cs)([12, 13]) == 12 + @test __constraint(ocp, :cm)([12, 13], [14, 15]) == 12 + 14 ocp = Model() time!(ocp; t0 = 0, tf = 1) @@ -1093,10 +1093,10 @@ function test_model() # 30 55 185 ub = [1, 1], label = :cm, ) - @test constraint(ocp, :cb)([13, 14, 15], [17, 18, 19]) == [13 + 17, 14 + 18] - @test constraint(ocp, :cu)([12, 13, 14]) == [12, 13] - @test constraint(ocp, :cs)([12, 13, 14]) == [12, 13] - @test constraint(ocp, :cm)([12, 13, 14], [15, 16, 17]) == [12 + 15, 13 + 16] + @test __constraint(ocp, :cb)([13, 14, 15], [17, 18, 19]) == [13 + 17, 14 + 18] + @test __constraint(ocp, :cu)([12, 13, 14]) == [12, 13] + @test __constraint(ocp, :cs)([12, 13, 14]) == [12, 13] + @test __constraint(ocp, :cm)([12, 13, 14], [15, 16, 17]) == [12 + 15, 13 + 16] end @testset "constraint! 7" begin @@ -1122,11 +1122,11 @@ function test_model() # 30 55 185 ub = [1, 0, 1, 0], label = :eq5, ) - @test constraint(ocp, :eq1)(v) == v - @test constraint(ocp, :eq2)(v) == v[1] - @test constraint(ocp, :eq3)(v) == v[1:2] - @test constraint(ocp, :eq4)(v) == v[1:2:4] - @test constraint(ocp, :eq5)(v) == v .^ 2 + @test __constraint(ocp, :eq1)(v) == v + @test __constraint(ocp, :eq2)(v) == v[1] + @test __constraint(ocp, :eq3)(v) == v[1:2] + @test __constraint(ocp, :eq4)(v) == v[1:2:4] + @test __constraint(ocp, :eq5)(v) == v .^ 2 end @testset "constraint! 8" begin @@ -1156,15 +1156,15 @@ function test_model() # 30 55 185 ub = [0, 0, 0, 0], label = :eq5, ) - @test constraint(ocp, :cb)(x0, xf, v) == x0 + xf + v[1] - @test constraint(ocp, :cu)(u, v) == u + v[1] - @test constraint(ocp, :cs)(x, v) == x + v[1] - @test constraint(ocp, :cm)(x, u, v) == x + u + v[1] - @test constraint(ocp, :eq1)(v) == v - @test constraint(ocp, :eq2)(v) == v[1] - @test constraint(ocp, :eq3)(v) == v[1:2] - @test constraint(ocp, :eq4)(v) == v[1:2:4] - @test constraint(ocp, :eq5)(v) == v .^ 2 + @test __constraint(ocp, :cb)(x0, xf, v) == x0 + xf + v[1] + @test __constraint(ocp, :cu)(u, v) == u + v[1] + @test __constraint(ocp, :cs)(x, v) == x + v[1] + @test __constraint(ocp, :cm)(x, u, v) == x + u + v[1] + @test __constraint(ocp, :eq1)(v) == v + @test __constraint(ocp, :eq2)(v) == v[1] + @test __constraint(ocp, :eq3)(v) == v[1:2] + @test __constraint(ocp, :eq4)(v) == v[1:2:4] + @test __constraint(ocp, :eq5)(v) == v .^ 2 end @testset "constraint! 9" begin @@ -1173,28 +1173,28 @@ function test_model() # 30 55 185 state!(ocp, 1) control!(ocp, 1) dynamics!(ocp, (x, u) -> x + u) - @test dynamics(ocp)(1, 2) == 3 + @test __dynamics(ocp)(1, 2) == 3 ocp = Model() time!(ocp; t0 = 0, tf = 1) state!(ocp, 2) control!(ocp, 2) dynamics!(ocp, (x, u) -> x[1] + u[1]) - @test dynamics(ocp)([1, 2], [3, 4]) == 4 + @test __dynamics(ocp)([1, 2], [3, 4]) == 4 ocp = Model() time!(ocp; t0 = 0, tf = 1) state!(ocp, 2) control!(ocp, 2) dynamics!(ocp, (x, u) -> [x[1] + u[1], x[2] + u[2]]) - @test dynamics(ocp)([1, 2], [3, 4]) == [4, 6] + @test __dynamics(ocp)([1, 2], [3, 4]) == [4, 6] ocp = Model() time!(ocp; t0 = 0, tf = 1) state!(ocp, 2) control!(ocp, 1) dynamics!(ocp, (x, u) -> [x[1] + u, x[2] + u]) - @test dynamics(ocp)([1, 2], 3) == [4, 5] + @test __dynamics(ocp)([1, 2], 3) == [4, 5] end @testset "constraint! 10" begin @@ -1204,8 +1204,8 @@ function test_model() # 30 55 185 control!(ocp, 1) constraint!(ocp, :initial, lb = 0, ub = 1, label = :c0) constraint!(ocp, :final, lb = 1, ub = 2, label = :cf) - @test constraint(ocp, :c0)(12, ∅) == 12 - @test constraint(ocp, :cf)(∅, 12) == 12 + @test __constraint(ocp, :c0)(12, ∅) == 12 + @test __constraint(ocp, :cf)(∅, 12) == 12 end @testset "constraint! 11" begin @@ -1888,60 +1888,60 @@ function test_model() # 30 55 185 state!(ocp, 1) control!(ocp, 1) objective!(ocp, :lagrange, (x, u) -> 0.5u^2) - @test lagrange(ocp)(1, 2) == 2 + @test __lagrange(ocp)(1, 2) == 2 ocp = Model() time!(ocp; t0 = 0, tf = 1) state!(ocp, 2) control!(ocp, 2) objective!(ocp, :lagrange, (x, u) -> 0.5u[1]^2) - @test lagrange(ocp)([1, 2], [3, 4]) == 4.5 + @test __lagrange(ocp)([1, 2], [3, 4]) == 4.5 ocp = Model() time!(ocp; t0 = 0, tf = 1) state!(ocp, 1) control!(ocp, 1) objective!(ocp, :mayer, (x0, xf) -> 0.5x0^2) - @test mayer(ocp)(2, 3) == 2 + @test __mayer(ocp)(2, 3) == 2 ocp = Model() time!(ocp; t0 = 0, tf = 1) state!(ocp, 2) control!(ocp, 2) objective!(ocp, :mayer, (x0, xf) -> 0.5x0[1]^2) - @test mayer(ocp)([2, 3], [5, 6]) == 2 + @test __mayer(ocp)([2, 3], [5, 6]) == 2 ocp = Model() time!(ocp; t0 = 0, tf = 1) state!(ocp, 1) control!(ocp, 1) objective!(ocp, :bolza, (x0, xf) -> 0.5x0^2, (x, u) -> 0.5u^2) - @test mayer(ocp)(2, 3) == 2 - @test lagrange(ocp)(1, 2) == 2 + @test __mayer(ocp)(2, 3) == 2 + @test __lagrange(ocp)(1, 2) == 2 ocp = Model() time!(ocp; t0 = 0, tf = 1) state!(ocp, 2) control!(ocp, 2) objective!(ocp, :bolza, (x0, xf) -> 0.5x0[1]^2, (x, u) -> 0.5u[1]^2) - @test mayer(ocp)([2, 3], [5, 6]) == 2 - @test lagrange(ocp)([1, 2], [3, 4]) == 4.5 + @test __mayer(ocp)([2, 3], [5, 6]) == 2 + @test __lagrange(ocp)([1, 2], [3, 4]) == 4.5 ocp = Model() time!(ocp; t0 = 0, tf = 1) state!(ocp, 2) control!(ocp, 2) objective!(ocp, :lagrange, (x, u) -> 0.5u[1]^2) - @test lagrange(ocp)([1, 2], [3, 4]) == 4.5 - @test isnothing(mayer(ocp)) + @test __lagrange(ocp)([1, 2], [3, 4]) == 4.5 + @test isnothing(__mayer(ocp)) ocp = Model() time!(ocp; t0 = 0, tf = 1) state!(ocp, 2) control!(ocp, 2) objective!(ocp, :mayer, (x0, xf) -> 0.5x0[1]^2) - @test mayer(ocp)([2, 3], [5, 6]) == 2 - @test isnothing(lagrange(ocp)) + @test __mayer(ocp)([2, 3], [5, 6]) == 2 + @test isnothing(__lagrange(ocp)) end @testset "redeclarations" begin diff --git a/test/test_plot.jl b/test/test_plot.jl index 7e6fc3ac..2652dd18 100644 --- a/test/test_plot.jl +++ b/test/test_plot.jl @@ -51,4 +51,4 @@ function test_plot() @test plot(sol, layout = :split) isa Plots.Plot @test plot(sol, layout = :group) isa Plots.Plot @test display(sol) isa Nothing -end +end \ No newline at end of file From c1bed0a8e7889856bf03e56990b80b3b3d53a3c4 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Caillau Date: Fri, 6 Sep 2024 18:24:12 +0200 Subject: [PATCH 19/33] removed useless change to __getter in test_model, as everything is functional and oop (= out of place) --- test/test_model.jl | 164 +++++++++++++++--------------- test/test_plot_joseph.jl | 54 ---------- test/test_plot_manual.jl | 211 --------------------------------------- 3 files changed, 82 insertions(+), 347 deletions(-) delete mode 100644 test/test_plot_joseph.jl delete mode 100644 test/test_plot_manual.jl diff --git a/test/test_model.jl b/test/test_model.jl index b0cd0515..29a34447 100644 --- a/test/test_model.jl +++ b/test/test_model.jl @@ -781,8 +781,8 @@ function test_model() # 30 55 185 ) constraint!(ocp, :initial, lb = 0, ub = 0, label = :c0) constraint!(ocp, :final, lb = 1, ub = 1, label = :cf) - @test __constraint(ocp, :c0)(12, ∅) == 12 - @test __constraint(ocp, :cf)(∅, 12) == 12 + @test constraint(ocp, :c0)(12, ∅) == 12 + @test constraint(ocp, :cf)(∅, 12) == 12 ocp = Model() time!(ocp; t0 = 0, tf = 1) @@ -790,8 +790,8 @@ function test_model() # 30 55 185 control!(ocp, 1) constraint!(ocp, :initial, lb = [0, 1], ub = [0, 1], label = :c0) constraint!(ocp, :final, lb = [1, 2], ub = [1, 2], label = :cf) - @test __constraint(ocp, :c0)([12, 13], ∅) == [12, 13] - @test __constraint(ocp, :cf)(∅, [12, 13]) == [12, 13] + @test constraint(ocp, :c0)([12, 13], ∅) == [12, 13] + @test constraint(ocp, :cf)(∅, [12, 13]) == [12, 13] # constraint already exists ocp = Model() @@ -812,13 +812,13 @@ function test_model() # 30 55 185 xf = 1 constraint!(ocp, :initial, rg = 1, lb = x0, ub = x0, label = :c0) constraint!(ocp, :final, rg = 1, lb = xf, ub = xf, label = :cf) - @test __constraint(ocp, :c0)(x, ∅) == x - @test __constraint(ocp, :cf)(∅, x) == x + @test constraint(ocp, :c0)(x, ∅) == x + @test constraint(ocp, :cf)(∅, x) == x constraint!(ocp, :initial, rg = 1, lb = x0, ub = x0, label = :c00) constraint!(ocp, :final, rg = 1, lb = xf, ub = xf, label = :cff) - @test __constraint(ocp, :c00)(x, ∅) == x - @test __constraint(ocp, :cff)(∅, x) == x + @test constraint(ocp, :c00)(x, ∅) == x + @test constraint(ocp, :cff)(∅, x) == x ocp = Model() time!(ocp; t0 = 0, tf = 1) @@ -853,8 +853,8 @@ function test_model() # 30 55 185 xf = [1, 2] constraint!(ocp, :initial, rg = 1:2, lb = x0, ub = x0, label = :c0) constraint!(ocp, :final, rg = 1:2, lb = xf, ub = xf, label = :cf) - @test __constraint(ocp, :c0)(x, ∅) == x[1:2] - @test __constraint(ocp, :cf)(∅, x) == x[1:2] + @test constraint(ocp, :c0)(x, ∅) == x[1:2] + @test constraint(ocp, :cf)(∅, x) == x[1:2] # constraint already exists ocp = Model() @@ -874,10 +874,10 @@ function test_model() # 30 55 185 constraint!(ocp, :final, lb = 1, ub = 2, label = :cf) constraint!(ocp, :control, lb = 0, ub = 1, label = :cu) constraint!(ocp, :state, lb = 0, ub = 1, label = :cs) - @test __constraint(ocp, :c0)(12, ∅) == 12 - @test __constraint(ocp, :cf)(∅, 12) == 12 - @test __constraint(ocp, :cu)(12) == 12 - @test __constraint(ocp, :cs)(12) == 12 + @test constraint(ocp, :c0)(12, ∅) == 12 + @test constraint(ocp, :cf)(∅, 12) == 12 + @test constraint(ocp, :cu)(12) == 12 + @test constraint(ocp, :cs)(12) == 12 ocp = Model() time!(ocp; t0 = 0, tf = 1) @@ -887,10 +887,10 @@ function test_model() # 30 55 185 constraint!(ocp, :final, lb = [1, 2], ub = [2, 3], label = :cf) constraint!(ocp, :control, lb = [0, 1], ub = [1, 2], label = :cu) constraint!(ocp, :state, lb = [0, 1], ub = [1, 2], label = :cs) - @test __constraint(ocp, :c0)([12, 13], ∅) == [12, 13] - @test __constraint(ocp, :cf)(∅, [12, 13]) == [12, 13] - @test __constraint(ocp, :cu)([12, 13]) == [12, 13] - @test __constraint(ocp, :cs)([12, 13]) == [12, 13] + @test constraint(ocp, :c0)([12, 13], ∅) == [12, 13] + @test constraint(ocp, :cf)(∅, [12, 13]) == [12, 13] + @test constraint(ocp, :cu)([12, 13]) == [12, 13] + @test constraint(ocp, :cs)([12, 13]) == [12, 13] # constraint already exists ocp = Model() @@ -910,10 +910,10 @@ function test_model() # 30 55 185 constraint!(ocp, :final, rg = 1, lb = 1, ub = 2, label = :cf) constraint!(ocp, :control, rg = 1, lb = 0, ub = 1, label = :cu) constraint!(ocp, :state, rg = 1, lb = 0, ub = 1, label = :cs) - @test __constraint(ocp, :c0)(12, ∅) == 12 - @test __constraint(ocp, :cf)(∅, 12) == 12 - @test __constraint(ocp, :cu)(12) == 12 - @test __constraint(ocp, :cs)(12) == 12 + @test constraint(ocp, :c0)(12, ∅) == 12 + @test constraint(ocp, :cf)(∅, 12) == 12 + @test constraint(ocp, :cu)(12) == 12 + @test constraint(ocp, :cs)(12) == 12 ocp = Model() time!(ocp; t0 = 0, tf = 1) @@ -960,10 +960,10 @@ function test_model() # 30 55 185 constraint!(ocp, :final, rg = 1:2, lb = [1, 2], ub = [2, 3], label = :cf) constraint!(ocp, :control, rg = 1:2, lb = [0, 1], ub = [1, 2], label = :cu) constraint!(ocp, :state, rg = 1:2, lb = [0, 1], ub = [1, 2], label = :cs) - @test __constraint(ocp, :c0)([12, 13], ∅) == [12, 13] - @test __constraint(ocp, :cf)(∅, [12, 13]) == [12, 13] - @test __constraint(ocp, :cu)([12, 13]) == [12, 13] - @test __constraint(ocp, :cs)([12, 13]) == [12, 13] + @test constraint(ocp, :c0)([12, 13], ∅) == [12, 13] + @test constraint(ocp, :cf)(∅, [12, 13]) == [12, 13] + @test constraint(ocp, :cu)([12, 13]) == [12, 13] + @test constraint(ocp, :cs)([12, 13]) == [12, 13] # constraint already exists ocp = Model() @@ -983,10 +983,10 @@ function test_model() # 30 55 185 constraint!(ocp, :control, f = u -> u, lb = 0, ub = 0, label = :cu) constraint!(ocp, :state, f = x -> x, lb = 0, ub = 0, label = :cs) constraint!(ocp, :mixed, f = (x, u) -> x + u, lb = 1, ub = 1, label = :cm) - @test __constraint(ocp, :cb)(12, 13) == 12 + 13 - @test __constraint(ocp, :cu)(12) == 12 - @test __constraint(ocp, :cs)(12) == 12 - @test __constraint(ocp, :cm)(12, 13) == 12 + 13 + @test constraint(ocp, :cb)(12, 13) == 12 + 13 + @test constraint(ocp, :cu)(12) == 12 + @test constraint(ocp, :cs)(12) == 12 + @test constraint(ocp, :cm)(12, 13) == 12 + 13 ocp = Model() time!(ocp; t0 = 0, tf = 1) @@ -996,10 +996,10 @@ function test_model() # 30 55 185 constraint!(ocp, :control, f = u -> u[1], lb = 0, ub = 0, label = :cu) constraint!(ocp, :state, f = x -> x[1], lb = 0, ub = 0, label = :cs) constraint!(ocp, :mixed, f = (x, u) -> x[1] + u[1], lb = 1, ub = 1, label = :cm) - @test __constraint(ocp, :cb)([13, 14], [16, 17]) == 13 + 16 - @test __constraint(ocp, :cu)([12, 13]) == 12 - @test __constraint(ocp, :cs)([12, 13]) == 12 - @test __constraint(ocp, :cm)([12, 13], [14, 15]) == 12 + 14 + @test constraint(ocp, :cb)([13, 14], [16, 17]) == 13 + 16 + @test constraint(ocp, :cu)([12, 13]) == 12 + @test constraint(ocp, :cs)([12, 13]) == 12 + @test constraint(ocp, :cm)([12, 13], [14, 15]) == 12 + 14 ocp = Model() time!(ocp; t0 = 0, tf = 1) @@ -1023,10 +1023,10 @@ function test_model() # 30 55 185 ub = [0, 0], label = :cm, ) - @test __constraint(ocp, :cb)([13, 14, 15], [17, 18, 19]) == [13 + 17, 14 + 18] - @test __constraint(ocp, :cu)([12, 13, 14]) == [12, 13] - @test __constraint(ocp, :cs)([12, 13, 14]) == [12, 13] - @test __constraint(ocp, :cm)([12, 13, 14], [15, 16, 17]) == [12 + 15, 13 + 16] + @test constraint(ocp, :cb)([13, 14, 15], [17, 18, 19]) == [13 + 17, 14 + 18] + @test constraint(ocp, :cu)([12, 13, 14]) == [12, 13] + @test constraint(ocp, :cs)([12, 13, 14]) == [12, 13] + @test constraint(ocp, :cm)([12, 13, 14], [15, 16, 17]) == [12 + 15, 13 + 16] # constraint already exists ocp = Model() @@ -1053,10 +1053,10 @@ function test_model() # 30 55 185 constraint!(ocp, :control, f = u -> u, lb = 0, ub = 1, label = :cu) constraint!(ocp, :state, f = x -> x, lb = 0, ub = 1, label = :cs) constraint!(ocp, :mixed, f = (x, u) -> x + u, lb = 1, ub = 1, label = :cm) - @test __constraint(ocp, :cb)(12, 13) == 12 + 13 - @test __constraint(ocp, :cu)(12) == 12 - @test __constraint(ocp, :cs)(12) == 12 - @test __constraint(ocp, :cm)(12, 13) == 12 + 13 + @test constraint(ocp, :cb)(12, 13) == 12 + 13 + @test constraint(ocp, :cu)(12) == 12 + @test constraint(ocp, :cs)(12) == 12 + @test constraint(ocp, :cm)(12, 13) == 12 + 13 ocp = Model() time!(ocp; t0 = 0, tf = 1) @@ -1066,10 +1066,10 @@ function test_model() # 30 55 185 constraint!(ocp, :control, f = u -> u[1], lb = 0, ub = 1, label = :cu) constraint!(ocp, :state, f = x -> x[1], lb = 0, ub = 1, label = :cs) constraint!(ocp, :mixed, f = (x, u) -> x[1] + u[1], lb = 1, ub = 1, label = :cm) - @test __constraint(ocp, :cb)([13, 14], [16, 17]) == 13 + 16 - @test __constraint(ocp, :cu)([12, 13]) == 12 - @test __constraint(ocp, :cs)([12, 13]) == 12 - @test __constraint(ocp, :cm)([12, 13], [14, 15]) == 12 + 14 + @test constraint(ocp, :cb)([13, 14], [16, 17]) == 13 + 16 + @test constraint(ocp, :cu)([12, 13]) == 12 + @test constraint(ocp, :cs)([12, 13]) == 12 + @test constraint(ocp, :cm)([12, 13], [14, 15]) == 12 + 14 ocp = Model() time!(ocp; t0 = 0, tf = 1) @@ -1093,10 +1093,10 @@ function test_model() # 30 55 185 ub = [1, 1], label = :cm, ) - @test __constraint(ocp, :cb)([13, 14, 15], [17, 18, 19]) == [13 + 17, 14 + 18] - @test __constraint(ocp, :cu)([12, 13, 14]) == [12, 13] - @test __constraint(ocp, :cs)([12, 13, 14]) == [12, 13] - @test __constraint(ocp, :cm)([12, 13, 14], [15, 16, 17]) == [12 + 15, 13 + 16] + @test constraint(ocp, :cb)([13, 14, 15], [17, 18, 19]) == [13 + 17, 14 + 18] + @test constraint(ocp, :cu)([12, 13, 14]) == [12, 13] + @test constraint(ocp, :cs)([12, 13, 14]) == [12, 13] + @test constraint(ocp, :cm)([12, 13, 14], [15, 16, 17]) == [12 + 15, 13 + 16] end @testset "constraint! 7" begin @@ -1122,11 +1122,11 @@ function test_model() # 30 55 185 ub = [1, 0, 1, 0], label = :eq5, ) - @test __constraint(ocp, :eq1)(v) == v - @test __constraint(ocp, :eq2)(v) == v[1] - @test __constraint(ocp, :eq3)(v) == v[1:2] - @test __constraint(ocp, :eq4)(v) == v[1:2:4] - @test __constraint(ocp, :eq5)(v) == v .^ 2 + @test constraint(ocp, :eq1)(v) == v + @test constraint(ocp, :eq2)(v) == v[1] + @test constraint(ocp, :eq3)(v) == v[1:2] + @test constraint(ocp, :eq4)(v) == v[1:2:4] + @test constraint(ocp, :eq5)(v) == v .^ 2 end @testset "constraint! 8" begin @@ -1156,15 +1156,15 @@ function test_model() # 30 55 185 ub = [0, 0, 0, 0], label = :eq5, ) - @test __constraint(ocp, :cb)(x0, xf, v) == x0 + xf + v[1] - @test __constraint(ocp, :cu)(u, v) == u + v[1] - @test __constraint(ocp, :cs)(x, v) == x + v[1] - @test __constraint(ocp, :cm)(x, u, v) == x + u + v[1] - @test __constraint(ocp, :eq1)(v) == v - @test __constraint(ocp, :eq2)(v) == v[1] - @test __constraint(ocp, :eq3)(v) == v[1:2] - @test __constraint(ocp, :eq4)(v) == v[1:2:4] - @test __constraint(ocp, :eq5)(v) == v .^ 2 + @test constraint(ocp, :cb)(x0, xf, v) == x0 + xf + v[1] + @test constraint(ocp, :cu)(u, v) == u + v[1] + @test constraint(ocp, :cs)(x, v) == x + v[1] + @test constraint(ocp, :cm)(x, u, v) == x + u + v[1] + @test constraint(ocp, :eq1)(v) == v + @test constraint(ocp, :eq2)(v) == v[1] + @test constraint(ocp, :eq3)(v) == v[1:2] + @test constraint(ocp, :eq4)(v) == v[1:2:4] + @test constraint(ocp, :eq5)(v) == v .^ 2 end @testset "constraint! 9" begin @@ -1173,28 +1173,28 @@ function test_model() # 30 55 185 state!(ocp, 1) control!(ocp, 1) dynamics!(ocp, (x, u) -> x + u) - @test __dynamics(ocp)(1, 2) == 3 + @test dynamics(ocp)(1, 2) == 3 ocp = Model() time!(ocp; t0 = 0, tf = 1) state!(ocp, 2) control!(ocp, 2) dynamics!(ocp, (x, u) -> x[1] + u[1]) - @test __dynamics(ocp)([1, 2], [3, 4]) == 4 + @test dynamics(ocp)([1, 2], [3, 4]) == 4 ocp = Model() time!(ocp; t0 = 0, tf = 1) state!(ocp, 2) control!(ocp, 2) dynamics!(ocp, (x, u) -> [x[1] + u[1], x[2] + u[2]]) - @test __dynamics(ocp)([1, 2], [3, 4]) == [4, 6] + @test dynamics(ocp)([1, 2], [3, 4]) == [4, 6] ocp = Model() time!(ocp; t0 = 0, tf = 1) state!(ocp, 2) control!(ocp, 1) dynamics!(ocp, (x, u) -> [x[1] + u, x[2] + u]) - @test __dynamics(ocp)([1, 2], 3) == [4, 5] + @test dynamics(ocp)([1, 2], 3) == [4, 5] end @testset "constraint! 10" begin @@ -1204,8 +1204,8 @@ function test_model() # 30 55 185 control!(ocp, 1) constraint!(ocp, :initial, lb = 0, ub = 1, label = :c0) constraint!(ocp, :final, lb = 1, ub = 2, label = :cf) - @test __constraint(ocp, :c0)(12, ∅) == 12 - @test __constraint(ocp, :cf)(∅, 12) == 12 + @test constraint(ocp, :c0)(12, ∅) == 12 + @test constraint(ocp, :cf)(∅, 12) == 12 end @testset "constraint! 11" begin @@ -1888,60 +1888,60 @@ function test_model() # 30 55 185 state!(ocp, 1) control!(ocp, 1) objective!(ocp, :lagrange, (x, u) -> 0.5u^2) - @test __lagrange(ocp)(1, 2) == 2 + @test lagrange(ocp)(1, 2) == 2 ocp = Model() time!(ocp; t0 = 0, tf = 1) state!(ocp, 2) control!(ocp, 2) objective!(ocp, :lagrange, (x, u) -> 0.5u[1]^2) - @test __lagrange(ocp)([1, 2], [3, 4]) == 4.5 + @test lagrange(ocp)([1, 2], [3, 4]) == 4.5 ocp = Model() time!(ocp; t0 = 0, tf = 1) state!(ocp, 1) control!(ocp, 1) objective!(ocp, :mayer, (x0, xf) -> 0.5x0^2) - @test __mayer(ocp)(2, 3) == 2 + @test mayer(ocp)(2, 3) == 2 ocp = Model() time!(ocp; t0 = 0, tf = 1) state!(ocp, 2) control!(ocp, 2) objective!(ocp, :mayer, (x0, xf) -> 0.5x0[1]^2) - @test __mayer(ocp)([2, 3], [5, 6]) == 2 + @test mayer(ocp)([2, 3], [5, 6]) == 2 ocp = Model() time!(ocp; t0 = 0, tf = 1) state!(ocp, 1) control!(ocp, 1) objective!(ocp, :bolza, (x0, xf) -> 0.5x0^2, (x, u) -> 0.5u^2) - @test __mayer(ocp)(2, 3) == 2 - @test __lagrange(ocp)(1, 2) == 2 + @test mayer(ocp)(2, 3) == 2 + @test lagrange(ocp)(1, 2) == 2 ocp = Model() time!(ocp; t0 = 0, tf = 1) state!(ocp, 2) control!(ocp, 2) objective!(ocp, :bolza, (x0, xf) -> 0.5x0[1]^2, (x, u) -> 0.5u[1]^2) - @test __mayer(ocp)([2, 3], [5, 6]) == 2 - @test __lagrange(ocp)([1, 2], [3, 4]) == 4.5 + @test mayer(ocp)([2, 3], [5, 6]) == 2 + @test lagrange(ocp)([1, 2], [3, 4]) == 4.5 ocp = Model() time!(ocp; t0 = 0, tf = 1) state!(ocp, 2) control!(ocp, 2) objective!(ocp, :lagrange, (x, u) -> 0.5u[1]^2) - @test __lagrange(ocp)([1, 2], [3, 4]) == 4.5 - @test isnothing(__mayer(ocp)) + @test lagrange(ocp)([1, 2], [3, 4]) == 4.5 + @test isnothing(mayer(ocp)) ocp = Model() time!(ocp; t0 = 0, tf = 1) state!(ocp, 2) control!(ocp, 2) objective!(ocp, :mayer, (x0, xf) -> 0.5x0[1]^2) - @test __mayer(ocp)([2, 3], [5, 6]) == 2 - @test isnothing(__lagrange(ocp)) + @test mayer(ocp)([2, 3], [5, 6]) == 2 + @test isnothing(lagrange(ocp)) end @testset "redeclarations" begin diff --git a/test/test_plot_joseph.jl b/test/test_plot_joseph.jl deleted file mode 100644 index 0f401559..00000000 --- a/test/test_plot_joseph.jl +++ /dev/null @@ -1,54 +0,0 @@ -# using OptimalControl - -# @def ocp begin - -# t ∈ [ 0, 1 ], time -# x ∈ R, state -# u ∈ R, control -# x(0) == 0 -# -1 ≤ u(t) ≤ 1 -# ẋ(t) == -x(t) + u(t) -# x(1) → min - -# end - -# sol = solve(ocp, grid_size=20, print_level=5) -# plt = plot(sol) - -# a la main -using CTBase -using PlotUtils - -n = 1 -m = 1 -t0 = 0 -tf = 1 -x0 = 0 -x = t -> -1 + 1e-8 * rand() -p = t -> 0 + 1e-8 * rand() -u = t -> 0 -objective = 1 -# -N = 201 -times = range(t0, tf, N) -# - -sol = OptimalControlSolution() -sol.state_dimension = n -sol.control_dimension = m -sol.time_grid = times -sol.time_name = "t" -sol.state = x -sol.state_name = "x" -sol.state_components_names = ["x"] -sol.costate = p -sol.control = u -sol.control_name = "u" -sol.control_components_names = ["u"] -sol.objective = objective -sol.iterations = 0 -sol.stopping = :dummy -sol.message = "ceci est un test" -sol.success = true - -plt = plot(sol) diff --git a/test/test_plot_manual.jl b/test/test_plot_manual.jl deleted file mode 100644 index a5ce33a0..00000000 --- a/test/test_plot_manual.jl +++ /dev/null @@ -1,211 +0,0 @@ -using CTBase -using Plots - -layout = :split -size = (900, 600) -control_plt = :all - -# -do_plot_2 = true - -# ---------------------------------------- -# SOL 1 -n = 2 -m = 1 -t0 = 0.0 -tf = 1.0 -x0 = [-1.0, 0.0] -xf = [0.0, 0.0] -a = x0[1] -b = x0[2] -C = [ - -(tf - t0)^3/6.0 (tf - t0)^2/2.0 - -(tf - t0)^2/2.0 (tf-t0) -] -D = [-a - b * (tf - t0), -b] + xf -p0 = C \ D -α = p0[1] -β = p0[2] -x = - t -> [ - a + b * (t - t0) + β * (t - t0)^2 / 2.0 - α * (t - t0)^3 / 6.0, - b + β * (t - t0) - α * (t - t0)^2 / 2.0, - ] -p = t -> [α, -α * (t - t0) + β] -u = t -> [p(t)[2]] -objective = 0.5 * (α^2 * (tf - t0)^3 / 3 + β^2 * (tf - t0) - α * β * (tf - t0)^2) -# -N = 201 -times = range(t0, tf, N) -# - -sol = OptimalControlSolution() -sol.state_dimension = n -sol.control_dimension = m -sol.time_grid = times -sol.time_name = "t" -sol.state = x -sol.state_name = "x" -sol.state_components_names = ["x" * ctindices(i) for i ∈ range(1, n)] -sol.costate = p -sol.control = u -sol.control_name = "u" -sol.control_components_names = ["u"] -sol.objective = objective -sol.iterations = 0 -sol.stopping = :dummy -sol.message = "ceci est un test" -sol.success = true - -# -plt = plot( - sol, - layout = layout, - control = control_plt, - size = size, - flip = true, - linewidth = 5, - solution_label = "sol1", -) -#plot(sol, layout=:group) -#ps=plot(sol, :time, (:state, 1)) -#plot!(ps, sol, :time, (:control, 1)) - -# ---------------------------------------- -# SOL 2 -n = 2 -m = 1 -t0 = 0.0 -tf = 1.0 -x0 = [-1.0, -1.0] -xf = [0.0, 0.0] -a = x0[1] -b = x0[2] -C = [ - -(tf - t0)^3/6.0 (tf - t0)^2/2.0 - -(tf - t0)^2/2.0 (tf-t0) -] -D = [-a - b * (tf - t0), -b] + xf -p0 = C \ D -α = p0[1] -β = p0[2] -x = - t -> [ - a + b * (t - t0) + β * (t - t0)^2 / 2.0 - α * (t - t0)^3 / 6.0, - b + β * (t - t0) - α * (t - t0)^2 / 2.0, - ] -p = t -> [α, -α * (t - t0) + β] -u = t -> [p(t)[2]] -objective = 0.5 * (α^2 * (tf - t0)^3 / 3 + β^2 * (tf - t0) - α * β * (tf - t0)^2) -# -N = 201 -times = range(t0, tf, N) -# - -sol = OptimalControlSolution() -sol.state_dimension = n -sol.control_dimension = m -sol.time_grid = times -sol.time_name = "t" -sol.state = x -sol.state_name = "y" -sol.state_components_names = ["y" * ctindices(i) for i ∈ range(1, n)] -sol.costate = p -sol.control = u -sol.control_name = "v" -sol.control_components_names = ["v"] -sol.objective = objective -sol.iterations = 0 -sol.stopping = :dummy -sol.message = "ceci est un test" -sol.success = true - -if do_plot_2 - plot!(plt, sol, layout = layout, size = size, control = control_plt, solution_label = "sol2") -else - plt -end - -# ---------------------------------------- -# Orbital transfer consumption -#= -n=4 -m=2 - -x0 = [-42272.67, 0, 0, -5796.72] -μ = 5.1658620912*1e12 -rf = 42165.0 ; -rf3 = rf^3 ; -m0 = 2000.0 -F_max = 100.0 -γ_max = F_max*3600.0^2/(m0*10^3) -t0 = 0.0 -α = sqrt(μ/rf3); -β = 0.0 - -tol = 1e-9; - -F_max_100 = 100.0 - -tf_min = 13.40318195708344 # minimal time for Fmax = 100 N -tf = 1.5*tf_min - -Th(F) = F*3600.0^2/(10^3) -u_max = Th(F_max) - -# the solution -x0 = [x0; 0] - -u0(x,p) = [0, 0] -u1(x,p) = p[3:4]/norm(p[3:4]) - -Hc(x,p) = p[1]*x[3] + p[2]*x[4] + p[3]*(-μ*x[1]/norm(x[1:2])^3) + p[4]*(-μ*x[2]/norm(x[1:2])^3) -H(x,p,u) = -norm(u) + Hc(x,p) + u[1]*p[3]*γ_max + u[2]*p[4]*γ_max + p[5]*norm(u) -H0(x,p) = H(x,p,u0(x,p)) -H1(x,p) = H(x,p,u1(x,p)) - -# Flow -f0 = Flow(Hamiltonian(H0)); -f1 = Flow(Hamiltonian(H1)); - -# Initial guess -p0_guess = [0.02698412111231433, 0.006910835140705538, 0.050397371862031096, -0.0032972040120747836, -1.0076835239866583e-23] -ti_guess = [0.4556797711668658, 3.6289692721936913, 11.683607683450061, 12.505465498856514] -ξ_guess = [p0_guess;ti_guess] - -p0 = p0_guess -t1, t2, t3, t4 = ti_guess - -# computing x, p, u -f = f1 * (t1, f0) * (t2, f1) * (t3, f0) * (t4, f1) -ode_sol = f((t0, tf), x0, p0) - -x = t -> ode_sol(t)[1:4] -p = t -> ode_sol(t)[6:9] -u = t -> [0,0]*(t ∈ Interval(t1,t2)∪Interval(t3,t4)) + - p(t)[3:4]/norm(p(t)[3:4])*(t ∈ Interval(t0,t1)∪Interval(t2,t3)∪Interval(t4,tf)) -objective = ode_sol(tf)[5] - -# -N=201 -times = range(t0, tf, N) -# -sol = OptimalControlSolution() #n, m, times, x, p, u) -sol.state_dimension = n -sol.control_dimension = m -sol.time_grid = times -sol.state = x -sol.state_name = "y" -sol.state_components_names = [ "x" * ctindices(1), "x" * ctindices(2), "v" * ctindices(1), "v" * ctindices(2)] -sol.adjoint = p -sol.control = u -sol.control_name = "u" -sol.control_components_names = [ "u" * ctindices(i) for i ∈ range(1, m)] -sol.objective = objective -sol.iterations = 0 -sol.message = "structure: B+B0B+B0B+" -sol.success = true -sol.infos[:resolution] = :numerical - -plt_transfert = plot(sol, layout=:split, size=(900, 600)) -=# From 57c8fa5d6e5f8015f0d94472835a30a75da7b16a Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Caillau Date: Fri, 6 Sep 2024 18:50:08 +0200 Subject: [PATCH 20/33] removed useless @_def; added nothing case in to_out_of_place --- src/onepass.jl | 30 +++++++++++------------------- src/utils.jl | 8 ++++---- test/test_utils.jl | 8 ++++++++ 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/onepass.jl b/src/onepass.jl index 324a32e6..85eaf50a 100644 --- a/src/onepass.jl +++ b/src/onepass.jl @@ -356,7 +356,7 @@ p_constraint!(p, ocp, e1, e2, e3, label = gensym(); log = false) = begin ee2 = replace_call(ee2, p.x, p.tf, xf) args = [x0, xf] __v_dep(p) && push!(args, p.v) - quote + quote # todo function $gs($(args...)) $ee2 end @@ -374,7 +374,7 @@ p_constraint!(p, ocp, e1, e2, e3, label = gensym(); log = false) = begin __t_dep(p) && push!(args, p.t) push!(args, ut) __v_dep(p) && push!(args, p.v) - quote + quote # todo function $gs($(args...)) $ee2 end @@ -392,7 +392,7 @@ p_constraint!(p, ocp, e1, e2, e3, label = gensym(); log = false) = begin __t_dep(p) && push!(args, p.t) push!(args, xt) __v_dep(p) && push!(args, p.v) - quote + quote # todo function $gs($(args...)) $ee2 end @@ -404,7 +404,7 @@ p_constraint!(p, ocp, e1, e2, e3, label = gensym(); log = false) = begin :variable_fun => begin gs = gensym() args = [p.v] - quote + quote # todo function $gs($(args...)) $e2 end @@ -421,7 +421,7 @@ p_constraint!(p, ocp, e1, e2, e3, label = gensym(); log = false) = begin __t_dep(p) && push!(args, p.t) push!(args, xt, ut) __v_dep(p) && push!(args, p.v) - quote + quote # todo function $gs($(args...)) $ee2 end @@ -448,7 +448,7 @@ p_dynamics!(p, ocp, x, t, e, label = nothing; log = false) = begin p.t_dep = p.t_dep || has(e, t) gs = gensym() args = [ ]; __t_dep(p) && push!(args, p.t); push!(args, xt, ut); __v_dep(p) && push!(args, p.v) - code = quote + code = quote # todo function $gs($(args...)) $e end @@ -469,7 +469,7 @@ p_lagrange!(p, ocp, e, type; log = false) = begin ttype = QuoteNode(type) gs = gensym() args = [ ]; __t_dep(p) && push!(args, p.t); push!(args, xt, ut); __v_dep(p) && push!(args, p.v) - code = quote + code = quote # todo function $gs($(args...)) $e end @@ -495,7 +495,7 @@ p_mayer!(p, ocp, e, type; log = false) = begin e = replace_call(e, p.x, p.tf, xf) ttype = QuoteNode(type) args = [ x0, xf ]; __v_dep(p) && push!(args, p.v) - code = quote + code = quote # todo function $gs($(args...)) $e end @@ -528,7 +528,7 @@ p_bolza!(p, ocp, e1, e2, type; log = false) = begin push!(args2, xt, ut) __v_dep(p) && push!(args2, p.v) ttype = QuoteNode(type) - code = quote + code = quote # todo function $gs1($(args1...)) $e1 end @@ -608,16 +608,7 @@ macro def(e) esc(code) end -macro __def(e) # todo: remove after in place test - ocp = gensym() - code = quote - @def $ocp $e false true # Force in place - $ocp - end - esc(code) -end - -macro def(ocp, e, log = false, in_place = false) # todo: default to in_place +macro def(ocp, e, log = false) try p0 = ParsingInfo() parse!(p0, ocp, e; log = false) # initial pass to get the dependencies (time and variable) @@ -625,6 +616,7 @@ macro def(ocp, e, log = false, in_place = false) # todo: default to in_place p.t_dep = p0.t_dep p.v = p0.v code = parse!(p, ocp, e; log = log) + in_place = False # todo: change to True for in place init = @match (__t_dep(p), __v_dep(p)) begin (false, false) => :($ocp = __OCPModel(; in_place = $in_place)) (true, false) => :($ocp = __OCPModel(autonomous = false; in_place = $in_place)) diff --git a/src/utils.jl b/src/utils.jl index 8487e245..bdf4096e 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -252,15 +252,15 @@ __view(x::AbstractVector, rg::AbstractRange) = view(x, rg) # Allows StepRange $(TYPEDSIGNATURES) Tranform in place function to out of place. Pass the result size and type (default = `Float64`). -Return a scalar when the result has size one. +Return a scalar when the result has size one. If `f!` is `nothing`, return `nothing`. """ function to_out_of_place(f!, n; T = Float64) - function f(x...) + function f(args...; kwargs...) r = zeros(T, n) - f!(r, x...) + f!(r, args...; kwargs...) return n == 1 ? r[1] : r end - return f + return isnothing(f!) ? nothing : f end # Adapt getters to test in place diff --git a/test/test_utils.jl b/test/test_utils.jl index cc917e79..2d34ffa8 100644 --- a/test/test_utils.jl +++ b/test/test_utils.jl @@ -94,5 +94,13 @@ function test_utils() end @test CTBase.to_out_of_place(f2!, 1; T = Int32)(1, 2) == 3 + function f3!(r, x; y = 1) + r[:] .= x + y + return nothing + end + @test CTBase.to_out_of_place(f3!, 1; T = Int32)(1; y = 2) == 3 + + @test isnothing( CTBase.to_out_of_place(nothing, 1) ) + end end \ No newline at end of file From e2b173324051c83ff7e064762921cd1d143012a2 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Caillau Date: Fri, 6 Sep 2024 19:26:34 +0200 Subject: [PATCH 21/33] updated onepass to generate in place functions; called by @def that generates an is_in_place(ocp) --- src/CTBase.jl | 1 - src/onepass.jl | 80 +++++++++++++++++++++++++++++++------------------- 2 files changed, 50 insertions(+), 31 deletions(-) diff --git a/src/CTBase.jl b/src/CTBase.jl index a822da9f..bdccaf49 100644 --- a/src/CTBase.jl +++ b/src/CTBase.jl @@ -313,7 +313,6 @@ export replace_call, constraint_type # onepass export @def -export @__def # todo: remove after in place tests # repl export ct_repl, ct_repl_update_model diff --git a/src/onepass.jl b/src/onepass.jl index 85eaf50a..a6a1411a 100644 --- a/src/onepass.jl +++ b/src/onepass.jl @@ -352,13 +352,15 @@ p_constraint!(p, ocp, e1, e2, e3, label = gensym(); log = false) = begin gs = gensym() x0 = gensym() xf = gensym() + r = gensym() ee2 = replace_call(e2, p.x, p.t0, x0) ee2 = replace_call(ee2, p.x, p.tf, xf) - args = [x0, xf] + args = [r, x0, xf] __v_dep(p) && push!(args, p.v) - quote # todo + quote function $gs($(args...)) - $ee2 + $r[:] .= $ee2 + return nothing end constraint!($ocp, :boundary; f = $gs, lb = $e1, ub = $e3, label = $llabel) end @@ -368,15 +370,17 @@ p_constraint!(p, ocp, e1, e2, e3, label = gensym(); log = false) = begin :control_fun => begin gs = gensym() ut = gensym() + r = gensym() ee2 = replace_call(e2, p.u, p.t, ut) p.t_dep = p.t_dep || has(ee2, p.t) - args = [] + args = [r] __t_dep(p) && push!(args, p.t) push!(args, ut) __v_dep(p) && push!(args, p.v) - quote # todo + quote function $gs($(args...)) - $ee2 + $r[:] .= $ee2 + return nothing end constraint!($ocp, :control; f = $gs, lb = $e1, ub = $e3, label = $llabel) end @@ -386,15 +390,17 @@ p_constraint!(p, ocp, e1, e2, e3, label = gensym(); log = false) = begin :state_fun => begin gs = gensym() xt = gensym() + r = gensym() ee2 = replace_call(e2, p.x, p.t, xt) p.t_dep = p.t_dep || has(ee2, p.t) - args = [] + args = [r] __t_dep(p) && push!(args, p.t) push!(args, xt) __v_dep(p) && push!(args, p.v) - quote # todo + quote function $gs($(args...)) - $ee2 + $r[:] .= $ee2 + return nothing end constraint!($ocp, :state; f = $gs, lb = $e1, ub = $e3, label = $llabel) end @@ -403,10 +409,12 @@ p_constraint!(p, ocp, e1, e2, e3, label = gensym(); log = false) = begin :(constraint!($ocp, :variable; rg = $rg, lb = $e1, ub = $e3, label = $llabel)) :variable_fun => begin gs = gensym() - args = [p.v] - quote # todo + r = gensym() + args = [r, p.v] + quote function $gs($(args...)) - $e2 + $r[:] .= $e2 + return nothing end constraint!($ocp, :variable; f = $gs, lb = $e1, ub = $e3, label = $llabel) end @@ -415,15 +423,17 @@ p_constraint!(p, ocp, e1, e2, e3, label = gensym(); log = false) = begin gs = gensym() xt = gensym() ut = gensym() + r = gensym() ee2 = replace_call(e2, [p.x, p.u], p.t, [xt, ut]) p.t_dep = p.t_dep || has(ee2, p.t) - args = [] + args = [r] __t_dep(p) && push!(args, p.t) push!(args, xt, ut) __v_dep(p) && push!(args, p.v) - quote # todo + quote function $gs($(args...)) - $ee2 + $r[:] .= $ee2 + return nothing end constraint!($ocp, :mixed; f = $gs, lb = $e1, ub = $e3, label = $llabel) end @@ -447,10 +457,12 @@ p_dynamics!(p, ocp, x, t, e, label = nothing; log = false) = begin e = replace_call(e, [p.x, p.u], p.t, [xt, ut]) p.t_dep = p.t_dep || has(e, t) gs = gensym() - args = [ ]; __t_dep(p) && push!(args, p.t); push!(args, xt, ut); __v_dep(p) && push!(args, p.v) - code = quote # todo + r = gensym() + args = [r]; __t_dep(p) && push!(args, p.t); push!(args, xt, ut); __v_dep(p) && push!(args, p.v) + code = quote function $gs($(args...)) - $e + $r[:] .= $e + return nothing end dynamics!($ocp, $gs) end @@ -468,10 +480,12 @@ p_lagrange!(p, ocp, e, type; log = false) = begin p.t_dep = p.t_dep || has(e, p.t) ttype = QuoteNode(type) gs = gensym() - args = [ ]; __t_dep(p) && push!(args, p.t); push!(args, xt, ut); __v_dep(p) && push!(args, p.v) - code = quote # todo + r = gensym() + args = [r]; __t_dep(p) && push!(args, p.t); push!(args, xt, ut); __v_dep(p) && push!(args, p.v) + code = quote function $gs($(args...)) - $e + $r[:] .= $e + return nothing end objective!($ocp, :lagrange, $gs, $ttype) end @@ -491,13 +505,15 @@ p_mayer!(p, ocp, e, type; log = false) = begin gs = gensym() x0 = gensym() xf = gensym() + r = gensym() e = replace_call(e, p.x, p.t0, x0) e = replace_call(e, p.x, p.tf, xf) ttype = QuoteNode(type) - args = [ x0, xf ]; __v_dep(p) && push!(args, p.v) - code = quote # todo + args = [r, x0, xf]; __v_dep(p) && push!(args, p.v) + code = quote function $gs($(args...)) - $e + $r[:] .= $e + return nothing end objective!($ocp, :mayer, $gs, $ttype) end @@ -514,26 +530,30 @@ p_bolza!(p, ocp, e1, e2, type; log = false) = begin gs1 = gensym() x0 = gensym() xf = gensym() + r1 = gensym() e1 = replace_call(e1, p.x, p.t0, x0) e1 = replace_call(e1, p.x, p.tf, xf) - args1 = [x0, xf] + args1 = [r1, x0, xf] __v_dep(p) && push!(args1, p.v) gs2 = gensym() xt = gensym() ut = gensym() + r2 = gensym() e2 = replace_call(e2, [p.x, p.u], p.t, [xt, ut]) p.t_dep = p.t_dep || has(e2, p.t) - args2 = [] + args2 = [r2] __t_dep(p) && push!(args2, p.t) push!(args2, xt, ut) __v_dep(p) && push!(args2, p.v) ttype = QuoteNode(type) - code = quote # todo + code = quote function $gs1($(args1...)) - $e1 + $r1[:] .= $e1 + return nothing end function $gs2($(args2...)) - $e2 + $r2[:] .= $e2 + return nothing end objective!($ocp, :bolza, $gs1, $gs2, $ttype) end @@ -616,7 +636,7 @@ macro def(ocp, e, log = false) p.t_dep = p0.t_dep p.v = p0.v code = parse!(p, ocp, e; log = log) - in_place = False # todo: change to True for in place + in_place = true # todo: remove? init = @match (__t_dep(p), __v_dep(p)) begin (false, false) => :($ocp = __OCPModel(; in_place = $in_place)) (true, false) => :($ocp = __OCPModel(autonomous = false; in_place = $in_place)) From 807e6f122197baa12521f3c3e3356bae8373ab42 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Caillau Date: Fri, 6 Sep 2024 19:41:12 +0200 Subject: [PATCH 22/33] fix: added __view of vector with an Index --- src/utils.jl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/utils.jl b/src/utils.jl index bdf4096e..b745ca3b 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -244,6 +244,13 @@ __view(x::AbstractVector, rg::Integer) = x[rg] """ $(TYPEDSIGNATURES) +Adapt `view` to treat uniformly scalars. +""" +__view(x::AbstractVector, rg::Index) = x[rg] + +""" +$(TYPEDSIGNATURES) + Adapt `view` to treat uniformly scalars. """ __view(x::AbstractVector, rg::AbstractRange) = view(x, rg) # Allows StepRange From 9ff490706aada125c2c063102ac055141549e8dd Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Caillau Date: Fri, 6 Sep 2024 23:49:43 +0200 Subject: [PATCH 23/33] fix: missing r in ControlConstraint! and some wrong sizes in lb / ub in test_onepass --- src/functions.jl | 4 ++-- test/test_onepass.jl | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/functions.jl b/src/functions.jl index d45dac55..0a5bb4fc 100644 --- a/src/functions.jl +++ b/src/functions.jl @@ -1222,7 +1222,7 @@ function ControlConstraint(f::Function, dependencies::DataType...) return ControlConstraint{time_dependence, variable_dependence}(f) end -function ControlConstraint!(f!::Function, dependencies::DataType...) +function ControlConstraint!(f!::Function, dependencies::DataType...) # todo: useless? only use version above? __check_dependencies(dependencies) time_dependence = NonAutonomous ∈ dependencies ? NonAutonomous : Autonomous variable_dependence = NonFixed ∈ dependencies ? NonFixed : Fixed @@ -1297,7 +1297,7 @@ function (F::ControlConstraint!{Autonomous, Fixed})(r::ctVector, t::Time, u::Con end function (F::ControlConstraint!{Autonomous, NonFixed})(r::ctVector, u::Control, v::Variable)::Nothing - return F.f!(u, v) + return F.f!(r, u, v) end function (F::ControlConstraint!{Autonomous, NonFixed})(r::ctVector, t::Time, u::Control, v::Variable)::Nothing diff --git a/test/test_onepass.jl b/test/test_onepass.jl index 2da41455..d752a591 100644 --- a/test/test_onepass.jl +++ b/test/test_onepass.jl @@ -647,8 +647,8 @@ function test_onepass() [0, 0] ≤ u[1:2](t) ≤ [1, 1], (7) [0, 0] ≤ u[1:2:4](t) ≤ [1, 1], (8) 0 ≤ u₂(t)^2 ≤ 1, (9) - u₁(t) * x[1:2](t) == 1, (10) - 0 ≤ u₁(t) * x[1:2](t) .^ 3 ≤ 1, (11) + u₁(t) * x[1:2](t) == [1, 1], (10) + 0 ≤ u₁(t) * x[1:2](t) .^ 3 ≤ [1, 1], (11) end x = Vector{Float64}(1:n) u = 2 * Vector{Float64}(1:m) @@ -682,8 +682,8 @@ function test_onepass() [0, 0] ≤ u[1:2](t) ≤ [1, 1], (7) [0, 0] ≤ u[1:2:4](t) ≤ [1, 1], (8) 0 ≤ u₂(t)^2 ≤ 1, (9) - u₁(t) * x[1:2](t) + z + f() == 1, (10) - 0 ≤ u₁(t) * x[1:2](t) .^ 3 + z ≤ 1, (11) + u₁(t) * x[1:2](t) + z + f() == [1, 1], (10) + [0, 0] ≤ u₁(t) * x[1:2](t) .^ 3 + z ≤ [1, 1], (11) end f() = [1, 1] z = 3 * Vector{Float64}(1:2) From d516f63f0f8432e400f621104a36d3a7837d7bc7 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Caillau Date: Sat, 7 Sep 2024 00:29:28 +0200 Subject: [PATCH 24/33] fix: old dim error in test_onepass --- test/test_onepass.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_onepass.jl b/test/test_onepass.jl index d752a591..5060a1b6 100644 --- a/test/test_onepass.jl +++ b/test/test_onepass.jl @@ -648,7 +648,7 @@ function test_onepass() [0, 0] ≤ u[1:2:4](t) ≤ [1, 1], (8) 0 ≤ u₂(t)^2 ≤ 1, (9) u₁(t) * x[1:2](t) == [1, 1], (10) - 0 ≤ u₁(t) * x[1:2](t) .^ 3 ≤ [1, 1], (11) + [0, 0] ≤ u₁(t) * x[1:2](t) .^ 3 ≤ [1, 1], (11) end x = Vector{Float64}(1:n) u = 2 * Vector{Float64}(1:m) From fe958233768a5efa29908cdd7e9dd4771bf5bed8 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Caillau Date: Sat, 7 Sep 2024 01:53:47 +0200 Subject: [PATCH 25/33] foo --- src/onepass.jl | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/onepass.jl b/src/onepass.jl index a6a1411a..fad80760 100644 --- a/src/onepass.jl +++ b/src/onepass.jl @@ -286,13 +286,13 @@ p_state!(p, ocp, x, n; components_names = nothing, log = false) = begin nn = n isa Integer ? n : 9 for i ∈ 1:nn p.aliases[Symbol(x, ctindices(i))] = :($x[$i]) - end # make: x₁, x₂... if the state is named x + end # Make x₁, x₂... if the state is named x for i ∈ 1:nn p.aliases[Symbol(x, i)] = :($x[$i]) - end # make: x1, x2... if the state is named x + end # Make x1, x2... if the state is named x for i ∈ 1:9 p.aliases[Symbol(x, ctupperscripts(i))] = :($x^$i) - end # make: x¹, x²... if the state is named x + end # Make x¹, x²... if the state is named x p.aliases[Symbol(Unicode.normalize(string(x, "̇")))] = :(∂($x)) if (isnothing(components_names)) code = :( state!($ocp, $n, $xx) ) @@ -301,7 +301,8 @@ p_state!(p, ocp, x, n; components_names = nothing, log = false) = begin return __throw("the number of state components must be $nn", p.lnum, p.line) for i ∈ 1:nn p.aliases[components_names.args[i]] = :($x[$i]) - end # aliases from names given by the user + # todo: add aliases for state components (scalar) derivatives + end # Aliases from names given by the user ss = QuoteNode(string.(components_names.args)) code = :( state!($ocp, $n, $xx, $ss) ) end From 0eff660ba8b7e02bcc077b8de328b43b227837bf Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Caillau Date: Sun, 8 Sep 2024 00:04:24 +0200 Subject: [PATCH 26/33] added in place tests in test_model --- src/optimal_control_model-getters.jl | 2 +- test/test_model.jl | 418 +++++++++++++++++++++++++++ 2 files changed, 419 insertions(+), 1 deletion(-) diff --git a/src/optimal_control_model-getters.jl b/src/optimal_control_model-getters.jl index 1ff464c7..b8bae46f 100644 --- a/src/optimal_control_model-getters.jl +++ b/src/optimal_control_model-getters.jl @@ -339,7 +339,7 @@ function constraint( (:control, rg, _, _) => begin C = @match ocp begin ::OptimalControlModel{Autonomous, Fixed} => is_in_place(ocp) ? - ControlConstraint!((r, u) -> (r[:] .= __view(u, rg); nothing), T, V) : + ControlConstraint!((r, u) -> (r[:] .= __view(u, rg); nothing), T, V) : # todo: CC!{T, V}(fun) syntax? ControlConstraint(u -> u[rg], T, V) ::OptimalControlModel{Autonomous, NonFixed} => is_in_place(ocp) ? ControlConstraint!((r, u, v) -> (r[:] .= __view(u, rg); nothing), T, V) : diff --git a/test/test_model.jl b/test/test_model.jl index 29a34447..936bb355 100644 --- a/test/test_model.jl +++ b/test/test_model.jl @@ -1482,6 +1482,207 @@ function test_model() # 30 55 185 @test dim_variable_range(ocp) == 7 end + + @testset "nlp_constraints! without variable (in place)" begin + ocp = Model(; in_place = true) + time!(ocp; t0 = 0, tf = 1) + state!(ocp, 2) + control!(ocp, 1) + constraint!(ocp, :initial, rg = 2, lb = 10, ub = 10, label = :ci) + constraint!(ocp, :final, rg = 1, lb = 1, ub = 1, label = :cf) + constraint!(ocp, :control, lb = 0, ub = 1, label = :cu) + constraint!(ocp, :state, lb = [0, 1], ub = [1, 2], label = :cs) + constraint!(ocp, :boundary, f = (r, x0, xf) -> (r[:] = x0[2] + xf[2]; nothing), lb = 0, ub = 1, label = :cb) + constraint!(ocp, :control, f = (r, u) -> (r[:] = u; nothing), lb = 0, ub = 1, label = :cuu) + constraint!(ocp, :state, f = (r, x) -> (r[:] = x; nothing), lb = [0, 1], ub = [1, 2], label = :css) + constraint!(ocp, :mixed, f = (r, x, u) -> (r[:] = x[1] + u; nothing), lb = 1, ub = 1, label = :cm) + + # dimensions (not set yet) + @test dim_control_constraints(ocp) === nothing + @test dim_state_constraints(ocp) === nothing + @test dim_mixed_constraints(ocp) === nothing + @test dim_path_constraints(ocp) === nothing + @test dim_boundary_constraints(ocp) === nothing + @test dim_variable_constraints(ocp) === nothing + @test dim_control_range(ocp) === nothing + @test dim_state_range(ocp) === nothing + @test dim_variable_range(ocp) === nothing + + (ξl, ξ!, ξu), + (ηl, η!, ηu), + (ψl, ψ!, ψu), + (ϕl, ϕ!, ϕu), + (θl, θ!, θu), + (ul, uind, uu), + (xl, xind, xu), + (vl, vind, vu) = nlp_constraints!(ocp) + + v = Real[] + + # control + @test sort(ξl) == sort([0]) + @test sort(ξu) == sort([1]) + r = [0.] + ξ!(r, -1, 1, v) + @test sort(r) == sort([1]) + + # state + @test sort(ηl) == sort([0, 1]) + @test sort(ηu) == sort([1, 2]) + r = [0., 0.] + η!(r, -1, [1, 1], v) + @test r == sort([1, 1]) + + # mixed + @test sort(ψl) == sort([1]) + @test sort(ψu) == sort([1]) + r = [0.] + ψ!(r, -1, [1, 1], 2, v) + @test r == sort([3]) + + # boundary + @test sort(ϕl) == sort([10, 1, 0]) + @test sort(ϕu) == sort([10, 1, 1]) + r = [0., 0., 0.] + ϕ!(r, [1, 3], [4, 100], v) + @test r == sort([3, 4, 103]) + + # box constraint + @test sort(ul) == sort([0]) + @test sort(uind) == sort([1]) + @test sort(uu) == sort([1]) + @test sort(xl) == sort([0, 1]) + @test sort(xind) == sort([1, 2]) + @test sort(xu) == sort([1, 2]) + + # variable + @test sort(vl) == sort([]) + @test sort(vind) == sort([]) + @test sort(vu) == sort([]) + @test sort(θl) == sort([]) + @test sort(θu) == sort([]) + r = Real[] + θ!(r, v) + @test r == sort([]) + + # dimensions (set) + @test dim_control_constraints(ocp) == 1 + @test dim_state_constraints(ocp) == 2 + @test dim_mixed_constraints(ocp) == 1 + @test dim_path_constraints(ocp) == 4 + @test dim_boundary_constraints(ocp) == 3 + @test dim_variable_constraints(ocp) == 0 + @test dim_control_range(ocp) == 1 + @test dim_state_range(ocp) == 2 + @test dim_variable_range(ocp) == 0 + end + + @testset "nlp_constraints! with variable (in place)" begin + ocp = Model(; variable = true, in_place = true) + time!(ocp; t0 = 0, tf = 1) + variable!(ocp, 4) + state!(ocp, 2) + control!(ocp, 1) + constraint!(ocp, :initial, rg = 2, lb = 10, ub = 10, label = :ci) + constraint!(ocp, :final, rg = 1, lb = 1, ub = 1, label = :cf) + constraint!(ocp, :control, lb = 0, ub = 1, label = :cu) + constraint!(ocp, :state, lb = [0, 1], ub = [1, 2], label = :cs) + constraint!( + ocp, + :boundary, + f = (r, x0, xf, v) -> (r[:] = x0[2] + xf[2] + v[1]; nothing), + lb = 0, + ub = 1, + label = :cb, + ) + constraint!(ocp, :control, f = (r, u, v) -> (r[:] = u + v[2]; nothing), lb = 0, ub = 1, label = :cuu) + constraint!(ocp, :state, f = (r, x, v) -> (r[:] = x + v[1:2]; nothing), lb = [0, 1], ub = [1, 2], label = :css) + constraint!(ocp, :mixed, f = (r, x, u, v) -> (r[:] = x[1] + u + v[2]; nothing), lb = 1, ub = 1, label = :cm) + constraint!(ocp, :variable, lb = [0, 0, 0, 0], ub = [5, 5, 5, 5], label = :cv1) + constraint!(ocp, :variable, rg = 1:2, lb = [1, 2], ub = [3, 4], label = :cv2) + constraint!(ocp, :variable, rg = 3, lb = 2, ub = 3, label = :cv3) + constraint!(ocp, :variable, f = (r, v) -> (r[:] = v[3]^2; nothing), lb = 0, ub = 1, label = :cv4) + + # dimensions (not set yet) + @test dim_control_constraints(ocp) === nothing + @test dim_state_constraints(ocp) === nothing + @test dim_mixed_constraints(ocp) === nothing + @test dim_path_constraints(ocp) === nothing + @test dim_boundary_constraints(ocp) === nothing + @test dim_variable_constraints(ocp) === nothing + @test dim_control_range(ocp) === nothing + @test dim_state_range(ocp) === nothing + @test dim_variable_range(ocp) === nothing + + (ξl, ξ!, ξu), + (ηl, η!, ηu), + (ψl, ψ!, ψu), + (ϕl, ϕ!, ϕu), + (θl, θ!, θu), + (ul, uind, uu), + (xl, xind, xu), + (vl, vind, vu) = nlp_constraints!(ocp) + + v = [1, 2, 3, 4] + + # control + @test sort(ξl) == sort([0]) + @test sort(ξu) == sort([1]) + r = [0.] + ξ!(r, -1, 1, v) + @test r == sort([1 + v[2]]) + + # state + @test sort(ηl) == sort([0, 1]) + @test sort(ηu) == sort([1, 2]) + r = [0., 0.] + η!(r, -1, [1, 1], v) + @test r == sort([1, 1] + v[1:2]) + + # mixed + @test sort(ψl) == sort([1]) + @test sort(ψu) == sort([1]) + r = [0.] + ψ!(r, -1, [1, 1], 2, v) + @test r == sort([3 + v[2]]) + + # boundary + @test sort(ϕl) == sort([10, 1, 0]) + @test sort(ϕu) == sort([10, 1, 1]) + r = [0., 0., 0.] + ϕ!(r, [1, 3], [4, 100], v)) == sort([3, 4, 103 + v[1]]) + @test r == sort([3, 4, 103 + v[1]]) + + # variable + @test sort(θl) == sort([0]) + @test sort(θu) == sort([1]) + r = [0.] + θ!(r, v) + @test r == sort([v[3]^2]) + + # box constraint + @test sort(ul) == sort([0]) + @test sort(uind) == sort([1]) + @test sort(uu) == sort([1]) + @test sort(xl) == sort([0, 1]) + @test sort(xind) == sort([1, 2]) + @test sort(xu) == sort([1, 2]) + @test sort(vl) == sort([0, 0, 0, 0, 1, 2, 2]) + @test sort(vind) == sort([1, 2, 3, 4, 1, 2, 3]) + @test sort(vu) == sort([5, 5, 5, 5, 3, 4, 3]) + + # dimensions + @test dim_control_constraints(ocp) == 1 + @test dim_state_constraints(ocp) == 2 + @test dim_mixed_constraints(ocp) == 1 + @test dim_path_constraints(ocp) == 4 + @test dim_boundary_constraints(ocp) == 3 + @test dim_variable_constraints(ocp) == 1 + @test dim_control_range(ocp) == 1 + @test dim_state_range(ocp) == 2 + @test dim_variable_range(ocp) == 7 + end + @testset "val vs lb and ub, errors" begin ocp = Model(variable = true) @@ -1872,6 +2073,223 @@ function test_model() # 30 55 185 @test dim_variable_range(ocp) == 7 end + + @testset "val vs lb and ub, 1/2 (in place)" begin + ocp = Model(variable = true, in_place = true) + + time!(ocp; t0 = 0, tf = 1) + variable!(ocp, 4) + state!(ocp, 2) + control!(ocp, 1) + + constraint!(ocp, :initial; rg = Index(2), lb = 10, ub = 10, label = :ci) + constraint!(ocp, :final; rg = Index(1), lb = 1, ub = 1, label = :cf) + constraint!(ocp, :control; lb = 0, ub = 0, label = :cu) + constraint!(ocp, :state; lb = [0, 1], ub = [0, 1], label = :cs) + constraint!( + ocp, + :boundary; + f = (r, x0, xf, v) -> (r[:] = x0[2] + xf[2] + v[1]; nothing), + lb = 2, + ub = 2, + label = :cb, + ) + constraint!(ocp, :control; f = (r, u, v) -> (r[:] = u + v[2]; nothing), lb = 20, ub = 20, label = :cuu) + constraint!( + ocp, + :state; + f = (r, x, v) -> (r[:] = x + v[1:2]; nothing), + lb = [100, 101], + ub = [100, 101], + label = :css, + ) + constraint!(ocp, :mixed; f = (r, x, u, v) -> (r[:] = x[1] + u + v[2]; nothing), lb = -1, ub = -1, label = :cm) + constraint!(ocp, :variable; lb = [5, 5, 5, 5], ub = [5, 5, 5, 5], label = :cv1) + constraint!(ocp, :variable; rg = 1:2, lb = [10, 20], ub = [10, 20], label = :cv2) + constraint!(ocp, :variable; rg = Index(3), lb = 1000, ub = 1000, label = :cv3) + constraint!(ocp, :variable; f = (r, v) -> (r[:] = v[3]^2; nothing), lb = -10, ub = -10, label = :cv4) + + # dimensions (not set yet) + @test dim_control_constraints(ocp) === nothing + @test dim_state_constraints(ocp) === nothing + @test dim_mixed_constraints(ocp) === nothing + @test dim_path_constraints(ocp) === nothing + @test dim_boundary_constraints(ocp) === nothing + @test dim_variable_constraints(ocp) === nothing + @test dim_control_range(ocp) === nothing + @test dim_state_range(ocp) === nothing + @test dim_variable_range(ocp) === nothing + + (ξl, ξ!, ξu), + (ηl, η!, ηu), + (ψl, ψ!, ψu), + (ϕl, ϕ!, ϕu), + (θl, θ!, θu), + (ul, uind, uu), + (xl, xind, xu), + (vl, vind, vu) = nlp_constraints!(ocp) + + v = [1, 2, 3, 4] + + # control + @test sort(ξl) == sort([20]) + @test sort(ξu) == sort([20]) + r = [0.] + ξ!(r, -1, 1, v) + @test r == sort([1 + v[2]]) + + # state + @test sort(ηl) == sort([100, 101]) + @test sort(ηu) == sort([100, 101]) + r = [0., 0.] + η!(r, -1, [1, 1], v)) + @test r == sort([1, 1] + v[1:2]) + + # mixed + @test sort(ψl) == sort([-1]) + @test sort(ψu) == sort([-1]) + r = [0.] + ψ!(r, -1, [1, 1], 2, v) + @test r == sort([3 + v[2]]) + + # boundary + @test sort(ϕl) == sort([10, 1, 2]) + @test sort(ϕu) == sort([10, 1, 2]) + r = [0., 0., 0.] + ϕ!(r, [1, 3], [4, 100], v)) + @test r == sort([3, 4, 103 + v[1]]) + + # variable + @test sort(θl) == sort([-10]) + @test sort(θu) == sort([-10]) + r = [0.] + θ!(r, v) + @test r == sort([v[3]^2]) + + # box constraint + @test sort(ul) == sort([0]) + @test sort(uind) == sort([1]) + @test sort(uu) == sort([0]) + @test sort(xl) == sort([0, 1]) + @test sort(xind) == sort([1, 2]) + @test sort(xu) == sort([0, 1]) + @test sort(vl) == sort([5, 5, 5, 5, 10, 20, 1000]) + @test sort(vind) == sort([1, 2, 3, 4, 1, 2, 3]) + @test sort(vu) == sort([5, 5, 5, 5, 10, 20, 1000]) + + # dimensions + @test dim_control_constraints(ocp) == 1 + @test dim_state_constraints(ocp) == 2 + @test dim_mixed_constraints(ocp) == 1 + @test dim_path_constraints(ocp) == 4 + @test dim_boundary_constraints(ocp) == 3 + @test dim_variable_constraints(ocp) == 1 + @test dim_control_range(ocp) == 1 + @test dim_state_range(ocp) == 2 + @test dim_variable_range(ocp) == 7 + end + + @testset "val vs lb and ub, 2/2 (in place)" begin + ocp = Model(variable = true, in_place = true) + + time!(ocp; t0 = 0, tf = 1) + variable!(ocp, 4) + state!(ocp, 2) + control!(ocp, 1) + + constraint!(ocp, :initial; rg = Index(2), val = 10, label = :ci) + constraint!(ocp, :final; rg = Index(1), val = 1, label = :cf) + constraint!(ocp, :control; val = 0, label = :cu) + constraint!(ocp, :state; val = [0, 1], label = :cs) + constraint!(ocp, :boundary; f = (r, x0, xf, v) -> (r[:] = x0[2] + xf[2] + v[1]; nothing), val = 2, label = :cb) + constraint!(ocp, :control; f = (r, u, v) -> (r[:] = u + v[2]; nothing), val = 20, label = :cuu) + constraint!(ocp, :state; f = (r, x, v) -> (r[:] = x + v[1:2]; nothing), val = [100, 101], label = :css) + constraint!(ocp, :mixed; f = (r, x, u, v) -> (r[:] = x[1] + u + v[2]; nothing), val = -1, label = :cm) + constraint!(ocp, :variable; val = [5, 5, 5, 5], label = :cv1) + constraint!(ocp, :variable; rg = 1:2, val = [10, 20], label = :cv2) + constraint!(ocp, :variable; rg = Index(3), val = 1000, label = :cv3) + constraint!(ocp, :variable; f = (r, v) -> (r[:] = v[3]^2; nothing), val = -10, label = :cv4) + + # dimensions (not set yet) + @test dim_control_constraints(ocp) === nothing + @test dim_state_constraints(ocp) === nothing + @test dim_mixed_constraints(ocp) === nothing + @test dim_path_constraints(ocp) === nothing + @test dim_boundary_constraints(ocp) === nothing + @test dim_variable_constraints(ocp) === nothing + @test dim_control_range(ocp) === nothing + @test dim_state_range(ocp) === nothing + @test dim_variable_range(ocp) === nothing + + (ξl, ξ!, ξu), + (ηl, η!, ηu), + (ψl, ψ!, ψu), + (ϕl, ϕ!, ϕu), + (θl, θ!, θu), + (ul, uind, uu), + (xl, xind, xu), + (vl, vind, vu) = nlp_constraints!(ocp) + + v = [1, 2, 3, 4] + + # control + @test sort(ξl) == sort([20]) + @test sort(ξu) == sort([20]) + r = [0.] + ξ!(r, -1, 1, v) + @test r == sort([1 + v[2]]) + + # state + @test sort(ηl) == sort([100, 101]) + @test sort(ηu) == sort([100, 101]) + r = [0., 0.] + η!(r, -1, [1, 1], v) + @test r == sort([1, 1] + v[1:2]) + + # mixed + @test sort(ψl) == sort([-1]) + @test sort(ψu) == sort([-1]) + r = [0.] + ψ!(r, -1, [1, 1], 2, v) + @test r == sort([3 + v[2]]) + + # boundary + @test sort(ϕl) == sort([10, 1, 2]) + @test sort(ϕu) == sort([10, 1, 2]) + r = [0., 0., 0.] + ϕ!(r, [1, 3], [4, 100], v)) + @test r == sort([3, 4, 103 + v[1]]) + + # variable + @test sort(θl) == sort([-10]) + @test sort(θu) == sort([-10]) + r = [0.] + θ!(r, v) + @test r == sort([v[3]^2]) + + # box constraint + @test sort(ul) == sort([0]) + @test sort(uind) == sort([1]) + @test sort(uu) == sort([0]) + @test sort(xl) == sort([0, 1]) + @test sort(xind) == sort([1, 2]) + @test sort(xu) == sort([0, 1]) + @test sort(vl) == sort([5, 5, 5, 5, 10, 20, 1000]) + @test sort(vind) == sort([1, 2, 3, 4, 1, 2, 3]) + @test sort(vu) == sort([5, 5, 5, 5, 10, 20, 1000]) + + # dimensions + @test dim_control_constraints(ocp) == 1 + @test dim_state_constraints(ocp) == 2 + @test dim_mixed_constraints(ocp) == 1 + @test dim_path_constraints(ocp) == 4 + @test dim_boundary_constraints(ocp) == 3 + @test dim_variable_constraints(ocp) == 1 + @test dim_control_range(ocp) == 1 + @test dim_state_range(ocp) == 2 + @test dim_variable_range(ocp) == 7 + end + @testset "objective!" begin ocp = Model() @test_throws UnauthorizedCall objective!(ocp, :lagrange, (x, u) -> 0.5u^2) From 317fbc9fb39e10ec9f773560db30fd6d0e7d4c38 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Caillau Date: Sun, 8 Sep 2024 00:24:36 +0200 Subject: [PATCH 27/33] fix: test_model.jl --- test/test_model.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_model.jl b/test/test_model.jl index 936bb355..d386c040 100644 --- a/test/test_model.jl +++ b/test/test_model.jl @@ -1650,7 +1650,7 @@ function test_model() # 30 55 185 @test sort(ϕl) == sort([10, 1, 0]) @test sort(ϕu) == sort([10, 1, 1]) r = [0., 0., 0.] - ϕ!(r, [1, 3], [4, 100], v)) == sort([3, 4, 103 + v[1]]) + ϕ!(r, [1, 3], [4, 100], v) == sort([3, 4, 103 + v[1]]) @test r == sort([3, 4, 103 + v[1]]) # variable From 7151bd23c8be2202067eecf6e39e4b9d43f61fb4 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Caillau Date: Sun, 8 Sep 2024 00:33:46 +0200 Subject: [PATCH 28/33] fix: test_model.jl --- test/test_model.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_model.jl b/test/test_model.jl index d386c040..6430fea4 100644 --- a/test/test_model.jl +++ b/test/test_model.jl @@ -1650,7 +1650,7 @@ function test_model() # 30 55 185 @test sort(ϕl) == sort([10, 1, 0]) @test sort(ϕu) == sort([10, 1, 1]) r = [0., 0., 0.] - ϕ!(r, [1, 3], [4, 100], v) == sort([3, 4, 103 + v[1]]) + ϕ!(r, [1, 3], [4, 100], v) @test r == sort([3, 4, 103 + v[1]]) # variable @@ -2142,7 +2142,7 @@ function test_model() # 30 55 185 @test sort(ηl) == sort([100, 101]) @test sort(ηu) == sort([100, 101]) r = [0., 0.] - η!(r, -1, [1, 1], v)) + η!(r, -1, [1, 1], v) @test r == sort([1, 1] + v[1:2]) # mixed From 159476bf4cdf1998e7f3cd3d6eb2588e31952040 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Caillau Date: Sun, 8 Sep 2024 01:10:55 +0200 Subject: [PATCH 29/33] Update test_model.jl --- test/test_model.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_model.jl b/test/test_model.jl index 6430fea4..b0d54647 100644 --- a/test/test_model.jl +++ b/test/test_model.jl @@ -2156,7 +2156,7 @@ function test_model() # 30 55 185 @test sort(ϕl) == sort([10, 1, 2]) @test sort(ϕu) == sort([10, 1, 2]) r = [0., 0., 0.] - ϕ!(r, [1, 3], [4, 100], v)) + ϕ!(r, [1, 3], [4, 100], v) @test r == sort([3, 4, 103 + v[1]]) # variable @@ -2257,7 +2257,7 @@ function test_model() # 30 55 185 @test sort(ϕl) == sort([10, 1, 2]) @test sort(ϕu) == sort([10, 1, 2]) r = [0., 0., 0.] - ϕ!(r, [1, 3], [4, 100], v)) + ϕ!(r, [1, 3], [4, 100], v) @test r == sort([3, 4, 103 + v[1]]) # variable From 6d538c5be035f24d88f056810074a0d56b1aebdd Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Caillau Date: Sun, 8 Sep 2024 22:12:23 +0200 Subject: [PATCH 30/33] test_model: pass --- test/test_model.jl | 84 +++++++++++++++++++++++----------------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/test/test_model.jl b/test/test_model.jl index 936bb355..2be8b97b 100644 --- a/test/test_model.jl +++ b/test/test_model.jl @@ -1492,10 +1492,10 @@ function test_model() # 30 55 185 constraint!(ocp, :final, rg = 1, lb = 1, ub = 1, label = :cf) constraint!(ocp, :control, lb = 0, ub = 1, label = :cu) constraint!(ocp, :state, lb = [0, 1], ub = [1, 2], label = :cs) - constraint!(ocp, :boundary, f = (r, x0, xf) -> (r[:] = x0[2] + xf[2]; nothing), lb = 0, ub = 1, label = :cb) - constraint!(ocp, :control, f = (r, u) -> (r[:] = u; nothing), lb = 0, ub = 1, label = :cuu) - constraint!(ocp, :state, f = (r, x) -> (r[:] = x; nothing), lb = [0, 1], ub = [1, 2], label = :css) - constraint!(ocp, :mixed, f = (r, x, u) -> (r[:] = x[1] + u; nothing), lb = 1, ub = 1, label = :cm) + constraint!(ocp, :boundary, f = (r, x0, xf) -> (r[:] .= x0[2] + xf[2]; nothing), lb = 0, ub = 1, label = :cb) + constraint!(ocp, :control, f = (r, u) -> (r[:] .= u; nothing), lb = 0, ub = 1, label = :cuu) + constraint!(ocp, :state, f = (r, x) -> (r[:] .= x; nothing), lb = [0, 1], ub = [1, 2], label = :css) + constraint!(ocp, :mixed, f = (r, x, u) -> (r[:] .= x[1] + u; nothing), lb = 1, ub = 1, label = :cm) # dimensions (not set yet) @test dim_control_constraints(ocp) === nothing @@ -1531,21 +1531,21 @@ function test_model() # 30 55 185 @test sort(ηu) == sort([1, 2]) r = [0., 0.] η!(r, -1, [1, 1], v) - @test r == sort([1, 1]) + @test sort(r) == sort([1, 1]) # mixed @test sort(ψl) == sort([1]) @test sort(ψu) == sort([1]) r = [0.] ψ!(r, -1, [1, 1], 2, v) - @test r == sort([3]) + @test sort(r) == sort([3]) # boundary @test sort(ϕl) == sort([10, 1, 0]) @test sort(ϕu) == sort([10, 1, 1]) r = [0., 0., 0.] ϕ!(r, [1, 3], [4, 100], v) - @test r == sort([3, 4, 103]) + @test sort(r) == sort([3, 4, 103]) # box constraint @test sort(ul) == sort([0]) @@ -1563,7 +1563,7 @@ function test_model() # 30 55 185 @test sort(θu) == sort([]) r = Real[] θ!(r, v) - @test r == sort([]) + @test sort(r) == sort([]) # dimensions (set) @test dim_control_constraints(ocp) == 1 @@ -1590,18 +1590,18 @@ function test_model() # 30 55 185 constraint!( ocp, :boundary, - f = (r, x0, xf, v) -> (r[:] = x0[2] + xf[2] + v[1]; nothing), + f = (r, x0, xf, v) -> (r[:] .= x0[2] + xf[2] + v[1]; nothing), lb = 0, ub = 1, label = :cb, ) - constraint!(ocp, :control, f = (r, u, v) -> (r[:] = u + v[2]; nothing), lb = 0, ub = 1, label = :cuu) - constraint!(ocp, :state, f = (r, x, v) -> (r[:] = x + v[1:2]; nothing), lb = [0, 1], ub = [1, 2], label = :css) - constraint!(ocp, :mixed, f = (r, x, u, v) -> (r[:] = x[1] + u + v[2]; nothing), lb = 1, ub = 1, label = :cm) + constraint!(ocp, :control, f = (r, u, v) -> (r[:] .= u + v[2]; nothing), lb = 0, ub = 1, label = :cuu) + constraint!(ocp, :state, f = (r, x, v) -> (r[:] .= x + v[1:2]; nothing), lb = [0, 1], ub = [1, 2], label = :css) + constraint!(ocp, :mixed, f = (r, x, u, v) -> (r[:] .= x[1] + u + v[2]; nothing), lb = 1, ub = 1, label = :cm) constraint!(ocp, :variable, lb = [0, 0, 0, 0], ub = [5, 5, 5, 5], label = :cv1) constraint!(ocp, :variable, rg = 1:2, lb = [1, 2], ub = [3, 4], label = :cv2) constraint!(ocp, :variable, rg = 3, lb = 2, ub = 3, label = :cv3) - constraint!(ocp, :variable, f = (r, v) -> (r[:] = v[3]^2; nothing), lb = 0, ub = 1, label = :cv4) + constraint!(ocp, :variable, f = (r, v) -> (r[:] .= v[3]^2; nothing), lb = 0, ub = 1, label = :cv4) # dimensions (not set yet) @test dim_control_constraints(ocp) === nothing @@ -1630,35 +1630,35 @@ function test_model() # 30 55 185 @test sort(ξu) == sort([1]) r = [0.] ξ!(r, -1, 1, v) - @test r == sort([1 + v[2]]) + @test sort(r) == sort([1 + v[2]]) # state @test sort(ηl) == sort([0, 1]) @test sort(ηu) == sort([1, 2]) r = [0., 0.] η!(r, -1, [1, 1], v) - @test r == sort([1, 1] + v[1:2]) + @test sort(r) == sort([1, 1] + v[1:2]) # mixed @test sort(ψl) == sort([1]) @test sort(ψu) == sort([1]) r = [0.] ψ!(r, -1, [1, 1], 2, v) - @test r == sort([3 + v[2]]) + @test sort(r) == sort([3 + v[2]]) # boundary @test sort(ϕl) == sort([10, 1, 0]) @test sort(ϕu) == sort([10, 1, 1]) r = [0., 0., 0.] - ϕ!(r, [1, 3], [4, 100], v)) == sort([3, 4, 103 + v[1]]) - @test r == sort([3, 4, 103 + v[1]]) + ϕ!(r, [1, 3], [4, 100], v) + @test sort(r) == sort([3, 4, 103 + v[1]]) # variable @test sort(θl) == sort([0]) @test sort(θu) == sort([1]) r = [0.] θ!(r, v) - @test r == sort([v[3]^2]) + @test sort(r) == sort([v[3]^2]) # box constraint @test sort(ul) == sort([0]) @@ -2089,25 +2089,25 @@ function test_model() # 30 55 185 constraint!( ocp, :boundary; - f = (r, x0, xf, v) -> (r[:] = x0[2] + xf[2] + v[1]; nothing), + f = (r, x0, xf, v) -> (r[:] .= x0[2] + xf[2] + v[1]; nothing), lb = 2, ub = 2, label = :cb, ) - constraint!(ocp, :control; f = (r, u, v) -> (r[:] = u + v[2]; nothing), lb = 20, ub = 20, label = :cuu) + constraint!(ocp, :control; f = (r, u, v) -> (r[:] .= u + v[2]; nothing), lb = 20, ub = 20, label = :cuu) constraint!( ocp, :state; - f = (r, x, v) -> (r[:] = x + v[1:2]; nothing), + f = (r, x, v) -> (r[:] .= x + v[1:2]; nothing), lb = [100, 101], ub = [100, 101], label = :css, ) - constraint!(ocp, :mixed; f = (r, x, u, v) -> (r[:] = x[1] + u + v[2]; nothing), lb = -1, ub = -1, label = :cm) + constraint!(ocp, :mixed; f = (r, x, u, v) -> (r[:] .= x[1] + u + v[2]; nothing), lb = -1, ub = -1, label = :cm) constraint!(ocp, :variable; lb = [5, 5, 5, 5], ub = [5, 5, 5, 5], label = :cv1) constraint!(ocp, :variable; rg = 1:2, lb = [10, 20], ub = [10, 20], label = :cv2) constraint!(ocp, :variable; rg = Index(3), lb = 1000, ub = 1000, label = :cv3) - constraint!(ocp, :variable; f = (r, v) -> (r[:] = v[3]^2; nothing), lb = -10, ub = -10, label = :cv4) + constraint!(ocp, :variable; f = (r, v) -> (r[:] .= v[3]^2; nothing), lb = -10, ub = -10, label = :cv4) # dimensions (not set yet) @test dim_control_constraints(ocp) === nothing @@ -2136,35 +2136,35 @@ function test_model() # 30 55 185 @test sort(ξu) == sort([20]) r = [0.] ξ!(r, -1, 1, v) - @test r == sort([1 + v[2]]) + @test sort(r) == sort([1 + v[2]]) # state @test sort(ηl) == sort([100, 101]) @test sort(ηu) == sort([100, 101]) r = [0., 0.] - η!(r, -1, [1, 1], v)) - @test r == sort([1, 1] + v[1:2]) + η!(r, -1, [1, 1], v) + @test sort(r) == sort([1, 1] + v[1:2]) # mixed @test sort(ψl) == sort([-1]) @test sort(ψu) == sort([-1]) r = [0.] ψ!(r, -1, [1, 1], 2, v) - @test r == sort([3 + v[2]]) + @test sort(r) == sort([3 + v[2]]) # boundary @test sort(ϕl) == sort([10, 1, 2]) @test sort(ϕu) == sort([10, 1, 2]) r = [0., 0., 0.] - ϕ!(r, [1, 3], [4, 100], v)) - @test r == sort([3, 4, 103 + v[1]]) + ϕ!(r, [1, 3], [4, 100], v) + @test sort(r) == sort([3, 4, 103 + v[1]]) # variable @test sort(θl) == sort([-10]) @test sort(θu) == sort([-10]) r = [0.] θ!(r, v) - @test r == sort([v[3]^2]) + @test sort(r) == sort([v[3]^2]) # box constraint @test sort(ul) == sort([0]) @@ -2201,14 +2201,14 @@ function test_model() # 30 55 185 constraint!(ocp, :final; rg = Index(1), val = 1, label = :cf) constraint!(ocp, :control; val = 0, label = :cu) constraint!(ocp, :state; val = [0, 1], label = :cs) - constraint!(ocp, :boundary; f = (r, x0, xf, v) -> (r[:] = x0[2] + xf[2] + v[1]; nothing), val = 2, label = :cb) - constraint!(ocp, :control; f = (r, u, v) -> (r[:] = u + v[2]; nothing), val = 20, label = :cuu) - constraint!(ocp, :state; f = (r, x, v) -> (r[:] = x + v[1:2]; nothing), val = [100, 101], label = :css) - constraint!(ocp, :mixed; f = (r, x, u, v) -> (r[:] = x[1] + u + v[2]; nothing), val = -1, label = :cm) + constraint!(ocp, :boundary; f = (r, x0, xf, v) -> (r[:] .= x0[2] + xf[2] + v[1]; nothing), val = 2, label = :cb) + constraint!(ocp, :control; f = (r, u, v) -> (r[:] .= u + v[2]; nothing), val = 20, label = :cuu) + constraint!(ocp, :state; f = (r, x, v) -> (r[:] .= x + v[1:2]; nothing), val = [100, 101], label = :css) + constraint!(ocp, :mixed; f = (r, x, u, v) -> (r[:] .= x[1] + u + v[2]; nothing), val = -1, label = :cm) constraint!(ocp, :variable; val = [5, 5, 5, 5], label = :cv1) constraint!(ocp, :variable; rg = 1:2, val = [10, 20], label = :cv2) constraint!(ocp, :variable; rg = Index(3), val = 1000, label = :cv3) - constraint!(ocp, :variable; f = (r, v) -> (r[:] = v[3]^2; nothing), val = -10, label = :cv4) + constraint!(ocp, :variable; f = (r, v) -> (r[:] .= v[3]^2; nothing), val = -10, label = :cv4) # dimensions (not set yet) @test dim_control_constraints(ocp) === nothing @@ -2237,35 +2237,35 @@ function test_model() # 30 55 185 @test sort(ξu) == sort([20]) r = [0.] ξ!(r, -1, 1, v) - @test r == sort([1 + v[2]]) + @test sort(r) == sort([1 + v[2]]) # state @test sort(ηl) == sort([100, 101]) @test sort(ηu) == sort([100, 101]) r = [0., 0.] η!(r, -1, [1, 1], v) - @test r == sort([1, 1] + v[1:2]) + @test sort(r) == sort([1, 1] + v[1:2]) # mixed @test sort(ψl) == sort([-1]) @test sort(ψu) == sort([-1]) r = [0.] ψ!(r, -1, [1, 1], 2, v) - @test r == sort([3 + v[2]]) + @test sort(r) == sort([3 + v[2]]) # boundary @test sort(ϕl) == sort([10, 1, 2]) @test sort(ϕu) == sort([10, 1, 2]) r = [0., 0., 0.] - ϕ!(r, [1, 3], [4, 100], v)) - @test r == sort([3, 4, 103 + v[1]]) + ϕ!(r, [1, 3], [4, 100], v) + @test sort(r) == sort([3, 4, 103 + v[1]]) # variable @test sort(θl) == sort([-10]) @test sort(θu) == sort([-10]) r = [0.] θ!(r, v) - @test r == sort([v[3]^2]) + @test sort(r) == sort([v[3]^2]) # box constraint @test sort(ul) == sort([0]) From ff75ab0c8fa840e8fd91286490afc82d47d753ad Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Caillau Date: Mon, 9 Sep 2024 12:47:54 +0200 Subject: [PATCH 31/33] added @views in generated functions (onepass) --- src/onepass.jl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/onepass.jl b/src/onepass.jl index fad80760..74f4325b 100644 --- a/src/onepass.jl +++ b/src/onepass.jl @@ -360,7 +360,7 @@ p_constraint!(p, ocp, e1, e2, e3, label = gensym(); log = false) = begin __v_dep(p) && push!(args, p.v) quote function $gs($(args...)) - $r[:] .= $ee2 + @views $r[:] .= $ee2 return nothing end constraint!($ocp, :boundary; f = $gs, lb = $e1, ub = $e3, label = $llabel) @@ -380,7 +380,7 @@ p_constraint!(p, ocp, e1, e2, e3, label = gensym(); log = false) = begin __v_dep(p) && push!(args, p.v) quote function $gs($(args...)) - $r[:] .= $ee2 + @views $r[:] .= $ee2 return nothing end constraint!($ocp, :control; f = $gs, lb = $e1, ub = $e3, label = $llabel) @@ -400,7 +400,7 @@ p_constraint!(p, ocp, e1, e2, e3, label = gensym(); log = false) = begin __v_dep(p) && push!(args, p.v) quote function $gs($(args...)) - $r[:] .= $ee2 + @views $r[:] .= $ee2 return nothing end constraint!($ocp, :state; f = $gs, lb = $e1, ub = $e3, label = $llabel) @@ -414,7 +414,7 @@ p_constraint!(p, ocp, e1, e2, e3, label = gensym(); log = false) = begin args = [r, p.v] quote function $gs($(args...)) - $r[:] .= $e2 + @views $r[:] .= $e2 return nothing end constraint!($ocp, :variable; f = $gs, lb = $e1, ub = $e3, label = $llabel) @@ -433,7 +433,7 @@ p_constraint!(p, ocp, e1, e2, e3, label = gensym(); log = false) = begin __v_dep(p) && push!(args, p.v) quote function $gs($(args...)) - $r[:] .= $ee2 + @views $r[:] .= $ee2 return nothing end constraint!($ocp, :mixed; f = $gs, lb = $e1, ub = $e3, label = $llabel) @@ -462,7 +462,7 @@ p_dynamics!(p, ocp, x, t, e, label = nothing; log = false) = begin args = [r]; __t_dep(p) && push!(args, p.t); push!(args, xt, ut); __v_dep(p) && push!(args, p.v) code = quote function $gs($(args...)) - $r[:] .= $e + @views $r[:] .= $e return nothing end dynamics!($ocp, $gs) @@ -485,7 +485,7 @@ p_lagrange!(p, ocp, e, type; log = false) = begin args = [r]; __t_dep(p) && push!(args, p.t); push!(args, xt, ut); __v_dep(p) && push!(args, p.v) code = quote function $gs($(args...)) - $r[:] .= $e + @views $r[:] .= $e return nothing end objective!($ocp, :lagrange, $gs, $ttype) @@ -513,7 +513,7 @@ p_mayer!(p, ocp, e, type; log = false) = begin args = [r, x0, xf]; __v_dep(p) && push!(args, p.v) code = quote function $gs($(args...)) - $r[:] .= $e + @views $r[:] .= $e return nothing end objective!($ocp, :mayer, $gs, $ttype) From a9f1c7ca2561e6a41d19fa6b43bb2a56afa6cc01 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Caillau Date: Mon, 9 Sep 2024 17:11:12 +0200 Subject: [PATCH 32/33] replace __view by @views r[:] .= ... --- src/optimal_control_model-getters.jl | 18 ++++++++--------- src/optimal_control_model-setters.jl | 8 ++++---- src/utils.jl | 30 ---------------------------- 3 files changed, 13 insertions(+), 43 deletions(-) diff --git a/src/optimal_control_model-getters.jl b/src/optimal_control_model-getters.jl index b8bae46f..446c6fb3 100644 --- a/src/optimal_control_model-getters.jl +++ b/src/optimal_control_model-getters.jl @@ -339,16 +339,16 @@ function constraint( (:control, rg, _, _) => begin C = @match ocp begin ::OptimalControlModel{Autonomous, Fixed} => is_in_place(ocp) ? - ControlConstraint!((r, u) -> (r[:] .= __view(u, rg); nothing), T, V) : # todo: CC!{T, V}(fun) syntax? + ControlConstraint!((r, u) -> (@views r[:] .= u[rg]; nothing), T, V) : # todo: CC!{T, V}(fun) syntax? ControlConstraint(u -> u[rg], T, V) ::OptimalControlModel{Autonomous, NonFixed} => is_in_place(ocp) ? - ControlConstraint!((r, u, v) -> (r[:] .= __view(u, rg); nothing), T, V) : + ControlConstraint!((r, u, v) -> (@views r[:] .= u[rg]; nothing), T, V) : ControlConstraint((u, v) -> u[rg], T, V) ::OptimalControlModel{NonAutonomous, Fixed} => is_in_place(ocp) ? - ControlConstraint!((r, t, u) -> (r[:] .= __view(u, rg); nothing), T, V) : + ControlConstraint!((r, t, u) -> (@views r[:] .= u[rg]; nothing), T, V) : ControlConstraint((t, u) -> u[rg], T, V) ::OptimalControlModel{NonAutonomous, NonFixed} => is_in_place(ocp) ? - ControlConstraint!((r, t, u, v) -> (r[:] .= __view(u, rg); nothing), T, V) : + ControlConstraint!((r, t, u, v) -> (@views r[:] .= u[rg]; nothing), T, V) : ControlConstraint((t, u, v) -> u[rg], T, V) _ => nothing end @@ -358,16 +358,16 @@ function constraint( (:state, rg, _, _) => begin S = @match ocp begin ::OptimalControlModel{Autonomous, Fixed} => is_in_place(ocp) ? - StateConstraint!((r, x) -> (r[:] .= __view(x, rg); nothing), T, V) : + StateConstraint!((r, x) -> (@views r[:] .= x[rg]; nothing), T, V) : StateConstraint(x -> x[rg], T, V) ::OptimalControlModel{Autonomous, NonFixed} => is_in_place(ocp) ? - StateConstraint!((r, x, v) -> (r[:] .= __view(x, rg); nothing), T, V) : + StateConstraint!((r, x, v) -> (@views r[:] .= x[rg]; nothing), T, V) : StateConstraint((x, v) -> x[rg], T, V) ::OptimalControlModel{NonAutonomous, Fixed} => is_in_place(ocp) ? - StateConstraint!((r, t, x) -> (r[:] .= __view(x, rg); nothing), T, V) : + StateConstraint!((r, t, x) -> (@views r[:] .= x[rg]; nothing), T, V) : StateConstraint((t, x) -> x[rg], T, V) ::OptimalControlModel{NonAutonomous, NonFixed} => is_in_place(ocp) ? - StateConstraint!((r, t, x, v) -> (r[:] .= __view(x, rg); nothing), T, V) : + StateConstraint!((r, t, x, v) -> (@views r[:] .= x[rg]; nothing), T, V) : StateConstraint((t, x, v) -> x[rg], T, V) _ => nothing end @@ -376,7 +376,7 @@ function constraint( (:mixed, f::MixedConstraint_, _, _) => return f (:variable, f::VariableConstraint_, _, _) => return f (:variable, rg, _, _) => return ( is_in_place(ocp) ? - VariableConstraint!((r, v) -> (r[:] .= __view(v, rg); nothing)) : + VariableConstraint!((r, v) -> (@views r[:] .= v[rg]; nothing)) : VariableConstraint(v -> v[rg]) ) _ => error("Internal error") end diff --git a/src/optimal_control_model-setters.jl b/src/optimal_control_model-setters.jl index 2519d462..29a3991d 100644 --- a/src/optimal_control_model-setters.jl +++ b/src/optimal_control_model-setters.jl @@ -642,16 +642,16 @@ function constraint!( fun_rg = @match type begin :initial => if is_in_place(ocp) - V == Fixed ? BoundaryConstraint!((r, x0, xf) -> (r[:] .= __view(x0, rg); nothing), V) : - BoundaryConstraint!((r, x0, xf, v) -> (r[:] .= __view(x0, rg); nothing), V) + V == Fixed ? BoundaryConstraint!((r, x0, xf) -> (@views r[:] .= x0[rg]; nothing), V) : + BoundaryConstraint!((r, x0, xf, v) -> (@views r[:] .= x0[rg]; nothing), V) else V == Fixed ? BoundaryConstraint((x0, xf) -> x0[rg], V) : BoundaryConstraint((x0, xf, v) -> x0[rg], V) end :final => if is_in_place(ocp) - V == Fixed ? BoundaryConstraint!((r, x0, xf) -> (r[:] .= __view(xf, rg); nothing), V) : - BoundaryConstraint!((r, x0, xf, v) -> (r[:] .= __view(xf, rg); nothing), V) + V == Fixed ? BoundaryConstraint!((r, x0, xf) -> (@views r[:] .= xf[rg]; nothing), V) : + BoundaryConstraint!((r, x0, xf, v) -> (@views r[:] .= xf[rg]; nothing), V) else V == Fixed ? BoundaryConstraint((x0, xf) -> xf[rg], V) : BoundaryConstraint((x0, xf, v) -> xf[rg], V) diff --git a/src/utils.jl b/src/utils.jl index b745ca3b..6a4ac54d 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -228,36 +228,6 @@ end """ $(TYPEDSIGNATURES) -Adapt `view` to treat uniformly scalars. - -**Note.** Throws an error if `rg` is not one (or `Index(1)`). -""" -__view(x::Number, rg) = x[rg] - -""" -$(TYPEDSIGNATURES) - -Adapt `view` to treat uniformly scalars. -""" -__view(x::AbstractVector, rg::Integer) = x[rg] - -""" -$(TYPEDSIGNATURES) - -Adapt `view` to treat uniformly scalars. -""" -__view(x::AbstractVector, rg::Index) = x[rg] - -""" -$(TYPEDSIGNATURES) - -Adapt `view` to treat uniformly scalars. -""" -__view(x::AbstractVector, rg::AbstractRange) = view(x, rg) # Allows StepRange - -""" -$(TYPEDSIGNATURES) - Tranform in place function to out of place. Pass the result size and type (default = `Float64`). Return a scalar when the result has size one. If `f!` is `nothing`, return `nothing`. """ From 8abc547d56022137fa8c42ae831e533c0e3412ab Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Caillau Date: Mon, 9 Sep 2024 17:23:18 +0200 Subject: [PATCH 33/33] replaced view(x, ...) by @view(x[...]) for further perf. improvements --- src/optimal_control_model-getters.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/optimal_control_model-getters.jl b/src/optimal_control_model-getters.jl index 446c6fb3..7b22695e 100644 --- a/src/optimal_control_model-getters.jl +++ b/src/optimal_control_model-getters.jl @@ -162,7 +162,7 @@ function nlp_constraints!(ocp::OptimalControlModel) j = 1 for i ∈ 1:length(ξf) li = ξs[i] - ξf[i](view(val, j:(j + li - 1)), t, u, v) + ξf[i](@view(val[j:(j + li - 1)]), t, u, v) j = j + li end return nothing @@ -185,7 +185,7 @@ function nlp_constraints!(ocp::OptimalControlModel) j = 1 for i ∈ 1:length(ηf) li = ηs[i] - ηf[i](view(val, j:(j + li - 1)), t, x, v) + ηf[i](@view(val[j:(j + li - 1)]), t, x, v) j = j + li end return nothing @@ -208,7 +208,7 @@ function nlp_constraints!(ocp::OptimalControlModel) j = 1 for i ∈ 1:length(ψf) li = ψs[i] - ψf[i](view(val, j:(j + li - 1)), t, x, u, v) + ψf[i](@view(val[j:(j + li - 1)]), t, x, u, v) j = j + li end return nothing @@ -231,7 +231,7 @@ function nlp_constraints!(ocp::OptimalControlModel) j = 1 for i ∈ 1:length(ϕf) li = ϕs[i] - ϕf[i](view(val, j:(j + li - 1)), x0, xf, v) + ϕf[i](@view(val[j:(j + li - 1)]), x0, xf, v) j = j + li end return nothing @@ -254,7 +254,7 @@ function nlp_constraints!(ocp::OptimalControlModel) j = 1 for i ∈ 1:length(θf) li = θs[i] - θf[i](view(val, j:(j + li - 1)), v) + θf[i](@view(val[j:(j + li - 1)]), v) j = j + li end return nothing