def invert(self, solution, inverse_data): """Returns the solution to the original problem given the inverse_data. """ status = self.STATUS_MAP[solution["info"]["status"]] attr = {} attr[s.SOLVE_TIME] = solution["info"]["solveTime"] attr[s.SETUP_TIME] = solution["info"]["setupTime"] attr[s.NUM_ITERS] = solution["info"]["iter"] if status in s.SOLUTION_PRESENT: primal_val = solution["info"]["pobj"] opt_val = primal_val + inverse_data[s.OFFSET] # TODO expand primal and dual variables from lower triangular to full. # TODO but this makes map from solution to variables not a slice. primal_vars = { inverse_data[SCS.VAR_ID]: solution["x"] } eq_dual_vars = utilities.get_dual_values( solution["y"][:inverse_data[ConicSolver.DIMS].zero], self.extract_dual_value, inverse_data[SCS.EQ_CONSTR] ) ineq_dual_vars = utilities.get_dual_values( solution["y"][inverse_data[ConicSolver.DIMS].zero:], self.extract_dual_value, inverse_data[SCS.NEQ_CONSTR] ) dual_vars = {} dual_vars.update(eq_dual_vars) dual_vars.update(ineq_dual_vars) return Solution(status, opt_val, primal_vars, dual_vars, attr) else: return failure_solution(status)
def invert(self, solution, inverse_data): """Returns solution to original problem, given inverse_data. """ status = self.STATUS_MAP[solution['info']['exitFlag']] # Timing data attr = {} attr[s.SOLVE_TIME] = solution["info"]["timing"]["tsolve"] attr[s.SETUP_TIME] = solution["info"]["timing"]["tsetup"] attr[s.NUM_ITERS] = solution["info"]["iter"] if status in s.SOLUTION_PRESENT: primal_val = solution['info']['pcost'] opt_val = primal_val + inverse_data[s.OFFSET] primal_vars = { inverse_data[self.VAR_ID]: intf.DEFAULT_INTF.const_to_matrix(solution['x']) } eq_dual = utilities.get_dual_values( solution['y'], utilities.extract_dual_value, inverse_data[self.EQ_CONSTR]) leq_dual = utilities.get_dual_values( solution['z'], utilities.extract_dual_value, inverse_data[self.NEQ_CONSTR]) eq_dual.update(leq_dual) dual_vars = eq_dual return Solution(status, opt_val, primal_vars, dual_vars, attr) else: return failure_solution(status)
def invert(self, solution: Dict[str, Any], inverse_data: Dict[str, Any]) -> Solution: """Returns the solution to the original problem given the inverse_data.""" status = solution['status'] dual_vars = None if status in s.SOLUTION_PRESENT: opt_val = solution['value'] + inverse_data[s.OFFSET] primal_vars = {inverse_data[SCIP.VAR_ID]: solution['primal']} if "eq_dual" in solution and not inverse_data['is_mip']: eq_dual = utilities.get_dual_values( result_vec=solution['eq_dual'], parse_func=utilities.extract_dual_value, constraints=inverse_data[SCIP.EQ_CONSTR], ) leq_dual = utilities.get_dual_values( result_vec=solution['ineq_dual'], parse_func=utilities.extract_dual_value, constraints=inverse_data[SCIP.NEQ_CONSTR], ) eq_dual.update(leq_dual) dual_vars = eq_dual return Solution(status, opt_val, primal_vars, dual_vars, {}) else: return failure_solution(status)
def invert(self, solution, inverse_data): """Returns the solution to the original problem given the inverse_data. """ status = solution[s.STATUS] primal_vars = None dual_vars = None if status in s.SOLUTION_PRESENT: opt_val = solution['getObjVal'] + inverse_data[s.OFFSET] primal_vars = {inverse_data[XPRESS.VAR_ID]: solution['primal']} if not inverse_data['is_mip']: eq_dual = utilities.get_dual_values( solution['eq_dual'], utilities.extract_dual_value, inverse_data[XPRESS.EQ_CONSTR]) leq_dual = utilities.get_dual_values( solution['ineq_dual'], utilities.extract_dual_value, inverse_data[XPRESS.NEQ_CONSTR]) eq_dual.update(leq_dual) dual_vars = eq_dual else: if status == s.INFEASIBLE: opt_val = np.inf elif status == s.UNBOUNDED: opt_val = -np.inf else: opt_val = None other = {} other[s.XPRESS_IIS] = solution[s.XPRESS_IIS] other[s.XPRESS_TROW] = solution[s.XPRESS_TROW] other[s.SOLVE_TIME] = solution[s.SOLVE_TIME] return Solution(status, opt_val, primal_vars, dual_vars, other)
def invert(self, solution, inverse_data): """Returns the solution to the original problem given the inverse_data. """ status = solution['status'] if status in s.SOLUTION_PRESENT: opt_val = solution['value'] primal_vars = {inverse_data[self.VAR_ID]: solution['primal']} eq_dual = utilities.get_dual_values(solution['eq_dual'], utilities.extract_dual_value, inverse_data[Solver.EQ_CONSTR]) leq_dual = utilities.get_dual_values( solution['ineq_dual'], utilities.extract_dual_value, inverse_data[Solver.NEQ_CONSTR]) eq_dual.update(leq_dual) dual_vars = eq_dual else: if status == s.INFEASIBLE: opt_val = np.inf elif status == s.UNBOUNDED: opt_val = -np.inf else: opt_val = None primal_vars = None dual_vars = None return Solution(status, opt_val, primal_vars, dual_vars, {})
def invert(self, solution, inverse_data): """Returns solution to original problem, given inverse_data. """ status = self.STATUS_MAP[solution['info']['exitFlag']] if status in s.SOLUTION_PRESENT: primal_val = solution['info']['pcost'] opt_val = primal_val + inverse_data[s.OFFSET] primal_vars = { inverse_data[self.VAR_ID]: intf.DEFAULT_INTF.const_to_matrix(solution['x']) } dual_vars = None if not inverse_data['is_mip']: eq_dual = utilities.get_dual_values( solution['y'], utilities.extract_dual_value, inverse_data[self.EQ_CONSTR]) leq_dual = utilities.get_dual_values( solution['z'], utilities.extract_dual_value, inverse_data[self.NEQ_CONSTR]) eq_dual.update(leq_dual) dual_vars = eq_dual return Solution(status, opt_val, primal_vars, dual_vars, {}) else: return failure_solution(status)
def invert(self, solution, inverse_data): """Returns the solution to the original problem given the inverse_data. """ status = solution['status'] attr = { s.EXTRA_STATS: solution['model'], s.SOLVE_TIME: solution[s.SOLVE_TIME] } primal_vars = None dual_vars = None if status in s.SOLUTION_PRESENT: opt_val = solution['value'] + inverse_data[s.OFFSET] primal_vars = {inverse_data[GUROBI.VAR_ID]: solution['primal']} if "eq_dual" in solution and not inverse_data['is_mip']: eq_dual = utilities.get_dual_values( solution['eq_dual'], utilities.extract_dual_value, inverse_data[GUROBI.EQ_CONSTR]) leq_dual = utilities.get_dual_values( solution['ineq_dual'], utilities.extract_dual_value, inverse_data[GUROBI.NEQ_CONSTR]) eq_dual.update(leq_dual) dual_vars = eq_dual return Solution(status, opt_val, primal_vars, dual_vars, attr) else: return failure_solution(status, attr)
def invert(self, solution, inverse_data): """Returns solution to original problem, given inverse_data. """ status = self.STATUS_MAP[solution['info']['exitFlag']] # Timing data attr = {} attr[s.SOLVE_TIME] = solution["info"]["timing"]["tsolve"] attr[s.SETUP_TIME] = solution["info"]["timing"]["tsetup"] attr[s.NUM_ITERS] = solution["info"]["iter"] if status in s.SOLUTION_PRESENT: primal_val = solution['info']['pcost'] opt_val = primal_val + inverse_data[s.OFFSET] primal_vars = { inverse_data[self.VAR_ID]: intf.DEFAULT_INTF.const_to_matrix(solution['x']) } dual_vars = utilities.get_dual_values( solution['z'], utilities.extract_dual_value, inverse_data[self.NEQ_CONSTR]) for con in inverse_data[self.NEQ_CONSTR]: if isinstance(con, ExpCone): cid = con.id n_cones = con.num_cones() perm = utilities.expcone_permutor(n_cones, ECOS.EXP_CONE_ORDER) dual_vars[cid] = dual_vars[cid][perm] eq_duals = utilities.get_dual_values(solution['y'], utilities.extract_dual_value, inverse_data[self.EQ_CONSTR]) dual_vars.update(eq_duals) return Solution(status, opt_val, primal_vars, dual_vars, attr) else: return failure_solution(status)
def invert(self, solution, inverse_data): """Returns the solution to the original problem given the inverse_data. """ status = self.STATUS_MAP[solution["info"]["status"]] attr = {} attr[s.SOLVE_TIME] = solution["info"]["solveTime"] attr[s.SETUP_TIME] = solution["info"]["setupTime"] attr[s.NUM_ITERS] = solution["info"]["iter"] if status in s.SOLUTION_PRESENT: primal_val = solution["info"]["pobj"] opt_val = primal_val + inverse_data[s.OFFSET] primal_vars = { inverse_data[SCS.VAR_ID]: intf.DEFAULT_INTF.const_to_matrix(solution["x"]) } eq_dual_vars = utilities.get_dual_values( intf.DEFAULT_INTF.const_to_matrix( solution["y"][:inverse_data[ConicSolver.DIMS].zero]), self.extract_dual_value, inverse_data[SCS.EQ_CONSTR]) ineq_dual_vars = utilities.get_dual_values( intf.DEFAULT_INTF.const_to_matrix( solution["y"][inverse_data[ConicSolver.DIMS].zero:]), self.extract_dual_value, inverse_data[SCS.NEQ_CONSTR]) dual_vars = {} dual_vars.update(eq_dual_vars) dual_vars.update(ineq_dual_vars) return Solution(status, opt_val, primal_vars, dual_vars, attr) else: return failure_solution(status)
def invert(self, solution, inverse_data): """Returns the solution to the original problem given the inverse_data. """ status = self.STATUS_MAP[solution['status']] primal_vars = None dual_vars = None if status in s.SOLUTION_PRESENT: primal_val = solution['fun'] opt_val = primal_val + inverse_data[s.OFFSET] primal_vars = {inverse_data[self.VAR_ID]: solution['x']} # SciPy linprog only returns duals for version >= 1.7.0 # and method is one of 'highs', 'highs-ds' or 'highs-ipm' if ('ineqlin' in solution.keys()): eq_dual = utilities.get_dual_values( -solution['eqlin']['marginals'], utilities.extract_dual_value, inverse_data[self.EQ_CONSTR]) leq_dual = utilities.get_dual_values( -solution['ineqlin']['marginals'], utilities.extract_dual_value, inverse_data[self.NEQ_CONSTR]) eq_dual.update(leq_dual) dual_vars = eq_dual return Solution(status, opt_val, primal_vars, dual_vars, {}) else: return failure_solution(status)
def invert(self, solution, inverse_data): """Returns the solution to the original problem given the inverse_data. """ model = solution["model"] attr = {} if s.SOLVE_TIME in solution: attr[s.SOLVE_TIME] = solution[s.SOLVE_TIME] status = get_status(model) primal_vars = None dual_vars = None if status in s.SOLUTION_PRESENT: opt_val = (model.solution.get_objective_value() + inverse_data[s.OFFSET]) x = np.array(model.solution.get_values()) primal_vars = {inverse_data[CPLEX.VAR_ID]: x} if not inverse_data['is_mip']: # The dual values are retrieved in the order that the # constraints were added in solve_via_data() below. We # must be careful to map them to inverse_data[EQ_CONSTR] # followed by inverse_data[NEQ_CONSTR] accordingly. y = -np.array(model.solution.get_dual_values()) dual_vars = utilities.get_dual_values( y, utilities.extract_dual_value, inverse_data[CPLEX.EQ_CONSTR] + inverse_data[CPLEX.NEQ_CONSTR]) return Solution(status, opt_val, primal_vars, dual_vars, attr) else: return failure_solution(status)
def invert(self, solution, inverse_data): """Returns the solution to the original problem given the inverse_data. """ status = solution[s.STATUS] primal_vars = None dual_vars = None if status in s.SOLUTION_PRESENT: opt_val = solution[s.VALUE] primal_vars = {inverse_data[XPRESS.VAR_ID]: solution['primal']} if not inverse_data['is_mip']: dual_vars = utilities.get_dual_values( solution[s.EQ_DUAL], utilities.extract_dual_value, inverse_data[s.EQ_CONSTR]) else: if status == s.INFEASIBLE: opt_val = np.inf elif status == s.UNBOUNDED: opt_val = -np.inf else: opt_val = None other = {} other[s.XPRESS_IIS] = solution[s.XPRESS_IIS] other[s.XPRESS_TROW] = solution[s.XPRESS_TROW] return Solution(status, opt_val, primal_vars, dual_vars, other)
def invert(self, solution, inverse_data): """Returns the solution to the original problem given the inverse_data. """ attr = {} if solution["solve_method"] == s.SCS: import scs if Version(scs.__version__) < Version('3.0.0'): status = scs_conif.SCS.STATUS_MAP[solution["info"]["statusVal"]] attr[s.SOLVE_TIME] = solution["info"]["solveTime"] attr[s.SETUP_TIME] = solution["info"]["setupTime"] else: status = scs_conif.SCS.STATUS_MAP[solution["info"]["status_val"]] attr[s.SOLVE_TIME] = solution["info"]["solve_time"] attr[s.SETUP_TIME] = solution["info"]["setup_time"] elif solution["solve_method"] == s.ECOS: status = self.STATUS_MAP[solution["info"]["status"]] attr[s.SOLVE_TIME] = solution["info"]["solveTime"] attr[s.SETUP_TIME] = solution["info"]["setupTime"] attr[s.NUM_ITERS] = solution["info"]["iter"] attr[s.EXTRA_STATS] = solution if status in s.SOLUTION_PRESENT: primal_val = solution["info"]["pobj"] opt_val = primal_val + inverse_data[s.OFFSET] # TODO expand primal and dual variables from lower triangular to full. # TODO but this makes map from solution to variables not a slice. primal_vars = { inverse_data[DIFFCP.VAR_ID]: solution["x"] } eq_dual_vars = utilities.get_dual_values( solution["y"][:inverse_data[ConicSolver.DIMS].zero], self.extract_dual_value, inverse_data[DIFFCP.EQ_CONSTR] ) ineq_dual_vars = utilities.get_dual_values( solution["y"][inverse_data[ConicSolver.DIMS].zero:], self.extract_dual_value, inverse_data[DIFFCP.NEQ_CONSTR] ) dual_vars = {} dual_vars.update(eq_dual_vars) dual_vars.update(ineq_dual_vars) return Solution(status, opt_val, primal_vars, dual_vars, attr) else: return failure_solution(status, attr)
def invert(self, solution, inverse_data): """Returns the solution to the original problem given the inverse_data. """ status = solution['status'] if status in s.SOLUTION_PRESENT: opt_val = solution['value'] + inverse_data[s.OFFSET] primal_vars = {inverse_data[self.VAR_ID]: solution['primal']} eq_dual = utilities.get_dual_values(solution[s.EQ_DUAL], utilities.extract_dual_value, inverse_data[self.EQ_CONSTR]) leq_dual = utilities.get_dual_values(solution[s.INEQ_DUAL], utilities.extract_dual_value, inverse_data[self.NEQ_CONSTR]) eq_dual.update(leq_dual) dual_vars = eq_dual return Solution(status, opt_val, primal_vars, dual_vars, {}) else: return failure_solution(status)
def invert(self, solution: Dict[str, Any], inverse_data: Dict[str, Any]) -> Solution: """Returns the solution to the original problem.""" status = solution["status"] if status in s.SOLUTION_PRESENT: primal_vars = {inverse_data[self.VAR_ID]: solution["primal"]} dual_vars = utilities.get_dual_values( result_vec=solution["dual"], parse_func=utilities.extract_dual_value, constraints=inverse_data["constraints"], ) return Solution(status, solution["value"], primal_vars, dual_vars, {}) else: return failure_solution(status)
def invert(self, results, inverse_data): model = results["model"] attr = {} if "cputime" in results: attr[s.SOLVE_TIME] = results["cputime"] attr[s.NUM_ITERS] = \ int(model.solution.progress.get_num_barrier_iterations()) \ if not inverse_data.is_mip \ else 0 status = self.STATUS_MAP.get(model.solution.get_status(), s.SOLVER_ERROR) if status in s.SOLUTION_PRESENT: # Get objective value opt_val = model.solution.get_objective_value() # Get solution x = np.array(model.solution.get_values()) primal_vars = { list(inverse_data.id_map.keys())[0]: intf.DEFAULT_INTF.const_to_matrix(np.array(x)) } # Only add duals if not a MIP. dual_vars = None if not inverse_data.is_mip: y = -np.array(model.solution.get_dual_values()) dual_vars = utilities.get_dual_values( intf.DEFAULT_INTF.const_to_matrix(y), utilities.extract_dual_value, inverse_data.sorted_constraints) else: primal_vars = None dual_vars = None opt_val = np.inf if status == s.UNBOUNDED: opt_val = -np.inf return Solution(status, opt_val, primal_vars, dual_vars, attr)
def invert(self, results, inverse_data): model = results["model"] x_grb = model.getVars() n = len(x_grb) constraints_grb = model.getConstrs() m = len(constraints_grb) # Start populating attribute dictionary attr = {s.SOLVE_TIME: model.Runtime, s.NUM_ITERS: model.BarIterCount} # Map GUROBI statuses back to CVXPY statuses status = self.STATUS_MAP.get(model.Status, s.SOLVER_ERROR) if status in s.SOLUTION_PRESENT: opt_val = model.objVal x = np.array([x_grb[i].X for i in range(n)]) primal_vars = { list(inverse_data.id_map.keys())[0]: intf.DEFAULT_INTF.const_to_matrix(np.array(x)) } # Only add duals if not a MIP. dual_vars = None if not inverse_data.is_mip: y = -np.array([constraints_grb[i].Pi for i in range(m)]) dual_vars = utilities.get_dual_values( intf.DEFAULT_INTF.const_to_matrix(y), utilities.extract_dual_value, inverse_data.sorted_constraints) else: primal_vars = None dual_vars = None opt_val = np.inf if status == s.UNBOUNDED: opt_val = -np.inf return Solution(status, opt_val, primal_vars, dual_vars, attr)
def invert(self, solution, inverse_data): attr = {s.SOLVE_TIME: solution.info.run_time} # Map OSQP statuses back to CVXPY statuses status = self.STATUS_MAP.get(solution.info.status_val, s.SOLVER_ERROR) if status in s.SOLUTION_PRESENT: opt_val = solution.info.obj_val primal_vars = { list(inverse_data.id_map.keys())[0]: intf.DEFAULT_INTF.const_to_matrix(np.array(solution.x)) } dual_vars = utilities.get_dual_values( intf.DEFAULT_INTF.const_to_matrix(solution.y), utilities.extract_dual_value, inverse_data.sorted_constraints) attr[s.NUM_ITERS] = solution.info.iter else: primal_vars = None dual_vars = None opt_val = np.inf if status == s.UNBOUNDED: opt_val = -np.inf return Solution(status, opt_val, primal_vars, dual_vars, attr)