예제 #1
0
        /// <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;
        }
예제 #2
0
        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);
        }
예제 #3
0
 /// <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);
     }
 }
예제 #4
0
 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);
        }
예제 #7
0
        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);
        }
예제 #8
0
        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();
        }
예제 #9
0
 /// <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;
 }
예제 #10
0
 /// <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;
 }
예제 #11
0
        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();
        }
예제 #13
0
        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);
        }
예제 #14
0
        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);
        }
예제 #15
0
 /// <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;
 }
예제 #16
0
        /// <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);
        }
예제 #17
0
        /// <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();
        }
예제 #19
0
        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);
        }
예제 #20
0
        /// <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);
        }
예제 #21
0
        /// <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);
        }
예제 #22
0
        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);
        }
예제 #23
0
        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);
                }
            }
        }
예제 #24
0
        /// <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 &lt;= 0 or E &lt; 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);
        }
예제 #25
0
 /// <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;
 }
예제 #26
0
        /// <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();
                }
            }
        }
예제 #28
0
        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);
            }
        }
예제 #29
0
        /// <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 &lt;= 0 or E &lt;= 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();
        }
예제 #31
0
 /// <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++;
 }
예제 #32
0
        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();
        }
예제 #33
0
 /// <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;
 }
예제 #34
0
        /// <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;
        }
예제 #35
0
        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;
        }
예제 #36
0
        /// <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);
        }
예제 #37
0
 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();
        }
예제 #39
0
        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);
        }