def test_create_task_variable_duration(self) -> None: pb = ps.SchedulingProblem("CreateVariableDurationTask") ps.VariableDurationTask("vdt1") vdt_2 = ps.VariableDurationTask("vdt2", max_duration=4) vdt_3 = ps.VariableDurationTask("vdt3", min_duration=5) solver = ps.SchedulingSolver(pb) solution = solver.solve() self.assertTrue(solution) self.assertTrue(solution.tasks[vdt_2.name].duration <= 4) self.assertTrue(solution.tasks[vdt_3.name].duration >= 5)
def test_create_task_variable_duration_from_list(self) -> None: pb = ps.SchedulingProblem("CreateVariableDurationTaskFromList") vdt_1 = ps.VariableDurationTask("vdt1", allowed_durations=[3, 4]) vdt_2 = ps.VariableDurationTask("vdt2", allowed_durations=[5, 6]) vdt_3 = ps.VariableDurationTask("vdt3", allowed_durations=[7, 8]) solver = ps.SchedulingSolver(pb) solution = solver.solve() self.assertTrue(solution) self.assertTrue(solution.tasks[vdt_1.name].duration in [3, 4]) self.assertTrue(solution.tasks[vdt_2.name].duration in [5, 6]) self.assertTrue(solution.tasks[vdt_3.name].duration in [7, 8])
def test_nested_boolean_operators(self) -> None: new_problem_or_clear() t_1 = ps.VariableDurationTask("t1") or_constraint_1 = ps.or_([ps.TaskStartAt(t_1, 1), ps.TaskStartAt(t_1, 2)]) or_constraint_2 = ps.or_([ps.TaskStartAt(t_1, 4), ps.TaskStartAt(t_1, 5)]) and_constraint = ps.and_([or_constraint_1, or_constraint_2]) self.assertIsInstance(and_constraint, ps.BoolRef)
def test_print_objects(self) -> None: new_problem_or_clear() t1 = ps.FixedDurationTask("task_1", duration=1) t2 = ps.VariableDurationTask("task_2") worker_1 = ps.Worker("W1") self.assertTrue("task_1" in "%s" % t1) self.assertTrue("task_2" in "%s" % t2) self.assertTrue("W1" in "%s" % worker_1)
def test_force_schedule_optional_tasks_3(self) -> None: """Check an error is raised if ever one of the task is not optional.""" ps.SchedulingProblem("ForceScheduleOptionalTasks3", horizon=14) task_1 = ps.VariableDurationTask("task1") # this one is not optional task_2 = ps.FixedDurationTask("task2", duration=7, optional=True) with self.assertRaises(TypeError): ps.ForceScheduleNOptionalTasks([task_1, task_2], 2)
def test_task_duration_depend_on_start(self) -> None: pb = ps.SchedulingProblem("TaskDurationDependsOnStart", horizon=30) task_1 = ps.VariableDurationTask("Task1") task_2 = ps.VariableDurationTask("Task2") ps.TaskStartAt(task_1, 5) pb.add_constraint(task_1.duration == task_1.start * 3) ps.TaskStartAt(task_2, 11) pb.add_constraint( ps.if_then_else(task_2.start < 10, [task_2.duration == 3], [task_2.duration == 1])) solver = ps.SchedulingSolver(pb) solution = solver.solve() self.assertTrue(solution) self.assertEqual(solution.tasks["Task1"].duration, 15) self.assertEqual(solution.tasks["Task2"].duration, 1)
def test_cumulative_productivity(self): """Horizon should be 4, 100/29=3.44.""" problem = ps.SchedulingProblem("CumulativeProductivity") t_1 = ps.VariableDurationTask("t1", work_amount=100) worker_1 = ps.CumulativeWorker("CumulWorker", size=3, productivity=29) t_1.add_required_resource(worker_1) problem.add_objective_makespan() solution = ps.SchedulingSolver(problem).solve() self.assertTrue(solution) self.assertEqual(solution.horizon, 4)
def test_work_amount_2(self): # try the same problem than above, but with one more resource # check that the task duration is lower problem = ps.SchedulingProblem("WorkAmount", horizon=4) task_1 = ps.VariableDurationTask("task1", work_amount=11) # create two workers worker_1 = ps.Worker("Worker1", productivity=2) worker_2 = ps.Worker("Worker2", productivity=3) task_1.add_required_resources([worker_1, worker_2]) # solve self.assertTrue(_solve_problem(problem))
def test_work_amount_1(self): problem = ps.SchedulingProblem("WorkAmount") task_1 = ps.VariableDurationTask("task1", work_amount=11) # create one worker with a productivity of 2 worker_1 = ps.Worker("Worker1", productivity=2) task_1.add_required_resource(worker_1) # solve solution = _solve_problem(problem) self.assertTrue(solution) # the expected duration for task 1 is 6 self.assertEqual(solution.tasks[task_1.name].duration, 6)
def test_schedule_single_variable_duration_task(self) -> None: problem = ps.SchedulingProblem("SingleVariableDurationTaskScheduling") task = ps.VariableDurationTask("task") # add two constraints to set start and end ps.TaskStartAt(task, 1) ps.TaskEndAt(task, 4) solution = _solve_problem(problem) self.assertTrue(solution) # task should have been scheduled with start at 0 # and end at 2 task_solution = solution.tasks[task.name] self.assertEqual(task_solution.start, 1) self.assertEqual(task_solution.duration, 3) self.assertEqual(task_solution.end, 4)
def test_json_export_1(self): pb = ps.SchedulingProblem("JSONExport1", horizon=10) # tasks task_1 = ps.FixedDurationTask("task1", duration=3) task_2 = ps.VariableDurationTask("task2") task_3 = ps.ZeroDurationTask("task3") # buffers buffer_1 = ps.NonConcurrentBuffer("Buffer1", initial_state=10) buffer_2 = ps.NonConcurrentBuffer("Buffer2", initial_state=0) # resources worker_1 = ps.Worker("Worker1") worker_2 = ps.Worker("Worker2") worker_3 = ps.Worker("Worker3") sw_1 = ps.SelectWorkers([worker_1, worker_2, worker_3]) sw_2 = ps.SelectWorkers([worker_1, worker_2, worker_3]) sw_3 = ps.SelectWorkers([worker_1, worker_2, worker_3]) ps.CumulativeWorker("CumulMachine1", size=3) ps.CumulativeWorker("CumulMachine2", size=7) # assign resources to tasks task_1.add_required_resources([worker_1, worker_2]) task_2.add_required_resource(sw_1) task_3.add_required_resource(sw_2) # task constraints ps.TaskPrecedence(task_1, task_2) ps.TaskStartAt(task_1, 5) ps.TaskUnloadBuffer(task_1, buffer_1, quantity=3) ps.TaskLoadBuffer(task_1, buffer_2, quantity=2) # resource constraints ps.SameWorkers(sw_1, sw_2) ps.DistinctWorkers(sw_2, sw_3) ps.WorkLoad(worker_1, {(0, 6): 3, (19, 24): 4}, kind="exact") ps.ResourceUnavailable(worker_1, [(1, 3), (6, 8)]) ps.ResourceTasksDistance(worker_1, distance=4, mode="exact", list_of_time_intervals=[[10, 18]]) # export to json solver = ps.SchedulingSolver(pb) ps.export_json_to_file(pb, solver, "test_export_1.json")
def test_constant_cost_per_period_2(self) -> None: problem = ps.SchedulingProblem( "IndicatorResourceConstantCostPerPeriod12") t_1 = ps.VariableDurationTask("t1", work_amount=100) worker_1 = ps.Worker("Worker1", productivity=4, cost=ps.ConstantCostPerPeriod(10)) worker_2 = ps.Worker("Worker2", productivity=7, cost=ps.ConstantCostPerPeriod(20)) all_workers = [worker_1, worker_2] problem.add_objective_makespan() t_1.add_required_resources(all_workers) cost_ind = problem.add_indicator_resource_cost(all_workers) solution = ps.SchedulingSolver(problem).solve() self.assertTrue(solution) self.assertEqual(solution.indicators[cost_ind.name], 300)
def test_task_types(self) -> None: new_problem_or_clear() with self.assertRaises(TypeError): ps.VariableDurationTask("vdt5", max_duration=4.5) with self.assertRaises(TypeError): ps.VariableDurationTask("vdt6", max_duration=-1) with self.assertRaises(TypeError): ps.VariableDurationTask("vdt7", min_duration=-1) with self.assertRaises(TypeError): ps.VariableDurationTask("vdt8", work_amount=-1) with self.assertRaises(TypeError): ps.VariableDurationTask("vdt9", work_amount=1.5) with self.assertRaises(TypeError): ps.VariableDurationTask("vdt10", work_amount=None)
def test_force_schedule_optional_tasks_2(self) -> None: """Just change the number of tasks to be scheduled.""" pb = ps.SchedulingProblem("ForceScheduleOptionalTasks2", horizon=14) task_1 = ps.VariableDurationTask("task1", optional=True) task_2 = ps.FixedDurationTask("task2", duration=7, optional=True) task_3 = ps.FixedDurationTask("task3", duration=2, optional=True) ps.ForceScheduleNOptionalTasks([task_1, task_2, task_3], 2) solver = ps.SchedulingSolver(pb) solution = solver.solve() self.assertTrue(solution) results = [ solution.tasks[task_1.name].scheduled, solution.tasks[task_2.name].scheduled, solution.tasks[task_3.name].scheduled, ] self.assertEqual(results.count(True), 2)
def test_force_schedule_optional_tasks(self) -> None: """task_3 is not scheduled, because task_2 should not.""" pb = ps.SchedulingProblem("ForceScheduleOptionalTasks", horizon=9) task_1 = ps.VariableDurationTask("task1", optional=True) task_2 = ps.FixedDurationTask("task2", duration=4, optional=True) task_3 = ps.FixedDurationTask("task3", duration=1, optional=True) ps.ForceScheduleNOptionalTasks([task_1, task_2, task_3], 1) solver = ps.SchedulingSolver(pb) solution = solver.solve() self.assertTrue(solution) results = [ solution.tasks[task_1.name].scheduled, solution.tasks[task_2.name].scheduled, solution.tasks[task_3.name].scheduled, ] self.assertEqual(results.count(True), 1)
def test_task_same_names(self) -> None: new_problem_or_clear() ps.VariableDurationTask("t1") with self.assertRaises(ValueError): ps.VariableDurationTask("t1")