/// <summary> /// check that pre() and post() are consistent with pre(v) and post(v) /// </summary> /// <param name="g"></param> /// <returns></returns> public bool Check(Digraph g) { // check that post(v) is consistent with post() var r = 0; foreach (int v in Post()) { if (Post(v) != r) { Console.WriteLine("post(v) and post() inconsistent"); return false; } r++; } // check that pre(v) is consistent with pre() r = 0; foreach (int v in Pre()) { if (Pre(v) != r) { Console.WriteLine("pre(v) and pre() inconsistent"); return false; } r++; } return true; }
private Collections.Stack<Integer> _cycle; // directed cycle (or null if no such cycle) #endregion Fields #region Constructors /// <summary> /// Determines whether the digraph <tt>G</tt> has a directed cycle and, if so, /// finds such a cycle. /// </summary> /// <param name="g">g the digraph</param> public DirectedCycle(Digraph g) { _marked = new bool[g.V]; _onStack = new bool[g.V]; _edgeTo = new int[g.V]; for (var v = 0; v < g.V; v++) if (!_marked[v] && _cycle == null) Dfs(g, v); }
/// <summary> /// Computes the vertices in digraph <tt>G</tt> that are /// connected to any of the source vertices <tt>sources</tt>. /// </summary> /// <param name="g">g the graph</param> /// <param name="sources">sources the source vertices</param> public DirectedDFS(Digraph g, IEnumerable<Integer> sources) { _marked = new bool[g.V]; foreach (int v in sources) { if (!_marked[v]) Dfs(g, v); } }
private void Dfs(Digraph g, int v) { _count++; _marked[v] = true; foreach (int w in g.Adj(v)) { if (!_marked[w]) Dfs(g, w); } }
/// <summary> /// Computes the shortest path from any one of the source vertices in <tt>sources</tt> /// to every other vertex in graph <tt>G</tt>. /// </summary> /// <param name="g">g the digraph</param> /// <param name="sources">sources the source vertices</param> public BreadthFirstDirectedPaths(Digraph g, IEnumerable<Integer> sources) { _marked = new bool[g.V]; _distTo = new int[g.V]; _edgeTo = new int[g.V]; for (var v = 0; v < g.V; v++) _distTo[v] = INFINITY; Bfs(g, sources); }
private readonly bool[] _marked; // marked[v] = is there an s->v path? #endregion Fields #region Constructors /// <summary> /// Computes the shortest path from <tt>s</tt> and every other vertex in graph <tt>G</tt>. /// </summary> /// <param name="g">g the digraph</param> /// <param name="s">s the source vertex</param> public BreadthFirstDirectedPaths(Digraph g, int s) { _marked = new bool[g.V]; _distTo = new int[g.V]; _edgeTo = new int[g.V]; for (var v = 0; v < g.V; v++) _distTo[v] = INFINITY; Bfs(g, s); }
private int _preCounter; // counter or preorder numbering #endregion Fields #region Constructors /// <summary> /// Determines a depth-first order for the digraph <tt>G</tt>. /// </summary> /// <param name="g">g the digraph</param> public DepthFirstOrder(Digraph g) { _pre = new int[g.V]; _post = new int[g.V]; _postorder = new Collections.Queue<Integer>(); _preorder = new Collections.Queue<Integer>(); _marked = new bool[g.V]; for (var v = 0; v < g.V; v++) if (!_marked[v]) Dfs(g, v); }
public void Run() { Console.WriteLine("Choose file:"); // Prompt Console.WriteLine("1 - tinyDG.txt"); // Prompt Console.WriteLine("or quit"); // Prompt var fileNumber = Console.ReadLine(); string fileName; switch (fileNumber) { case "1": fileName = "tinyDG.txt"; break; case "quit": return; default: return; } var @in = new In($"Files\\Graphs\\{fileName}"); var lines = @in.ReadAllLines(); var lineIterator = 0; var v = 0; var e = 0; var edges = new List<EdgeD>(); foreach (var line in lines) { if (lineIterator == 0) { v = Convert.ToInt32(line); } if (lineIterator == 1) { e = Convert.ToInt32(line); } if (lineIterator > 1) { var lineSplitted = line.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries); var ve = Convert.ToInt32(lineSplitted[0]); var we = Convert.ToInt32(lineSplitted[1]); var edge = new EdgeD(ve, we); edges.Add(edge); } lineIterator++; } var digraph = new Digraph(v, e, edges); Console.WriteLine(digraph); Console.ReadLine(); }
/// <summary> /// Returns a complete binary tree digraph on <tt>V</tt> vertices. /// </summary> /// <param name="v">V the number of vertices in the binary tree</param> /// <returns>a digraph that is a complete binary tree on <tt>V</tt> vertices</returns> public static Digraph BinaryTree(int v) { var g = new Digraph(v); var vertices = new int[v]; for (var i = 0; i < v; i++) vertices[i] = i; StdRandom.Shuffle(vertices); for (var i = 1; i < v; i++) { g.AddEdge(vertices[i], vertices[(i - 1) / 2]); } return g; }
/// <summary> /// does the id[] array contain the strongly connected components? /// </summary> /// <param name="g"></param> /// <returns></returns> public bool Check(Digraph g) { var tc = new TransitiveClosure(g); for (var v = 0; v < g.V; v++) { for (var w = 0; w < g.V; w++) { if (StronglyConnected(v, w) != (tc.Reachable(v, w) && tc.Reachable(w, v))) return false; } } return true; }
private readonly int[] _rank; // rank[v] = position of vertex v in topological order #endregion Fields #region Constructors /// <summary> /// Determines whether the digraph <tt>G</tt> has a topological order and, if so, /// finds such a topological order. /// </summary> /// <param name="g">g the digraph</param> public Topological(Digraph g) { var finder = new DirectedCycle(g); if (!finder.HasCycle()) { var dfs = new DepthFirstOrder(g); _order = dfs.ReversePost(); _rank = new int[g.V]; var i = 0; foreach (int v in _order) _rank[v] = i++; } }
public void Run() { const int v = 50; const int e = 100; // Eulerian cycle var g1 = DigraphGenerator.EulerianCycle(v, e); DirectedEulerianCycle.UnitTest(g1, "Eulerian cycle"); Console.WriteLine("---------------------------------------------------------------"); // Eulerian path var g2 = DigraphGenerator.EulerianPath(v, e); DirectedEulerianCycle.UnitTest(g2, "Eulerian path"); Console.WriteLine("---------------------------------------------------------------"); // empty digraph var g3 = new Digraph(v); DirectedEulerianCycle.UnitTest(g3, "empty digraph"); Console.WriteLine("---------------------------------------------------------------"); // self loop var g4 = new Digraph(v); var v4 = StdRandom.Uniform(v); g4.AddEdge(v4, v4); DirectedEulerianCycle.UnitTest(g4, "single self loop"); Console.WriteLine("---------------------------------------------------------------"); // union of two disjoint cycles var h1 = DigraphGenerator.EulerianCycle(v / 2, e / 2); var h2 = DigraphGenerator.EulerianCycle(v - v / 2, e - e / 2); var perm = new int[v]; for (var i = 0; i < v; i++) perm[i] = i; StdRandom.Shuffle(perm); var g5 = new Digraph(v); for (var vi = 0; vi < h1.V; vi++) foreach (int w in h1.Adj(vi)) g5.AddEdge(perm[vi], perm[w]); for (var vi = 0; vi < h2.V; vi++) foreach (int w in h2.Adj(vi)) g5.AddEdge(perm[v / 2 + vi], perm[v / 2 + w]); DirectedEulerianCycle.UnitTest(g5, "Union of two disjoint cycles"); Console.WriteLine("---------------------------------------------------------------"); // random digraph var g6 = DigraphGenerator.Simple(v, e); DirectedEulerianCycle.UnitTest(g6, "simple digraph"); Console.WriteLine("---------------------------------------------------------------"); Console.ReadLine(); }
private int _pre; // preorder number counter #endregion Fields #region Constructors /// <summary> /// Computes the strong components of the digraph <tt>G</tt>. /// </summary> /// <param name="g">g the digraph</param> public TarjanSCC(Digraph g) { _marked = new bool[g.V]; _stack = new Stack<Integer>(); _id = new int[g.V]; _low = new int[g.V]; for (var v = 0; v < g.V; v++) { if (!_marked[v]) Dfs(g, v); } // check that id[] gives strong components //assert check(G); }
private readonly Collections.Stack<Integer> _path; // Eulerian path; null if no suh path #endregion Fields #region Constructors /// <summary> /// Computes an Eulerian path in the specified digraph, if one exists. /// </summary> /// <param name="g">g the digraph</param> public DirectedEulerianPath(Digraph g) { // find vertex from which to start potential Eulerian path: // a vertex v with outdegree(v) > indegree(v) if it exits; // otherwise a vertex with outdegree(v) > 0 var deficit = 0; var s = NonIsolatedVertex(g); for (var v = 0; v < g.V; v++) { if (g.Outdegree(v) > g.Indegree(v)) { deficit += (g.Outdegree(v) - g.Indegree(v)); s = v; } } // digraph can't have an Eulerian path // (this condition is needed) if (deficit > 1) return; // special case for digraph with zero edges (has a degenerate Eulerian path) if (s == -1) s = 0; // create local view of adjacency lists, to iterate one vertex at a time var adj = new IEnumerator<Integer>[g.V]; for (var v = 0; v < g.V; v++) adj[v] = g.Adj(v).GetEnumerator(); // greedily add to cycle, depth-first search style var stack = new Collections.Stack<Integer>(); stack.Push(s); _path = new Collections.Stack<Integer>(); while (!stack.IsEmpty()) { int v = stack.Pop(); while (adj[v].MoveNext()) { stack.Push(v); v = adj[v].Current; } // push vertex with no more available edges to path _path.Push(v); } // check if all edges have been used if (_path.Size() != g.E + 1) _path = null; //assert check(G); }
/// <summary> /// Returns a cycle digraph on <tt>V</tt> vertices. /// </summary> /// <param name="v">V the number of vertices in the cycle</param> /// <returns>a digraph that is a directed cycle on <tt>V</tt> vertices</returns> public static Digraph Cycle(int v) { var g = new Digraph(v); var vertices = new int[v]; for (var i = 0; i < v; i++) vertices[i] = i; StdRandom.Shuffle(vertices); for (var i = 0; i < v - 1; i++) { g.AddEdge(vertices[i], vertices[i + 1]); } g.AddEdge(vertices[v - 1], vertices[0]); return g; }
/// <summary> /// Returns a complete binary tree digraph on <tt>V</tt> vertices. /// </summary> /// <param name="v">V the number of vertices in the binary tree</param> /// <returns>a digraph that is a complete binary tree on <tt>V</tt> vertices</returns> public static Digraph BinaryTree(int v) { var g = new Digraph(v); var vertices = new int[v]; for (var i = 0; i < v; i++) { vertices[i] = i; } StdRandom.Shuffle(vertices); for (var i = 1; i < v; i++) { g.AddEdge(vertices[i], vertices[(i - 1) / 2]); } return(g); }
/// <summary> /// Returns a path digraph on <tt>V</tt> vertices. /// </summary> /// <param name="v">V the number of vertices in the path</param> /// <returns>a digraph that is a directed path on <tt>V</tt> vertices</returns> public static Digraph Path(int v) { var g = new Digraph(v); var vertices = new int[v]; for (var i = 0; i < v; i++) { vertices[i] = i; } StdRandom.Shuffle(vertices); for (var i = 0; i < v - 1; i++) { g.AddEdge(vertices[i], vertices[i + 1]); } return(g); }
public void Run() { const int v = 50; const int e = 100; // Eulerian cycle var g1 = DigraphGenerator.EulerianCycle(v, e); DirectedEulerianPath.UnitTest(g1, "Eulerian cycle"); Console.WriteLine("---------------------------------------------------------------"); // Eulerian path var g2 = DigraphGenerator.EulerianPath(v, e); DirectedEulerianPath.UnitTest(g2, "Eulerian path"); Console.WriteLine("---------------------------------------------------------------"); // add one random edge var g3 = new Digraph(g2); g3.AddEdge(StdRandom.Uniform(v), StdRandom.Uniform(v)); DirectedEulerianPath.UnitTest(g3, "one random edge added to Eulerian path"); Console.WriteLine("---------------------------------------------------------------"); // self loop var g4 = new Digraph(v); var v4 = StdRandom.Uniform(v); g4.AddEdge(v4, v4); DirectedEulerianPath.UnitTest(g4, "single self loop"); Console.WriteLine("---------------------------------------------------------------"); // single edge var g5 = new Digraph(v); g5.AddEdge(StdRandom.Uniform(v), StdRandom.Uniform(v)); DirectedEulerianPath.UnitTest(g5, "single edge"); Console.WriteLine("---------------------------------------------------------------"); // empty digraph var g6 = new Digraph(v); DirectedEulerianPath.UnitTest(g6, "empty digraph"); Console.WriteLine("---------------------------------------------------------------"); // random digraph var g7 = DigraphGenerator.Simple(v, e); DirectedEulerianPath.UnitTest(g7, "simple digraph"); Console.WriteLine("---------------------------------------------------------------"); Console.ReadLine(); }
private int _pre; // preorder number counter #endregion Fields #region Constructors /// <summary> /// Computes the strong components of the digraph <tt>G</tt>. /// </summary> /// <param name="g">g the digraph</param> public GabowSCC(Digraph g) { _marked = new bool[g.V]; _stack1 = new Stack<Integer>(); _stack2 = new Stack<Integer>(); _id = new int[g.V]; _preorder = new int[g.V]; for (var v = 0; v < g.V; v++) _id[v] = -1; for (var v = 0; v < g.V; v++) { if (!_marked[v]) Dfs(g, v); } // check that id[] gives strong components //assert check(G); }
/// <summary> /// Returns a random rooted-out DAG on <tt>V</tt> vertices and <tt>E</tt> edges. /// A rooted out-tree is a DAG in which every vertex is reachable from a /// single vertex. /// The DAG returned is not chosen uniformly at random among all such DAGs. /// </summary> /// <param name="v">V the number of vertices</param> /// <param name="e">E the number of edges</param> /// <returns>a random rooted-out DAG on <tt>V</tt> vertices and <tt>E</tt> edges</returns> public static Digraph RootedOutDag(int v, int e) { if (e > (long)v * (v - 1) / 2) { throw new ArgumentException("Too many edges"); } if (e < v - 1) { throw new ArgumentException("Too few edges"); } var g = new Digraph(v); var set = new SET <EdgeD>(); // fix a topological order var vertices = new int[v]; for (var 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 (var ve = 0; ve < v - 1; ve++) { var we = StdRandom.Uniform(ve + 1, v); var edge = new EdgeD(we, ve); set.Add(edge); g.AddEdge(vertices[we], vertices[ve]); } while (g.E < e) { var ve = StdRandom.Uniform(v); var we = StdRandom.Uniform(v); var edge = new EdgeD(we, ve); if ((ve < we) && !set.Contains(edge)) { set.Add(edge); g.AddEdge(vertices[we], vertices[ve]); } } return(g); }
/// <summary> /// Returns a random tournament digraph on <tt>V</tt> vertices. A tournament digraph /// is a DAG in which for every two vertices, there is one directed edge. /// A tournament is an oriented complete graph. /// </summary> /// <param name="v">V the number of vertices</param> /// <returns>a random tournament digraph on <tt>V</tt> vertices</returns> public static Digraph Tournament(int v) { var g = new Digraph(v); for (var ve = 0; ve < g.V; ve++) { for (var we = ve + 1; we < g.V; we++) { if (StdRandom.Bernoulli(0.5)) { g.AddEdge(ve, we); } else { g.AddEdge(we, ve); } } } return(g); }
private readonly int[] _rank; // rank[v] = order where vertex v appers in order #endregion Fields #region Constructors /// <summary> /// Determines whether the digraph <tt>G</tt> has a topological order and, if so, /// finds such a topological order. /// </summary> /// <param name="g">g the digraph</param> public TopologicalX(Digraph g) { // indegrees of remaining vertices var indegree = new int[g.V]; for (var v = 0; v < g.V; v++) { indegree[v] = g.Indegree(v); } // initialize _rank = new int[g.V]; _order = new Collections.Queue<Integer>(); var count = 0; // initialize queue to contain all vertices with indegree = 0 var queue = new Collections.Queue<Integer>(); for (var v = 0; v < g.V; v++) if (indegree[v] == 0) queue.Enqueue(v); for (var j = 0; !queue.IsEmpty(); j++) { int v = queue.Dequeue(); _order.Enqueue(v); _rank[v] = count++; foreach (int w in g.Adj(v)) { indegree[w]--; if (indegree[w] == 0) queue.Enqueue(w); } } // there is a directed cycle in subgraph of vertices with indegree >= 1. if (count != g.V) { _order = null; } //assert check(G); }
private readonly ST<string, Integer> _st; // string -> index #endregion Fields #region Constructors /// <summary> /// Initializes a digraph from a file using the specified delimiter. /// Each line in the file contains /// the name of a vertex, followed by a list of the names /// of the vertices adjacent to that vertex, separated by the delimiter. /// </summary> /// <param name="lines"></param> /// <param name="delimiter"></param> public SymbolDigraph(IList<string> lines, char delimiter) { _st = new ST<string, Integer>(); // First pass builds the index by reading strings to associate // distinct strings with an index foreach (var line in lines) { var a = line.Split(new[] { delimiter }, StringSplitOptions.RemoveEmptyEntries); foreach (var word in a) { if (!_st.Contains(word)) _st.Put(word, _st.Size()); } } // inverted index to get string keys in an aray _keys = new string[_st.Size()]; foreach (var name in _st.Keys()) { _keys[_st.Get(name)] = name; } // second pass builds the digraph by connecting first vertex on each // line to all others G = new Digraph(_st.Size()); foreach (var line in lines) { var a = line.Split(new[] { delimiter }, StringSplitOptions.RemoveEmptyEntries); int v = _st.Get(a[0]); for (var i = 1; i < a.Length; i++) { int w = _st.Get(a[i]); G.AddEdge(v, w); } } }
/// <summary> /// Returns an Eulerian path digraph on <tt>V</tt> vertices. /// </summary> /// <param name="v">V the number of vertices in the path</param> /// <param name="e">E the number of edges in the path</param> /// <returns>a digraph that is a directed Eulerian path on <tt>V</tt> vertices and <tt>E</tt> edges</returns> /// <exception cref="ArgumentException">if either V <= 0 or E < 0</exception> public static Digraph EulerianPath(int v, int e) { if (e < 0) { throw new ArgumentException("negative number of edges"); } if (v <= 0) { throw new ArgumentException("An Eulerian path must have at least one vertex"); } var g = new Digraph(v); var vertices = new int[e + 1]; for (var i = 0; i < e + 1; i++) { vertices[i] = StdRandom.Uniform(v); } for (var i = 0; i < e; i++) { g.AddEdge(vertices[i], vertices[i + 1]); } return(g); }
/// <summary> /// Returns a random simple DAG containing <tt>V</tt> vertices and <tt>E</tt> edges. /// Note: it is not uniformly selected at random among all such DAGs. /// </summary> /// <param name="v">V the number of vertices</param> /// <param name="e">E the number of vertices</param> /// <returns>a random simple DAG on <tt>V</tt> vertices, containing a total of <tt>E</tt> edges</returns> /// <exception cref="ArgumentException">if no such simple DAG exists</exception> public static Digraph Dag(int v, int e) { if (e > (long)v * (v - 1) / 2) throw new ArgumentException("Too many edges"); if (e < 0) throw new ArgumentException("Too few edges"); var g = new Digraph(v); var set = new SET<EdgeD>(); var vertices = new int[v]; for (var i = 0; i < v; i++) vertices[i] = i; StdRandom.Shuffle(vertices); while (g.E < e) { var ve = StdRandom.Uniform(v); var we = StdRandom.Uniform(v); var edge = new EdgeD(ve, we); if ((ve < we) && !set.Contains(edge)) { set.Add(edge); g.AddEdge(vertices[ve], vertices[we]); } } return g; }
/// <summary> /// 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. /// This implementations takes time propotional to V^2 (even if <tt>p</tt> is small). /// /// </summary> /// <param name="v">V the number of vertices</param> /// <param name="p">p the probability of choosing an edge</param> /// <returns>a random simple digraph on <tt>V</tt> vertices, with an edge between any two vertices with probability <tt>p</tt></returns> /// <exception cref="ArgumentException">if probability is not between 0 and 1</exception> public static Digraph Simple(int v, double p) { if (p < 0.0 || p > 1.0) { throw new ArgumentException("Probability must be between 0 and 1"); } var g = new Digraph(v); for (var i = 0; i < v; i++) { for (var j = 0; j < v; j++) { if (i != j) { if (StdRandom.Bernoulli(p)) { g.AddEdge(i, j); } } } } return(g); }
private readonly bool[] _marked; // marked[v] = is there an s->v path? #endregion Fields #region Constructors /// <summary> /// Computes the vertices reachable from the source vertex <tt>s</tt> in the digraph <tt>G</tt>. /// </summary> /// <param name="g">g the digraph</param> /// <param name="s">s the source vertex</param> public NonrecursiveDirectedDFS(Digraph g, int s) { _marked = new bool[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 var adj = new IEnumerator<Integer>[g.V]; for (var v = 0; v < g.V; v++) adj[v] = g.Adj(v).GetEnumerator(); // depth-first search using an explicit stack var stack = new Collections.Stack<Integer>(); _marked[s] = true; stack.Push(s); while (!stack.IsEmpty()) { int v = stack.Peek(); if (adj[v].MoveNext()) { int w = adj[v].Current; // 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(); } } }
private readonly string _regexp; // regular expression #endregion Fields #region Constructors /// <summary> /// Initializes the NFA from the specified regular expression. /// </summary> /// <param name="regexp">regexp the regular expression</param> public NFA(string regexp) { _regexp = regexp; _m = regexp.Length; var ops = new Stack<Integer>(); _g = new Digraph(_m + 1); for (var i = 0; i < _m; i++) { var lp = i; if (regexp[i] == '(' || regexp[i] == '|') ops.Push(i); else if (regexp[i] == ')') { int or = ops.Pop(); // 2-way or operator if (regexp[or] == '|') { lp = ops.Pop(); _g.AddEdge(lp, or + 1); _g.AddEdge(or, i); } else if (regexp[or] == '(') lp = or; //else assert false; } // closure operator (uses 1-character lookahead) if (i < _m - 1 && regexp[i + 1] == '*') { _g.AddEdge(lp, i + 1); _g.AddEdge(i + 1, lp); } if (regexp[i] == '(' || regexp[i] == '*' || regexp[i] == ')') _g.AddEdge(i, i + 1); } }
/// <summary> /// Returns an Eulerian cycle digraph on <tt>V</tt> vertices. /// </summary> /// <param name="v">V the number of vertices in the cycle</param> /// <param name="e">E the number of edges in the cycle</param> /// <returns>a digraph that is a directed Eulerian cycle on <tt>V</tt> vertices and <tt>E</tt> edges</returns> /// <exception cref="ArgumentException">if either V <= 0 or E <= 0</exception> public static Digraph EulerianCycle(int v, int e) { if (e <= 0) { throw new ArgumentException("An Eulerian cycle must have at least one edge"); } if (v <= 0) { throw new ArgumentException("An Eulerian cycle must have at least one vertex"); } var g = new Digraph(v); var vertices = new int[e]; for (var i = 0; i < e; i++) { vertices[i] = StdRandom.Uniform(v); } for (var i = 0; i < e - 1; i++) { g.AddEdge(vertices[i], vertices[i + 1]); } g.AddEdge(vertices[e - 1], vertices[0]); return(g); }
public void Run() { Console.WriteLine("Choose file:"); // Prompt Console.WriteLine("1 - tinyDG.txt"); // Prompt Console.WriteLine("or quit"); // Prompt var fileNumber = Console.ReadLine(); string fileName; switch (fileNumber) { case "1": fileName = "tinyDG.txt"; break; case "quit": return; default: return; } var @in = new In($"Files\\Graphs\\{fileName}"); var lines = @in.ReadAllLines(); var lineIterator = 0; var v = 0; var e = 0; var edges = new List<EdgeD>(); foreach (var line in lines) { if (lineIterator == 0) { v = Convert.ToInt32(line); } if (lineIterator == 1) { e = Convert.ToInt32(line); } if (lineIterator > 1) { var lineSplitted = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); var ve = Convert.ToInt32(lineSplitted[0]); var we = Convert.ToInt32(lineSplitted[1]); var edge = new EdgeD(ve, we); edges.Add(edge); } lineIterator++; } var digraph = new Digraph(v, e, edges); Console.WriteLine(digraph); Console.WriteLine("------------------------------------------------------"); var bag1 = new Core.Collections.Bag<Integer> { new Integer(1) }; var bag2 = new Core.Collections.Bag<Integer> { new Integer(2) }; var bag3 = new Core.Collections.Bag<Integer> { new Integer(6) }; var listSources = new List<Core.Collections.Bag<Integer>> { bag1, bag2, bag3 }; foreach (var sources in listSources) { foreach (var source in sources) { // multiple-source reachability var dfs = new NonrecursiveDirectedDFS(digraph, source.Value); // print out vertices reachable from sources for (var i = 0; i < digraph.V; i++) { if (dfs.Marked(i)) Console.Write($"{i} "); } Console.WriteLine(); } Console.WriteLine(); Console.WriteLine("---------------------------------------------------------"); } Console.ReadLine(); }
/// <summary> /// run DFS in digraph G from vertex v and compute preorder/postorder /// </summary> /// <param name="g"></param> /// <param name="v"></param> private void Dfs(Digraph g, int v) { _marked[v] = true; _pre[v] = _preCounter++; _preorder.Enqueue(v); foreach (int w in g.Adj(v)) { if (!_marked[w]) { Dfs(g, w); } } _postorder.Enqueue(v); _post[v] = _postCounter++; }
public static void UnitTest(Digraph g, string description) { Console.WriteLine(description); Console.WriteLine("-------------------------------------"); Console.Write(g); var euler = new DirectedEulerianPath(g); Console.Write("Eulerian path: "); if (euler.HasEulerianPath()) { foreach (int v in euler.Path()) { Console.Write($"{v} "); } Console.WriteLine(); } else { Console.WriteLine("none"); } Console.WriteLine(); }
/// <summary> /// returns any non-isolated vertex; -1 if no such vertex /// </summary> /// <param name="g"></param> /// <returns></returns> private static int NonIsolatedVertex(Digraph g) { for (var v = 0; v < g.V; v++) if (g.Outdegree(v) > 0) return v; return -1; }
/// <summary> /// Determines whether a digraph has an Eulerian path using necessary /// and sufficient conditions (without computing the path itself): /// - indegree(v) = outdegree(v) for every vertex, /// except one vertex v may have outdegree(v) = indegree(v) + 1 /// (and one vertex v may have indegree(v) = outdegree(v) + 1) /// - the graph is connected, when viewed as an undirected graph /// (ignoring isolated vertices) /// This method is solely for unit testing. /// </summary> /// <param name="g"></param> /// <returns></returns> private static bool HasEulerianPath(Digraph g) { if (g.E == 0) return true; // Condition 1: indegree(v) == outdegree(v) for every vertex, // except one vertex may have outdegree(v) = indegree(v) + 1 var deficit = 0; for (var v = 0; v < g.V; v++) if (g.Outdegree(v) > g.Indegree(v)) deficit += (g.Outdegree(v) - g.Indegree(v)); if (deficit > 1) return false; // Condition 2: graph is connected, ignoring isolated vertices var h = new Graph(g.V); for (var v = 0; v < g.V; v++) foreach (int w in g.Adj(v)) h.AddEdge(v, w); // check that all non-isolated vertices are connected var s = NonIsolatedVertex(g); var bfs = new BreadthFirstPaths(h, s); for (var v = 0; v < g.V; v++) if (h.Degree(v) > 0 && !bfs.HasPathTo(v)) return false; return true; }
public bool Check(Digraph g) { // internal consistency check if (HasEulerianPath() == (Path() == null)) return false; // hashEulerianPath() returns correct value if (HasEulerianPath() != HasEulerianPath(g)) return false; // nothing else to check if no Eulerian path if (_path == null) return true; // check that path() uses correct number of edges if (_path.Size() != g.E + 1) return false; // check that path() is a directed path in G // TODO return true; }
/// <summary> /// Returns a random simple digraph on <tt>V</tt> vertices, <tt>E</tt> /// edges and (at least) <tt>c</tt> strong components. The vertices are randomly /// assigned integer labels between <tt>0</tt> and <tt>c-1</tt> (corresponding to /// strong components). Then, a strong component is creates among the vertices /// with the same label. Next, random edges (either between two vertices with /// the same labels or from a vetex with a smaller label to a vertex with a /// larger label). The number of components will be equal to the number of /// distinct labels that are assigned to vertices. /// </summary> /// <param name="v">V the number of vertices</param> /// <param name="e">E the number of edges</param> /// <param name="c">c the (maximum) number of strong components</param> /// <returns>a random simple digraph on <tt>V</tt> vertices and <tt>E</tt> edges, with (at most) <tt>c</tt> strong components</returns> /// <exception cref="ArgumentException">if <tt>c</tt> is larger than <tt>V</tt></exception> public static Digraph Strong(int v, int e, int c) { if (c >= v || c <= 0) { throw new ArgumentException("Number of components must be between 1 and V"); } if (e <= 2 * (v - c)) { throw new ArgumentException("Number of edges must be at least 2(V-c)"); } if (e > (long)v * (v - 1) / 2) { throw new ArgumentException("Too many edges"); } // the digraph var g = new Digraph(v); // edges added to G (to avoid duplicate edges) var set = new SET <EdgeD>(); var label = new int[v]; for (var i = 0; i < v; i++) { label[i] = StdRandom.Uniform(c); } // make all vertices with label c a strong component by // combining a rooted in-tree and a rooted out-tree for (var i = 0; i < c; i++) { // how many vertices in component c var count = 0; for (var ii = 0; ii < g.V; ii++) { if (label[ii] == i) { count++; } } // if (count == 0) System.err.println("less than desired number of strong components"); var vertices = new int[count]; var j = 0; for (var jj = 0; jj < v; jj++) { if (label[jj] == i) { vertices[j++] = jj; } } StdRandom.Shuffle(vertices); // rooted-in tree with root = vertices[count-1] for (var ve = 0; ve < count - 1; ve++) { var we = StdRandom.Uniform(ve + 1, count); var edge = new EdgeD(we, ve); set.Add(edge); g.AddEdge(vertices[we], vertices[ve]); } // rooted-out tree with root = vertices[count-1] for (var ve = 0; ve < count - 1; ve++) { var we = StdRandom.Uniform(ve + 1, count); var edge = new EdgeD(ve, we); set.Add(edge); g.AddEdge(vertices[ve], vertices[we]); } } while (g.E < e) { var ve = StdRandom.Uniform(v); var we = StdRandom.Uniform(v); var edge = new EdgeD(ve, we); if (!set.Contains(edge) && ve != we && label[ve] <= label[we]) { set.Add(edge); g.AddEdge(ve, we); } } return(g); }
private void Dfs(Digraph g, int v) { _marked[v] = true; _low[v] = _pre++; var min = _low[v]; _stack.Push(v); foreach (int j in g.Adj(v)) { if (!_marked[j]) Dfs(g, j); if (_low[j] < min) min = _low[j]; } if (min < _low[v]) { _low[v] = min; return; } int w; do { w = _stack.Pop(); _id[w] = _count; _low[w] = g.V; } while (w != v); _count++; }
public void Run() { Console.WriteLine("Choose file:"); // Prompt Console.WriteLine("1 - tinyDG.txt"); // Prompt Console.WriteLine("2 - mediumDG.txt"); // Prompt Console.WriteLine("or quit"); // Prompt var fileNumber = Console.ReadLine(); string fileName; switch (fileNumber) { case "1": fileName = "tinyDG.txt"; break; case "2": fileName = "mediumDG.txt"; break; case "quit": return; default: return; } var @in = new In($"Files\\Graphs\\{fileName}"); var lines = @in.ReadAllLines(); var lineIterator = 0; var v = 0; var e = 0; var edges = new List<EdgeD>(); foreach (var line in lines) { if (lineIterator == 0) { v = Convert.ToInt32(line); } if (lineIterator == 1) { e = Convert.ToInt32(line); } if (lineIterator > 1) { var lineSplitted = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); var ve = Convert.ToInt32(lineSplitted[0]); var we = Convert.ToInt32(lineSplitted[1]); var edge = new EdgeD(ve, we); edges.Add(edge); } lineIterator++; } var digraph = new Digraph(v, e, edges); Console.WriteLine(digraph); Console.WriteLine("------------------------------------------------------"); const int s = 3; var bfs = new BreadthFirstDirectedPaths(digraph, s); for (var i = 0; i < digraph.V; i++) { if (bfs.HasPathTo(i)) { Console.Write($"{s} to {i} ({bfs.DistTo(i)}): "); foreach (int x in bfs.PathTo(i)) { if (x == s) Console.Write(x); else Console.Write("->" + x); } Console.WriteLine(); } else { Console.Write($"{s} to {i} (-): not connected{Environment.NewLine}"); } } Console.ReadLine(); }
private int _count; // number of vertices reachable from s /// <summary> /// Computes the vertices in digraph <tt>G</tt> that are /// reachable from the source vertex <tt>s</tt>. /// </summary> /// <param name="g">g the digraph</param> /// <param name="s">s the source vertex</param> public DirectedDFS(Digraph g, int s) { _marked = new bool[g.V]; Dfs(g, s); }