def __call__(self, chromosome, **kwargs):
        '''
        Parameters:
            chromosome : is a EdgeSet type or a Bag

        Results :
            _cost : Number
                the edgeset cost
            nro_components : int
                graph components identified
        '''
        assert isinstance(
            chromosome, EdgeSet
        ), f"unsupported operation for chromosome type {type(chromosome)}"

        disjointset = DisjointSets()
        _cost = 0
        GRAPH = self.STPG.graph

        for v, u in chromosome:
            if not GRAPH.has_edge(v, u):
                raise RuntimeError("STPG instance has not this edge")
            _cost += GRAPH.weight(v, u)
            if v not in disjointset:
                disjointset.make_set(v)
            if u not in disjointset:
                disjointset.make_set(u)
            disjointset.union(v, u)

        nro_components = len(disjointset.get_disjoint_sets())

        _cost += self.penality_function(nro_components)

        return _cost, nro_components
    def __call__(self, parent_a, parent_b):
        assert isinstance(
            parent_a, EdgeSet
        ), f'parent_a has to be EdgeSet type. Give was {type(parent_a)}'
        assert isinstance(
            parent_b, EdgeSet
        ), f'parent_b has to be EdgeSet type. Give was {type(parent_b)}'

        edges = parent_a | parent_b

        done = DisjointSets()
        for v in edges.vertices:
            done.make_set(v)

        edges = set(edges)

        result = EdgeSet()
        while edges and len(done.get_disjoint_sets()) > 1:
            edge = sample(edges, k=1)[0]
            y, z = edge[0], edge[1]
            if done.find(y) != done.find(z):
                result.add(edge)
                done.union(y, z)
            edges.discard(edge)

        return result
Beispiel #3
0
    def __call__(self, red, blue):
        assert isinstance(
            red, UGraph), f'red parent must be UGraph. Given {type(red)}'
        assert isinstance(
            blue, UGraph), f'blue parent must be UGraph. Given {type(blue)}'

        done = DisjointSets()

        union_g = UGraph()
        for v, u in red.gen_undirect_edges():
            union_g.add_edge(v, u)
        for v, u in blue.gen_undirect_edges():
            union_g.add_edge(v, u)

        for v in union_g.vertices:
            done.make_set(v)

        all_edges = set()
        for edge in union_g.gen_undirect_edges():
            all_edges.add(edge)

        result = UGraph()
        while all_edges and len(done.get_disjoint_sets()) > 1:
            edge = sample(all_edges, k=1)[0]
            v, u = edge[0], edge[1]
            if done.find(v) != done.find(u):
                result.add_edge(v, u)
                done.union(v, u)
            all_edges.remove(edge)

        return result
Beispiel #4
0
    def binary2treegraph(self, chromosome):
        '''Converts from BinaryChromosome to TreeChromosome'''

        GRAPH = self.STPG.graph

        queue = PriorityQueue()
        disjointset = DisjointSets()
        subgraph = UGraph()
        dones = set()

        # todos os vértices esperados na solução parcial
        vertices = self.vertices_from_chromosome(chromosome)

        # adiciona uma aresta se os vértices extremos da aresta
        # estão contidos no conjunto vertices
        # mantém essas arestas em uma fila de prioridades para
        # formar uma MST baseado no algoritmo de Kruskal
        for v in vertices:
            dones.add(v)
            disjointset.make_set(v)  # para construir a MST
            subgraph.add_node(v)  # garantir a inserção de um vértice isolado
            for u in GRAPH.adjacent_to(v):
                if (u in vertices) and (u not in dones):
                    weight = GRAPH.weight(v, u)
                    queue.push(weight, (v, u))

        while queue:
            v, u = queue.pop()
            if disjointset.find(v) != disjointset.find(u):
                subgraph.add_edge(v, u)
                disjointset.union(v, u)

        return subgraph
    def test_attributes(self):
        obj = Subset(10)
        self.assertTrue(hasattr(obj, "rank"))
        self.assertTrue(hasattr(obj, "parent"))

        DS = DisjointSets()

        self.assertEqual(len(DS), 0)

        for item in range(3, 50, 10):
            DS.make_set(item)

        self.assertTrue(hasattr(DS, "make_set"))
        self.assertTrue(hasattr(DS, "find"))
        self.assertTrue(hasattr(DS, "union"))
        self.assertTrue(hasattr(DS, "get_disjoint_sets"))
