public TargetAnalyzer(Node myStart, Node myEnd, UInt64 myMaxPathLength) { _Paths = new HashSet<List<Tuple<long, long>>>(); _Uninteresting = new HashSet<Tuple<long, long>>(); _PathsLeft = new HashSet<List<Tuple<long, long>>>(); _PathsRight = new HashSet<List<Tuple<long, long>>>(); _TempList = new List<Tuple<long, long>>(); _TempListLeft = new List<Tuple<long, long>>(); _TempListRight = new List<Tuple<long, long>>(); _Start = myStart; _End = myEnd; _MaxPathLength = Convert.ToInt16(myMaxPathLength); _MaxPartLengthLeft = 0; _MaxPartLengthRight = 0; }
private bool getPath(Node myCurrent) { bool currentIsInteresting = false; if (!_TempList.Contains(myCurrent.Key)) { if (!_Uninteresting.Contains<Tuple<long, long>>(myCurrent.Key)) { //add myCurrent to actual path _TempList.Add(myCurrent.Key); //set flag to mark that myCurrent is in actual path myCurrent.AlreadyInPath = true; //abort recursion when myCurrent is the root node if (_Start.Key.Equals(myCurrent.Key)) { currentIsInteresting = true; //duplicate list var temp = new List<Tuple<long, long>>(_TempList); //reverse because the path is calculated beginning at the target temp.Reverse(); //add completed path to result list _Paths.Add(temp); } //MaxPathLength is not reached else if (_TempList.Count < _MaxPathLength) { //for all parent nodes which are not already in actual path foreach (Node parent in myCurrent.Parents) { //if currentIsInteresting already true doen't set to false if (currentIsInteresting) getPath(parent); else currentIsInteresting = getPath(parent); } } else currentIsInteresting = true; if (_TempList.Count != 0) { //remove last node from actual path _TempList.Remove(_TempList.Last<Tuple<long, long>>()); //myCurrent isn't in actual path myCurrent.AlreadyInPath = false; } if (!currentIsInteresting) _Uninteresting.Add(myCurrent.Key); } } else currentIsInteresting = true; return currentIsInteresting; }
private bool VisitedByRightSide(Tuple<long, long> myTuple, ref Node myCurrentNodeLeft) { //get node Node temp = _VisitedNodesRight[myTuple]; //add parent new temp.addParent(myCurrentNodeLeft); //add as child myCurrentNodeLeft.addChild(temp); _VisitedNodesRight.Remove(temp.Key); _VisitedNodesRight.Add(temp.Key, temp); if (_VisitedNodesLeft.Remove(temp.Key)) { _VisitedNodesLeft.Add(temp.Key, temp); } if (_ShortestOnly && !_FindAll) { if ((_DepthLeft + _DepthRight + 1) > _MaxPathLength) { _ShortestPathLength = _MaxPathLength; } else { _ShortestPathLength = Convert.ToUInt64(_DepthLeft + _DepthRight + 1); } return true; } else if (_ShortestOnly && _FindAll) { _MaxDepthLeft = _DepthLeft; _ShortestPathLength = Convert.ToUInt64(_MaxDepthLeft + _MaxDepthRight); } return false; }
private void UpdateVisitedRight(Tuple<long, long> myTuple, ref Node myNode) { //set found children _VisitedNodesRight[myTuple].addChild(myNode); myNode.addParent(_VisitedNodesRight[myTuple]); }
private void UpdateVisitedLeft(Tuple<long, long> myTuple, ref Node myNode) { //set currentLeft as parent _VisitedNodesLeft[myTuple].addParent(myNode); //set currentNodeLeft as child myNode.addChild(_VisitedNodesLeft[myTuple]); }
/// <summary> /// Checks if the search should be aborted. /// </summary> /// <param name="myTuple">the Tuple of the current Vertex.</param> /// <param name="myCurrentNode">The current Node.</param> /// <param name="myNextNode">The next Node.</param> /// <param name="myVertex">The actual Vertex.</param> /// <returns>True, if the target is found AND the BFS could be finished. False, if the BFS should be continued.</returns> private bool TargetFoundCheckAbort(Tuple<long, long> myTuple, ref Node myCurrentNode, ref Node myNextNode, IVertex myVertex) { if (myTuple.Equals(_Target.Key)) { //set currentLeft as parent of _Target _Target.addParent(myCurrentNode); #region check if already visited if (_VisitedNodesLeft.ContainsKey(myTuple)) { //set currentLeft as parent _VisitedNodesLeft[myTuple].addParent(myCurrentNode); //set currentNodeLeft as child myCurrentNode.addChild(_VisitedNodesLeft[myTuple]); } else { //create a new node and set currentLeft = parent myNextNode = new Node(myTuple, myCurrentNode); //set currentNodeLeft as child of currentLeft myCurrentNode.addChild(myNextNode); //never seen before //mark the node as visited _VisitedNodesLeft.Add(myNextNode.Key, myNextNode); //and put node into the queue _QueueLeft.Enqueue(myVertex); } #endregion #region check how much parents are searched if (_ShortestOnly && !_FindAll) { if ((_DepthLeft + _DepthRight + 1) > _MaxPathLength) { _ShortestPathLength = _MaxPathLength; } else { _ShortestPathLength = Convert.ToUInt64(_DepthLeft + _DepthRight + 1); } return true; } //if find all shortest paths else if (_ShortestOnly && _FindAll) { //set maxDepth to actual depth _MaxDepthLeft = _DepthLeft; _MaxDepthRight = _DepthRight; if ((_DepthLeft + _DepthRight) > _MaxPathLength) { _ShortestPathLength = _MaxPathLength; } else { _ShortestPathLength = Convert.ToUInt64(_DepthLeft + _DepthRight); } } #endregion } return false; }
/// <summary> /// Fügt dem Knoten ein Parent hinzu, existiert dieser schon, werden die Parents und Children des existierenden aktualisiert. /// </summary> /// <param name="myParent">Parent welcher hinzugefügt werden soll.</param> /// <returns></returns> public bool addParent(Node myParent) { bool equal = false; foreach (var thisParent in _Parents) { //check if the node wich should be added IS already existing if (thisParent.Equals(myParent)) { //exists equal = true; break; } } //node is NOT already existing, add if (!equal) { return _Parents.Add(myParent); } return false; }
public TargetAnalyzer(Node myStart, Node myEnd, UInt64 myMaxPathLength, bool myShortestOnly, bool myFindAll) : this(myStart, myEnd, myMaxPathLength) { _ShortestOnly = myShortestOnly; _FindAll = myFindAll; }
private bool RootFoundCheckAbort(Tuple<long, long> myTuple, ref Node myCurrentNode, ref Node myNextNode, IVertex myVertex) { #region check if already visited //mark node as visited if (_VisitedNodesRight.ContainsKey(myTuple)) { //set found children _VisitedNodesRight[myTuple].addChild(myCurrentNode); myCurrentNode.addParent(_VisitedNodesRight[myTuple]); } else { //create a new node and set currentRight = child myNextNode = new Node(myTuple); myNextNode.addChild(myCurrentNode); //set currentNodeRight as parent of current Right myCurrentNode.addParent(myNextNode); //never seen before //mark the node as visited _VisitedNodesRight.Add(myNextNode.Key, myNextNode); //and look what comes on the next level of depth _QueueRight.Enqueue(myVertex); } #endregion check if already visited #region check how much paths are searched if (_ShortestOnly && !_FindAll) { if ((_DepthLeft + _DepthRight + 1) > _MaxPathLength) { _ShortestPathLength = _MaxPathLength; } else { _ShortestPathLength = Convert.ToUInt64(_DepthLeft + _DepthRight + 1); } return true; } //if find all shortest paths else if (_ShortestOnly && _FindAll) { //set maxDepth to actual depth _MaxDepthLeft = _DepthLeft; _MaxDepthRight = _DepthRight; if ((_DepthLeft + _DepthRight) > _MaxPathLength) { _ShortestPathLength = _MaxPathLength; } else { _ShortestPathLength = Convert.ToUInt64(_DepthLeft + _DepthRight); } } #endregion check how much paths are searched return false; }
private HashSet<List<Tuple<long, long>>> CheckNextVerticesOfRightSide(ref IVertex myCurrentVertexRight, ref Node myCurrentNodeRight) { //get all referenced ObjectUUIDs using the given Edge var rightVertices = GetIncomingVertices(myCurrentVertexRight); #region check right friends foreach (var nextRightVertex in rightVertices) { Node nextRightNode = null; Tuple<long, long> nextRight = new Tuple<long, long>(nextRightVertex.VertexTypeID, nextRightVertex.VertexID); #region if the child is the _Target if (_Root.Key.Equals(nextRight)) { if (RootFoundCheckAbort(nextRight, ref myCurrentNodeRight, ref nextRightNode, nextRightVertex)) return new TargetAnalyzer(_Root, _Target, _ShortestPathLength, _ShortestOnly, _FindAll).GetPaths(); } #endregion if the child is the _Target #region already visited from right side else if (_VisitedNodesLeft.ContainsKey(nextRight)) { if (VisitedByLeftSide(nextRight, ref myCurrentNodeRight)) return new TargetAnalyzer(_Root, _Target, _ShortestPathLength, _ShortestOnly, _FindAll).GetPaths(); } #endregion already visited from left side #region already visited else if (_VisitedNodesRight.ContainsKey(nextRight)) { UpdateVisitedRight(nextRight, ref myCurrentNodeRight); } #endregion already visited #region set as visited else { SetAsVisitedRight(nextRight, ref myCurrentNodeRight, ref nextRightNode, nextRightVertex); } #endregion set as visited } #endregion check right friends return null; }
private HashSet<List<Tuple<long, long>>> CheckNextVerticesOfLeftSide(ref IVertex myCurrentVertexLeft, ref Node myCurrentNodeLeft) { //get all referenced ObjectUUIDs using the given Edge var leftVertices = myCurrentVertexLeft.GetOutgoingEdge(_AttributeDefinition.ID).GetTargetVertices(); #region check left friends foreach (var nextLeftVertex in leftVertices) { Node nextLeftNode = null; Tuple<long, long> nextLeft = new Tuple<long, long>(nextLeftVertex.VertexTypeID, nextLeftVertex.VertexID); #region if the child is the _Target if (nextLeft.Equals(_Target.Key)) { if (TargetFoundCheckAbort(nextLeft, ref myCurrentNodeLeft, ref nextLeftNode, nextLeftVertex)) return new TargetAnalyzer(_Root, _Target, _ShortestPathLength, _ShortestOnly, _FindAll).GetPaths(); } #endregion #region already visited from right side else if (_VisitedNodesRight.ContainsKey(nextLeft)) { if (VisitedByRightSide(nextLeft, ref myCurrentNodeLeft)) return new TargetAnalyzer(_Root, _Target, _ShortestPathLength, _ShortestOnly, _FindAll).GetPaths(); } #endregion already visited from right side #region already visited else if (_VisitedNodesLeft.ContainsKey(nextLeft)) { UpdateVisitedLeft(nextLeft, ref myCurrentNodeLeft); } #endregion already visited #region set as visited else { SetAsVisitedLeft(nextLeft, ref myCurrentNodeLeft, ref nextLeftNode, nextLeftVertex); } #endregion set as visited } #endregion check left friends return null; }
/// <summary> /// Please look at the class documentation for detailed description how this algorithm works. /// </summary> /// <param name="myTypeAttribute">The Attribute representing the edge to follow (p.e. "Friends")</param> /// <param name="myVertexType">The type of the start node.</param> /// <param name="myStart">The start node</param> /// <param name="myEnd">The end node</param> /// <param name="shortestOnly">true, if only shortest path shall be found</param> /// <param name="findAll">if true and shortestOnly is true, all shortest paths will be found. /// If true, and shortest only is false, all paths will be searched</param> /// <param name="myMaxDepth">The maximum depth to search</param> /// <param name="myMaxPathLength">The maximum path length which shall be analyzed</param> /// <returns>A HashSet which contains all found paths. Every path is represented by a List of ObjectUUIDs</returns>m> public HashSet<List<Tuple<long, long>>> Find(IAttributeDefinition myTypeAttribute, IVertexType myVertexType, IVertex myStart, IVertex myEnd, bool shortestOnly, bool findAll, UInt64 myMaxDepth, UInt64 myMaxPathLength) { #region declarations //set current depth _DepthLeft = 1; _DepthRight = 1; //maximum depth _MaxDepthLeft = 0; _MaxDepthRight = 0; _MaxPathLength = myMaxPathLength; #region initialize maxDepths //if the maxDepth is greater then maxPathLength, then set maxDepth to maxPathLength if (myMaxDepth > _MaxPathLength) myMaxDepth = _MaxPathLength; else if (_MaxPathLength > myMaxDepth) _MaxPathLength = myMaxDepth; //set depth for left side _MaxDepthLeft = Convert.ToUInt64(myMaxDepth / 2 + 1); //if myMaxDepth is 1 _MaxDepthRight keeps 0, just one side is searching if (myMaxDepth > 1) //both sides have the same depth _MaxDepthRight = _MaxDepthLeft; //if myMaxDepth is even, one side has to search in a greater depth if ((myMaxDepth % 2) == 0) _MaxDepthRight = Convert.ToUInt64(_MaxDepthLeft - 1); #endregion //shortest path length _ShortestPathLength = 0; //_Target node, the _Target of the select _Target = new Node(myEnd.VertexTypeID, myEnd.VertexID); _Root = new Node(myStart.VertexTypeID, myStart.VertexID); //the attribute (edge) which is used for the search _AttributeDefinition = myTypeAttribute; //search the type on which the attribute is defined IVertexType current = myVertexType; List<IVertexType> tempList = new List<IVertexType>(); tempList.Add(current); bool foundDefinedType = false; while (current.HasParentType && !foundDefinedType) { if (current.ParentVertexType.HasAttribute(_AttributeDefinition.Name)) { foundDefinedType = true; } current = current.ParentVertexType; tempList.Add(current); } if (foundDefinedType) _Types = tempList; else _Types.Add(myVertexType); //dummy node to check in which level the BFS is _DummyLeft = null; _DummyRight = null; _FindAll = findAll; _ShortestOnly = shortestOnly; #endregion #region BidirectionalBFS //check if the EdgeType is ASetReferenceEdgeType #region initialize variables //enqueue start node to start from left side _QueueLeft.Enqueue(myStart); //enqueue _DummyLeft to analyze the depth of the left side _QueueLeft.Enqueue(_DummyLeft); //enqueue _Target node to start from right side _QueueRight.Enqueue(myEnd); //enqueue _DummyRight to analyze the depth of the right side _QueueRight.Enqueue(_DummyRight); //add _Root and _Target to visitedNodes _VisitedNodesLeft.Add(_Root.Key, _Root); _VisitedNodesRight.Add(_Target.Key, _Target); #endregion #region check if start has outgoing and _Target has incoming edge //check that the start node has the outgoing edge and the target has incoming vertices if (!myStart.HasOutgoingEdge(_AttributeDefinition.ID) && !HasIncomingVertices(myEnd)) { return null; } #endregion //if there is more than one object in the queue and the actual depth is less than MaxDepth while (((_QueueLeft.Count > 0) && (_QueueRight.Count > 0)) && ((_DepthLeft <= _MaxDepthLeft) || (_DepthRight <= _MaxDepthRight))) { #region both queues contain objects and both depths are not reached if (((_QueueLeft.Count > 0) && (_QueueRight.Count > 0)) && ((_DepthLeft <= _MaxDepthLeft) && (_DepthRight <= _MaxDepthRight))) { #region check if a level is completely searched if (LeftLevelCompleted()) continue; if (RightLevelCompleted()) continue; #endregion check if there is a dummyNode at the beginning of a queue #region get first nodes of the queues //hold the actual element of the queues Node currentNodeLeft; Node currentNodeRight; IVertex currentVertexLeft; IVertex currentVertexRight; Tuple<long, long> currentLeft; Tuple<long, long> currentRight; //get the first Object of the queue currentVertexLeft = _QueueLeft.Dequeue(); currentLeft = new Tuple<long, long>(currentVertexLeft.VertexTypeID, currentVertexLeft.VertexID); if (_VisitedNodesLeft.ContainsKey(currentLeft)) currentNodeLeft = _VisitedNodesLeft[currentLeft]; else currentNodeLeft = new Node(currentLeft); //get the first Object of the queue currentVertexRight = _QueueRight.Dequeue(); currentRight = new Tuple<long, long>(currentVertexRight.VertexTypeID, currentVertexRight.VertexID); if (_VisitedNodesRight.ContainsKey(currentRight)) currentNodeRight = _VisitedNodesRight[currentRight]; else currentNodeRight = new Node(currentRight); #endregion #region the edge and the backwardedge are existing if (currentVertexLeft.HasOutgoingEdge(_AttributeDefinition.ID) && HasIncomingVertices(currentVertexRight)) { //get all referenced ObjectUUIDs using the given Edge var leftVertices = currentVertexLeft.GetOutgoingEdge(_AttributeDefinition.ID).GetTargetVertices(); #region check left friends foreach (var nextLeftVertex in leftVertices) { Node nextLeftNode = null; Tuple<long, long> nextLeft = new Tuple<long, long>(nextLeftVertex.VertexTypeID, nextLeftVertex.VertexID); #region if the child is the _Target if (nextLeft.Equals(_Target.Key)) { if (TargetFoundCheckAbort(nextLeft, ref currentNodeLeft, ref nextLeftNode, nextLeftVertex)) return new TargetAnalyzer(_Root, _Target, _ShortestPathLength, _ShortestOnly, _FindAll).GetPaths(); } #endregion #region already visited else if (_VisitedNodesLeft.ContainsKey(nextLeft)) { UpdateVisitedLeft(nextLeft, ref currentNodeLeft); } #endregion already visited #region set as visited else { SetAsVisitedLeft(nextLeft, ref currentNodeLeft, ref nextLeftNode, nextLeftVertex); } #endregion set as visited } #endregion check left friends //get all referenced ObjectUUIDs using the given Edge var rightVertices = GetIncomingVertices(currentVertexRight); #region check right friends foreach (var nextRightVertex in rightVertices) { Node nextRightNode = null; Tuple<long, long> nextRight = new Tuple<long, long>(nextRightVertex.VertexTypeID, nextRightVertex.VertexID); #region if the child is the _Target if (_Root.Key.Equals(nextRight)) { if (RootFoundCheckAbort(nextRight, ref currentNodeRight, ref nextRightNode, nextRightVertex)) return new TargetAnalyzer(_Root, _Target, _ShortestPathLength, _ShortestOnly, _FindAll).GetPaths(); } #endregion if the child is the _Target #region already visited else if (_VisitedNodesRight.ContainsKey(nextRight)) { UpdateVisitedRight(nextRight, ref currentNodeRight); } #endregion already visited #region set as visited else { SetAsVisitedRight(nextRight, ref currentNodeRight, ref nextRightNode, nextRightVertex); } #endregion set as visited } #endregion check right friends #region build intersection of _VisitedNodesLeft and _VisitedNodesRight //marks if intersection nodes are existing bool foundIntersect = false; foreach (var node in _VisitedNodesLeft) { if (_VisitedNodesRight.ContainsKey(node.Key)) { //set nodes children and parents node.Value.addChildren(_VisitedNodesRight[node.Key].Children); node.Value.addParents(_VisitedNodesRight[node.Key].Parents); //set nodes children and parents _VisitedNodesRight[node.Key].addChildren(node.Value.Children); _VisitedNodesRight[node.Key].addParents(node.Value.Parents); _IntersectNodes.Add(_VisitedNodesRight[node.Key]); foundIntersect = true; } } #endregion build intersection of _VisitedNodesLeft and _VisitedNodesRight #region analyze intersection //if intersection nodes existing if (foundIntersect) { //only shortest path if (_ShortestOnly && !_FindAll) { if ((_DepthLeft + _DepthRight + 1) > _MaxPathLength) { _ShortestPathLength = _MaxPathLength; } else { _ShortestPathLength = Convert.ToUInt64(_DepthLeft + _DepthRight + 1); } //return new TargetAnalyzer(_Root, _Target, _ShortestPathLength, _ShortestOnly, _FindAll).GetPaths(); return new TargetAnalyzer(_Root, _Target, _ShortestPathLength, _ShortestOnly, _FindAll) .GetShortestPath(_IntersectNodes); } //if find all shortest paths else if (_ShortestOnly && _FindAll) { //set maxDepth to actual depth _MaxDepthLeft = _DepthLeft; _MaxDepthRight = _DepthRight; if ((_DepthLeft + _DepthRight + 1) > _MaxPathLength) { _ShortestPathLength = _MaxPathLength; } else if (_ShortestPathLength == 0) { _ShortestPathLength = Convert.ToUInt64(_DepthLeft + _DepthRight + 1); } } } #endregion analyze intersection } #endregion the edge and the backwardedge are existing #region only the edge exists else if (currentVertexLeft.HasOutgoingEdge(_AttributeDefinition.ID)) { var result = CheckNextVerticesOfLeftSide(ref currentVertexLeft, ref currentNodeLeft); if (result != null) return result; } #endregion only the edge exists #region only the backwardedge exists else if (HasIncomingVertices(currentVertexRight)) { var result = CheckNextVerticesOfRightSide(ref currentVertexRight, ref currentNodeRight); if (result != null) return result; } #endregion only the backwardedge exists } #endregion both queues contain objects and both depths are not reached #region only left queue contain objects else if ((_QueueLeft.Count > 0) && (_DepthLeft <= _MaxDepthLeft)) { #region check if first element of queue is a dummy if (LeftLevelCompleted()) continue; #endregion check if first element of queue is a dummy #region get first nodes of the queues //hold the actual element of the queues Node currentNodeLeft; IVertex currentVertexLeft; //get the first Object of the queue currentVertexLeft = _QueueLeft.Dequeue(); Tuple<long, long> currentLeft = new Tuple<long, long>(currentVertexLeft.VertexTypeID, currentVertexLeft.VertexID); if (_VisitedNodesLeft.ContainsKey(currentLeft)) continue; if (_VisitedNodesLeft.ContainsKey(currentLeft)) currentNodeLeft = _VisitedNodesLeft[currentLeft]; else currentNodeLeft = new Node(currentLeft); #endregion #region check next vertices if (currentVertexLeft.HasOutgoingEdge(_AttributeDefinition.ID)) { var result = CheckNextVerticesOfLeftSide(ref currentVertexLeft, ref currentNodeLeft); if (result != null) return result; } #endregion } #endregion only left queue contain objects #region only right queue contain objects else if ((_QueueRight.Count > 0) && (_DepthRight <= _MaxDepthRight)) { #region check if first element of the queue is a dummy if (RightLevelCompleted()) continue; #endregion check if first element of the queue is a dummy #region get first nodes of the queues //hold the actual element of the queues Node currentNodeRight; IVertex currentVertexRight; //get the first Object of the queue currentVertexRight = _QueueRight.Dequeue(); Tuple<long, long> currentRight = new Tuple<long, long>(currentVertexRight.VertexTypeID, currentVertexRight.VertexID); if (_VisitedNodesRight.ContainsKey(currentRight)) continue; if (_VisitedNodesRight.ContainsKey(currentRight)) currentNodeRight = _VisitedNodesRight[currentRight]; else currentNodeRight = new Node(currentRight); #endregion #region check next vertices if (HasIncomingVertices(currentVertexRight)) { var result = CheckNextVerticesOfRightSide(ref currentVertexRight, ref currentNodeRight); if (result != null) return result; } #endregion } #endregion only right queue contain objects #region abort loop else break; #endregion abort loop } #region nothing found if (_ShortestOnly && !_FindAll) return null; #endregion //get result paths #region start TargetAnalyzer if (_ShortestOnly && _FindAll) { if (_ShortestPathLength > _MaxPathLength) { _ShortestPathLength = _MaxPathLength; } return new TargetAnalyzer(_Root, _Target, _ShortestPathLength, _ShortestOnly, _FindAll).GetPaths(); } else { return new TargetAnalyzer(_Root, _Target, _MaxPathLength, _ShortestOnly, _FindAll).GetPaths(); } #endregion start TargetAnalyzer #endregion BidirectionalBFS }
public Node(Tuple<long, long> myKey, Node myParent) : this(myKey.Item1, myKey.Item2) { _Parents.Add(myParent); }
public Node(long myTypeID, long myVertexID, Node myParent) : this(myTypeID, myVertexID) { _Parents.Add(myParent); }
private void getShortestPathUpwards(Node myCurrent) { if (!_TempListRight.Contains(myCurrent.Key) && !foundRight) { //add myCurrent to actual path _TempListRight.Add(myCurrent.Key); //set flag to mark that myCurrent is in actual path myCurrent.AlreadyInPath = true; //abort recursion when myCurrent is the root node if (_Start.Key.Equals(myCurrent.Key) && _TempListRight.Count <= _MaxPartLengthRight) { //duplicate list var temp = new List<Tuple<long, long>>(_TempListRight); //actualize the max part length _MaxPartLengthRight = temp.Count; _PathsRight.Add(temp); if (_ShortestOnly) foundRight = true; } //MaxPathLength is not reached else if (_TempListRight.Count <= _MaxPartLengthRight) //for all parent nodes which are not already in actual path foreach (Node parent in myCurrent.Parents.Where(_ => !_.AlreadyInPath)) { getShortestPathUpwards(parent); } if (_TempListRight.Count != 0) { //remove last node from actual path _TempListRight.Remove(_TempListRight.Last<Tuple<long, long>>()); //myCurrent isn't in actual path myCurrent.AlreadyInPath = false; } } return; }
private void SetAsVisitedLeft(Tuple<long, long> myTuple, ref Node myCurrentNode, ref Node myNextNode, IVertex myVertex) { //create a new node myNextNode = new Node(myTuple, myCurrentNode); //set currentNode myCurrentNode.addChild(myNextNode); //never seen before //mark the node as visited //_VisitedNodesLeft.Add(currentNodeLeft.Key, currentNodeLeft); _VisitedNodesLeft.Add(myNextNode.Key, myNextNode); //and put node into the queue _QueueLeft.Enqueue(myVertex); }
private void SetAsVisitedRight(Tuple<long, long> myTuple, ref Node myCurrentNode, ref Node myNextNode, IVertex myVertex) { //create a new node and set currentRight = child myNextNode = new Node(myTuple); myNextNode.addChild(myCurrentNode); //set currentNodeRight as parent of current Right myCurrentNode.addParent(myNextNode); //never seen before //mark the node as visited _VisitedNodesRight.Add(myNextNode.Key, myNextNode); //and look what comes on the next level of depth _QueueRight.Enqueue(myVertex); }
/// <summary> /// Searches shortest, all shortest or all paths starting from "myStart" to "myEnd". /// </summary> /// <param name="myTypeAttribute">The Attribute representing the edge to follow (p.e. "Friends")</param> /// <param name="myTypeManager">The TypeManager for the Node type</param> /// <param name="myDBObjectCache">The Object Cache for faster object lookup</param> /// <param name="myStart">The start node</param> /// <param name="myEnd">The end node</param> /// <param name="shortestOnly">true, if only shortest path shall be found</param> /// <param name="findAll">if true and shortestOnly is true, all shortest paths will be found. if true, and shortest only is false, all paths will be searched</param> /// <param name="myMaxDepth">The maximum depth to search</param> /// <param name="myMaxPathLength">The maximum path length which shall be analyzed</param> /// <returns>A HashSet which contains all found paths. Every path is represented by a List of ObjectUUIDs</returns> public HashSet<List<Tuple<long, long>>> Find(IAttributeDefinition myTypeAttribute, IVertexType myVertexType, IVertex myStart, IVertex myEnd, bool shortestOnly, bool findAll, UInt64 myMaxDepth, UInt64 myMaxPathLength) { #region data //queue for BFS Queue<IVertex> queue = new Queue<IVertex>(); //Dictionary to store visited TreeNodes Dictionary<Tuple<long, long>, Node> visitedNodes = new Dictionary<Tuple<long, long>, Node>(); HashSet<Tuple<long, long>> visitedVertices = new HashSet<Tuple<long, long>>(); //current depth UInt64 depth = 1; //first node in path tree, the start of the select Node root = new Node(myStart.VertexTypeID, myStart.VertexID); //target node, the target of the select Node target = new Node(myEnd.VertexTypeID, myEnd.VertexID); //dummy node to check in which level the BFS is IVertex dummy = null; //if the maxDepth is greater then maxPathLength, then set maxDepth to maxPathLength if (myMaxDepth > myMaxPathLength) myMaxDepth = myMaxPathLength; else if (myMaxPathLength > myMaxDepth) myMaxPathLength = myMaxDepth; //enqueue first node to start the BFS queue.Enqueue(myStart); queue.Enqueue(dummy); //add root to visitedNodes visitedNodes.Add(root.Key, root); //search the type on which the attribute is defined IVertexType currentType = myVertexType; List<IVertexType> tempList = new List<IVertexType>(); tempList.Add(currentType); bool foundDefinedType = false; while (currentType.HasParentType && !foundDefinedType) { if (currentType.ParentVertexType.HasAttribute(myTypeAttribute.Name)) { foundDefinedType = true; } currentType = currentType.ParentVertexType; tempList.Add(currentType); } if (foundDefinedType) _Types = tempList; else _Types.Add(myVertexType); #endregion #region BFS //check that the start node has the outgoing edge and the target has incoming vertices if (!myStart.HasOutgoingEdge(myTypeAttribute.ID) && !HasIncomingVertices(myEnd, myTypeAttribute.ID)) { return null; } //if there is more than one object in the queue and the actual depth is less than MaxDepth while ((queue.Count > 0) && (depth < myMaxDepth)) { //get the first Object of the queue IVertex currentVertex = queue.Dequeue(); //dummy if (currentVertex == null || visitedVertices.Contains(new Tuple<long, long>(currentVertex.VertexTypeID, currentVertex.VertexID))) { continue; } Tuple<long, long> current = new Tuple<long, long>(currentVertex.VertexTypeID, currentVertex.VertexID); Node currentNode; visitedVertices.Add(current); if (visitedNodes.ContainsKey(current)) { currentNode = visitedNodes[current]; } else { currentNode = new Node(current); } if (currentVertex.HasOutgoingEdge(myTypeAttribute.ID)) { var vertices = currentVertex.GetOutgoingEdge(myTypeAttribute.ID).GetTargetVertices(); Node nextNode; Tuple<long, long> next; foreach (var vertex in vertices) { //create a new node and set currentNode = parent, nextNode = child next = new Tuple<long, long>(vertex.VertexTypeID, vertex.VertexID); nextNode = new Node(next, currentNode); currentNode.addChild(nextNode); //if the child is the target if (nextNode.Equals(target)) { //node points on the target target.Parents.Add(currentNode); //if shortestOnly == true we are finished here if (shortestOnly) { if (findAll) { if (Convert.ToUInt64(depth + 1) <= myMaxPathLength) { //continue searching the current depth if there are any other shortest paths myMaxDepth = Convert.ToUInt64(depth + 1); myMaxPathLength = Convert.ToUInt64(depth + 1); } } else { //got the shortest, finished return new TargetAnalyzer(root, target, myMaxPathLength, shortestOnly, findAll).GetPaths(); } } } else { //been there before if (visitedNodes.ContainsKey(nextNode.Key)) { //node has more then one parent visitedNodes[nextNode.Key].Parents.Add(currentNode); } //never seen before else { //mark the node as visited visitedNodes.Add(nextNode.Key, nextNode); } //and look what comes on the next level of depth queue.Enqueue(vertex); } } } //if a new depth is reached if (queue.First() == null) { //enqueue the dummy at the end of to mark the next depth queue.Enqueue(queue.Dequeue()); //one step deeper in the dungen depth++; } } #endregion //analyze paths return new TargetAnalyzer(root, target, myMaxPathLength, shortestOnly, findAll).GetPaths(); }
/// <summary> /// Fügt dem Knoten ein Child hinzu, existiert dieser schon, werden die Parents und Children des existierenden aktualisiert. /// </summary> /// <param name="myChild">Child welches hinzugefügt werden soll.</param> /// <returns></returns> public bool addChild(Node myChild) { bool equal = false; foreach (var thisChild in _Children) { //check if the node wich should be added IS already existing if (thisChild.Equals(myChild)) { equal = true; break; } } if (!equal) { return _Children.Add(myChild); } return false; }