Skip to content

Commit b866d16

Browse files
authored
Merge pull request #98 from control-toolbox/96-general-bug-constraint
96 general bug constraint
2 parents 9a4f396 + 62a23de commit b866d16

7 files changed

Lines changed: 145 additions & 19 deletions

File tree

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "CTModels"
22
uuid = "34c4fa32-2049-4079-8329-de33c2a22e2d"
33
authors = ["Olivier Cots <olivier.cots@toulouse-inp.fr>"]
4-
version = "0.3.2"
4+
version = "0.3.3"
55

66
[deps]
77
CTBase = "54762871-cc72-4466-b8e8-f6c8b58076cd"

src/constraints.jl

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,3 +337,92 @@ Return the dimension of variable box constraints.
337337
function dim_variable_constraints_box(model::ConstraintsModel)::Dimension
338338
return length(variable_constraints_box(model)[1])
339339
end
340+
341+
# ------------------------------------------------------------------------------ #
342+
"""
343+
$(TYPEDSIGNATURES)
344+
345+
Get a labelled constraint from the model.
346+
"""
347+
function constraint(model::Model, label::Symbol)::Function # not type stable
348+
349+
# check if the label is in the path constraints
350+
cp = path_constraints_nl(model)
351+
labels = cp[4] # vector of labels
352+
if label in labels
353+
# get all the indices of the label
354+
indices = findall(x -> x == label, labels)
355+
fc! = (r, t, x, u, v) -> begin
356+
r_ = zeros(length(cp[1]))
357+
cp[2](r_, t, x, u, v)
358+
r .= r_[indices]
359+
end
360+
return to_out_of_place(fc!, length(indices))
361+
end
362+
363+
# check if the label is in the boundary constraints
364+
cp = boundary_constraints_nl(model)
365+
labels = cp[4] # vector of labels
366+
if label in labels
367+
# get all the indices of the label
368+
indices = findall(x -> x == label, labels)
369+
fc! = (r, x0, xf, v) -> begin
370+
r_ = zeros(length(cp[1]))
371+
cp[2](r_, x0, xf, v)
372+
r .= r_[indices]
373+
end
374+
return to_out_of_place(fc!, length(indices))
375+
end
376+
377+
# check if the label is in the state constraints
378+
cp = state_constraints_box(model)
379+
labels = cp[4] # vector of labels
380+
if label in labels
381+
# get all the indices of the label
382+
indices = Int[]
383+
for i in eachindex(labels)
384+
if labels[i] == label
385+
push!(indices, cp[2][i])
386+
end
387+
end
388+
fc = (t, x, u, v) -> begin
389+
length(indices) == 1 ? x[indices[1]] : x[indices]
390+
end
391+
return fc
392+
end
393+
394+
# check if the label is in the control constraints
395+
cp = control_constraints_box(model)
396+
labels = cp[4] # vector of labels
397+
if label in labels
398+
# get all the indices of the label
399+
indices = Int[]
400+
for i in eachindex(labels)
401+
if labels[i] == label
402+
push!(indices, cp[2][i])
403+
end
404+
end
405+
fc = (t, x, u, v) -> begin
406+
length(indices) == 1 ? u[indices[1]] : u[indices]
407+
end
408+
return fc
409+
end
410+
411+
# check if the label is in the variable constraints
412+
cp = variable_constraints_box(model)
413+
labels = cp[4] # vector of labels
414+
if label in labels
415+
# get all the indices of the label
416+
indices = Int[]
417+
for i in eachindex(labels)
418+
if labels[i] == label
419+
push!(indices, cp[2][i])
420+
end
421+
end
422+
fc = (t, x, u, v) -> begin
423+
length(indices) == 1 ? v[indices[1]] : v[indices]
424+
end
425+
return fc
426+
end
427+
428+
end

