diff --git a/docs/src/reference/internal.md b/docs/src/reference/internal.md index 9678a03..bd40ad2 100644 --- a/docs/src/reference/internal.md +++ b/docs/src/reference/internal.md @@ -1,5 +1,12 @@ # Internal types +## Internal supertypes + +```@docs +TimeStruct.TimeStructInnerIter +TimeStruct.TimeStructOuterIter +``` + ## Strategic period types ([`TwoLevelTree`](@ref)) ### Single types @@ -32,7 +39,7 @@ TimeStruct.StrategicPeriod ```@docs TimeStruct.SingleStrategicPeriodWrapper -TimeStruct.StratPeriods +TimeStruct.StratPers ``` ## Representative period types @@ -51,9 +58,9 @@ TimeStruct.StratNodeReprPeriod ```@docs TimeStruct.SingleReprPeriodWrapper -TimeStruct.ReprPeriods -TimeStruct.StratReprPeriods -TimeStruct.StratNodeReprPeriods +TimeStruct.ReprPers +TimeStruct.StratReprPers +TimeStruct.StratNodeReprPers ``` ## Operational scenarios types @@ -64,10 +71,10 @@ TimeStruct.StratNodeReprPeriods TimeStruct.AbstractOperationalScenario TimeStruct.SingleScenario TimeStruct.OperationalScenario -TimeStruct.ReprOperationalScenario -TimeStruct.StratOperationalScenario -TimeStruct.StratReprOpscenario -TimeStruct.StratNodeOperationalScenario +TimeStruct.ReprOpScenario +TimeStruct.StratOpScenario +TimeStruct.StratReprOpScenario +TimeStruct.StratNodeOpScenario TimeStruct.StratNodeReprOpScenario ``` @@ -78,7 +85,7 @@ TimeStruct.SingleScenarioWrapper TimeStruct.OpScens TimeStruct.RepOpScens TimeStruct.StratOpScens -TimeStruct.StratReprOpscenarios +TimeStruct.StratReprOpScens TimeStruct.StratNodeOpScens TimeStruct.StratNodeReprOpScens ``` diff --git a/src/calendar.jl b/src/calendar.jl index 28c6447..c142148 100644 --- a/src/calendar.jl +++ b/src/calendar.jl @@ -90,7 +90,7 @@ function Base.last(ts::CalendarTimes) end """ - struct CalendarPeriod <: TimePeriod + struct CalendarPeriod{T} <: TimePeriod Time period for a single operational period. It is created through iterating through a [`CalendarTimes`](@ref) time structure with duration measured in hours (by default). diff --git a/src/op_scenarios/core_types.jl b/src/op_scenarios/core_types.jl index 5835640..545a605 100644 --- a/src/op_scenarios/core_types.jl +++ b/src/op_scenarios/core_types.jl @@ -99,16 +99,12 @@ function Base.iterate(oscs::OperationalScenarios, state = (nothing, 1)) return ScenarioPeriod(oscs, next[1], osc), (next[2], osc) end function Base.last(oscs::OperationalScenarios) - return ScenarioPeriod( - oscs.len, - oscs.probability[oscs.len], - _multiple_adj(oscs, oscs.len), - last(oscs.scenarios[oscs.len]), - ) + per = last(oscs.scenarios[oscs.len]) + return ScenarioPeriod(oscs, per, oscs.len) end """ - ScenarioPeriod{P} <: TimePeriod where {P<:TimePeriod} + struct ScenarioPeriod{P} <: TimePeriod where {P<:TimePeriod} Time period for a single operational period. It is created through iterating through a [`OperationalScenarios`](@ref) time structure. It is as well created as period within @@ -116,35 +112,37 @@ Time period for a single operational period. It is created through iterating thr """ struct ScenarioPeriod{P} <: TimePeriod where {P<:TimePeriod} osc::Int - prob::Float64 - multiple::Float64 period::P + multiple::Float64 + prob::Float64 end +_period(t::ScenarioPeriod) = t.period -_oper(t::ScenarioPeriod) = _oper(t.period) +_oper(t::ScenarioPeriod) = _oper(_period(t)) _opscen(t::ScenarioPeriod) = t.osc -isfirst(t::ScenarioPeriod) = isfirst(t.period) -duration(t::ScenarioPeriod) = duration(t.period) +isfirst(t::ScenarioPeriod) = isfirst(_period(t)) +duration(t::ScenarioPeriod) = duration(_period(t)) multiple(t::ScenarioPeriod) = t.multiple probability(t::ScenarioPeriod) = t.prob -Base.show(io::IO, t::ScenarioPeriod) = print(io, "sc$(t.osc)-$(t.period)") +Base.show(io::IO, t::ScenarioPeriod) = print(io, "sc$(_opscen(t))-$(_period(t))") function Base.isless(t1::ScenarioPeriod, t2::ScenarioPeriod) - return t1.osc < t2.osc || (t1.osc == t2.osc && t1.period < t2.period) + return _opscen(t1) < _opscen(t2) || + (_opscen(t1) == _opscen(t2) && _period(t1) < _period(t2)) end # Convenience constructors for the type function ScenarioPeriod(osc::Int, prob::Number, multiple::Number, period) return ScenarioPeriod( osc, - Base.convert(Float64, prob), - Base.convert(Float64, multiple), period, + Base.convert(Float64, multiple), + Base.convert(Float64, prob), ) end function ScenarioPeriod(oscs::OperationalScenarios, per::TimePeriod, osc::Int) prob = oscs.probability[osc] mult = _multiple_adj(oscs, osc) - return ScenarioPeriod(osc, prob, mult, per) + return ScenarioPeriod(osc, per, mult, prob) end diff --git a/src/op_scenarios/opscenarios.jl b/src/op_scenarios/opscenarios.jl index d27207a..ea2f572 100644 --- a/src/op_scenarios/opscenarios.jl +++ b/src/op_scenarios/opscenarios.jl @@ -1,5 +1,5 @@ """ - AbstractOperationalScenario{T} <: TimeStructure{T} + abstract type AbstractOperationalScenario{T} <: TimeStructure{T} Abstract type used for time structures that represent an operational scenario. These periods are obtained when iterating through the operational scenarios of a time @@ -26,7 +26,7 @@ ScenarioIndexable(::Type{<:AbstractOperationalScenario}) = HasScenarioIndex() ScenarioIndexable(::Type{<:TimePeriod}) = HasScenarioIndex() """ - SingleScenario{T,SC<:TimeStructure{T}} <: AbstractRepresentativePeriod{T} + struct SingleScenario{T,SC<:TimeStructure{T}} <: AbstractRepresentativePeriod{T} A type representing a single operational scenario supporting iteration over its time periods. It is created when iterating through [`SingleScenarioWrapper`](@ref). @@ -68,16 +68,18 @@ function Base.last( # TODO: Considering removing the function as the the structu end """ - SingleScenarioWrapper{T,OP<:TimeStructure{T}} <: TimeStructure{T} + struct SingleScenarioWrapper{T,OP<:TimeStructure{T}} <: TimeStructInnerIter{T} Type for iterating through the individual operational scenarios of a time structure without [`OperationalScenarios`](@ref). It is automatically created through the function [`opscenarios`](@ref). """ -struct SingleScenarioWrapper{T,SC<:TimeStructure{T}} <: TimeStructure{T} +struct SingleScenarioWrapper{T,SC<:TimeStructure{T}} <: TimeStructInnerIter{T} ts::SC end +_oper_struct(oscs::SingleScenarioWrapper) = oscs.ts + """ opscenarios(ts::TimeStructure) @@ -91,24 +93,24 @@ When the `TimeStructure` is a `TimeStructure`, `opscenarios` returns a opscenarios(ts::TimeStructure) = SingleScenarioWrapper(ts) # Add basic functions of iterators -Base.length(ssw::SingleScenarioWrapper) = 1 +Base.length(oscs::SingleScenarioWrapper) = 1 function Base.eltype(::Type{SingleScenarioWrapper{T,SC}}) where {T,SC} return SingleScenario{T,SC} end -function Base.iterate(ssw::SingleScenarioWrapper, state = nothing) +function Base.iterate(oscs::SingleScenarioWrapper, state = nothing) !isnothing(state) && return nothing - return SingleScenario(ssw.ts), 1 + return SingleScenario(_oper_struct(oscs)), 1 end """ - OperationalScenario{T,OP<:TimeStructure{T}} <: AbstractOperationalScenario{T} + struct OperationalScenario{T,OP<:TimeStructure{T}} <: AbstractOperationalScenario{T} A type representing a single operational scenario supporting iteration over its time periods. It is created when iterating through [`OpScens`](@ref). """ struct OperationalScenario{T,OP<:TimeStructure{T}} <: AbstractOperationalScenario{T} scen::Int - mult_sc::Float64 + mult_scen::Float64 probability::Float64 operational::OP end @@ -116,17 +118,14 @@ end _opscen(osc::OperationalScenario) = osc.scen probability(osc::OperationalScenario) = osc.probability -mult_scen(osc::OperationalScenario) = osc.mult_sc +mult_scen(osc::OperationalScenario) = osc.mult_scen Base.show(io::IO, osc::OperationalScenario) = print(io, "sc-$(osc.scen)") # Provide a constructor to simplify the design -function ScenarioPeriod( - osc::OperationalScenario, - per::P, -) where {P<:Union{TimePeriod,TimeStructure}} +function ScenarioPeriod(osc::OperationalScenario, per::TimePeriod) mult = mult_scen(osc) * multiple(per) - return ScenarioPeriod(_opscen(osc), probability(osc), mult, per) + return ScenarioPeriod(_opscen(osc), per, mult, probability(osc)) end # Add basic functions of iterators @@ -151,17 +150,17 @@ function Base.eachindex(osc::OperationalScenario) end """ - OpScens{T,OP} + struct OpScens{T,OP} <: TimeStructInnerIter{T} Type for iterating through the individual operational scenarios of a [`OperationalScenarios`](@ref) time structure. It is automatically created through the function [`opscenarios`](@ref). """ -struct OpScens{T,OP} +struct OpScens{T,OP} <: TimeStructInnerIter{T} ts::OperationalScenarios{T,OP} end -_oper_it(oscs::OpScens) = oscs.ts +_oper_struct(oscs::OpScens) = oscs.ts """ When the `TimeStructure` is an [`OperationalScenarios`](@ref), `opscenarios` returns the @@ -173,14 +172,14 @@ opscenarios(oscs::OperationalScenarios) = OpScens(oscs) function OperationalScenario(oscs::OpScens, per::Int) return OperationalScenario( per, - _multiple_adj(oscs.ts, per), - oscs.ts.probability[per], - oscs.ts.scenarios[per], + _multiple_adj(_oper_struct(oscs), per), + _oper_struct(oscs).probability[per], + _oper_struct(oscs).scenarios[per], ) end # Add basic functions of iterators -Base.length(oscs::OpScens) = oscs.ts.len +Base.length(oscs::OpScens) = _oper_struct(oscs).len function Base.eltype(_::Type{OpScens{T,OP}}) where {T,OP<:TimeStructure{T}} return OperationalScenario{T,OP} end @@ -194,6 +193,6 @@ function Base.getindex(oscs::OpScens, index::Int) return OperationalScenario(oscs, index) end function Base.eachindex(oscs::OpScens) - return eachindex(oscs.ts.scenarios) + return eachindex(_oper_struct(oscs).scenarios) end Base.last(oscs::OpScens) = OperationalScenario(oscs, length(oscs)) diff --git a/src/op_scenarios/rep_periods.jl b/src/op_scenarios/rep_periods.jl index 08390e9..547b3c0 100644 --- a/src/op_scenarios/rep_periods.jl +++ b/src/op_scenarios/rep_periods.jl @@ -1,10 +1,10 @@ """ - ReprOperationalScenario{T,OP<:TimeStructure{T}} <: AbstractOperationalScenario{T} + struct ReprOpScenario{T,OP<:TimeStructure{T}} <: AbstractOperationalScenario{T} A type representing a single operational scenarios supporting iteration over its time periods. It is created when iterating through [`RepOpScens`](@ref). """ -struct ReprOperationalScenario{T,OP<:TimeStructure{T}} <: AbstractOperationalScenario{T} +struct ReprOpScenario{T,OP<:TimeStructure{T}} <: AbstractOperationalScenario{T} rp::Int scen::Int mult_rp::Float64 @@ -13,56 +13,56 @@ struct ReprOperationalScenario{T,OP<:TimeStructure{T}} <: AbstractOperationalSce operational::OP end -_opscen(osc::ReprOperationalScenario) = osc.scen -_rper(osc::ReprOperationalScenario) = osc.rp +_opscen(osc::ReprOpScenario) = osc.scen +_rper(osc::ReprOpScenario) = osc.rp -probability(osc::ReprOperationalScenario) = osc.probability -mult_scen(osc::ReprOperationalScenario) = osc.mult_scen -mult_repr(osc::ReprOperationalScenario) = osc.mult_rp +probability(osc::ReprOpScenario) = osc.probability +mult_scen(osc::ReprOpScenario) = osc.mult_scen +mult_repr(osc::ReprOpScenario) = osc.mult_rp -RepresentativeIndexable(::Type{<:ReprOperationalScenario}) = HasReprIndex() +RepresentativeIndexable(::Type{<:ReprOpScenario}) = HasReprIndex() # Provide a constructor to simplify the design -function ReprPeriod(osc::ReprOperationalScenario, per) +function ReprPeriod(osc::ReprOpScenario, per) mult = mult_repr(osc) * multiple(per) return ReprPeriod(_rper(osc), per, mult) end -function Base.show(io::IO, osc::ReprOperationalScenario) +function Base.show(io::IO, osc::ReprOpScenario) return print(io, "rp$(_rper(osc))-sc$(_opscen(osc))") end # Add basic functions of iterators -Base.length(osc::ReprOperationalScenario) = length(osc.operational) -function Base.eltype(_::ReprOperationalScenario{T,OP}) where {T,OP} +Base.length(osc::ReprOpScenario) = length(osc.operational) +function Base.eltype(_::ReprOpScenario{T,OP}) where {T,OP} return ReprPeriod{eltype(OP)} end -function Base.iterate(osc::ReprOperationalScenario, state = nothing) +function Base.iterate(osc::ReprOpScenario, state = nothing) next = isnothing(state) ? iterate(osc.operational) : iterate(osc.operational, state) next === nothing && return nothing return ReprPeriod(osc, next[1]), next[2] end -function Base.getindex(osc::ReprOperationalScenario, index::Int) +function Base.getindex(osc::ReprOpScenario, index::Int) per = osc.operational[index] return ReprPeriod(osc, per) end -function Base.eachindex(osc::ReprOperationalScenario) +function Base.eachindex(osc::ReprOpScenario) return eachindex(osc.operational) end -function Base.last(osc::ReprOperationalScenario) +function Base.last(osc::ReprOpScenario) per = last(osc.operational) return ReprPeriod(osc, per) end """ - RepOpScens{OP} + struct RepOpScens{T,OP<:TimeStructInnerIter{T}} <: TimeStructOuterIter{T} Type for iterating through the individual operational scenarios of a [`RepresentativePeriod`](@ref) time structure. It is automatically created through the function [`opscenarios`](@ref). """ -struct RepOpScens{OP} +struct RepOpScens{T,OP<:TimeStructInnerIter{T}} <: TimeStructOuterIter{T} rp::Int mult_rp::Float64 opscens::OP @@ -72,7 +72,7 @@ _rper(oscs::RepOpScens) = oscs.rp mult_repr(oscs::RepOpScens) = oscs.mult_rp -_oper_it(oscs::RepOpScens) = oscs.opscens +_oper_struct(oscs::RepOpScens) = oscs.opscens """ When the `TimeStructure` is a [`RepresentativePeriod`](@ref) with [`OperationalScenarios`](@ref), @@ -83,39 +83,41 @@ function opscenarios(rep::RepresentativePeriod{T,OperationalScenarios{T,OP}}) wh end # Provide a constructor to simplify the design -function ReprOperationalScenario(oscs::RepOpScens, scen::Int, per) - return ReprOperationalScenario( +function ReprOpScenario(oscs::RepOpScens, scen::Int, per) + return ReprOpScenario( _rper(oscs), scen, mult_repr(oscs), - _multiple_adj(_oper_it(_oper_it(oscs)), scen), + _multiple_adj(_oper_struct(_oper_struct(oscs)), scen), probability(per), per, ) end # Add basic functions of iterators -Base.length(oscs::RepOpScens) = length(_oper_it(_oper_it(oscs)).scenarios) +Base.length(oscs::RepOpScens) = length(_oper_struct(_oper_struct(oscs)).scenarios) function Base.eltype(_::Type{RepOpScens{SC}}) where {T,OP,SC<:OpScens{T,OP}} - return ReprOperationalScenario{T,eltype(SC)} + return ReprOpScenario{T,eltype(SC)} end function Base.iterate(oscs::RepOpScens, state = (nothing, 1)) - next = isnothing(state[1]) ? iterate(_oper_it(oscs)) : iterate(_oper_it(oscs), state[1]) + next = + isnothing(state[1]) ? iterate(_oper_struct(oscs)) : + iterate(_oper_struct(oscs), state[1]) isnothing(next) && return nothing scen = state[2] - return ReprOperationalScenario(oscs, _opscen(next[1]), next[1]), (next[2], scen + 1) + return ReprOpScenario(oscs, _opscen(next[1]), next[1]), (next[2], scen + 1) end function Base.getindex(oscs::RepOpScens, index::Int) - per = _oper_it(oscs)[index] - return ReprOperationalScenario(oscs, _opscen(per), per) + per = _oper_struct(oscs)[index] + return ReprOpScenario(oscs, _opscen(per), per) end function Base.eachindex(oscs::RepOpScens) - return eachindex(_oper_it(oscs)) + return eachindex(_oper_struct(oscs)) end function Base.last(oscs::RepOpScens) - per = last(_oper_it(oscs)) - return ReprOperationalScenario(oscs, _opscen(per), per) + per = last(_oper_struct(oscs)) + return ReprOpScenario(oscs, _opscen(per), per) end """ @@ -125,7 +127,7 @@ correct behavior based on the substructure. opscenarios(ts::SingleReprPeriod) = opscenarios(ts.ts) """ When the `TimeStructure` is a [`RepresentativePeriods`](@ref), `opscenarios` returns an -`Array` of all [`ReprOperationalScenario`](@ref)s. +`Array` of all [`ReprOpScenario`](@ref)s. """ function opscenarios(ts::RepresentativePeriods) return collect(Iterators.flatten(opscenarios(rp) for rp in repr_periods(ts))) diff --git a/src/op_scenarios/strat_periods.jl b/src/op_scenarios/strat_periods.jl index 76e837a..499f8c1 100644 --- a/src/op_scenarios/strat_periods.jl +++ b/src/op_scenarios/strat_periods.jl @@ -1,10 +1,10 @@ """ - StratOperationalScenario{T,OP<:TimeStructure{T}} <: AbstractOperationalScenario{T} + struct StratOpScenario{T,OP<:TimeStructure{T}} <: AbstractOperationalScenario{T} A type representing a single operational scenario supporting iteration over its time periods. It is created when iterating through [`StratOpScens`](@ref). """ -struct StratOperationalScenario{T,OP<:TimeStructure{T}} <: AbstractOperationalScenario{T} +struct StratOpScenario{T,OP<:TimeStructure{T}} <: AbstractOperationalScenario{T} sp::Int scen::Int mult_sp::Float64 @@ -13,57 +13,57 @@ struct StratOperationalScenario{T,OP<:TimeStructure{T}} <: AbstractOperationalSc operational::OP end -_strat_per(osc::StratOperationalScenario) = osc.sp -_opscen(osc::StratOperationalScenario) = osc.scen +_strat_per(osc::StratOpScenario) = osc.sp +_opscen(osc::StratOpScenario) = osc.scen -mult_strat(osc::StratOperationalScenario) = osc.mult_sp -mult_scen(osc::StratOperationalScenario) = osc.mult_scen -probability(osc::StratOperationalScenario) = osc.probability +mult_strat(osc::StratOpScenario) = osc.mult_sp +mult_scen(osc::StratOpScenario) = osc.mult_scen +probability(osc::StratOpScenario) = osc.probability -StrategicIndexable(::Type{<:StratOperationalScenario}) = HasStratIndex() -ScenarioIndexable(::Type{<:StratOperationalScenario}) = HasScenarioIndex() +StrategicIndexable(::Type{<:StratOpScenario}) = HasStratIndex() +ScenarioIndexable(::Type{<:StratOpScenario}) = HasScenarioIndex() # Provide a constructor to simplify the design -function OperationalPeriod(osc::StratOperationalScenario, per) +function OperationalPeriod(osc::StratOpScenario, per) mult = mult_strat(osc) * multiple(per) return OperationalPeriod(osc.sp, per, mult) end -function Base.show(io::IO, osc::StratOperationalScenario) +function Base.show(io::IO, osc::StratOpScenario) return print(io, "sp$(osc.sp)-sc$(osc.scen)") end # Add basic functions of iterators -Base.length(osc::StratOperationalScenario) = length(osc.operational) -function Base.eltype(::Type{StratOperationalScenario{T,OP}}) where {T,OP} - return OperationalPeriod +Base.length(osc::StratOpScenario) = length(osc.operational) +function Base.eltype(::Type{StratOpScenario{T,OP}}) where {T,OP} + return OperationalPeriod{eltype(OP)} end -function Base.iterate(osc::StratOperationalScenario, state = nothing) +function Base.iterate(osc::StratOpScenario, state = nothing) next = isnothing(state) ? iterate(osc.operational) : iterate(osc.operational, state) isnothing(next) && return nothing return OperationalPeriod(osc, next[1]), next[2] end -function Base.getindex(osc::StratOperationalScenario, index) +function Base.getindex(osc::StratOpScenario, index) per = osc.operational[index] return OperationalPeriod(osc, per) end -function Base.eachindex(osc::StratOperationalScenario) +function Base.eachindex(osc::StratOpScenario) return eachindex(osc.operational) end -function Base.last(osc::StratOperationalScenario) +function Base.last(osc::StratOpScenario) per = last(osc.operational) return OperationalPeriod(osc, per) end """ - StratOpScens{OP} + struct StratOpScens{T,OP<:TimeStructInnerIter{T}} <: TimeStructOuterIter{T} Type for iterating through the individual operational scenarios of a [`StrategicPeriod`](@ref) time structure. It is automatically created through the function [`opscenarios`](@ref). """ -struct StratOpScens{OP} +struct StratOpScens{T,OP<:TimeStructInnerIter{T}} <: TimeStructOuterIter{T} sp::Int mult_sp::Float64 opscens::OP @@ -73,7 +73,7 @@ _strat_per(oscs::StratOpScens) = oscs.sp mult_strat(oscs::StratOpScens) = oscs.mult_sp -_oper_it(oscs::StratOpScens) = oscs.opscens +_oper_struct(oscs::StratOpScens) = oscs.opscens """ When the `TimeStructure` is a [`StrategicPeriod`](@ref), `opscenarios` returns the iterator @@ -83,8 +83,8 @@ function opscenarios(sp::StrategicPeriod{S,T,OP}) where {S,T,OP} return StratOpScens(_strat_per(sp), mult_strat(sp), opscenarios(sp.operational)) end # Provide a constructor to simplify the design -function StratOperationalScenario(oscs::StratOpScens, scen::Int, per) - return StratOperationalScenario( +function StratOpScenario(oscs::StratOpScens, scen::Int, per) + return StratOpScenario( _strat_per(oscs), scen, mult_strat(oscs), @@ -95,99 +95,102 @@ function StratOperationalScenario(oscs::StratOpScens, scen::Int, per) end # Add basic functions of iterators -Base.length(oscs::StratOpScens) = length(_oper_it(oscs)) +Base.length(oscs::StratOpScens) = length(_oper_struct(oscs)) function Base.iterate(oscs::StratOpScens, state = (nothing, 1)) - next = isnothing(state[1]) ? iterate(_oper_it(oscs)) : iterate(_oper_it(oscs), state[1]) + next = + isnothing(state[1]) ? iterate(_oper_struct(oscs)) : + iterate(_oper_struct(oscs), state[1]) isnothing(next) && return nothing scen = state[2] - return StratOperationalScenario(oscs, _opscen(next[1]), next[1]), (next[2], scen + 1) + return StratOpScenario(oscs, _opscen(next[1]), next[1]), (next[2], scen + 1) end function Base.getindex(oscs::StratOpScens, index::Int) - per = _oper_it(oscs)[index] - return StratOperationalScenario(oscs, index, per) + per = _oper_struct(oscs)[index] + return StratOpScenario(oscs, index, per) end function Base.eachindex(oscs::StratOpScens) - return eachindex(_oper_it(oscs)) + return eachindex(_oper_struct(oscs)) end function Base.last(oscs::StratOpScens) per = last(oscs.repr) - return StratOperationalScenario(oscs, _opscen(per), per) + return StratOpScenario(oscs, _opscen(per), per) end """ - StratReprOpscenario{T, OP<:TimeStructure{T}} <: AbstractRepresentativePeriod{T} + struct StratReprOpScenario{T, OP<:TimeStructure{T}} <: AbstractRepresentativePeriod{T} A type representing a single representative period supporting iteration over its -time periods. It is created when iterating through [`StratReprPeriods`](@ref). +time periods. It is created when iterating through [`StratReprPers`](@ref). """ -struct StratReprOpscenario{T,OP<:TimeStructure{T}} <: AbstractOperationalScenario{T} +struct StratReprOpScenario{T,OP<:TimeStructure{T}} <: AbstractOperationalScenario{T} sp::Int rp::Int - opscen::Int + scen::Int mult_sp::Float64 mult_rp::Float64 + mult_scen::Float64 probability::Float64 operational::OP end -_opscen(osc::StratReprOpscenario) = osc.opscen -_rper(osc::StratReprOpscenario) = osc.rp -_strat_per(osc::StratReprOpscenario) = osc.sp +_opscen(osc::StratReprOpScenario) = osc.scen +_rper(osc::StratReprOpScenario) = osc.rp +_strat_per(osc::StratReprOpScenario) = osc.sp -probability(osc::StratReprOpscenario) = osc.probability -mult_scen(osc::StratReprOpscenario) = osc.multiple_scen -mult_repr(osc::StratReprOpscenario) = osc.mult_rp -mult_strat(osc::StratReprOpscenario) = osc.mult_sp +probability(osc::StratReprOpScenario) = osc.probability +mult_strat(osc::StratReprOpScenario) = osc.mult_sp +mult_repr(osc::StratReprOpScenario) = osc.mult_rp +mult_scen(osc::StratReprOpScenario) = osc.mult_scen -StrategicIndexable(::Type{<:StratReprOpscenario}) = HasStratIndex() -function RepresentativeIndexable(::Type{<:StratReprOpscenario}) +StrategicIndexable(::Type{<:StratReprOpScenario}) = HasStratIndex() +function RepresentativeIndexable(::Type{<:StratReprOpScenario}) return HasReprIndex() end -ScenarioIndexable(::Type{<:StratReprOpscenario}) = HasScenarioIndex() +ScenarioIndexable(::Type{<:StratReprOpScenario}) = HasScenarioIndex() # Provide a constructor to simplify the design -function OperationalPeriod(osc::StratReprOpscenario, per) +function OperationalPeriod(osc::StratReprOpScenario, per) rper = ReprPeriod(_rper(osc), per, mult_repr(osc) * multiple(per)) mult = mult_strat(osc) * mult_repr(osc) * multiple(per) return OperationalPeriod(_strat_per(osc), rper, mult) end -function Base.show(io::IO, osc::StratReprOpscenario) +function Base.show(io::IO, osc::StratReprOpScenario) return print(io, "sp$(osc.sp)-rp$(_rper(osc))-sc$(osc.opscen)") end # Add basic functions of iterators -Base.length(osc::StratReprOpscenario) = length(osc.operational) -function Base.eltype(::Type{StratReprOpscenario{T,OP}}) where {T,OP} - return OperationalPeriod +Base.length(osc::StratReprOpScenario) = length(osc.operational) +function Base.eltype(::Type{StratReprOpScenario{T,OP}}) where {T,OP} + return OperationalPeriod{ReprPeriod{eltype(OP)}} end -function Base.iterate(osc::StratReprOpscenario, state = nothing) +function Base.iterate(osc::StratReprOpScenario, state = nothing) next = isnothing(state) ? iterate(osc.operational) : iterate(osc.operational, state) isnothing(next) && return nothing return OperationalPeriod(osc, next[1]), next[2] end -function Base.getindex(osc::StratReprOpscenario, index) +function Base.getindex(osc::StratReprOpScenario, index) per = osc.operational[index] return OperationalPeriod(osc, per) end -function Base.eachindex(osc::StratReprOpscenario) +function Base.eachindex(osc::StratReprOpScenario) return eachindex(osc.operational) end -function Base.last(osc::StratReprOpscenario) +function Base.last(osc::StratReprOpScenario) per = last(osc.operational) return OperationalPeriod(osc, per) end """ - StratReprOpscenarios{OP} + struct StratReprOpScens{T,OP<:TimeStructInnerIter{T}} <: TimeStructOuterIter{T} Type for iterating through the individual operational scenarios of a [`StrategicPeriod`](@ref) time structure with [`RepresentativePeriods`](@ref). It is automatically created through the function [`opscenarios`](@ref). """ -struct StratReprOpscenarios{OP} +struct StratReprOpScens{T,OP<:TimeStructInnerIter{T}} <: TimeStructOuterIter{T} sp::Int rp::Int mult_sp::Float64 @@ -195,16 +198,16 @@ struct StratReprOpscenarios{OP} opscens::OP end -_strat_per(oscs::StratReprOpscenarios) = oscs.sp -_rper(oscs::StratReprOpscenarios) = oscs.rp +_strat_per(oscs::StratReprOpScens) = oscs.sp +_rper(oscs::StratReprOpScens) = oscs.rp -mult_strat(oscs::StratReprOpscenarios) = oscs.mult_sp -mult_repr(oscs::StratReprOpscenarios) = oscs.mult_rp +mult_strat(oscs::StratReprOpScens) = oscs.mult_sp +mult_repr(oscs::StratReprOpScens) = oscs.mult_rp -_oper_it(oscs::StratReprOpscenarios) = oscs.opscens +_oper_struct(oscs::StratReprOpScens) = oscs.opscens function opscenarios(rp::StratReprPeriod{T,RepresentativePeriod{T,OP}}) where {T,OP} - return StratReprOpscenarios( + return StratReprOpScens( _strat_per(rp), _rper(rp), mult_strat(rp), @@ -218,7 +221,7 @@ end """ When the `TimeStructure` is a [`StrategicPeriod`](@ref) with [`RepresentativePeriods`](@ref), -`opscenarios` returns a vector of [`StratReprOpscenario`](@ref)s. +`opscenarios` returns a vector of [`StratReprOpScenario`](@ref)s. """ function opscenarios( sp::StrategicPeriod{S1,T,RepresentativePeriods{S2,T,OP}}, @@ -227,39 +230,42 @@ function opscenarios( end # Provide a constructor to simplify the design -function StratReprOpscenario(oscs::StratReprOpscenarios, scen, per) - return StratReprOpscenario( +function StratReprOpScenario(oscs::StratReprOpScens, scen, per) + return StratReprOpScenario( _strat_per(oscs), _rper(oscs), scen, mult_strat(oscs), mult_repr(oscs), + mult_scen(per), probability(per), per, ) end # Add basic functions of iterators -Base.length(oscs::StratReprOpscenarios) = length(_oper_it(oscs)) -function Base.eltype(_::Type{StratReprOpscenarios{SC}}) where {T,OP,SC<:OpScens{T,OP}} - return StratReprOpscenario{T,eltype(SC)} -end -function Base.iterate(oscs::StratReprOpscenarios, state = (nothing, 1)) - next = isnothing(state[1]) ? iterate(_oper_it(oscs)) : iterate(_oper_it(oscs), state[1]) +Base.length(oscs::StratReprOpScens) = length(_oper_struct(oscs)) +function Base.eltype(_::Type{StratReprOpScens{SC}}) where {T,OP,SC<:OpScens{T,OP}} + return StratReprOpScenario{T,eltype(SC)} +end +function Base.iterate(oscs::StratReprOpScens, state = (nothing, 1)) + next = + isnothing(state[1]) ? iterate(_oper_struct(oscs)) : + iterate(_oper_struct(oscs), state[1]) isnothing(next) && return nothing - return StratReprOpscenario(oscs, state[2], next[1]), (next[2], state[2] + 1) + return StratReprOpScenario(oscs, state[2], next[1]), (next[2], state[2] + 1) end -function Base.getindex(oscs::StratReprOpscenarios, index::Int) - per = _oper_it(oscs)[index] - return StratReprOpscenario(oscs, _opscen(per), per) +function Base.getindex(oscs::StratReprOpScens, index::Int) + per = _oper_struct(oscs)[index] + return StratReprOpScenario(oscs, _opscen(per), per) end -function Base.eachindex(oscs::StratReprOpscenarios) - return eachindex(_oper_it(oscs)) +function Base.eachindex(oscs::StratReprOpScens) + return eachindex(_oper_struct(oscs)) end -function Base.last(oscs::StratReprOpscenarios) - per = last(_oper_it(oscs)) - return StratReprOpscenario(oscs, _opscen(per), per) +function Base.last(oscs::StratReprOpScens) + per = last(_oper_struct(oscs)) + return StratReprOpScenario(oscs, _opscen(per), per) end """ @@ -269,14 +275,14 @@ correct behavior based on the substructure. opscenarios(ts::SingleStrategicPeriod) = opscenarios(ts.ts) """ When the `TimeStructure` is a [`TwoLevel`](@ref), `opscenarios` returns a vector of -[`StratOperationalScenario`](@ref)s. +[`StratOpScenario`](@ref)s. """ function opscenarios(ts::TwoLevel{S,T,OP}) where {S,T,OP} return collect(Iterators.flatten(opscenarios(sp) for sp in strategic_periods(ts))) end """ When the `TimeStructure` is a [`TwoLevel`](@ref) with [`RepresentativePeriods`](@ref), -`opscenarios` returns a vector of [`StratReprOpscenario`](@ref)s. +`opscenarios` returns a vector of [`StratReprOpScenario`](@ref)s. """ function opscenarios(ts::TwoLevel{S1,T,RepresentativePeriods{S2,T,OP}}) where {S1,S2,T,OP} return collect( diff --git a/src/op_scenarios/tree_periods.jl b/src/op_scenarios/tree_periods.jl index 9a20e88..3fdd45f 100644 --- a/src/op_scenarios/tree_periods.jl +++ b/src/op_scenarios/tree_periods.jl @@ -1,15 +1,14 @@ """ - struct StratNodeOperationalScenario{T,OP<:TimeStructure{T}} <: AbstractOperationalScenario{T} + struct StratNodeOpScenario{T,OP<:TimeStructure{T}} <: AbstractOperationalScenario{T} A structure representing a single operational scenario for a strategic node supporting iteration over its time periods. It is created through iterating through [`StratNodeOpScens`](@ref). -It is equivalent to a [`StratOperationalScenario`](@ref) of a [`TwoLevel`](@ref) time +It is equivalent to a [`StratOpScenario`](@ref) of a [`TwoLevel`](@ref) time structure when utilizing a [`TwoLevelTree`](@ref). """ -struct StratNodeOperationalScenario{T,OP<:TimeStructure{T}} <: - AbstractOperationalScenario{T} +struct StratNodeOpScenario{T,OP<:TimeStructure{T}} <: AbstractOperationalScenario{T} sp::Int branch::Int scen::Int @@ -20,49 +19,46 @@ struct StratNodeOperationalScenario{T,OP<:TimeStructure{T}} <: operational::OP end -_strat_per(osc::StratNodeOperationalScenario) = osc.sp -_branch(osc::StratNodeOperationalScenario) = osc.branch -_opscen(osc::StratNodeOperationalScenario) = osc.scen +_strat_per(osc::StratNodeOpScenario) = osc.sp +_branch(osc::StratNodeOpScenario) = osc.branch +_opscen(osc::StratNodeOpScenario) = osc.scen -mult_strat(osc::StratNodeOperationalScenario) = osc.mult_sp -mult_scen(osc::StratNodeOperationalScenario) = osc.mult_scen -probability(osc::StratNodeOperationalScenario) = osc.prob_branch * prob_scen -probability_branch(osc::StratNodeOperationalScenario) = osc.prob_branch +mult_strat(osc::StratNodeOpScenario) = osc.mult_sp +mult_scen(osc::StratNodeOpScenario) = osc.mult_scen +probability(osc::StratNodeOpScenario) = osc.prob_branch * prob_scen +probability_branch(osc::StratNodeOpScenario) = osc.prob_branch -_oper_struct(osc::StratNodeOperationalScenario) = osc.operational +_oper_struct(osc::StratNodeOpScenario) = osc.operational # Provide a constructor to simplify the design -function TreePeriod( - osc::StratNodeOperationalScenario, - per::P, -) where {P<:Union{TimePeriod,AbstractOperationalScenario}} +function TreePeriod(osc::StratNodeOpScenario, per::TimePeriod) mult = mult_strat(osc) * multiple(per) - return TreePeriod(_strat_per(osc), _branch(osc), probability_branch(osc), mult, per) + return TreePeriod(_strat_per(osc), _branch(osc), per, mult, probability_branch(osc)) end -function StrategicTreeIndexable(::Type{<:StratNodeOperationalScenario}) +function StrategicTreeIndexable(::Type{<:StratNodeOpScenario}) return HasStratTreeIndex() end -StrategicIndexable(::Type{<:StratNodeOperationalScenario}) = HasStratIndex() +StrategicIndexable(::Type{<:StratNodeOpScenario}) = HasStratIndex() # Adding methods to existing Julia functions -function Base.show(io::IO, osc::StratNodeOperationalScenario) +function Base.show(io::IO, osc::StratNodeOpScenario) return print(io, "sp$(_strat_per(osc))-br$(_branch(osc))-sc$(_opscen(osc))") end -Base.eltype(_::StratNodeOperationalScenario) = TreePeriod +Base.eltype(_::StratNodeOpScenario{T,OP}) where {T,OP} = TreePeriod{eltype(op)} """ - struct StratNodeOpScens <: AbstractTreeStructure + struct StratNodeOpScens{T,OP<:TimeStructInnerIter{T}} <: AbstractTreeStructure{T} Type for iterating through the individual operational scenarios of a [`StratNode`](@ref). It is automatically created through the function [`opscenarios`](@ref). """ -struct StratNodeOpScens <: AbstractTreeStructure +struct StratNodeOpScens{T,OP<:TimeStructInnerIter{T}} <: AbstractTreeStructure{T} sp::Int branch::Int mult_sp::Float64 prob_branch::Float64 - opscens::Any + opscens::OP end _strat_per(oscs::StratNodeOpScens) = oscs.sp @@ -88,7 +84,7 @@ function opscenarios(n::StratNode{S,T,OP}) where {S,T,OP<:TimeStructure{T}} end function strat_node_period(oscs::StratNodeOpScens, next, state) - return StratNodeOperationalScenario( + return StratNodeOpScenario( _strat_per(oscs), _branch(oscs), state, @@ -100,7 +96,7 @@ function strat_node_period(oscs::StratNodeOpScens, next, state) ) end -Base.eltype(_::StratNodeOpScens) = StratNodeOperationalScenario +Base.eltype(_::StratNodeOpScens) = StratNodeOpScenario """ struct StratNodeReprOpScenario{T} <: AbstractOperationalScenario{T} @@ -142,13 +138,10 @@ end ScenarioIndexable(::Type{<:StratNodeReprOpScenario}) = HasScenarioIndex() # Provide a constructor to simplify the design -function TreePeriod( - osc::StratNodeReprOpScenario, - per::P, -) where {P<:Union{TimePeriod,AbstractOperationalScenario}} +function TreePeriod(osc::StratNodeReprOpScenario, per::TimePeriod) rper = ReprPeriod(_rper(osc), per, mult_repr(osc) * multiple(per)) mult = mult_strat(osc) * mult_repr(osc) * multiple(per) - return TreePeriod(_strat_per(osc), _branch(osc), probability_branch(osc), mult, rper) + return TreePeriod(_strat_per(osc), _branch(osc), rper, mult, probability_branch(osc)) end # Adding methods to existing Julia functions @@ -158,23 +151,23 @@ function Base.show(io::IO, osc::StratNodeReprOpScenario) "sp$(_strat_per(osc))-br$(_branch(osc))-rp$(_rper(osc))-sc$(_opscen(osc))", ) end -Base.eltype(_::StratNodeReprOpScenario) = TreePeriod +Base.eltype(_::StratNodeReprOpScenario{T,OP}) where {T,OP} = TreePeriod{eltype(op)} """ - struct StratNodeReprOpScens <: AbstractTreeStructure + struct StratNodeReprOpScens{T,OP<:TimeStructInnerIter{T}} <: AbstractTreeStructure{T} Type for iterating through the individual operational scenarios of a [`StratNodeReprPeriod`](@ref). It is automatically created through the function [`opscenarios`](@ref). """ -struct StratNodeReprOpScens <: AbstractTreeStructure +struct StratNodeReprOpScens{T,OP<:TimeStructInnerIter{T}} <: AbstractTreeStructure{T} sp::Int branch::Int rp::Int mult_sp::Float64 mult_rp::Float64 prob_branch::Float64 - opscens::Any + opscens::OP end _strat_per(oscs::StratNodeReprOpScens) = oscs.sp @@ -245,11 +238,11 @@ end """ When the `TimeStructure` is a [`TwoLevelTree`](@ref), `opscenarios` returns an `Array` of -all [`StratNodeOperationalScenario`](@ref)s or [`StratNodeReprOpScenario`](@ref)s types, +all [`StratNodeOpScenario`](@ref)s or [`StratNodeReprOpScenario`](@ref)s types, dependening on whether the [`TwoLevelTree`](@ref) includes [`RepresentativePeriods`](@ref) or not. -These are equivalent to a [`StratOperationalScenario`](@ref) and [`StratReprOpscenario`](@ref) +These are equivalent to a [`StratOpScenario`](@ref) and [`StratReprOpScenario`](@ref) of a [`TwoLevel`](@ref) time structure. """ function opscenarios(ts::TwoLevelTree) diff --git a/src/representative/core_types.jl b/src/representative/core_types.jl index 77fa15a..77f9752 100644 --- a/src/representative/core_types.jl +++ b/src/representative/core_types.jl @@ -156,7 +156,7 @@ function Base.last(rpers::RepresentativePeriods) end """ - ReprPeriod{P} <: TimePeriod where {P<:TimePeriod} + struct ReprPeriod{P} <: TimePeriod where {P<:TimePeriod} Time period for a single operational period. It is created through iterating through a [`RepresentativePeriods`](@ref) time structure. It is as well created as period within @@ -165,20 +165,22 @@ Time period for a single operational period. It is created through iterating thr struct ReprPeriod{P} <: TimePeriod where {P<:TimePeriod} rp::Int period::P - mult::Float64 + multiple::Float64 end -_oper(t::ReprPeriod) = _oper(t.period) -_opscen(t::ReprPeriod) = _opscen(t.period) +_period(t::ReprPeriod) = t.period + +_oper(t::ReprPeriod) = _oper(_period(t)) +_opscen(t::ReprPeriod) = _opscen(_period(t)) _rper(t::ReprPeriod) = t.rp -isfirst(t::ReprPeriod) = isfirst(t.period) -duration(t::ReprPeriod) = duration(t.period) -multiple(t::ReprPeriod) = t.mult -probability(t::ReprPeriod) = probability(t.period) +isfirst(t::ReprPeriod) = isfirst(_period(t)) +duration(t::ReprPeriod) = duration(_period(t)) +multiple(t::ReprPeriod) = t.multiple +probability(t::ReprPeriod) = probability(_period(t)) -Base.show(io::IO, t::ReprPeriod) = print(io, "rp$(t.rp)-$(t.period)") +Base.show(io::IO, t::ReprPeriod) = print(io, "rp$(t.rp)-$(_period(t))") function Base.isless(t1::ReprPeriod, t2::ReprPeriod) - return t1.rp < t2.rp || (t1.rp == t2.rp && t1.period < t2.period) + return _rper(t1) < _rper(t2) || (_rper(t1) == _rper(t2) && _period(t1) < _period(t2)) end # Convenience constructor for the type diff --git a/src/representative/rep_periods.jl b/src/representative/rep_periods.jl index e7c7e91..6b3a3b9 100644 --- a/src/representative/rep_periods.jl +++ b/src/representative/rep_periods.jl @@ -1,5 +1,5 @@ """ - AbstractRepresentativePeriod{T} <: TimeStructure{T} + abstract type AbstractRepresentativePeriod{T} <: TimeStructure{T} Abstract type used for time structures that represent a representative period. These periods are obtained when iterating through the representative periods of a time @@ -28,7 +28,7 @@ RepresentativeIndexable(::Type{<:AbstractRepresentativePeriod}) = HasReprIndex() RepresentativeIndexable(::Type{<:TimePeriod}) = HasReprIndex() """ - SingleReprPeriod{T,OP<:TimeStructure{T}} <: AbstractRepresentativePeriod{T} + struct SingleReprPeriod{T,OP<:TimeStructure{T}} <: AbstractRepresentativePeriod{T} A type representing a single representative period supporting iteration over its time periods. It is created when iterating through [`SingleReprPeriodWrapper`](@ref). @@ -52,16 +52,18 @@ Base.eltype(::Type{SingleReprPeriod{T,OP}}) where {T,OP} = eltype(OP) Base.last(rp::SingleReprPeriod) = last(rp.ts) """ - SingleReprPeriodWrapper{T,OP<:TimeStructure{T}} <: TimeStructure{T} + struct SingleReprPeriodWrapper{T,OP<:TimeStructure{T}} <: TimeStructInnerIter{T} Type for iterating through the individual representative periods of a time structure without [`RepresentativePeriods`](@ref). It is automatically created through the function [`repr_periods`](@ref). """ -struct SingleReprPeriodWrapper{T,OP<:TimeStructure{T}} <: TimeStructure{T} +struct SingleReprPeriodWrapper{T,OP<:TimeStructure{T}} <: TimeStructInnerIter{T} ts::OP end +_oper_struct(rpers::SingleReprPeriodWrapper) = rpers.ts + # Add basic functions of iterators Base.length(rpers::SingleReprPeriodWrapper) = 1 function Base.eltype(::Type{SingleReprPeriodWrapper{T,OP}}) where {T,OP} @@ -69,9 +71,9 @@ function Base.eltype(::Type{SingleReprPeriodWrapper{T,OP}}) where {T,OP} end function Base.iterate(rpers::SingleReprPeriodWrapper, state = nothing) !isnothing(state) && return nothing - return SingleReprPeriod(rpers.ts), 1 + return SingleReprPeriod(_oper_struct(rpers)), 1 end -Base.last(rpers::SingleReprPeriodWrapper) = SingleReprPeriod(rpers.ts) +Base.last(rpers::SingleReprPeriodWrapper) = SingleReprPeriod(_oper_struct(rpers)) """ repr_periods(ts::TimeStructure) @@ -86,10 +88,10 @@ When the `TimeStructure` is a `TimeStructure`, `repr_periods` returns a repr_periods(ts::TimeStructure) = SingleReprPeriodWrapper(ts) """ - RepresentativePeriod{T,OP<:TimeStructure{T}} <: AbstractRepresentativePeriod{T} + struct RepresentativePeriod{T,OP<:TimeStructure{T}} <: AbstractRepresentativePeriod{T} A type representing a single representative period supporting iteration over its -time periods. It is created when iterating through [`ReprPeriods`](@ref). +time periods. It is created when iterating through [`ReprPers`](@ref). """ struct RepresentativePeriod{T,OP<:TimeStructure{T}} <: AbstractRepresentativePeriod{T} rp::Int @@ -104,10 +106,7 @@ mult_repr(rp::RepresentativePeriod) = rp.mult_rp Base.show(io::IO, rp::RepresentativePeriod) = print(io, "rp-$(_rper(rp))") # Provide a constructor to simplify the design -function ReprPeriod( - rp::RepresentativePeriod, - per::P, -) where {P<:Union{TimePeriod,TimeStructure}} +function ReprPeriod(rp::RepresentativePeriod, per::TimePeriod) mult = mult_repr(rp) * multiple(per) return ReprPeriod(_rper(rp), per, mult) end @@ -136,46 +135,48 @@ function Base.last(rp::RepresentativePeriod) end """ - ReprPeriods{S,T,OP} + struct ReprPers{S,T,OP} <: TimeStructInnerIter{T} Type for iterating through the individual representative periods of a [`RepresentativePeriods`](@ref) time structure. It is automatically created through the function [`repr_periods`](@ref). """ -struct ReprPeriods{S,T,OP} +struct ReprPers{S,T,OP} <: TimeStructInnerIter{T} ts::RepresentativePeriods{S,T,OP} end +_oper_struct(rpers::ReprPers) = rpers.ts + """ When the `TimeStructure` is a [`RepresentativePeriods`](@ref), `repr_periods` returns the -iterator [`ReprPeriods`](@ref). +iterator [`ReprPers`](@ref). """ -repr_periods(ts::RepresentativePeriods) = ReprPeriods(ts) +repr_periods(ts::RepresentativePeriods) = ReprPers(ts) # Provide a constructor to simplify the design -function RepresentativePeriod(rpers::ReprPeriods, per::Int) +function RepresentativePeriod(rpers::ReprPers, per::Int) return RepresentativePeriod( per, - _multiple_adj(rpers.ts, per), - rpers.ts.rep_periods[per], + _multiple_adj(_oper_struct(rpers), per), + _oper_struct(rpers).rep_periods[per], ) end # Add basic functions of iterators -Base.length(rpers::ReprPeriods) = rpers.ts.len -function Base.eltype(_::ReprPeriods{S,T,OP}) where {S,T,OP<:TimeStructure{T}} +Base.length(rpers::ReprPers) = _oper_struct(rpers).len +function Base.eltype(_::ReprPers{S,T,OP}) where {S,T,OP<:TimeStructure{T}} return RepresentativePeriod{T,OP} end -function Base.iterate(rpers::ReprPeriods, state = nothing) +function Base.iterate(rpers::ReprPers, state = nothing) per = isnothing(state) ? 1 : state + 1 per > length(rpers) && return nothing return RepresentativePeriod(rpers, per), per end -function Base.getindex(rpers::ReprPeriods, index::Int) +function Base.getindex(rpers::ReprPers, index::Int) return RepresentativePeriod(rpers, index) end -function Base.eachindex(rpers::ReprPeriods) - return eachindex(rpers.ts.rep_periods) +function Base.eachindex(rpers::ReprPers) + return eachindex(_oper_struct(rpers).rep_periods) end -Base.last(rpers::ReprPeriods) = RepresentativePeriod(rpers, length(rpers)) +Base.last(rpers::ReprPers) = RepresentativePeriod(rpers, length(rpers)) diff --git a/src/representative/strat_periods.jl b/src/representative/strat_periods.jl index d6dae00..e20fa16 100644 --- a/src/representative/strat_periods.jl +++ b/src/representative/strat_periods.jl @@ -1,8 +1,8 @@ """ - StratReprPeriod{T,OP<:TimeStructure{T}} <: AbstractRepresentativePeriod{T} + struct StratReprPeriod{T,OP<:TimeStructure{T}} <: AbstractRepresentativePeriod{T} A type representing a single representative period supporting iteration over its -time periods. It is created when iterating through [`StratReprPeriods`](@ref). +time periods. It is created when iterating through [`StratReprPers`](@ref). """ struct StratReprPeriod{T,OP<:TimeStructure{T}} <: AbstractRepresentativePeriod{T} sp::Int @@ -12,12 +12,12 @@ struct StratReprPeriod{T,OP<:TimeStructure{T}} <: AbstractRepresentativePeriod{T operational::OP end -_rper(rp::StratReprPeriod) = rp.rp _strat_per(rp::StratReprPeriod) = rp.sp +_rper(rp::StratReprPeriod) = rp.rp -multiple(rp::StratReprPeriod, t::OperationalPeriod) = t.multiple / rp.mult_sp -mult_repr(rp::StratReprPeriod) = rp.mult_rp mult_strat(rp::StratReprPeriod) = rp.mult_sp +mult_repr(rp::StratReprPeriod) = rp.mult_rp +multiple(rp::StratReprPeriod, t::OperationalPeriod) = t.multiple / rp.mult_sp StrategicIndexable(::Type{<:StratReprPeriod}) = HasStratIndex() @@ -33,7 +33,7 @@ end # Add basic functions of iterators Base.length(rp::StratReprPeriod) = length(rp.operational) -Base.eltype(_::Type{StratReprPeriod{T,OP}}) where {T,OP} = OperationalPeriod +Base.eltype(_::Type{StratReprPeriod{T,OP}}) where {T,OP} = OperationalPeriod{eltype(OP)} function Base.iterate(rp::StratReprPeriod, state = nothing) next = isnothing(state) ? iterate(rp.operational) : iterate(rp.operational, state) isnothing(next) && return nothing @@ -53,47 +53,55 @@ function Base.last(rp::StratReprPeriod) end """ - StratReprPeriods{OP} + struct StratReprPers{T,OP<:TimeStructInnerIter{T}} <: TimeStructOuterIter{T} Type for iterating through the individual representative periods of a [`StrategicPeriod`](@ref) time structure. It is automatically created through the function [`repr_periods`](@ref). """ -struct StratReprPeriods{OP} +struct StratReprPers{T,OP<:TimeStructInnerIter{T}} <: TimeStructOuterIter{T} sp::Int mult_sp::Float64 repr::OP end +_strat_per(rpers::StratReprPers) = rpers.sp + +mult_strat(rpers::StratReprPers) = rpers.mult_sp + +_oper_struct(rpers::StratReprPers) = rpers.repr + """ When the `TimeStructure` is a [`StrategicPeriod`](@ref), `repr_periods` returns the iterator -[`StratReprPeriods`](@ref). +[`StratReprPers`](@ref). """ function repr_periods(sp::StrategicPeriod{S,T,OP}) where {S,T,OP} - return StratReprPeriods(_strat_per(sp), mult_strat(sp), repr_periods(sp.operational)) + return StratReprPers(_strat_per(sp), mult_strat(sp), repr_periods(sp.operational)) end # Provide a constructor to simplify the design -function StratReprPeriod(rpers::StratReprPeriods, state, per) - return StratReprPeriod(rpers.sp, state, rpers.mult_sp, mult_repr(per), per) +function StratReprPeriod(rpers::StratReprPers, state, per) + return StratReprPeriod(_strat_per(rpers), state, mult_strat(rpers), mult_repr(per), per) end # Add basic functions of iterators -Base.length(rpers::StratReprPeriods) = length(rpers.repr) -function Base.iterate(rpers::StratReprPeriods, state = (nothing, 1)) - next = isnothing(state[1]) ? iterate(rpers.repr) : iterate(rpers.repr, state[1]) +Base.length(rpers::StratReprPers) = length(_oper_struct(rpers)) +function Base.iterate(rpers::StratReprPers, state = (nothing, 1)) + next = + isnothing(state[1]) ? iterate(_oper_struct(rpers)) : + iterate(_oper_struct(rpers), state[1]) isnothing(next) && return nothing return StratReprPeriod(rpers, state[2], next[1]), (next[2], state[2] + 1) end -function Base.getindex(rpers::StratReprPeriods, index::Int) +function Base.getindex(rpers::StratReprPers, index::Int) return StratReprPeriod(rpers, index) end -function Base.eachindex(rpers::StratReprPeriods) - return eachindex(rpers.repr) +function Base.eachindex(rpers::StratReprPers) + return eachindex(_oper_struct(rpers)) end -function Base.last(rpers::StratReprPeriods) - per = last(rpers.repr) +function Base.last(rpers::StratReprPers) + per = last(_oper_struct(rpers)) return StratReprPeriod(rpers, _rper(per), per) end diff --git a/src/representative/tree_periods.jl b/src/representative/tree_periods.jl index 21e13a9..eae9865 100644 --- a/src/representative/tree_periods.jl +++ b/src/representative/tree_periods.jl @@ -2,7 +2,7 @@ struct StratNodeReprPeriod{T,OP<:TimeStructure{T}} <: AbstractRepresentativePeriod{T} A structure representing a single representative period of a [`StratNode`](@ref) of a -[`TwoLevelTree`](@ref). It is created through iterating through [`StratNodeReprPeriods`](@ref). +[`TwoLevelTree`](@ref). It is created through iterating through [`StratNodeReprPers`](@ref). It is equivalent to a [`StratReprPeriod`](@ref) of a [`TwoLevel`](@ref) time structure when utilizing a [`TwoLevelTree`](@ref). @@ -23,58 +23,55 @@ _rper(rp::StratNodeReprPeriod) = rp.rp mult_strat(rp::StratNodeReprPeriod) = rp.mult_sp mult_repr(rp::StratNodeReprPeriod) = rp.mult_rp -probability_branch(rp::StratNodeReprPeriod) = rp.prob_branch -probability(rp::StratNodeReprPeriod) = rp.prob_branch function multiple(rp::StratNodeReprPeriod, t::OperationalPeriod) return t.multiple / rp.mult_sp end +probability_branch(rp::StratNodeReprPeriod) = rp.prob_branch +probability(rp::StratNodeReprPeriod) = rp.prob_branch StrategicTreeIndexable(::Type{<:StratNodeReprPeriod}) = HasStratTreeIndex() StrategicIndexable(::Type{<:StratNodeReprPeriod}) = HasStratIndex() # Provide a constructor to simplify the design -function TreePeriod( - rp::StratNodeReprPeriod, - per::P, -) where {P<:Union{TimePeriod,AbstractRepresentativePeriod}} +function TreePeriod(rp::StratNodeReprPeriod, per::TimePeriod) mult = mult_strat(rp) * multiple(per) - return TreePeriod(_strat_per(rp), _branch(rp), probability_branch(rp), mult, per) + return TreePeriod(_strat_per(rp), _branch(rp), per, mult, probability_branch(rp)) end # Adding methods to existing Julia functions function Base.show(io::IO, rp::StratNodeReprPeriod) return print(io, "sp$(_strat_per(rp))-br$(_branch(rp))-rp$(_rper(rp))") end -Base.eltype(_::StratNodeReprPeriod) = TreePeriod +Base.eltype(_::StratNodeReprPeriod{T,OP}) where {T,OP} = TreePeriod{eltype(op)} """ - struct StratNodeReprPeriods <: AbstractTreeStructure + struct StratNodeReprPers{T,OP<:TimeStructInnerIter{T}} <: AbstractTreeStructure{T} Type for iterating through the individual presentative periods of a [`StratNode`](@ref). It is automatically created through the function [`repr_periods`](@ref). """ -struct StratNodeReprPeriods <: AbstractTreeStructure +struct StratNodeReprPers{T,OP<:TimeStructInnerIter{T}} <: AbstractTreeStructure{T} sp::Int branch::Int mult_sp::Float64 prob_branch::Float64 - repr::Any + repr::OP end -_strat_per(rps::StratNodeReprPeriods) = rps.sp -_branch(rps::StratNodeReprPeriods) = rps.branch +_strat_per(rps::StratNodeReprPers) = rps.sp +_branch(rps::StratNodeReprPers) = rps.branch -mult_strat(rps::StratNodeReprPeriods) = rps.mult_sp -probability_branch(rps::StratNodeReprPeriods) = rps.prob_branch +mult_strat(rps::StratNodeReprPers) = rps.mult_sp +probability_branch(rps::StratNodeReprPers) = rps.prob_branch -_oper_struct(rps::StratNodeReprPeriods) = rps.repr +_oper_struct(rps::StratNodeReprPers) = rps.repr """ When the `TimeStructure` is a [`StratNode`](@ref), `repr_periods` returns the iterator -[`StratNodeReprPeriods`](@ref). +[`StratNodeReprPers`](@ref). """ function repr_periods(n::StratNode{S,T,OP}) where {S,T,OP<:TimeStructure{T}} - return StratNodeReprPeriods( + return StratNodeReprPers( _strat_per(n), _branch(n), mult_strat(n), @@ -83,7 +80,7 @@ function repr_periods(n::StratNode{S,T,OP}) where {S,T,OP<:TimeStructure{T}} ) end -function strat_node_period(rps::StratNodeReprPeriods, next, state) +function strat_node_period(rps::StratNodeReprPers, next, state) return StratNodeReprPeriod( _strat_per(rps), _branch(rps), @@ -95,7 +92,7 @@ function strat_node_period(rps::StratNodeReprPeriods, next, state) ) end -Base.eltype(_::StratNodeReprPeriods) = StratNodeReprPeriod +Base.eltype(_::StratNodeReprPers) = StratNodeReprPeriod """ When the `TimeStructure` is a [`TwoLevelTree`](@ref), `repr_periods` returns an `Array` of diff --git a/src/strat_scenarios/core_types.jl b/src/strat_scenarios/core_types.jl index f61fd34..e862ea5 100644 --- a/src/strat_scenarios/core_types.jl +++ b/src/strat_scenarios/core_types.jl @@ -71,35 +71,36 @@ respective branch and probability of the branch struct TreePeriod{P} <: TimePeriod where {P<:TimePeriod} sp::Int branch::Int - prob_branch::Float64 - multiple::Float64 period::P + multiple::Float64 + prob_branch::Float64 end +_period(t::TreePeriod) = t.period _strat_per(t::TreePeriod) = t.sp _branch(t::TreePeriod) = t.branch +_rper(t::TreePeriod) = _rper(_period(t)) +_opscen(t::TreePeriod) = _opscen(_period(t)) +_oper(t::TreePeriod) = _oper(_period(t)) -_rper(t::TreePeriod) = _rper(t.period) -_opscen(t::TreePeriod) = _opscen(t.period) -_oper(t::TreePeriod) = _oper(t.period) - -isfirst(t::TreePeriod) = isfirst(t.period) -duration(t::TreePeriod) = duration(t.period) +isfirst(t::TreePeriod) = isfirst(_period(t)) +duration(t::TreePeriod) = duration(_period(t)) multiple(t::TreePeriod) = t.multiple probability_branch(t::TreePeriod) = t.prob_branch -probability(t::TreePeriod) = probability(t.period) * probability_branch(t) +probability(t::TreePeriod) = probability(_period(t)) * probability_branch(t) function Base.show(io::IO, t::TreePeriod) - return print(io, "sp$(t.sp)-br$(t.branch)-$(t.period)") + return print(io, "sp$(_strat_per(t))-br$(_branch(t))-$(_period(t))") end function Base.isless(t1::TreePeriod, t2::TreePeriod) - return t1.period < t2.period + return _strat_per(t1) < _strat_per(t2) || + (_strat_per(t1) == _strat_per(t2) && _period(t1) < _period(t2)) end # Convenient constructors for the individual types -function TreePeriod(n::StratNode, per::P) where {P<:Union{TimePeriod,TimeStructure}} +function TreePeriod(n::StratNode, per::TimePeriod) mult = n.mult_sp * multiple(per) - return TreePeriod(_strat_per(n), _branch(n), probability_branch(n), mult, per) + return TreePeriod(_strat_per(n), _branch(n), per, mult, probability_branch(n)) end """ struct StrategicScenario @@ -198,8 +199,8 @@ function add_node( sp, branches(tree, sp) + 1, duration, - prob_branch, mult_sp, + prob_branch, parent, oper, ) @@ -240,7 +241,7 @@ function regular_tree( end """ - struct StratTreeNodes{S, T, OP} <: AbstractTreeStructure + struct StratTreeNodes{S,T,OP<:TimeStructure{T}} <: AbstractTreeStructure{T} Type for iterating through the individual strategic nodes of a [`TwoLevelTree`](@ref). It is automatically created through the function [`strat_periods`](@ref), and hence, @@ -249,7 +250,7 @@ It is automatically created through the function [`strat_periods`](@ref), and he Iterating through `StratTreeNodes` using the `WithPrev` iterator changes the behaviour, although the meaning remains unchanged. """ -struct StratTreeNodes{S,T,OP} <: AbstractTreeStructure +struct StratTreeNodes{S,T,OP<:TimeStructure{T}} <: AbstractTreeStructure{T} ts::TwoLevelTree{S,T,OP} end diff --git a/src/strat_scenarios/tree_periods.jl b/src/strat_scenarios/tree_periods.jl index aad0915..17940d8 100644 --- a/src/strat_scenarios/tree_periods.jl +++ b/src/strat_scenarios/tree_periods.jl @@ -1,16 +1,16 @@ """ - AbstractTreeNode{S,T} <: AbstractStrategicPeriod{S,T} + abstract type AbstractTreeNode{S,T} <: AbstractStrategicPeriod{S,T} Abstract base type for all tree nodes within a [`TwoLevelTree`](@ref) type. """ abstract type AbstractTreeNode{S,T} <: AbstractStrategicPeriod{S,T} end """ - AbstractTreeStructure + abstract type AbstractTreeStructure{T} <: TimeStructOuterIter{T} Abstract base type for all tree timestructures within a [`TwoLevelTree`](@ref) type. """ -abstract type AbstractTreeStructure end +abstract type AbstractTreeStructure{T} <: TimeStructOuterIter{T} end Base.length(ats::AbstractTreeStructure) = length(_oper_struct(ats)) function Base.iterate(ats::AbstractTreeStructure, state = (nothing, 1)) @@ -43,8 +43,8 @@ struct StratNode{S,T,OP<:TimeStructure{T}} <: AbstractTreeNode{S,T} sp::Int branch::Int duration::S - prob_branch::Float64 mult_sp::Float64 + prob_branch::Float64 parent::Any operational::OP end diff --git a/src/strategic/core_types.jl b/src/strategic/core_types.jl index a53f03f..0f496b0 100644 --- a/src/strategic/core_types.jl +++ b/src/strategic/core_types.jl @@ -167,7 +167,7 @@ end function Base.length(ts::TwoLevel) return sum(length(op) for op in ts.operational) end -Base.eltype(::Type{TwoLevel{S,T,OP}}) where {S,T,OP} = OperationalPeriod +Base.eltype(::Type{TwoLevel{S,T,OP}}) where {S,T,OP} = OperationalPeriod{eltype(OP)} function Base.iterate(ts::TwoLevel, state = (nothing, 1)) sp = state[2] next = @@ -188,32 +188,34 @@ function Base.last(ts::TwoLevel) end """ - struct OperationalPeriod <: TimePeriod + struct OperationalPeriod{P} <: TimePeriod where {P<:TimePeriod} Time period for a single operational period. It is created through iterating through a [`TwoLevel`](@ref) time structure. """ -struct OperationalPeriod <: TimePeriod +struct OperationalPeriod{P} <: TimePeriod where {P<:TimePeriod} sp::Int - period::TimePeriod + period::P multiple::Float64 end +_period(t::OperationalPeriod) = t.period -_oper(t::OperationalPeriod) = _oper(t.period) -_opscen(t::OperationalPeriod) = _opscen(t.period) -_rper(t::OperationalPeriod) = _rper(t.period) _strat_per(t::OperationalPeriod) = t.sp +_rper(t::OperationalPeriod) = _rper(_period(t)) +_opscen(t::OperationalPeriod) = _opscen(_period(t)) +_oper(t::OperationalPeriod) = _oper(_period(t)) -isfirst(t::OperationalPeriod) = isfirst(t.period) -duration(t::OperationalPeriod) = duration(t.period) +isfirst(t::OperationalPeriod) = isfirst(_period(t)) +duration(t::OperationalPeriod) = duration(_period(t)) multiple(t::OperationalPeriod) = t.multiple -probability(t::OperationalPeriod) = probability(t.period) +probability(t::OperationalPeriod) = probability(_period(t)) function Base.show(io::IO, t::OperationalPeriod) - return print(io, "sp$(t.sp)-$(t.period)") + return print(io, "sp$(_strat_per(t))-$(_period(t))") end function Base.isless(t1::OperationalPeriod, t2::OperationalPeriod) - return t1.sp < t2.sp || (t1.sp == t2.sp && t1.period < t2.period) + return _strat_per(t1) < _strat_per(t2) || + (_strat_per(t1) == _strat_per(t2) && _period(t1) < _period(t2)) end # Convenience constructor for the type diff --git a/src/strategic/strat_periods.jl b/src/strategic/strat_periods.jl index ea43cec..09d5218 100644 --- a/src/strategic/strat_periods.jl +++ b/src/strategic/strat_periods.jl @@ -1,5 +1,5 @@ """ - AbstractStrategicPeriod{S,T} <: TimeStructure{T} + abstract type AbstractStrategicPeriod{S,T} <: TimeStructure{T} Abstract type used for time structures that represent a strategic period. These periods are obtained when iterating through the strategic periods of a time @@ -44,7 +44,7 @@ function remaining(sp::AbstractStrategicPeriod, ts::TimeStructure) end """ - SingleStrategicPeriodWrapper{T,SP<:TimeStructure{T}} <: AbstractStrategicPeriod{T,T} + struct SingleStrategicPeriodWrapper{T,SP<:TimeStructure{T}} <: AbstractStrategicPeriod{T,T} A type representing a single strategic period supporting iteration over its time periods. It is created when iterating through [`SingleStrategicPeriodWrapper`](@ref). @@ -68,16 +68,18 @@ end Base.last(sp::SingleStrategicPeriod) = last(sp.ts) """ - SingleStrategicPeriodWrapper{T,SP<:TimeStructure{T}} <: TimeStructure{T} + struct SingleStrategicPeriodWrapper{T,SP<:TimeStructure{T}} <: TimeStructInnerIter{T} Type for iterating through the individual strategic periods of a time structure without [`TwoLevel`](@ref). It is automatically created through the function [`strat_periods`](@ref). """ -struct SingleStrategicPeriodWrapper{T,SP<:TimeStructure{T}} <: TimeStructure{T} +struct SingleStrategicPeriodWrapper{T,SP<:TimeStructure{T}} <: TimeStructInnerIter{T} ts::SP end +_oper_struct(sps::SingleStrategicPeriodWrapper) = sps.ts + """ strat_periods(ts::TimeStructure) @@ -101,18 +103,18 @@ strategic_periods(ts) = strat_periods(ts) Base.length(sps::SingleStrategicPeriodWrapper) = 1 function Base.iterate(sps::SingleStrategicPeriodWrapper, state = nothing) !isnothing(state) && return nothing - return SingleStrategicPeriod(sps.ts), 1 + return SingleStrategicPeriod(_oper_struct(sps)), 1 end function Base.eltype(::Type{SingleStrategicPeriodWrapper{T,SP}}) where {T,SP} return SingleStrategicPeriod{T,SP} end -Base.last(sps::SingleStrategicPeriodWrapper) = SingleStrategicPeriod(sps.ts) +Base.last(sps::SingleStrategicPeriodWrapper) = SingleStrategicPeriod(_oper_struct(sps)) """ - StrategicPeriod{S,T,OP<:TimeStructure{T}} <: AbstractStrategicPeriod{S,T} + struct StrategicPeriod{S,T,OP<:TimeStructure{T}} <: AbstractStrategicPeriod{S,T} A type representing a single strategic period supporting iteration over its -time periods. It is created when iterating through [`StratPeriods`](@ref). +time periods. It is created when iterating through [`StratPers`](@ref). """ struct StrategicPeriod{S,T,OP<:TimeStructure{T}} <: AbstractStrategicPeriod{S,T} sp::Int @@ -136,7 +138,7 @@ end # Add basic functions of iterators Base.length(sp::StrategicPeriod) = length(sp.operational) function Base.eltype(_::Type{StrategicPeriod{S,T,OP}}) where {S,T,OP} - return OperationalPeriod + return OperationalPeriod{eltype(OP)} end function Base.iterate(sp::StrategicPeriod, state = nothing) next = isnothing(state) ? iterate(sp.operational) : iterate(sp.operational, state) @@ -173,23 +175,25 @@ end multiple_strat(sp::StrategicPeriod, t) = multiple(t) / duration_strat(sp) """ - StratPeriods{S,T,OP} + struct StratPers{S,T,OP} <:TimeStructInnerIter{T} Type for iterating through the individual strategic periods of a [`TwoLevel`](@ref) time structure. It is automatically created through the function [`strat_periods`](@ref). """ -struct StratPeriods{S,T,OP} +struct StratPers{S,T,OP} <: TimeStructInnerIter{T} ts::TwoLevel{S,T,OP} end -function remaining(sp::AbstractStrategicPeriod, sps::StratPeriods) +_oper_struct(sps::StratPers) = sps.ts + +function remaining(sp::AbstractStrategicPeriod, sps::StratPers) return sum(duration_strat(spp) for spp in sps if spp >= sp) end """ When the `TimeStructure` is a [`TwoLevel`](@ref), `strat_periods` returns the -iterator [`StratPeriods`](@ref). +iterator [`StratPers`](@ref). ## Example ```julia @@ -197,35 +201,35 @@ periods = TwoLevel(5, SimpleTimes(10,1)) total_dur = sum(duration_strat(sp) for sp in strategic_periods(periods)) ``` """ -strat_periods(ts::TwoLevel) = StratPeriods(ts) +strat_periods(ts::TwoLevel) = StratPers(ts) # Provide a constructor to simplify the design -function StrategicPeriod(sps::StratPeriods, sp::Int) +function StrategicPeriod(sps::StratPers, sp::Int) return StrategicPeriod( sp, - sps.ts.duration[sp], - _multiple_adj(sps.ts, sp), - sps.ts.operational[sp], + _oper_struct(sps).duration[sp], + _multiple_adj(_oper_struct(sps), sp), + _oper_struct(sps).operational[sp], ) end # Add basic functions of iterators -Base.length(sps::StratPeriods) = sps.ts.len -function Base.eltype(_::StratPeriods{S,T,OP}) where {S,T,OP<:TimeStructure{T}} +Base.length(sps::StratPers) = _oper_struct(sps).len +function Base.eltype(_::StratPers{S,T,OP}) where {S,T,OP<:TimeStructure{T}} return StrategicPeriod{S,T,OP} end -function Base.iterate(sps::StratPeriods, state = nothing) +function Base.iterate(sps::StratPers, state = nothing) sp = isnothing(state) ? 1 : state + 1 sp > length(sps) && return nothing return StrategicPeriod(sps, sp), sp end -function Base.getindex(sps::StratPeriods, index::Int) +function Base.getindex(sps::StratPers, index::Int) return StrategicPeriod(sps, index) end -function Base.eachindex(sps::StratPeriods) - return eachindex(sps.ts.rep_periods) +function Base.eachindex(sps::StratPers) + return eachindex(_oper_struct(sps).rep_periods) end -function Base.last(sps::StratPeriods) +function Base.last(sps::StratPers) return StrategicPeriod(sps, length(sps)) end diff --git a/src/structures.jl b/src/structures.jl index a8166e5..bc2d9c3 100644 --- a/src/structures.jl +++ b/src/structures.jl @@ -2,7 +2,7 @@ Duration = Number """ - abstract type TimeStructure{T} + abstract type TimeStructure{T<:Duration} Abstract type representing different time structures that consists of one or more time periods. The type 'T' gives @@ -10,6 +10,36 @@ the data type used for the duration of the time periods. """ abstract type TimeStructure{T<:Duration} end +""" + abstract type TimeStructInnerIter{T<:Duration} + +Abstract type representing different iterators for individual time structures. +The difference to [`TimeStructure`](@ref) is that iterating through a `TimeStructInnerIter` +will not provide a [`TimePeriod`](@ref), but a [`TimeStructure`](@ref). + +!!! note + `TimeStructInnerIter` and [`TimeStructOuterIter`](@ref) are comparable. The + former is implemented for the inner level, that is if you want to use, _e.g._, + `opscenarios(OperationalScenarios())` while the latter is used for the outer level, + _e.g._, `opscenarios(StrategicPeriod())`. +""" +abstract type TimeStructInnerIter{T<:Duration} end + +""" + abstract type TimeStructOuterIter{T<:Duration} + +Abstract type representing different iterators for individual time structures. +The difference to [`TimeStructure`](@ref) is that iterating through a `TimeStructOuterIter` +will not provide a [`TimePeriod`](@ref), but a [`TimeStructure`](@ref). + +!!! note + [`TimeStructInnerIter`](@ref) and `TimeStructOuterIter` are comparable. The + former is implemented for the inner level, that is if you want to use, _e.g._, + `opscenarios(OperationalScenarios())` while the latter is used for the outer level, + _e.g._, `opscenarios(StrategicPeriod())`. +""" +abstract type TimeStructOuterIter{T<:Duration} end + """ abstract type TimePeriod diff --git a/src/utils.jl b/src/utils.jl index 4b9438f..4144c3e 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -135,8 +135,7 @@ function expand_dataframe!(df, periods) end # All introduced subtypes require the same procedures for the iteration and indexing. # Hence, all introduced types use the same functions. -TreeStructure = - Union{StratNodeOperationalScenario,StratNodeReprPeriod,StratNodeReprOpScenario} +TreeStructure = Union{StratNodeOpScenario,StratNodeReprPeriod,StratNodeReprOpScenario} Base.length(ts::TreeStructure) = length(ts.operational) function Base.last(ts::TreeStructure) per = last(ts.operational) diff --git a/test/runtests.jl b/test/runtests.jl index 8ac9c4a..1d07778 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -116,7 +116,7 @@ end week = SimpleTimes(168, 1) ts = OperationalScenarios(3, [day, day, week], [0.1, 0.2, 0.7]) - @test first(ts) == TimeStruct.ScenarioPeriod(1, 0.1, 7.0, TimeStruct.SimplePeriod(1, 1)) + @test first(ts) == TimeStruct.ScenarioPeriod(1, TimeStruct.SimplePeriod(1, 1), 7.0, 0.1) @test length(ts) == 216 pers = [] for sc in opscenarios(ts) @@ -133,7 +133,7 @@ end # resolution and the same probability of occuring ts = OperationalScenarios([day, week]) - @test first(ts) == TimeStruct.ScenarioPeriod(1, 0.5, 7.0, TimeStruct.SimplePeriod(1, 1)) + @test first(ts) == TimeStruct.ScenarioPeriod(1, TimeStruct.SimplePeriod(1, 1), 7.0, 0.5) @test length(ts) == 192 scens = opscenarios(ts) @@ -189,7 +189,7 @@ end @test rps[1] < rps[2] @test rps[1] < rps[25] - # Test of direct functions of `ReprPeriods` + # Test of direct functions of `ReprPers` rpers = repr_periods(rep) @test eltype(rpers) == TimeStruct.RepresentativePeriod{Int,SimpleTimes{Int}} @test last(rpers) == collect(rpers)[end] @@ -477,7 +477,7 @@ end ops = collect(seasonal_year) @test ops[1] == TimeStruct.OperationalPeriod( 1, - TimeStruct.ScenarioPeriod(1, 0.1, 7.0, TimeStruct.SimplePeriod(1, 1)), + TimeStruct.ScenarioPeriod(1, TimeStruct.SimplePeriod(1, 1), 7.0, 0.1), 91.0, ) @@ -524,7 +524,7 @@ end sp = first(strat_periods(ts)) scen = first(opscenarios(sp)) @test length(scen) == 10 - @test eltype(typeof(scen)) == TimeStruct.OperationalPeriod + @test eltype(typeof(scen)) == TimeStruct.OperationalPeriod{TimeStruct.SimplePeriod{Int}} @test repr(scen) == "sp1-sc1" @test probability(scen) == 1.0 per = first(scen)