Exemple #1
0
    def _apply_solver(self, timer: HierarchicalTimer):
        config = self.config

        if config.time_limit is not None:
            timeout = config.time_limit + min(max(1, 0.01 * config.time_limit), 100)
        else:
            timeout = None

        ostreams = [LogStream(level=self.config.log_level, logger=self.config.solver_output_logger)]
        if self.config.stream_solver:
            ostreams.append(sys.stdout)

        cmd = [str(config.executable),
               self._filename + '.nl',
               '-AMPL',
               'option_file_name=' + self._filename + '.opt']
        if 'option_file_name' in self.solver_options:
            raise ValueError('Use Ipopt.config.filename to specify the name of the options file. '
                             'Do not use Ipopt.solver_options["option_file_name"].')
        for k, v in self.solver_options.items():
            cmd.append(str(k) + '=' + str(v))

        with TeeStream(*ostreams) as t:
            timer.start('subprocess')
            cp = subprocess.run(cmd,
                                timeout=timeout,
                                stdout=t.STDOUT,
                                stderr=t.STDERR,
                                universal_newlines=True)
            timer.stop('subprocess')

        if cp.returncode != 0:
            if self.config.load_solution:
                raise RuntimeError('A feasible solution was not found, so no solution can be loaded.'
                                   'Please set opt.config.load_solution=False and check '
                                   'results.termination_condition and '
                                   'results.best_feasible_objective before loading a solution.')
            results = Results()
            results.termination_condition = TerminationCondition.error
            results.best_feasible_objective = None
            self._primal_sol = None
            self._dual_sol = None
        else:
            timer.start('parse solution')
            results = self._parse_sol()
            timer.stop('parse solution')

        if self._writer.get_active_objective() is None:
            results.best_objective_bound = None
        else:
            if self._writer.get_active_objective().sense == minimize:
                results.best_objective_bound = -math.inf
            else:
                results.best_objective_bound = math.inf

        return results
Exemple #2
0
    def _parse_sol(self):
        solve_vars = self._writer.get_ordered_vars()
        solve_cons = self._writer.get_ordered_cons()
        results = Results()

        f = open(self._filename + '.sol', 'r')
        all_lines = list(f.readlines())
        f.close()

        termination_line = all_lines[1]
        if 'Optimal Solution Found' in termination_line:
            results.termination_condition = TerminationCondition.optimal
        elif 'Problem may be infeasible' in termination_line:
            results.termination_condition = TerminationCondition.infeasible
        elif 'problem might be unbounded' in termination_line:
            results.termination_condition = TerminationCondition.unbounded
        elif 'Maximum Number of Iterations Exceeded' in termination_line:
            results.termination_condition = TerminationCondition.maxIterations
        elif 'Maximum CPU Time Exceeded' in termination_line:
            results.termination_condition = TerminationCondition.maxTimeLimit
        else:
            results.termination_condition = TerminationCondition.unknown

        n_cons = len(solve_cons)
        n_vars = len(solve_vars)
        dual_lines = all_lines[12:12 + n_cons]
        primal_lines = all_lines[12 + n_cons:12 + n_cons + n_vars]

        rc_upper_info_line = all_lines[12 + n_cons + n_vars + 1]
        assert rc_upper_info_line.startswith('suffix')
        n_rc_upper = int(rc_upper_info_line.split()[2])
        assert 'ipopt_zU_out' in all_lines[12 + n_cons + n_vars + 2]
        upper_rc_lines = all_lines[12 + n_cons + n_vars + 3:12 + n_cons +
                                   n_vars + 3 + n_rc_upper]

        rc_lower_info_line = all_lines[12 + n_cons + n_vars + 3 + n_rc_upper]
        assert rc_lower_info_line.startswith('suffix')
        n_rc_lower = int(rc_lower_info_line.split()[2])
        assert 'ipopt_zL_out' in all_lines[12 + n_cons + n_vars + 3 +
                                           n_rc_upper + 1]
        lower_rc_lines = all_lines[12 + n_cons + n_vars + 3 + n_rc_upper +
                                   2:12 + n_cons + n_vars + 3 + n_rc_upper +
                                   2 + n_rc_lower]

        self._dual_sol = dict()
        self._primal_sol = ComponentMap()
        self._reduced_costs = ComponentMap()

        for ndx, dual in enumerate(dual_lines):
            dual = float(dual)
            con = solve_cons[ndx]
            self._dual_sol[con] = dual

        for ndx, primal in enumerate(primal_lines):
            primal = float(primal)
            var = solve_vars[ndx]
            self._primal_sol[var] = primal

        for rcu_line in upper_rc_lines:
            split_line = rcu_line.split()
            var_ndx = int(split_line[0])
            rcu = float(split_line[1])
            var = solve_vars[var_ndx]
            self._reduced_costs[var] = rcu

        for rcl_line in lower_rc_lines:
            split_line = rcl_line.split()
            var_ndx = int(split_line[0])
            rcl = float(split_line[1])
            var = solve_vars[var_ndx]
            if var in self._reduced_costs:
                if abs(rcl) > abs(self._reduced_costs[var]):
                    self._reduced_costs[var] = rcl
            else:
                self._reduced_costs[var] = rcl

        for var in solve_vars:
            if var not in self._reduced_costs:
                self._reduced_costs[var] = 0

        if results.termination_condition == TerminationCondition.optimal and self.config.load_solution:
            for v, val in self._primal_sol.items():
                v.set_value(val, skip_validation=True)

            if self._writer.get_active_objective() is None:
                results.best_feasible_objective = None
            else:
                results.best_feasible_objective = value(
                    self._writer.get_active_objective().expr)
        elif results.termination_condition == TerminationCondition.optimal:
            if self._writer.get_active_objective() is None:
                results.best_feasible_objective = None
            else:
                obj_expr_evaluated = replace_expressions(
                    self._writer.get_active_objective().expr,
                    substitution_map={
                        id(v): val
                        for v, val in self._primal_sol.items()
                    },
                    descend_into_named_expressions=True,
                    remove_named_expressions=True)
                results.best_feasible_objective = value(obj_expr_evaluated)
        elif self.config.load_solution:
            raise RuntimeError(
                'A feasible solution was not found, so no solution can be loaded.'
                'Please set opt.config.load_solution=False and check '
                'results.termination_condition and '
                'resutls.best_feasible_objective before loading a solution.')

        results.solution_loader = PersistentSolutionLoader(solver=self)

        return results
