def test_resource_tasks_distance_2(self) -> None:
        pb = ps.SchedulingProblem("ResourceTasksDistance2")
        task_1 = ps.FixedDurationTask("task1", duration=8)
        task_2 = ps.FixedDurationTask("task2", duration=4)
        worker_1 = ps.Worker("Worker1")
        task_1.add_required_resource(worker_1)
        task_2.add_required_resource(worker_1)

        ps.ResourceTasksDistance(worker_1, distance=4, mode="max")
        ps.TaskStartAt(task_1, 1)

        pb.add_objective_makespan()

        solver = ps.SchedulingSolver(pb)
        solution = solver.solve()
        self.assertTrue(solution)

        t1_start = solution.tasks[task_1.name].start
        t2_start = solution.tasks[task_2.name].start
        t1_end = solution.tasks[task_1.name].end
        t2_end = solution.tasks[task_2.name].end
        self.assertEqual(t1_start, 1)
        self.assertEqual(t1_end, 9)
        self.assertEqual(t2_start, 9)
        self.assertEqual(t2_end, 13)
    def test_resource_tasks_distance_3(self) -> None:
        pb = ps.SchedulingProblem("ResourceTasksDistanceContiguous3")
        task_1 = ps.FixedDurationTask("task1", duration=8)
        task_2 = ps.FixedDurationTask("task2", duration=4)
        task_3 = ps.FixedDurationTask("task3", duration=5)
        worker_1 = ps.Worker("Worker1")
        task_1.add_required_resource(worker_1)
        task_2.add_required_resource(worker_1)
        task_3.add_required_resource(worker_1)

        # a constraint to tell tasks are contiguous
        ps.ResourceTasksDistance(worker_1, distance=0, mode="exact")
        ps.TaskStartAt(task_1, 2)

        pb.add_objective_makespan()

        solver = ps.SchedulingSolver(pb)
        solution = solver.solve()
        self.assertTrue(solution)

        t1_start = solution.tasks[task_1.name].start
        t2_start = solution.tasks[task_2.name].start
        t3_start = solution.tasks[task_3.name].start
        t1_end = solution.tasks[task_1.name].end

        self.assertEqual(t1_start, 2)
        self.assertEqual(t1_end, 10)
        self.assertTrue(t3_start in [10, 14])
        self.assertTrue(t2_start in [10, 15])
    def test_resource_tasks_distance_double_time_period_1(self) -> None:
        """1 resource, 4 tasks, two time intervals for the ResourceTaskDistance"""
        pb = ps.SchedulingProblem("ResourceTasksDistanceMultiTimePeriod1")
        tasks = [
            ps.FixedDurationTask("task%i" % i, duration=1) for i in range(4)
        ]

        worker_1 = ps.Worker("Worker1")
        for t in tasks:
            t.add_required_resource(worker_1)

        ps.ResourceTasksDistance(
            worker_1,
            distance=4,
            mode="exact",
            list_of_time_intervals=[[10, 20], [30, 40]],
        )

        # add a makespan objective, all tasks should be scheduled from 0 to 4
        pb.add_objective_makespan()

        # as a consequence, task2 should be scheduled 4 periods after and start at 15
        solver = ps.SchedulingSolver(pb)

        solution = solver.solve()

        self.assertTrue(solution)
        self.assertEqual(solution.horizon, 4)
    def test_resource_tasks_distance_single_time_period_2(self) -> None:
        """The same as above, except that we force the tasks to be scheduled
        in the time period so that the distance applies"""
        pb = ps.SchedulingProblem("ResourceTasksDistanceSingleTimePeriod2")
        task_1 = ps.FixedDurationTask("task1", duration=1)
        task_2 = ps.FixedDurationTask("task2", duration=1)

        worker_1 = ps.Worker("Worker1")
        task_1.add_required_resource(worker_1)
        task_2.add_required_resource(worker_1)

        ps.ResourceTasksDistance(worker_1,
                                 distance=4,
                                 mode="exact",
                                 list_of_time_intervals=[[10, 18]])
        # force task 1 to start at 10 (in the time period intervak)
        ps.TaskStartAt(task_1, 10)
        # task_2 must be scheduled after task_1
        ps.TaskPrecedence(task_1, task_2)

        # add a makespan objective, to be sure, to schedule task_2 in the time interal
        pb.add_objective_makespan()

        # as a consequence, task2 should be scheduled 4 periods after and start at 15
        solver = ps.SchedulingSolver(pb)

        solution = solver.solve()

        self.assertTrue(solution)
        self.assertEqual(solution.tasks[task_2.name].start, 15)
        self.assertEqual(solution.tasks[task_2.name].end, 16)
    def test_resource_tasks_distance_single_time_period_1(self) -> None:
        """Adding one or more non scheduled optional tasks should not change anything"""
        pb = ps.SchedulingProblem("ResourceTasksDistanceSingleTimePeriod1")
        task_1 = ps.FixedDurationTask("task1", duration=1)
        task_2 = ps.FixedDurationTask("task2", duration=1)

        worker_1 = ps.Worker("Worker1")
        task_1.add_required_resource(worker_1)
        task_2.add_required_resource(worker_1)

        ps.ResourceTasksDistance(worker_1,
                                 distance=4,
                                 mode="exact",
                                 list_of_time_intervals=[[10, 18]])
        ps.TaskPrecedence(task_1, task_2)
        # we add a makespan objective: the two tasks should be scheduled with an horizon of 2
        # because they are outside the time period
        pb.add_objective_makespan()

        solver = ps.SchedulingSolver(pb)

        solution = solver.solve()

        self.assertTrue(solution)
        t1_start = solution.tasks[task_1.name].start
        t2_start = solution.tasks[task_2.name].start
        t1_end = solution.tasks[task_1.name].end
        t2_end = solution.tasks[task_2.name].end
        self.assertEqual(t1_start, 0)
        self.assertEqual(t1_end, 1)
        self.assertEqual(t2_start, 1)
        self.assertEqual(t2_end, 2)
    def test_resource_tasks_distance_4(self) -> None:
        """Adding one or more non scheduled optional tasks should not change anything"""
        pb = ps.SchedulingProblem("ResourceTasksDistance4OptionalTasks",
                                  horizon=20)
        task_1 = ps.FixedDurationTask("task1", duration=8)
        task_2 = ps.FixedDurationTask("task2", duration=4)
        task_3 = ps.FixedDurationTask("task3", duration=3, optional=True)
        task_4 = ps.FixedDurationTask("task4", duration=2, optional=True)
        task_5 = ps.FixedDurationTask("task5", duration=1, optional=True)
        worker_1 = ps.Worker("Worker1")
        task_1.add_required_resource(worker_1)
        task_2.add_required_resource(worker_1)

        ps.ResourceTasksDistance(worker_1, distance=4, mode="exact")
        ps.TaskStartAt(task_1, 1)

        solver = ps.SchedulingSolver(pb)
        # for optional tasks to not be scheduled
        solver.append_z3_assertion(task_3.scheduled == False)
        solver.append_z3_assertion(task_4.scheduled == False)
        solver.append_z3_assertion(task_5.scheduled == False)

        solution = solver.solve()

        self.assertTrue(solution)

        t1_start = solution.tasks[task_1.name].start
        t2_start = solution.tasks[task_2.name].start
        t1_end = solution.tasks[task_1.name].end
        t2_end = solution.tasks[task_2.name].end
        self.assertEqual(t1_start, 1)
        self.assertEqual(t1_end, 9)
        self.assertEqual(t2_start, 13)
        self.assertEqual(t2_end, 17)
