Example #1
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)
Example #2
0
 def test_gantt_matplotlib_zero_duration_task(self):
     pb = ps.SchedulingProblem("GanttZeroDuration", horizon=10)
     ps.ZeroDurationTask("task1")
     solver = ps.SchedulingSolver(pb)
     solution = solver.solve()
     self.assertTrue(solution)
     solution.render_gantt_matplotlib(show_plot=False)
Example #3
0
    def test_tasks_contiguous(self) -> None:
        pb = ps.SchedulingProblem("TasksContiguous")
        n = 7
        tasks_w1 = [
            ps.FixedDurationTask("t_w1_%i" % i, duration=3) for i in range(n)
        ]
        tasks_w2 = [
            ps.FixedDurationTask("t_w2_%i" % i, duration=5) for i in range(n)
        ]
        worker_1 = ps.Worker("Worker1")
        worker_2 = ps.Worker("Worker2")
        for t in tasks_w1:
            t.add_required_resource(worker_1)
        for t in tasks_w2:
            t.add_required_resource(worker_2)

        c1 = ps.TasksContiguous(tasks_w1 + tasks_w2)
        pb.add_constraint(c1)

        pb.add_objective_makespan()

        solver = ps.SchedulingSolver(pb)
        solution = solver.solve()
        self.assertTrue(solution)
        self.assertEqual(solution.horizon, 56)
Example #4
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)
Example #5
0
 def test_export_to_smt2(self):
     problem = build_complex_problem("SolveExportToSMT2", 50)
     solver = ps.SchedulingSolver(problem)
     solution = _solve_problem(problem)
     self.assertTrue(solution)
     solver.export_to_smt2("complex_problem.smt2")
     self.assertTrue(os.path.isfile("complex_problem.smt2"))
Example #6
0
    def test_gantt_matplotlib_base(self):
        """take the single task/single resource and display output"""
        problem = ps.SchedulingProblem("RenderSolution", horizon=7)
        task = ps.FixedDurationTask("task", duration=7)
        # problem.add_task(task)
        worker = ps.Worker("worker")
        # problem.add_resource(worker)
        task.add_required_resource(worker)
        solver = ps.SchedulingSolver(problem)
        solution = solver.solve()
        self.assertTrue(solution)

        # display solution, using both ascii or matplotlib
        solution.render_gantt_matplotlib(
            render_mode="Resource",
            show_plot=False,
            fig_filename="test_render_resources_matplotlib.svg",
        )
        solution.render_gantt_matplotlib(
            render_mode="Task",
            show_plot=False,
            fig_filename="test_render_tasks_matplotlib.svg",
        )
        self.assertTrue(os.path.isfile("test_render_resources_matplotlib.svg"))
        self.assertTrue(os.path.isfile("test_render_tasks_matplotlib.svg"))
    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])
Example #8
0
    def test_buffer_bounds_1(self) -> None:
        # n tasks take 1, n tasks feed one. Bounds 0 to 1
        pb = ps.SchedulingProblem("BufferBounds1")

        n = 3
        unloading_tasks = [
            ps.FixedDurationTask("LoadTask_%i" % i, duration=3)
            for i in range(n)
        ]
        loading_tasks = [
            ps.FixedDurationTask("UnloadTask_%i" % i, duration=3)
            for i in range(n)
        ]
        # create buffer
        buffer = ps.NonConcurrentBuffer("Buffer1",
                                        lower_bound=0,
                                        upper_bound=1)

        for t in unloading_tasks:
            ps.TaskUnloadBuffer(t, buffer, quantity=1)

        for t in loading_tasks:
            ps.TaskLoadBuffer(t, buffer, quantity=1)

        pb.add_objective_makespan()

        solver = ps.SchedulingSolver(
            pb, max_time=300,
            parallel=True)  # , debug=True)#, logics="QF_UFIDL")
        solution = solver.solve()
        self.assertTrue(solution)
        self.assertEqual(solution.horizon, 9)
Example #9
0
    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)
Example #10
0
    def test_indicator_flowtime_single_resource_6(self) -> None:
        # Mutliple time intervals (Currently fails for nb_time_intervals > 2, gantt to check total_flowtime is correct)
        nb_time_intervals = 7
        time_interval_length = 13  # always > 5
        horizon = nb_time_intervals * time_interval_length
        time_intervals = [
            (i, i + time_interval_length)
            for i in range(0, horizon, time_interval_length)
        ]

        (
            problem,
            worker_1,
            sum_durations,
        ) = self.get_single_resource_utilization_problem_2(time_intervals)
        for interval in time_intervals:
            problem.add_objective_flowtime_single_resource(
                worker_1, time_interval=interval
            )

        solver = ps.SchedulingSolver(problem)

        solution = solver.solve()

        self.assertTrue(solution)
        self.assertEqual(sum_durations, self.get_sum_flowtime(solution))
