mirror of
https://github.com/ANL-CEEESA/MIPLearn.git
synced 2025-12-06 09:28:51 -06:00
Remove methods to set solver parameters
This commit is contained in:
@@ -315,22 +315,6 @@ class GurobiSolver(InternalSolver):
|
|||||||
self._raise_if_callback()
|
self._raise_if_callback()
|
||||||
logger.warning("set_branching_priorities not implemented")
|
logger.warning("set_branching_priorities not implemented")
|
||||||
|
|
||||||
def set_threads(self, threads):
|
|
||||||
self._raise_if_callback()
|
|
||||||
self.params["Threads"] = threads
|
|
||||||
|
|
||||||
def set_time_limit(self, time_limit):
|
|
||||||
self._raise_if_callback()
|
|
||||||
self.params["TimeLimit"] = time_limit
|
|
||||||
|
|
||||||
def set_node_limit(self, node_limit):
|
|
||||||
self._raise_if_callback()
|
|
||||||
self.params["NodeLimit"] = node_limit
|
|
||||||
|
|
||||||
def set_gap_tolerance(self, gap_tolerance):
|
|
||||||
self._raise_if_callback()
|
|
||||||
self.params["MIPGap"] = gap_tolerance
|
|
||||||
|
|
||||||
def _extract_warm_start_value(self, log):
|
def _extract_warm_start_value(self, log):
|
||||||
ws = self.__extract(log, "MIP start with objective ([0-9.e+-]*)")
|
ws = self.__extract(log, "MIP start with objective ([0-9.e+-]*)")
|
||||||
if ws is not None:
|
if ws is not None:
|
||||||
|
|||||||
@@ -36,6 +36,40 @@ class InternalSolver(ABC):
|
|||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def solve(self, tee=False, iteration_cb=None, lazy_cb=None):
|
||||||
|
"""
|
||||||
|
Solves the currently loaded instance. After this method finishes,
|
||||||
|
the best solution found can be retrieved by calling `get_solution`.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
iteration_cb: () -> Bool
|
||||||
|
By default, InternalSolver makes a single call to the native `solve`
|
||||||
|
method and returns the result. If an iteration callback is provided
|
||||||
|
instead, InternalSolver enters a loop, where `solve` and `iteration_cb`
|
||||||
|
are called alternatively. To stop the loop, `iteration_cb` should
|
||||||
|
return False. Any other result causes the solver to loop again.
|
||||||
|
lazy_cb: (internal_solver, model) -> None
|
||||||
|
This function is called whenever the solver finds a new candidate
|
||||||
|
solution and can be used to add lazy constraints to the model. Only
|
||||||
|
the following operations within the callback are allowed:
|
||||||
|
- Querying the value of a variable, through `get_value(var, idx)`
|
||||||
|
- Querying if a constraint is satisfied, through `is_constraint_satisfied(cobj)`
|
||||||
|
- Adding a new constraint to the problem, through `add_constraint`
|
||||||
|
Additional operations may be allowed by specific subclasses.
|
||||||
|
tee: Bool
|
||||||
|
If true, prints the solver log to the screen.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
dict
|
||||||
|
A dictionary of solver statistics containing the following keys:
|
||||||
|
"Lower bound", "Upper bound", "Wallclock time", "Nodes", "Sense",
|
||||||
|
"Log" and "Warm start value".
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def get_solution(self):
|
def get_solution(self):
|
||||||
"""
|
"""
|
||||||
@@ -43,7 +77,7 @@ class InternalSolver(ABC):
|
|||||||
|
|
||||||
If called after `solve`, returns the best primal solution found during
|
If called after `solve`, returns the best primal solution found during
|
||||||
the search. If called after `solve_lp`, returns the optimal solution
|
the search. If called after `solve_lp`, returns the optimal solution
|
||||||
to the LP relaxation.
|
to the LP relaxation. If no primal solution is available, return None.
|
||||||
|
|
||||||
The solution is a dictionary `sol`, where the optimal value of `var[idx]`
|
The solution is a dictionary `sol`, where the optimal value of `var[idx]`
|
||||||
is given by `sol[var][idx]`.
|
is given by `sol[var][idx]`.
|
||||||
@@ -62,13 +96,6 @@ class InternalSolver(ABC):
|
|||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def clear_warm_start(self):
|
|
||||||
"""
|
|
||||||
Removes any existing warm start from the solver.
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def set_instance(self, instance, model=None):
|
def set_instance(self, instance, model=None):
|
||||||
"""
|
"""
|
||||||
@@ -76,7 +103,7 @@ class InternalSolver(ABC):
|
|||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
instance: miplearn.Instance
|
instance: Instance
|
||||||
The instance to be loaded.
|
The instance to be loaded.
|
||||||
model:
|
model:
|
||||||
The concrete optimization model corresponding to this instance
|
The concrete optimization model corresponding to this instance
|
||||||
@@ -118,40 +145,6 @@ class InternalSolver(ABC):
|
|||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def solve(self, tee=False, iteration_cb=None, lazy_cb=None):
|
|
||||||
"""
|
|
||||||
Solves the currently loaded instance. After this method finishes,
|
|
||||||
the best solution found can be retrieved by calling `get_solution`.
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
iteration_cb: () -> Bool
|
|
||||||
By default, InternalSolver makes a single call to the native `solve`
|
|
||||||
method and returns the result. If an iteration callback is provided
|
|
||||||
instead, InternalSolver enters a loop, where `solve` and `iteration_cb`
|
|
||||||
are called alternatively. To stop the loop, `iteration_cb` should
|
|
||||||
return False. Any other result causes the solver to loop again.
|
|
||||||
lazy_cb: (internal_solver, model) -> None
|
|
||||||
This function is called whenever the solver finds a new candidate
|
|
||||||
solution and can be used to add lazy constraints to the model. Only
|
|
||||||
the following operations within the callback are allowed:
|
|
||||||
- Querying the value of a variable, through `get_value(var, idx)`
|
|
||||||
- Querying if a constraint is satisfied, through `is_constraint_satisfied(cobj)`
|
|
||||||
- Adding a new constraint to the problem, through `add_constraint`
|
|
||||||
Additional operations may be allowed by specific subclasses.
|
|
||||||
tee: Bool
|
|
||||||
If true, prints the solver log to the screen.
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
dict
|
|
||||||
A dictionary of solver statistics containing the following keys:
|
|
||||||
"Lower bound", "Upper bound", "Wallclock time", "Nodes", "Sense",
|
|
||||||
"Log" and "Warm start value".
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def get_value(self, var_name, index):
|
def get_value(self, var_name, index):
|
||||||
"""
|
"""
|
||||||
@@ -206,7 +199,7 @@ class InternalSolver(ABC):
|
|||||||
value of the dual variable associated with this constraint. If the model is infeasible,
|
value of the dual variable associated with this constraint. If the model is infeasible,
|
||||||
returns a portion of the infeasibility certificate corresponding to the given constraint.
|
returns a portion of the infeasibility certificate corresponding to the given constraint.
|
||||||
|
|
||||||
Solve must be called prior to this method.
|
Must be called after solve.
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -219,6 +212,7 @@ class InternalSolver(ABC):
|
|||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def is_constraint_satisfied(self, cobj):
|
def is_constraint_satisfied(self, cobj):
|
||||||
|
"""Returns True if the current solution satisfies the given constraint."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
@@ -233,22 +227,6 @@ class InternalSolver(ABC):
|
|||||||
def set_constraint_rhs(self, cid, rhs):
|
def set_constraint_rhs(self, cid, rhs):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def set_threads(self, threads):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def set_time_limit(self, time_limit):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def set_node_limit(self, node_limit):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def set_gap_tolerance(self, gap_tolerance):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def get_variables(self):
|
def get_variables(self):
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -204,22 +204,6 @@ class BasePyomoSolver(InternalSolver):
|
|||||||
def _extract_node_count(self, log):
|
def _extract_node_count(self, log):
|
||||||
return int(self.__extract(log, self._get_node_count_regexp(), default=1))
|
return int(self.__extract(log, self._get_node_count_regexp(), default=1))
|
||||||
|
|
||||||
def set_threads(self, threads):
|
|
||||||
key = self._get_threads_option_name()
|
|
||||||
self._pyomo_solver.options[key] = threads
|
|
||||||
|
|
||||||
def set_time_limit(self, time_limit):
|
|
||||||
key = self._get_time_limit_option_name()
|
|
||||||
self._pyomo_solver.options[key] = time_limit
|
|
||||||
|
|
||||||
def set_node_limit(self, node_limit):
|
|
||||||
key = self._get_node_limit_option_name()
|
|
||||||
self._pyomo_solver.options[key] = node_limit
|
|
||||||
|
|
||||||
def set_gap_tolerance(self, gap_tolerance):
|
|
||||||
key = self._get_gap_tolerance_option_name()
|
|
||||||
self._pyomo_solver.options[key] = gap_tolerance
|
|
||||||
|
|
||||||
def get_constraint_ids(self):
|
def get_constraint_ids(self):
|
||||||
return list(self._cname_to_constr.keys())
|
return list(self._cname_to_constr.keys())
|
||||||
|
|
||||||
@@ -231,22 +215,6 @@ class BasePyomoSolver(InternalSolver):
|
|||||||
def _get_node_count_regexp(self):
|
def _get_node_count_regexp(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def _get_threads_option_name(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def _get_time_limit_option_name(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def _get_node_limit_option_name(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def _get_gap_tolerance_option_name(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def extract_constraint(self, cid):
|
def extract_constraint(self, cid):
|
||||||
raise Exception("Not implemented")
|
raise Exception("Not implemented")
|
||||||
|
|
||||||
|
|||||||
@@ -33,17 +33,5 @@ class CplexPyomoSolver(BasePyomoSolver):
|
|||||||
def _get_node_count_regexp(self):
|
def _get_node_count_regexp(self):
|
||||||
return "^[ *] *([0-9]+)"
|
return "^[ *] *([0-9]+)"
|
||||||
|
|
||||||
def _get_threads_option_name(self):
|
|
||||||
return "threads"
|
|
||||||
|
|
||||||
def _get_time_limit_option_name(self):
|
|
||||||
return "timelimit"
|
|
||||||
|
|
||||||
def _get_node_limit_option_name(self):
|
|
||||||
return "mip_limits_nodes"
|
|
||||||
|
|
||||||
def _get_gap_tolerance_option_name(self):
|
|
||||||
return "mip_tolerances_mipgap"
|
|
||||||
|
|
||||||
def set_branching_priorities(self, priorities):
|
def set_branching_priorities(self, priorities):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|||||||
@@ -41,18 +41,6 @@ class GurobiPyomoSolver(BasePyomoSolver):
|
|||||||
def _get_node_count_regexp(self):
|
def _get_node_count_regexp(self):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def _get_threads_option_name(self):
|
|
||||||
return "Threads"
|
|
||||||
|
|
||||||
def _get_time_limit_option_name(self):
|
|
||||||
return "TimeLimit"
|
|
||||||
|
|
||||||
def _get_node_limit_option_name(self):
|
|
||||||
return "NodeLimit"
|
|
||||||
|
|
||||||
def _get_gap_tolerance_option_name(self):
|
|
||||||
return "MIPGap"
|
|
||||||
|
|
||||||
def set_branching_priorities(self, priorities):
|
def set_branching_priorities(self, priorities):
|
||||||
from gurobipy import GRB
|
from gurobipy import GRB
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user