Exemple #7
0
    def test_resource_tasks_distance_1(self) -> None:
        pb = ps.SchedulingProblem("ResourceTasksDistance1", horizon=20)
        task_1 = ps.FixedDurationTask("task1", duration=8)
        task_2 = ps.FixedDurationTask("task2", duration=4)
        worker_1 = ps.Worker("Worker1")
        task_1.add_required_resource(worker_1)
        task_2.add_required_resource(worker_1)

        c1 = ps.ResourceTasksDistance(worker_1, distance=4, mode="exact")
        pb.add_constraint(c1)

        pb.add_constraint(ps.TaskStartAt(task_1, 1))

        solver = ps.SchedulingSolver(pb)
        solution = solver.solve()
        self.assertTrue(solution)

        t1_start = solution.tasks[task_1.name].start
        t2_start = solution.tasks[task_2.name].start
        t1_end = solution.tasks[task_1.name].end
        t2_end = solution.tasks[task_2.name].end
        self.assertEqual(t1_start, 1)
        self.assertEqual(t1_end, 9)
        self.assertEqual(t2_start, 13)
        self.assertEqual(t2_end, 17)
 def test_resource_tasks_distance_raise_1(self) -> None:
     # if only one task is assigned to the worker, a issue is raised
     ps.SchedulingProblem("ResourceTasksDistanceOneTaskRaiseAssertionError")
     worker = ps.Worker("worker")
     task = ps.FixedDurationTask("Task", 1)
     task.add_required_resource(worker)
     with self.assertRaises(AssertionError):
         ps.ResourceTasksDistance(worker, 0, [(0, 5)])
    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")
