private WordPrediction GetTopPrediction(ScoredTokenPredictionMaker maker, bool isFirstWord)
        {
            WordPrediction value;

            if (_findFollowOnPredictions)
            {
                var topScores = maker.GetTopScores(0, _source.Count, true, false);
                using (var enumerator = topScores.GetEnumerator())
                {
                    value = GetNextCorePrediction(enumerator, isFirstWord);
                }
            }
            else
            {
                value = null;
            }

            Debug.Assert(value == null || value.Score.IsInContextScore, "Only true following predictions expected");

            return(value);
        }
        private void CreateCorePredictions()
        {
            var scores = _maker.GetTopScores(_lowerBound, _upperBound, _isTokenVisible == null, true);

            using (var enumerator = scores.GetEnumerator())
            {
                // Seed predictions with most likely items.
                var nextCorePrediction = GetNextCorePrediction(enumerator, _startOnFirstWord);
                for (var iteration = 0; iteration < _maxListCount && nextCorePrediction != null; iteration++)
                {
                    AddNextPrediction(nextCorePrediction);
                    nextCorePrediction = GetNextCorePrediction(enumerator, _startOnFirstWord);
                }

                // Apply strategies to improve the core predictions.
                for (var improved = _combineCorePredictions; improved;)
                {
                    improved = false;

                    if (1 < _nascents.Count && nextCorePrediction != null)
                    {
                        var pairable       = -1;
                        var lostPrediction = (WordPrediction)null;

                        var next = _nascents[0];
                        var definiteImprovementFound = false;
                        for (var i = 1; !definiteImprovementFound && i < _nascents.Count; i++)
                        {
                            var prev = next;
                            next = _nascents[i];

                            if (prev.CanMergeWithNext(next))
                            {
                                var potentialLostPrediction = prev._followOn;

                                if (pairable == -1 || potentialLostPrediction == null)
                                {
                                    pairable                 = i - 1;
                                    lostPrediction           = potentialLostPrediction;
                                    definiteImprovementFound = potentialLostPrediction == null;
                                }
                                else if (potentialLostPrediction.Score < lostPrediction.Score)
                                {
                                    pairable       = i - 1;
                                    lostPrediction = potentialLostPrediction;
                                }
                            }
                        }

                        if (pairable != -1 &&
                            (lostPrediction == null || lostPrediction.Score < nextCorePrediction.Score))
                        {
                            _nascents[pairable].MergeWithNext(_nascents[pairable + 1]);
                            _nascents.RemoveAt(pairable + 1);

                            AddNextPrediction(nextCorePrediction);
                            nextCorePrediction = GetNextCorePrediction(enumerator, _startOnFirstWord);

                            improved = true;
                        }
                    }
                }
            }
        }