Skip to content

Commit e6a50fb

Browse files
committed
simplified boundary functions
1 parent 0be8c04 commit e6a50fb

11 files changed

+201
-172
lines changed

docs/Project.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
[deps]
22
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
3+
DocumenterInterLinks = "d12716ef-a0f6-4df4-a9f1-a5a34e75c656"
34
DynOptInterface = "6c38235a-427b-4736-80fa-cf75909744ec"

docs/src/reference/abstractions.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ The following are sub-types of [`AbstractDynamicFunction`](@ref):
1515
* ``t_i \mapsto \dot{y}_j(t_i) - a(y(t_i), t_i, x)`` [`ExplicitDifferentialFunction`](@ref)
1616
* ``t_i \mapsto r(\dot{y}(t_i), y(t_i), t_i, x)`` [`NonlinearDifferentialFunction`](@ref)
1717
* [`AbstractBoundaryFunction`](@ref)
18-
* ``t_i^0, t_i^f`` [`DomainInitial`](@ref), [`DomainFinal`](@ref)
19-
* ``y_j(t_i^0), y_j(t_i^f)`` [`DynamicVariableInitial`](@ref), [`DynamicVariableFinal`](@ref)
18+
* ``a(y(t_i^0), t_i^0, x)`` [`Initial`](@ref)
19+
* ``a(y(t_i^f), t_i^f, x)`` [`Final`](@ref)
2020
* ``b(y(t^0), y(t^f), t^0, t^f, x)`` [`NonlinearBoundaryFunction`](@ref)
2121
* ``\int_{t_i^0}^{t_i^f} a(y(t_i), t_i, x) \mathrm{d}t_i`` [`IntegralFunction`](@ref)
2222
* ``b(y(t_i^0), y(t_i^f), t_i^0, t_i^f, x) + \int_{t_i^0}^{t_i^f} a(y(t_i), t_i, x) \mathrm{d}t_i`` [`BolzaFunction`](@ref)

docs/src/reference/boundary_functions.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@ CurrentModule = DynOptInterface
55
# Boundary Functions
66

77
```@docs
8-
DomainInitial
9-
DomainFinal
10-
DynamicVariableInitial
11-
DynamicVariableFinal
8+
Initial
9+
Final
1210
NonlinearBoundaryFunction
1311
```

src/DynOptInterface.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ include("algebraic_functions.jl")
99
include("differential_functions.jl")
1010
include("boundary_functions.jl")
1111
include("integral_functions.jl")
12-
include("print.jl")
1312

1413

1514
end

