Closed jkrathore closed 5 years ago
If you need to allocate the tasks to the workers, so that, unlike in the 'house_building_calendar' example, a part of the decisions of the problem is to select one or several workers for a given task, then you should have a look at the 'alternative' constraint. There is an example in 'house_building_optional'. By default, the alternative constraint will select 1 alternative interval (so 1 worker) for each task but there is an extended version of the alternative constraint 'alternative(task, [taskOnWorker_1,taskOnWorker_2,...,taskOnWorker_n],n)' that permits to select 'n' intervals in the alternative. This is useful if you need to allocate the task to more than 1 worker.
Closing this since there is no activity in more than 3 months. Thanks
Hi All,
I beg your pardon, don't know is it a right forum to ask this question. I am working on a problem similar to house_building_calendar example mentioned in "docplex-examples/examples/cp/visu/house_building_calendar". In this example, each task has to be assigned to only one worker, what if I need one or more resources for same task, I have modified the existing code with three workers and trying to add a constraint to satisfy minimum workers required for each task, I believe it should be like "count of workers appended to a task should be less than or equal to number of workers required", however I am finding difficulty to implement it. Can somebody please assist me to write this sort of constraint. I have attached modified code here. Thank you
`from docplex.cp.model import CpoModel, CpoStepFunction import docplex.cp.utils_visu as visu
-----------------------------------------------------------------------------
Initialize the problem data
-----------------------------------------------------------------------------
House building task descriptor
class BuildingTask(object): def init(self, name, duration, noWorkers): self.name = name self.duration = duration self.noWorkers = noWorkers
List of tasks to be executed for each house
MASONRY = BuildingTask('masonry', 35, 2) CARPENTRY = BuildingTask('carpentry', 15, 1) PLUMBING = BuildingTask('plumbing', 40, 3) CEILING = BuildingTask('ceiling', 15, 2) ROOFING = BuildingTask('roofing', 5, 3) PAINTING = BuildingTask('painting', 10, 1) WINDOWS = BuildingTask('windows', 5, 2) FACADE = BuildingTask('facade', 10, 1) GARDEN = BuildingTask('garden', 5, 1) MOVING = BuildingTask('moving', 5, 2)
Tasks precedence constraints (each tuple (X, Y) means X ends before start of Y)
PRECEDENCES = ( (MASONRY, CARPENTRY), (MASONRY, PLUMBING), (MASONRY, CEILING), (CARPENTRY, ROOFING), (CEILING, PAINTING), (ROOFING, WINDOWS), (ROOFING, FACADE), (PLUMBING, FACADE), (ROOFING, GARDEN), (PLUMBING, GARDEN), (WINDOWS, MOVING), (FACADE, MOVING), (GARDEN, MOVING), (PAINTING, MOVING), )
Tasks assigned to Joe and Jim
JOE_TASKS = (MASONRY, CARPENTRY, ROOFING, FACADE, GARDEN, CEILING, PLUMBING) JIM_TASKS = (PLUMBING, CEILING, PAINTING, WINDOWS, MOVING, ROOFING) MIKE_TASKS = (MASONRY, CARPENTRY, ROOFING, WINDOWS, MOVING, PLUMBING)
Total number of houses to build
NUMBER_OF_HOUSES = 5
Max number of calendar years
MAX_YEARS = 2
Holydays for Joe and Jim as list of tuples (start_day_index, end_day_index)
JOE_HOLYDAYS = ((5, 12), (124, 131), (215, 236), (369, 376), (495, 502), (579, 600)) JIM_HOLYDAYS = ((26, 40), (201, 225), (306, 313), (397, 411), (565, 579)) MIKE_TASKS = ((26, 40), (201, 225), (306, 313), (397, 411), (565, 579))
-----------------------------------------------------------------------------
Prepare the data for modeling
-----------------------------------------------------------------------------
Assign an index to tasks
ALL_TASKS = (MASONRY, CARPENTRY, PLUMBING, CEILING, ROOFING, PAINTING, WINDOWS, FACADE, GARDEN, MOVING) for i in range(len(ALL_TASKS)): ALL_TASKS[i].id = i
Initialize availability calendar for workers
joe_calendar = CpoStepFunction() jim_calendar = CpoStepFunction() mike_calendar = CpoStepFunction() joe_calendar.set_value(0, MAX_YEARS 365, 100) jim_calendar.set_value(0, MAX_YEARS 365, 100) mike_calendar.set_value(0, MAX_YEARS * 365, 100)
Remove week ends
for w in range(MAX_YEARS 52): joe_calendar.set_value(5 + (7 w), 7 + (7 w), 0) jim_calendar.set_value(5 + (7 w), 7 + (7 w), 0) mike_calendar.set_value(5 + (7 w), 7 + (7 * w), 0)
Remove holidays
for b, e in JOE_HOLYDAYS: joe_calendar.set_value(b, e, 0) for b, e in JIM_HOLYDAYS: jim_calendar.set_value(b, e, 0) for b, e in MIKE_HOLYDAYS: mike_calendar.set_value(b, e, 0)
-----------------------------------------------------------------------------
Build the model
-----------------------------------------------------------------------------
Create model
mdl = CpoModel()
Initialize model variable sets
all_tasks = [] # Array of all tasks joe_tasks = [] # Tasks assigned to Joe jim_tasks = [] # Tasks assigned to Jim mike_tasks = [] # Tasks assigned to Mike house_finish_times = [] # Array of house finishing times type = dict()
Utility function
def make_house(loc): ''' Create model elements corresponding to the building of one house loc: Identification (index) of the house to build '''
Make houses
for i in range(NUMBER_OF_HOUSES): make_house(i)
Avoid each worker tasks overlapping
mdl.add(mdl.no_overlap(joe_tasks)) mdl.add(mdl.no_overlap(jim_tasks)) mdl.add(mdl.no_overlap(mike_tasks))
Add minimization objective
mdl.add(mdl.minimize(mdl.max(house_finish_times)))
-----------------------------------------------------------------------------
Solve the model and display the result
-----------------------------------------------------------------------------
def compact(name):
Example: H3-garden -> G3
Solve model
print("Solving model....") msol = mdl.solve(TimeLimit=10) print("Solution: ") msol.print_solution()
Display result
if msol and visu.is_visu_enabled(): visu.timeline('Solution SchedCalendar') visu.panel() visu.pause(joe_calendar) visu.sequence(name='Joe', intervals=[(msol.get_var_solution(t), type[t], compact(t.name)) for t in joe_tasks]) visu.panel() visu.pause(jim_calendar) visu.sequence(name='Jim', intervals=[(msol.get_var_solution(t), type[t], compact(t.name)) for t in jim_tasks]) visu.panel() visu.pause(mike_calendar) visu.sequence(name='Mike', intervals=[(msol.get_var_solution(t), type[t], compact(t.name)) for t in mike_tasks]) visu.show()`