Exemplo n.º 1
0
        /// <summary>
        /// Determines whether a graph has an Eulerian cycle using necessary
        /// and sufficient conditions (without computing the cycle itself):
        ///    - at least one EdgeW
        ///    - degree(v) is even for every vertex v
        ///    - the graph is connected (ignoring isolated vertices)
        /// </summary>
        /// <param name="g"></param>
        /// <returns></returns>
        private static bool HasEulerianCycle(Graph g)
        {
            // Condition 0: at least 1 EdgeW
            if (g.E == 0)
            {
                return(false);
            }

            // Condition 1: degree(v) is even for every vertex
            for (var v = 0; v < g.V; v++)
            {
                if (g.Degree(v) % 2 != 0)
                {
                    return(false);
                }
            }

            // Condition 2: graph is connected, ignoring isolated vertices
            var s   = NonIsolatedVertex(g);
            var bfs = new BreadthFirstPaths(g, s);

            for (var v = 0; v < g.V; v++)
            {
                if (g.Degree(v) > 0 && !bfs.HasPathTo(v))
                {
                    return(false);
                }
            }

            return(true);
        }
Exemplo n.º 2
0
 /// <summary>
 /// returns any non-isolated vertex; -1 if no such vertex
 /// </summary>
 /// <param name="g"></param>
 /// <returns></returns>
 private static int NonIsolatedVertex(Graph g)
 {
     for (var v = 0; v < g.V; v++)
     {
         if (g.Degree(v) > 0)
         {
             return(v);
         }
     }
     return(-1);
 }
Exemplo n.º 3
0
        /// <summary>
        /// Determines whether a graph has an Eulerian path using necessary
        /// and sufficient conditions (without computing the path itself):
        ///    - degree(v) is even for every vertex, except for possibly two
        ///    - the graph is connected (ignoring isolated vertices)
        /// This method is solely for unit testing.
        /// </summary>
        /// <param name="g"></param>
        /// <returns></returns>
        private static bool HasEulerianPath(Graph g)
        {
            if (g.E == 0)
            {
                return(true);
            }

            // Condition 1: degree(v) is even except for possibly two
            var oddDegreeVertices = 0;

            for (var v = 0; v < g.V; v++)
            {
                if (g.Degree(v) % 2 != 0)
                {
                    oddDegreeVertices++;
                }
            }
            if (oddDegreeVertices > 2)
            {
                return(false);
            }

            // Condition 2: graph is connected, ignoring isolated vertices
            var s   = NonIsolatedVertex(g);
            var bfs = new BreadthFirstPaths(g, s);

            for (var v = 0; v < g.V; v++)
            {
                if (g.Degree(v) > 0 && !bfs.HasPathTo(v))
                {
                    return(false);
                }
            }

            return(true);
        }
Exemplo n.º 4
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);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Determines whether a digraph has an Eulerian cycle using necessary
        /// and sufficient conditions (without computing the cycle itself):
        ///    - at least one edge
        ///    - indegree(v) = outdegree(v) for every vertex
        ///    - the graph is connected, when viewed as an undirected graph
        ///      (ignoring isolated vertices)
        /// </summary>
        /// <param name="g"></param>
        /// <returns></returns>
        private static bool HasEulerianCycle(Digraph g)
        {
            // Condition 0: at least 1 edge
            if (g.E == 0)
            {
                return(false);
            }

            // Condition 1: indegree(v) == outdegree(v) for every vertex
            for (var v = 0; v < g.V; v++)
            {
                if (g.Outdegree(v) != g.Indegree(v))
                {
                    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 conneted
            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);
        }
        /// <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;
        }
