def __init__(self, **kwds): # # Call base class constructor # kwds['type'] = 'cplexpersistent' CPLEXDirect.__init__(self, **kwds) # maps pyomo var data labels to the corresponding CPLEX variable id. self._cplex_variable_ids = {} self._cplex_variable_names = None
def _presolve(self, *args, **kwds): if self._active_cplex_instance is None: raise RuntimeError("***The CPLEXPersistent solver plugin" " cannot presolve - no instance is " "presently compiled") # These must be passed in to the compile_instance method, # but assert that any values here match those already supplied if 'symbolic_solver_labels' in kwds: assert self._symbolic_solver_labels == \ kwds['symbolic_solver_labels'] if 'output_fixed_variable_bounds' in kwds: assert self._output_fixed_variable_bounds == \ kwds['output_fixed_variable_bounds'] if 'skip_trivial_constraints' in kwds: assert self._skip_trivial_constraints == \ kwds["skip_trivial_constraints"] if self._smap_id not in self._instance.solutions.symbol_map: self._instance.solutions.add_symbol_map(self._symbol_map) CPLEXDirect._presolve(self, *args, **kwds) # like other solver plugins, persistent solver plugins can # take an instance as an input argument. the only context in # which this instance is used, however, is for warm-starting. if len(args) > 2: raise ValueError("The CPLEXPersistent plugin method " "'_presolve' can be supplied at most " "one problem instance - %s were " "supplied" % len(args)) # Re-add the symbol map id if it was cleared # after a previous solution load if id(self._symbol_map) not in args[0].solutions.symbol_map: args[0].solutions.add_symbol_map(self._symbol_map) self._smap_id = id(self._symbol_map)
def _apply_solver(self): if self._active_cplex_instance is None: raise RuntimeError("***The CPLEXPersistent solver plugin cannot " "apply solver - no instance is presently compiled") # NOTE: # CPLEX maintains the pool of feasible solutions from the # prior solve as the set of mip starts for the next solve. # and evaluating multiple mip starts (and there can be many) # is expensive. so if the warm_start method is not invoked, # there will potentially be a lot of time wasted. return CPLEXDirect._apply_solver(self)
def _postsolve(self): if self._active_cplex_instance is None: raise RuntimeError("***The CPLEXPersistent solver plugin " "cannot postsolve - no instance is " "presently compiled") active_cplex_instance = self._active_cplex_instance variable_symbol_map = self._variable_symbol_map instance = self._instance ret = CPLEXDirect._postsolve(self) # # These get reset to None by the base class method # self._active_cplex_instance = active_cplex_instance self._variable_symbol_map = variable_symbol_map self._instance = instance return ret
def _presolve(self, *args, **kwds): if self._active_cplex_instance is None: raise RuntimeError("***The CPLEXPersistent solver plugin" " cannot presolve - no instance is " "presently compiled") # These must be passed in to the compile_instance method, # but assert that any values here match those already supplied if 'symbolic_solver_labels' in kwds: assert self._symbolic_solver_labels == \ kwds['symbolic_solver_labels'] if 'output_fixed_variable_bounds' in kwds: assert self._output_fixed_variable_bounds == \ kwds['output_fixed_variable_bounds'] if 'skip_trivial_constraints' in kwds: assert self._skip_trivial_constraints == \ kwds["skip_trivial_constraints"] if isinstance(self._instance, IBlockStorage): # BIG HACK if not hasattr(self._instance, "._symbol_maps"): setattr(self._instance, "._symbol_maps", {}) getattr(self._instance, "._symbol_maps")[id(self._symbol_map)] = \ self._symbol_map else: if self._smap_id not in self._instance.solutions.symbol_map: self._instance.solutions.add_symbol_map(self._symbol_map) ################################################ # populate the problem type in the cplex model # ################################################ # This gets rid of the annoying "Freeing MIP data." message. def _filter_freeing_mip_data(val): if val.strip() == 'Freeing MIP data.': return "" return val self._active_cplex_instance.set_warning_stream(sys.stderr, fn=_filter_freeing_mip_data) if (self._has_quadratic_objective is True) or \ (self._has_quadratic_constraints is True): if (self._num_integer_variables > 0) or \ (self._num_binary_variables > 0) or \ (self._used_sos_constraints): if self._has_quadratic_constraints is True: self._active_cplex_instance.set_problem_type( self._active_cplex_instance.problem_type.MIQCP) else: self._active_cplex_instance.set_problem_type( self._active_cplex_instance.problem_type.MIQP) else: if self._has_quadratic_constraints is True: self._active_cplex_instance.set_problem_type( self._active_cplex_instance.problem_type.QCP) else: self._active_cplex_instance.set_problem_type( self._active_cplex_instance.problem_type.QP) elif (self._num_integer_variables > 0) or \ (self._num_binary_variables > 0) or \ (self._used_sos_constraints): self._active_cplex_instance.set_problem_type( self._active_cplex_instance.problem_type.MILP) else: self._active_cplex_instance.set_problem_type( self._active_cplex_instance.problem_type.LP) # restore the warning stream without our filter function self._active_cplex_instance.set_warning_stream(sys.stderr) CPLEXDirect._presolve(self, *args, **kwds) # like other solver plugins, persistent solver plugins can # take an instance as an input argument. the only context in # which this instance is used, however, is for warm-starting. if len(args) > 2: raise ValueError("The CPLEXPersistent plugin method " "'_presolve' can be supplied at most " "one problem instance - %s were " "supplied" % len(args)) # Re-add the symbol map id if it was cleared # after a previous solution load if id(self._symbol_map) not in args[0].solutions.symbol_map: args[0].solutions.add_symbol_map(self._symbol_map) self._smap_id = id(self._symbol_map)