src/model.jl

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -741,15 +741,6 @@ end
741741
"""
742742
$(TYPEDSIGNATURES)
743743
744-
Get a labelled constraint from the model.
745-
"""
746-
function constraint(ocp::Model, label::Symbol)::Tuple # not type stable
747-
return constraints(ocp).dict[label]
748-
end
749-
750-
"""
751-
$(TYPEDSIGNATURES)
752-
753744
Get the nonlinear path constraints from the model.
754745
"""
755746
function path_constraints_nl(

src/utils.jl

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,19 @@ function matrix2vec(
1919
)::Vector{<:Vector{<:ctNumber}}
2020
return dim==1 ? [A[i, :] for i in 1:size(A, 1)] : [A[:, i] for i in 1:size(A, 2)]
2121
end
22+
23+
"""
24+
$(TYPEDSIGNATURES)
25+
26+
Transform an in-place function `f!` to an out-of-place function `f`.
27+
The function `f` will return a vector of the same type as `T` and size `n`.
28+
"""
29+
function to_out_of_place(f!, n; T=Float64)
30+
function f(args...; kwargs...)
31+
r = zeros(T, n)
32+
f!(r, args...; kwargs...)
33+
return n == 1 ? r[1] : r
34+
#return r # everything is now a vector
35+
end
36+
return isnothing(f!) ? nothing : f
37+
end

test/solution_test.jld2

0 Bytes
Binary file not shown.

test/test_constraints.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,4 +131,5 @@ function test_constraints()
131131
# test with :variable constraint and range
132132
CTModels.constraint!(ocp_set, :variable; rg=1:1, lb=[1], ub=[1], label=:variable_rg)
133133
@test ocp_set.constraints[:variable_rg] == (:variable, 1:1, [1], [1])
134+
134135
end

test/test_model.jl

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,23 +57,51 @@ function test_model()
5757
# set some constraints
5858
f_path(r, t, x, u, v) = r .= x .+ u .+ v .+ t
5959
f_boundary(r, x0, xf, v) = r .= x0 .+ v .* (xf .- x0)
60-
f_variable(r, t, v) = r .= v .+ t
60+
6161
CTModels.constraint!(pre_ocp, :path; f=f_path, lb=[0, 1], ub=[1, 2], label=:path)
62-
CTModels.constraint!(
63-
pre_ocp, :boundary; f=f_boundary, lb=[0, 1], ub=[1, 2], label=:boundary
64-
)
65-
CTModels.constraint!(pre_ocp, :state; rg=1:2, lb=[0, 1], ub=[1, 2], label=:state_rg)
66-
CTModels.constraint!(pre_ocp, :control; rg=1:2, lb=[0, 1], ub=[1, 2], label=:control_rg)
67-
CTModels.constraint!(
68-
pre_ocp, :variable; rg=1:2, lb=[0, 1], ub=[1, 2], label=:variable_rg
69-
)
62+
CTModels.constraint!(pre_ocp, :boundary; f=f_boundary, lb=[0, 1], ub=[1, 2], label=:boundary)
63+
CTModels.constraint!(pre_ocp, :state; rg=1:2, lb=[0, 1], ub=[1, 2], label=:state)
64+
CTModels.constraint!(pre_ocp, :control; rg=1:2, lb=[0, 1], ub=[1, 2], label=:control)
65+
CTModels.constraint!(pre_ocp, :variable; rg=1:2, lb=[0, 1], ub=[1, 2], label=:variable)
66+
67+
f_path_scalar(r, t, x, u, v) = r .= x[1] + u[1] + v[1] + t
68+
f_boundary_scalar(r, x0, xf, v) = r .= x0[1] + v[1] * (xf[1] - x0[1])
69+
CTModels.constraint!(pre_ocp, :path; f=f_path_scalar, lb=0, ub=1, label=:path_scalar)
70+
CTModels.constraint!(pre_ocp, :boundary; f=f_boundary_scalar, lb=0, ub=1, label=:boundary_scalar)
71+
CTModels.constraint!(pre_ocp, :state; rg=1, lb=0, ub=1, label=:state_scalar)
72+
CTModels.constraint!(pre_ocp, :control; rg=1, lb=0, ub=1, label=:control_scalar)
73+
CTModels.constraint!(pre_ocp, :variable; rg=1, lb=0, ub=1, label=:variable_scalar)
74+
CTModels.constraint!(pre_ocp, :state; rg=2, lb=0, ub=1, label=:state_scalar_2)
75+
CTModels.constraint!(pre_ocp, :control; rg=2, lb=0, ub=1, label=:control_scalar_2)
76+
CTModels.constraint!(pre_ocp, :variable; rg=2, lb=0, ub=1, label=:variable_scalar_2)
7077

7178
# build the model
7279
model = CTModels.build_model(pre_ocp)
7380

7481
# check the type of the model
7582
@test model isa CTModels.Model
7683

84+
# check retrieved constraints
85+
t = 1
86+
x = [2, 3]
87+
u = [4, 5]
88+
v = [6, 7]
89+
x0 = [1, 2]
90+
xf = [3, 4]
91+
@test CTModels.constraint(model, :path)(t, x, u, v) == x .+ u .+ v .+ t
92+
@test CTModels.constraint(model, :boundary)(x0, xf, v) == x0 .+ v .* (xf .- x0)
93+
@test CTModels.constraint(model, :state)(t, x, u, v) == x
94+
@test CTModels.constraint(model, :control)(t, x, u, v) == u
95+
@test CTModels.constraint(model, :variable)(t, x, u, v) == v
96+
@test CTModels.constraint(model, :path_scalar)(t, x, u, v) == x[1] + u[1] + v[1] + t
97+
@test CTModels.constraint(model, :boundary_scalar)(x0, xf, v) == x0[1] + v[1] * (xf[1] - x0[1])
98+
@test CTModels.constraint(model, :state_scalar)(t, x, u, v) == x[1]
99+
@test CTModels.constraint(model, :control_scalar)(t, x, u, v) == u[1]
100+
@test CTModels.constraint(model, :variable_scalar)(t, x, u, v) == v[1]
101+
@test CTModels.constraint(model, :state_scalar_2)(t, x, u, v) == x[2]
102+
@test CTModels.constraint(model, :control_scalar_2)(t, x, u, v) == u[2]
103+
@test CTModels.constraint(model, :variable_scalar_2)(t, x, u, v) == v[2]
104+
77105
# print the premodel
78106
display(pre_ocp)
79107

@@ -100,4 +128,5 @@ function test_model()
100128
CTModels.objective!(pre_ocp, :min; mayer=mayer, lagrange=lagrange)
101129
CTModels.definition!(pre_ocp, quote end)
102130
display(pre_ocp)
131+
103132
end

0 commit comments

Comments
 (0)