コード例 #1
0
    def test_mst_random(self):

        graph = WeightedGraph()
        number_of_vertices = 10 ** 3
        max_value = number_of_vertices + 10 ** 2
        number_of_chords = number_of_vertices // 2
        branching_factor = 4
        delta_weight = 30

        vs = sample(range(max_value), number_of_vertices)
        trees = [[v] for v in vs]
        guaranteed = set()
        possible = set()
        min_weight, max_weight = 0, 0
        while len(trees) > 1:  # spanning tree of the graph
            min_weight, max_weight = max_weight, max_weight + delta_weight  # in each iteration weight is increased
            nodes_on_level = max(len(trees) // branching_factor, 1)
            trees, tail = trees[:nodes_on_level], trees[nodes_on_level:]
            for (tree, t) in ((choice(trees), t) for t in tail):  # Cut property:
                [u], [v] = sample(tree, 1), sample(t, 1)  # Let S be any subset of vertices,
                w = randrange(min_weight, max_weight)  # and let e be the min cost edge
                graph.add_direct_link(u, v, w)  # with exactly one endpoint in S.
                tree.extend(t)  # Then the MST contains e.
                e = tuple(sorted((u, v)))
                if nodes_on_level > 1:  # So the lightest edges must be present in the graph's MST
                    guaranteed.add(e)
                else:  # There will be more edges within the last range
                    possible.add(e)
        i = 0
        extralarge_weight = max_weight + delta_weight
        while i < number_of_chords:
            (u, v) = sorted(sample(vs, 2))
            if (u, v) not in graph._edge:
                if getrandbits(1):  # Here they are
                    graph.add_direct_link(u, v, randrange(min_weight, max_weight))  # Cycle property:
                    possible.add((u, v))  # Let C be any cycle in G,
                else:  # and let f be the max cost
                    graph.add_direct_link(u, v, randrange(max_weight, extralarge_weight))  # edge belonging to C.
                i += 1  # Then the MST
        mst = graph.mst()  # does not contain f.
        result = set(mst._edge)
        self.check_spanning(mst, graph)
        self.assertTrue(guaranteed <= result)  # Cut property: contains all min edges of spanning forest
        self.assertTrue(result - guaranteed <= possible)  # Cycle property: contains no heavy chords
コード例 #2
0
    def test_mst_manually(self):

        graph = WeightedGraph()
        graph.add_direct_link(1, 2, 1).add_direct_link(1, 3, 1).add_direct_link(1, 4, 1).add_direct_link(
            2, 3, 1
        ).add_direct_link(2, 4, 1).add_direct_link(3, 4, 1)
        mst = graph.mst()
        self.check_spanning(mst, graph)
        self.assertEqual(mst.weight(), 3)

        graph = WeightedGraph()
        graph.add_direct_link(2, 3, 1).add_direct_link(2, 4, 2).add_direct_link(3, 4, 3).add_direct_link(
            1, 2, 3
        ).add_direct_link(1, 3, 2).add_direct_link(1, 4, 1)
        mst = graph.mst()  # 1-4, 2-3, 2-4 or 1-3, 1-4, 2-3
        self.check_spanning(mst, graph)
        self.assertEqual(mst.weight(), 4)
        self.assertTrue(
            set(mst._edge.items()) == {((1, 4), 1), ((2, 3), 1), ((2, 4), 2)}
            or set(mst._edge.items()) == {((1, 3), 2), ((1, 4), 1), ((2, 3), 1)}
        )