Beispiel #6
0
    def __call__(self, red: UGraph, blue: UGraph):
        child     = UGraph()
        red_only  = UGraph()
        blue_only = UGraph()

        for v, u in red.gen_undirect_edges():
            if blue.has_edge(v, u):
                child.add_edge(v, u)
            else:
                red_only.add_edge(v, u)

        for v, u in blue.gen_undirect_edges():
            if not red.has_edge(v, u):
                blue_only.add_edge(v, u)

        common_nodes_red = set(red_only.vertices) & set(blue.vertices)
        common_nodes_blue = set(blue_only.vertices) & set(red.vertices)

        red_partitions  = self.find_partitions(red_only, common_nodes_red)
        blue_partitions = self.find_partitions(blue_only, common_nodes_blue)

        queue = PriorityQueue()

        for partition in red_partitions:
            queue.push(partition.cost, partition)

        for partition in blue_partitions:
            queue.push(partition.cost, partition)

        common_nodes = set(red.vertices) | set(blue.vertices)
        dset = DisjointSets()

        for v in common_nodes:
            dset.make_set(v)

        for v, u in child.gen_undirect_edges():
            dset.union(v, u)

        while queue:
            partition = queue.pop()

            if check_portals(partition.portal, dset):

                # add edges
                for v, u in partition:
                    child.add_edge(v, u)

                # update dset
                portals = iter(partition.portal)

                p_last = next(portals)
                for p in portals:
                    dset.union(p_last, p)
                    p_last = p

        return child
Beispiel #7
0
    def test_EvaluateZeroChromossome(self):
        stpg = self.stpg
        graph = self.stpg.graph
        nro_terminals = stpg.nro_terminals
        terminals = stpg.terminals

        disset = DisjointSets()
        for v in terminals:
            disset.make_set(v)

        edges_sum = 0
        done = set()
        for t in terminals:
            done.add(t)
            for v in graph.adjacent_to(t):
                if v in terminals and v not in done:
                    disset.union(t, v)
                    edges_sum += graph.weight(t, v)

        qtd_disjoint_sets = len(disset.get_disjoint_sets())

        expected_lenght = stpg.nro_nodes - stpg.nro_terminals
        chromosome = '0' * expected_lenght

        evaluator = EvaluateKruskalBased(stpg)

        evaluator_cost, qtd_partitions = evaluator(chromosome)

        self.assertEqual(evaluator_cost,
                         ((qtd_partitions - 1) * 1_000) + edges_sum)
        self.assertEqual(evaluator_cost,
                         ((qtd_disjoint_sets - 1) * 1_000) + edges_sum)
        self.assertEqual(qtd_partitions, qtd_disjoint_sets)
    def __call__(self, chromosome, **kwargs):

        GRAPH = self.STPG.graph

        penality = self.penality_function

        vertices = self.vertices_from_chromosome(chromosome)

        # instânciando variáveis e funções auxiliares
        queue = PriorityQueue()
        dones = set()

        # adiciona uma aresta se os vértices extremos da aresta
        # estão contidos no conjunto vertices
        # mantém essas arestas em uma fila de prioridades para
        # formar uma MST baseado no algoritmo de Kruskal
        # (o trabalho de Kapsalis utilizava o algoritmo de Prim)
        for v in vertices:
            dones.add(v)
            for u in GRAPH.adjacent_to(v):
                if (u in vertices) and (u not in dones):
                    weight = GRAPH.weight(v, u)
                    queue.push(weight, (v, u, weight))

        ## Monta a MST baseado no algoritmo de Kruskal
        DS = DisjointSets()
        for v in vertices:
            DS.make_set(v)

        total_cost = 0
        while queue:
            v, u, weight = queue.pop()
            if DS.find(v) != DS.find(u):
                total_cost += weight
                DS.union(v, u)
        # Repare que não construimos a MST mas apenas
        # definimos os conjuntos disjuntos.

        # a quantidade de partições se refere a
        # quantidade de parents distintos temos no conjunto disjunto.
        qtd_partition = len(DS.get_disjoint_sets())

        total_cost += penality(qtd_partition)

        return total_cost, qtd_partition
    def test_inserting_item(self):

        DS = DisjointSets()

        for item in range(3, 50, 10):
            DS.make_set(item)

        self.assertEqual(len(DS), 5)
        self.assertEqual(len(DS), len(DS.get_disjoint_sets()))

        with self.assertRaises(ValueError):
            DS.make_set(13)
        ## check ignore_previous
        self.assertTrue(33 in DS)
        DS.make_set(33, ignore_previous=True)

        self.assertTrue(not 171 in DS)
        self.assertFalse(171 in DS)
Beispiel #10
0
    def __call__(self, tree):

        GRAPH = self.STPG.graph
        total_cost = 0
        qtd_partition = 0
        DS = DisjointSets()

        for v in tree.vertices:
            DS.make_set(v)

        for v, u in tree.gen_undirect_edges():
            if DS.find(v) == DS.find(u):
                ## trocar isso por um log
                print("FOI IDENTIFICADO UM CICLO EM UMA DAS SOLUÇÕES")
            DS.union(v, u)
            total_cost += GRAPH.weight(v, u)

        qtd_partition = len(DS.get_disjoint_sets())

        if self.apply_penalization:
            total_cost += self.penality(qtd_partition)

        return total_cost, qtd_partition
