Skip to content

Commit

Permalink
simplified boundary functions
Browse files Browse the repository at this point in the history
  • Loading branch information
e-duar-do committed May 31, 2024
1 parent 0be8c04 commit e6a50fb
Show file tree
Hide file tree
Showing 11 changed files with 201 additions and 172 deletions.
1 change: 1 addition & 0 deletions docs/Project.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
[deps]
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
DocumenterInterLinks = "d12716ef-a0f6-4df4-a9f1-a5a34e75c656"
DynOptInterface = "6c38235a-427b-4736-80fa-cf75909744ec"
4 changes: 2 additions & 2 deletions docs/src/reference/abstractions.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ The following are sub-types of [`AbstractDynamicFunction`](@ref):
* ``t_i \mapsto \dot{y}_j(t_i) - a(y(t_i), t_i, x)`` [`ExplicitDifferentialFunction`](@ref)
* ``t_i \mapsto r(\dot{y}(t_i), y(t_i), t_i, x)`` [`NonlinearDifferentialFunction`](@ref)
* [`AbstractBoundaryFunction`](@ref)
* ``t_i^0, t_i^f`` [`DomainInitial`](@ref), [`DomainFinal`](@ref)
* ``y_j(t_i^0), y_j(t_i^f)`` [`DynamicVariableInitial`](@ref), [`DynamicVariableFinal`](@ref)
* ``a(y(t_i^0), t_i^0, x)`` [`Initial`](@ref)
* ``a(y(t_i^f), t_i^f, x)`` [`Final`](@ref)
* ``b(y(t^0), y(t^f), t^0, t^f, x)`` [`NonlinearBoundaryFunction`](@ref)
* ``\int_{t_i^0}^{t_i^f} a(y(t_i), t_i, x) \mathrm{d}t_i`` [`IntegralFunction`](@ref)
* ``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)
Expand Down
6 changes: 2 additions & 4 deletions docs/src/reference/boundary_functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ CurrentModule = DynOptInterface
# Boundary Functions

```@docs
DomainInitial
DomainFinal
DynamicVariableInitial
DynamicVariableFinal
Initial
Final
NonlinearBoundaryFunction
```
1 change: 0 additions & 1 deletion src/DynOptInterface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ include("algebraic_functions.jl")
include("differential_functions.jl")
include("boundary_functions.jl")
include("integral_functions.jl")
include("print.jl")


