コード例 #1
0
class TestSpanningTrees(unittest.TestCase):
    def setUp(self):
        self.graph = Graph()
        self.graph.add_edges([('a', 'b'), ('a', 's'), ('b', 'c'), ('c', 's'),
                              ('d', 'e'), ('d', 's'), ('e', 'd'), ('e', 's')])

    def test_breadth_first_search(self):
        vertices = list(breadth_first_search(self.graph, 's'))
        self.assertEqual(vertices, ['s', 'a', 'c', 'e', 'd', 'b'])

        vertices = list(breadth_first_search(self.graph, 's', 1))
        self.assertEqual(vertices, ['s', 'a', 'c', 'e', 'd'])

    def test_breadth_first_search_tree(self):
        pred = breadth_first_search_tree(self.graph, 's')
        ans = {'a': 's', 'b': 'a', 'c': 's', 'd': 's', 'e': 's', 's': None}
        self.assertEqual(pred, ans)

    def test_depth_first_search(self):
        vertices = list(depth_first_search(self.graph, 's'))
        self.assertEqual(vertices, ['s', 'd', 'e', 'c', 'b', 'a'])

        vertices = list(depth_first_search(self.graph, 's', 1))
        self.assertEqual(vertices, ['s', 'd', 'e', 'c', 'a'])

    def test_depth_first_search_tree(self):
        pred = depth_first_search_tree(self.graph, 's')
        ans = {'a': 'b', 'b': 'c', 'c': 's', 'd': 's', 'e': 'd', 's': None}
        self.assertEqual(pred, ans)
コード例 #2
0
ファイル: test_traversal.py プロジェクト: siegelzero/rosemary
class TestSpanningTrees(unittest.TestCase):
    def setUp(self):
        self.graph = Graph()
        self.graph.add_edges([
            ('a', 'b'), ('a', 's'), ('b', 'c'), ('c', 's'),
            ('d', 'e'), ('d', 's'), ('e', 'd'), ('e', 's')
        ])

    def test_breadth_first_search(self):
        vertices = list(breadth_first_search(self.graph, 's'))
        self.assertEqual(vertices, ['s', 'a', 'c', 'e', 'd', 'b'])

        vertices = list(breadth_first_search(self.graph, 's', 1))
        self.assertEqual(vertices, ['s', 'a', 'c', 'e', 'd'])

    def test_breadth_first_search_tree(self):
        pred = breadth_first_search_tree(self.graph, 's')
        ans = {'a': 's', 'b': 'a', 'c': 's', 'd': 's', 'e': 's', 's': None}
        self.assertEqual(pred, ans)

    def test_depth_first_search(self):
        vertices = list(depth_first_search(self.graph, 's'))
        self.assertEqual(vertices, ['s', 'd', 'e', 'c', 'b', 'a'])

        vertices = list(depth_first_search(self.graph, 's', 1))
        self.assertEqual(vertices, ['s', 'd', 'e', 'c', 'a'])

    def test_depth_first_search_tree(self):
        pred = depth_first_search_tree(self.graph, 's')
        ans = {'a': 'b', 'b': 'c', 'c': 's', 'd': 's', 'e': 'd', 's': None}
        self.assertEqual(pred, ans)
コード例 #3
0
class TestSpanningTrees(unittest.TestCase):
    def setUp(self):
        # Graph in Section 3.2.2 of Dasgupta
        self.graph = Graph()
        self.graph.add_vertices(['a', 'b', 'c', 'd', 'e', 'f',
                                 'g', 'h', 'i', 'j', 'k', 'l'])

        self.graph.add_edges([('a', 'b'), ('a', 'e'), ('e', 'i'), ('e', 'j'),
                              ('i', 'j'), ('c', 'd'), ('c', 'g'), ('c', 'h'),
                              ('d', 'h'), ('g', 'h'), ('g', 'k'), ('h', 'k'),
                              ('h', 'l')])

        self.graph_components = [
            ['a', 'b', 'e', 'i', 'j'],
            ['c', 'h', 'd', 'g', 'k', 'l'],
            ['f']
        ]

        self.graph_component = ['a', 'b', 'e', 'i', 'j']

    def test_connected_component(self):
        component = connected_component(self.graph, 'a')
        self.assertEqual(component, self.graph_component)

    def test_connected_components(self):
        components = connected_components(self.graph)
        self.assertEqual(components, self.graph_components)
コード例 #4
0
ファイル: test_paths.py プロジェクト: ynasser/rosemary
    def setUp(self):
        graph = Graph()
        graph.add_edges([('a', 'b', 2), ('a', 'c', 1), ('b', 'c', 1),
                         ('b', 'd', 2), ('b', 'e', 3), ('c', 'e', 4),
                         ('d', 'e', 2)])
        self.graph = graph

        self.distance = {'a': 0, 'b': 2, 'c': 1, 'd': 4, 'e': 5}
        self.previous = {'a': None, 'b': 'a', 'c': 'a', 'd': 'b', 'e': 'c'}
コード例 #5
0
    def setUp(self):
        # Example in Section 5.1.5 in Dasgupta
        graph = Graph()
        graph.add_edges([('a', 'b', 5), ('a', 'c', 6), ('a', 'd', 4),
                         ('b', 'c', 1), ('b', 'd', 2), ('c', 'd', 2),
                         ('c', 'e', 5), ('c', 'f', 3), ('d', 'f', 4),
                         ('e', 'f', 4)])
        self.dasgupta_graph = graph
        self.dasgupta_weight = 14
        self.dasgupta_edges = [('a', 'd'), ('b', 'c'), ('b', 'd'), ('c', 'f'),
                               ('e', 'f')]
        self.dasgupta_dict = {
            'a': None,
            'b': 'd',
            'c': 'b',
            'd': 'a',
            'e': 'f',
            'f': 'c'
        }

        graph = Graph()
        graph.add_edges([(1, 2, 3), (1, 3, 4), (1, 4, 5), (2, 3, 4),
                         (3, 4, 5)])
        self.gabow_graph = graph
        self.gabow_trees = [(12, [(1, 2), (1, 3), (1, 4)]),
                            (12, [(1, 2), (1, 4), (2, 3)]),
                            (12, [(1, 2), (1, 3), (3, 4)]),
                            (12, [(1, 2), (2, 3), (3, 4)]),
                            (13, [(1, 3), (1, 4), (2, 3)]),
                            (13, [(1, 3), (2, 3), (3, 4)]),
                            (13, [(1, 2), (1, 4), (3, 4)]),
                            (14, [(1, 4), (2, 3), (3, 4)])]

        self.petersen_graph = petersen_graph()
