Exemple #1
0
    def __call__(self, treegraph: UGraph):

        GRAPH = self.stpg.graph
        vertices = set(treegraph.vertices)

        # Build the subgraph induced by the nodes in treegraph
        subgraph = UWGraph()
        for v in vertices:
            for u in GRAPH.adjacent_to(v):
                if u in vertices:
                    weigth = GRAPH.weight(v, u)
                    subgraph.add_edge(v, u, weight=weigth)

        # Compute the Prim MST for the subgraph
        mst = UGraph()
        queue = PriorityQueue()

        start = choice(tuple(vertices))

        for next_node, weight in subgraph.edges[start].items():
            queue.push(weight, (start, next_node))

        while queue:
            node_start, node_end = queue.pop()
            if node_end not in mst:
                mst.add_edge(node_start, node_end)

                for next_node, weight in subgraph.edges[node_end].items():
                    queue.push(weight, (node_end, next_node))

        return mst
Exemple #2
0
    def test_is_steiner_tree(self):
        stpg = self.stpg

        chromosome = gen_random_kruskal(stpg)
        tree = UGraph()

        for edge in chromosome:
            v, u = edge
            tree.add_edge(v, u)

        _, response = is_steiner_tree(tree, stpg)
        self.assertTrue(response['all_terminals_in'])
        self.assertFalse(response['has_cycle'])
        self.assertTrue(response['all_edges_are_reliable'])
        self.assertTrue(response['graph_is_connected'])
    def test_edge_non_exist_in_stpg_instance(self):
        filename = path.join("tests", "data", "test4.txt")
        stpg = ReaderORLibrary().parser(filename)

        tree = UGraph()
        edges = [(1, 3), (3, 8), (8, 5), (5, 6), (8, 9)]
        for edge in edges:
            v, u = edge
            tree.add_edge(v, u)

        evaluator = EvaluateTreeGraph(stpg)
        self.assertTrue(callable(evaluator))

        with self.assertRaises(ValueError):
            cost, __ = evaluator(tree)
Exemple #4
0
    def __call__(self):

        GRAPH = self.stpg.graph
        terminals = self.stpg.terminals.copy()
        result = UGraph()

        v = terminals.pop()
        while terminals:
            adjacents = GRAPH.adjacent_to(v, lazy=False)
            u = sample(adjacents, k=1)[0]
            if u not in result:
                result.add_edge(v, u)
                terminals.discard(u)
            v = u

        return result
    def test_example_solution_two_components(self):
        filename = path.join("tests", "data", "test4.txt")
        stpg = ReaderORLibrary().parser(filename)

        tree = UGraph()
        edges = [(1, 3), (3, 8), (8, 5), (5, 6), (2, 4)]
        for edge in edges:
            v, u = edge
            tree.add_edge(v, u)

        evaluator = EvaluateTreeGraph(stpg)
        self.assertTrue(callable(evaluator))

        cost, nro_partition = evaluator(tree)

        self.assertEqual(nro_partition, 2)
        self.assertEqual(cost, (5 + 7 + 7 + 15 + 16))
    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)}'
        stpg = self.stpg
        terminals = set(stpg.terminals)

        subgraph = UGraph()
        for edge in parent_a:
            u, v = edge
            subgraph.add_edge(u, v)
        for edge in parent_b:
            u, v = edge
            subgraph.add_edge(u, v)

        done = set()
        result = EdgeSet()

        v = terminals.pop()
        while terminals:
            done.add(v)
            adjacents = subgraph.adjacent_to(v, lazy=False)
            u = sample(adjacents, k=1)[0]
            if u not in done:
                result.add(v, u)
            terminals.discard(u)
            v = u

        return result
    def test_if_is_it_a_tree(self):
        filename = path.join('datasets', 'ORLibrary', 'steinb15.txt')
        stpg = ReaderORLibrary().parser(filename)

        crossover = CrossoverKruskalRST(stpg)

        parent_a = gen_random_walk(stpg)
        parent_b = gen_random_walk(stpg)
        offspring = crossover(parent_a, parent_b)

        tree = UGraph()
        for edge in offspring:
            u, v = edge[0], edge[1]
            tree.add_edge(u, v)

        _, response = is_steiner_tree(tree, stpg)
        self.assertTrue(response['all_terminals_in'])
        self.assertFalse(response['has_cycle'])
        self.assertTrue(response['all_edges_are_reliable'])
        self.assertTrue(response['graph_is_connected'])