Exemple #3
0
    def _apply_solver(self, timer: HierarchicalTimer):
        config = self.config

        if config.time_limit is not None:
            timeout = config.time_limit + min(max(1, 0.01 * config.time_limit), 100)
        else:
            timeout = None

        def _check_and_escape_options():
            for key, val in self.solver_options.items():
                tmp_k = str(key)
                _bad = ' ' in tmp_k

                tmp_v = str(val)
                if ' ' in tmp_v:
                    if '"' in tmp_v:
                        if "'" in tmp_v:
                            _bad = True
                        else:
                            tmp_v = "'" + tmp_v + "'"
                    else:
                        tmp_v = '"' + tmp_v + '"'

                if _bad:
                    raise ValueError("Unable to properly escape solver option:"
                                     "\n\t%s=%s" % (key, val) )
                yield tmp_k, tmp_v

        cmd = [str(config.executable)]
        action_options = list()
        if config.time_limit is not None:
            cmd.extend(['-sec', str(config.time_limit)])
            cmd.extend(['-timeMode', 'elapsed'])
        for key, val in _check_and_escape_options():
            if val.strip() != '':
                cmd.append('-'+key, val)
            else:
                action_options.append('-'+key)
        cmd.extend(['-printingOptions', 'all'])
        cmd.extend(['-import', self._filename + '.lp'])
        cmd.extend(action_options)
        cmd.extend(['-stat=1'])
        cmd.extend(['-solve'])
        cmd.extend(['-solu', self._filename + '.soln'])

        ostreams = [LogStream(level=self.config.log_level, logger=self.config.solver_output_logger)]
        if self.config.stream_solver:
            ostreams.append(sys.stdout)

        with TeeStream(*ostreams) as t:
            timer.start('subprocess')
            cp = subprocess.run(cmd,
                                timeout=timeout,
                                stdout=t.STDOUT,
                                stderr=t.STDERR,
                                universal_newlines=True)
            timer.stop('subprocess')

        if cp.returncode != 0:
            if self.config.load_solution:
                raise RuntimeError('A feasible solution was not found, so no solution can be loaded.'
                                   'Please set opt.config.load_solution=False and check '
                                   'results.termination_condition and '
                                   'results.best_feasible_objective before loading a solution.')
            results = Results()
            results.termination_condition = TerminationCondition.error
            results.best_feasible_objective = None
            self._primal_sol = None
            self._dual_sol = None
            self._reduced_costs = None
        else:
            timer.start('parse solution')
            results = self._parse_soln()
            timer.stop('parse solution')

        if self._writer.get_active_objective() is None:
            results.best_feasible_objective = None
            results.best_objective_bound = None
        else:
            if self._writer.get_active_objective().sense == minimize:
                results.best_objective_bound = -math.inf
            else:
                results.best_objective_bound = math.inf

        return results
