// Check list of paths are paths and that they are edge-disjoint. // Throws an exception, or if okay, returns a list of used (directed) edges. private static HashSet <Tuple <int, int> > CheckEDP(IGraphEdges <int> g, int startVertex, int endVertex, List <List <int> > paths, bool log) { if (log) { Console.Write("Edge-Disjoint paths: "); foreach (var path in paths) { foreach (var v in path) { Console.Write("{0} ", v); } Console.Write("\n"); } } // Check are paths foreach (var path in paths) { if (path[0] != startVertex || path[path.Count() - 1] != endVertex) { throw new Exception("Path does not start/end at correct vertex."); } for (int i = 0; i < path.Count() - 1; ++i) { if (!g.IsNeighbour(path[i], path[i + 1])) { throw new Exception("Path uses an edge which doesn't exist."); } } } // Check are disjoint var usedEdges = new HashSet <Tuple <int, int> >(); foreach (var path in paths) { for (int i = 0; i < path.Count() - 1; ++i) { var edge = Tuple.Create(path[i], path[i + 1]); if (!usedEdges.Add(edge)) { throw new Exception("Paths are not edge-disjoint!"); } } } return(usedEdges); }
public static HashSet <int> CheckVDP(IGraphEdges <int> g, List <List <int> > paths, bool log) { if (log) { Console.WriteLine("Found {0} vertex-disjoint path(s), which are: ", paths.Count()); foreach (var path in paths) { Console.Write("-- "); foreach (var v in path) { Console.Write("{0} ", v); } Console.Write("\n"); } } // Check disjoint! var usedVertices = new HashSet <int>(); foreach (var path in paths) { for (int i = 1; i < path.Count() - 1; ++i) { if (!usedVertices.Add(path[i])) { throw new Exception(String.Format("Vertex {0} used twice", path[i])); } } } // Check are paths! foreach (var path in paths) { for (int i = 0; i < path.Count() - 1; ++i) { if (!g.IsNeighbour(path[i], path[i + 1])) { throw new Exception(String.Format("Edge {0}--{1} not in graph!", path[i], path[i + 1])); } } } return(usedVertices); }
// Uses our search above to find a maximal family of vertex disjoint paths. // If the path finding algorithm, it builds a dictionary of accessible vertices and a viable edge // _to_ that vertex. Once we find the `to` vertex we work backwards to find a new path. // Because of the "non-local" rules of path-finding in the "residual" graph, this gets complicated! // However, the _only_ complication is that if our vertex search algorithm returns an edge // `parent`->`vertex` with `parent` on a path and `vertex` not, then _previously_ to this, // it must have returned an edge `prev`->`parent` which is the reverse of a used edge. public static List <List <T> > FindVertexDisjointPaths1 <T>(this IGraphEdges <T> graph, T startVertex, T to) { // Corner cases for `startVertex` and `to` var allPaths = new List <List <T> >(); if (Eq(startVertex, to)) { allPaths.Add(new List <T>()); allPaths[0].Add(to); return(allPaths); } if (graph.IsNeighbour(startVertex, to)) { allPaths.Add(new List <T>()); allPaths[0].Add(startVertex); allPaths[0].Add(to); return(allPaths); } // Apply FF algorithm return(graph.FindVertexDisjointPaths1(startVertex, to, new HashSet <Tuple <T, T> >())); }
// Returns a list of paths which form vertex-disjoint paths public static List <List <T> > FindVertexDisjointPaths <T>(this IGraphEdges <T> graph, T startVertex, T to) { var allPaths = new List <List <T> >(); if (Eq(startVertex, to)) { allPaths.Add(new List <T>()); allPaths[0].Add(to); return(allPaths); } if (graph.IsNeighbour(startVertex, to)) { allPaths.Add(new List <T>()); allPaths[0].Add(startVertex); allPaths[0].Add(to); return(allPaths); } var pathEdges = graph.VertexDisjointPaths(startVertex, to); return(ConvertEdgesToPaths(pathEdges, startVertex, to)); }