Exemple #8
0
    def __call__(self, treegraph: UGraph):

        terminals = self.terminals
        result = UGraph()
        for v, u in treegraph.gen_undirect_edges():
            result.add_edge(v, u)

        leaves = deque([
            v for v in result.vertices
            if (v not in terminals) and (result.degree(v) == 1)
        ])

        while leaves:
            v = leaves.pop()
            for w in result.adjacent_to(v):
                if (w not in terminals) and (result.degree(w) == 2):
                    leaves.appendleft(w)
            result.remove_node(v)

        return result
    def test_penality_function(self):

        filename = path.join("tests", "data", "test4.txt")
        stpg = ReaderORLibrary().parser(filename)

        tree = UGraph()
        edges = [(1, 3), (3, 8), (8, 5), (5, 6), (2, 4)]
        for edge in edges:
            v, u = edge
            tree.add_edge(v, u)

        evaluator = EvaluateTreeGraph(stpg,
                                      penality_function=lambda nro:
                                      (nro - 1) * 100)
        self.assertTrue(callable(evaluator))

        cost, nro_partition = evaluator(tree)

        self.assertEqual(nro_partition, 2)
        self.assertEqual(cost, (5 + 7 + 7 + 15 + 16 + 100))
Exemple #10
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
    def test_simpliest(self):
        stpg = self.stpg

        mutate = MutationReplaceByRandomEdge(stpg)

        after = gen_random_prim(stpg)

        self.assertIsInstance(after, EdgeSet)

        before = mutate(after)

        self.assertIsInstance(before, EdgeSet)

        tree = UGraph()

        for edge in before:
            v, u = edge
            tree.add_edge(v, u)

        _, response = is_steiner_tree(tree, stpg)
        self.assertTrue(response['all_terminals_in'])
        self.assertFalse(response['has_cycle'])
        self.assertTrue(response['all_edges_are_reliable'])
        self.assertTrue(response['graph_is_connected'])
Exemple #12
0
    def __call__(self):

        result = UGraph()
        terminals = self.stpg.terminals.copy()
        GRAPH = self.stpg.graph
        edges = set()  # or is it better a list?
        vi = sample(range(1, self.stpg.nro_nodes + 1), k=1)[0]

        terminals.discard(vi)
        for w in GRAPH.adjacent_to(vi):
            edges.add((vi, w))

        while terminals and edges:
            edge = sample(edges, k=1)[0]  # need to ensure randomness
            v, w = edge
            if w not in result:
                terminals.discard(w)
                result.add_edge(v, w)
                for u in GRAPH.adjacent_to(w):
                    if u not in result:
                        edges.add((w, u))
            edges.remove(edge)  # to remove from a list it can take O(n)

        return result
    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)}'
        stpg = self.stpg
        terminals = set(stpg.terminals)
        done = set()
        result = EdgeSet()

        subgraph = UGraph()
        for edge in parent_a:
            u, v = edge
            subgraph.add_edge(u, v)
        for edge in parent_b:
            u, v = edge
            subgraph.add_edge(u, v)

        vi = terminals.pop()
        done.add(vi)

        candidates_edges = set()
        for u in subgraph.adjacent_to(vi):
            candidates_edges.add((vi, u))

        while candidates_edges and terminals:
            edge = sample(candidates_edges, k=1)[0]
            v, w = edge
            if w not in done:
                done.add(w)
                result.add(v, w)
                terminals.discard(w)
                for u in subgraph.adjacent_to(w):
                    if u not in done: candidates_edges.add((w, u))
            candidates_edges.discard((v, w))

        return result