コード例 #6
0
    def setUp(self):
        # Graph in Section 3.2.2 of Dasgupta
        self.graph = Graph()
        self.graph.add_vertices(
            ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l'])

        self.graph.add_edges([('a', 'b'), ('a', 'e'), ('e', 'i'), ('e', 'j'),
                              ('i', 'j'), ('c', 'd'), ('c', 'g'), ('c', 'h'),
                              ('d', 'h'), ('g', 'h'), ('g', 'k'), ('h', 'k'),
                              ('h', 'l')])

        self.graph_components = [['a', 'b', 'e', 'i', 'j'],
                                 ['c', 'h', 'd', 'g', 'k', 'l'], ['f']]

        self.graph_component = ['a', 'b', 'e', 'i', 'j']
コード例 #7
0
ファイル: test_cliques.py プロジェクト: ynasser/rosemary
    def setUp(self):
        self.petersen_graph = petersen_graph()
        self.random_graph10_5 = random_graph(10, 0.5)
        self.random_graph100_3 = random_graph(100, 0.3)

        self.petersen_cliques = [
            [0, 1], [0, 4], [0, 5], [1, 2], [1, 6],
            [2, 3], [2, 7], [3, 4], [3, 8], [4, 9],
            [5, 7], [5, 8], [6, 8], [6, 9], [7, 9],
        ]

        self.random_graph_edges = [
            (0, 2), (0, 3), (0, 5), (0, 7),
            (0, 9), (1, 2), (1, 3), (1, 5),
            (1, 6), (1, 7), (1, 9), (2, 3),
            (2, 5), (2, 6), (2, 7), (2, 8),
            (3, 5), (3, 7), (4, 6), (4, 7),
            (5, 6), (5, 7), (5, 9), (6, 7),
            (6, 8), (6, 9), (7, 9),
        ]

        self.random_graph = Graph()
        self.random_graph.add_edges(self.random_graph_edges)
        self.random_graph_clique = [0, 2, 3, 5, 7]

        self.coprime_graph10 = coprime_pairs_graph(10)
        self.coprime_graph10_weight = 30
        self.coprime_graph10_clique = [1, 5, 7, 8, 9]

        self.coprime_graph100 = coprime_pairs_graph(100)
        self.coprime_graph100_weight = 1356
        self.coprime_graph100_clique = [
            1, 17, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61,
            67, 71, 73, 79, 81, 83, 88, 89, 91, 95, 97,
        ]
コード例 #8
0
    def setUp(self):
        # Example in Section 5.1.5 in Dasgupta
        graph = Graph()
        graph.add_edges([('u1', 'u2', 1), ('u1', 'v1', 2), ('u1', 'v2', 2),
                         ('u2', 'v3', 4), ('u2', 'v4', 3), ('u2', 'v5', 5),
                         ('u3', 'v1', 2), ('u3', 'v3', 8), ('u4', 'v2', 8),
                         ('u4', 'v5', 8), ('v1', 'v2', 8), ('v1', 'v3', 9),
                         ('v2', 'v5', 5), ('v3', 'v4', 8)])

        self.graph1 = graph
        self.terminals1 = ['v1', 'v2', 'v3', 'v4', 'v5']
        self.weight1 = 17
        self.edges1 = [('u1', 'u2'), ('u1', 'v1'), ('u1', 'v2'), ('u2', 'v3'), ('u2', 'v4'), ('u2', 'v5')]

        graph = Graph()
        graph.add_edges([(0, 1, 1), (0, 4, 2), (1, 2, 3), (1, 4, 1), (1, 5, 2),
                         (2, 3, 2), (2, 6, 6), (3, 6, 3), (3, 7, 1), (4, 5, 3),
                         (4, 8, 3), (4, 9, 4), (5, 6, 1), (5, 9, 4), (5, 10, 3),
                         (6, 7, 4), (6, 10, 2), (7, 10, 1), (7, 11, 2), (8, 9, 2),
                         (8, 12, 1), (9, 10, 5), (9, 13, 6), (10, 11, 3), (10, 13, 1),
                         (10, 14, 1), (10, 15, 4), (11, 15, 1), (12, 13, 3),
                         (13, 14, 4), (14, 15, 6)])

        self.graph2 = graph
        self.terminals2 = [0, 3, 6, 9, 12, 15]
        self.weight2 = 18
        self.edges2 = [(0, 1), (1, 5), (3, 6), (3, 7), (5, 6), (5, 9), (7, 11), (8, 9), (8, 12), (11, 15)]

        graph = Graph()
        edges = [
            (0, 10, 0.18711581985575576), (1, 9, 0.8355759080627565), (1, 16, 0.7333895522013495),
            (2, 8, 0.2179642234669944), (2, 13, 0.8912036215549415), (2, 19, 0.6431373258117827),
            (2, 24, 0.04038712999015037), (3, 6, 0.12324233297257259), (4, 6, 0.8716054380512974),
            (4, 14, 0.8394000635595052), (5, 13, 0.5808432084428543), (5, 15, 0.3817889531355405),
            (6, 28, 0.7104386125476283), (7, 17, 0.8196386513589949), (7, 22, 0.5415599110939858),
            (7, 26, 0.48022044306517697), (10, 13, 0.2289107839123704), (10, 27, 0.6078612772657713),
            (10, 28, 0.18320583236837396), (11, 14, 0.21670116683074658), (11, 23, 0.814622874490316),
            (11, 24, 0.2741012085352842), (12, 14, 0.020838710732781984), (12, 26, 0.32305190820208796),
            (13, 16, 0.7798216089004076), (14, 24, 0.42823907465971456), (14, 29, 0.8005872492974788),
            (15, 24, 0.5714901649169496), (16, 23, 0.3254825323952686), (17, 19, 0.4371620863350263),
            (17, 20, 0.7305916551727157), (17, 26, 0.20057807143450757), (18, 25, 0.99192719132646),
            (19, 25, 0.4630494211413302), (20, 29, 0.02443067673210797), (21, 22, 0.19217126655249206),
            (21, 29, 0.5188924055605231), (22, 25, 0.7632549163886935), (24, 28, 0.8954891075360596)
        ]
        graph.add_edges(edges)
        self.graph3 = graph
        self.terminals3 = range(5)
        self.weight3 = 4.708933602364698
        self.edges3 = [(0, 10), (1, 16), (2, 13), (3, 6), (4, 6), (6, 28), (10, 13), (10, 28), (13, 16)]
コード例 #9
0
    def setUp(self):
        # Example in Section 5.1.5 in Dasgupta
        graph = Graph()
        graph.add_edges([('a', 'b', 5), ('a', 'c', 6), ('a', 'd', 4),
                         ('b', 'c', 1), ('b', 'd', 2), ('c', 'd', 2),
                         ('c', 'e', 5), ('c', 'f', 3), ('d', 'f', 4),
                         ('e', 'f', 4)])
        self.dasgupta_graph = graph
        self.dasgupta_weight = 14
        self.dasgupta_edges = [('a', 'd'), ('b', 'c'), ('b', 'd'), ('c', 'f'), ('e', 'f')]
        self.dasgupta_dict = {'a': None, 'b': 'd', 'c': 'b', 'd': 'a', 'e': 'f', 'f': 'c'}

        graph = Graph()
        graph.add_edges([(1, 2, 3), (1, 3, 4), (1, 4, 5), (2, 3, 4), (3, 4, 5)])
        self.gabow_graph = graph
        self.gabow_trees = [
            (12, [(1, 2), (1, 3), (1, 4)]),
            (12, [(1, 2), (1, 4), (2, 3)]),
            (12, [(1, 2), (1, 3), (3, 4)]),
            (12, [(1, 2), (2, 3), (3, 4)]),
            (13, [(1, 3), (1, 4), (2, 3)]),
            (13, [(1, 3), (2, 3), (3, 4)]),
            (13, [(1, 2), (1, 4), (3, 4)]),
            (14, [(1, 4), (2, 3), (3, 4)])
        ]

        self.petersen_graph = petersen_graph()
コード例 #10
0
class TestSpanningTrees(unittest.TestCase):
    def setUp(self):
        # Graph in Section 3.2.2 of Dasgupta
        self.graph = Graph()
        self.graph.add_vertices(
            ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l'])

        self.graph.add_edges([('a', 'b'), ('a', 'e'), ('e', 'i'), ('e', 'j'),
                              ('i', 'j'), ('c', 'd'), ('c', 'g'), ('c', 'h'),
                              ('d', 'h'), ('g', 'h'), ('g', 'k'), ('h', 'k'),
                              ('h', 'l')])

        self.graph_components = [['a', 'b', 'e', 'i', 'j'],
                                 ['c', 'h', 'd', 'g', 'k', 'l'], ['f']]

        self.graph_component = ['a', 'b', 'e', 'i', 'j']

    def test_connected_component(self):
        component = connected_component(self.graph, 'a')
        self.assertEqual(component, self.graph_component)

    def test_connected_components(self):
        components = connected_components(self.graph)
        self.assertEqual(components, self.graph_components)
コード例 #11
0
def _delete_nonterminal_leaves(edges, terminals):
    r"""Prunes all non-terminal leaves from the tree.

    Given the edges of a tree and a set of terminal vertices, this method
    removes all non-terminal leaves and returns the new tree edges.

    Parameters
    ----------
    edges : list
        A list of the edges of the tree.

    terminals : set
        A set of the terminal vertices.

    Returns
    -------
    tree_edges : list
        A list of the edges of the pruned tree.

    Notes
    -----
    This method deletes all non-terminal leaves from the tree. This process
    is repeated until all leaves are terminals. There is room to improve
    this algorithm.
    """
    # Form a graph from the edge list.
    tree = Graph()
    for (u, v) in edges:
        tree.add_edge(u, v)

    # Now delete all leaves that are not terminals
    while True:
        leaves = tree.leaves()
        changed = False

        for leaf in leaves:
            if leaf not in terminals:
                tree.delete_vertex(leaf)
                changed = True

        if not changed:
            break

    return tree.edges()
コード例 #12
0
    def setUp(self):
        # Graph in Section 3.2.2 of Dasgupta
        self.graph = Graph()
        self.graph.add_vertices(['a', 'b', 'c', 'd', 'e', 'f',
                                 'g', 'h', 'i', 'j', 'k', 'l'])

        self.graph.add_edges([('a', 'b'), ('a', 'e'), ('e', 'i'), ('e', 'j'),
                              ('i', 'j'), ('c', 'd'), ('c', 'g'), ('c', 'h'),
                              ('d', 'h'), ('g', 'h'), ('g', 'k'), ('h', 'k'),
                              ('h', 'l')])

        self.graph_components = [
            ['a', 'b', 'e', 'i', 'j'],
            ['c', 'h', 'd', 'g', 'k', 'l'],
            ['f']
        ]

        self.graph_component = ['a', 'b', 'e', 'i', 'j']
コード例 #13
0
    def setUp(self):
        graph = Graph()
        graph.add_edges([('a', 'b', 2), ('a', 'c', 1), ('b', 'c', 1),
                         ('b', 'd', 2), ('b', 'e', 3), ('c', 'e', 4),
                         ('d', 'e', 2)])
        self.graph = graph

        self.distance = {'a': 0, 'b': 2, 'c': 1, 'd': 4, 'e': 5}
        self.previous = {'a': None, 'b': 'a', 'c': 'a', 'd': 'b', 'e': 'c'}

        graph = Graph()
        edges = [('a', 'd', 4), ('a', 'e', 1), ('a', 'h', 10), ('b', 'c', 2), ('b', 'f', 1), ('c', 'f', 3),
                 ('d', 'h', 1), ('e', 'f', 3), ('e', 'h', 5), ('f', 'g', 7), ('f', 'i', 1), ('g', 'j', 1),
                 ('h', 'i', 9), ('i', 'j', 2)]

        graph.add_edges(edges)

        self.graph2 = graph
        self.distance2 = {'a': 4, 'c': 11, 'b': 9, 'e': 5, 'd': 0, 'g': 12, 'f': 8, 'i': 9, 'h': 1, 'j': 11}
        self.previous2 = {'a': 'd', 'c': 'f', 'b': 'f', 'e': 'a', 'd': None,
                          'g': 'j', 'f': 'e', 'i': 'f', 'h': 'd', 'j': 'i'}
コード例 #14
0
 def setUp(self):
     self.graph = Graph()
     self.graph.add_edges([('a', 'b'), ('a', 's'), ('b', 'c'), ('c', 's'),
                           ('d', 'e'), ('d', 's'), ('e', 'd'), ('e', 's')])
コード例 #15
0
def distance_network_heuristic(graph, terminals):
    r"""Returns an approximate minimal Steiner tree connecting `terminals`
    in `graph`.

    Given a connected, undirected graph `graph` with positive edge weights
    and a subset of the vertices `terminals`, this method finds a subgraph
    with near-minimal total edge cost among all connected subgraphs that
    contain these vertices.

    Parameters
    ----------
    graph : rosemary.graphs.graphs.Graph

    terminals : list or set or tuple
        A collection of vertices of `graph`.

    Returns
    -------
    (weight, edges) : tuple
        The number `weight` is the weight of the Steiner tree. The list
        `edges` is a list of the edges in the Steiner tree.

    Notes
    -----
    The Steiner problem in graphs asks to find the minimal tree connecting
    the terminal vertices. This problem is NP-complete and has proven to be
    extremely difficult even for small problem instances. Given this, it is
    of practical importance to have heuristics for finding low-cost Steiner
    trees.

    This method uses the heuristic algorithm given in [1], which produces a
    tree spanning the terminals with total cost <= 2*(1 - 1/t)*MST, where t
    is the number of terminal vertices and MST is the weight of a minimal
    Steiner tree. We also apply the improvement procedure given in [3].

    The implementation given runs in time O(t*|E|*log(|V|)), where |E| is
    the number of edges of `graph` and |V| is the number of vertices.

    References
    ----------
    .. [1] L. Kou, G. Markowsky, L. Berman, "A Fast Algorithm for Steiner
    Trees", Acta Informatica, Volume 15, Issue 2, June 1981, 141-145.

    .. [2] P. Winter, "Steiner Problem in Networks: A Survey", Networks,
    Volume 17, Issue 2, Summer 1987, 129-167.

    .. [3] S. Voss, "Steiner's Problem in Graphs: Heuristic Methods",
    Discrete Applied Mathematics 40, 1992, 45-72.

    .. [4] H.J. Proemel, A. Steger, "The Steiner Tree Problem - A Tour
    through Graphs, Algorithms, and Complexity", Vieweg, 2002.

    Examples
    --------
    >>> G = Graph()
    >>> G.add_edges([('u1', 'u2', 1), ('u1', 'v1', 2), ('u1', 'v2', 2),
                     ('u2', 'v3', 4), ('u2', 'v4', 3), ('u2', 'v5', 5),
                     ('u3', 'v1', 2), ('u3', 'v3', 8), ('u4', 'v2', 8),
                     ('u4', 'v5', 8), ('v1', 'v2', 8), ('v1', 'v3', 9),
                     ('v2', 'v5', 5), ('v3', 'v4', 8)])
    >>> distance_network_heuristic(G, ['v1', 'v2', 'v3', 'v4', 'v5'])
    (17, [('u1', 'u2'), ('u1', 'v1'), ('u1', 'v2'), ('u2', 'v3'),
          ('u2', 'v4'), ('v2', 'v5')])
    """
    # Create the distance network induced by the terminal set.
    distance_network = Graph()

    # shortest_prev[u] holds the predecessor dict for the shortest path
    # tree rooted at u.
    shortest_prev = {}
    shortest_dist = {}

    for u in terminals:
        u_dist, u_prev = dijkstra(graph, u)
        shortest_dist[u] = u_dist
        shortest_prev[u] = u_prev

    # For each pair (u, v) of terminal vertices, add an edge with weight
    # equal to the length of the shortest u, v path.
    distance_network.add_edges([(u, v, shortest_dist[u][v]) for (u, v) in itertools.combinations(terminals, 2)])

    # Determine the minimum spanning tree of the distance network.
    _, mst_edges = prim(distance_network, edge_list=True)
    subnetwork = Graph()

    # Construct a subnetwork of the graph by replacing each edge in the
    # minimum spanning tree by the corresponding minimum cost path.
    for (u, v) in mst_edges:
        a, b = shortest_prev[u][v], v
        while a is not None:
            subnetwork.add_edge(a, b, graph[a][b])
            a, b = shortest_prev[u][a], a

    # Determine the minimum spanning tree of the subnetwork.
    _, subnetwork_mst_edges = prim(subnetwork, edge_list=True)
    tree_weight, tree_edges = _improve(graph, subnetwork_mst_edges, terminals)

    return (tree_weight, tree_edges)
コード例 #16
0
    def setUp(self):
        # Example in Section 5.1.5 in Dasgupta
        graph = Graph()
        graph.add_edges([('u1', 'u2', 1), ('u1', 'v1', 2), ('u1', 'v2', 2),
                         ('u2', 'v3', 4), ('u2', 'v4', 3), ('u2', 'v5', 5),
                         ('u3', 'v1', 2), ('u3', 'v3', 8), ('u4', 'v2', 8),
                         ('u4', 'v5', 8), ('v1', 'v2', 8), ('v1', 'v3', 9),
                         ('v2', 'v5', 5), ('v3', 'v4', 8)])

        self.graph1 = graph
        self.terminals1 = ['v1', 'v2', 'v3', 'v4', 'v5']
        self.weight1 = 17
        self.edges1 = [('u1', 'u2'), ('u1', 'v1'), ('u1', 'v2'), ('u2', 'v3'),
                       ('u2', 'v4'), ('u2', 'v5')]

        graph = Graph()
        graph.add_edges([(0, 1, 1), (0, 4, 2), (1, 2, 3), (1, 4, 1), (1, 5, 2),
                         (2, 3, 2), (2, 6, 6), (3, 6, 3), (3, 7, 1), (4, 5, 3),
                         (4, 8, 3), (4, 9, 4), (5, 6, 1), (5, 9, 4),
                         (5, 10, 3), (6, 7, 4), (6, 10, 2), (7, 10, 1),
                         (7, 11, 2), (8, 9, 2), (8, 12, 1), (9, 10, 5),
                         (9, 13, 6), (10, 11, 3), (10, 13, 1), (10, 14, 1),
                         (10, 15, 4), (11, 15, 1), (12, 13, 3), (13, 14, 4),
                         (14, 15, 6)])

        self.graph2 = graph
        self.terminals2 = [0, 3, 6, 9, 12, 15]
        self.weight2 = 18
        self.edges2 = [(0, 1), (1, 5), (3, 6), (3, 7), (5, 6), (5, 9), (7, 11),
                       (8, 9), (8, 12), (11, 15)]

        graph = Graph()
        edges = [(0, 10, 0.18711581985575576), (1, 9, 0.8355759080627565),
                 (1, 16, 0.7333895522013495), (2, 8, 0.2179642234669944),
                 (2, 13, 0.8912036215549415), (2, 19, 0.6431373258117827),
                 (2, 24, 0.04038712999015037), (3, 6, 0.12324233297257259),
                 (4, 6, 0.8716054380512974), (4, 14, 0.8394000635595052),
                 (5, 13, 0.5808432084428543), (5, 15, 0.3817889531355405),
                 (6, 28, 0.7104386125476283), (7, 17, 0.8196386513589949),
                 (7, 22, 0.5415599110939858), (7, 26, 0.48022044306517697),
                 (10, 13, 0.2289107839123704), (10, 27, 0.6078612772657713),
                 (10, 28, 0.18320583236837396), (11, 14, 0.21670116683074658),
                 (11, 23, 0.814622874490316), (11, 24, 0.2741012085352842),
                 (12, 14, 0.020838710732781984), (12, 26, 0.32305190820208796),
                 (13, 16, 0.7798216089004076), (14, 24, 0.42823907465971456),
                 (14, 29, 0.8005872492974788), (15, 24, 0.5714901649169496),
                 (16, 23, 0.3254825323952686), (17, 19, 0.4371620863350263),
                 (17, 20, 0.7305916551727157), (17, 26, 0.20057807143450757),
                 (18, 25, 0.99192719132646), (19, 25, 0.4630494211413302),
                 (20, 29, 0.02443067673210797), (21, 22, 0.19217126655249206),
                 (21, 29, 0.5188924055605231), (22, 25, 0.7632549163886935),
                 (24, 28, 0.8954891075360596)]
        graph.add_edges(edges)
        self.graph3 = graph
        self.terminals3 = range(5)
        self.weight3 = 4.708933602364698
        self.edges3 = [(0, 10), (1, 16), (2, 13), (3, 6), (4, 6), (6, 28),
                       (10, 13), (10, 28), (13, 16)]
コード例 #17
0
ファイル: spanning_trees.py プロジェクト: ynasser/rosemary
def gabow(graph, k=None):
    def find_exchange(father, included, excluded):
        X = NamedUnionFind(vertices)
        find = X.find
        union = X.union

        (min_weight, e, f) = (inf, None, None)

        for (x, y) in included:
            # Make it so that y = father[x]
            if y != father[x]:
                x, y = y, x
            y = find(y)
            union(x, y, y)

        for edge in excluded:
            mark(edge)

        for (x, y) in edges:
            if (x, y) in marked or (y, x) in marked:
                unmark((x, y))
                unmark((y, x))

            elif father[x] != y and father[y] != x:
                a = find(x)
                ancestors = set()
                while a not in ancestors:
                    ancestors.add(a)
                    a = find(father[a])

                a = find(y)
                while a not in ancestors:
                    a = find(father[a])

                for u in [x, y]:
                    v = find(u)
                    while v != a:
                        fv = father[v]
                        exchange_weight = weight[x, y] - weight[v, fv]
                        if exchange_weight < min_weight:
                            min_weight = exchange_weight
                            e = (v, fv)
                            f = (x, y)
                        w = find(fv)
                        union(v, w, w)
                        v = w

        return (min_weight, e, f)

    inf = float('inf')
    if k is None:
        k = inf

    weight = {(u, v): graph[u][v] for u in graph for v in graph[u]}

    marked = set()
    mark = marked.add
    unmark = marked.discard

    edges = sorted(graph.edge_set(), key=lambda (u, v): weight[(u, v)])
    vertices = graph.vertices()

    # arbitrary root vertex
    root = vertices[0]
    tree_weight, father = prim(graph, root, edge_list=False)
    father[root] = root

    (exchange_weight, e, f) = find_exchange(father, [], [])
    heap = [(tree_weight + exchange_weight, e, f, father, [], [])]

    tree_edges = sorted([(min(x, y), max(x, y)) for (x, y) in father.items() if x != y])
    yield tree_weight, tree_edges

    j = 1
    while j < k:
        (tree_weight, e, f, father, included, excluded) = heappop(heap)

        if tree_weight == inf:
            return

        new_graph = Graph()
        new_graph.add_edges(father.items())
        new_graph.delete_edge(e)
        new_graph.add_edge(f)

        new_father = breadth_first_search_tree(new_graph, root)
        new_father[root] = root

        tree_edges = sorted([(min(x, y), max(x, y)) for (x, y) in new_father.items() if x != y])
        yield tree_weight, tree_edges

        new_tree_weight = tree_weight - weight[f] + weight[e]

        included_i = included + [e]
        excluded_j = excluded + [e]

        (exchange_weight, e, f) = find_exchange(father, included_i, excluded)
        heappush(heap, (new_tree_weight + exchange_weight, e, f, father, included_i, excluded))

        (exchange_weight, e, f) = find_exchange(new_father, included, excluded_j)
        heappush(heap, (tree_weight + exchange_weight, e, f, new_father, included, excluded_j))
        j += 1
コード例 #18
0
ファイル: test_traversal.py プロジェクト: siegelzero/rosemary
 def setUp(self):
     self.graph = Graph()
     self.graph.add_edges([
         ('a', 'b'), ('a', 's'), ('b', 'c'), ('c', 's'),
         ('d', 'e'), ('d', 's'), ('e', 'd'), ('e', 's')
     ])
コード例 #19
0
def gabow(graph, k=None):
    def find_exchange(father, included, excluded):
        X = NamedUnionFind(vertices)
        find = X.find
        union = X.union

        (min_weight, e, f) = (inf, None, None)

        for (x, y) in included:
            # Make it so that y = father[x]
            if y != father[x]:
                x, y = y, x
            y = find(y)
            union(x, y, y)

        for edge in excluded:
            mark(edge)

        for (x, y) in edges:
            if (x, y) in marked or (y, x) in marked:
                unmark((x, y))
                unmark((y, x))

            elif father[x] != y and father[y] != x:
                a = find(x)
                ancestors = set()
                while a not in ancestors:
                    ancestors.add(a)
                    a = find(father[a])

                a = find(y)
                while a not in ancestors:
                    a = find(father[a])

                for u in [x, y]:
                    v = find(u)
                    while v != a:
                        fv = father[v]
                        exchange_weight = weight[x, y] - weight[v, fv]
                        if exchange_weight < min_weight:
                            min_weight = exchange_weight
                            e = (v, fv)
                            f = (x, y)
                        w = find(fv)
                        union(v, w, w)
                        v = w

        return (min_weight, e, f)

    inf = float('inf')
    if k is None:
        k = inf

    weight = {(u, v): graph[u][v] for u in graph for v in graph[u]}

    marked = set()
    mark = marked.add
    unmark = marked.discard

    edges = sorted(graph.edge_set(), key=lambda (u, v): weight[(u, v)])
    vertices = graph.vertices()

    # arbitrary root vertex
    root = vertices[0]
    tree_weight, father = prim(graph, root, edge_list=False)
    father[root] = root

    (exchange_weight, e, f) = find_exchange(father, [], [])
    heap = [(tree_weight + exchange_weight, e, f, father, [], [])]

    tree_edges = sorted([(min(x, y), max(x, y)) for (x, y) in father.items()
                         if x != y])
    yield tree_weight, tree_edges

    j = 1
    while j < k:
        (tree_weight, e, f, father, included, excluded) = heappop(heap)

        if tree_weight == inf:
            return

        new_graph = Graph()
        new_graph.add_edges(father.items())
        new_graph.delete_edge(e)
        new_graph.add_edge(f)

        new_father = breadth_first_search_tree(new_graph, root)
        new_father[root] = root

        tree_edges = sorted([(min(x, y), max(x, y))
                             for (x, y) in new_father.items() if x != y])
        yield tree_weight, tree_edges

        new_tree_weight = tree_weight - weight[f] + weight[e]

        included_i = included + [e]
        excluded_j = excluded + [e]

        (exchange_weight, e, f) = find_exchange(father, included_i, excluded)
        heappush(heap, (new_tree_weight + exchange_weight, e, f, father,
                        included_i, excluded))

        (exchange_weight, e, f) = find_exchange(new_father, included,
                                                excluded_j)
        heappush(heap, (tree_weight + exchange_weight, e, f, new_father,
                        included, excluded_j))
        j += 1
コード例 #20
0
    def setUp(self):
        self.petersen_graph = petersen_graph()
        self.petersen_colors = 3

        self.coprime_graph30 = coprime_pairs_graph(30)
        self.coprime_graph30_colors = 11

        graph = Graph()
        graph.add_edges([(0, 2), (0, 4), (0, 5), (0, 8), (1, 3), (1, 4), (2, 6), (2, 8), (3, 4), (3, 7), (4, 6), (4, 7),
                         (4, 9), (5, 8)])
        self.small_random = graph
        self.small_colors = 3
        self.small_classes = [[4, 8], [0, 3, 6, 9], [1, 2, 5, 7]]

        graph = Graph()
        graph.add_edges([(0, 4), (0, 6), (1, 2), (1, 4), (1, 8), (1, 9), (2, 3), (2, 4), (3, 5), (3, 7), (4, 6), (4, 8),
                         (4, 9), (5, 7), (5, 9), (6, 8), (7, 8)])
        self.small_random2 = graph
        self.small_colors2 = 4
        self.small_classes2 = [[4, 7], [0, 2, 8, 9], [1, 5, 6], [3]]

        graph = Graph()
        graph.add_edges([(0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 7), (0, 8), (0, 9), (0, 10), (0, 11), (0, 12),
                         (0, 13), (0, 14), (0, 15), (0, 16), (0, 17), (0, 18), (0, 19), (1, 2), (1, 3), (1, 4), (1, 5),
                         (1, 6), (1, 7), (1, 8), (1, 9), (1, 10), (1, 12), (1, 14), (1, 15), (1, 17), (1, 18), (1, 19),
                         (2, 4), (2, 5), (2, 6), (2, 7), (2, 8), (2, 9), (2, 11), (2, 12), (2, 13), (2, 14), (2, 15),
                         (2, 17), (2, 18), (2, 19), (3, 4), (3, 5), (3, 6), (3, 7), (3, 8), (3, 9), (3, 10), (3, 11),
                         (3, 12), (3, 14), (3, 15), (3, 16), (3, 17), (3, 18), (4, 5), (4, 6), (4, 7), (4, 9), (4, 10),
                         (4, 11), (4, 13), (4, 14), (4, 15), (4, 16), (4, 17), (4, 18), (4, 19), (5, 6), (5, 7), (5, 9),
                         (5, 10), (5, 13), (5, 14), (5, 15), (5, 17), (5, 19), (6, 8), (6, 9), (6, 10), (6, 11),
                         (6, 12), (6, 13), (6, 14), (6, 15), (6, 16), (6, 17), (6, 19), (7, 8), (7, 9), (7, 12),
                         (7, 15), (7, 16), (7, 17), (7, 19), (8, 9), (8, 10), (8, 11), (8, 12), (8, 13), (8, 14),
                         (8, 16), (8, 17), (8, 18), (8, 19), (9, 10), (9, 11), (9, 14), (9, 17), (9, 18), (9, 19),
                         (10, 11), (10, 12), (10, 13), (10, 15), (10, 16), (10, 17), (10, 18), (10, 19), (11, 12),
                         (11, 13), (11, 14), (11, 15), (11, 16), (11, 17), (11, 18), (11, 19), (12, 13), (12, 14),
                         (12, 15), (12, 16), (12, 17), (12, 18), (12, 19), (13, 14), (13, 15), (13, 16), (13, 17),
                         (13, 18), (13, 19), (14, 16), (14, 17), (14, 18), (15, 17), (15, 19), (16, 18), (16, 19),
                         (17, 18), (18, 19)])
        self.big_random = graph
        self.big_colors = 10
        self.big_classes = [[0, 6], [17, 19], [4, 8], [5, 11], [7, 10, 14], [2, 3], [15, 18], [9, 12], [1, 16], [13]]
コード例 #21
0
ファイル: test_cliques.py プロジェクト: ynasser/rosemary
class TestCliques(unittest.TestCase):
    def setUp(self):
        self.petersen_graph = petersen_graph()
        self.random_graph10_5 = random_graph(10, 0.5)
        self.random_graph100_3 = random_graph(100, 0.3)

        self.petersen_cliques = [
            [0, 1], [0, 4], [0, 5], [1, 2], [1, 6],
            [2, 3], [2, 7], [3, 4], [3, 8], [4, 9],
            [5, 7], [5, 8], [6, 8], [6, 9], [7, 9],
        ]

        self.random_graph_edges = [
            (0, 2), (0, 3), (0, 5), (0, 7),
            (0, 9), (1, 2), (1, 3), (1, 5),
            (1, 6), (1, 7), (1, 9), (2, 3),
            (2, 5), (2, 6), (2, 7), (2, 8),
            (3, 5), (3, 7), (4, 6), (4, 7),
            (5, 6), (5, 7), (5, 9), (6, 7),
            (6, 8), (6, 9), (7, 9),
        ]

        self.random_graph = Graph()
        self.random_graph.add_edges(self.random_graph_edges)
        self.random_graph_clique = [0, 2, 3, 5, 7]

        self.coprime_graph10 = coprime_pairs_graph(10)
        self.coprime_graph10_weight = 30
        self.coprime_graph10_clique = [1, 5, 7, 8, 9]

        self.coprime_graph100 = coprime_pairs_graph(100)
        self.coprime_graph100_weight = 1356
        self.coprime_graph100_clique = [
            1, 17, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61,
            67, 71, 73, 79, 81, 83, 88, 89, 91, 95, 97,
        ]

    def test_maximal_cliques(self):
        print "Testing Bron-Kerbosh algorithm"
        cliques = [sorted(e) for e in bron_kerbosch(self.petersen_graph)]
        self.assertEqual(sorted(cliques), self.petersen_cliques)

        print "Testing binary Bron-Kerbosh algorithm"
        cliques = [sorted(e) for e in bron_kerbosch_binary(self.petersen_graph)]
        self.assertEqual(sorted(cliques), self.petersen_cliques)

        print "Testing Tomita algorithm"
        cliques = [sorted(e) for e in tomita(self.petersen_graph)]
        self.assertEqual(sorted(cliques), self.petersen_cliques)

        print "Testing generic maximal cliques algorithm"
        for algorithm in ['tomita', 'bron_kerbosch', 'bron_kerbosch_binary']:
            cliques = [sorted(e) for e in maximal_cliques(self.petersen_graph, algorithm=algorithm)]
            self.assertEqual(sorted(cliques), self.petersen_cliques)

        print "Testing with random graphs"
        cliques1 = list(bron_kerbosch(self.random_graph10_5))
        cliques2 = list(bron_kerbosch_binary(self.random_graph10_5))
        cliques3 = list(tomita(self.random_graph10_5))

        self.assertEqual(len(cliques1), len(cliques2))
        self.assertEqual(len(cliques2), len(cliques3))

        cliques1 = list(bron_kerbosch(self.random_graph100_3))
        cliques2 = list(bron_kerbosch_binary(self.random_graph100_3))
        cliques3 = list(tomita(self.random_graph100_3))

        self.assertEqual(len(cliques1), len(cliques2))
        self.assertEqual(len(cliques2), len(cliques3))

    def test_maximum_clique(self):
        print "Testing Ostergard algorithm"
        size, clique = ostergard(self.random_graph)
        self.assertEqual(size, 5)
        self.assertEqual(sorted(clique), self.random_graph_clique)

        print "Testing Pardalos algorithm"
        size, clique = pardalos(self.random_graph)
        self.assertEqual(size, 5)
        self.assertEqual(sorted(clique), self.random_graph_clique)

        print "Testing generic maximum-clique algorithm"
        for algorithm in ['pardalos', 'ostergard']:
            size, clique = maximum_clique(self.random_graph, algorithm=algorithm)
            self.assertEqual(size, 5)
            self.assertEqual(sorted(clique), self.random_graph_clique)

    def test_maximum_weight_clique(self):
        print "Testing Maximum-weight clique algorithm"
        size, clique = maximum_weight_clique(self.coprime_graph10)
        self.assertEqual(size, self.coprime_graph10_weight)
        self.assertEqual(sorted(clique), self.coprime_graph10_clique)

        size, clique = maximum_weight_clique(self.coprime_graph100)
        self.assertEqual(size, self.coprime_graph100_weight)
        self.assertEqual(sorted(clique), self.coprime_graph100_clique)
コード例 #22
0
ファイル: test_cliques.py プロジェクト: fagan2888/rosemary
    def setUp(self):
        self.petersen_graph = petersen_graph()
        self.random_graph10_5 = random_graph(10, 0.5)
        self.random_graph100_3 = random_graph(100, 0.3)

        self.petersen_cliques = [
            [0, 1],
            [0, 4],
            [0, 5],
            [1, 2],
            [1, 6],
            [2, 3],
            [2, 7],
            [3, 4],
            [3, 8],
            [4, 9],
            [5, 7],
            [5, 8],
            [6, 8],
            [6, 9],
            [7, 9],
        ]

        self.random_graph_edges = [
            (0, 2),
            (0, 3),
            (0, 5),
            (0, 7),
            (0, 9),
            (1, 2),
            (1, 3),
            (1, 5),
            (1, 6),
            (1, 7),
            (1, 9),
            (2, 3),
            (2, 5),
            (2, 6),
            (2, 7),
            (2, 8),
            (3, 5),
            (3, 7),
            (4, 6),
            (4, 7),
            (5, 6),
            (5, 7),
            (5, 9),
            (6, 7),
            (6, 8),
            (6, 9),
            (7, 9),
        ]

        self.random_graph = Graph()
        self.random_graph.add_edges(self.random_graph_edges)
        self.random_graph_clique = [0, 2, 3, 5, 7]
        self.random_graph_clique2 = [1, 5, 6, 7, 9]

        self.coprime_graph10 = coprime_pairs_graph(10)
        self.coprime_graph10_weight = 30
        self.coprime_graph10_clique = [1, 5, 7, 8, 9]

        self.coprime_graph100 = coprime_pairs_graph(100)
        self.coprime_graph100_weight = 1356
        self.coprime_graph100_clique = [
            1,
            17,
            23,
            29,
            31,
            37,
            41,
            43,
            47,
            53,
            59,
            61,
            67,
            71,
            73,
            79,
            81,
            83,
            88,
            89,
            91,
            95,
            97,
        ]
コード例 #23
0
ファイル: test_cliques.py プロジェクト: fagan2888/rosemary
class TestCliques(unittest.TestCase):
    def setUp(self):
        self.petersen_graph = petersen_graph()
        self.random_graph10_5 = random_graph(10, 0.5)
        self.random_graph100_3 = random_graph(100, 0.3)

        self.petersen_cliques = [
            [0, 1],
            [0, 4],
            [0, 5],
            [1, 2],
            [1, 6],
            [2, 3],
            [2, 7],
            [3, 4],
            [3, 8],
            [4, 9],
            [5, 7],
            [5, 8],
            [6, 8],
            [6, 9],
            [7, 9],
        ]

        self.random_graph_edges = [
            (0, 2),
            (0, 3),
            (0, 5),
            (0, 7),
            (0, 9),
            (1, 2),
            (1, 3),
            (1, 5),
            (1, 6),
            (1, 7),
            (1, 9),
            (2, 3),
            (2, 5),
            (2, 6),
            (2, 7),
            (2, 8),
            (3, 5),
            (3, 7),
            (4, 6),
            (4, 7),
            (5, 6),
            (5, 7),
            (5, 9),
            (6, 7),
            (6, 8),
            (6, 9),
            (7, 9),
        ]

        self.random_graph = Graph()
        self.random_graph.add_edges(self.random_graph_edges)
        self.random_graph_clique = [0, 2, 3, 5, 7]
        self.random_graph_clique2 = [1, 5, 6, 7, 9]

        self.coprime_graph10 = coprime_pairs_graph(10)
        self.coprime_graph10_weight = 30
        self.coprime_graph10_clique = [1, 5, 7, 8, 9]

        self.coprime_graph100 = coprime_pairs_graph(100)
        self.coprime_graph100_weight = 1356
        self.coprime_graph100_clique = [
            1,
            17,
            23,
            29,
            31,
            37,
            41,
            43,
            47,
            53,
            59,
            61,
            67,
            71,
            73,
            79,
            81,
            83,
            88,
            89,
            91,
            95,
            97,
        ]

    def test_maximal_cliques(self):
        print "Testing Bron-Kerbosh algorithm"
        cliques = [sorted(e) for e in bron_kerbosch(self.petersen_graph)]
        self.assertEqual(sorted(cliques), self.petersen_cliques)

        print "Testing binary Bron-Kerbosh algorithm"
        cliques = [
            sorted(e) for e in bron_kerbosch_binary(self.petersen_graph)
        ]
        self.assertEqual(sorted(cliques), self.petersen_cliques)

        print "Testing Tomita algorithm"
        cliques = [sorted(e) for e in tomita(self.petersen_graph)]
        self.assertEqual(sorted(cliques), self.petersen_cliques)

        print "Testing generic maximal cliques algorithm"
        for algorithm in ['tomita', 'bron_kerbosch', 'bron_kerbosch_binary']:
            cliques = [
                sorted(e) for e in maximal_cliques(self.petersen_graph,
                                                   algorithm=algorithm)
            ]
            self.assertEqual(sorted(cliques), self.petersen_cliques)

        print "Testing with random graphs"
        cliques1 = list(bron_kerbosch(self.random_graph10_5))
        cliques2 = list(bron_kerbosch_binary(self.random_graph10_5))
        cliques3 = list(tomita(self.random_graph10_5))

        self.assertEqual(len(cliques1), len(cliques2))
        self.assertEqual(len(cliques2), len(cliques3))

        cliques1 = list(bron_kerbosch(self.random_graph100_3))
        cliques2 = list(bron_kerbosch_binary(self.random_graph100_3))
        cliques3 = list(tomita(self.random_graph100_3))

        self.assertEqual(len(cliques1), len(cliques2))
        self.assertEqual(len(cliques2), len(cliques3))

    def test_maximum_clique(self):
        print "Testing Ostergard algorithm"
        size, clique = ostergard(self.random_graph)
        self.assertEqual(size, 5)
        self.assertEqual(sorted(clique), self.random_graph_clique2)

        print "Testing Pardalos algorithm"
        size, clique = pardalos(self.random_graph)
        self.assertEqual(size, 5)
        self.assertEqual(sorted(clique), self.random_graph_clique)

        print "Testing generic maximum-clique algorithm"
        for algorithm in ['pardalos', 'ostergard']:
            size, clique = maximum_clique(self.random_graph,
                                          algorithm=algorithm)
            self.assertEqual(size, 5)

    def test_maximum_weight_clique(self):
        print "Testing Maximum-weight clique algorithm"
        size, clique = maximum_weight_clique(self.coprime_graph10)
        self.assertEqual(size, self.coprime_graph10_weight)
        self.assertEqual(sorted(clique), self.coprime_graph10_clique)

        size, clique = maximum_weight_clique(self.coprime_graph100)
        self.assertEqual(size, self.coprime_graph100_weight)
        self.assertEqual(sorted(clique), self.coprime_graph100_clique)