end
52 changes: 47 additions & 5 deletions src/algebraic_functions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,56 @@ Each node in `args` can be one of the following:
* Another [`NonlinearAlgebraicFunction`](@ref)
"""
struct NonlinearAlgebraicFunction <: AbstractAlgebraicFunction
domain::DomainIndex
head::Symbol
args::Vector{Any}
t_i::DomainIndex

#=function NonlinearAlgebraicFunction(head::Symbol, args::AbstractVector)
function NonlinearAlgebraicFunction(head::Symbol, args::AbstractVector, t_i::DomainIndex)
for arg in args
if arg isa Real || arg isa MOI.VariableIndex
continue
elseif arg isa DomainIndex
arg.value == t_i.value ? continue : error("Different domains not allowed.")

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

return new(head, convert(Vector{Any}, args))
end=#
else
error("Unsupported object: $arg")
end
end
return new(head, convert(Vector{Any}, args), t_i)
end
end

function _nonlinear_to_string(options::MOI.Utilities._PrintOptions, model::MOI.ModelLike,
nlf::NLF,
) where {NLF}
io, stack, is_open = IOBuffer(), Any[nlf], true
while !isempty(stack)
arg = pop!(stack)
if !is_open && arg != ')'
print(io, ", ")
end
if arg isa NLF
print(io, arg.head, "(")
push!(stack, ')')
for i in length(arg.args):-1:1
push!(stack, arg.args[i])
end
elseif arg isa Char
print(io, arg)
else
print(io, MOI.Utilities._to_string(options, model, arg))
end
is_open = arg isa NLF
end
seekstart(io)
return read(io, String)
end

function MOI.Utilities._to_string(options::MOI.Utilities._PrintOptions, model::MOI.ModelLike,
naf::NonlinearAlgebraicFunction,
)
return _nonlinear_to_string(options, model, naf)
end
99 changes: 62 additions & 37 deletions src/boundary_functions.jl
Original file line number Diff line number Diff line change
@@ -1,70 +1,95 @@
"""
DomainInitial <: AbstractBoundaryFunction
Initial{AF<:AbstractAlgebraicFunction} <: AbstractBoundaryFunction
```math
t_i^0
a(y(t_i^0), t_i^0, x)
```
Represents the initial point of a [`DomainIndex`](@ref).
Represents the evaluation of an [`AbstractAlgebraicFunction`](@ref) at the initial
point of its domain. Common cases are:
* ``t_i^0`` `Initial{DomainIndex}`
* ``y_j(t_i^0)`` `Initial{DynamicVariableIndex}`
"""
struct DomainInitial <: AbstractBoundaryFunction
index::DomainIndex
struct Initial{AF<:AbstractAlgebraicFunction} <: AbstractBoundaryFunction
evaluand::AF
end

"""
DomainFinal <: AbstractBoundaryFunction
```math
t_i^f
```
Represents the final point of a [`DomainIndex`](@ref).
"""
struct DomainFinal <: AbstractBoundaryFunction
index::DomainIndex
function MOI.Utilities._to_string(options::MOI.Utilities._PrintOptions, model::MOI.ModelLike,
initial::Initial,
)
return string(
"Initial(",
MOI.Utilities._to_string(options, model, initial.evaluand),
")",
)
end

"""
DynamicVariableInitial <: AbstractBoundaryFunction
Final{AF<:AbstractAlgebraicFunction} <: AbstractBoundaryFunction
```math
y_j(t_i^0)
```
Represents a [`DynamicVariableIndex`](@ref) evaluated at the initial point of its [`DomainIndex`](@ref)
a(y(t_i^f), t_i^f, x)
```
Represents the evaluation of an [`AbstractAlgebraicFunction`](@ref) at the final
point of its domain. Common cases are:
* ``t_i^f`` `Final{DomainIndex}`
* ``y_j(t_i^f)`` `Final{DynamicVariableIndex}`
"""
struct DynamicVariableInitial <: AbstractBoundaryFunction
variable_index::DynamicVariableIndex
struct Final{AF<:AbstractAlgebraicFunction} <: AbstractBoundaryFunction
evaluand::AF
end

"""
DynamicVariableFinal <: AbstractBoundaryFunction
```math
y_j(t_i^f)
```
Represents a [`DynamicVariableIndex`](@ref) evaluated at the final point of its [`DomainIndex`](@ref)
"""
struct DynamicVariableFinal <: AbstractBoundaryFunction
variable_index::DynamicVariableIndex
function MOI.Utilities._to_string(options::MOI.Utilities._PrintOptions, model::MOI.ModelLike,
final::Final,
)
return string(
"Final(",
MOI.Utilities._to_string(options, model, final.evaluand),
")",
)
end

const _NONLINEAR_BOUNDARY_TYPES = Union{
Real,
MOI.VariableIndex,
Initial{DomainIndex},
Final{DomainIndex},
Initial{DynamicVariableIndex},
Final{DynamicVariableIndex},
}

"""
NonlinearBoundaryFunction <: AbstractBoundaryFunction
```math
b(y_j(t^0), y_j(t^f), t^0, t^f, x)
b(y(t^0), y(t^f), t^0, t^f, x)
```
Similar to [`MathOptInterface.ScalarNonlinearFunction`](@extref),
Each node in `args` can be one of the following:
* A constant value of type `T<:Real`
* A [`MathOptInterface.VariableIndex`](@extref)
* A [`DomainInitial`](@ref)
* A [`DomainFinal`](@ref)
* A [`DynamicVariableInitial`](@ref)
* A [`DynamicVariableFinal`](@ref)
* An `Initial{DomainIndex}`
* A `Final{DomainIndex}`
* An `Initial{DynamicVariableIndex}`
* A `Final{DynamicVariableIndex}`
* Another [`NonlinearBoundaryFunction`](@ref)
"""
struct NonlinearBoundaryFunction <: AbstractBoundaryFunction
head::Symbol
args::Vector{Any}
# Inner constructor to enforce rules

function NonlinearBoundaryFunction(head::Symbol, args::AbstractVector)
for arg in args
if !(arg isa _NONLINEAR_BOUNDARY_TYPES)
error("Unsupported object: $arg")
end
end
return new(head, convert(Vector{Any}, args), t_i)
end
end

function MOI.Utilities._to_string(options::MOI.Utilities._PrintOptions, model::MOI.ModelLike,
nbf::NonlinearBoundaryFunction,
)
return _nonlinear_to_string(options, model, nbf)
end
48 changes: 45 additions & 3 deletions src/differential_functions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ t_i \\mapsto \\dot{y}_j(t_i)
A derivative
"""
struct DynamicVariableDerivative <: AbstractDifferentialFunction
variable_index::DynamicVariableIndex
y_j::DynamicVariableIndex
end

function MOI.Utilities._to_string(::MOI.Utilities._PrintOptions, ::MOI.ModelLike,
derivative::DynamicVariableDerivative,
)
return string("ẏ[", derivative.y_j.value, "]")
end

"""
Expand All @@ -22,6 +28,17 @@ struct ExplicitDifferentialFunction{AF<:AbstractAlgebraicFunction} <: AbstractDi
algebraic_function::AF
end

function MOI.Utilities._to_string(options::MOI.Utilities._PrintOptions, model::MOI.ModelLike,
edf::ExplicitDifferentialFunction,
)
return string(
MOI.Utilities._to_string(options, model, edf.derivative),
" - (",
MOI.Utilities._to_string(options, model, edf.algebraic_function),
")",
)
end

"""
NonlinearDifferentialFunction <: AbstractDifferentialFunction
Expand All @@ -39,8 +56,33 @@ Each node in `args` can be one of the following:
* Another [`NonlinearDifferentialFunction`](@ref)
"""
struct NonlinearDifferentialFunction <: AbstractDifferentialFunction
domain::DomainIndex
head::Symbol
args::Vector{Any}
# Inner constructor to enforce rules
t_i::DomainIndex

function NonlinearDifferentialFunction(head::Symbol, args::AbstractVector, t_i::DomainIndex)
for arg in args
if arg isa Real || arg isa MOI.VariableIndex
continue
elseif arg isa DomainIndex
arg.value == t_i.value ? continue : error("Different domains not allowed.")

elseif arg isa DynamicVariableIndex || arg isa NonlinearDifferentialFunction
arg.t_i.value == t_i.value ? continue : error("Different domains not allowed.")

elseif arg isa DynamicVariableDerivative
arg.y_j.t_i.value == t_i.value ? continue : error("Different domains not allowed.")

else
error("Unsupported object: $arg")
end
end
return new(head, convert(Vector{Any}, args), t_i)
end
end

function MOI.Utilities._to_string(options::MOI.Utilities._PrintOptions, model::MOI.ModelLike,
ndf::NonlinearDifferentialFunction,
)
return _nonlinear_to_string(options, model, ndf)
end
39 changes: 10 additions & 29 deletions src/domains.jl
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
"""
DomainIndex <: AbstractDynamicFunction
DomainIndex <: AbstractAlgebraicFunction
```math
t_i
```
A type-safe wrapper for `Int64` for use in referencing domains.
"""
struct DomainIndex <: AbstractDynamicFunction
struct DomainIndex <: AbstractAlgebraicFunction
value::Int64
end

function MOI.Utilities._to_string(::MOI.Utilities._PrintOptions, ::MOI.ModelLike,
t_i::DomainIndex
)
return string("t[", t_i.value, "]")
end

"""
supports_domain(model::MOI.ModelLike)
Expand Down Expand Up @@ -42,33 +48,8 @@ MOI.operation_name(::AddDomainNotAllowed) = "Adding a domain"
"""
add_domain(model::MOI.ModelLike)
Add a domain to the model, returning a [`DomainIndex`](@ref). An
Add a domain to `model`, returning a [`DomainIndex`](@ref). An
[`AddDomainNotAllowed`](@ref) is thrown if a domain cannot be added
to the `model` in its current state.
"""
add_domain(::MOI.ModelLike) = throw(AddDomainNotAllowed(""))

#=
# Parameters
@parameter(model, t_0)
# Design Variables
@variable(model, 1.0 ≤ t_f ≤ 2.0)
# Time Domains
@domain(model, t ∈ [0.0, t_f])
add_domain()::Tuple{DomainIndex, ConstraintIndex, ConstraintIndex}
# start(t) ∈ EqualTo
# final(t) ∈ Interval
# Algebraic Variables
@algebraic(model, u(t))
add_algebraic()::AlgebraicVariableIndex()
# Differential Variable
@differential(model, y(t))
add_differential()::DynamicVariableIndex()
=#
add_domain(::MOI.ModelLike) = throw(AddDomainNotAllowed(""))
14 changes: 11 additions & 3 deletions src/dynamic_variables.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ A type-safe wrapper for `Int64` for use in referencing dynamic variables.
"""
struct DynamicVariableIndex <: AbstractAlgebraicFunction
value::Int64
domain::DomainIndex
t_i::DomainIndex
end

function MOI.Utilities._to_string(::MOI.Utilities._PrintOptions, ::MOI.ModelLike,
y_j::DynamicVariableIndex
)
return string("y[", y_j.value, "]")
end

"""
Expand Down Expand Up @@ -41,8 +47,10 @@ end
MOI.operation_name(::AddDynamicVariableNotAllowed) = "Adding a dynamic variable"

"""
add_dynamic_variable(::MOI.ModelLike)
add_dynamic_variable(model::MOI.ModelLike)
Add
Add a dynamic variable to `model`, returning a [`DynamicVariableIndex`](@ref). An
[`AddDynamicVariableNotAllowed`](@ref) is thrown if a dynamic variable cannot be added
to `model` in its current state.
"""
add_dynamic_variable(::MOI.ModelLike) = throw(AddDynamicVariableNotAllowed(""))
Loading

0 comments on commit e6a50fb

Please sign in to comment.