Esempio n. 1
0
    def __init__(self, G):
        self._weight = 0.0  # total weight of MST
        self._mst = Queue()  # edges in the MST
        self._marked = [False] * G.V()  # marked[v] = True if v on tree
        self._pq = MinPQ()  # edges with one endpoint in tree

        for v in range(G.V()):  # run Prim from all vertices to
            if not self._marked[v]:
                self._prim(G, v)  # get a minimum spanning forest
    def __init__(self, G):
        # initialise
        self._mst = Queue()
        self._edges = MinPQ()
        for edge in G.edges():
            self._edges.insert(edge)
        self._uf = WeightedQuickUnionUF(G.V())

        while not self._edges.is_empty() and self._mst.size() < G.V() - 1:
            min_edge = self._edges.del_min()
            u = min_edge.either()
            v = min_edge.other(u)
            if self._uf.connected(u, v):
                continue  # ineligible edge
            self._uf.union(u, v)  # union (are part of mst now)
            self._mst.enqueue(min_edge)
Esempio n. 3
0
    def __init__(self, G):
        """
        Compute a minimum spanning tree (or forest) of an edge-weighted graph.
        :param G: the edge-weighted graph
        """
        self._weight = 0.0  # total weight of MST
        self._mst = Queue()  # edges in the MST
        self._marked = [False] * G.V()  # marked[v] = True if v on tree
        self._pq = MinPQ()  # edges with one endpoint in tree

        for v in range(G.V()):  # run Prim from all vertices to
            if not self._marked[v]:
                self._prim(G, v)  # get a minimum spanning forest

        # check optimality conditions
        assert self._check(G)
Esempio n. 4
0
class LazyPrimMST:
    def __init__(self, G):
        self._weight = 0.0  # total weight of MST
        self._mst = Queue()  # edges in the MST
        self._marked = [False] * G.V()  # marked[v] = True if v on tree
        self._pq = MinPQ()  # edges with one endpoint in tree

        for v in range(G.V()):  # run Prim from all vertices to
            if not self._marked[v]:
                self._prim(G, v)  # get a minimum spanning forest

    def _prim(self, G, s):
        # run prim's algorithm
        self._scan(G, s)
        while not self._pq.is_empty():  # better to stop when mst has V-1 edges
            e = self._pq.del_min()  # smallest edge on pq (frontier)
            v = e.either()  # two endpoints
            w = e.other(v)
            assert self._marked[v] or self._marked[w]
            if (self._marked[v]
                    and self._marked[w]):  # lazy, both v and w already scanned
                continue
            self._mst.enqueue(e)  # add e to MST
            self._weight += e.weight()
            if not self._marked[v]:
                self._scan(G, v)  # v becomes part of tree
            if not self._marked[w]:
                self._scan(G, w)  # w becomes part of tree

    def _scan(self, G, v):
        # add all edges e incident to v onto pq if the other endpoint has not yet been scanned
        assert not self._marked[v]
        self._marked[v] = True
        for e in G.adj(v):
            if not self._marked[e.other(v)]:
                self._pq.insert(e)

    def edges(self):
        return self._mst

    def weight(self):
        return self._weight
Esempio n. 5
0
    def __init__(self, G):
        """Computes a minimum spanning tree (or forest) of an edge-weighted
        graph.

        :param G: the edge-weighted graph

        """
        self._weight = 0
        self._mst = Queue()
        pq = MinPQ()

        for e in G.edges():
            pq.insert(e)

        uf = WeightedQuickUnionUF(G.V())
        while not pq.is_empty() and self._mst.size() < G.V() - 1:
            e = pq.del_min()
            v = e.either()
            w = e.other(v)
            if not uf.connected(v, w):
                uf.union(v, w)
                self._mst.enqueue(e)
                self._weight += e.weight()
def _build_trie(freq):
    pq = MinPQ()
    for i in range(0, _R):
        if freq[i] > 0:
            pq.insert(_Node(chr(i), freq[i], None, None))
    if pq.size() == 0:
        raise ValueError("The provided file is empty")
    if pq.size() == 1:
        if freq[ord("\0")] == 0:
            pq.insert(_Node("\0", 0, None, None))
        else:
            pq.insert(_Node("\1", 0, None, None))
    while pq.size() > 1:
        left = pq.del_min()
        right = pq.del_min()
        parent = _Node("\0", left.freq + right.freq, left, right)
        pq.insert(parent)
    return pq.del_min()
