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()
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:]))
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))
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")
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)))
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('{} {}')
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)
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))
# 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)