Beispiel #1
0
    def solve_relaxed(self, mdl, prio_name, relaxable_groups, relax_mode, parameters=None):
        # --- 1 serialize
        job_name = normalize_basename(mdl.name, force_lowercase=True)
        model_data = self.serialize_model(mdl)
        docloud_parameters = mdl.parameters
        prm_data = self._serialize_parameters(docloud_parameters, write_level=1, relax_mode=relax_mode)
        prm_name = self._make_attachment_name(job_name, '.prm')
        feasopt_data = self._serialize_relaxables(relaxable_groups)

        # --- dump if need be
        if prio_name:
            prio_name = "_%s" % prio_name
        relax_basename = normalize_basename("%s_feasopt%s" % (mdl.name, prio_name))

        prm_basename = normalize_basename("%s_feasopt" % mdl.name)
        self._dump_if_required(model_data, mdl, basename=job_name, extension=".lp", forced=True)
        self._dump_if_required(feasopt_data, mdl, basename=relax_basename, extension=FeasibilityPrinter.extension,
                               forced=True)
        self._dump_if_required(prm_data, mdl, basename=prm_basename, extension=".prm", forced=True)

        # --- submit job somehow...
        attachments = []
        model_name = normalize_basename(job_name) + self._exchange_format.extension
        attachments.append(self._make_attachment(model_name, model_data))

        attachments.append(self._make_attachment(prm_name, prm_data))
        attachments.append(self._make_attachment(normalize_basename(job_name) + FeasibilityPrinter.extension,
                                                 feasopt_data))

        # here we go...
        def notify_info(info):
            if "jobid" in info:
                mdl.fire_jobid(jobid=info["jobid"])
            if "progress" in info:
                mdl.fire_progress(progress_data=info["progress"])

        connector = self._connector
        mdl.notify_start_solve()
        connector.submit_model_data(attachments,
                                    gzip=not self._exchange_format.is_binary,
                                    info_callback=notify_info,
                                    info_to_monitor={'jobid', 'progress'})

        # --- cplex solve details
        json_details = connector.get_cplex_details()
        self._solve_details = SolveDetails.from_json(json_details)
        # ---

        # --- build a solution object, or None
        solution_handler = JSONSolutionHandler(connector.results.get('solution.json'))
        if not solution_handler.has_solution:
            mdl.notify_solve_failed()
            return None
        else:
            infeas_json = connector.results.get('infeasibilities.json')
            infeas_handler = JSONInfeasibilityHandler(infeas_json) if infeas_json else None
            sol = self._make_relaxed_solution(mdl, solution_handler, infeas_handler)
            return sol
Beispiel #2
0
    def solve(self, mdl, parameters=None, **kwargs):
        # Before submitting the job, we will build the list of attachments
        # parameters are CPLEX parameters
        lex_mipstart = kwargs.pop('_lex_mipstart', None)
        attachments = []

        # make sure model is the first attachment: that will be the name of the job on the console
        job_name = normalize_basename("python_%s" % mdl.name)
        model_file = self.serialize_model_as_file(mdl)
        try:
            model_data_name = self._make_attachment_name(
                job_name, self._exchange_format.extension)
            attachments.append({
                'name': model_data_name,
                'filename': model_file
            })

            # prm
            docloud_parameters = parameters if parameters is not None else mdl.parameters
            prm_data = self._serialize_parameters(docloud_parameters)
            prm_name = self._make_attachment_name(job_name, '.prm')
            attachments.append({'name': prm_name, 'data': prm_data})

            # warmstart_data
            # export mipstart solution in CPLEX mst format, if any, else None
            # if within a lexicographic solve, th elex_mipstart supersedes allother mipstarts
            if lex_mipstart:
                mipstart_name = lex_mipstart.name.lower(
                ) if lex_mipstart.name else job_name
                warmstart_data = SolutionMSTPrinter.print_to_string(
                    lex_mipstart).encode('utf-8')
                warmstart_name = self._make_attachment_name(
                    mipstart_name, ".mst")
                attachments.append({
                    'name': warmstart_name,
                    'data': warmstart_data
                })

            elif mdl.number_of_mip_starts:
                mipstart_name = job_name
                warmstart_name = self._make_attachment_name(
                    mipstart_name, ".mst")
                mdl_mipstarts = [s for s, _ in mdl.iter_mip_starts()]
                mdl_efforts = [eff for (_, eff) in mdl.iter_mip_starts()]
                warmstart_data = SolutionMSTPrinter.print_to_string(
                    mdl_mipstarts, effort_level=mdl_efforts,
                    use_lp_names=True).encode('utf-8')
                attachments.append({
                    'name': warmstart_name,
                    'data': warmstart_data
                })

            # benders annotation
            if mdl.has_benders_annotations():
                anno_data = ModelAnnotationPrinter.print_to_string(mdl).encode(
                    'utf-8')
                anno_name = self._make_attachment_name(job_name, '.ann')
                attachments.append({'name': anno_name, 'data': anno_data})

            # info_to_monitor = {'jobid'}
            # if mdl.progress_listeners:
            # info_to_monitor.add('progress')

            def notify_info(info):
                if "jobid" in info:
                    mdl.fire_jobid(jobid=info["jobid"])
                if "progress" in info:
                    mdl.fire_progress(progress_data=info["progress"])

            # This block used to be try/catched for DOcloudConnector exceptions
            # and DOcloudException, but then infrastructure error were not
            # handled properly. Now we let the exception raise.
            connector = self._connector
            mdl.notify_start_solve()
            connector.submit_model_data(
                attachments,
                gzip=not self._exchange_format.is_binary,
                info_callback=notify_info,
                info_to_monitor={'jobid', 'progress'})

            # --- cplex solve details
            json_details = connector.get_cplex_details()
            self._solve_details = SolveDetails.from_json(json_details)
            self._solve_details._quality_metrics = self._compute_quality_metrics(
                json_details)
            # ---

            # --- build a solution object, or None
            solution_handler = JSONSolutionHandler(
                connector.results.get('solution.json'))
            if not solution_handler.has_solution:
                mdl.notify_solve_failed()
                solution = None
            else:
                solution = self._make_solution(mdl, solution_handler)
            # ---

            return solution
        finally:
            if os.path.isfile(model_file):
                os.remove(model_file)