public IInferenceResult Ask(FOLKnowledgeBase kb, ISentence aQuery)
        {
            //
            // Get the background knowledge - are assuming this is satisfiable
            // as using Set of Support strategy.
            ISet <Clause> bgClauses = new HashedSet <Clause>(kb.GetAllClauses());

            bgClauses.ExceptWith(SubsumptionElimination.FindSubsumedClauses(bgClauses));
            IList <Chain> background = CreateChainsFromClauses(bgClauses);

            // Collect the information necessary for constructing
            // an answer (supports use of answer literals).
            var ansHandler = new AnswerHandler(kb, aQuery, this.MaxQueryTime);

            var ifps = new IndexedFarParents(ansHandler
                                             .GetSetOfSupport(), background);

            // Iterative deepening to be used
            for (int maxDepth = 1; maxDepth < int.MaxValue; maxDepth++)
            {
                // Track the depth actually reached
                ansHandler.ResetMaxDepthReached();

                if (null != tracer)
                {
                    tracer.Reset();
                }

                foreach (Chain nearParent in ansHandler.GetSetOfSupport())
                {
                    this.RecursiveDls(maxDepth, 0, nearParent, ifps, ansHandler);
                    if (ansHandler.IsComplete())
                    {
                        return(ansHandler);
                    }
                }
                // This means the search tree
                // has bottomed out (i.e. finite).
                // Return what I know based on exploring everything.
                if (ansHandler.GetMaxDepthReached() < maxDepth)
                {
                    return(ansHandler);
                }
            }

            return(ansHandler);
        }
        // Recursive Depth Limited Search
        private void RecursiveDls(int maxDepth, int currentDepth, Chain nearParent,
                                  IndexedFarParents indexedFarParents, AnswerHandler ansHandler)
        {
            // Keep track of the maximum depth reached.
            ansHandler.UpdateMaxDepthReached(currentDepth);

            if (currentDepth == maxDepth)
            {
                return;
            }

            int noCandidateFarParents = indexedFarParents
                                        .GetNumberCandidateFarParents(nearParent);

            if (null != tracer)
            {
                tracer.Increment(currentDepth, noCandidateFarParents);
            }
            indexedFarParents.StandardizeApart(nearParent);
            for (int farParentIdx = 0; farParentIdx < noCandidateFarParents; farParentIdx++)
            {
                // If have a complete answer, don't keep
                // checking candidate far parents
                if (ansHandler.IsComplete())
                {
                    break;
                }

                // Reduction
                Chain nextNearParent = indexedFarParents.AttemptReduction(
                    nearParent, farParentIdx);

                if (null == nextNearParent)
                {
                    // Unable to remove the head via reduction
                    continue;
                }

                // Handle Canceling and Dropping
                bool cancelled;
                bool dropped;
                do
                {
                    cancelled = false;
                    Chain nextParent;
                    while (nextNearParent != (nextParent = this.TryCancellation(nextNearParent)))
                    {
                        nextNearParent = nextParent;
                        cancelled      = true;
                    }

                    dropped = false;
                    while (nextNearParent != (nextParent = this.TryDropping(nextNearParent)))
                    {
                        nextNearParent = nextParent;
                        dropped        = true;
                    }
                } while (dropped || cancelled);

                // Check if have answer before
                // going to the next level
                if (!ansHandler.IsAnswer(nextNearParent))
                {
                    // Keep track of the current # of
                    // far parents that are possible for the next near parent.
                    int noNextFarParents = indexedFarParents
                                           .GetNumberFarParents(nextNearParent);
                    // Add to indexed far parents
                    nextNearParent = indexedFarParents.AddToIndex(nextNearParent);

                    // Check the next level
                    this.RecursiveDls(maxDepth, currentDepth + 1, nextNearParent,
                                      indexedFarParents, ansHandler);

                    // Reset the number of far parents possible
                    // when recursing back up.
                    indexedFarParents.ResetNumberFarParentsTo(nextNearParent,
                                                              noNextFarParents);
                }
            }
        }