Python CPSAT AddCumulative like constraint which forces equal and t depending capacity

544 views
Skip to first unread message

Philipp Schmette

unread,
Apr 3, 2020, 2:21:17 PM4/3/20
to or-tools...@googlegroups.com
hi :)
I would like to have a constraint which calculates the number of overlapping intervals at time t.
Like the AddCumulative constraint:

```python
    def AddCumulative(self, intervals, demands, capacity):
        """Adds Cumulative(intervals, demands, capacity).
    This constraint enforces that:
        for all t:
          sum(demands[i]
            if (start(intervals[t]) <= t < end(intervals[t])) and
            (t is present)) <= capacity
```
I would like to have a constraint which does the following
```python
    def AddXXX(self, intervals, demands, capacity):
       """
    This constraint enforces that:
        for all t:
          sum(demands[i]
            if (start(intervals[t]) <= t < end(intervals[t])) and
            (t is present)) == capacity[t]
```

At the moment I am using a boolean array for each interval which indicates if the index of the given boolean in the array is included in the interval. Afterwards I sum them up, but that seems to be quite slow if I add a lot of intervals.

How I calculate the array:
```
overlapping_table =[model.NewBoolVar("") for_ in range(...)]
interval = model.NewOptionalIntervalVar(start,duration,end,is_present,"")
model.Add(sum(is_working_table)==duration)
for t in range(0,24*4):
    over_bool = overlapping_table[t]#
    model.AddImplication(over_bool,is_present)
    model.Add(over_bool==0).OnlyEnforceIf(is_present.Not())

    model.Add(t >= start).OnlyEnforceIf([over_bool,is_present])
    model.Add(t < end).OnlyEnforceIf([over_bool,is_present])

    # As we already force the duration to be equal to the sum of the
    # working table we do not have to create the opposite constraint,
    # but it seems to be faster
    t_smaller = model.NewBoolVar("")
    model.Add(t < start).OnlyEnforceIf(t_smaller)
    model.Add(t >= start).OnlyEnforceIf(t_smaller.Not())
    model.Add(t < start).OnlyEnforceIf([over_bool.Not(),t_smaller,is_present])
    model.Add(t >= end).OnlyEnforceIf([over_bool.Not(),t_smaller.Not(),is_present])

#sum over all overlapping_tables for each index ...
```

How I tried to optimize it (a little bit off-topic):

I tried using `NewConstant(0/1)` instead of `NewBoolean` if I already know the result for the time t, but this did not change anything.

1. Are constant IntVars added to some cache in the presolver?
2: Is there a difference between creating a boolean variable and forcing it to be a value and creating a Constant?
3. Is it worth to use a number and not NewConstant? I am using .Not() a lot, but I could write a custom number wrapper, so it should be fine.

Thank you for your help

Phibedy

unread,
Apr 23, 2020, 4:25:29 PM4/23/20
to or-tools-discuss
Would be great if someone could answer questions 1,2,3 because I am kind of lost in the pre-solver code. I found a lot of constraints which can be presolved but I am missing the part where a variable with a domain size of 1 (after it was reduced by the presolver) is converted into a constant and removed.
Is there a way to get the model from the presolver/see somehow what the pre-solver did to the model?

Thank you for your time :)
Reply all
Reply to author
Forward
0 new messages