1

Good Morning,

I'm trying to find a way to convert IntervalVars into a List of BooleanVars with or tools in order to use the binary list as a sort of field in which the booleans indicate where the Interval is located in the window between time 0 and horizon. I've got it working with just one Interval, i.e. when i print all Solutions it shows the interval in all possible positions:

all combination/solutions:

[
 [0, 0, 1, 1, 0], 
 [0, 1, 1, 0, 0], 
 [0, 0, 0, 1, 1], 
 [1, 1, 0, 0, 0]
]

working model:

    duration = 2
    horizon = 5
    model = cp_model.CpModel()

    bool_vars = []
    start_var = model.NewIntVar(0, horizon, "start")
    interval_var = model.NewFixedSizeIntervalVar(start_var, duration, "interval")

    for i in range(horizon):
        bool_var = model.NewBoolVar(f"bool_{i}")
        model.Add(interval_var.StartExpr() <= i).OnlyEnforceIf(bool_var)
        model.Add(interval_var.EndExpr() > i).OnlyEnforceIf(bool_var)
        bool_vars.append(bool_var)

    model.Add(sum(bool_vars) == duration)

Now if i try to extend this method to two intervals it doesn't work.

    durations = [1,2]
    horizon = 5
    model = cp_model.CpModel()

    bool_vars = [model.NewBoolVar(f"bool_{i}") for i in range(horizon)]

    for duration in durations:
        start_var = model.NewIntVar(0, horizon, f"start_{duration}")
        interval_var = model.NewFixedSizeIntervalVar(start_var, duration, f"interval_{duration}")
        for i in range(horizon):
            model.Add(interval_var.StartExpr() <= i).OnlyEnforceIf(bool_vars[i])
            model.Add(interval_var.EndExpr() > i).OnlyEnforceIf(bool_vars[i])
    model.Add(sum(bool_vars) == sum(durations))

I suspect its the lines

    model.Add(interval_var.StartExpr() <= i).OnlyEnforceIf(bool_var)
    model.Add(interval_var.EndExpr() > i).OnlyEnforceIf(bool_var)

I know theres something fundamental which I'm missing but I cant think of another solution at the moment

Any input and criticism is appreciated! <3

The concrete Problem I'm trying to solve in this current step is:

Modify the current method (utilizing Google OR Tools) such that: given a list of durations and a horizon, find all possible combinations. With the constraint that sequences are separated by a gap/pause with duration_of_gap >= 1.

Example 1:

inputs:
  durations = [1,2]
  horizon = 5
solution:
  combinations = [
 [1, 0, 1, 1, 0], 
 [1, 0, 0, 1, 1], 
 [0, 1, 0, 1, 1], 
]

Example 2:

inputs:
  durations = [3,1,2]
  horizon = 10
solution:
  combinations = [
    [1, 1, 1, 0, 1, 0, 1, 1, 0, 0],
    [1, 1, 1, 0, 1, 0, 0, 1, 1, 0],
    [1, 1, 1, 0, 1, 0, 0, 0, 1, 1],
    [1, 1, 1, 0, 0, 1, 0, 1, 1, 0],
    [1, 1, 1, 0, 0, 1, 0, 0, 1, 1],
    [1, 1, 1, 0, 0, 0, 1, 0, 1, 1],
    [0, 1, 1, 1, 0, 1, 0, 1, 1, 0],
    [0, 1, 1, 1, 0, 1, 0, 0, 1, 1],
    [0, 1, 1, 1, 0, 0, 1, 0, 1, 1],
    [0, 0, 1, 1, 1, 0, 1, 0, 1, 1]
]
m_c_frank
  • 46
  • 7
  • What does not work? You are aware, that you are only expressed one implication (direction of effects) of some equality? I guess you want to do something with `OnlyEnforceIf(bool_var.Not())` too. – sascha Jan 17 '22 at 10:15
  • For the current step i'm just trying to convert a list of intervals into an 1d list of binary vars. Example: I have two Intervals with durations of 1 and 3 which i want to fit into timeframe with say length 5 with a minimum gap of 1. One of the possible solutions is [1,0,1,1,1,0] another is [0,1,0,1,1,1] and so on. How can one map the booleans in the list to correspond to the intervals. – m_c_frank Jan 19 '22 at 16:28
  • That comment does not address anything from my comment. It even describes a different task than the original questions asks about. Then there is the approach itself... You look for *valid patterns*... I would go for *automata* or maybe something based on *circuits* (together with *disjunctive sched*). That channeling you try sounds *slow*. – sascha Jan 19 '22 at 16:33
  • In your example, you're creating 5 `bool_vars` and constraining their sum to be 3. These can represent neither of the two `interval_var` with durations 1 and 2. The `bool_vars` don't have a correspondence to a particular interval, the constraint `interval_var.StartExpr() <= i` will be enforced for both intervals if `bool_vars[i]` is true, and I suppose that is leading to infeasibility. You'd be better off directly constraining the gap between `interval_var1.StartExpr()` and `interval_var0.EndExpr()` – Christopher Hamkins Jan 24 '22 at 15:50
  • An even simpler solution would be to simply include the gap directly in the interval, i.e. create `IntervalVar` whose length is 1 larger than the given durations, and extend the horizon by 1 to allow for the gap at the end. Then a simple no-overlap constraint will be all you need; in the output just reduce the interval end by 1 to display the end of the desired task without the gap. – Christopher Hamkins Jan 25 '22 at 11:37
  • One more thing: the formulation of the "concrete problem" sounds like some kind of homework assignment. Asking about homework is generally discouraged on Stack Overflow. In any case, if you use these ideas, make sure to attribute "Solved with help of https://stackoverflow.com/questions/70728700/". – Christopher Hamkins Jan 25 '22 at 11:44

0 Answers0