Пример #1
0
        private void ProcessNextEvaluationsForReverseChildTraversal(List <TreeEvalItem <TTreeNode> > nextEvals)
        {
            TreeEvalItem <TTreeNode> nextEval = null;

            if (m_traversalParameters.ChildTraversalStrategy == eTraversalStrategy.BreadthFirst)
            {
                nextEval = this.ProcessNextEvaluationsForRBFS(this.Target, new TreeNodePath(this.TargetPath), this.CurrentDepthFromOrigin);

                // If the processing gives us nothing, then it's time to move up to the next
                if (nextEval == null)
                {
                    var root = TreeTraversal <TTreeNode> .FindRoot(this.Target);

                    if (root != null)
                    {
                        nextEval = this.GetLastLeafAtDepth(root, new TreeNodePath(), this.TargetPath.Count - 1);
                    }
                }
            }
            else if (m_traversalParameters.ChildTraversalStrategy == eTraversalStrategy.DepthFirst)
            {
                var parent = m_traversalParameters.GetParentMethod(this.Target);
                if (parent == null)
                {
                    return;
                }

                // Iterate over the children, saving the current one into toVisit until we reach
                //  the target, that will give us the sibling before target
                TTreeNode toVisit = null;
                foreach (var child in m_traversalParameters.GetChildrenMethod(parent))
                {
                    if (child == this.Target)
                    {
                        break;
                    }

                    toVisit = child;
                }

                // If there are no siblings before target, then we need to move up to the parent
                if (toVisit == null)
                {
                    TreeNodePath parentPath = this.TargetPath.CopyAndRemoveEnd();
                    nextEval = new TreeEvalItem <TTreeNode>(parent, parentPath);
                }
                else
                {
                    // If there was an adjacent sibling, then we need to get the last leaf node of it, that is the next
                    //  evaluation. When that item gets evaluated, it will go through this same process which will lead
                    //  to any of it's siblings, andtheir last leaf, etc. etc. giving us a depth first search backwards
                    nextEval = this.GetLastLeaf(toVisit, this.CurrentDepthFromOrigin, new TreeNodePath(this.TargetPath));
                }
            }

            if (nextEval != null && this.IsUniqueInIteration(nextEval.Node))
            {
                nextEvals.Add(nextEval);
            }
        }
Пример #2
0
        private TreeEvalItem <TTreeNode> ProcessNextEvaluationsForRBFS(TTreeNode target, TreeNodePath path, int targetDepth)
        {
            if (target == null)
            {
                return(null);
            }

            var parent = m_traversalParameters.GetParentMethod(target);

            if (parent == null)
            {
                return(null);
            }


            TTreeNode nextClosestSibling      = null;
            int       nextClosestSiblingIndex = -1;
            int       childIndex = 0;

            foreach (var sibling in m_traversalParameters.GetChildrenMethod(parent))
            {
                if (sibling == target)
                {
                    break;
                }

                nextClosestSiblingIndex = childIndex++;
                nextClosestSibling      = sibling;
            }

            // No siblings, recurse to the parent/grandparent
            if (nextClosestSibling == null)
            {
                TreeEvalItem <TTreeNode> cousin = this.GetNextRBFSCousin(parent, path.CopyAndRemoveEnd(), targetDepth);
                if (cousin != null)
                {
                    return(cousin);
                }

                // Looks like end of this depth... time to go forward and back to the end
                return(this.GetLastLeafAtDepth(m_traversalParameters.Root, new TreeNodePath(), this.CurrentDepthFromOrigin - 1));
            }


            // There were some siblings, see if we can find our next target
            return(new TreeEvalItem <TTreeNode>(nextClosestSibling, path.CopyAndSwapEndForSibling(nextClosestSiblingIndex)));
        }
Пример #3
0
        private TreeEvalItem <TTreeNode> GetNextRBFSCousin(TTreeNode curr, TreeNodePath path, int targetDepth)
        {
            // If we've gotten into an error state, or if we're attempting to go past root
            if (curr == null || curr == m_traversalParameters.Root)
            {
                return(null);
            }

            // Iterate over all siblings and build a stack of siblings for us to evaluate (popping will give us sibling closest to curr, instead of parent's index[0])
            var parent = m_traversalParameters.GetParentMethod(curr);

            if (parent == null)
            {
                return(null);
            }

            var siblingStack = new Stack <IndexTrackedNode>();
            int siblingIndex = 0;

            foreach (var sibling in m_traversalParameters.GetChildrenMethod(parent))
            {
                if (sibling == curr)
                {
                    break;
                }

                siblingStack.Push(new IndexTrackedNode(siblingIndex++, sibling));
            }

            // Evaluate from closest to curr back to index zero, and call GetlastLeafAtDepth, if we find a cousin at the target depth
            //  then that is the next BFS item to search
            while (siblingStack.Count > 0)
            {
                var next = siblingStack.Pop();
                TreeEvalItem <TTreeNode> cousinLeaf = this.GetLastLeafAtDepth(next.Node, path.CopyAndSwapEndForSibling(next.Index), targetDepth);
                if (cousinLeaf != null)
                {
                    return(cousinLeaf);
                }
            }

            // If no cousin is found, than recurse upwards, this will be evaluting parent as curr
            return(this.GetNextRBFSCousin(parent, path.CopyAndRemoveEnd(), targetDepth));
        }
Пример #4
0
        /// <summary>
        /// Determines the next action in iteration that should be taken. This is called *after* a node has been sucessfully processed,
        /// and determines what the next phase of iteration should be in regards to the next node.
        /// </summary>
        /// <returns></returns>
        private eNextTraversalMove DetermineNextAction()
        {
            TreeEvalItem <TTreeNode> next = this.State.PeekNext();

            // If we are over our max number of allowed evaluations, or there is a termination path set, and we've already evaluted that, then it's time to quit.
            if (next == null ||
                (this.TraversalParameters.HasEvaluationCap && this.State.CurrentNumberOfEvaluations >= this.TraversalParameters.MaxNumberOfEvaluations) ||
                (this.TraversalParameters.TerminationNodePath != null && this.NodePath.Equals(this.TraversalParameters.TerminationNodePath)))
            {
                return(eNextTraversalMove.Quit);
            }

            // Make sure we're allowed to run our action
            if (!this.State.HasPendingEvalItems || (this.TraversalParameters.EnforcesLevelRestriction && !this.TraversalParameters.DepthLimits.Passes(next.DepthFromOrigin, true)))
            {
                return(eNextTraversalMove.PruneAndContinueSearching);
            }

            // Note: Evaluting type before predicate because some predicates are actually typed
            if (this.TraversalParameters.RequiresTypeMatching && !this.TraversalParameters.TypeMatching.Evaluate(next.Node.GetType()))
            {
                return(eNextTraversalMove.SkipAndContinueSearching);
            }

            if (this.TraversalParameters.HasPredicate && !this.TraversalParameters.Predicate(next.Node))
            {
                return(eNextTraversalMove.SkipAndContinueSearching);
            }

            if (this.TraversalParameters.PruneAfterFirstFind)
            {
                return(eNextTraversalMove.ProcessAndPrune);
            }

            return(eNextTraversalMove.Process);
        }