Example #11
0
    def test_optimize_linear_cost_3(self) -> None:
        # same cost function as above, we minimize the cst,
        # the task should be scheduled at 0 (because the cost function increases)
        problem = ps.SchedulingProblem("OptimizeLinearCost3")

        t_1 = ps.FixedDurationTask("t1", duration=17)

        def real_cost_function(t):
            return 23.112 * t + 3.5

        worker_1 = ps.Worker(
            "Worker1", cost=ps.PolynomialCostFunction(real_cost_function))
        t_1.add_required_resource(worker_1)

        cost_ind = problem.add_indicator_resource_cost([worker_1])
        problem.add_objective_resource_cost([worker_1])

        solution = ps.SchedulingSolver(problem).solve()

        self.assertTrue(solution)
        # the task is scheduled at the beginning of the workplan
        self.assertEqual(solution.tasks[t_1.name].start, 0)
        # expected cost should be 3374
        expected_cost = (
            (real_cost_function(0) + real_cost_function(17)) * 17) / 2
        # Because there are Int type conversions, the result may not be exactly
        # the one expected, let's assume 99% is a good approx.
        err = abs(solution.indicators[cost_ind.name] / expected_cost - 1)
        self.assertLessEqual(err, 0.01)
    def test_optional_cumulative(self):
        """Same as above, but with an optional taskand an horizon of 2.
        t2 should not be scheduled."""
        pb_bs = ps.SchedulingProblem("OptionalCumulative", 2)
        # tasks
        t1 = ps.FixedDurationTask("T1", duration=2)
        t2 = ps.FixedDurationTask("T2", duration=2, optional=True)
        t3 = ps.FixedDurationTask("T3", duration=2)

        # workers
        r1 = ps.CumulativeWorker("Machine1", size=2)
        # resource assignment
        t1.add_required_resource(r1)
        t2.add_required_resource(r1)

        # constraints
        pb_bs.add_constraint(ps.TaskStartAt(t2, 1))

        # plot solution
        solver = ps.SchedulingSolver(pb_bs)
        solution = solver.solve()
        self.assertTrue(solution)
        self.assertTrue(solution.tasks[t1.name].scheduled)
        self.assertTrue(solution.tasks[t3.name].scheduled)
        self.assertFalse(solution.tasks[t2.name].scheduled)
    def test_multi_constraintsp(self) -> None:
        # we want to schedule one task in slot [1,5] and one task into slot [7, 12]
        pb = ps.SchedulingProblem(
            "ScheduleNTasksInTimeIntervalsMultipleConstraints", horizon=20
        )
        task_1 = ps.FixedDurationTask("task1", duration=3)
        task_2 = ps.FixedDurationTask("task2", duration=3)

        ps.ScheduleNTasksInTimeIntervals(
            [task_1, task_2], nb_tasks_to_schedule=1, list_of_time_intervals=[[1, 5]]
        )
        ps.ScheduleNTasksInTimeIntervals(
            [task_1, task_2], nb_tasks_to_schedule=1, list_of_time_intervals=[[7, 12]]
        )

        solver = ps.SchedulingSolver(pb)
        solution = solver.solve()
        self.assertTrue(solution)
        # check the solution
        task1_start = solution.tasks[task_1.name].start
        task1_end = solution.tasks[task_1.name].end
        task2_start = solution.tasks[task_2.name].start
        task2_end = solution.tasks[task_2.name].end

        task1_in_interval_1 = task1_start >= 1 and task1_end <= 5
        task2_in_interval_1 = task2_start >= 1 and task2_end <= 5
        self.assertTrue(task1_in_interval_1 != task2_in_interval_1)  # xor

        task1_in_interval_2 = task1_start >= 7 and task1_end <= 12
        task2_in_interval_2 = task2_start >= 7 and task2_end <= 12
        self.assertTrue(task1_in_interval_2 != task2_in_interval_2)  # xor

        self.assertTrue(task1_in_interval_1 != task2_in_interval_1)  # xor
        self.assertTrue(task1_in_interval_2 != task2_in_interval_2)  # xor
