From 46386cd95e0482103c9defa98c20ef6080f798e8 Mon Sep 17 00:00:00 2001 From: Baptiste Combelles Date: Mon, 31 Jul 2023 11:07:28 +0200 Subject: [PATCH] change functional constraint functions --- bench/bench_nlp_constraints.md | 238 +++++++++++++++++++-------------- src/ctparser_utils.jl | 20 +-- src/model.jl | 176 ++---------------------- test/test_ctparser_utils.jl | 10 +- test/test_model.jl | 133 +++++++++--------- test/test_print.jl | 12 +- 6 files changed, 232 insertions(+), 357 deletions(-) diff --git a/bench/bench_nlp_constraints.md b/bench/bench_nlp_constraints.md index 6aee2ff7..f0f90403 100644 --- a/bench/bench_nlp_constraints.md +++ b/bench/bench_nlp_constraints.md @@ -4,6 +4,7 @@ using BenchmarkTools using CTBase using MLStyle +using StaticArrays rg(i::Integer, j::Integer) = begin if i == j i @@ -11,22 +12,22 @@ rg(i::Integer, j::Integer) = begin i:j end end -$(Expr(:toplevel, :(ocp = Model()), :(time!(ocp, 0, 1)), :(state!(ocp, 2)), :(control!(ocp, 1)))) +$(Expr(:toplevel, :(ocp = Model()), :(time!(ocp, 0, 1)), :(state!(ocp, 2)), :(control!(ocp, 2)))) constraint!(ocp, :initial, Index(2), 10, :ci) constraint!(ocp, :final, Index(1), 1, :cf) -constraint!(ocp, :control, 0, 1, :cu) +constraint!(ocp, :control, [0, 0], [1, 1], :cu) constraint!(ocp, :state, [0, 1], [1, 2], :cs) constraint!(ocp, :boundary, ((x0, xf)->begin x0[2] + xf[2] end), 0, 1, :cb) constraint!(ocp, :control, (u->begin u - end), 0, 1, :cuu) + end), [0, 0], [1, 1], :cuu) constraint!(ocp, :state, (x->begin x end), [0, 1], [1, 2], :css) constraint!(ocp, :mixed, ((x, u)->begin - x[1] + u + x[1] + u[1] end), 1, 1, :cm) function nlp_constraints_original(ocp::OptimalControlModel) CTBase.__check_all_set(ocp) @@ -147,42 +148,52 @@ function nlp_constraints_original(ocp::OptimalControlModel) end return ((ξl, ξ, ξu), (ηl, η, ηu), (ψl, ψ, ψu), (ϕl, ϕ, ϕu), (θl, θ, θu), (ul, uind, uu), (xl, xind, xu), (vl, vind, vu)) end -function test_alloc_bad(ocp) - function get_state(XU, i, n, m) - return XU[rg((i - 1) * (n + m) + 1, (i - 1) * (n + m) + n)] - end - function get_control(XU, i, n, m) - return XU[rg((i - 1) * (n + m) + n + 1, (i - 1) * (n + m) + n + m)] - end - function set_control_constraint!(C, i, ξ, nξ, nc) - C[(i - 1) * nc + 1:(i - 1) * nc + nξ] = ξ - end - function set_state_constraint!(C, i, η, nη, nξ, nc) - C[(i - 1) * nc + nξ + 1:(i - 1) * nc + nξ + nη] = η - end - function set_mixed_constraint!(C, i, ψ, nψ, nξ, nη, nc) - C[(i - 1) * nc + nξ + nη + 1:(i - 1) * nc + nξ + nη + nψ] = ψ +function test_alloc_bad(ocp, N) + println(" getters and setters") + begin + function get_state(XU, i, n, m) + return XU[rg((i - 1) * (n + m) + 1, (i - 1) * (n + m) + n)] + end + function get_control(XU, i, n, m) + return XU[rg((i - 1) * (n + m) + n + 1, (i - 1) * (n + m) + n + m)] + end + function set_control_constraint!(C, i, ξ, nξ, nc) + C[(i - 1) * nc + 1:(i - 1) * nc + nξ] = ξ + end + function set_state_constraint!(C, i, η, nη, nξ, nc) + C[(i - 1) * nc + nξ + 1:(i - 1) * nc + nξ + nη] = η + end + function set_mixed_constraint!(C, i, ψ, nψ, nξ, nη, nc) + C[(i - 1) * nc + nξ + nη + 1:(i - 1) * nc + nξ + nη + nψ] = ψ + end end + println(" call nlp_constraints_original") ((ξl, ξ, ξu), (ηl, η, ηu), (ψl, ψ, ψu), (ϕl, ϕ, ϕu), (θl, θ, θu), (ul, uind, uu), (xl, xind, xu), (vl, vind, vu)) = nlp_constraints_original(ocp) - v = Real[] - n = 2 - m = 1 - N = 200 - times = LinRange(0, 1, N) - XU = ones(N * (n + m)) - nξ = length(ξl) - nη = length(ηl) - nψ = length(ψl) - nc = nξ + nη + nψ - C = zeros(N * nc) - for i = 1:N - t = times[i] - x = get_state(XU, i, n, m) - u = get_control(XU, i, n, m) - set_control_constraint!(C, i, ξ(t, u, v), nξ, nc) - set_state_constraint!(C, i, η(t, x, v), nη, nξ, nc) - set_mixed_constraint!(C, i, ψ(t, x, u, v), nψ, nξ, nη, nc) + println(" declare variables") + begin + v = Real[] + n = ocp.state_dimension + m = ocp.control_dimension + times = LinRange(0, 1, N) + XU = ones(N * (n + m)) + nξ = length(ξl) + nη = length(ηl) + nψ = length(ψl) + nc = nξ + nη + nψ + C = zeros(N * nc) + end + println(" start for loop") + begin + for i = 1:N + t = times[i] + x = get_state(XU, i, n, m) + u = get_control(XU, i, n, m) + set_control_constraint!(C, i, ξ(t, u, v), nξ, nc) + set_state_constraint!(C, i, η(t, x, v), nη, nξ, nc) + set_mixed_constraint!(C, i, ψ(t, x, u, v), nψ, nξ, nη, nc) + end end + println(" end for loop") nothing end function nlp_constraints_optimized(ocp::OptimalControlModel) @@ -284,101 +295,122 @@ function nlp_constraints_optimized(ocp::OptimalControlModel) ψfn = length(ψf) ϕfn = length(ϕf) θfn = length(θf) - function ξ!(val, t, u, v) + function ξ!(val, t, u, v, N = ξfn) offset = 0 - for i = 1:ξfn - val[1 + offset:(ξn[i] + offset) - 1] = (ξf[i])(t, u, v) + for i = 1:N + z = ((ξf[i])(t, u, v))[:] + val[rg(1 + offset, ξn[i] + offset)] = z offset += ξn[i] end nothing end - function η!(val, t, x, v) + function η!(val, t, x, v, N = ηfn) offset = 0 - for i = 1:ηfn - val[1 + offset:(ηn[i] + offset) - 1] = (ηf[i])(t, x, v) + for i = 1:N + val[rg(1 + offset, ηn[i] + offset)] = (ηf[i])(t, x, v) offset += ηn[i] end nothing end - function ψ!(val, t, x, u, v) + function ψ!(val, t, x, u, v, N = ψfn) offset = 0 - for i = 1:ψfn - val[1 + offset:(ψn[i] + offset) - 1] = (ψf[i])(t, x, u, v) + for i = 1:N + val[rg(1 + offset, ψn[i] + offset)] = (ψf[i])(t, x, u, v) offset += ψn[i] end nothing end - function ϕ!(val, x0, xf, v) + function ϕ!(val, x0, xf, v, N = ϕfn) offset = 0 - for i = 1:ϕfn - val[1 + offset:(ϕn[i] + offset) - 1] = (ϕf[i])(x0, xf, v) + for i = 1:N + val[rg(1 + offset, ϕn[i] + offset)] = (ϕf[i])(x0, xf, v) offset += ϕn[i] end nothing end - function θ!(val, v) + function θ!(val, v, N = θfn) offset = 0 - for i = 1:θfn - val[1 + offset:(θn[i] + offset) - 1] = (θf[i])(v) + for i = 1:N + val[rg(1 + offset, θn[i] + offset)] = (θf[i])(v) offset += θn[i] end nothing end return ((ξl, ξ!, ξu), (ηl, η!, ηu), (ψl, ψ!, ψu), (ϕl, ϕ!, ϕu), (θl, θ!, θu), (uind, ul, uu), (xind, xl, xu), (vind, vl, vu)) end -function test_alloc_good(ocp) - function get_state(XU, i, n, m) - if n == 1 - return XU[(i - 1) * (n + m) + 1] - else - return @view(XU[rg((i - 1) * (n + m) + 1, (i - 1) * (n + m) + n)]) +function test_alloc_good(ocp, N) + begin + println(" getters and setters") + begin + function get_state(XU, i, n, m) + if n == 1 + return XU[(i - 1) * (n + m) + 1] + else + return @view(XU[(i - 1) * (n + m) + 1:(i - 1) * (n + m) + n]) + end + end + function get_control(XU, i, n, m) + if m == 1 + return XU[(i - 1) * (n + m) + n + 1] + else + return @view(XU[(i - 1) * (n + m) + n + 1:(i - 1) * (n + m) + n + m]) + end + end + function set_control_constraint!(C, i, valξ, nξ, nc) + C[(i - 1) * nc + 1:(i - 1) * nc + nξ] = valξ + end + function set_state_constraint!(C, i, valη, nη, nξ, nc) + C[(i - 1) * nc + nξ + 1:(i - 1) * nc + nξ + nη] = valη + end + function set_mixed_constraint!(C, i, valψ, nψ, nξ, nη, nc) + C[(i - 1) * nc + nξ + nη + 1:(i - 1) * nc + nξ + nη + nψ] = valψ + end end - end - function get_control(XU, i, n, m) - if m == 1 - return XU[(i - 1) * (n + m) + n + 1] - else - return @view(XU[rg((i - 1) * (n + m) + n + 1, (i - 1) * (n + m) + n + m)]) + println(" call nlp_constraints_optimized") + begin + ((ξl, ξ!, ξu), (ηl, η!, ηu), (ψl, ψ!, ψu), (ϕl, ϕ!, ϕu), (θl, θ!, θu), (ul, uind, uu), (xl, xind, xu), (vl, vind, vu)) = nlp_constraints_optimized(ocp) end + println(" declare variables") + begin + v = Real[] + n = ocp.state_dimension + m = ocp.control_dimension + times = LinRange(0, 1, N) + XU = zeros(N * (n + m)) + nξ = length(ξl) + nη = length(ηl) + nψ = length(ψl) + nc = nξ + nη + nψ + C = zeros(N * nc) + valξ = SizedVector{nξ}(zeros(nξ)) + valη = SizedVector{nη}(zeros(nη)) + valψ = SizedVector{nψ}(zeros(nψ)) + x = SizedVector{n}(zeros(n)) + u = SizedVector{m}(zeros(m)) + end + t = 0 + println(" start for loop") + for i = 1:N + t = times[i] + x[:] = XU[(i - 1) * (n + m) + 1:(i - 1) * (n + m) + n] + u[:] = @view(XU[(i - 1) * (n + m) + n + 1:(i - 1) * (n + m) + n + m]) + ξ!(valξ, t, u, v) + η!(valη, t, x, v) + ψ!(valψ, t, x, u, v) + C[(i - 1) * nc + 1:(i - 1) * nc + nξ] = valξ + C[(i - 1) * nc + nξ + 1:(i - 1) * nc + nξ + nη] = valη + C[(i - 1) * nc + nξ + nη + 1:(i - 1) * nc + nξ + nη + nψ] = valψ + end + println(" end for loop") + nothing end - function set_control_constraint!(C, i, valξ, nξ, nc) - C[(i - 1) * nc + 1:(i - 1) * nc + nξ] = valξ - end - function set_state_constraint!(C, i, valη, nη, nξ, nc) - C[(i - 1) * nc + nξ + 1:(i - 1) * nc + nξ + nη] = valη - end - function set_mixed_constraint!(C, i, valψ, nψ, nξ, nη, nc) - C[(i - 1) * nc + nξ + nη + 1:(i - 1) * nc + nξ + nη + nψ] = valψ - end - ((ξl, ξ!, ξu), (ηl, η!, ηu), (ψl, ψ!, ψu), (ϕl, ϕ!, ϕu), (θl, θ!, θu), (ul, uind, uu), (xl, xind, xu), (vl, vind, vu)) = nlp_constraints_optimized(ocp) - v = Real[] - n = 2 - m = 1 - N = 100 - times = LinRange(0, 1, N) - XU = ones(N * (n + m)) - nξ = length(ξl) - nη = length(ηl) - nψ = length(ψl) - nc = nξ + nη + nψ - C = zeros(N * nc) - valξ = zeros(nξ) - valη = zeros(nη) - valψ = zeros(nψ) - for i = 1:N - t = times[i] - x = get_state(XU, i, n, m) - u = get_control(XU, i, n, m) - ξ!(valξ, t, u, v) - η!(valη, t, x, v) - ψ!(valψ, t, x, u, v) - set_control_constraint!(C, i, valξ, nξ, nc) - set_state_constraint!(C, i, valη, nη, nξ, nc) - set_mixed_constraint!(C, i, valψ, nψ, nξ, nη, nc) - end - nothing end -println("Allocations and times for good and bad code") -println() +N = 10000 +$(Expr(:toplevel, :(test_alloc_good(ocp, N)))) +$(Expr(:toplevel, :(test_alloc_bad(ocp, N)))) +println("----------------------------------------") println("good code") -t_good = @benchmark(test_alloc_good(ocp)) +@time test_alloc_good(ocp, N) +println() +println("bad code") +@time test_alloc_bad(ocp, N) diff --git a/src/ctparser_utils.jl b/src/ctparser_utils.jl index c2ac2825..ac3f6698 100644 --- a/src/ctparser_utils.jl +++ b/src/ctparser_utils.jl @@ -249,7 +249,7 @@ julia> constraint_type(:( x[1:2](0) ), t, t0, tf, x, u, v) (:initial, 1:2) julia> constraint_type(:( x[1](0) ), t, t0, tf, x, u, v) -(:initial, Index(1)) +(:initial, 1) julia> constraint_type(:( 2x[1](0)^2 ), t, t0, tf, x, u, v) :boundary @@ -264,7 +264,7 @@ julia> constraint_type(:( x[1:2](tf) ), t, t0, tf, x, u, v) (:final, 1:2) julia> constraint_type(:( x[1](tf) ), t, t0, tf, x, u, v) -(:final, Index(1)) +(:final, 1) julia> constraint_type(:( 2x[1](tf)^2 ), t, t0, tf, x, u, v) :boundary @@ -279,7 +279,7 @@ julia> constraint_type(:( u[1:2](t) ), t, t0, tf, x, u, v) (:control_range, 1:2) julia> constraint_type(:( u[1](t) ), t, t0, tf, x, u, v) -(:control_range, Index(1)) +(:control_range, 1) julia> constraint_type(:( u(t) ), t, t0, tf, x, u, v) (:control_range, nothing) @@ -294,7 +294,7 @@ julia> constraint_type(:( x[1:2](t) ), t, t0, tf, x, u, v) (:state_range, 1:2) julia> constraint_type(:( x[1](t) ), t, t0, tf, x, u, v) -(:state_range, Index(1)) +(:state_range, 1) julia> constraint_type(:( x(t) ), t, t0, tf, x, u, v) (:state_range, nothing) @@ -321,7 +321,7 @@ julia> constraint_type(:( v[1:10] ), t, t0, tf, x, u, v) (:variable_range, 1:10) julia> constraint_type(:( v[2] ), t, t0, tf, x, u, v) -(:variable_range, Index(2)) +(:variable_range, 2) julia> constraint_type(:( v ), t, t0, tf, x, u, v) (:variable_range, nothing) @@ -338,33 +338,33 @@ constraint_type(e, t, t0, tf, x, u, v) = begin [ true , false, false, false, false, false, _ ] => @match e begin :( $y[$i:$p:$j]($s) ) && if (y == x && s == t0) end => (:initial , i:p:j ) :( $y[$i:$j ]($s) ) && if (y == x && s == t0) end => (:initial , i:j ) - :( $y[$i ]($s) ) && if (y == x && s == t0) end => (:initial , Index(i)) + :( $y[$i ]($s) ) && if (y == x && s == t0) end => (:initial , i) :( $y($s) ) && if (y == x && s == t0) end => (:initial , nothing ) _ => :boundary end [ false, true , false, false, false, false, _ ] => @match e begin :( $y[$i:$p:$j]($s) ) && if (y == x && s == tf) end => (:final , i:p:j ) :( $y[$i:$j ]($s) ) && if (y == x && s == tf) end => (:final , i:j ) - :( $y[$i ]($s) ) && if (y == x && s == tf) end => (:final , Index(i)) + :( $y[$i ]($s) ) && if (y == x && s == tf) end => (:final , i) :( $y($s) ) && if (y == x && s == tf) end => (:final , nothing ) _ => :boundary end [ true , true , false, false, false, false, _ ] => :boundary [ false, false, true , false, false, false, _ ] => @match e begin :( $c[$i:$p:$j]($s) ) && if (c == u && s == t) end => (:control_range, i:p:j ) :( $c[$i:$j ]($s) ) && if (c == u && s == t) end => (:control_range, i:j ) - :( $c[$i ]($s) ) && if (c == u && s == t) end => (:control_range, Index(i)) + :( $c[$i ]($s) ) && if (c == u && s == t) end => (:control_range, i) :( $c($s) ) && if (c == u && s == t) end => (:control_range, nothing ) _ => :control_fun end [ false, false, false, true , false, false, _ ] => @match e begin :( $y[$i:$p:$j]($s) ) && if (y == x && s == t) end => (:state_range, i:p:j ) :( $y[$i:$j ]($s) ) && if (y == x && s == t) end => (:state_range, i:j ) - :( $y[$i ]($s) ) && if (y == x && s == t) end => (:state_range, Index(i)) + :( $y[$i ]($s) ) && if (y == x && s == t) end => (:state_range, i) :( $y($s) ) && if (y == x && s == t) end => (:state_range, nothing ) _ => :state_fun end [ false, false, true , true , false, false, _ ] => :mixed [ false, false, false, false, false, false, true ] => @match e begin :( $w[$i:$p:$j] ) && if (w == v) end => (:variable_range, i:p:j ) :( $w[$i:$j ] ) && if (w == v) end => (:variable_range, i:j ) - :( $w[$i ] ) && if (w == v) end => (:variable_range, Index(i)) + :( $w[$i ] ) && if (w == v) end => (:variable_range, i) _ && if (e == v) end => (:variable_range, nothing ) _ => :variable_fun end _ => :other diff --git a/src/model.jl b/src/model.jl index d9ffaaf4..1580ed96 100644 --- a/src/model.jl +++ b/src/model.jl @@ -500,113 +500,6 @@ end """ $(TYPEDSIGNATURES) -Add an `:initial` or `:final` value constraint on a range of the state, or a value constraint on a range of the -`:variable`. - -!!! note - - - The range of the constraint must be contained in 1:n if the constraint is on the state, or 1:q if the constraint is on the variable. - - The state, control and variable dimensions must be set before. Use state!, control! and variable!. - - The times must be set before. Use time!. - -# Examples - -```jldoctest -julia> constraint!(ocp, :initial, 1:2:5, [ 0, 0, 0 ]) -julia> constraint!(ocp, :initial, 2:3, [ 0, 0 ]) -julia> constraint!(ocp, :final, Index(2), 0) -julia> constraint!(ocp, :variable, 2:3, [ 0, 3 ]) -``` -""" -function constraint!(ocp::OptimalControlModel, type::Symbol, rg::RangeConstraint, val::ctVector, label::Symbol=__constraint_label()) - - # we check if the dimensions and times have been set just to force the user to set them before - __check_all_set(ocp) - type == :variable && is_variable_independent(ocp) && throw(UnauthorizedCall("the ocp is variable independent" * - ", you cannot use constraint! function with type=:variable.")) - - # check if the constraint named label already exists - if label ∈ constraints_labels(ocp) - throw(UnauthorizedCall("the constraint named " * String(label) * " already exists.")) - end - - # check if rg and val are consistent - (length(rg) != length(val)) && throw(IncorrectArgument("the range `rg`` and the value `val` must have the same dimension")) - - # dimensions - n = ocp.state_dimension - q = ocp.variable_dimension - - # check if the range is valid - if type == :initial - !all(1 .≤ rg .≤ n) && throw(IncorrectArgument("the range $rg of the initial state constraint must be contained in 1:$n")) - elseif type == :final - !all(1 .≤ rg .≤ n) && throw(IncorrectArgument("the range $rg of the final state constraint must be contained in 1:$n")) - elseif type == :variable - !all(1 .≤ rg .≤ q) && throw(IncorrectArgument("the range $rg of the variable constraint must be contained in 1:$q")) - end - - # - constraint!(ocp, type, rg, val, val, label) - -end - -""" -$(TYPEDSIGNATURES) - -Add an `:initial` or `:final` value constraint on the state, or a `:variable` value. Can also be used with -`:state` and `:control`. - -!!! note - - - The state, control and variable dimensions must be set before. Use state!, control! and variable!. - - The times must be set before. Use time!. - - When an element is of dimension 1, consider it as a scalar. - -# Examples - -```jldoctest -julia> constraint!(ocp, :initial, [ 0, 0 ]) -julia> constraint!(ocp, :final, 2) # if the state is of dimension 1 -julia> constraint!(ocp, :variable, [ 3, 0, 1 ]) -``` -""" -function constraint!(ocp::OptimalControlModel, type::Symbol, val::ctVector, label::Symbol=__constraint_label()) - # we use the constraint! defined before - - # we check if the dimensions and times have been set - __check_all_set(ocp) - type == :variable && is_variable_independent(ocp) && throw(UnauthorizedCall("the ocp is variable independent" * - ", you cannot use constraint! function with type=:variable.")) - - # - rg = nothing - - # dimensions - n = ocp.state_dimension - q = ocp.variable_dimension - - # - if type ∈ [:initial, :final, :state, :control ] # also allowed for :control and :state to treat uniformly eq and ineq - rg = n == 1 ? Index(1) : 1:n - # check if rg and val are consistent - (length(rg) != length(val)) && throw(IncorrectArgument("`val` must be of dimension $n")) - elseif type == :variable - rg = q == 1 ? Index(1) : 1:q - (length(rg) != length(val)) && throw(IncorrectArgument("`val` must be of dimension $q")) - else - throw(IncorrectArgument("the following type of constraint is not valid: " * String(type) * - ". Please choose in [ :initial, :final, :state, :control, :variable ] or check the arguments of the constraint! method.")) - end - - # - constraint!(ocp, type, rg, val, label) - -end - -""" -$(TYPEDSIGNATURES) - Add an `:initial`, `:final`, `:control`, `:state` or `:variable` box constraint (whole range). !!! note @@ -739,53 +632,6 @@ function constraint!(ocp::OptimalControlModel{T, V}, type::Symbol, f::Function, end -""" -$(TYPEDSIGNATURES) - -Add a `:boundary`, `:control`, `:state`, `:mixed` or `:variable` value functional constraint. - -!!! note - - - The state, control and variable dimensions must be set before. Use state!, control! and variable!. - - The times must be set before. Use time!. - - When an element is of dimension 1, consider it as a scalar. - -# Examples - -```@example -# variable independent ocp -julia> constraint!(ocp, :boundary, (x0, xf) -> x0[3]+xf[2], 0) - -# variable dependent ocp -julia> constraint!(ocp, :boundary, (x0, xf, v) -> x0[3]+xf[2]*v[1], 0) - -# time independent and variable independent ocp -julia> constraint!(ocp, :control, u -> 2u, 1) -julia> constraint!(ocp, :state, x -> x-1, [ 0, 0, 0 ]) -julia> constraint!(ocp, :mixed, (x, u) -> x[1]-u, 0) - -# time dependent and variable independent ocp -julia> constraint!(ocp, :control, (t, u) -> 2u, 1) -julia> constraint!(ocp, :state, (t, x) -> x-t, [ 0, 0, 0 ]) -julia> constraint!(ocp, :mixed, (t, x, u) -> x[1]-u, 0) - -# time independent and variable dependent ocp -julia> constraint!(ocp, :control, (u, v) -> 2u*v[1], 1) -julia> constraint!(ocp, :state, (x, v) -> x-v[2], [ 0, 0, 0 ]) -julia> constraint!(ocp, :mixed, (x, u) -> x[1]-u+v[1], 0) - -# time dependent and variable dependent ocp -julia> constraint!(ocp, :control, (t, u, v) -> 2u-t*v[2], 1) -julia> constraint!(ocp, :state, (t, x, v) -> x-t+v[1], [ 0, 0, 0 ]) -julia> constraint!(ocp, :mixed, (t, x, u, v) -> x[1]-u*v[1], 0) -``` -""" -function constraint!(ocp::OptimalControlModel, type::Symbol, f::Function, val::ctVector, - label::Symbol=__constraint_label()) # we use the constraint! defined before - constraint!(ocp, type, f, val, val, label) -end - - """ $(TYPEDSIGNATURES) @@ -801,29 +647,25 @@ Add an `:initial`, `:final`, `:control`, `:state` or `:variable` box constraint ```jldoctest julia> constraint!(ocp, :initial, rg=2:3, lb=[ 0, 0 ], ub=[ 1, 2 ]) -julia> constraint!(ocp, :final, val=Index(1), lb=0, ub=2) -julia> constraint!(ocp, :control, val=Index(1), lb=0, ub=2) +julia> constraint!(ocp, :final, rg=1, lb=0, ub=2) +julia> constraint!(ocp, :control, rg=1, lb=0, ub=2) julia> constraint!(ocp, :state, rg=2:3, lb=[ 0, 0 ], ub=[ 1, 2 ]) julia> constraint!(ocp, :initial, rg=1:2:5, lb=[ 0, 0, 0 ], ub=[ 1, 2, 1 ]) julia> constraint!(ocp, :variable, rg=1:2, lb=[ 0, 0 ], ub=[ 1, 2 ]) ``` """ function constraint!(ocp::OptimalControlModel{<: TimeDependence, <: VariableDependence}, type::Symbol; - rg::Union{RangeConstraint,Nothing}=nothing, f::Union{Function,Nothing}=nothing, - val::Union{ctVector,Nothing}=nothing, lb::Union{ctVector,Nothing}=nothing, ub::Union{ctVector,Nothing}=nothing, + rg::Union{OrdinalRange{<:Integer},Integer,Nothing}=nothing, f::Union{Function,Nothing}=nothing, lb::Union{ctVector,Nothing}=nothing, ub::Union{ctVector,Nothing}=nothing, label::Symbol=__constraint_label()) - (lb ≢ nothing && ub === nothing) && (ub = Inf*(size(lb,1) == 1 ? 1 : ones(eltype(ub), size(ub,1)))) (lb === nothing && ub ≢ nothing) && (lb = -Inf*(size(ub,1) == 1 ? 1 : ones(eltype(ub), size(ub,1)))) - - @match (rg,f,val,lb,ub) begin - (::Nothing,::Nothing,::ctVector,::Nothing,::Nothing) => return constraint!(ocp, type, val, label) # - (::Nothing,::Nothing,::Nothing,::ctVector,::ctVector) => return constraint!(ocp, type, lb, ub, label) # - (::Nothing,::Function,::ctVector,::Nothing,::Nothing) => return constraint!(ocp, type, f, val, label) # - (::Nothing,::Function,::Nothing,::ctVector,::ctVector) => return constraint!(ocp, type, f, lb, ub, label) # - (::RangeConstraint,::Nothing,::ctVector,::Nothing,::Nothing) => return constraint!(ocp, type, rg, val, label) # - (::RangeConstraint,::Nothing,::Nothing,::ctVector,::ctVector) => return constraint!(ocp, type, rg, lb, ub, label) # + (typeof(rg) <: Int) && (rg = Index(rg)) + + @match (rg,f,lb,ub) begin + (::Nothing,::Nothing,::ctVector,::ctVector) => return constraint!(ocp, type, lb, ub, label) # + (::Nothing,::Function,::ctVector,::ctVector) => return constraint!(ocp, type, f, lb, ub, label) # + (::RangeConstraint,::Nothing,::ctVector,::ctVector) => return constraint!(ocp, type, rg, lb, ub, label) # _ => throw(IncorrectArgument("Provided arguments are inconsistent")) end diff --git a/test/test_ctparser_utils.jl b/test/test_ctparser_utils.jl index aeb1454b..9acf7e11 100644 --- a/test/test_ctparser_utils.jl +++ b/test/test_ctparser_utils.jl @@ -64,24 +64,24 @@ t = :t; t0 = 0; tf = :tf; x = :x; u = :u; v = :v @test constraint_type(:( x(0) ), t, t0, tf, x, u, v) == (:initial, nothing) @test constraint_type(:( x[1:2:5](0) ), t, t0, tf, x, u, v) == (:initial, 1:2:5) @test constraint_type(:( x[1:2](0) ), t, t0, tf, x, u, v) == (:initial, 1:2) -@test constraint_type(:( x[1](0) ), t, t0, tf, x, u, v) == (:initial, Index(1)) +@test constraint_type(:( x[1](0) ), t, t0, tf, x, u, v) == (:initial, 1) @test constraint_type(:( x[1:2](0) ), t, t0, tf, x, u, v) == (:initial, 1:2) @test constraint_type(:( 2x[1](0)^2 ), t, t0, tf, x, u, v) == :boundary @test constraint_type(:( x(tf) ), t, t0, tf, x, u, v) == (:final, nothing) @test constraint_type(:( x[1:2:5](tf) ), t, t0, tf, x, u, v) == (:final, 1:2:5) @test constraint_type(:( x[1:2](tf) ), t, t0, tf, x, u, v) == (:final, 1:2) -@test constraint_type(:( x[1](tf) ), t, t0, tf, x, u, v) == (:final, Index(1)) +@test constraint_type(:( x[1](tf) ), t, t0, tf, x, u, v) == (:final, 1) @test constraint_type(:( x[1:2](tf) ), t, t0, tf, x, u, v) == (:final, 1:2) @test constraint_type(:( x[1](tf) - x[2](0) ), t, t0, tf, x, u, v) == :boundary @test constraint_type(:( 2x[1](tf)^2 ), t, t0, tf, x, u, v) == :boundary @test constraint_type(:( u[1:2:5](t) ), t, t0, tf, x, u, v) == (:control_range, 1:2:5) @test constraint_type(:( u[1:2](t) ), t, t0, tf, x, u, v) == (:control_range, 1:2) -@test constraint_type(:( u[1](t) ), t, t0, tf, x, u, v) == (:control_range, Index(1)) +@test constraint_type(:( u[1](t) ), t, t0, tf, x, u, v) == (:control_range, 1) @test constraint_type(:( u(t) ), t, t0, tf, x, u, v) == (:control_range, nothing) @test constraint_type(:( 2u[1](t)^2 ), t, t0, tf, x, u, v) == :control_fun @test constraint_type(:( x[1:2:5](t) ), t, t0, tf, x, u, v) == (:state_range, 1:2:5) @test constraint_type(:( x[1:2](t) ), t, t0, tf, x, u, v) == (:state_range, 1:2) -@test constraint_type(:( x[1](t) ), t, t0, tf, x, u, v) == (:state_range, Index(1)) +@test constraint_type(:( x[1](t) ), t, t0, tf, x, u, v) == (:state_range, 1) @test constraint_type(:( x(t) ), t, t0, tf, x, u, v) == (:state_range, nothing) @test constraint_type(:( 2x[1](t)^2 ), t, t0, tf, x, u, v) == :state_fun @test constraint_type(:( 2u[1](t)^2 * x(t) ), t, t0, tf, x, u, v) == :mixed @@ -89,7 +89,7 @@ t = :t; t0 = 0; tf = :tf; x = :x; u = :u; v = :v @test constraint_type(:( 2u[1](t)^2 * x(t) + v ), t, t0, tf, x, u, v) == :mixed @test constraint_type(:( v[1:2:10] ), t, t0, tf, x, u, v) == (:variable_range, 1:2:9) @test constraint_type(:( v[1:10] ), t, t0, tf, x, u, v) == (:variable_range, 1:10) -@test constraint_type(:( v[2] ), t, t0, tf, x, u, v) == (:variable_range, Index(2)) +@test constraint_type(:( v[2] ), t, t0, tf, x, u, v) == (:variable_range, 2) @test constraint_type(:( v ), t, t0, tf, x, u, v) == (:variable_range, nothing) @test constraint_type(:( v^2 + 1 ), t, t0, tf, x, u, v) == :variable_fun @test constraint_type(:( v[2]^2 + 1 ), t, t0, tf, x, u, v) == :variable_fun diff --git a/test/test_model.jl b/test/test_model.jl index 744431d1..b5d4b1c2 100644 --- a/test/test_model.jl +++ b/test/test_model.jl @@ -5,10 +5,10 @@ function test_model() # 30 55 185 @testset "variable!" begin ocp = Model(variable=false) @test_throws UnauthorizedCall variable!(ocp, 1) - @test_throws UnauthorizedCall constraint!(ocp, :variable, 2:3, [ 0, 3 ]) + @test_throws UnauthorizedCall constraint!(ocp, :variable, 2:3, [ 0, 3 ], [ 0, 3 ]) @test_throws UnauthorizedCall constraint!(ocp, :variable, 0, 1) # the variable here is of dimension 1 @test_throws UnauthorizedCall constraint!(ocp, :variable, 1:2, [ 0, 0 ], [ 1, 2 ]) - @test_throws UnauthorizedCall constraint!(ocp, :variable, [ 3, 0, 1 ]) + @test_throws UnauthorizedCall constraint!(ocp, :variable, [ 3, 0, 1 ], [ 3, 0, 1 ]) ocp = Model(variable=true) variable!(ocp, 1) @@ -59,13 +59,13 @@ end i == 7 && begin state!(ocp, 2); control!(ocp, 1) end # constraint! 1 - @test_throws UnauthorizedCall constraint!(ocp, :initial, 1:2:5, [ 0, 0, 0 ]) - @test_throws UnauthorizedCall constraint!(ocp, :initial, 2:3, [ 0, 0 ]) - @test_throws UnauthorizedCall constraint!(ocp, :final, Index(2), 0) + @test_throws UnauthorizedCall constraint!(ocp, :initial, 1:2:5, [ 0, 0, 0 ], [ 0, 0, 0 ]) + @test_throws UnauthorizedCall constraint!(ocp, :initial, 2:3, [ 0, 0 ], [ 0, 0 ]) + @test_throws UnauthorizedCall constraint!(ocp, :final, Index(2), 0, 0) # constraint! 2 - @test_throws UnauthorizedCall constraint!(ocp, :initial, [ 0, 0 ]) - @test_throws UnauthorizedCall constraint!(ocp, :final, 2) # if the state is of dimension 1 + @test_throws UnauthorizedCall constraint!(ocp, :initial, [ 0, 0 ], [ 0, 0 ]) + @test_throws UnauthorizedCall constraint!(ocp, :final, 2, 2) # if the state is of dimension 1 # constraint! 3 @test_throws UnauthorizedCall constraint!(ocp, :initial, 2:3, [ 0, 0 ], [ 1, 2 ]) @@ -109,30 +109,30 @@ end # constraint! 6 # variable independent ocp - @test_throws UnauthorizedCall constraint!(ocp, :boundary, (x0, xf) -> x0[3]+xf[2], 0) + @test_throws UnauthorizedCall constraint!(ocp, :boundary, (x0, xf) -> x0[3]+xf[2], 0, 0) # variable dependent ocp - @test_throws UnauthorizedCall constraint!(ocp, :boundary, (x0, xf, v) -> x0[3]+xf[2]*v[1], 0) + @test_throws UnauthorizedCall constraint!(ocp, :boundary, (x0, xf, v) -> x0[3]+xf[2]*v[1], 0, 0) # time independent and variable independent ocp - @test_throws UnauthorizedCall constraint!(ocp, :control, u -> 2u, 1) - @test_throws UnauthorizedCall constraint!(ocp, :state, x -> x-1, [ 0, 0, 0 ]) - @test_throws UnauthorizedCall constraint!(ocp, :mixed, (x, u) -> x[1]-u, 0) + @test_throws UnauthorizedCall constraint!(ocp, :control, u -> 2u, 1, 1) + @test_throws UnauthorizedCall constraint!(ocp, :state, x -> x-1, [ 0, 0, 0 ], [ 0, 0, 0 ]) + @test_throws UnauthorizedCall constraint!(ocp, :mixed, (x, u) -> x[1]-u, 0, 0) # time dependent and variable independent ocp - @test_throws UnauthorizedCall constraint!(ocp, :control, (t, u) -> 2u, 1) - @test_throws UnauthorizedCall constraint!(ocp, :state, (t, x) -> x-t, [ 0, 0, 0 ]) - @test_throws UnauthorizedCall constraint!(ocp, :mixed, (t, x, u) -> x[1]-u, 0) + @test_throws UnauthorizedCall constraint!(ocp, :control, (t, u) -> 2u, 1, 1) + @test_throws UnauthorizedCall constraint!(ocp, :state, (t, x) -> x-t, [ 0, 0, 0 ], [ 0, 0, 0 ]) + @test_throws UnauthorizedCall constraint!(ocp, :mixed, (t, x, u) -> x[1]-u, 0, 0) # time independent and variable dependent ocp - @test_throws UnauthorizedCall constraint!(ocp, :control, (u, v) -> 2u*v[1], 1) - @test_throws UnauthorizedCall constraint!(ocp, :state, (x, v) -> x-v[2], [ 0, 0, 0 ]) - @test_throws UnauthorizedCall constraint!(ocp, :mixed, (x, u) -> x[1]-u+v[1], 0) + @test_throws UnauthorizedCall constraint!(ocp, :control, (u, v) -> 2u*v[1], 1, 1) + @test_throws UnauthorizedCall constraint!(ocp, :state, (x, v) -> x-v[2], [ 0, 0, 0 ], [ 0, 0, 0 ]) + @test_throws UnauthorizedCall constraint!(ocp, :mixed, (x, u) -> x[1]-u+v[1], 0, 0) # time dependent and variable dependent ocp - @test_throws UnauthorizedCall constraint!(ocp, :control, (t, u, v) -> 2u-t*v[2], 1) - @test_throws UnauthorizedCall constraint!(ocp, :state, (t, x, v) -> x-t+v[1], [ 0, 0, 0 ]) - @test_throws UnauthorizedCall constraint!(ocp, :mixed, (t, x, u, v) -> x[1]-u*v[1], 0) + @test_throws UnauthorizedCall constraint!(ocp, :control, (t, u, v) -> 2u-t*v[2], 1, 1) + @test_throws UnauthorizedCall constraint!(ocp, :state, (t, x, v) -> x-t+v[1], [ 0, 0, 0 ], [ 0, 0, 0 ]) + @test_throws UnauthorizedCall constraint!(ocp, :mixed, (t, x, u, v) -> x[1]-u*v[1], 0, 0) end @@ -514,22 +514,22 @@ end @testset "constraint! 1" begin ocp = Model(); time!(ocp, 0, 1); state!(ocp, 1); control!(ocp, 1) - @test_throws IncorrectArgument constraint!(ocp, :initial, [0, 1], :c0) - constraint!(ocp, :initial, 0, :c0) - constraint!(ocp, :final, 1, :cf) + @test_throws IncorrectArgument constraint!(ocp, :initial, [0, 1], [0, 1], :c0) + constraint!(ocp, :initial, 0, 0, :c0) + constraint!(ocp, :final, 1, 1, :cf) @test constraint(ocp, :c0)(12, ∅) == 12 @test constraint(ocp, :cf)(∅, 12) == 12 ocp = Model(); time!(ocp, 0, 1); state!(ocp, 2); control!(ocp, 1) - constraint!(ocp, :initial, [0, 1], :c0) - constraint!(ocp, :final, [1, 2], :cf) + constraint!(ocp, :initial, [0, 1], [0, 1], :c0) + constraint!(ocp, :final, [1, 2], [1, 2], :cf) @test constraint(ocp, :c0)([12, 13], ∅) == [12, 13] @test constraint(ocp, :cf)(∅, [12, 13]) == [12, 13] # constraint already exists ocp = Model(); time!(ocp, 0, 1); state!(ocp, 1); control!(ocp, 1) - constraint!(ocp, :initial, 0, :c) - @test_throws UnauthorizedCall constraint!(ocp, :final, 0, :c) + constraint!(ocp, :initial, 0, 0, :c) + @test_throws UnauthorizedCall constraint!(ocp, :final, 0, 0, :c) end @@ -539,8 +539,8 @@ end x = 12 x0 = 0 xf = 1 - constraint!(ocp, :initial, Index(1), x0, :c0) - constraint!(ocp, :final, Index(1), xf, :cf) + constraint!(ocp, :initial, Index(1), x0, x0, :c0) + constraint!(ocp, :final, Index(1), xf, xf, :cf) @test constraint(ocp, :c0)(x, ∅) == x @test constraint(ocp, :cf)(∅, x) == x @@ -548,22 +548,22 @@ end x = [12, 13] x0 = [0, 1] xf = [1, 2] - @test_throws IncorrectArgument constraint!(ocp, :initial, Index(2), x0, :c0) - @test_throws IncorrectArgument constraint!(ocp, :final, Index(2), xf, :cf) + @test_throws IncorrectArgument constraint!(ocp, :initial, Index(2), x0, x0, :c0) + @test_throws IncorrectArgument constraint!(ocp, :final, Index(2), xf, xf, :cf) ocp = Model(); time!(ocp, 0, 1); state!(ocp, 2); control!(ocp, 1) x = [12, 13] x0 = [0, 1] xf = [1, 2] - constraint!(ocp, :initial, 1:2, x0, :c0) - constraint!(ocp, :final, 1:2, xf, :cf) + constraint!(ocp, :initial, 1:2, x0, x0, :c0) + constraint!(ocp, :final, 1:2, xf, xf, :cf) @test constraint(ocp, :c0)(x, ∅) == x[1:2] @test constraint(ocp, :cf)(∅, x) == x[1:2] # constraint already exists ocp = Model(); time!(ocp, 0, 1); state!(ocp, 2); control!(ocp, 1) - constraint!(ocp, :initial, Index(1), 0, :c) - @test_throws UnauthorizedCall constraint!(ocp, :final, Index(1), 0, :c) + constraint!(ocp, :initial, Index(1), 0, 0, :c) + @test_throws UnauthorizedCall constraint!(ocp, :final, Index(1), 0, 0, :c) end @@ -634,30 +634,30 @@ end @testset "constraint! 5" begin ocp = Model(); time!(ocp, 0, 1); state!(ocp, 1); control!(ocp, 1) - constraint!(ocp, :boundary, (x0, xf) -> x0+xf, 0, :cb) - constraint!(ocp, :control, u->u, 0, :cu) - constraint!(ocp, :state, x->x, 0, :cs) - constraint!(ocp, :mixed, (x,u)->x+u, 1, :cm) + constraint!(ocp, :boundary, (x0, xf) -> x0+xf, 0, 0, :cb) + constraint!(ocp, :control, u->u, 0, 0, :cu) + constraint!(ocp, :state, x->x, 0, 0, :cs) + constraint!(ocp, :mixed, (x,u)->x+u, 1, 1, :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 ocp = Model(); time!(ocp, 0, 1); state!(ocp, 2); control!(ocp, 2) - constraint!(ocp, :boundary, (x0, xf) -> x0[1]+xf[1], 0, :cb) - constraint!(ocp, :control, u->u[1], 0, :cu) - constraint!(ocp, :state, x->x[1], 0, :cs) - constraint!(ocp, :mixed, (x,u)->x[1]+u[1], 1, :cm) + constraint!(ocp, :boundary, (x0, xf) -> x0[1]+xf[1], 0, 0, :cb) + constraint!(ocp, :control, u->u[1], 0, 0, :cu) + constraint!(ocp, :state, x->x[1], 0, 0, :cs) + constraint!(ocp, :mixed, (x,u)->x[1]+u[1], 1, 1, :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 ocp = Model(); time!(ocp, 0, 1); state!(ocp, 3); control!(ocp, 3) - constraint!(ocp, :boundary, (x0, xf) -> [x0[1]+xf[1], x0[2]+xf[2]], [0, 0], :cb) - constraint!(ocp, :control, u->u[1:2], [0, 0], :cu) - constraint!(ocp, :state, x->x[1:2], [0, 0], :cs) - constraint!(ocp, :mixed, (x,u)->[x[1]+u[1], x[2]+u[2]], [0, 0], :cm) + constraint!(ocp, :boundary, (x0, xf) -> [x0[1]+xf[1], x0[2]+xf[2]], [0, 0], [0, 0], :cb) + constraint!(ocp, :control, u->u[1:2], [0, 0], [0, 0], :cu) + constraint!(ocp, :state, x->x[1:2], [0, 0], [0, 0], :cs) + constraint!(ocp, :mixed, (x,u)->[x[1]+u[1], x[2]+u[2]], [0, 0], [0, 0], :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] @@ -745,11 +745,11 @@ end constraint!(ocp, :control, (u, v) -> u + v[1], 0, 1, :cu) constraint!(ocp, :state, (x, v) -> x + v[1], 0, 1, :cs) constraint!(ocp, :mixed, (x, u, v) -> x + u + v[1], 1, 1, :cm) - constraint!(ocp, :variable, [ 0, 0, 0, 0 ], :eq1) - constraint!(ocp, :variable, Index(1), 0, :eq2) - constraint!(ocp, :variable, 1:2, [ 0, 0 ], :eq3) - constraint!(ocp, :variable, 1:2:4, [ 0, 0 ], :eq4) - constraint!(ocp, :variable, v -> v.^2, [ 0, 0, 0, 0 ], :eq5) + constraint!(ocp, :variable, [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], :eq1) + constraint!(ocp, :variable, Index(1), 0, 0, :eq2) + constraint!(ocp, :variable, 1:2, [ 0, 0 ], [ 0, 0 ], :eq3) + constraint!(ocp, :variable, 1:2:4, [ 0, 0 ], [ 0, 0 ], :eq4) + constraint!(ocp, :variable, v -> v.^2, [ 0, 0, 0, 0 ], [ 0, 0, 0, 0], :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] @@ -798,33 +798,34 @@ end ocp = Model(variable=true); time!(ocp, 0, 1); state!(ocp, 1); control!(ocp, 1); variable!(ocp,3) constraint!(ocp, :state, 0, 1, :c0) - constraint!(ocp, :control, dummy, 1, :c1) + constraint!(ocp, :control, dummy, 1, 1, :c1) constraint!(ocp, :variable, 1:2:3, [-Inf,-Inf], [0,0], :c2) ocp_bis = Model(variable=true); time!(ocp_bis, 0, 1); state!(ocp_bis, 1); control!(ocp_bis, 1); variable!(ocp_bis,3) constraint!(ocp_bis, :state, lb=0, ub=1, label=:c0) - constraint!(ocp_bis, :control, f=dummy, val=1, label=:c1) + constraint!(ocp_bis, :control, f=dummy, ub=1, lb=1, label=:c1) constraint!(ocp_bis, :variable, rg=1:2:3, ub=[0,0], label=:c2) @test ocp.constraints == ocp_bis.constraints ocp_ter = Model(variable=true); time!(ocp_ter, 0, 1); state!(ocp_ter, 3); control!(ocp_ter, 1); variable!(ocp_ter,1) - constraint!(ocp_ter, :variable, 1, :c0) + constraint!(ocp_ter, :variable, 1, 1, :c0) constraint!(ocp_ter, :control, dummy, 1, Inf, :c1) - constraint!(ocp_ter, :state, 1:2:3, [0,0], :c2) + constraint!(ocp_ter, :state, 1:2:3, [0,0], [0,0], :c2) ocp_quad = Model(variable=true); time!(ocp_quad, 0, 1); state!(ocp_quad, 3); control!(ocp_quad, 1); variable!(ocp_quad,1) - constraint!(ocp_quad, :variable, val=1, label=:c0) + constraint!(ocp_quad, :variable, lb=1, ub=1, label=:c0) constraint!(ocp_quad, :control, f=dummy, lb=1, label=:c1) - constraint!(ocp_quad, :state, rg=1:2:3, val=[0,0], label=:c2) + constraint!(ocp_quad, :state, rg=1:2:3, lb=[0,0],ub=[0,0], label=:c2) @test ocp_ter.constraints == ocp_quad.constraints ocp_error = ocp_error = Model(variable=true); time!(ocp_error, 0, 1); state!(ocp_error, 3); control!(ocp_error, 1); variable!(ocp_error,1) @test_throws IncorrectArgument constraint!(ocp_error, :variable) - @test_throws IncorrectArgument constraint!(ocp_error, :control, f=dummy, val=1, lb=1, label=:c1) - @test_throws IncorrectArgument constraint!(ocp_error, :state, rg=1:2:3, f=dummy, val=[0,0], label=:c2) - + @test_throws IncorrectArgument constraint!(ocp_error, :control, f=dummy, label=:c1) + @test_throws IncorrectArgument constraint!(ocp_error, :state, rg=1:2:3, label=:c2) + @test_throws IncorrectArgument constraint!(ocp_error, :state, rg=1:2:3, f=dummy, lb=[0,0], ub=[0,0], label=:c3) + @test_throws IncorrectArgument constraint!(ocp_error, :state, f=dummy, rg=1:2:3, lb=[0,0], ub=[0,0], label=:c4) end @testset "remove_constraint! and constraints_labels" begin @@ -845,8 +846,8 @@ end @testset "nlp_constraints without variable" begin ocp = Model(); time!(ocp, 0, 1); state!(ocp, 2); control!(ocp, 1) - constraint!(ocp, :initial, Index(2), 10, :ci) - constraint!(ocp, :final, Index(1), 1, :cf) + constraint!(ocp, :initial, Index(2), 10, 10, :ci) + constraint!(ocp, :final, Index(1), 1, 1, :cf) constraint!(ocp, :control, 0, 1, :cu) constraint!(ocp, :state, [0, 1], [1, 2], :cs) constraint!(ocp, :boundary, (x0, xf) -> x0[2]+xf[2], 0, 1, :cb) @@ -904,8 +905,8 @@ end variable!(ocp, 4) state!(ocp, 2) control!(ocp, 1) - constraint!(ocp, :initial, Index(2), 10, :ci) - constraint!(ocp, :final, Index(1), 1, :cf) + constraint!(ocp, :initial, Index(2), 10, 10, :ci) + constraint!(ocp, :final, Index(1), 1, 1, :cf) constraint!(ocp, :control, 0, 1, :cu) constraint!(ocp, :state, [0, 1], [1, 2], :cs) constraint!(ocp, :boundary, (x0, xf, v) -> x0[2]+xf[2]+v[1], 0, 1, :cb) diff --git a/test/test_print.jl b/test/test_print.jl index da7f9adb..82cb22b4 100644 --- a/test/test_print.jl +++ b/test/test_print.jl @@ -8,8 +8,8 @@ function test_print() state!(ocp, 2, "state", ["r", "v"]) # dimension of the state with the names of the components control!(ocp, 1) # dimension of the control time!(ocp, 0, 1, "s") # initial and final time, with the name of the variable time - constraint!(ocp, :initial, [-1, 0]) - constraint!(ocp, :final , [ 0, 0]) + constraint!(ocp, :initial, [-1, 0], [-1, 0]) + constraint!(ocp, :final , [ 0, 0], [0, 0]) A = [ 0 1 0 0 ] B = [ 0 @@ -28,8 +28,8 @@ function test_print() state!(ocp, 1, "y") # dimension of the state with the names of the components control!(ocp, 1, "v") # dimension of the control time!(ocp, 0, 1, "s") # initial and final time, with the name of the variable time - constraint!(ocp, :initial, -1) - constraint!(ocp, :final , 0) + constraint!(ocp, :initial, -1, -1) + constraint!(ocp, :final , 0, 0) dynamics!(ocp, (t, x, u) -> x+u) constraint!(ocp, :state, (t, x) -> x, 0, 1) constraint!(ocp, :control, (t, u) -> u, -1, 1) @@ -45,8 +45,8 @@ function test_print() state!(ocp, 1, "y") # dimension of the state with the names of the components control!(ocp, 2) # dimension of the control time!(ocp, 0, Index(1), "s") # initial and final time, with the name of the variable time - constraint!(ocp, :initial, -1) - constraint!(ocp, :final , 0) + constraint!(ocp, :initial, -1, -1) + constraint!(ocp, :final , 0, 0) dynamics!(ocp, (t, x, u) -> x+u) objective!(ocp, :mayer, (t0, x0, tf, xf) -> tf) @test display(ocp) isa Nothing