Exemplo n.º 7
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 graph, if one exists.
        /// </summary>
        /// <param name="g">g the graph</param>
        public EulerianPath(Graph g)
        {
            // find vertex from which to start potential Eulerian path:
            // a vertex v with odd degree(v) if it exits;
            // otherwise a vertex with degree(v) > 0
            var oddDegreeVertices = 0;
            var s = NonIsolatedVertex(g);
            for (var v = 0; v < g.V; v++)
            {
                if (g.Degree(v) % 2 != 0)
                {
                    oddDegreeVertices++;
                    s = v;
                }
            }

            // graph can't have an Eulerian path
            // (this condition is needed for correctness)
            if (oddDegreeVertices > 2) return;

            // special case for graph 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
            // the helper Edge data type is used to avoid exploring both copies of an edge v-w
            var adj = new Collections.Queue<EdgeW>[g.V];
            for (var v = 0; v < g.V; v++)
                adj[v] = new Collections.Queue<EdgeW>();

            for (var v = 0; v < g.V; v++)
            {
                var selfLoops = 0;
                foreach (int w in g.Adj(v))
                {
                    // careful with self loops
                    if (v == w)
                    {
                        if (selfLoops % 2 == 0)
                        {
                            var e = new EdgeW(v, w, 0);
                            adj[v].Enqueue(e);
                            adj[w].Enqueue(e);
                        }
                        selfLoops++;
                    }
                    else if (v < w)
                    {
                        var e = new EdgeW(v, w, 0);
                        adj[v].Enqueue(e);
                        adj[w].Enqueue(e);
                    }
                }
            }

            // initialize stack with any non-isolated vertex
            var stack = new Collections.Stack<Integer>();
            stack.Push(s);

            // greedily search through edges in iterative DFS style
            _path = new Collections.Stack<Integer>();
            while (!stack.IsEmpty())
            {
                int v = stack.Pop();
                while (!adj[v].IsEmpty())
                {
                    var edge = adj[v].Dequeue();
                    if (edge.IsUsed) continue;
                    edge.IsUsed = true;
                    stack.Push(v);
                    v = edge.Other(v);
                }
                // push vertex with no more leaving edges to path
                _path.Push(v);
            }

            // check if all edges are used
            if (_path.Size() != g.E + 1)
                _path = null;

            //assert certifySolution(G);
        }
Exemplo n.º 8
0
 // returns any non-isolated vertex; -1 if no such vertex
 private static int NonIsolatedVertex(Graph g)
 {
     for (var v = 0; v < g.V; v++)
         if (g.Degree(v) > 0)
             return v;
     return -1;
 }
Exemplo n.º 9
0
        /// <summary>
        /// Determines whether a graph has an Eulerian path using necessary
        /// and sufficient conditions (without computing the path itself):
        ///    - degree(v) is even for every vertex, except for possibly two
        ///    - the graph is connected (ignoring isolated vertices)
        /// This method is solely for unit testing.
        /// </summary>
        /// <param name="g"></param>
        /// <returns></returns>
        private static bool HasEulerianPath(Graph g)
        {
            if (g.E == 0) return true;

            // Condition 1: degree(v) is even except for possibly two
            var oddDegreeVertices = 0;
            for (var v = 0; v < g.V; v++)
                if (g.Degree(v) % 2 != 0)
                    oddDegreeVertices++;
            if (oddDegreeVertices > 2) return false;

            // Condition 2: graph is connected, ignoring isolated vertices
            var s = NonIsolatedVertex(g);
            var bfs = new BreadthFirstPaths(g, s);
            for (var v = 0; v < g.V; v++)
                if (g.Degree(v) > 0 && !bfs.HasPathTo(v))
                    return false;

            return true;
        }