Exemple #10
0
    def test_resource_tasks_distance_double_time_period_2(self) -> None:
        """Same as above, but force the tasks to be scheduled within the time intervals"""
        pb = ps.SchedulingProblem("ResourceTasksDistanceMultiTimePeriod2")
        tasks = [
            ps.FixedDurationTask("task%i" % i, duration=1) for i in range(4)
        ]

        worker_1 = ps.Worker("Worker1")
        for t in tasks:
            t.add_required_resource(worker_1)

        c1 = ps.ResourceTasksDistance(worker_1,
                                      distance=4,
                                      mode="exact",
                                      time_periods=[[10, 20], [30, 40]])
        pb.add_constraint(c1)

        # add a makespan objective, all tasks should be scheduled from 0 to 4
        pb.add_constraint(ps.TaskStartAt(tasks[0], 10))
        pb.add_constraint(ps.TaskStartAfterLax(tasks[1], 10))
        pb.add_constraint(ps.TaskEndBeforeLax(tasks[1], 20))
        pb.add_constraint(ps.TaskStartAt(tasks[2], 30))
        pb.add_constraint(ps.TaskStartAfterLax(tasks[3], 30))
        pb.add_constraint(ps.TaskEndBeforeLax(tasks[3], 40))
        # as a consequence, task2 should be scheduled 4 periods after and start at 15
        solver = ps.SchedulingSolver(pb)

        solution = solver.solve()

        self.assertTrue(solution)
        self.assertEqual(solution.horizon, 36)
        t0_start = solution.tasks[tasks[0].name].start
        t1_start = solution.tasks[tasks[1].name].start
        t2_start = solution.tasks[tasks[2].name].start
        t3_start = solution.tasks[tasks[3].name].start
        t0_end = solution.tasks[tasks[0].name].end
        t1_end = solution.tasks[tasks[1].name].end
        t2_end = solution.tasks[tasks[2].name].end
        t3_end = solution.tasks[tasks[3].name].end
        self.assertEqual(t0_start, 10)
        self.assertEqual(t0_end, 11)
        self.assertEqual(t1_start, 15)
        self.assertEqual(t1_end, 16)
        self.assertEqual(t2_start, 30)
        self.assertEqual(t2_end, 31)
        self.assertEqual(t3_start, 35)
        self.assertEqual(t3_end, 36)
 def test_resource_tasks_distance_raise_1(self) -> None:
     # if no task is assigned to the worker, a issue is raised
     ps.SchedulingProblem("ResourceTasksDistanceNoTaskRaiseAssertionError")
     worker = ps.Worker("Worker")
     with self.assertRaises(AssertionError):
         ps.ResourceTasksDistance(worker, 0, [(0, 5)])