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
        ]
Example #3
0
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
Example #5
0
    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