Skip to content

New version for chunks #94

@JulStraus

Description

@JulStraus

Problem statement

While we have in the current iteration the potential of including chunks, both based on length and based on the duration, there is in my opinion an interesting additional functionality which could be represented, chunks where the time period within one chunk is not present in another chunk.

Consider the following example:

ts = TwoLevel(1,1, SimpleTimes([1, 2, 3, 6, 1, 1, 1, 1, 1, 1]))
t_inv = first(strategic_periods(ts))

Utilizing chunk(t_inv, 3) on the system provides us with iterators containing the following periods

[sp1-t1, sp1-t2, sp1-t3]
[sp1-t2, sp1-t3, sp1-t4]
[sp1-t3, sp1-t4, sp1-t5]
[sp1-t4, sp1-t5, sp1-t6]
[sp1-t5, sp1-t6, sp1-t7]
[sp1-t6, sp1-t7, sp1-t8]
[sp1-t7, sp1-t8, sp1-t9]
[sp1-t8, sp1-t9, sp1-t10]
[sp1-t9, sp1-t10]
[sp1-t10]

while chunk_duration(t_inv,6) leads to:

[sp1-t1, sp1-t2, sp1-t3]
[sp1-t2, sp1-t3, sp1-t4]
[sp1-t3, sp1-t4]
[sp1-t4]
[sp1-t5, sp1-t6, sp1-t7, sp1-t8, sp1-t9, sp1-t10]
[sp1-t6, sp1-t7, sp1-t8, sp1-t9, sp1-t10]
[sp1-t7, sp1-t8, sp1-t9, sp1-t10]
[sp1-t8, sp1-t9, sp1-t10]
[sp1-t9, sp1-t10]
[sp1-t10]

I would be interested in non repetitive periods, i.e.,

[sp1-t1, sp1-t2, sp1-t3]
[sp1-t4, sp1-t5, sp1-t6]
[sp1-t7, sp1-t8, sp1-t9]
[sp1-t10]

and

[sp1-t1, sp1-t2, sp1-t3]
[sp1-t4]
[sp1-t5, sp1-t6, sp1-t7, sp1-t8, sp1-t9, sp1-t10]

This is in general a bit more tricky to utilize, as

  1. the length of the iterator is not known beforehand, even if it could be deduced and
  2. if the TimeStructure and the chosen number of periods (or their duration) is not consistent.

However, I still think it can be rather beneficial to include this also as it can be good for, e.g., demand that must be satisfied within a given period but the exact time is is satisfied is not important. Examples for this behavior is given by the PeriodDemandSink or CapacityCostLink.

Potential solution

In theory, this can be implemented quite fast, e.g., as

struct ChunkDurationTest{I}
    itr::I
    duration::TS.Duration
end
function Base.iterate(w::ChunkDurationTest, state = nothing)
    n = isnothing(state) ? iterate(w.itr) : iterate(w.itr, state)
    n === nothing && return n
    itr = w.itr
    next = TS.take_duration(isnothing(state) ? itr : Iterators.rest(itr, state...), w.duration)
    return next, n[2] + length(collect(next)) - 1
end

# With 
ChunkDurationTest(t_inv, 6)
# we receive
[sp1-t1, sp1-t2, sp1-t3]
[sp1-t4]
[sp1-t5, sp1-t6, sp1-t7, sp1-t8, sp1-t9, sp1-t10]

This is definitely not the most elegant approach, but it works. The onlydifference to ChunkDuration is related to the return of the next state as I take here as well the states which have passed already into account for defining the next state.

Is that fundamentally wrong through process for iterators? What are your thoughts @trulsf and @hellemo?

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request
No fields configured for Feature.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions