简体   繁体   中英

docplex - set an interval_var's size as a function of another variable

In IBM's docplex optimization library, can you set an interval_var 's size parameter as a function of another variable? Meaning, say for this example I wanted to make the task size dependent on the skill level of the worker. If the worker has a skill level of 2 and another worker has a skill level of 1, the task is completed twice as fast with the first worker. So the size parameter of the interval_var for that task should be the task.duration / skill_level .

It is typically set as an integer value based on the documentation, so I am wondering if there is a workaround to make this possible.

From the example:

Task = (namedtuple("Task", ["name", "duration"]))
TASKS = {Task("masonry",   35),
         Task("carpentry", 15),
         Task("plumbing",  40),
         Task("ceiling",   15),
         Task("roofing",    5),
         Task("painting",  10),
         Task("windows",    5),
         Task("facade",    10),
         Task("garden",     5),
         Task("moving",     5),
        }

tasks = {}   # dict of interval variable for each house and task
for house in HOUSES:
    for task in TASKS:
        tasks[(house, task)] = mdl.interval_var(start=period_domain,
                                                end=period_domain,
                                                size=task.duration,
                                                name="house {} task {}".format(house, task))

There are two possibilities:

1- In general, if you have to handle workers with different skills, you will have also to handle the allocation of tasks to workers in the scheduling problem. In this case, for a given tasks (for instance 'masonry') you will create one optional interval variable per possible worker (or per skill) and you will specify the skill-related duration on this interval variable. See for example the delivered Python example "house_building_optional.py" (though in this example, we assume the duration is worker independent). So you will end up with a pattern like:

tasks = [ interval_var(name='Task{}'.format(i)) for i in ... ]
tasksOnWorkers = [ [ interval_var(optional=True, size=DURATION[i,j], name='Task{}_Worker{}'.format(i,j)) for j in ...] for i in ... ]

model.add(alternative(tasks[i], [tasksOnWorkers[i][j] for j in ...]) for i in ...)

Stated otherwise, in the example you mention you would not specify the size here:

tasks[(house, task)] = mdl.interval_var(start=period_domain,
                                                end=period_domain,
                                                size=task.duration,
                                                name="house {} task {}".format(house, task))

But instead, here:

for house in HOUSES:
    for skill in SKILLS:
        iv = mdl.interval_var(name='H' + str(house) + '-' + skill.task + '(' + skill.worker + ')')
        iv.set_optional()
        wtasks[(house, skill)] = iv

2- The above method is the preferred one in case of resource allocation. But you can also use an integer expression length_of(intervalVar) to constrain the length of the interval:

x = interval_var() # By default length is unconstrained in [0,INTERVAL_MAX)

model.add(length_of(x) == 'Whatever integer expression or variable in the model')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM