Ejemplo n.º 1
0
    def _find_negative_cycle(self):
        V = len(self._edgeTo)
        spt = EdgeWeightedDigraph(V)
        for v in range(V):
            if self._edgeTo[v] is not None:
                spt.add_edge(self._edgeTo[v])

        finder = EdgeWeightedDirectedCycle(spt)
        self._cycle = finder.cycle()
Ejemplo n.º 2
0
def solve(h, weights):
    # construct complete binary tree
    weights = [item for sublist in weights for item in sublist]
    h += 1
    V = int((h * (h + 1)) / 2)
    G = EdgeWeightedDigraph(V)

    # construct edges of the graph
    _sum = 0
    added_edges = 0
    for level in range(0, h):
        for i in range(level):
            #print(f'add: {_sum+i}, {_sum+i+level}')
            G.add_edge(
                DirectedEdge(_sum + i, _sum + i + level, weights[added_edges]))
            added_edges += 1
            #print(f'add: {_sum+i}, {_sum+i+level+1}')
            G.add_edge(
                DirectedEdge(_sum + i, _sum + i + level + 1,
                             weights[added_edges]))
            added_edges += 1
        _sum += level

    dist_to = [math.inf for _ in range(V)]

    q = IndexMinPQ(G.V())
    q.insert(0, 0.0)  # enqueue root
    dist_to[0] = 0.0

    # iterate until all vertices possibly reachable are reached
    while not q.is_empty():
        u = q.del_min()
        for e in G.adj(u):
            u = e.from_vertex()
            v = e.to_vertex()
            if dist_to[v] > dist_to[u] + e.weight():
                dist_to[v] = dist_to[u] + e.weight()
                if q.contains(v):
                    q.decrease_key(v, dist_to[v])
                else:
                    q.insert(v, dist_to[v])

    # while not q.is_empty():
    #    curr = q.dequeue()
    #    for adj in G.adj(curr):
    #        u = curr
    #        v = adj.other(u)
    #        if dist_to[v] > dist_to[u] + adj.weight():
    #            dist_to[v] = dist_to[u] + adj.weight()
    #            q.enqueue(v)

    # get minimum of leaves
    return int(min(dist_to[len(dist_to) - h:]))
Ejemplo n.º 3
0
def main(args):
    stream = InStream(args[0])
    s = int(args[1])
    G = EdgeWeightedDigraph.from_stream(stream)
    sp = BellmanFordSP(G, s)

    #print negative cycle
    if sp.has_negative_cycle():
        for e in sp.negative_cycle():
            print(e)
    #print shortest paths
    else:
        for v in range(G.V()):
            if sp.has_path_to(v):
                print("{} to {} ({})  ".format(s, v, sp.dist_to(v)))
                for e in sp.path_to(v):
                    print("{}\t".format(e), end='')
                print()
            else:
                print("{} to {} no path".format(s, v))
Ejemplo n.º 4
0
def main():
    """
    Creates an EdgeWeightedDigraph from input file.
    Runs DijkstraSP on the graph with the given source vertex.
    Prints the shortest path from the source vertex to all other vertices.
    """
    if len(sys.argv) == 3:
        stream = InStream(sys.argv[1])
        G = EdgeWeightedDigraph.from_stream(stream)
        s = int(sys.argv[2])
        sp = DijkstraSP(G, s)
        for t in range(G.V()):
            if sp.has_path_to(t):
                print("{} to {} ({:.2f})  ".format(s, t, sp.dist_to(t)),
                      end='')
                for e in sp.path_to(t):
                    print(e, end='   ')
                print()
            else:
                print("{} to {}         no path\n".format(s, t))
def main(args):
    from itu.algs4.stdlib import stdrandom as stdrandom

    # create random DAG with V vertices and E edges; then add F random edges
    V = int(args[0])
    E = int(args[1])
    F = int(args[2])
    G = EdgeWeightedDigraph(V)
    vertices = [i for i in range(V)]
    stdrandom.shuffle(vertices)
    for _ in range(E):
        while True:
            v = stdrandom.uniformInt(0, V)
            w = stdrandom.uniformInt(0, V)
            if v >= w:
                break
        weight = stdrandom.uniformFloat(0.0, 1.0)
        G.add_edge(DirectedEdge(v, w, weight))

    # add F extra edges
    for _ in range(F):
        v = stdrandom.uniformInt(0, V)
        w = stdrandom.uniformInt(0, V)
        weight = stdrandom.uniformFloat(0.0, 1.0)
        G.add_edge(DirectedEdge(v, w, weight))

    print(G)

    # find a directed cycle
    finder = EdgeWeightedDirectedCycle(G)
    if finder.has_cycle():
        print("Cycle: ")
        for e in finder.cycle():
            print("{}  ".format(e), end="")
        print()
    # or give topologial sort
    else:
        print("No directed cycle")