Exemple #14
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
    def test_exchange_edges(self):
        filename = path.join('tests', 'data', 'test3.txt')
        stpg = ReaderORLibrary().parser(filename)

        red = UGraph()
        edges = [(1, 3), (3, 8), (8, 5), (5, 6)]
        for edge in edges:
            red.add_edge(edge[0], edge[1])

        blue = UGraph()
        edges = [(1, 3), (3, 8), (3, 7), (7, 4), (4, 6)]
        for edge in edges:
            blue.add_edge(edge[0], edge[1])

        crossover = PXTree(stpg)

        child = crossover(red, blue)

        _, response = is_steiner_tree(child, stpg)
        self.assertTrue(response['all_terminals_in'])
        self.assertFalse(response['has_cycle'])
        self.assertTrue(response['all_edges_are_reliable'])
        self.assertTrue(response['graph_is_connected'])
        self.assertTrue(response['all_leaves_are_terminals'])
Exemple #16
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
    def __call__(self, red: UGraph, blue: UGraph):

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

        p_queue = PriorityQueue()
        vertices = list(g_union.vertices)
        v = choice(vertices)
        for u in g_union.adjacent_to(v):
            weight = self.f_weight(v, u)
            p_queue.push(weight, (v, u))

        g_child = UGraph()
        done = set()
        done.add(v)
        while len(p_queue):
            v, u = p_queue.pop()
            if u not in done:
                g_child.add_edge(v, u)
                done.add(u)

            for w in g_union.adjacent_to(u):
                if w not in done:
                    p_queue.push(self.f_weight(u, w), (u, w))

        terminals = self.STPG.terminals

        prunne_leaves = deque([
            v for v in g_child.vertices
            if ((g_child.degree(v) == 1) and (v not in terminals))
        ])

        while prunne_leaves:
            v = prunne_leaves.pop()
            prev = g_child.adjacent_to(v, lazy=False)
            g_child.remove_node(v)
            for w in prev:
                if g_child.degree(w) == 1 and w not in terminals:
                    prunne_leaves.appendleft(w)

        return g_child
Exemple #18
0
    def __call__(self, red: UGraph, blue: UGraph):
        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)}'

        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)

        terminals = self.terminals.copy()
        done = set()
        result = UGraph()
        candidates_edges = set()

        vi = terminals.pop()
        done.add(vi)
        for u in union_g.adjacent_to(vi):
            candidates_edges.add((vi, u))

        while candidates_edges and terminals:
            edge = sample(candidates_edges, k=1)[0]
            v, w = edge
            if w not in done:
                done.add(w)
                result.add_edge(v, w)
                terminals.discard(w)
                for u in union_g.adjacent_to(w):
                    if u not in done:
                        candidates_edges.add((w, u))
            candidates_edges.discard((v, w))

        return result
Exemple #19
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
Exemple #20
0
    def __call__(self, red: UGraph, blue: UGraph):
        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)}'

        terminals = self.terminals.copy()
        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)

        done = set()
        result = UGraph()

        v = terminals.pop()
        while terminals:
            done.add(v)
            adjacents = union_g.adjacent_to(v, lazy=False)
            u = sample(adjacents, k=1)[0]
            if u not in done:
                result.add_edge(v, u)
            terminals.discard(u)
            v = u

        return result
Exemple #21
0
    def __call__(self, red: UGraph, blue: UGraph):

        f_weight = lambda v, u: self.stpg.graph.weight(v, u)

        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)

        queue = PriorityQueue()
        start = choice(tuple(self.stpg.terminals))

        for u in union_g.adjacent_to(start):
            queue.push(f_weight(start, u), (start, u))

        result = UGraph()
        while queue:
            start, end = queue.pop()
            if end not in result:
                result.add_edge(start, end)
                for w in union_g.adjacent_to(end):
                    queue.push(f_weight(end, w), (end, w))

        return result
Exemple #22
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