def _get_nonzero_triplets(self): """ Get the edge tuples plus edge weight for each nonzero value of the solution """ return [ mip_utils.get_variable_tuple(key) + (value, ) for (key, value) in zip(self.keys, self.solution) if value > 0.0001 ]
def _get_nonzero_edges(self): """ Get the edge tuples for the nonzero values of the solution """ return [ mip_utils.get_variable_tuple(key) for (key, value) in zip(self.keys, self.solution) if value > 0.0001 ]
def get_mincut_variables(graph, vertex_a, vertex_b, variable_dict, is_symmetric=True): """ Get the variables needed to build a mincut constraint for a specific vertex pair """ cut_value, (set_a, set_b) = nx.minimum_cut(graph, vertex_a, vertex_b) if cut_value <= 0.99 + is_symmetric * 1: if len(set_a) <= len(set_b): set_c = set_a else: set_c = set_b keys = variable_dict.keys() keys = [ key for key in keys if (mip_utils.get_variable_tuple(key)[0] in set_c and mip_utils.get_variable_tuple(key)[1] in set_c) ] return [variable_dict[key] for key in keys] return None
def find_subtours(self, checkonly, solution, variable_dict): """ find subtours in the current solution """ graph = nx.Graph() variables = list(self.solver.variable_dict.values()) keys = list(self.solver.variable_dict.keys()) solution = [ self.model.getSolVal(solution, variable) for variable in variables ] self.solver.solutions.append(solution) indices = [num for num, item in enumerate(solution) if item > 0] nonzero_edges = [ mip_utils.get_variable_tuple(variables[index].name) for index in indices ] graph.add_edges_from(nonzero_edges) components = list(nx.connected_components(graph)) if len(components) == 1 or self.round_counter >= self.max_rounds: return False elif checkonly: return True subtour_selector = subtourStrategy( cut_strategy=self.solver.cut_strategy) for S in subtour_selector.get_subtours(components): if self.solver._is_symmetric: varnames = [ "x_{},{}".format(i, j) for i in S for j in S if j > i and "x_{},{}".format(i, j) in keys ] if self.solver._is_asymmetric: varnames = [ "x_{},{}".format(i, j) for i in S for j in S if "x_{},{}".format(i, j) in keys ] self.model.addCons( quicksum(self.solver.variable_dict[name] for name in varnames) <= len(S) - 1) self.round_counter += 1 self.solver.counter += 1 return True
def get_variable_tuple(self, string): """ Get the (vertex_a, vertex_b) integer tuple from a variable name """ return mip_utils.get_variable_tuple(string)
def find_subtours(self, checkonly, solution, variable_dict): """ find subtours in the current solution """ graph = nx.Graph() variables = list(self.solver.variable_dict.values()) keys = list(self.solver.variable_dict.keys()) solution = [ self.model.getSolVal(solution, variable) for variable in variables ] self.solver.solutions.append(solution) indices = [num for num, item in enumerate(solution) if item > 0] nonzero_edges = [ mip_utils.get_variable_tuple(variables[index].name) for index in indices ] graph.add_edges_from(nonzero_edges) if np.sum(solution) > 0 and np.sum( solution) < self.solver.vehicle_num + len( self.solver.vertices): cycles = [] while (len(graph.edges)) > 0: edges = nx.find_cycle(graph) cycles.append(edges) graph.remove_edges_from(edges) components = [set(np.unique(item)) for item in cycles] else: components = nx.connected_components(graph) components = [ item for item in components if len(item.intersection(set(self.solver.depots))) == 0 or np.sum([self.solver.demands[k] for k in item]) > self.solver.get_capacity() ] if len(components) == 1 or self.round_counter >= self.max_rounds: return False elif checkonly: return True subtour_selector = subtourStrategy( cut_strategy=self.solver.cut_strategy) for S in subtour_selector.get_subtours(components): min_vehicles = len( bp.to_constant_volume( {item: self.solver.demands[item] for item in S}, self.solver.get_capacity())) if self.solver._is_symmetric: varnames = [ "x_{},{}".format(i, j) for i in S for j in S if j > i and "x_{},{}".format(i, j) in keys ] if self.solver._is_asymmetric: varnames = [ "x_{},{}".format(i, j) for i in S for j in S if "x_{},{}".format(i, j) in keys ] self.model.addCons( quicksum(self.solver.variable_dict[name] for name in varnames) <= len(S) - min_vehicles) self.round_counter += 1 self.solver.counter += 1 return True