From 5e51c4e91f584fc4e24aac70c958b6ee8ca9300e Mon Sep 17 00:00:00 2001 From: Haroldo Date: Mon, 3 Aug 2020 13:58:54 -0300 Subject: [PATCH] inform include three depth and pass while generating cuts --- examples/tsp-cuts-ulysses22.py | 2 +- examples/tsp-cuts.py | 2 +- examples/tsp-lazy-ulysses22.py | 2 +- mip/callbacks.py | 8 ++++++-- mip/cbc.py | 13 +++++++------ 5 files changed, 16 insertions(+), 11 deletions(-) diff --git a/examples/tsp-cuts-ulysses22.py b/examples/tsp-cuts-ulysses22.py index ed703dc7..7065272e 100644 --- a/examples/tsp-cuts-ulysses22.py +++ b/examples/tsp-cuts-ulysses22.py @@ -79,7 +79,7 @@ class SubTourCutGenerator(ConstrsGenerator): def __init__(self, Fl: List[Tuple[int, int]], x_): self.F, self.x = Fl, x_ - def generate_constrs(self, m_: Model): + def generate_constrs(self, m_: Model, depth: int = 0, npass: int = 0): xf, cp, Gl = m_.translate(self.x), CutPool(), nx.DiGraph() Ar = [(i, j) for (i, j) in Arcs if xf[i][j] and xf[i][j].x >= 1e-4] for (u, v) in Ar: diff --git a/examples/tsp-cuts.py b/examples/tsp-cuts.py index 2243fd74..99eb2a65 100644 --- a/examples/tsp-cuts.py +++ b/examples/tsp-cuts.py @@ -18,7 +18,7 @@ class SubTourCutGenerator(ConstrsGenerator): def __init__(self, Fl: List[Tuple[int, int]], x_, V_): self.F, self.x, self.V = Fl, x_, V_ - def generate_constrs(self, model: Model): + def generate_constrs(self, model: Model, depth: int = 0, npass: int = 0): xf, V_, cp, G = model.translate(self.x), self.V, CutPool(), nx.DiGraph() for (u, v) in [(k, l) for (k, l) in product(V_, V_) if k != l and xf[k][l]]: G.add_edge(u, v, capacity=xf[u][v].x) diff --git a/examples/tsp-lazy-ulysses22.py b/examples/tsp-lazy-ulysses22.py index e266142b..d6e80623 100644 --- a/examples/tsp-lazy-ulysses22.py +++ b/examples/tsp-lazy-ulysses22.py @@ -36,7 +36,7 @@ class SubTourLazyGenerator(ConstrsGenerator): def __init__(self, xv): self._x = xv - def generate_constrs(self, model: Model): + def generate_constrs(self, model: Model, depth: int = 0, npass: int = 0): x_, N, cp = model.translate(self._x), range(len(self._x)), CutPool() outa = [[j for j in N if x_[i][j].x >= 0.99] for i in N] diff --git a/mip/callbacks.py b/mip/callbacks.py index df4c25c7..1cb27380 100644 --- a/mip/callbacks.py +++ b/mip/callbacks.py @@ -44,12 +44,14 @@ def generate_columns(self, model: "mip.Model"): class ConstrsGenerator: - """Abstract class for implementing cuts and lazy constraints generators.""" + """Abstract class for implementing cuts and lazy constraints generators. + + """ def __init__(self): pass - def generate_constrs(self, model: "mip.Model"): + def generate_constrs(self, model: "mip.Model", depth: int = 0, npass: int = 0): """Method called by the solver engine to generate *cuts* or *lazy constraints*. After analyzing the contents of the solution in model @@ -80,6 +82,8 @@ def generate_constrs(self, model: "mip.Model"): query model properties and add cuts (:meth:`~mip.Model.add_cut`) or lazy constraints (:meth:`~mip.Model.add_lazy_constr`), but you cannot perform other model modifications, such as add columns. + depth(int): depth of the search tree (0 is the root node) + npass(int): current number of cut passes in this node """ raise NotImplementedError() diff --git a/mip/cbc.py b/mip/cbc.py index 3fddbfe0..6b74bf7f 100644 --- a/mip/cbc.py +++ b/mip/cbc.py @@ -129,8 +129,7 @@ const double *dvec, int nint, const int *ivec, int nchar, char **cvec); - typedef void(*cbc_cut_callback)(void *osiSolver, - void *osiCuts, void *appdata); + typedef void(*cbc_cut_callback)(void *osiSolver, void *osiCuts, void *appdata, int level, int npass); typedef int (*cbc_incumbent_callback)(void *cbcModel, double obj, int nz, @@ -985,10 +984,10 @@ def cbc_inc_callback( # cut callback @ffi.callback( """ - void (void *osi_solver, void *osi_cuts, void *app_data) + void (void *osi_solver, void *osi_cuts, void *app_data, int level, int npass) """ ) - def cbc_cut_callback(osi_solver, osi_cuts, app_data): + def cbc_cut_callback(osi_solver, osi_cuts, app_data, depth, npass): if ( osi_solver == ffi.NULL or osi_cuts == ffi.NULL @@ -1017,9 +1016,11 @@ def cbc_cut_callback(osi_solver, osi_cuts, app_data): osi_model.solver.osi_cutsp = osi_cuts osi_model.fractional = fractional if fractional and self.model.cuts_generator: - self.model.cuts_generator.generate_constrs(osi_model) + self.model.cuts_generator.generate_constrs(osi_model, depth, npass) if (not fractional) and self.model.lazy_constrs_generator: - self.model.lazy_constrs_generator.generate_constrs(osi_model) + self.model.lazy_constrs_generator.generate_constrs( + osi_model, depth, npass + ) if self.__verbose == 0: cbclib.Cbc_setLogLevel(self._model, 0)