Exemplo n.º 10
0
        private readonly Collections.Stack <Integer> _cycle = new Collections.Stack <Integer>();  // Eulerian cycle; null if no such cycle


        /// <summary>
        /// Computes an Eulerian cycle in the specified graph, if one exists.
        /// </summary>
        /// <param name="g">g the graph</param>
        public EulerianCycle(Graph g)
        {
            // must have at least one EdgeW
            if (g.E == 0)
            {
                return;
            }

            // necessary condition: all vertices have even degree
            // (this test is needed or it might find an Eulerian path instead of cycle)
            for (var v = 0; v < g.V; v++)
            {
                if (g.Degree(v) % 2 != 0)
                {
                    return;
                }
            }

            // create local view of adjacency lists, to iterate one vertex at a time
            // the helper EdgeW data type is used to avoid exploring both copies of an EdgeW v-w
            var adj = new Collections.Queue <EdgeW> [g.V];

            for (var v = 0; v < g.V; v++)
            {
                adj[v] = new Collections.Queue <EdgeW>();
            }

            for (var v = 0; v < g.V; v++)
            {
                var selfLoops = 0;
                foreach (int w in g.Adj(v))
                {
                    // careful with self loops
                    if (v == w)
                    {
                        if (selfLoops % 2 == 0)
                        {
                            var e = new EdgeW(v, w, 0);
                            adj[v].Enqueue(e);
                            adj[w].Enqueue(e);
                        }
                        selfLoops++;
                    }
                    else if (v < w)
                    {
                        var e = new EdgeW(v, w, 0);
                        adj[v].Enqueue(e);
                        adj[w].Enqueue(e);
                    }
                }
            }

            // initialize Collections.Stack with any non-isolated vertex
            var s     = NonIsolatedVertex(g);
            var stack = new Collections.Stack <Integer>();

            stack.Push(s);

            // greedily search through EdgeWs in iterative DFS style
            _cycle = new Collections.Stack <Integer>();
            while (!stack.IsEmpty())
            {
                int v = stack.Pop();
                while (!adj[v].IsEmpty())
                {
                    var edgeW = adj[v].Dequeue();
                    if (edgeW.IsUsed)
                    {
                        continue;
                    }
                    edgeW.IsUsed = true;
                    stack.Push(v);
                    v = edgeW.Other(v);
                }
                // push vertex with no more leaving EdgeWs to cycle
                _cycle.Push(v);
            }

            // check if all EdgeWs are used
            if (_cycle.Size() != g.E + 1)
            {
                _cycle = null;
            }

            //assert certifySolution(G);
        }
Exemplo n.º 11
0
        private readonly Collections.Stack <Integer> _path;   // Eulerian path; null if no suh path


        /// <summary>
        /// Computes an Eulerian path in the specified graph, if one exists.
        /// </summary>
        /// <param name="g">g the graph</param>
        public EulerianPath(Graph g)
        {
            // find vertex from which to start potential Eulerian path:
            // a vertex v with odd degree(v) if it exits;
            // otherwise a vertex with degree(v) > 0
            var oddDegreeVertices = 0;
            var s = NonIsolatedVertex(g);

            for (var v = 0; v < g.V; v++)
            {
                if (g.Degree(v) % 2 != 0)
                {
                    oddDegreeVertices++;
                    s = v;
                }
            }

            // graph can't have an Eulerian path
            // (this condition is needed for correctness)
            if (oddDegreeVertices > 2)
            {
                return;
            }

            // special case for graph 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
            // the helper Edge data type is used to avoid exploring both copies of an edge v-w
            var adj = new Collections.Queue <EdgeW> [g.V];

            for (var v = 0; v < g.V; v++)
            {
                adj[v] = new Collections.Queue <EdgeW>();
            }

            for (var v = 0; v < g.V; v++)
            {
                var selfLoops = 0;
                foreach (int w in g.Adj(v))
                {
                    // careful with self loops
                    if (v == w)
                    {
                        if (selfLoops % 2 == 0)
                        {
                            var e = new EdgeW(v, w, 0);
                            adj[v].Enqueue(e);
                            adj[w].Enqueue(e);
                        }
                        selfLoops++;
                    }
                    else if (v < w)
                    {
                        var e = new EdgeW(v, w, 0);
                        adj[v].Enqueue(e);
                        adj[w].Enqueue(e);
                    }
                }
            }

            // initialize stack with any non-isolated vertex
            var stack = new Collections.Stack <Integer>();

            stack.Push(s);

            // greedily search through edges in iterative DFS style
            _path = new Collections.Stack <Integer>();
            while (!stack.IsEmpty())
            {
                int v = stack.Pop();
                while (!adj[v].IsEmpty())
                {
                    var edge = adj[v].Dequeue();
                    if (edge.IsUsed)
                    {
                        continue;
                    }
                    edge.IsUsed = true;
                    stack.Push(v);
                    v = edge.Other(v);
                }
                // push vertex with no more leaving edges to path
                _path.Push(v);
            }

            // check if all edges are used
            if (_path.Size() != g.E + 1)
            {
                _path = null;
            }

            //assert certifySolution(G);
        }
