public static bool RemoveEdgeFromGraph(UndirectedGraph <int, Edge <int> > originalGraph, Edge <int> edgeToRemove, out UndirectedGraph <int, Edge <int> > resultGraph) { var edgeComparer = new EdgeComparer(); var edges = new HashSet <Edge <int> >(originalGraph.Edges, edgeComparer); bool isRemoved = edges.Remove(edgeToRemove); if (!isRemoved) { resultGraph = originalGraph; return(false); } else { resultGraph = GetGraphFromEdges(edges); return(true); } }
private static List <Edge <int> > LiftingV3(List <Edge <int> > augmentingPath, List <Edge <int> > blossom, UndirectedGraph <int, Edge <int> > g, Edge <int> edgeBetweenTrees, int superVertex, List <Edge <int> > currentMatching) { var edgeComparer = new EdgeComparer(); var matchedVertices = GetAllVerticesForPath(currentMatching); var matchedEdges = new HashSet <Edge <int> >(currentMatching, new EdgeComparer()); GetPathEnds(augmentingPath, out int firstVertex, out int lastVertex); var superVertexEdges = new List <Edge <int> >(); foreach (var edge in augmentingPath) { if (edge.Source == superVertex || edge.Target == superVertex) { superVertexEdges.Add(edge); } } if (superVertexEdges.Count > 2) { throw new ArgumentException("There can be max 2 edges adjacent to superVertex in augmenting path"); } var superVertexUnmatchedEdge = superVertexEdges.FirstOrDefault(edge => !matchedEdges.Contains(edge)); var superVertexMatchedEdge = superVertexEdges.FirstOrDefault(edge => matchedEdges.Contains(edge)); if (superVertexEdges.Count == 2 && (superVertexMatchedEdge == null || superVertexUnmatchedEdge == null)) { throw new ArgumentException("Super vertex edges found incorrectly"); } if (superVertexEdges.Count == 1 && (superVertexMatchedEdge == null && superVertexUnmatchedEdge == null)) { throw new ArgumentException("Super vertex edges found incorrectly"); } var pathForMatchedEdge = new List <Edge <int> >(); var pathForUnmatchedEdge = new List <Edge <int> >(); var pathForBlossom = new List <Edge <int> >(); if (superVertexMatchedEdge != null) { int oppositeToSuperVertex1 = GetTargetVertex(superVertexMatchedEdge, superVertex); if (oppositeToSuperVertex1 != firstVertex && oppositeToSuperVertex1 != lastVertex) { var augmentingPathGraph1 = GetGraphFromEdges(augmentingPath); var edges = new HashSet <Edge <int> >(g.Edges, edgeComparer); if (!edges.Contains(superVertexMatchedEdge)) { throw new ArgumentException("Graph should contain matched Edge"); } bool wasRemoved = RemoveEdgeFromGraph(augmentingPathGraph1, superVertexMatchedEdge, out augmentingPathGraph1); //bool remove1 = augmentingPathGraph1.RemoveEdge(superVertexMatchedEdge); //bool remove2 = augmentingPathGraph1.RemoveEdge(new Edge<int>(superVertexMatchedEdge.Target, superVertexMatchedEdge.Source)); if (!wasRemoved) { throw new ArgumentException("Edge was not removed"); } bool pathFound = DFSSearch(firstVertex, oppositeToSuperVertex1, augmentingPathGraph1, out List <Edge <int> > path1); if (pathFound) { pathForMatchedEdge = path1; } else { pathFound = DFSSearch(oppositeToSuperVertex1, lastVertex, augmentingPathGraph1, out List <Edge <int> > path2); if (!pathFound) { throw new ArgumentException("Path should exist"); } pathForMatchedEdge = path2; } } pathForMatchedEdge.Add(superVertexMatchedEdge); } if (superVertexUnmatchedEdge != null) { int oppositeToSuperVertex2 = GetTargetVertex(superVertexUnmatchedEdge, superVertex); if (oppositeToSuperVertex2 != firstVertex && oppositeToSuperVertex2 != lastVertex) { var augmentingPathGraph2 = GetGraphFromEdges(augmentingPath); var edges = new HashSet <Edge <int> >(g.Edges, edgeComparer); //if (!edges.Contains(superVertexUnmatchedEdge)) // throw new ArgumentException("Graph should contain matched Edge"); bool wasRemoved = RemoveEdgeFromGraph(augmentingPathGraph2, superVertexUnmatchedEdge, out augmentingPathGraph2); //bool remove1 = augmentingPathGraph2.RemoveEdge(superVertexUnmatchedEdge); //bool remove2 = augmentingPathGraph2.RemoveEdge(new Edge<int>(superVertexUnmatchedEdge.Target, superVertexUnmatchedEdge.Source)); if (!wasRemoved) { throw new ArgumentException("Edge was not removed"); } bool pathFound = DFSSearch(firstVertex, oppositeToSuperVertex2, augmentingPathGraph2, out List <Edge <int> > path1); if (pathFound) { pathForUnmatchedEdge = path1; } else { pathFound = DFSSearch(oppositeToSuperVertex2, lastVertex, augmentingPathGraph2, out List <Edge <int> > path2); if (!pathFound) { throw new ArgumentException("Path should exist"); } pathForUnmatchedEdge = path2; } } //pathForUnmatchedEdge.Add(superVertexUnmatchedEdge); } Edge <int> firstEdgeInPath = null; var blossomVertices = GetAllVerticesForPath(blossom); int oppositeToSuperVertex = GetTargetVertex(superVertexUnmatchedEdge, superVertex); int firstVertexOnBlossom = -1; foreach (var edge in g.AdjacentEdges(oppositeToSuperVertex)) { int target = GetTargetVertex(edge, oppositeToSuperVertex); if (blossomVertices.Contains(target)) { firstEdgeInPath = edge; firstVertexOnBlossom = target; break; } } if (firstEdgeInPath == null || firstVertexOnBlossom < 0) { throw new ArgumentException("This path should be found"); } if (!matchedVertices.Contains(firstVertexOnBlossom)) { return(augmentingPath); } if (firstVertexOnBlossom == superVertex) { pathForBlossom = new List <Edge <int> > { firstEdgeInPath }; } else { var blossomGraph = GetGraphFromEdges(blossom); foreach (var edge in blossomGraph.AdjacentEdges(firstVertexOnBlossom)) { int target = GetTargetVertex(edge, firstVertexOnBlossom); if (!matchedVertices.Contains(target)) { bool edgeRemoved = blossomGraph.RemoveEdge(edge); if (!edgeRemoved) { throw new ArgumentException("Edge should be removed"); } break; } } bool pathFound = DFSSearch(firstVertexOnBlossom, superVertex, blossomGraph, out pathForBlossom); pathForBlossom.Add(firstEdgeInPath); } // Merge results for all the 3 paths var augmentingPathGraph = GetGraphFromEdges(pathForBlossom); if (superVertexMatchedEdge != null) { augmentingPathGraph.AddVerticesAndEdgeRange(pathForMatchedEdge); } if (superVertexUnmatchedEdge != null) { augmentingPathGraph.AddVerticesAndEdgeRange(pathForUnmatchedEdge); } if (!augmentingPathGraph.Vertices.Contains(firstVertex) || !augmentingPathGraph.Vertices.Contains(lastVertex)) { throw new ArgumentException("First and last vertex must be a part of the graph"); } var liftedAugmentingPathFound = DFSSearch(firstVertex, lastVertex, augmentingPathGraph, out List <Edge <int> > liftedAugmentingPath); if (!liftedAugmentingPathFound) { throw new ArgumentException("Lifted augmenting path not found"); } return(liftedAugmentingPath); }