Esempio n. 1
0
    def solve(self, options):
        # takes into account successors
        jobs = copy.deepcopy(self.instance.data["jobs"])
        all_jobs = set(jobs.keys())
        solution = pt.SuperDict()
        succ = jobs.get_property("successors")
        durations = self.instance.data["durations"]

        # algorithm
        period = 0
        job = 1
        succ.pop(job)
        mode = 1  # we always chose the first mode
        solution[job] = dict(period=period, mode=mode)
        period = period + durations[job][mode]

        while len(succ):
            reverse = succ.list_reverse()
            possible = all_jobs - reverse.keys() - solution.keys()
            for job in possible:
                succ.pop(job)
                solution[job] = dict(period=period, mode=mode)
                period = period + durations[job][mode]
        self.solution = Solution(solution)
        return 2
    def solve(self, options=None, print_file=False):
        """
        Solve the problem.
        """
        log.debug(options)
        model = get_model()

        data = self.get_input_data()

        if options is None:
            options = {}

        if "timeLimit" in options:
            if "SOLVER_PARAMETERS" in options:
                options["SOLVER_PARAMETERS"]["sec"] = max(
                    int(options["timeLimit"] / 10), MIN_ITERATION_TIME)
            else:
                options["SOLVER_PARAMETERS"] = {
                    "sec": max(int(options["timeLimit"] / 10),
                               MIN_ITERATION_TIME)
                }
        else:
            options["SOLVER_PARAMETERS"] = SOLVER_PARAMETERS

        model_instance = model.create_instance(data, report_timing=False)
        opt = SolverFactory("cbc")
        opt.options.update(options["SOLVER_PARAMETERS"])
        self.iterator = BaseIterator(model_instance, opt, verbose=False)
        status, obj = self.get_initial_solution(step=5, modes_steps=3)

        log.debug("Solving the complete problem")
        status, obj = self.iterator.solve()

        self.status = status
        self.model_solution = self.iterator.instance
        log.debug("Status: {}  Objective value: {}".format(self.status, obj))

        if is_feasible(self.status):
            if print_file:
                self.print_instance()
            data = self.format_solution()
            self.solution = Solution(data)
        else:
            self.solution = Solution({})

        return get_status_value(self.status)
    def solve(self, options, print_file=False):
        """
        Solve the problem.
        """
        print_file = options.get("print_file", False)
        debug = log.root.level == log.DEBUG

        model = get_assign_tasks_model()

        data = self.get_input_data()

        # parameters of the resolution.

        if "SOLVER_PARAMETERS" not in options:
            options["SOLVER_PARAMETERS"] = {}
        if "timeLimit" in options:
            options["SOLVER_PARAMETERS"]["sec"] = options["timeLimit"]
        else:
            options["timeLimit"] = SOLVER_PARAMETERS["sec"]
        log.debug("Max time(s): {}".format(options["timeLimit"]))

        model_instance = model.create_instance(data, report_timing=True)
        opt = SolverFactory("cbc")

        opt.options.update(options["SOLVER_PARAMETERS"])
        result = opt.solve(model_instance, tee=debug)

        self.status = get_status(result)
        self.model_solution = model_instance

        if is_feasible(self.status):
            if print_file:
                self.print_instance()
            data = self.format_solution()
            self.solution = Solution(data)
        else:
            self.solution = Solution({})

        return get_status_value(self.status)
    def solve(self, options, print_file=False):
        """
        Solve the problem.
        """
        model = get_model()
        data = self.get_input_data()

        if options is None:
            options = {}
        if "timeLimit" in options:
            if "SOLVER_PARAMETERS" in options:
                options["SOLVER_PARAMETERS"]["sec"] = options["timeLimit"]
            else:
                options["SOLVER_PARAMETERS"] = {"sec": options["timeLimit"]}
        else:
            options["SOLVER_PARAMETERS"] = SOLVER_PARAMETERS

        model_instance = model.create_instance(data, report_timing=False)
        opt = SolverFactory("cbc")
        opt.options.update(options["SOLVER_PARAMETERS"])
        result = opt.solve(model_instance, tee=False)

        self.status = get_status(result)
        self.model_solution = model_instance
        obj = model_instance.f_obj()
        print("Status: {} Objective value: {}".format(self.status, obj))

        if is_feasible(self.status):
            if print_file:
                self.print_instance()
            data = self.format_solution()
            self.solution = Solution(data)
        else:
            self.solution = Solution({})

        return get_status_value(self.status)
    def solve(self, options, print_file=False):
        """
        Solve the problem.
        """
        print_file = options.get("print_file", False)
        debug = log.root.level == log.DEBUG
        # parameters of the resolution.
        if "SOLVER_PARAMETERS" not in options:
            options["SOLVER_PARAMETERS"] = {}
        if "timeLimit" in options:
            if "SOLVER_PARAMETERS" in options:
                options["SOLVER_PARAMETERS"]["sec"] = options["timeLimit"]
            else:
                options["SOLVER_PARAMETERS"] = {"sec": options["timeLimit"]}
        else:
            options["timeLimit"] = SOLVER_PARAMETERS["sec"]
        log.debug("Max time(s): ", options["timeLimit"])

        dataDict = self.instance.to_dict()
        listJobs = list(set([j["id"] for j in dataDict["jobs"]]))

        # First we calculate feasible modes for jobs
        model_modes = get_feasible_modes()
        data, max_duration_new_job, mode_max_duration = self.get_input_data(
            jobsToSolve=len(listJobs))
        model_modes_instance = model_modes.create_instance(data)
        opt = SolverFactory("cbc")
        opt.options.update(options["SOLVER_PARAMETERS"])
        result = opt.solve(model_modes_instance, tee=debug)

        self.status = get_status(result)
        self.model_solution = model_modes_instance

        if not is_feasible(self.status):
            self.solution = Solution({})
            return get_status_value(self.status)

        for iResource in model_modes_instance.sResources:
            log.debug(
                "used",
                iResource,
                sum(
                    value(model_modes_instance.v01JobMode[iJob, iMode]) *
                    value(model_modes_instance.pNeeds[iJob, iMode, iResource])
                    for iJob in model_modes_instance.sJobs
                    for iMode in model_modes_instance.sModes
                    if (iJob, iMode,
                        iResource) in model_modes_instance.pNeeds),
                "total:",
                value(model_modes_instance.pAvailability[iResource]),
            )
        for iJob in model_modes_instance.sJobs:
            for iMode in model_modes_instance.sModes:
                if (iJob, iMode) in model_modes_instance.pDuration:
                    if value(model_modes_instance.v01JobMode[iJob,
                                                             iMode]) == 1:
                        log.debug(iJob, iMode)

        log.debug("time fix model (s):", result.solver.system_time)

        self.fixed_jobs_modes = {
            (iJob, iMode): value(model_modes_instance.v01JobMode[iJob, iMode])
            for iJob in model_modes_instance.sJobs
            for iMode in model_modes_instance.sModes
            if (iJob, iMode) in model_modes_instance.pDuration
        }
        # End feasible modes

        model = get_tasks_fix_modes()

        log.debug("Starting loop")
        # Loop for solving the problem
        for loop_jobs in listJobs:
            if loop_jobs == 2:
                # First we solve without warmstart
                # Get the data
                data, max_duration_new_job = self.get_input_data_fix_mode(
                    jobsToSolve=loop_jobs)
                model_instance = model.create_instance(data)
                opt = SolverFactory("cbc")
                options["SOLVER_PARAMETERS"] = {"ratio": 0.2}
                opt.options.update(options["SOLVER_PARAMETERS"])
                result = opt.solve(model_instance)
                end_solve = time.time()

                self.status = get_status(result)
                self.model_solution = model_instance

                if not is_feasible(self.status):
                    self.solution = Solution({})
                    return get_status_value(self.status)

                log.debug(
                    "Jobs solved: ",
                    loop_jobs,
                    ", nº Slots:",
                    int(value(model_instance.vMaxSlot)),
                    ", time (s):",
                    result.solver.system_time,
                )
                previous_instance = model_instance
                aux_periods = 0

            elif loop_jobs > 2:
                # We solve starting with previous solution and add new job
                # Get the data
                data, max_duration_new_job = self.get_input_data_fix_mode(
                    jobsToSolve=loop_jobs,
                    previusSlots=aux_periods +
                    value(previous_instance.vMaxSlot),
                )
                if loop_jobs == listJobs[-1]:
                    model_instance = model.create_instance(data)
                    options["SOLVER_PARAMETERS"] = {"ratio": 0.01}
                    opt.options.update(options["SOLVER_PARAMETERS"])
                else:
                    model_instance = model.create_instance(data)

                # Initialize previous solution
                for j in previous_instance.sJobs:
                    for s in previous_instance.sSlots:
                        if s <= model_instance.sSlots[-1]:
                            model_instance.v01Start[j, s].value = value(
                                previous_instance.v01Start[j, s])
                            model_instance.v01End[j, s].value = value(
                                previous_instance.v01End[j, s])
                            model_instance.v01JobDone[j, s].value = value(
                                previous_instance.v01JobDone[j, s])
                            # model_instance.vMaxSlot.value = value(previous_instance.vMaxSlot) +

                # Initialize new job, first to 0
                for n in range(
                        int(value(previous_instance.vMaxSlot) + 1),
                        int(
                            value(previous_instance.vMaxSlot) +
                            max_duration_new_job + 1),
                ):
                    model_instance.v01Start[loop_jobs, n].value = 0
                    model_instance.v01End[loop_jobs, n].value = 0

                # Then to 1 only when true
                model_instance.v01Start[
                    loop_jobs,
                    int(value(previous_instance.vMaxSlot) + 1)].value = 1
                model_instance.v01End[loop_jobs,
                                      int(
                                          value(previous_instance.vMaxSlot) +
                                          max_duration_new_job), ].value = 1
                for n in range(
                        int(value(previous_instance.vMaxSlot) + 1),
                        int(
                            value(previous_instance.vMaxSlot) +
                            max_duration_new_job + 1),
                ):
                    model_instance.v01JobDone[loop_jobs, n].value = 1

                # WarmStart
                write_cbc_warmstart_file("./cbc_warmstart.soln",
                                         model_instance, opt)

                result = opt.solve(
                    model_instance,
                    tee=debug,
                    warmstart=True,
                    warmstart_file="./cbc_warmstart.soln",
                )

                self.status = get_status(result)
                self.model_solution = model_instance

                if not is_feasible(self.status):
                    self.solution = Solution({})
                    return get_status_value(self.status)

                log.debug(
                    "Jobs solved: ",
                    loop_jobs,
                    ", nº Slots:",
                    int(value(model_instance.vMaxSlot)),
                    ", time (s):",
                    result.solver.system_time,
                )

                previous_instance = model_instance

                end_solve = time.time()

        # Solve complete problem with warmstart
        time_left = options["timeLimit"] - (time.time() - start_time)
        options["timeLimit"] = time_left
        log.debug("Time left (s)", time_left)
        log.debug("Solve complete problem with warmstart")
        model = get_assign_tasks_model()
        data, max_duration_new_job, mode_max_duration = self.get_input_data(
            jobsToSolve=len(listJobs),
            previusSlots=value(previous_instance.vMaxSlot))

        model_instance = model.create_instance(data)
        # Check input
        v01Start = dict()
        v01End = dict()
        v01JobDone = dict()
        v01JobMode = dict()

        # Initialize previous solution
        for j in previous_instance.sJobs:
            for s in previous_instance.sSlots:
                if s <= model_instance.sSlots[-1]:
                    model_instance.v01Start[j, s].value = int(
                        value(previous_instance.v01Start[j, s]))
                    model_instance.v01End[j, s].value = int(
                        value(previous_instance.v01End[j, s]))

                    v01Start[j,
                             s] = int(value(previous_instance.v01Start[j, s]))
                    v01End[j, s] = int(value(previous_instance.v01End[j, s]))

                    for m in model_instance.sModes:
                        if (j, m) in self.fixed_jobs_modes:
                            if self.fixed_jobs_modes[j, m] == 1:
                                model_instance.v01JobDone[j, s, m].value = int(
                                    value(previous_instance.v01JobDone[j, s]))
                                model_instance.v01JobMode[j, m].value = 1

                                v01JobDone[j, s, m] = int(
                                    value(previous_instance.v01JobDone[j, s]))
                                v01JobMode[j, m] = 1

        # WarmStart
        opt.options.update(options["SOLVER_PARAMETERS"])
        write_cbc_warmstart_file("./cbc_warmstart.soln", model_instance, opt)
        result = opt.solve(
            model_instance,
            tee=debug,
            warmstart=True,
            warmstart_file="./cbc_warmstart.soln",
        )

        log.debug(
            "Jobs solved: ",
            loop_jobs,
            ", nº Slots:",
            int(value(model_instance.vMaxSlot)),
            ", time (s):",
            result.solver.system_time,
        )
        log.debug("Finish")

        self.status = get_status(result)
        self.model_solution = model_instance

        log.debug("End of solver. Total time:  %.2f seconds" %
                  (time.time() - start_time))
        if is_feasible(self.status):
            if print_file:
                self.print_instance()
            data = self.format_solution()
            self.solution = Solution(data)
        else:
            self.solution = Solution({})

        return get_status_value(self.status)
 def __init__(self, instance, solution=None):
     if solution is None:
         solution = Solution({})
     super().__init__(instance, solution)
     self.input_data = {}
     log.debug("\nSolving with Iterator1")
 def __init__(self, instance, solution=None):
     if solution is None:
         solution = Solution({})
     super().__init__(instance, solution)
     print("\nSolving with Milp1")
    def solve(self, options):
        """
        Solve the problem.
        """
        print_file = options.get("print_file", False)
        debug = log.root.level == log.DEBUG
        # parameters of the resolution.
        if "SOLVER_PARAMETERS" not in options:
            options["SOLVER_PARAMETERS"] = {}
        if "timeLimit" in options:
            options["SOLVER_PARAMETERS"]["sec"] = options["timeLimit"]
        else:
            options["timeLimit"] = SOLVER_PARAMETERS["sec"]
        log.debug("Max time(s): ".format(options["timeLimit"]))

        model = get_assign_tasks_model()

        dataDict = self.instance.to_dict()
        listJobs = list(set([j["id"] for j in dataDict["jobs"]]))

        log.debug("Starting loop")
        # Loop for solving the problem
        for loop_jobs in listJobs:
            if loop_jobs == 2:
                # First we solve without warmstart
                # Get the data
                data, max_duration_new_job, mode_max_duration = self.get_input_data(
                    jobsToSolve=loop_jobs)
                model_instance = model.create_instance(data,
                                                       report_timing=debug)
                opt = SolverFactory("cbc")
                options["SOLVER_PARAMETERS"] = {"ratio": 0.2}
                opt.options.update(options["SOLVER_PARAMETERS"])
                result = opt.solve(model_instance, tee=debug)
                end_solve = time.time()

                log.debug(
                    "Jobs solved: {}, num Slots: {}, time (s): {}, ".format(
                        loop_jobs,
                        int(value(model_instance.vMaxSlot)),
                        result.solver.system_time,
                    ))

                previous_instance = model_instance
                aux_periods = 0

            elif loop_jobs > 2:
                # We solve starting with previous solution and add new job
                # Get the data
                data, max_duration_new_job, mode_max_duration = self.get_input_data(
                    jobsToSolve=loop_jobs,
                    previusSlots=aux_periods +
                    value(previous_instance.vMaxSlot),
                )
                if loop_jobs == listJobs[-1]:
                    model_instance = model.create_instance(data)
                    options["SOLVER_PARAMETERS"] = {"ratio": 0.01}
                    opt.options.update(options["SOLVER_PARAMETERS"])
                else:
                    model_instance = model.create_instance(data)

                # Initialize previous solution
                for j in previous_instance.sJobs:
                    for s in previous_instance.sSlots:
                        if s <= model_instance.sSlots[-1]:
                            for m in previous_instance.sModes:
                                model_instance.v01Start[j, s].value = value(
                                    previous_instance.v01Start[j, s])
                                model_instance.v01End[j, s].value = value(
                                    previous_instance.v01End[j, s])
                                model_instance.v01JobDone[
                                    j, s, m].value = value(
                                        previous_instance.v01JobDone[j, s, m])
                                model_instance.v01JobMode[j, m].value = value(
                                    previous_instance.v01JobMode[j, m])

                # Initialize new job, first to 0
                for n in range(
                        int(value(previous_instance.vMaxSlot) + 1),
                        int(
                            value(previous_instance.vMaxSlot) +
                            max_duration_new_job + 1),
                ):
                    model_instance.v01Start[loop_jobs, n].value = 0
                    model_instance.v01End[loop_jobs, n].value = 0
                for m in model_instance.sModes:
                    model_instance.v01JobMode[loop_jobs, m].value = 0

                # Then to 1 only when true
                model_instance.v01Start[
                    loop_jobs,
                    int(value(previous_instance.vMaxSlot) + 1)].value = 1
                model_instance.v01End[loop_jobs,
                                      int(
                                          value(previous_instance.vMaxSlot) +
                                          max_duration_new_job), ].value = 1
                for n in range(
                        int(value(previous_instance.vMaxSlot) + 1),
                        int(
                            value(previous_instance.vMaxSlot) +
                            max_duration_new_job + 1),
                ):
                    model_instance.v01JobDone[loop_jobs, n,
                                              int(mode_max_duration)].value = 1
                model_instance.v01JobMode[loop_jobs,
                                          int(mode_max_duration)].value = 1

                # WarmStart
                write_cbc_warmstart_file("./cbc_warmstart.soln",
                                         model_instance, opt)
                result = opt.solve(
                    model_instance,
                    tee=debug,
                    warmstart=True,
                    warmstart_file="./cbc_warmstart.soln",
                )

                log.debug(
                    "Jobs solved: {}, num Slots: {}, time (s): {}, ".format(
                        loop_jobs,
                        int(value(model_instance.vMaxSlot)),
                        result.solver.system_time,
                    ))

                previous_instance = model_instance

                # Check non-renawable resources availability:
                aux_periods = 0
                for iResource in model_instance.sResources:
                    if (sum(
                            value(model_instance.v01JobMode[iJob, iMode]) *
                            value(model_instance.pNeeds[iJob, iMode,
                                                        iResource])
                            for iJob in model_instance.sJobs
                            for iMode in model_instance.sModes if
                        (iJob, iMode, iResource) in model_instance.pNeeds) /
                            value(model_instance.pAvailability[iResource]) >
                            0.9 and "N" in iResource):
                        aux_periods = (round(
                            value(previous_instance.vMaxSlot) / loop_jobs) * 2)

                    log.debug("used: {} {}, total: {}".format(
                        iResource,
                        sum(
                            value(model_instance.v01JobMode[iJob, iMode]) *
                            value(model_instance.pNeeds[iJob, iMode,
                                                        iResource])
                            for iJob in model_instance.sJobs
                            for iMode in model_instance.sModes
                            if (iJob, iMode,
                                iResource) in model_instance.pNeeds),
                        value(model_instance.pAvailability[iResource]),
                    ))

        self.status = get_status(result)
        self.model_solution = model_instance

        log.debug("End of loop. Total time:  %.2f seconds" %
                  (time.time() - start_time))
        if is_feasible(self.status):
            if print_file:
                self.print_instance()
            data = self.format_solution()
            self.solution = Solution(data)
        else:
            self.solution = Solution({})

        return get_status_value(self.status)