Esempio n. 7
0
class LazyPrimMST:
    """The LazyPrimMST class represents a data type for computing a minimum
    spanning tree in an edge-weighted graph. The edge weights can be positive,
    zero, or negative and need not be distinct. If the graph is not connected,
    it computes a minimum spanning forest, which is the union of minimum
    spanning trees in each connected component. The weight() method returns the
    weight of a minimum spanning tree and the edges() method returns its edges.

    This implementation uses a lazy version of Prim's algorithm with a
    binary heap of edges. The constructor takes time proportional to E
    log E and extra space (not including the graph) proportional to E,
    where V is the number of vertices and E is the number of edges.
    Afterwards, the weight() method takes constant time and the edges()
    method takes time proportional to V.

    """

    FLOATING_POINT_EPSILON = 1e-12

    def __init__(self, G):
        """Compute a minimum spanning tree (or forest) of an edge-weighted
        graph.

        :param G: the edge-weighted graph

        """
        self._weight = 0.0  # total weight of MST
        self._mst = Queue()  # edges in the MST
        self._marked = [False] * G.V()  # marked[v] = True if v on tree
        self._pq = MinPQ()  # edges with one endpoint in tree

        for v in range(G.V()):  # run Prim from all vertices to
            if not self._marked[v]:
                self._prim(G, v)  # get a minimum spanning forest

        # check optimality conditions
        assert self._check(G)

    def _prim(self, G, s):
        # run Prim's algorithm
        self._scan(G, s)
        while not self._pq.is_empty():  # better to stop when mst has V-1 edges
            e = self._pq.del_min()  # smallest edge on pq
            v = e.either()  # two endpoints
            w = e.other(v)
            assert self._marked[v] or self._marked[w]
            if (self._marked[v]
                    and self._marked[w]):  # lazy, both v and w already scanned
                continue
            self._mst.enqueue(e)  # add e to MST
            self._weight += e.weight()
            if not self._marked[v]:
                self._scan(G, v)  # v becomes part of tree
            if not self._marked[w]:
                self._scan(G, w)  # w becomes part of tree

    def _scan(self, G, v):
        # add all edges e incident to v onto pq if the other endpoint has not yet been scanned
        assert not self._marked[v]
        self._marked[v] = True
        for e in G.adj(v):
            if not self._marked[e.other(v)]:
                self._pq.insert(e)

    def edges(self):
        """Returns the edges in a minimum spanning tree (or forest).

        :returns: the edges in a minimum spanning tree (or forest) as
            an iterable of edges

        """
        return self._mst

    def weight(self):
        """Returns the sum of the edge weights in a minimum spanning tree (or
        forest).

        :returns: the sum of the edge weights in a minimum spanning tree (or forest)

        """
        return self._weight

    def _check(self, G):
        # check optimality conditions (takes time proportional to E V lg* V)

        totalWeight = 0.0  # check weight
        for e in self.edges():
            totalWeight += e.weight()

        if abs(totalWeight -
               self.weight()) > LazyPrimMST.FLOATING_POINT_EPSILON:
            error = "Weight of edges does not equal weight(): {} vs. {}\n".format(
                totalWeight, self.weight())
            print(error, file=sys.stderr)
            return False

        # check that it is acyclic
        uf = UF(G.V())
        for e in self.edges():
            v = e.either()
            w = e.other(v)
            if uf.connected(v, w):
                print("Not a forest", file=sys.stderr)
                return False
            uf.union(v, w)

        # check that it is a spanning forest
        for e in G.edges():
            v = e.either()
            w = e.other(v)
            if not uf.connected(v, w):
                print("Not a forest", file=sys.stderr)
                return False

        # check that it is a minimal spanning forest (cut optimality conditions)
        for e in self.edges():
            # all edges in MST except e
            uf = UF(G.V())
            for f in self._mst:
                x = f.either()
                y = f.other(x)
                if f != e:
                    uf.union(x, y)

            # check that e is min weight edge in crossing cut
            for f in G.edges():
                x = f.either()
                y = f.other(x)
                if not uf.connected(x, y):
                    if f.weight() < e.weight():
                        error = "Edge {} violates cut optimality conditions".format(
                            f)
                        print(error, file=sys.stderr)
                        return False
        return True
Esempio n. 8
0
def _build_trie(freq):
    pq = MinPQ()
    for i in range(0, _R):
        if (freq[i] > 0):
            pq.insert(_Node(chr(i), freq[i], None, None))
    if (pq.size() == 0):
        raise ValueError("The provided file is empty")
    if (pq.size() == 1):
        if (freq[ord('\0')] == 0):
            pq.insert(_Node('\0', 0, None, None))
        else:
            pq.insert(_Node('\1', 0, None, None))
    while (pq.size() > 1):
        left = pq.del_min()
        right = pq.del_min()
        parent = _Node('\0', left.freq + right.freq, left, right)
        pq.insert(parent)
    return pq.del_min()