1

I would like to model a scheduling problem using constraint programming (Python API of CPLEX : docplex.cp) where I have machines to allocate to activities. Activities are performed during work shifts and some tasks can be divised in at most 3 parts but can also not be seperated into several parts. I use interval variables to model activities and optional interval variables (with "Alternative" constraints) to model equipement allocations. The different parts of a given tasks may be performed using different equipments or the same.

A naive approach might be to force the division of long activities but I would like to make sure that the model choose the division only when it is necessary.

Thanks in advance for your ideas and for the help!

1 Answers1

1

The best way is to create a chain of intervals and use logical primitives to use the lower indexed ones when less than the full number of segments is needed. Here is a code:

from docplex.cp.model import CpoModel

cp = CpoModel()

n = 3
total_duration = 100

itvs = [ cp.interval_var(optional=True, name="I_{}".format(i)) for i in range(n) ]

for i in range(1, n):
    cp.add(cp.end_before_start(itvs[i-1], itvs[i]))
    #cp.add(cp.presence_of(itvs[i-1]) >= cp.presence_of(itvs[i]))
    cp.add(cp.if_then(cp.presence_of(itvs[i]), cp.presence_of(itvs[i-1])))

cp.add(cp.sum(cp.length_of(itvs[i]) for i in range(n)) == total_duration)

cp.export_as_cpo("chain.cpo")

You will then have the following in the chain.cpo file:

#line 11 "chain.py"
I_1 = intervalVar(optional);
I_0 = intervalVar(optional);
I_2 = intervalVar(optional);

//--- Expressions ---
#line 11 "chain.py"
endBeforeStart(I_0, I_1);
#line 13
presenceOf(I_1) => presenceOf(I_0);
#line 11
endBeforeStart(I_1, I_2);
#line 13
presenceOf(I_2) => presenceOf(I_1);
#line 15
sum([lengthOf(I_0), lengthOf(I_1), lengthOf(I_2)]) == 100;
Paul Shaw
  • 36
  • 1