boundml.solvers
155class DefaultScipSolver(ScipSolver): 156 """ 157 Default scip solver. 158 Solve the instances based on the given scip parameters. 159 """ 160 def __init__(self, branching_strategy: Optional[str] = None, *args, **kwargs): 161 """ 162 Parameters 163 ---------- 164 branching_strategy : Optional[str] 165 Branching strategy to use. Must be a default SCIP strategy, or a strategy included in the Model using 166 the configure callback. 167 If None (default). It will use the default strategy of SCIP as set in the parameters. 168 args : 169 Arguments to build the parent class ScipSolver 170 kwargs : 171 Arguments to build the parent class ScipSolver 172 """ 173 super().__init__(*args, **kwargs) 174 self.branching_strategy = branching_strategy 175 176 def build_model(self): 177 super().build_model() 178 if self.branching_strategy is not None: 179 self.model.setParam(f"branching/{self.branching_strategy}/priority", 9999999) 180 181 182 def solve(self, instance: str): 183 self.build_model() 184 self.model.readProblem(instance) 185 self.model.optimize() 186 187 def __str__(self): 188 return self.branching_strategy
Default scip solver. Solve the instances based on the given scip parameters.
DefaultScipSolver(branching_strategy: Optional[str] = None, *args, **kwargs)
160 def __init__(self, branching_strategy: Optional[str] = None, *args, **kwargs): 161 """ 162 Parameters 163 ---------- 164 branching_strategy : Optional[str] 165 Branching strategy to use. Must be a default SCIP strategy, or a strategy included in the Model using 166 the configure callback. 167 If None (default). It will use the default strategy of SCIP as set in the parameters. 168 args : 169 Arguments to build the parent class ScipSolver 170 kwargs : 171 Arguments to build the parent class ScipSolver 172 """ 173 super().__init__(*args, **kwargs) 174 self.branching_strategy = branching_strategy
Parameters
- branching_strategy (Optional[str]): Branching strategy to use. Must be a default SCIP strategy, or a strategy included in the Model using the configure callback. If None (default). It will use the default strategy of SCIP as set in the parameters.
- args :: Arguments to build the parent class ScipSolver
- kwargs :: Arguments to build the parent class ScipSolver
12class ModularSolver(ScipSolver): 13 """ 14 A ModularSolver is ScipSolver that is parametrized with a list of Component 15 """ 16 17 def __init__(self, *components: Component, scip_params = None, configure: Callable[[Model], None] = None): 18 """ 19 Parameters 20 ---------- 21 components : [Component] 22 List of components that parametrized the solver. During a solving process, they are called depending on 23 their subtypes (e.g. BranchingComponent are called before making a branching strategy). If several 24 components have the same subtypes, they are called in the order they are given. Only the first component 25 of each subtype is allowed to perform an action (with passive=False). The other must remain passive. 26 scip_params : dict, optional 27 Dictionary of parameters to pass to the scip solver. 28 configure : Callable[[Model], None], optional 29 Callback function to configure the solver (e.g. add branching strategies, ...) 30 """ 31 super().__init__(scip_params, configure) 32 33 self.components = ComponentList(list(components)) 34 self.branching_components = [] 35 36 for component in components: 37 if isinstance(component, BranchingComponent): 38 self.branching_components.append(component) 39 40 41 42 def build_model(self): 43 super().build_model() 44 branchrule = BoundmlBranchrule(self.model, self.branching_components) 45 self.model.includeBranchrule( 46 branchrule, 47 "boundml", 48 "Custom branching rule for ModularSolver", 49 priority=10000000, 50 maxdepth=-1, 51 maxbounddist=1 52 ) 53 54 def solve(self, instance: str): 55 self.build_model() 56 57 self.model.readProblem(instance) 58 59 self.components.reset(self.model) 60 61 self.model.optimize() 62 63 self.components.done(self.model) 64 65 def __str__(self): 66 return "+".join([str(c) for c in self.components])
A ModularSolver is ScipSolver that is parametrized with a list of Component
ModularSolver( *components: boundml.components.Component, scip_params=None, configure: Callable[[pyscipopt.scip.Model], NoneType] = None)
17 def __init__(self, *components: Component, scip_params = None, configure: Callable[[Model], None] = None): 18 """ 19 Parameters 20 ---------- 21 components : [Component] 22 List of components that parametrized the solver. During a solving process, they are called depending on 23 their subtypes (e.g. BranchingComponent are called before making a branching strategy). If several 24 components have the same subtypes, they are called in the order they are given. Only the first component 25 of each subtype is allowed to perform an action (with passive=False). The other must remain passive. 26 scip_params : dict, optional 27 Dictionary of parameters to pass to the scip solver. 28 configure : Callable[[Model], None], optional 29 Callback function to configure the solver (e.g. add branching strategies, ...) 30 """ 31 super().__init__(scip_params, configure) 32 33 self.components = ComponentList(list(components)) 34 self.branching_components = [] 35 36 for component in components: 37 if isinstance(component, BranchingComponent): 38 self.branching_components.append(component)
Parameters
- components ([Component]): List of components that parametrized the solver. During a solving process, they are called depending on their subtypes (e.g. BranchingComponent are called before making a branching strategy). If several components have the same subtypes, they are called in the order they are given. Only the first component of each subtype is allowed to perform an action (with passive=False). The other must remain passive.
- scip_params (dict, optional): Dictionary of parameters to pass to the scip solver.
- configure (Callable[[Model], None], optional): Callback function to configure the solver (e.g. add branching strategies, ...)
def
solve(self, instance: str):
54 def solve(self, instance: str): 55 self.build_model() 56 57 self.model.readProblem(instance) 58 59 self.components.reset(self.model) 60 61 self.model.optimize() 62 63 self.components.done(self.model)
Solves a instancse that is a file
Parameters
- instance (str): Path to the instance
class
Solver(abc.ABC):
8class Solver(ABC): 9 """ 10 An abstract base class for solvers. 11 """ 12 13 def __init__(self): 14 self.seed = 0 15 self.items_collectors = {} 16 17 18 def set_seed(self, seed): 19 """ 20 Seed used by the underground solver. 21 Parameters 22 ---------- 23 seed : int 24 The new seed 25 """ 26 self.seed = seed 27 28 @abstractmethod 29 def solve(self, instance: str): 30 """ 31 Solves a instancse that is a file 32 Parameters 33 ---------- 34 instance : str 35 Path to the instance 36 """ 37 raise NotImplementedError("Subclasses must implement this method.") 38 39 def solve_model(self, model: Model): 40 """ 41 Solve directly a pyscipopt model. 42 Can work even if the underlying solver is not SCIP, as it only write the corresponding problem to a file in 43 order to use the method solve 44 Parameters 45 ---------- 46 model : Model 47 model to solve. 48 """ 49 model.setParam("display/verblevel", 0) 50 prob_file = tempfile.NamedTemporaryFile(suffix=".lp") 51 model.writeProblem(prob_file.name, verbose=False) 52 53 self.solve(prob_file.name) 54 prob_file.close() 55 56 def add_item(self, name: str, callback): 57 """ 58 Add a callback to compute a specific metric. Used when accessing solver["metric"] 59 Parameters 60 ---------- 61 name : Name of th metric added 62 callback : Function that return the metric value given the Solver 63 """ 64 self.items_collectors[name] = callback 65 66 def __getitem__(self, item: str) -> float: 67 """ 68 Get an attribute from the solver after a solving process. 69 70 Parameters 71 ---------- 72 item : str 73 Name of the attribute to get. Depends on the subtype of the solver. 74 75 Returns 76 ------- 77 Value of the attribute. 78 """ 79 if item in self.items_collectors: 80 return self.items_collectors[item](self) 81 raise KeyError(item)
An abstract base class for solvers.
def
set_seed(self, seed):
18 def set_seed(self, seed): 19 """ 20 Seed used by the underground solver. 21 Parameters 22 ---------- 23 seed : int 24 The new seed 25 """ 26 self.seed = seed
Seed used by the underground solver.
Parameters
- seed (int): The new seed
@abstractmethod
def
solve(self, instance: str):
28 @abstractmethod 29 def solve(self, instance: str): 30 """ 31 Solves a instancse that is a file 32 Parameters 33 ---------- 34 instance : str 35 Path to the instance 36 """ 37 raise NotImplementedError("Subclasses must implement this method.")
Solves a instancse that is a file
Parameters
- instance (str): Path to the instance
def
solve_model(self, model: pyscipopt.scip.Model):
39 def solve_model(self, model: Model): 40 """ 41 Solve directly a pyscipopt model. 42 Can work even if the underlying solver is not SCIP, as it only write the corresponding problem to a file in 43 order to use the method solve 44 Parameters 45 ---------- 46 model : Model 47 model to solve. 48 """ 49 model.setParam("display/verblevel", 0) 50 prob_file = tempfile.NamedTemporaryFile(suffix=".lp") 51 model.writeProblem(prob_file.name, verbose=False) 52 53 self.solve(prob_file.name) 54 prob_file.close()
Solve directly a pyscipopt model. Can work even if the underlying solver is not SCIP, as it only write the corresponding problem to a file in order to use the method solve
Parameters
- model (Model): model to solve.
def
add_item(self, name: str, callback):
56 def add_item(self, name: str, callback): 57 """ 58 Add a callback to compute a specific metric. Used when accessing solver["metric"] 59 Parameters 60 ---------- 61 name : Name of th metric added 62 callback : Function that return the metric value given the Solver 63 """ 64 self.items_collectors[name] = callback
Add a callback to compute a specific metric. Used when accessing solver["metric"]
Parameters
name (Name of th metric added):
callback (Function that return the metric value given the Solver):
83class ScipSolver(Solver): 84 def __init__(self, scip_params: dict = None, configure: Callable[[Model], None] = None): 85 """ 86 Parameters 87 ---------- 88 scip_params : dict, optional 89 Dictionary of parameters to pass to the scip solver. 90 configure : Callable[[Model], None], optional 91 Callback function to configure the solver (e.g. add branching strategies, ...) 92 """ 93 super().__init__() 94 self.scip_params = scip_params or {} 95 self.configure = configure 96 self.model = None 97 98 def build_model(self): 99 self.model = Model() 100 self.model.hideOutput() 101 self.model.setParams(self.scip_params) 102 if self.configure is not None: 103 self.configure(self.model) 104 self.model.setParam("randomization/randomseedshift", self.seed) 105 self.model.setParam("randomization/permutationseed", self.seed) 106 self.model.setParam("randomization/lpseed", self.seed) 107 108 def set_params(self, params): 109 self.scip_params = params 110 111 def __getitem__(self, item: str) -> float: 112 """ 113 Get an attribute from the solver after a solving process. 114 115 Parameters 116 ---------- 117 item : str 118 Name of the attribute to get. Either: 119 time: time in seconds used by the solver 120 nnodes: number of nodes used by the solver 121 obj: Final objective value 122 sol: Best solution found 123 estimate_nnodes: Estimated number of nodes used by the solver to go to optimality 124 125 Returns 126 ------- 127 Value of the attribute. 128 """ 129 match item: 130 case "time": 131 return self.model.getSolvingTime() 132 case "nnodes": 133 # return self.model.getNNodes() 134 return self.model.getNTotalNodes() 135 case "obj": 136 return self.model.getObjVal() 137 case "gap": 138 return self.model.getGap() 139 case "sol": 140 return self.model.getBestSol() 141 case "estimate_nnodes": 142 if self.model.getGap() == 0: 143 return self["nnodes"] 144 else: 145 return self.model.getTreesizeEstimation() 146 case _: 147 return super().__getitem__(item) 148 149 def __getstate__(self): 150 state = self.__dict__.copy() 151 state['model'] = None 152 153 return state
An abstract base class for solvers.
ScipSolver( scip_params: dict = None, configure: Callable[[pyscipopt.scip.Model], NoneType] = None)
84 def __init__(self, scip_params: dict = None, configure: Callable[[Model], None] = None): 85 """ 86 Parameters 87 ---------- 88 scip_params : dict, optional 89 Dictionary of parameters to pass to the scip solver. 90 configure : Callable[[Model], None], optional 91 Callback function to configure the solver (e.g. add branching strategies, ...) 92 """ 93 super().__init__() 94 self.scip_params = scip_params or {} 95 self.configure = configure 96 self.model = None
Parameters
- scip_params (dict, optional): Dictionary of parameters to pass to the scip solver.
- configure (Callable[[Model], None], optional): Callback function to configure the solver (e.g. add branching strategies, ...)
def
build_model(self):
98 def build_model(self): 99 self.model = Model() 100 self.model.hideOutput() 101 self.model.setParams(self.scip_params) 102 if self.configure is not None: 103 self.configure(self.model) 104 self.model.setParam("randomization/randomseedshift", self.seed) 105 self.model.setParam("randomization/permutationseed", self.seed) 106 self.model.setParam("randomization/lpseed", self.seed)