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
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
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
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