/// <summary> /// Returns the specified number of parses or fewer for the specified tokens. /// </summary> /// <param name="tokens">A parse containing the tokens with a single parent node.</param> /// <param name="numParses">The number of parses desired.</param> /// <returns>The specified number of parses for the specified tokens.</returns> /// <remarks> /// The nodes within the returned parses are shared with other parses and therefore their /// parent node references will not be consistent with their child node reference. /// <see cref="SharpNL.Parser.Parse.Parent"/> can be used to make the parents consistent with a /// particular parse, but subsequent calls to this property can invalidate the results of earlier /// calls. /// </remarks> public Parse[] Parse(Parse tokens, int numParses) { if (createDerivationString) { tokens.Derivation = new StringBuilder(); } odh.Clear(); ndh.Clear(); completeParses.Clear(); var derivationStage = 0; //derivation length var maxDerivationLength = 2 * tokens.ChildCount + 3; odh.Add(tokens); Parse guess = null; double minComplete = 2; double bestComplete = -100000; //approximating -infinity/0 in ln domain while (odh.Size() > 0 && (completeParses.Size() < M || odh.First().Probability < minComplete) && derivationStage < maxDerivationLength) { ndh = new ListHeap <Parse>(K); var derivationRank = 0; // foreach derivation for (var pi = odh.GetEnumerator(); pi.MoveNext() && derivationRank < K; derivationRank++) { var tp = pi.Current; //TODO: Need to look at this for K-best parsing cases /* * if (tp.getProb() < bestComplete) { //this parse and the ones which follow will never win, stop advancing. * break; * } */ if (guess == null && derivationStage == 2) { guess = tp; } #if DEBUG if (debugOn) { Console.Out.WriteLine(derivationStage + " " + derivationRank + " " + tp.Probability); Console.Out.WriteLine(tp.ToString()); Console.Out.WriteLine(); } #endif Parse[] nd; if (derivationStage == 0) { nd = AdvanceTags(tp); } else if (derivationStage == 1) { nd = AdvanceChunks(tp, ndh.Size() < K ? bestComplete : ndh.Last().Probability); } else { // i > 1 nd = AdvanceParses(tp, Q); } if (nd != null) { for (int k = 0, kl = nd.Length; k < kl; k++) { if (nd[k].Complete) { AdvanceTop(nd[k]); if (nd[k].Probability > bestComplete) { bestComplete = nd[k].Probability; } if (nd[k].Probability < minComplete) { minComplete = nd[k].Probability; } completeParses.Add(nd[k]); } else { ndh.Add(nd[k]); } } } else { if (ReportFailedParse) { Console.Error.WriteLine("Couldn't advance parse " + derivationStage + " stage " + derivationRank + "!\n"); } AdvanceTop(tp); completeParses.Add(tp); } } derivationStage++; odh = ndh; } if (completeParses.Size() == 0) { if (ReportFailedParse) { Console.Error.WriteLine("Couldn't find parse for: " + tokens); } //Parse r = (Parse) odh.first(); //r.show(); //System.out.println(); return(new[] { guess }); } if (numParses == 1) { return(new[] { completeParses.First() }); } var topParses = new List <Parse>(); while (!completeParses.IsEmpty() && topParses.Count < numParses) { var tp = completeParses.Extract(); topParses.Add(tp); //parses.remove(tp); } return(topParses.ToArray()); }