/// <summary>
        /// Returns the trees (and scores) corresponding to the
        /// k-best derivations of the sentence.
        /// </summary>
        /// <remarks>
        /// Returns the trees (and scores) corresponding to the
        /// k-best derivations of the sentence.  This cannot be
        /// a Counter because frequently there will be multiple
        /// derivations which lead to the same parse tree.
        /// </remarks>
        /// <param name="k">The number of best parses to return</param>
        /// <returns>The list of trees with their scores (log prob).</returns>
        public virtual IList <ScoredObject <Tree> > GetKBestPCFGParses(int k)
        {
            if (pparser == null)
            {
                return(null);
            }
            IList <ScoredObject <Tree> > binaryTrees = pparser.GetKBestParses(k);

            if (binaryTrees == null)
            {
                return(null);
            }
            IList <ScoredObject <Tree> > trees = new List <ScoredObject <Tree> >(k);

            foreach (ScoredObject <Tree> p in binaryTrees)
            {
                Tree t = debinarizer.TransformTree(p.Object());
                t = subcategoryStripper.TransformTree(t);
                RestoreOriginalWords(t);
                trees.Add(new ScoredObject <Tree>(t, p.Score()));
            }
            return(trees);
        }
        /// <summary>Parse a Sentence.</summary>
        /// <remarks>
        /// Parse a Sentence.  It is assumed that when this is called, the pparser
        /// has already been called to parse the sentence.
        /// </remarks>
        /// <param name="words">The list of words to parse.</param>
        /// <returns>true iff it could be parsed</returns>
        public virtual bool Parse <_T0>(IList <_T0> words)
            where _T0 : IHasWord
        {
            nGoodTrees.Clear();
            int numParsesToConsider = numToFind * op.testOptions.fastFactoredCandidateMultiplier + op.testOptions.fastFactoredCandidateAddend;

            if (pparser.HasParse())
            {
                IList <ScoredObject <Tree> > pcfgBest   = pparser.GetKBestParses(numParsesToConsider);
                Beam <ScoredObject <Tree> >  goodParses = new Beam <ScoredObject <Tree> >(numToFind);
                foreach (ScoredObject <Tree> candidate in pcfgBest)
                {
                    if (Thread.Interrupted())
                    {
                        throw new RuntimeInterruptedException();
                    }
                    double depScore       = DepScoreTree(candidate.Object());
                    ScoredObject <Tree> x = new ScoredObject <Tree>(candidate.Object(), candidate.Score() + depScore);
                    goodParses.Add(x);
                }
                nGoodTrees = goodParses.AsSortedList();
            }
            return(!nGoodTrees.IsEmpty());
        }