Esempio n. 9
0
    def solve(self, options):
        model = cp_model.CpModel()
        input_data = pt.SuperDict.from_dict(self.instance.data)
        durations_data = pt.SuperDict.from_dict(input_data["durations"])
        max_dur_job = durations_data.vapply(lambda v: max(v.values()))
        horizon = sum(max_dur_job.values()) + 1
        jobs_data = input_data["jobs"]
        needs_data = pt.SuperDict.from_dict(input_data["needs"])
        mode_dictionary_to_values = (
            lambda v: v.to_tuplist().sorted(key=lambda x: x[0]).take(1)
        )

        # variable declaration:
        starts = pt.SuperDict(
            {
                job: model.NewIntVar(0, horizon, "start_{}".format(job))
                for job in jobs_data
            }
        )
        ends = pt.SuperDict(
            {
                job: model.NewIntVar(0, horizon, "end_{}".format(job))
                for job in jobs_data
            }
        )
        job_mode = pt.SuperDict(
            {
                job: model.NewIntVar(0, len(modes) - 1, "mode_{}".format(job))
                for job, modes in durations_data.items()
            }
        )
        job_duration_min_max = {
            job: (min(modes.values()), max(modes.values()))
            for job, modes in durations_data.items()
        }
        job_duration = pt.SuperDict(
            {
                job: model.NewIntVar(*bounds, "duration_{}".format(job))
                for job, bounds in job_duration_min_max.items()
            }
        )
        interval = pt.SuperDict(
            {
                job: model.NewIntervalVar(
                    starts[job], job_duration[job], ends[job], "interval_{}".format(job)
                )
                for job in jobs_data
            }
        )
        mode_duration_perjob = durations_data.vapply(mode_dictionary_to_values)
        # definition of job duration
        [
            model.AddElement(
                job_mode[job], mode_duration_perjob[job], job_duration[job]
            )
            for job in jobs_data
        ]

        # for each job and resource:
        # an array of consumptions (one per mode in order)
        needs_data_perjob = (
            needs_data.to_dictup()
            .to_tuplist()
            .take([0, 2, 1, 3])
            .to_dict([2, 3])
            .vapply(sorted)
            .vapply(pt.TupList)
            .vapply(lambda v: v.take(1))
        )

        # for each job and resource:
        # a variable with the consumption
        job_consumption = needs_data_perjob.kvapply(
            lambda k, v: model.NewIntVar(min(v), max(v), "consumption_{}_{}".format(*k))
        )
        # definition of job consumption
        for (job, res), needs in needs_data_perjob.items():
            model.AddElement(job_mode[job], needs, job_consumption[job, res])

        # succession needs to be guaranteed
        for job, job_data in input_data["jobs"].items():
            for successor in job_data["successors"]:
                model.Add(starts[successor] >= ends[job])

        # resource usage
        job_consumption_per_res = (
            job_consumption.to_tuplist()
            .take([1, 0, 2])
            .to_dict(2, is_list=False)
            .to_dictdict()
        )
        for resource, res_data in input_data["resources"].items():
            # we get jobs that consume that resource and how much
            jobs, consumptions = zip(*job_consumption_per_res[resource].items_tl())
            relevant_intervals = [interval[j] for j in jobs]
            if resource in self.instance.get_renewable_resources():
                # renewable resources we use intervals to check them
                model.AddCumulative(
                    intervals=relevant_intervals,
                    demands=consumptions,
                    capacity=res_data["available"],
                )
            else:  # non renewable resources we sum all
                model.Add(sum(consumptions) <= res_data["available"])

        # we set the objective as the makespan
        obj_var = model.NewIntVar(0, horizon, "makespan")
        model.AddMaxEquality(obj_var, ends.values())
        model.Minimize(obj_var)

        solver = cp_model.CpSolver()
        solver.parameters.max_time_in_seconds = options.get("timeLimit", 10)
        status = solver.Solve(model)
        if status not in [cp_model.OPTIMAL, cp_model.FEASIBLE]:
            return status
        start_sol = starts.vapply(solver.Value)
        mode_sol = job_mode.vapply(lambda v: solver.Value(v) + 1)
        _func = lambda x, y: dict(period=x, mode=y)
        solution = start_sol.sapply(func=_func, other=mode_sol)
        self.solution = Solution(solution)
        return status