def _general_circle_elimination(self, model: grb.Model): # Calculate the adjacency matrix for the solution # ToDo: ^ this edges_solution = model.cbGetSolution(self.edges) ad_matrix = np.zeros(self.abstract_graph.ad_matrix.shape) for u, v in edges_solution: ad_matrix[u, v] = edges_solution[(u, v)] if max(np.triu(ad_matrix)) == 0 or max(np.tril(ad_matrix)) == 0: ad_matrix = ad_matrix + ad_matrix.T to_calc = {0} processed = {} while to_calc: i = to_calc.pop() non_zero = ad_matrix[i].nonzero() for j in non_zero: if j in to_calc or j in processed: # Found a circle: ELIMINATE # ToDo: implement elimination constraint pass to_calc.add(j) if len(processed) < len(self.abstract_graph.vertices): # The processed vertices itself are a subtour/circle pass pass #ToDo: circle elimination
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)
def _general_circle_elimination(self, model: grb.Model): edges_solution = model.cbGetSolution(self.edges) used_edges = grb.tupledict({key: edges_solution[key] for key in edges_solution if not math.isclose(0, edges_solution[key], abs_tol=10**-5)}) for edge in used_edges: if used_edges[edge] < 0.7: print("Found an edge with value less than 0.7") self._check_for_cycle(used_edges, model) return # Turn used_edges into a dependency graph dep_graph = self._get_dep_graph(used_edges) try: calculate_order(dep_graph, calculate_circle_dep=True) except CircularDependencyException as dep_exception: self._add_cycle_constr(dep_exception.circle_nodes, model) # For now we try to ignore this disconnected graphs except DisconnectedDependencyGraphException as disc_exception: cycle = calculate_cycle(disc_exception.disconnected_nodes) self._add_cycle_constr(cycle, model)