示例#1
0
 def _check_for_cycle(self, used_edges: grb.tupledict, model: grb.Model, lazy=True):
     unseen = {i for i in range(len(self.abstract_graph.vertices))}
     queued = set()
     while unseen:
         queued.add((None, unseen.pop()))
         prev = {}
         seen = set()
         while queued:
             edge = queued.pop()
             sub = used_edges.subset(edge[1], '*')
             seen.add(edge[1])
             for key in sub:
                 destination = key[1]
                 if destination in unseen:
                     try:
                         pass#unseen.remove(destination)
                     except KeyError:
                         print("Double unseen event!")
                         pass # It can happen that some nodes will be seen multiple times
                     queued.add(key)
                     prev[key] = edge
                 if destination in seen:
                     path = [key, edge]
                     while path[-1][0] and path[-1][0] != destination:
                         path.append(prev[path[-1]])
                     if path[-1][0] == destination:
                         self.found_circles.append(path)
                         expr = None
                         if self.with_vertex_subtour_constr:
                             abs_vert_on_path = [key[1] for key in path]
                             for v_i in range(self.graph.vert_amount):
                                 if self.v_incident_edges[v_i].issuperset(abs_vert_on_path):
                                     diff = self.v_incident_edges[v_i].difference(abs_vert_on_path)
                                     incoming = self.edges.subset(diff, abs_vert_on_path)
                                     outgoing = self.edges.subset(abs_vert_on_path, diff)
                                     expr = incoming.sum() + outgoing.sum() >= 1
                                     break
                             
                         if expr is None:
                             expr = sum(self.edges[i] for i in path) <= len(path)-1
                         
                         if lazy:
                             model.cbLazy(expr)
                         else:
                             model.addConstr(expr)
                         #print("Found cycle", path)
                         return True
                     #print("No cycle found for:", prev)
     return False
    def _subtour_elimination(self, model: gurobipy.Model):
        #nodecnt = model.cbGet(gurobipy.GRB.Callback.MIPSOL_NODCNT)
        #obj = model.cbGet(gurobipy.GRB.Callback.MIPSOL_OBJ)
        #solcnt = model.cbGet(gurobipy.GRB.Callback.MIPSOL_SOLCNT)
        #solution = model.cbGetSolution(self.edges)
        # for every subsolution, try to find shortcuts
        for base_vertex_index, edges in self.edges.items():
            edge_solution = model.cbGetSolution(edges)
            used_edges = {
                key: edge_solution[key]
                for key in edge_solution if edge_solution[key] > 0.1
            }
            ad_vert = {key[1]: key for key in used_edges}
            visited = set()
            all_ad_vert = {key[1]: key for key in edge_solution}
            vertices_amount = len(all_ad_vert)

            while len(visited) < vertices_amount:
                current_vertices = []
                vertex, edge_key = self._get_start_vertex(used_edges, visited)
                while vertex not in visited:
                    visited.add(vertex)
                    current_vertices.append(vertex)
                    vertex = edge_key[2]
                    try:
                        edge_key = ad_vert[vertex]
                    except KeyError:
                        # Should only happen if we get to an end of a path
                        # Therefore, just add them to also mark them as visited
                        visited.add(vertex)
                        current_vertices.append(vertex)
                # Found a subtour, need to eliminate it
                if len(current_vertices) < vertices_amount:
                    not_current_vertices = [
                        i for i in all_ad_vert if i not in current_vertices
                    ]
                    model.cbLazy(
                        edges.sum(base_vertex_index, current_vertices,
                                  not_current_vertices) +
                        edges.sum(base_vertex_index, not_current_vertices,
                                  current_vertices) >= 1)
                    print("Subtour found for point", base_vertex_index,
                          "with vertices", current_vertices)
示例#3
0
 def _check_for_cycle(self,
                      used_edges: grb.tupledict,
                      model: grb.Model,
                      lazy=True):
     unseen = {i for i in range(len(self.abstract_graph.vertices))}
     queued = set()
     while unseen:
         queued.add((None, unseen.pop()))
         prev = {}
         seen = set()
         while queued:
             edge = queued.pop()
             sub = used_edges.subset(edge[1], '*')
             seen.add(edge[1])
             for key in sub:
                 destination = key[1]
                 if destination in unseen:
                     try:
                         pass  #unseen.remove(destination)
                     except KeyError:
                         print("Double unseen event!")
                         pass  # It can happen that some nodes will be seen multiple times
                     queued.add(key)
                     prev[key] = edge
                 if destination in seen:
                     path = [key, edge]
                     while path[-1][0] and path[-1][0] != destination:
                         path.append(prev[path[-1]])
                     if path[-1][0] == destination:
                         if lazy:
                             self.found_circles.append(path)
                             model.cbLazy(
                                 sum(self.edges[i]
                                     for i in path) <= len(path) - 1)
                         else:
                             self.found_circles.append(path)
                             model.addConstr(
                                 sum(self.edges[i]
                                     for i in path) <= len(path) - 1)
                         #print("Found cycle", path)
                         return True
                     #print("No cycle found for:", prev)
     return False
示例#4
0
 def _add_cycle_constr(self, cycle_nodes, model: grb.Model):
     cycle = [nodes.value for nodes in cycle_nodes]
     l = len(cycle)
     cycle_edges = [(cycle[i], cycle[((i + 1) % l)]) for i in range(l)]
     cycle_edges_rev = [(cycle[((i + 1) % l)], cycle[i]) for i in range(l)]
     #print("CYCLE EDGES:", cycle_edges)
     l = len(cycle_edges) - 1
     try:
         cycle_edges_vars = grb.tupledict(
             {i: self.edges[i]
              for i in cycle_edges})
         cycle_edges_rev_vars = grb.tupledict(
             {i: self.edges[i]
              for i in cycle_edges_rev})
         exp = grb.LinExpr(cycle_edges_vars.sum())
         exp_rev = grb.LinExpr(cycle_edges_rev_vars.sum())
         model.cbLazy(exp <= l)
         model.cbLazy(exp_rev <= l)
         #model.addConstr(exp <= l)
     except grb.GurobiError as err:
         print("ERROR: Gurobi error with number:", err.errno)