/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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; }
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); }
// 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; }
/// <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; }
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); }
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); }
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); }
/// <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; }