Ejemplo n.º 6
0
        while edge is not None:
            path.push(edge)
            edge = self._edge_to[edge.from_vertex()]
        return path

    # relax edge e, but update if you find a *longer* path
    def _relax(self, edge):
        v, w = edge.from_vertex(), edge.to_vertex()
        if self._dist_to[w] < self._dist_to[v] + edge.weight():
            self._dist_to[w] = self._dist_to[v] + edge.weight()
            self._edge_to[w] = edge

    # throw an IllegalArgumentException unless 0 <= v < V
    def _validate_vertex(self, v):
        V = len(self._dist_to)
        if not (0 <= v < V):
            raise ValueError("vertex {} is not between 0 and {}".format(
                v, V - 1))


if __name__ == "__main__":
    # Create stream from file or the standard input,
    # depending on whether a file name was passed.
    stream = sys.argv[1] if len(sys.argv) > 1 else None
    d = EdgeWeightedDigraph.from_stream(instream.InStream(stream))
    a = AcyclicLp(d, 3)

    # print longest paths to all other vertices
    for i in range(d.V()):
        print("{} to {}".format(i, a.path_to(i)))
Ejemplo n.º 7
0
    where V is the number of currencies.

    For additional documentation, see Section 4.4 of Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
    """
    if len(sys.argv) > 1:
        try: 
            sys.stdin = open(sys.argv[1])
        except IOError:
            print("File not found, using standard input instead")
    
    # V currencies
    V = stdio.readInt()
    name = [None]*V
    
    # Create complete network
    graph = EdgeWeightedDigraph(V)
    for v in range(V):
        name[v] = stdio.readString()
        for w in range(V):
            rate = stdio.readFloat()
            edge = DirectedEdge(v, w, -math.log(rate))
            graph.add_edge(edge)
    
    # find negative cycle
    spt = BellmanFordSP(graph, 0)
    if spt.has_negative_cycle():
        stake = 1000.0
        for edge in spt.negative_cycle():
            print('{} {}', stake, name[edge.from_vertex()])
            stake *= math.exp(-edge.weight())
            print('{} {}')
Ejemplo n.º 8
0
        return path

    def _validate_vertex(self, v):
        # raise an ValueError unless 0 <= v < V
        V = len(self._dist_to)
        if v < 0 or v >= V:
            raise ValueError("vertex {} is not between 0 and {}".format(
                v, V - 1))


if __name__ == "__main__":
    import sys
    from itu.algs4.stdlib.instream import InStream
    from itu.algs4.stdlib import stdio
    from itu.algs4.graphs.edge_weighted_digraph import EdgeWeightedDigraph

    In = InStream(sys.argv[1])
    s = int(sys.argv[2])
    G = EdgeWeightedDigraph.from_stream(In)

    # find shortest path from s to each other vertex in DAG
    sp = AcyclicSP(G, s)
    for v in range(G.V()):
        if sp.has_path_to(v):
            stdio.writef("%d to %d (%.2f)  ", s, v, sp.dist_to(v))
            for e in sp.path_to(v):
                stdio.writef("%s\t", e.__repr__())
            stdio.writeln()
        else:
            stdio.writef("%d to %d no path\n", s, v)
Ejemplo n.º 9
0
        e = self._edge_to[v]
        while e is not None:
            path.push(e)
            e = self._edge_to[e.from_vertex()]
        return path

    def _relax(self, e):
        v = e.from_vertex()
        w = e.to_vertex()
        if self._dist_to[w] > self._dist_to[v] + e.weight():
            self._dist_to[w] = self._dist_to[v] + e.weight()
            self._edge_to[w] = e
            if self._pq.contains(w):
                self._pq.decrease_key(w, self._dist_to[w])
            else:
                self._pq.insert(w, self._dist_to[w])


if __name__ == '__main__':
    G = EdgeWeightedDigraph(5)
    G.add_edge(DirectedEdge(0, 1, 2))
    G.add_edge(DirectedEdge(0, 2, 2))
    G.add_edge(DirectedEdge(0, 3, 4))
    G.add_edge(DirectedEdge(2, 3, 1))
    G.add_edge(DirectedEdge(1, 4, 3))
    G.add_edge(DirectedEdge(3, 4, 6))

    spt = DijkstraSP(G)
    for i in range(5):
        print(spt.path_to(i), spt.dist_to(i))
Ejemplo n.º 10
0
# Try this with the jobsPC.txt data file
if __name__ == '__main__':
    # Create stream from file or the standard input,
    # depending on whether a file name was passed.
    file = sys.argv[1] if len(sys.argv) > 1 else None
    stream = instream.InStream(file)

    # Number of jobs
    N = stream.readInt()

    # Source and sink
    source, sink = 2 * N, 2 * N + 1

    # Construct the network
    G = EdgeWeightedDigraph(2 * N + 2)
    for i in range(N):
        duration = stream.readFloat()
        G.add_edge(DirectedEdge(i, i + N, duration))
        G.add_edge(DirectedEdge(source, i, 0.0))
        G.add_edge(DirectedEdge(i + N, sink, 0.0))

        # Precedence constraints
        m = stream.readInt()
        for _ in range(m):
            successor = stream.readInt()
            G.add_edge(DirectedEdge(i + N, successor, 0.0))

    # Compute longest path
    lp = AcyclicLp(G, source)