Exemplo n.º 12
0
        private readonly Collections.Stack<Integer> _cycle = new Collections.Stack<Integer>(); // Eulerian cycle; null if no such cycle

        #endregion Fields

        #region Constructors

        /// <summary>
        /// Computes an Eulerian cycle in the specified graph, if one exists.
        /// </summary>
        /// <param name="g">g the graph</param>
        public EulerianCycle(Graph g)
        {
            // must have at least one EdgeW
            if (g.E == 0) return;

            // necessary condition: all vertices have even degree
            // (this test is needed or it might find an Eulerian path instead of cycle)
            for (var v = 0; v < g.V; v++)
                if (g.Degree(v) % 2 != 0)
                    return;

            // create local view of adjacency lists, to iterate one vertex at a time
            // the helper EdgeW data type is used to avoid exploring both copies of an EdgeW v-w
            var adj = new Collections.Queue<EdgeW>[g.V];
            for (var v = 0; v < g.V; v++)
                adj[v] = new Collections.Queue<EdgeW>();

            for (var v = 0; v < g.V; v++)
            {
                var selfLoops = 0;
                foreach (int w in g.Adj(v))
                {
                    // careful with self loops
                    if (v == w)
                    {
                        if (selfLoops % 2 == 0)
                        {
                            var e = new EdgeW(v, w, 0);
                            adj[v].Enqueue(e);
                            adj[w].Enqueue(e);
                        }
                        selfLoops++;
                    }
                    else if (v < w)
                    {
                        var e = new EdgeW(v, w, 0);
                        adj[v].Enqueue(e);
                        adj[w].Enqueue(e);
                    }
                }
            }

            // initialize Collections.Stack with any non-isolated vertex
            var s = NonIsolatedVertex(g);
            var stack = new Collections.Stack<Integer>();
            stack.Push(s);

            // greedily search through EdgeWs in iterative DFS style
            _cycle = new Collections.Stack<Integer>();
            while (!stack.IsEmpty())
            {
                int v = stack.Pop();
                while (!adj[v].IsEmpty())
                {
                    var edgeW = adj[v].Dequeue();
                    if (edgeW.IsUsed) continue;
                    edgeW.IsUsed = true;
                    stack.Push(v);
                    v = edgeW.Other(v);
                }
                // push vertex with no more leaving EdgeWs to cycle
                _cycle.Push(v);
            }

            // check if all EdgeWs are used
            if (_cycle.Size() != g.E + 1)
                _cycle = null;

            //assert certifySolution(G);
        }
Exemplo n.º 13
0
        /// <summary>
        /// Determines whether a graph has an Eulerian cycle using necessary
        /// and sufficient conditions (without computing the cycle itself):
        ///    - at least one EdgeW
        ///    - degree(v) is even for every vertex v
        ///    - the graph is connected (ignoring isolated vertices)
        /// </summary>
        /// <param name="g"></param>
        /// <returns></returns>
        private static bool HasEulerianCycle(Graph g)
        {
            // Condition 0: at least 1 EdgeW
            if (g.E == 0) return false;

            // Condition 1: degree(v) is even for every vertex
            for (var v = 0; v < g.V; v++)
                if (g.Degree(v) % 2 != 0)
                    return false;

            // Condition 2: graph is connected, ignoring isolated vertices
            var s = NonIsolatedVertex(g);
            var bfs = new BreadthFirstPaths(g, s);
            for (var v = 0; v < g.V; v++)
                if (g.Degree(v) > 0 && !bfs.HasPathTo(v))
                    return false;

            return true;
        }