Example #14
0
    def test_load_unload_feed_buffers_1(self) -> None:
        # one task that consumes and feed two different buffers
        pb = ps.SchedulingProblem("LoadUnloadBuffer1")

        task_1 = ps.FixedDurationTask("task1", duration=3)
        buffer_1 = ps.NonConcurrentBuffer("Buffer1", initial_state=10)
        buffer_2 = ps.NonConcurrentBuffer("Buffer2", initial_state=0)

        pb.add_constraint(ps.TaskStartAt(task_1, 5))
        c1 = ps.TaskUnloadBuffer(task_1, buffer_1, quantity=3)
        pb.add_constraint(c1)

        c2 = ps.TaskLoadBuffer(task_1, buffer_2, quantity=2)
        pb.add_constraint(c2)

        solver = ps.SchedulingSolver(pb)
        solution = solver.solve()
        self.assertTrue(solution)
        self.assertEqual(solution.buffers[buffer_1.name].state, [10, 7])
        self.assertEqual(solution.buffers[buffer_1.name].state_change_times,
                         [5])
        self.assertEqual(solution.buffers[buffer_2.name].state, [0, 2])
        self.assertEqual(solution.buffers[buffer_2.name].state_change_times,
                         [8])

        # plot buffers
        solution.render_gantt_matplotlib(show_plot=False)
Example #15
0
    def test_incremental_optimizer_linear_cost_1(self) -> None:
        # same cost function as above, we minimize the cst,
        # the task should be scheduled at 0 (because the cost function increases)
        problem = ps.SchedulingProblem("IncrementalOptimizerLinearCost1",
                                       horizon=40)

        t_1 = ps.FixedDurationTask("t1", duration=17)

        # the task should be scheduled at the end
        def int_cost_function(t):
            return -23 * t + 321

        worker_1 = ps.Worker("Worker1",
                             cost=ps.PolynomialCostFunction(int_cost_function))
        t_1.add_required_resource(worker_1)

        cost_ind = problem.add_indicator_resource_cost([worker_1])
        problem.minimize_indicator(cost_ind)

        solver = ps.SchedulingSolver(problem, random_values=True)

        solution = solver.solve()

        self.assertTrue(solution)
        self.assertEqual(solution.tasks[t_1.name].start, 23)
Example #16
0
    def test_optimize_linear_cost_1(self) -> None:
        # same cost function as above, we minimize the cst,
        # the task should be scheduled at 0 (because the cost function increases)
        problem = ps.SchedulingProblem("OptimizeLinearCost1")

        t_1 = ps.FixedDurationTask("t1", duration=17)

        def int_cost_function(t):
            return 23 * t + 3

        worker_1 = ps.Worker("Worker1",
                             cost=ps.PolynomialCostFunction(int_cost_function))
        t_1.add_required_resource(worker_1)

        cost_ind = problem.add_indicator_resource_cost([worker_1])
        problem.add_objective_resource_cost([worker_1])

        solution = ps.SchedulingSolver(problem).solve()

        self.assertTrue(solution)
        # the task is scheduled at the beginning of the workplan
        self.assertEqual(solution.tasks[t_1.name].start, 0)
        # expected cost should be 3374
        expected_cost = int(
            ((int_cost_function(0) + int_cost_function(17)) * 17) / 2)
        self.assertEqual(solution.indicators[cost_ind.name], expected_cost)
    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_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_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)
    def test_non_dynamic_1(self) -> None:
        # same test as previously
        # but the task_1 workers are non dynamic.
        # so the horizon must be 20.
        pb = ps.SchedulingProblem("NonDynamicTest1")
        task_1 = ps.FixedDurationTask("task1", duration=10, work_amount=10)
        task_2 = ps.FixedDurationTask("task2", duration=5)
        task_3 = ps.FixedDurationTask("task3", duration=5)

        pb.add_constraint(ps.TaskStartAt(task_3, 0))
        pb.add_constraint(ps.TaskEndAt(task_2, 10))

        worker_1 = ps.Worker("Worker1", productivity=1)
        worker_2 = ps.Worker("Worker2", productivity=1)

        task_1.add_required_resources([worker_1,
                                       worker_2])  # dynamic False by default
        task_2.add_required_resource(worker_1)
        task_3.add_required_resource(worker_2)

        pb.add_objective_makespan()

        solver = ps.SchedulingSolver(pb)
        solution = solver.solve()
        self.assertEqual(solution.horizon, 20)
    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)
