def test_resource_utilization_maximization_incremental_1(self) -> None: """Same as above, but both workers are selectable. Force one with resource utilization maximization objective.""" problem = ps.SchedulingProblem("IndicatorMaximizeIncremental", horizon=10) t_1 = ps.FixedDurationTask("T1", duration=5) t_2 = ps.FixedDurationTask("T2", duration=5) worker_1 = ps.Worker("Worker1") worker_2 = ps.Worker("Worker2") t_1.add_required_resource(ps.SelectWorkers([worker_1, worker_2])) t_2.add_required_resource(ps.SelectWorkers([worker_1, worker_2])) utilization_res_1 = problem.add_indicator_resource_utilization(worker_1) utilization_res_2 = problem.add_indicator_resource_utilization(worker_2) problem.maximize_indicator(utilization_res_1) solver = ps.SchedulingSolver(problem) solution = solver.solve() self.assertTrue(solution) self.assertEqual(solution.indicators[utilization_res_1.name], 100) self.assertEqual(solution.indicators[utilization_res_2.name], 0)
def test_all_same_distinct_workers(self): pb = ps.SchedulingProblem("AllSameDistinctWorkers") task_1 = ps.FixedDurationTask("task1", duration=2) task_2 = ps.FixedDurationTask("task2", duration=2) task_3 = ps.FixedDurationTask("task3", duration=2) task_4 = ps.FixedDurationTask("task4", duration=2) worker_1 = ps.Worker("John") worker_2 = ps.Worker("Bob") res_for_t1 = ps.SelectWorkers([worker_1, worker_2], 1) res_for_t2 = ps.SelectWorkers([worker_1, worker_2], 1) res_for_t3 = ps.SelectWorkers([worker_1, worker_2], 1) res_for_t4 = ps.SelectWorkers([worker_1, worker_2], 1) task_1.add_required_resource(res_for_t1) task_2.add_required_resource(res_for_t2) task_3.add_required_resource(res_for_t3) task_4.add_required_resource(res_for_t4) ps.SameWorkers(res_for_t1, res_for_t2) ps.SameWorkers(res_for_t3, res_for_t4) ps.DistinctWorkers(res_for_t2, res_for_t4) solver = ps.SchedulingSolver(pb) solution = solver.solve() self.assertTrue(solution) self.assertEqual(solution.horizon, 4)
def test_schedule_three_tasks_three_alternative_workers(self) -> None: problem = ps.SchedulingProblem("ThreeTasksThreeSelectWorkers") # two tasks task_1 = ps.FixedDurationTask("task1", duration=3) task_2 = ps.FixedDurationTask("task2", duration=2) task_3 = ps.FixedDurationTask("task3", duration=2) # three workers worker_1 = ps.Worker("worker1") worker_2 = ps.Worker("worker2") worker_3 = ps.Worker("worker3") all_workers = [worker_1, worker_2, worker_3] task_1.add_required_resource(ps.SelectWorkers(all_workers, 1)) task_2.add_required_resource(ps.SelectWorkers(all_workers, 2)) task_3.add_required_resource(ps.SelectWorkers(all_workers, 3)) solution = _solve_problem(problem) self.assertTrue(solution) # each task should have one worker assigned self.assertEqual(len(solution.tasks[task_1.name].assigned_resources), 1) self.assertEqual(len(solution.tasks[task_2.name].assigned_resources), 2) self.assertEqual(len(solution.tasks[task_3.name].assigned_resources), 3)
def test_create_select_workers(self) -> None: new_problem_or_clear() worker_1 = ps.Worker("wkr_1") worker_2 = ps.Worker("wkr_2") worker_3 = ps.Worker("wkr_3") single_alternative_workers = ps.SelectWorkers([worker_1, worker_2], 1) self.assertIsInstance(single_alternative_workers, ps.SelectWorkers) double_alternative_workers = ps.SelectWorkers([worker_1, worker_2, worker_3], 2) self.assertIsInstance(double_alternative_workers, ps.SelectWorkers)
def test_select_worker_wrong_number_of_workers(self) -> None: new_problem_or_clear() worker_1 = ps.Worker("wkr_1") worker_2 = ps.Worker("wkr_2") ps.SelectWorkers([worker_1, worker_2], 2) ps.SelectWorkers([worker_1, worker_2], 1) with self.assertRaises(ValueError): ps.SelectWorkers([worker_1, worker_2], 3) with self.assertRaises(TypeError): ps.SelectWorkers([worker_1, worker_2], -1)
def test_select_worker_bad_type(self) -> None: new_problem_or_clear() worker_1 = ps.Worker("wkr_1") self.assertIsInstance(worker_1, ps.Worker) worker_2 = ps.Worker("wkr_2") with self.assertRaises(ValueError): ps.SelectWorkers([worker_1, worker_2], 1, kind="ee")
def test_resource_utilization_indicator_2(self) -> None: """Two tasks, two workers.""" problem = ps.SchedulingProblem("IndicatorUtilization2", horizon=10) t_1 = ps.FixedDurationTask("T1", duration=5) t_2 = ps.FixedDurationTask("T2", duration=5) worker_1 = ps.Worker("Worker1") worker_2 = ps.Worker("Worker2") t_1.add_required_resource(worker_1) t_2.add_required_resource(ps.SelectWorkers([worker_1, worker_2])) utilization_res_1 = problem.add_indicator_resource_utilization( worker_1) utilization_res_2 = problem.add_indicator_resource_utilization( worker_2) solution = ps.SchedulingSolver(problem).solve() self.assertTrue(solution) result_res_1 = solution.indicators[utilization_res_1.name] result_res_2 = solution.indicators[utilization_res_2.name] # sum should be 100 self.assertEqual(result_res_1 + result_res_2, 100)
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_cumulative_select_worker_1(self): pb_bs = ps.SchedulingProblem("CumulativeSelectWorker", 2) # tasks t1 = ps.FixedDurationTask("T1", duration=2) t2 = ps.FixedDurationTask("T2", duration=2) # workers r1 = ps.CumulativeWorker("Machine1", size=2) r2 = ps.CumulativeWorker("Machine2", size=2) # resource assignment t1.add_required_resource(ps.SelectWorkers([r1, r2], 1)) t2.add_required_resource(ps.SelectWorkers([r1, r2], 1)) # plot solution solver = ps.SchedulingSolver(pb_bs) solution = solver.solve() self.assertTrue(solution)
def test_schedule_two_tasks_two_alternative_workers(self) -> None: problem = ps.SchedulingProblem("TwoTasksTwoSelectWorkers", horizon=4) # two tasks task_1 = ps.FixedDurationTask("task1", duration=3) task_2 = ps.FixedDurationTask("task2", duration=2) # two workers worker_1 = ps.Worker("worker1") worker_2 = ps.Worker("worker2") task_1.add_required_resource(ps.SelectWorkers([worker_1, worker_2], 1)) task_2.add_required_resource(ps.SelectWorkers([worker_1, worker_2], 1)) solution = _solve_problem(problem) self.assertTrue(solution) # each task should have one worker assigned task_1_solution = solution.tasks[task_1.name] task_2_solution = solution.tasks[task_2.name] self.assertEqual(len(task_1_solution.assigned_resources), 1) self.assertEqual(len(task_1_solution.assigned_resources), 1) self.assertFalse(task_1_solution.assigned_resources == task_2_solution.assigned_resources)
def get_problem(): digital_transformation = ps.SchedulingProblem("DigitalTransformation") print("Create model...", end="") r_a = [ps.Worker("A_%i" % (i + 1)) for i in range(num_resource_a)] r_b = [ps.Worker("B_%i" % (i + 1)) for i in range(num_resource_b)] # Dev Team Tasks # For each dev_team pick one resource a and one resource b. ts_team_migration = [ ps.FixedDurationTask("DevTeam_%i" % (i + 1), duration=1, priority=i % 3 + 1) for i in range(num_dev_teams) ] for t_team_migration in ts_team_migration: t_team_migration.add_required_resource(ps.SelectWorkers(r_a)) t_team_migration.add_required_resource(ps.SelectWorkers(r_b)) # solve digital_transformation.add_objective_priorities() digital_transformation.add_objective_flowtime() # digital_transformation.add_objective_makespan(weight=10) return digital_transformation
def test_optional_task_select_workers_2(self) -> None: pb = ps.SchedulingProblem("OptionalTaskSelectWorkers2") task_1 = ps.FixedDurationTask("task1", duration=3, optional=True) pb.add_constraint(ps.TaskStartAt(task_1, 1)) worker_1 = ps.Worker("Worker1") worker_2 = ps.Worker("Worker2") task_1.add_required_resource(ps.SelectWorkers([worker_1, worker_2], 1)) # Force schedule False pb.add_constraint(task_1.scheduled == False) solver = ps.SchedulingSolver(pb) solution = solver.solve() self.assertTrue(solution) self.assertFalse(solution.tasks[task_1.name].scheduled) self.assertEqual(len(solution.tasks[task_1.name].assigned_resources), 0)
def test_alternative_workers_2(self) -> None: # problem pb_alt = ps.SchedulingProblem("AlternativeWorkerExample") # tasks t1 = ps.FixedDurationTask("t1", duration=3) t2 = ps.FixedDurationTask("t2", duration=2) t3 = ps.FixedDurationTask("t3", duration=2) t4 = ps.FixedDurationTask("t4", duration=2) t5 = ps.FixedDurationTask("t5", duration=2) # resource requirements w1 = ps.Worker("W1") w2 = ps.Worker("W2") w3 = ps.Worker("W3") w4 = ps.SelectWorkers([w1, w2, w3], nb_workers_to_select=1, kind="exact") w5 = ps.SelectWorkers([w1, w2, w3], nb_workers_to_select=2, kind="max") w6 = ps.SelectWorkers([w1, w2, w3], nb_workers_to_select=3, kind="min") # resource assignment t1.add_required_resource(w1) # t1 only needs w1 t2.add_required_resource(w2) # t2 only needs w2 t3.add_required_resource(w4) # t3 needs one of w1, 2 or 3 t4.add_required_resource(w5) # t4 needs at most 2 of w1, w2 or 3 t5.add_required_resource(w6) # t5 needs at least 3 of w1, w2 or w3 # add a makespan objective pb_alt.add_objective_makespan() # solve solver1 = ps.SchedulingSolver(pb_alt, debug=False) solution = solver1.solve() self.assertEqual(solution.horizon, 5)
def test_selectworker_work_load_1(self) -> None: pb = ps.SchedulingProblem("SelectWorkerWorkLoad1", horizon=12) worker_1 = ps.Worker("Worker1") worker_2 = ps.Worker("Worker2") task1 = ps.FixedDurationTask("Task1", duration=10) task1.add_required_resource(ps.SelectWorkers([worker_1, worker_2], 1, "min")) # the workload on worker_1 forces 0 between 4 and 8 # then the worker_1 can not be assigned ps.WorkLoad(worker_1, {(4, 8): 0}) solver = ps.SchedulingSolver(pb) solution = solver.solve() print(solution) self.assertTrue(solution) self.assertTrue( solution.tasks[task1.name].assigned_resources == [worker_2.name] )
init_time = time.perf_counter() # Resources digital_transformation = ps.SchedulingProblem( "DigitalTransformation", horizon=num_dev_teams ) r_a = [ps.Worker("A_%i" % (i + 1)) for i in range(num_resource_a)] r_b = [ps.Worker("B_%i" % (i + 1)) for i in range(num_resource_b)] # Dev Team Tasks # For each dev_team pick one resource a and one resource b. ts_team_migration = [ ps.FixedDurationTask("DevTeam_%i" % (i + 1), duration=1, priority=10) for i in range(num_dev_teams) ] for t_team_migration in ts_team_migration: t_team_migration.add_required_resource(ps.SelectWorkers(r_a)) t_team_migration.add_required_resource(ps.SelectWorkers(r_b)) # create the solver and solve solver = ps.SchedulingSolver( digital_transformation, max_time=mt, logics=args.logics ) solution = solver.solve() if not solution: break computation_times.append(time.perf_counter() - init_time) plot_abs.append(num_dev_teams) solver.print_statistics()