/** Unit tests the <tt>DepthFirstOrder</tt> data type. */ public static void main(String[] args) { In in = new In(args[0]); Digraph G = new Digraph(in); DepthFirstOrder dfs = new DepthFirstOrder(G); StdOut.println(" v pre post"); StdOut.println("--------------"); for (int v = 0; v < G.V(); v++) { StdOut.printf("%4d %4d %4d\n", v, dfs.pre(v), dfs.post(v)); } StdOut.print("Preorder: "); for (int v : dfs.pre()) { StdOut.print(v + " "); } StdOut.println(); StdOut.print("Postorder: "); for (int v : dfs.post()) { StdOut.print(v + " "); } StdOut.println(); StdOut.print("Reverse postorder: "); for (int v : dfs.reversePost()) { StdOut.print(v + " "); } StdOut.println(); }
public static boolean isTree(Digraph digraph) { Object root = null; for (Iterator i = digraph.vertexIterator(); i.hasNext(); ) { Object vertex = i.next(); int inSize = digraph.incomingSize(vertex); if (inSize == 0) { root = vertex; break; } } // not a tree - no vertex with 0 in-degree if (root == null) return false; // try to reach all vertices from the root candidate BreadthFirstSearch traversal = new BreadthFirstSearch(digraph, root); while (traversal.isValidTree() && traversal.hasNext()) traversal.next(); // not a tree - one of vertices has been seen more than once by the BFS if (!traversal.isValidTree()) return false; // has every vertex been reached? Set seenVertices = traversal.getSeenVertices(); for (Iterator i = digraph.vertexIterator(); i.hasNext(); ) if (!seenVertices.contains(i.next())) return false; // all tests are passed - good! return true; }
public static boolean isAcyclic(Digraph digraph) { int order = digraph.order(); if (order == 0) return true; Set spanned = new HashSet(order); DepthFirstStampSearch dfs = new DepthFirstStampSearch(digraph, digraph.vertexIterator().next()); for (Iterator i = digraph.vertexIterator(); i.hasNext(); ) { Object dfsRoot = i.next(); if (spanned.contains(dfsRoot)) continue; dfs.reset(dfsRoot); Map dfsOrders = dfs.traverse(new HashMap(digraph.order())); for (Iterator j = dfsOrders.entrySet().iterator(); j.hasNext(); ) { Map.Entry entry = (Map.Entry) j.next(); Object origin = entry.getKey(); DepthFirstStampSearch.OrderPair orgOrders = (DepthFirstStampSearch.OrderPair) entry.getValue(); spanned.add(origin); for (ArcIterator k = digraph.outgoingIterator(origin); k.hasNext(); ) { k.next(); Object dst = k.getDestination(); DepthFirstStampSearch.OrderPair dstOrders = (DepthFirstStampSearch.OrderPair) dfsOrders.get(dst); if (dstOrders.getPostOrder() > orgOrders.getPostOrder()) return false; } } if (dfsOrders.size() == order) break; } return true; }
/** * Returns a random rooted-out DAG on <tt>V</tt> vertices and <tt>E</tt> edges. The DAG returned * is not chosen uniformly at random among all such DAGs. * * @param V the number of vertices * @param E the number of edges * @return a random rooted-out DAG on <tt>V</tt> vertices and <tt>E</tt> edges */ public static Digraph rootedOutDAG(int V, int E) { if (E > (long) V * (V - 1) / 2) throw new IllegalArgumentException("Too many edges"); if (E < V - 1) throw new IllegalArgumentException("Too few edges"); Digraph G = new Digraph(V); SET<Edge> set = new SET<Edge>(); // fix a topological order int[] vertices = new int[V]; for (int i = 0; i < V; i++) vertices[i] = i; StdRandom.shuffle(vertices); // one edge pointing from each vertex, other than the root = vertices[V-1] for (int v = 0; v < V - 1; v++) { int w = StdRandom.uniform(v + 1, V); Edge e = new Edge(v, w); set.add(e); G.addEdge(vertices[w], vertices[v]); } while (G.E() < E) { int v = StdRandom.uniform(V); int w = StdRandom.uniform(V); Edge e = new Edge(v, w); if ((v < w) && !set.contains(e)) { set.add(e); G.addEdge(vertices[w], vertices[v]); } } return G; }
/** * Computes the vertices reachable from the source vertex <tt>s</tt> in the digraph <tt>G</tt>. * * @param G the digraph * @param s the source vertex */ public NonrecursiveDirectedDFS(Digraph G, int s) { marked = new boolean[G.V()]; // to be able to iterate over each adjacency list, keeping track of which // vertex in each adjacency list needs to be explored next Iterator<Integer>[] adj = (Iterator<Integer>[]) new Iterator[G.V()]; for (int v = 0; v < G.V(); v++) adj[v] = G.adj(v).iterator(); // depth-first search using an explicit stack Stack<Integer> stack = new Stack<Integer>(); marked[s] = true; stack.push(s); while (!stack.isEmpty()) { int v = stack.peek(); if (adj[v].hasNext()) { int w = adj[v].next(); // StdOut.printf("check %d\n", w); if (!marked[w]) { // discovered vertex w for the first time marked[w] = true; // edgeTo[w] = v; stack.push(w); // StdOut.printf("dfs(%d)\n", w); } } else { // StdOut.printf("%d done\n", v); stack.pop(); } } }
/** Unit tests the <tt>com.akieus.algos.coursera.lib.TopologicalX</tt> data type. */ public static void main(String[] args) { // create random DAG with V vertices and E edges; then add F random edges int V = Integer.parseInt(args[0]); int E = Integer.parseInt(args[1]); int F = Integer.parseInt(args[2]); Digraph G = DigraphGenerator.dag(V, E); // add F extra edges for (int i = 0; i < F; i++) { int v = StdRandom.uniform(V); int w = StdRandom.uniform(V); G.addEdge(v, w); } StdOut.println(G); // find a directed cycle TopologicalX topological = new TopologicalX(G); if (!topological.hasOrder()) { StdOut.println("Not a DAG"); } // or give topologial sort else { StdOut.print("com.akieus.algos.coursera.lib.Topological order: "); for (int v : topological.order()) { StdOut.print(v + " "); } StdOut.println(); } }
private int[] path(Iterable<Integer> v, Iterable<Integer> w) { boolean isWithin = true; for (int i : v) { if (i < 0 || i > G.V() - 1) isWithin = false; } for (int i : w) { if (i < 0 || i > G.V() - 1) isWithin = false; } if (!isWithin) throw new IndexOutOfBoundsException("Arguments not within [0, V-1]"); SAPPath vPath = new SAPPath(G, v); SAPPath wPath = new SAPPath(G, w); int[] distV = vPath.breath(); int[] distW = wPath.breath(); int sap = INFINITY; int distVW = INFINITY; int ancestor = INFINITY; for (int i = 0; i < G.V(); i++) { if (distV[i] != INFINITY && distW[i] != INFINITY) { distVW = distV[i] + distW[i]; if (distVW < sap) { sap = distVW; ancestor = i; } } } int[] p = {sap, ancestor}; return p; }
/** Unit tests the <tt>GabowSCC</tt> data type. */ public static void main(String[] args) { In in = new In(args[0]); Digraph G = new Digraph(in); GabowSCC scc = new GabowSCC(G); // number of connected components int M = scc.count(); StdOut.println(M + " components"); // compute list of vertices in each strong component Queue<Integer>[] components = (Queue<Integer>[]) new Queue[M]; for (int i = 0; i < M; i++) { components[i] = new Queue<Integer>(); } for (int v = 0; v < G.V(); v++) { components[scc.id(v)].enqueue(v); } // print results for (int i = 0; i < M; i++) { for (int v : components[i]) { StdOut.print(v + " "); } StdOut.println(); } }
/** * Ejecuta una caminata aleatoria sobre un grafo dirigido. Imprime por pantalla la cantidad de * pasos que dio antes de visitar todos los nodos del grafo. * * @param G Grafo dirigido sobre el cual se desea realizar la caminata aleatoria. */ public void randomWalk(Digraph G) { int cont = 0; if (G.V() == 0) return; boolean[] viewed = new boolean[G.V()]; int node = 0; viewed[node] = true; while (!this.allTrue(viewed)) { if (G.outdegree(node) == 0) { System.out.println("Encontrado un nodo sin salida"); System.out.println("Cantidad de pasos dados en el Random Walk : " + cont); return; } int visited = this.getRandomNode(G.adj(node), G.outdegree(node)); System.out.println(node + " -> " + visited); viewed[visited] = true; cont++; node = visited; } System.out.println("Cantidad de pasos dados en el Random Walk : " + cont); }
public BreadthFirstDirectedPaths(Digraph G, int s) { marked = new boolean[G.V()]; distTo = new int[G.V()]; edgeTo = new int[G.V()]; for (int v = 0; v < G.V(); v++) distTo[v] = INFINITY; this.s = s; bfs(G, s); }
/** * Determines a depth-first order for the digraph <tt>G</tt>. * * @param G the digraph */ public DepthFirstOrder(Digraph G) { pre = new int[G.V()]; post = new int[G.V()]; postorder = new Queue<Integer>(); preorder = new Queue<Integer>(); marked = new boolean[G.V()]; for (int v = 0; v < G.V(); v++) if (!marked[v]) dfs(G, v); }
/** Unit tests the <tt>NonrecursiveDirectedDFS</tt> data type. */ public static void main(String[] args) { In in = new In(args[0]); Digraph G = new Digraph(in); int s = Integer.parseInt(args[1]); NonrecursiveDirectedDFS dfs = new NonrecursiveDirectedDFS(G, s); for (int v = 0; v < G.V(); v++) if (dfs.marked(v)) StdOut.print(v + " "); StdOut.println(); }
/** Test client. */ public static void main(String[] args) { In in = new In(args[0]); Digraph G = new Digraph(in); StdOut.println(G); StdOut.println(); for (int v = 0; v < G.V(); v++) for (int w : G.adj(v)) StdOut.println(v + "->" + w); }
/** * Returns a random simple digraph on <tt>V</tt> vertices, with an edge between any two vertices * with probability <tt>p</tt>. This is sometimes referred to as the Erdos-Renyi random digraph * model. * * @param V the number of vertices * @param p the probability of choosing an edge * @return a random simple digraph on <tt>V</tt> vertices, with an edge between any two vertices * with probability <tt>p</tt> * @throws IllegalArgumentException if probability is not between 0 and 1 */ public static Digraph simple(int V, double p) { if (p < 0.0 || p > 1.0) throw new IllegalArgumentException("Probability must be between 0 and 1"); Digraph G = new Digraph(V); for (int v = 0; v < V; v++) for (int w = 0; w < V; w++) if (v != w) if (StdRandom.bernoulli(p)) G.addEdge(v, w); return G; }
// does the id[] array contain the strongly connected components? private boolean check(Digraph G) { TransitiveClosure tc = new TransitiveClosure(G); for (int v = 0; v < G.V(); v++) { for (int w = 0; w < G.V(); w++) { if (stronglyConnected(v, w) != (tc.reachable(v, w) && tc.reachable(w, v))) return false; } } return true; }
public static Map shiftLevelsDown(Map vertexLevelMap, Digraph digraph) { for (Iterator i = digraph.vertexIterator(); i.hasNext(); ) { Object rootCandidate = i.next(); if (digraph.incomingSize(rootCandidate) == 0) shiftLevelsDown(vertexLevelMap, digraph, rootCandidate); } return vertexLevelMap; }
/** Return the reverse of the digraph. */ public Digraph reverse() { Digraph R = new Digraph(V); for (int v = 0; v < V; v++) { for (int w : adj(v)) { R.addEdge(w, v); } } return R; }
/** * Returns a complete binary tree digraph on <tt>V</tt> vertices. * * @param V the number of vertices in the binary tree * @return a digraph that is a complete binary tree on <tt>V</tt> vertices */ public static Digraph binaryTree(int V) { Digraph G = new Digraph(V); int[] vertices = new int[V]; for (int i = 0; i < V; i++) vertices[i] = i; StdRandom.shuffle(vertices); for (int i = 1; i < V; i++) { G.addEdge(vertices[i], vertices[(i - 1) / 2]); } return G; }
public KosarajuSCC(Digraph G) { marked = new boolean[G.V()]; id = new int[G.V()]; DepthFirstOrder order = new DepthFirstOrder(G.reverse()); for (int s : order.reverse()) if (!marked[s]) { dfs(G, s); count++; } }
/** * Returns a path digraph on <tt>V</tt> vertices. * * @param V the number of vertices in the path * @return a digraph that is a directed path on <tt>V</tt> vertices */ public static Digraph path(int V) { Digraph G = new Digraph(V); int[] vertices = new int[V]; for (int i = 0; i < V; i++) vertices[i] = i; StdRandom.shuffle(vertices); for (int i = 0; i < V - 1; i++) { G.addEdge(vertices[i], vertices[i + 1]); } return G; }
DepthFirstOrder(Digraph G) { marked = new boolean[G.V()]; pre = new LinkedList<Integer>(); post = new LinkedList<Integer>(); reversePost = new Stack<Integer>(); for (int v = 0; v < G.V(); v++) { if (!marked[v]) { dfs(G, v); } } }
public static Map computeLevels(Map vertexLevelMap, Digraph digraph, boolean longest) { if (vertexLevelMap == null) vertexLevelMap = new HashMap(digraph.order()); for (Iterator i = digraph.vertexIterator(); i.hasNext(); ) { Object rootCandidate = i.next(); if (digraph.incomingSize(rootCandidate) == 0) computeLevels(vertexLevelMap, digraph, rootCandidate, longest); } return vertexLevelMap; }
/** * Unit tests the <tt>SymbolDigraph</tt> data type. */ public static void main(String[] args) { String filename = args[0]; String delimiter = args[1]; SymbolDigraph sg = new SymbolDigraph(filename, delimiter); Digraph G = sg.G(); while (!StdIn.isEmpty()) { String t = StdIn.readLine(); for (int v : G.adj(sg.index(t))) { StdOut.println(" " + sg.name(v)); } } }
private boolean rootedDAG(Digraph g) { int roots = 0; for (int i = 0; i < g.V(); i++) { if (!g.adj(i).iterator().hasNext()) { roots++; if (roots > 1) { return false; } } } return roots == 1; }
public static Digraph merge(Digraph destination, DigraphIteration graphToMerge) { for (Iterator i = graphToMerge.vertexIterator(); i.hasNext(); ) { destination.addVertex(i.next()); } for (ArcIterator i = graphToMerge.arcIterator(); i.hasNext(); ) { Object arc = i.next(); Object origin = i.getOrigin(); Object dst = i.getDestination(); destination.putArc(origin, dst, arc); } return destination; }
private Digraph initHypernyms(String sss) { In in = new In(sss); Digraph graph = new Digraph(this.idToSynset.size()); while (in.hasNextLine()) { String[] getLines = in.readLine().split(","); Integer id = Integer.valueOf(getLines[0]); for (int i = 1; i < getLines.length; i++) { graph.addEdge(id, Integer.valueOf(getLines[i])); } } return graph; }
public static Digraph randomize(Digraph digraph, int order, int size, Random randomizer) { for (int i = 1; i <= order; i++) digraph.addVertex(new Integer(i)); Random random = randomizer; int n_2 = order * order; size = Math.min(size, n_2); for (int arc = 1; arc <= size; arc++) { int arcCode = random.nextInt(n_2); int origin = arcCode / order + 1; int dst = arcCode % order + 1; digraph.putArc(new Integer(origin), new Integer(dst), new Integer(arc)); } return digraph; }
/** Copy constructor. */ public Digraph(Digraph G) { this(G.V()); this.E = G.E(); for (int v = 0; v < G.V(); v++) { // reverse so that adjacency list is in same order as original Stack<Integer> reverse = new Stack<Integer>(); for (int w : G.adj[v]) { reverse.push(w); } for (int w : reverse) { adj[v].add(w); } } }
private KosarajuSharirSCC(Digraph<V> digraph) { ids = new HashMap<>(digraph.vertexCount()); visited = new HashSet<>(digraph.vertexCount()); size = new int[digraph.vertexCount()]; DepthFirstOrder<V> dfo = DepthFirstOrder.from(digraph.reverse()); for (V vertex : dfo.reversePost()) { if (!visited.contains(vertex)) { dfs(digraph, vertex); count++; } } }
/** * Computes the strong components of the digraph <tt>G</tt>. * * @param G the digraph */ public GabowSCC(Digraph G) { marked = new boolean[G.V()]; stack1 = new Stack<Integer>(); stack2 = new Stack<Integer>(); id = new int[G.V()]; preorder = new int[G.V()]; for (int v = 0; v < G.V(); v++) id[v] = -1; for (int v = 0; v < G.V(); v++) { if (!marked[v]) dfs(G, v); } // check that id[] gives strong components assert check(G); }