Source code for ellpy.problem

from .cutting_plane import CUTStatus, Options, cutting_plane_dc


[docs]class Problem: _optim_value = None _optim_var = None _status = None _solver_stats = None # REGISTERED_SOLVE_METHODS = {} def __init__(self, S, oracle, options=Options()): """[summary] Arguments: S ([type]): [description] oracle ([type]): [description] Keyword Arguments: options ([type]): [description] (default: {Options()}) """ self.S = S self.oracle = oracle self.options = options @property def optim_value(self): """The optimal value from the last time the problem was solved. Returns ------- float or None """ return self._optim_value @property def optim_var(self): """The optimal value from the last time the problem was solved. Returns ------- x_best or None """ return self._optim_var @property def status(self): """The status from the last time the problem was solved. Returns ------- str """ return self._status @property def solver_stats(self): """Returns an object containing additional information returned by the solver. """ return self._solver_stats
[docs] def solve(self, *args, **kwargs): """Solves the problem using the specified method. Parameters ---------- method : function The solve method to use. solver : str, optional The solver to use. verbose : bool, optional Overrides the default of hiding solver output. solver_specific_opts : dict, optional A dict of options that will be passed to the specific solver. In general, these options will override any default settings imposed by cvxpy. Returns ------- float The optimal value for the problem, or a string indicating why the problem could not be solved. """ # func_name = kwargs.pop("method", None) # if func_name: # func = Problem.REGISTERED_SOLVE_METHODS[func_name] # return func(self, *args, **kwargs) return self._solve(*args, **kwargs)
# @classmethod # def register_solve(cls, name, func): # """Adds a solve method to the Problem class. # Parameters # ---------- # name : str # The keyword for the method. # func : function # The function that executes the solve method. # """ # cls.REGISTERED_SOLVE_METHODS[name] = func def _solve(self, t # solver=None, # warm_start=False, # verbose=False, **kwargs ): """Solves a DCP compliant optimization problem. Saves the values of primal and dual variables in the variable and constraint objects, respectively. Parameters ---------- t : Best-so-far value solver : str, optional The solver to use. Defaults to cutting_plane_dc warm_start : bool, optional Should the previous solver result be used to warm start? verbose : bool, optional Overrides the default of hiding solver output. kwargs : dict, optional A dict of options that will be passed to the specific solver. In general, these options will override any default settings imposed by ellpy. Returns ------- float The optimal value for the problem, or a string indicating why the problem could not be solved. """ xb, fb, ell_info = cutting_plane_dc(self.oracle, self.S, t, self.options) num_iters = ell_info.num_iters status = ell_info.status if ell_info.feasible: if status == CUTStatus.smallenough: self._status = 'optimal' else: self._status = 'feasible' self._optim_value = fb self._optim_var = xb else: self._status = 'infeasible' solver_stats = SolverStats('deep-cut') solver_stats.num_iters = num_iters self._solver_stats = solver_stats return self.optim_value
# def _handle_no_solution(self, status): # """Updates value fields when the problem is infeasible or unbounded. # Parameters # ---------- # status: str # The status of the solver. # """ # # Set all primal and dual variable values to None. # for var_ in self.variables(): # var_.save_value(None) # for constr in self.constraints: # constr.save_value(None) # # Set the problem value. # if status in [s.INFEASIBLE, s.INFEASIBLE_INACCURATE]: # self._value = self.objective.primal_to_result(np.inf) # elif status in [s.UNBOUNDED, s.UNBOUNDED_INACCURATE]: # self._value = self.objective.primal_to_result(-np.inf)
[docs]class SolverStats: """Reports some of the miscellaneous information that is returned by the solver after solving but that is not captured directly by the Problem instance. Attributes ---------- num_iters : int The number of iterations the solver had to go through to find a solution. """ def __init__(self, solver_name): """[summary] Arguments: solver_name ([type]): [description] """ self.solver_name = solver_name self.num_iters = None