Exemple #4
0
    def _parse_soln(self):
        results = Results()

        f = open(self._filename + '.soln', 'r')
        all_lines = list(f.readlines())
        f.close()

        termination_line = all_lines[0].lower()
        obj_val = None
        if termination_line.startswith('optimal'):
            results.termination_condition = TerminationCondition.optimal
            obj_val = float(termination_line.split()[-1])
        elif 'infeasible' in termination_line:
            results.termination_condition = TerminationCondition.infeasible
        elif 'unbounded' in termination_line:
            results.termination_condition = TerminationCondition.unbounded
        elif termination_line.startswith('stopped on time'):
            results.termination_condition = TerminationCondition.maxTimeLimit
            obj_val = float(termination_line.split()[-1])
        elif termination_line.startswith('stopped on iterations'):
            results.termination_condition = TerminationCondition.maxIterations
            obj_val = float(termination_line.split()[-1])
        else:
            results.termination_condition = TerminationCondition.unknown

        first_con_line = None
        last_con_line = None
        first_var_line = None
        last_var_line = None

        for ndx, line in enumerate(all_lines):
            if line.strip('*').strip().startswith('0'):
                if first_con_line is None:
                    first_con_line = ndx
                else:
                    last_con_line = ndx - 1
                    first_var_line = ndx
        last_var_line = len(all_lines) - 1

        self._dual_sol = dict()
        self._primal_sol = dict()
        self._reduced_costs = dict()

        symbol_map = self._writer.symbol_map

        for line in all_lines[first_con_line:last_con_line+1]:
            split_line = line.strip('*')
            split_line = split_line.split()
            name = split_line[1]
            orig_name = name[:-3]
            if orig_name == 'obj_const_con':
                continue
            con = symbol_map.bySymbol[orig_name]()
            dual_val = float(split_line[-1])
            if con in self._dual_sol:
                if abs(dual_val) > abs(self._dual_sol[con]):
                    self._dual_sol[con] = dual_val
            else:
                self._dual_sol[con] = dual_val

        for line in all_lines[first_var_line:last_var_line+1]:
            split_line = line.strip('*')
            split_line = split_line.split()
            name = split_line[1]
            if name == 'obj_const':
                continue
            val = float(split_line[2])
            rc = float(split_line[3])
            var = symbol_map.bySymbol[name]()
            self._primal_sol[id(var)] = (var, val)
            self._reduced_costs[id(var)] = (var, rc)

        if (self.version() < (2, 10, 2) and
                self._writer.get_active_objective() is not None and
                self._writer.get_active_objective().sense == maximize):
            obj_val = -obj_val
            for con, dual_val in self._dual_sol.items():
                self._dual_sol[con] = -dual_val
            for v_id, (v, rc_val) in self._reduced_costs.items():
                self._reduced_costs[v_id] = (v, -rc_val)

        if results.termination_condition == TerminationCondition.optimal and self.config.load_solution:
            for v_id, (v, val) in self._primal_sol.items():
                v.value = val
            if self._writer.get_active_objective() is None:
                results.best_feasible_objective = None
            else:
                results.best_feasible_objective = obj_val
        elif results.termination_condition == TerminationCondition.optimal:
            if self._writer.get_active_objective() is None:
                results.best_feasible_objective = None
            else:
                results.best_feasible_objective = obj_val
        elif self.config.load_solution:
            raise RuntimeError('A feasible solution was not found, so no solution can be loaded.'
                               'Please set opt.config.load_solution=False and check '
                               'results.termination_condition and '
                               'resutls.best_feasible_objective before loading a solution.')

        return results