src/algebraic_functions.jl

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,56 @@ Each node in `args` can be one of the following:
1414
* Another [`NonlinearAlgebraicFunction`](@ref)
1515
"""
1616
struct NonlinearAlgebraicFunction <: AbstractAlgebraicFunction
17-
domain::DomainIndex
1817
head::Symbol
1918
args::Vector{Any}
19+
t_i::DomainIndex
2020

21-
#=function NonlinearAlgebraicFunction(head::Symbol, args::AbstractVector)
21+
function NonlinearAlgebraicFunction(head::Symbol, args::AbstractVector, t_i::DomainIndex)
22+
for arg in args
23+
if arg isa Real || arg isa MOI.VariableIndex
24+
continue
25+
elseif arg isa DomainIndex
26+
arg.value == t_i.value ? continue : error("Different domains not allowed.")
2227

23-
# Check that all dynamic functions share the same domain index
28+
elseif arg isa DynamicVariableIndex || arg isa NonlinearAlgebraicFunction
29+
arg.t_i.value == t_i.value ? continue : error("Different domains not allowed.")
2430

25-
return new(head, convert(Vector{Any}, args))
26-
end=#
31+
else
32+
error("Unsupported object: $arg")
33+
end
34+
end
35+
return new(head, convert(Vector{Any}, args), t_i)
36+
end
37+
end
38+
39+
function _nonlinear_to_string(options::MOI.Utilities._PrintOptions, model::MOI.ModelLike,
40+
nlf::NLF,
41+
) where {NLF}
42+
io, stack, is_open = IOBuffer(), Any[nlf], true
43+
while !isempty(stack)
44+
arg = pop!(stack)
45+
if !is_open && arg != ')'
46+
print(io, ", ")
47+
end
48+
if arg isa NLF
49+
print(io, arg.head, "(")
50+
push!(stack, ')')
51+
for i in length(arg.args):-1:1
52+
push!(stack, arg.args[i])
53+
end
54+
elseif arg isa Char
55+
print(io, arg)
56+
else
57+
print(io, MOI.Utilities._to_string(options, model, arg))
58+
end
59+
is_open = arg isa NLF
60+
end
61+
seekstart(io)
62+
return read(io, String)
63+
end
64+
65+
function MOI.Utilities._to_string(options::MOI.Utilities._PrintOptions, model::MOI.ModelLike,
66+
naf::NonlinearAlgebraicFunction,
67+
)
68+
return _nonlinear_to_string(options, model, naf)
2769
end

src/boundary_functions.jl

Lines changed: 62 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,95 @@
11
"""
2-
DomainInitial <: AbstractBoundaryFunction
2+
Initial{AF<:AbstractAlgebraicFunction} <: AbstractBoundaryFunction
33
44
```math
5-
t_i^0
5+
a(y(t_i^0), t_i^0, x)
66
```
7-
Represents the initial point of a [`DomainIndex`](@ref).
7+
Represents the evaluation of an [`AbstractAlgebraicFunction`](@ref) at the initial
8+
point of its domain. Common cases are:
9+
* ``t_i^0`` `Initial{DomainIndex}`
10+
* ``y_j(t_i^0)`` `Initial{DynamicVariableIndex}`
811
"""
9-
struct DomainInitial <: AbstractBoundaryFunction
10-
index::DomainIndex
12+
struct Initial{AF<:AbstractAlgebraicFunction} <: AbstractBoundaryFunction
13+
evaluand::AF
1114
end
1215

13-
"""
14-
DomainFinal <: AbstractBoundaryFunction
15-
16-
```math
17-
t_i^f
18-
```
19-
Represents the final point of a [`DomainIndex`](@ref).
20-
"""
21-
struct DomainFinal <: AbstractBoundaryFunction
22-
index::DomainIndex
16+
function MOI.Utilities._to_string(options::MOI.Utilities._PrintOptions, model::MOI.ModelLike,
17+
initial::Initial,
18+
)
19+
return string(
20+
"Initial(",
21+
MOI.Utilities._to_string(options, model, initial.evaluand),
22+
")",
23+
)
2324
end
2425

2526
"""
26-
DynamicVariableInitial <: AbstractBoundaryFunction
27+
Final{AF<:AbstractAlgebraicFunction} <: AbstractBoundaryFunction
2728
2829
```math
29-
y_j(t_i^0)
30-
```
31-
Represents a [`DynamicVariableIndex`](@ref) evaluated at the initial point of its [`DomainIndex`](@ref)
30+
a(y(t_i^f), t_i^f, x)
31+
```
32+
Represents the evaluation of an [`AbstractAlgebraicFunction`](@ref) at the final
33+
point of its domain. Common cases are:
34+
* ``t_i^f`` `Final{DomainIndex}`
35+
* ``y_j(t_i^f)`` `Final{DynamicVariableIndex}`
3236
"""
33-
struct DynamicVariableInitial <: AbstractBoundaryFunction
34-
variable_index::DynamicVariableIndex
37+
struct Final{AF<:AbstractAlgebraicFunction} <: AbstractBoundaryFunction
38+
evaluand::AF
3539
end
3640

37-
"""
38-
DynamicVariableFinal <: AbstractBoundaryFunction
39-
40-
```math
41-
y_j(t_i^f)
42-
```
43-
Represents a [`DynamicVariableIndex`](@ref) evaluated at the final point of its [`DomainIndex`](@ref)
44-
"""
45-
struct DynamicVariableFinal <: AbstractBoundaryFunction
46-
variable_index::DynamicVariableIndex
41+
function MOI.Utilities._to_string(options::MOI.Utilities._PrintOptions, model::MOI.ModelLike,
42+
final::Final,
43+
)
44+
return string(
45+
"Final(",
46+
MOI.Utilities._to_string(options, model, final.evaluand),
47+
")",
48+
)
4749
end
4850

51+
const _NONLINEAR_BOUNDARY_TYPES = Union{
52+
Real,
53+
MOI.VariableIndex,
54+
Initial{DomainIndex},
55+
Final{DomainIndex},
56+
Initial{DynamicVariableIndex},
57+
Final{DynamicVariableIndex},
58+
}
59+
4960
"""
5061
NonlinearBoundaryFunction <: AbstractBoundaryFunction
5162
5263
```math
53-
b(y_j(t^0), y_j(t^f), t^0, t^f, x)
64+
b(y(t^0), y(t^f), t^0, t^f, x)
5465
```
5566
Similar to [`MathOptInterface.ScalarNonlinearFunction`](@extref),
5667
5768
Each node in `args` can be one of the following:
5869
* A constant value of type `T<:Real`
5970
* A [`MathOptInterface.VariableIndex`](@extref)
60-
* A [`DomainInitial`](@ref)
61-
* A [`DomainFinal`](@ref)
62-
* A [`DynamicVariableInitial`](@ref)
63-
* A [`DynamicVariableFinal`](@ref)
71+
* An `Initial{DomainIndex}`
72+
* A `Final{DomainIndex}`
73+
* An `Initial{DynamicVariableIndex}`
74+
* A `Final{DynamicVariableIndex}`
6475
* Another [`NonlinearBoundaryFunction`](@ref)
6576
"""
6677
struct NonlinearBoundaryFunction <: AbstractBoundaryFunction
6778
head::Symbol
6879
args::Vector{Any}
69-
# Inner constructor to enforce rules
80+
81+
function NonlinearBoundaryFunction(head::Symbol, args::AbstractVector)
82+
for arg in args
83+
if !(arg isa _NONLINEAR_BOUNDARY_TYPES)
84+
error("Unsupported object: $arg")
85+
end
86+
end
87+
return new(head, convert(Vector{Any}, args), t_i)
88+
end
89+
end
90+
91+
function MOI.Utilities._to_string(options::MOI.Utilities._PrintOptions, model::MOI.ModelLike,
92+
nbf::NonlinearBoundaryFunction,
93+
)
94+
return _nonlinear_to_string(options, model, nbf)
7095
end

src/differential_functions.jl

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,13 @@ t_i \\mapsto \\dot{y}_j(t_i)
77
A derivative
88
"""
99
struct DynamicVariableDerivative <: AbstractDifferentialFunction
10-
variable_index::DynamicVariableIndex
10+
y_j::DynamicVariableIndex
11+
end
12+
13+
function MOI.Utilities._to_string(::MOI.Utilities._PrintOptions, ::MOI.ModelLike,
14+
derivative::DynamicVariableDerivative,
15+
)
16+
return string("ẏ[", derivative.y_j.value, "]")
1117
end
1218

1319
"""
@@ -22,6 +28,17 @@ struct ExplicitDifferentialFunction{AF<:AbstractAlgebraicFunction} <: AbstractDi
2228
algebraic_function::AF
2329
end
2430

31+
function MOI.Utilities._to_string(options::MOI.Utilities._PrintOptions, model::MOI.ModelLike,
32+
edf::ExplicitDifferentialFunction,
33+
)
34+
return string(
35+
MOI.Utilities._to_string(options, model, edf.derivative),
36+
" - (",
37+
MOI.Utilities._to_string(options, model, edf.algebraic_function),
38+
")",
39+
)
40+
end
41+
2542
"""
2643
NonlinearDifferentialFunction <: AbstractDifferentialFunction
2744
@@ -39,8 +56,33 @@ Each node in `args` can be one of the following:
3956
* Another [`NonlinearDifferentialFunction`](@ref)
4057
"""
4158
struct NonlinearDifferentialFunction <: AbstractDifferentialFunction
42-
domain::DomainIndex
4359
head::Symbol
4460
args::Vector{Any}
45-
# Inner constructor to enforce rules
61+
t_i::DomainIndex
62+
63+
function NonlinearDifferentialFunction(head::Symbol, args::AbstractVector, t_i::DomainIndex)
64+
for arg in args
65+
if arg isa Real || arg isa MOI.VariableIndex
66+
continue
67+
elseif arg isa DomainIndex
68+
arg.value == t_i.value ? continue : error("Different domains not allowed.")
69+
70+
elseif arg isa DynamicVariableIndex || arg isa NonlinearDifferentialFunction
71+
arg.t_i.value == t_i.value ? continue : error("Different domains not allowed.")
72+
73+
elseif arg isa DynamicVariableDerivative
74+
arg.y_j.t_i.value == t_i.value ? continue : error("Different domains not allowed.")
75+
76+
else
77+
error("Unsupported object: $arg")
78+
end
79+
end
80+
return new(head, convert(Vector{Any}, args), t_i)
81+
end
82+
end
83+
84+
function MOI.Utilities._to_string(options::MOI.Utilities._PrintOptions, model::MOI.ModelLike,
85+
ndf::NonlinearDifferentialFunction,
86+
)
87+
return _nonlinear_to_string(options, model, ndf)
4688
end

src/domains.jl

Lines changed: 10 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
"""
2-
DomainIndex <: AbstractDynamicFunction
2+
DomainIndex <: AbstractAlgebraicFunction
33
44
```math
55
t_i
66
```
77
A type-safe wrapper for `Int64` for use in referencing domains.
88
"""
9-
struct DomainIndex <: AbstractDynamicFunction
9+
struct DomainIndex <: AbstractAlgebraicFunction
1010
value::Int64
1111
end
1212

13+
function MOI.Utilities._to_string(::MOI.Utilities._PrintOptions, ::MOI.ModelLike,
14+
t_i::DomainIndex
15+
)
16+
return string("t[", t_i.value, "]")
17+
end
18+
1319
"""
1420
supports_domain(model::MOI.ModelLike)
1521
@@ -42,33 +48,8 @@ MOI.operation_name(::AddDomainNotAllowed) = "Adding a domain"
4248
"""
4349
add_domain(model::MOI.ModelLike)
4450
45-
Add a domain to the model, returning a [`DomainIndex`](@ref). An
51+
Add a domain to `model`, returning a [`DomainIndex`](@ref). An
4652
[`AddDomainNotAllowed`](@ref) is thrown if a domain cannot be added
4753
to the `model` in its current state.
4854
"""
49-
add_domain(::MOI.ModelLike) = throw(AddDomainNotAllowed(""))
50-
51-
#=
52-
53-
54-
# Parameters
55-
@parameter(model, t_0)
56-
57-
# Design Variables
58-
@variable(model, 1.0 ≤ t_f ≤ 2.0)
59-
60-
# Time Domains
61-
@domain(model, t ∈ [0.0, t_f])
62-
add_domain()::Tuple{DomainIndex, ConstraintIndex, ConstraintIndex}
63-
# start(t) ∈ EqualTo
64-
# final(t) ∈ Interval
65-
66-
# Algebraic Variables
67-
@algebraic(model, u(t))
68-
add_algebraic()::AlgebraicVariableIndex()
69-
70-
# Differential Variable
71-
@differential(model, y(t))
72-
add_differential()::DynamicVariableIndex()
73-
74-
=#
55+
add_domain(::MOI.ModelLike) = throw(AddDomainNotAllowed(""))

src/dynamic_variables.jl

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,13 @@ A type-safe wrapper for `Int64` for use in referencing dynamic variables.
88
"""
99
struct DynamicVariableIndex <: AbstractAlgebraicFunction
1010
value::Int64
11-
domain::DomainIndex
11+
t_i::DomainIndex
12+
end
13+
14+
function MOI.Utilities._to_string(::MOI.Utilities._PrintOptions, ::MOI.ModelLike,
15+
y_j::DynamicVariableIndex
16+
)
17+
return string("y[", y_j.value, "]")
1218
end
1319

1420
"""
@@ -41,8 +47,10 @@ end
4147
MOI.operation_name(::AddDynamicVariableNotAllowed) = "Adding a dynamic variable"
4248

4349
"""
44-
add_dynamic_variable(::MOI.ModelLike)
50+
add_dynamic_variable(model::MOI.ModelLike)
4551
46-
Add
52+
Add a dynamic variable to `model`, returning a [`DynamicVariableIndex`](@ref). An
53+
[`AddDynamicVariableNotAllowed`](@ref) is thrown if a dynamic variable cannot be added
54+
to `model` in its current state.
4755
"""
4856
add_dynamic_variable(::MOI.ModelLike) = throw(AddDynamicVariableNotAllowed(""))

0 commit comments

Comments
 (0)