public static List <IVertex> Search(IGraph myGraph, IVertex mySource, IVertex myTarget, Func <IVertex, bool> myMatchingFunc = null) { // queue for bfs var leftQueue = new Queue <IVertex>(); var rightQueue = new Queue <IVertex>(); // store visited nodes in a hashset var visitedNodesLeft = new HashSet <IVertex>(); var visitedNodesRight = new HashSet <IVertex>(); var doMatching = myMatchingFunc != null; IVertex intersectionVertex = null; // init the queue with the source vertex mySource[PREDECESSOR_ATTRIBUTE_KEY] = null; myTarget[SUCCESSOR_ATTRIBUTE_KEY] = null; leftQueue.Enqueue(mySource); rightQueue.Enqueue(myTarget); visitedNodesLeft.Add(mySource); visitedNodesRight.Add(myTarget); IVertex currentLeftVertex = null; IVertex currentRightVertex = null; List <IVertex> result = null; while (leftQueue.Count > 0 && rightQueue.Count > 0) { currentLeftVertex = leftQueue.Dequeue(); currentRightVertex = rightQueue.Dequeue(); if (currentLeftVertex.Equals(myTarget)) { result = PathConcatenation.ConcatPath(myTarget, PREDECESSOR_ATTRIBUTE_KEY); break; } else if (currentRightVertex.Equals(mySource)) { result = PathConcatenation.ConcatPath(mySource, PREDECESSOR_ATTRIBUTE_KEY, false); break; } // check all children left foreach (var edge in currentLeftVertex.OutgoingEdges) { if (!visitedNodesLeft.Contains(edge.Target)) { edge.Target[PREDECESSOR_ATTRIBUTE_KEY] = currentLeftVertex; if (doMatching) { if (myMatchingFunc(edge.Target)) { leftQueue.Enqueue(edge.Target); edge.Target[MATCHING_ATTRIBUTE_KEY] = true; } else { edge.Target[MATCHING_ATTRIBUTE_KEY] = false; } } else { leftQueue.Enqueue(edge.Target); } visitedNodesLeft.Add(edge.Target); } } // check all parents right foreach (var edge in currentRightVertex.IncomingEdges) { if (!visitedNodesRight.Contains(edge.Source)) { edge.Source[SUCCESSOR_ATTRIBUTE_KEY] = currentRightVertex; if (doMatching) { if (myMatchingFunc(edge.Source)) { rightQueue.Enqueue(edge.Source); edge.Target[MATCHING_ATTRIBUTE_KEY] = true; } else { edge.Target[MATCHING_ATTRIBUTE_KEY] = false; } } else { rightQueue.Enqueue(edge.Source); } visitedNodesRight.Add(edge.Source); } } #region check intersect between visited nodes intersectionVertex = GetIntersectionVertex(visitedNodesLeft, visitedNodesRight, doMatching); if (intersectionVertex != null) { // got a connection between the searches List <IVertex> pathLeft = null; List <IVertex> pathRight = null; if (intersectionVertex[PREDECESSOR_ATTRIBUTE_KEY].Equals(currentLeftVertex)) { pathLeft = PathConcatenation.ConcatPath(intersectionVertex, PREDECESSOR_ATTRIBUTE_KEY); pathRight = PathConcatenation.ConcatPath((IVertex)intersectionVertex[SUCCESSOR_ATTRIBUTE_KEY], SUCCESSOR_ATTRIBUTE_KEY, false); } else { pathLeft = PathConcatenation.ConcatPath((IVertex)intersectionVertex[PREDECESSOR_ATTRIBUTE_KEY], PREDECESSOR_ATTRIBUTE_KEY); pathRight = PathConcatenation.ConcatPath(intersectionVertex, SUCCESSOR_ATTRIBUTE_KEY, false); } pathLeft.AddRange(pathRight); result = pathLeft; break; } #endregion } return(result); }
/// <summary> /// BFS for st-connectivity /// </summary> /// <param name="myGraph"></param> /// <param name="mySource"></param> /// <param name="myTarget"></param> /// <param name="myMatchingFunc"></param> /// <returns></returns> public static List <IVertex> Search(IGraph myGraph, IVertex mySource, IVertex myTarget, bool myInitGraph, Func <IVertex, bool> myMatchingFunc = null) { #region Init if (myInitGraph) { InitGraph(myGraph); } mySource[COLOR_ATTRIBUTE_KEY] = Color.RED; mySource[PREDECESSOR_ATTRIBUTE_KEY] = null; myTarget[COLOR_ATTRIBUTE_KEY] = Color.GREEN; myTarget[PREDECESSOR_ATTRIBUTE_KEY] = null; // bool if matching function has to be called var doMatching = myMatchingFunc != null; // used to indicate that the target node has been found var done = false; // use Concurrent Queue for parallel access var queue = new Queue <IVertex>(); IVertex u = null; #endregion #region BFS // enqueue the source vertex queue.Enqueue(mySource); while (queue.Count > 0 && !done) { u = queue.Dequeue(); // process neighbours in parallel //Parallel.ForEach<IEdge>(u.OutgoingEdges, outEdge => foreach (var outEdge in u.OutgoingEdges) { // neighbour node var v = outEdge.Target; // get the color of that neighbour var color = (Color)v[COLOR_ATTRIBUTE_KEY]; if (color == Color.WHITE) // not the target { // set as visited (Color.RED) v[COLOR_ATTRIBUTE_KEY] = Color.RED; // set the predecessor v[PREDECESSOR_ATTRIBUTE_KEY] = u; // and enqueue that node (if matching condition == true) if (doMatching) { // matches condition? if (myMatchingFunc(v)) { // matches, enqueue queue.Enqueue(v); } // do nothing } else { // no matching necessary queue.Enqueue(v); } } else if (color == Color.GREEN) // done { // finished done = true; // set the predecessor v[PREDECESSOR_ATTRIBUTE_KEY] = u; } } u[COLOR_ATTRIBUTE_KEY] = Color.RED; } #endregion if (done) { return(PathConcatenation.ConcatPath(myTarget, PREDECESSOR_ATTRIBUTE_KEY)); } return(null); }
/// <summary> /// BFS for st-connectivity /// </summary> /// <param name="myGraph"></param> /// <param name="mySource"></param> /// <param name="myTarget"></param> /// <param name="myMatchingFunc"></param> /// <returns></returns> public static List <IVertex> Search(IGraph myGraph, IVertex mySource, IVertex myTarget, bool myInitGraph, Func <IVertex, bool> myMatchingFunc = null) { #region Init if (myInitGraph) { InitGraph(myGraph); } mySource[COLOR_ATTRIBUTE_KEY] = Color.RED; mySource[PREDECESSOR_ATTRIBUTE_KEY] = null; myTarget[COLOR_ATTRIBUTE_KEY] = Color.GREEN; myTarget[PREDECESSOR_ATTRIBUTE_KEY] = null; var doMatching = myMatchingFunc != null; // used to indicate that the target node has been found var done = false; // use Concurrent Queue for parallel access var from = new List <IVertex>(); var to = new List <IVertex>(); var lockObj = new Object(); OrderablePartitioner <Tuple <int, int> > partitioner; #endregion #region BFS // enqueue the source vertex from.Add(mySource); while (from.Count > 0 && !done) { to = new List <IVertex>(); partitioner = Partitioner.Create(0, from.Count); // process queue in parallel Parallel.ForEach( // the values to be aggregated partitioner, // local initial partial result () => new List <IVertex>(), // loop body (range, loopState, partialResult) => { for (int i = range.Item1; i < range.Item2; i++) { IVertex u = from[i]; //Parallel.ForEach<IEdge>(u.OutgoingEdges, outEdge => foreach (var outEdge in u.OutgoingEdges) { // neighbour node var v = outEdge.Target; // get the color of that neighbour var color = (Color)v[COLOR_ATTRIBUTE_KEY]; if (color == Color.WHITE) // not the target { // set as visited (Color.RED) v[COLOR_ATTRIBUTE_KEY] = Color.RED; // set the predecessor v[PREDECESSOR_ATTRIBUTE_KEY] = u; // and enqueue that node (if matching condition == true) if (doMatching) { // matches condition? if (myMatchingFunc(v)) { // matches, add to local set partialResult.Add(v); } // do nothing } else { // no matching necessary, add to local set partialResult.Add(v); } } else if (color == Color.GREEN) // done { // finished done = true; // set the predecessor v[PREDECESSOR_ATTRIBUTE_KEY] = u; } //}); } u[COLOR_ATTRIBUTE_KEY] = Color.RED; } return(partialResult); }, //the final step of each local context (localPartialSet) => { lock (lockObj) { // sloooooow //to = to.Union<IVertex>(localPartialSet).ToList(); to.AddRange(localPartialSet); } }); from = to; } #endregion if (done) { return(PathConcatenation.ConcatPath(myTarget, PREDECESSOR_ATTRIBUTE_KEY)); } return(null); }