/// <summary> /// Computes the number of eulerian trail in the graph. /// </summary> /// <param name="g"></param> /// <returns>number of eulerian trails</returns> public static int ComputeEulerianPathCount(IVertexAndEdgeListGraph <TVertex, TEdge> g) { if (g == null) { throw new ArgumentNullException("g"); } if (g.EdgeCount < g.VertexCount) { return(0); } int odd = AlgoUtility.OddVertices(g).Count; if (odd == 0) { return(1); } else if (odd % 2 != 0) { return(0); } else { return(odd / 2); } }
/// <summary> /// Adds temporary edges to the graph to make all vertex even. /// </summary> /// <param name="g"></param> /// <returns></returns> public List <TEdge> AddTemporaryEdges(IEdgeFactory <TVertex, TEdge> edgeFactory) { // first gather odd edges. List <TVertex> oddVertices = AlgoUtility.OddVertices(this.VisitedGraph); // check that there are an even number of them if (oddVertices.Count % 2 != 0) { throw new Exception("number of odd vertices in not even!"); } // add temporary edges to create even edges: this.temporaryEdges = new List <TEdge>(); bool found, foundbe, foundadjacent; while (oddVertices.Count > 0) { TVertex u = oddVertices[0]; // find adjacent odd vertex. found = false; foundadjacent = false; foreach (var e in this.VisitedGraph.OutEdges(u)) { TVertex v = e.Target; if (!v.Equals(u) && oddVertices.Contains(v)) { foundadjacent = true; // check that v does not have an out-edge towards u foundbe = false; foreach (var be in this.VisitedGraph.OutEdges(v)) { if (be.Target.Equals(u)) { foundbe = true; break; } } if (foundbe) { continue; } // add temporary edge TEdge tempEdge = edgeFactory.CreateEdge(v, u); if (!this.VisitedGraph.AddEdge(tempEdge)) { throw new InvalidOperationException(); } // add to collection temporaryEdges.Add(tempEdge); // remove u,v from oddVertices oddVertices.Remove(u); oddVertices.Remove(v); // set u to null found = true; break; } } if (!foundadjacent) { // pick another vertex if (oddVertices.Count < 2) { throw new Exception("Eulerian trail failure"); } TVertex v = oddVertices[1]; TEdge tempEdge = edgeFactory.CreateEdge(u, v); if (!this.VisitedGraph.AddEdge(tempEdge)) { throw new InvalidOperationException(); } // add to collection temporaryEdges.Add(tempEdge); // remove u,v from oddVertices oddVertices.Remove(u); oddVertices.Remove(v); // set u to null found = true; } if (!found) { oddVertices.Remove(u); oddVertices.Add(u); } } return(this.temporaryEdges); }
protected override void InternalCompute() { var cancelManager = this.Services.CancelManager; this.matchedEdges.Clear(); AllVerticesGraphAugmentorAlgorithm <TVertex, TEdge> augmentor = null; ReversedEdgeAugmentorAlgorithm <TVertex, TEdge> reverser = null; try { if (cancelManager.IsCancelling) { return; } //augmenting graph augmentor = new AllVerticesGraphAugmentorAlgorithm <TVertex, TEdge>( this, this.VisitedGraph, this.VertexFactory, this.EdgeFactory); augmentor.Compute(); if (cancelManager.IsCancelling) { return; } // adding reverse edges reverser = new ReversedEdgeAugmentorAlgorithm <TVertex, TEdge>( this, this.VisitedGraph, this.EdgeFactory ); reverser.AddReversedEdges(); if (cancelManager.IsCancelling) { return; } // compute maxflow var flow = new EdmondsKarpMaximumFlowAlgorithm <TVertex, TEdge>( this, this.VisitedGraph, AlgoUtility.ConstantCapacities(this.VisitedGraph, 1), reverser.ReversedEdges ); flow.Compute(augmentor.SuperSource, augmentor.SuperSink); if (cancelManager.IsCancelling) { return; } foreach (var edge in this.VisitedGraph.Edges) { if (cancelManager.IsCancelling) { return; } if (flow.ResidualCapacities[edge] == 0) { this.matchedEdges.Add(edge); } } } finally { if (reverser != null && reverser.Augmented) { reverser.RemoveReversedEdges(); reverser = null; } if (augmentor != null && augmentor.Augmented) { augmentor.Rollback(); augmentor = null; } } }