Example #24
0
    def test_optimize_linear_cost_2(self) -> None:
        # now we have a cost function that decreases over time,
        # then minimizing the cost should schedule the task at the end.
        # so we define an horizon for the problem
        problem = ps.SchedulingProblem("OptimizeLinear2", horizon=87)

        t_1 = ps.FixedDurationTask("t1", duration=13)

        # be sure however that this function is positive on the interval
        def int_cost_function(t):
            return 711 - 5 * t

        worker_1 = ps.Worker("Worker1",
                             cost=ps.PolynomialCostFunction(int_cost_function))
        t_1.add_required_resource(worker_1)

        cost_ind = problem.add_indicator_resource_cost([worker_1])
        problem.add_objective_resource_cost([worker_1])

        solution = ps.SchedulingSolver(problem).solve()

        self.assertTrue(solution)
        # the task is scheduled at the beginning of the workplan
        self.assertEqual(solution.tasks[t_1.name].start, 74)

        # expected cost should be 3374
        expected_cost = int(
            ((int_cost_function(74) + int_cost_function(87)) * 13) / 2)
        self.assertEqual(solution.indicators[cost_ind.name], expected_cost)
Example #25
0
    def test_load_buffer_2(self) -> None:
        pb = ps.SchedulingProblem("LoadBuffer2")

        task_1 = ps.FixedDurationTask("task1", duration=3)
        task_2 = ps.FixedDurationTask("task2", duration=3)
        task_3 = ps.FixedDurationTask("task3", duration=3)
        buffer = ps.NonConcurrentBuffer("Buffer1", initial_state=10)

        pb.add_constraint(ps.TaskStartAt(task_1, 5))
        pb.add_constraint(ps.TaskStartAt(task_2, 10))
        pb.add_constraint(ps.TaskStartAt(task_3, 15))
        c1 = ps.TaskLoadBuffer(task_1, buffer, quantity=3)
        pb.add_constraint(c1)

        c2 = ps.TaskLoadBuffer(task_2, buffer, quantity=2)
        pb.add_constraint(c2)

        c3 = ps.TaskLoadBuffer(task_3, buffer, quantity=1)
        pb.add_constraint(c3)

        solver = ps.SchedulingSolver(pb)
        solution = solver.solve()
        self.assertTrue(solution)
        self.assertEqual(solution.buffers[buffer.name].state, [10, 13, 15, 16])
        self.assertEqual(solution.buffers[buffer.name].state_change_times,
                         [8, 13, 18])
Example #26
0
 def test_solve_non_integer_max_time(self):
     """a stress test which"""
     problem = build_complex_problem("SolveMaxTime", 1000)
     problem.add_objective_makespan()
     # 0.5s is not enough to solve this problem
     max_time_solver = ps.SchedulingSolver(problem, max_time=0.05)
     solution = max_time_solver.solve()
     self.assertFalse(solution)
Example #27
0
 def test_gantt_matplotlib_no_resource(self):
     pb = ps.SchedulingProblem("GanttNoResource", horizon=10)
     ps.FixedDurationTask("task1", duration=3)
     solver = ps.SchedulingSolver(pb)
     solution = solver.solve()
     self.assertTrue(solution)
     solution.render_gantt_matplotlib(render_mode="Resource",
                                      show_plot=False)
Example #28
0
    def test_find_another_solution_solve_before(self):
        problem = ps.SchedulingProblem("FindAnotherSolutionSolveBefore",
                                       horizon=6)

        task_1 = ps.FixedDurationTask("task1", duration=2)
        solver = ps.SchedulingSolver(problem)
        result = solver.find_another_solution(
            task_1.start)  # error, first have to solve
        self.assertFalse(result)
Example #29
0
 def test_tasks_end_sync(self) -> None:
     pb = ps.SchedulingProblem("TasksEndSync")
     t_1 = ps.FixedDurationTask("t1", duration=2)
     t_2 = ps.FixedDurationTask("t2", duration=3)
     ps.TasksEndSynced(t_1, t_2)
     solver = ps.SchedulingSolver(pb)
     solution = solver.solve()
     self.assertTrue(solution)
     self.assertEqual(solution.tasks[t_1.name].end,
                      solution.tasks[t_2.name].end)
    def test_optional_task_end_at_2(self) -> None:
        """Task cannot be scheduled."""
        pb = ps.SchedulingProblem("OptionalTaskEndAt2", horizon=2)
        task_1 = ps.FixedDurationTask("task1", duration=3, optional=True)
        pb.add_constraint(ps.TaskEndAt(task_1, 4))

        solver = ps.SchedulingSolver(pb)
        solution = solver.solve()
        self.assertTrue(solution)
        self.assertFalse(solution.tasks[task_1.name].scheduled)