Beispiel #11
0
def gen_random_kruskal(stpg: SteinerTreeProblem):

    terminals = set(stpg.terminals)
    edges = [(u, v) for u, v in stpg.graph.gen_undirect_edges()]
    shuffle(edges)

    done = DisjointSets()
    for v in terminals:
        done.make_set(v)

    result = EdgeSet()

    while edges and len(done.get_disjoint_sets()) > 1:
        edge = edges.pop()
        y, z = edge[0], edge[1]
        if y not in done: done.make_set(y)
        if z not in done: done.make_set(z)
        if done.find(y) != done.find(z):
            result.add(y, z)
            done.union(y, z)
            terminals.discard(y)
            terminals.discard(z)

    return result
Beispiel #12
0
    def __call__(self, red: UGraph, blue: UGraph):
        child = UGraph()
        red_only = UGraph()
        blue_only = UGraph()

        _vertices = set()

        for v, u in red.gen_undirect_edges():
            if blue.has_edge(v, u):
                child.add_edge(v, u)
                _vertices.add(v)
                _vertices.add(u)
            else:
                red_only.add_edge(v, u)

        for v, u in blue.gen_undirect_edges():
            if not red.has_edge(v, u):
                blue_only.add_edge(v, u)

        common_nodes_red = set(red_only.vertices) & set(blue.vertices)
        common_nodes_blue = set(blue_only.vertices) & set(red.vertices)

        red_partitions = self.find_partitions(red_only, common_nodes_red)
        blue_partitions = self.find_partitions(blue_only, common_nodes_blue)

        _vertices.update(common_nodes_red | common_nodes_blue)
        disjoint = DisjointSets()

        for v in _vertices:
            disjoint.make_set(v)

        for v, u in child.gen_undirect_edges():
            disjoint.union(v, u)

        red_dict = _dict_matches_from(red_partitions, disjoint)
        blue_dict = _dict_matches_from(blue_partitions, disjoint)
        matches = red_dict.keys() & blue_dict.keys()

        while matches:
            child, red_dict, blue_dict, disjoint = select_partition_and_union(
                child, red_dict, blue_dict, disjoint, matches)
            red_dict = _dict_matches_from(red_dict.values(), disjoint)
            blue_dict = _dict_matches_from(blue_dict.values(), disjoint)
            matches = red_dict.keys() & blue_dict.keys()

        red_child = UGraph()
        blue_child = UGraph()

        for v, u in child.gen_undirect_edges():
            red_child.add_edge(v, u)
            blue_child.add_edge(v, u)

        for partition in red_dict.values():
            for v, u in partition:
                red_child.add_edge(v, u)

        for partition in blue_dict.values():
            for v, u in partition:
                blue_child.add_edge(v, u)

        return red_child, blue_child
Beispiel #13
0
    def __call__(self, treegraph: UGraph):

        GRAPH = self.stpg.graph
        disjointset = DisjointSets()
        result = UGraph()

        for v in treegraph.vertices:
            disjointset.make_set(v)

        # remove edge
        edges = [edge for edge in treegraph.gen_undirect_edges()]
        index = randint(0, len(edges))
        for i, edge in enumerate(edges):
            if index != i:
                result.add_edge(*edge)
                disjointset.union(*edge)

        candidates = list()
        components = disjointset.get_disjoint_sets()

        lesser_idx = min(components, key=lambda key: len(components[key]))
        keys = components.keys() - set([lesser_idx])

        # replace edge
        lesser_component = components[lesser_idx]
        for key in keys:
            other_component = components[key]
            for v in lesser_component:
                for w in GRAPH.adjacent_to(v):
                    if w in other_component:
                        candidates.append((v, w))

            shuffle(candidates)
            while candidates:
                v, w = candidates.pop()
                if disjointset.find(v) != disjointset.find(w):
                    result.add_edge(v, w)
                    disjointset.union(v, w)
                    break

        return result
Beispiel #14
0
    def __call__(self):
        result = UGraph()
        done = DisjointSets()
        edges = [(u, v) for u, v in self.stpg.graph.gen_undirect_edges()]

        shuffle(edges)

        for v in self.stpg.terminals:
            done.make_set(v)

        while edges and len(done.get_disjoint_sets()) > 1:
            edge = edges.pop()
            y, z = edge[0], edge[1]
            if y not in done: done.make_set(y)
            if z not in done: done.make_set(z)
            if done.find(y) != done.find(z):
                result.add(y, z)
                done.union(y, z)

        return result