// Does this appear to be a reference for something?
        // Checks the part of our senses, and our sub-parts
        public static ProbableStrength SeemsAnaphora(InformedPhrase phrase)
        {
            ProbableStrength total = new ProbableStrength(0, 0);
            double strengthFactor = total.ImproveStrengthStart();

            foreach (KeyValuePair<PhraseSense, double> sense in phrase.Senses)
            {
                if (sense.Key.Phrases.Count == 1)
                    total.ImproveStrength(SeemsAnaphora(sense.Key.Phrases[0]), ref strengthFactor);
                else
                {
                    ProbableStrength singletotal = sense.Key.SpeechPart().SeemsAnaphora().DownWeight(1.0 / (sense.Key.Phrases.Count + 1));

                    // Combine together results from subphrases
                    ProbableStrength phrasetotal = new ProbableStrength(0, 0);
                    double phraseFactor = phrasetotal.ImproveStrengthStart();
                    foreach (InformedPhrase subphrase in sense.Key.Phrases)
                        phrasetotal.ImproveStrength(SeemsAnaphora(subphrase).DownWeight(1.0 / sense.Key.Phrases.Count), ref phraseFactor);
                    phrasetotal.ImproveStrengthFinish(phraseFactor);

                    // Use both our and the recursive result
                    total.ImproveStrength(singletotal.Combine(phrasetotal), ref strengthFactor);
                }
            }

            total.ImproveStrengthFinish(strengthFactor);

            return total;
        }
        // Could this be an anaphora for the given phrase?  Check the attributes
        public static ProbableStrength AnaphoraOf(InformedPhrase anaphora, PhraseSense prime)
        {
            if (anaphora.IsContained(prime) || prime.IsContained(anaphora))
                return ProbableStrength.Zero;   // can't refer to included structure

            ProbableStrength total = new ProbableStrength(0, 0);
            double strengthFactor = total.ImproveStrengthStart();

            foreach (KeyValuePair<PhraseSense, double> sense in anaphora.Senses)
            {
                ProbableStrength match = AnaphoraOf(sense.Key, prime);
                total.ImproveStrength(match.DownWeight(sense.Value), ref strengthFactor);
            }

            total.ImproveStrengthFinish(strengthFactor);

            return total;
        }
        public static ProbableStrength AnaphoraOf(PhraseSense anaphora, PhraseSense prime)
        {
            ProbableStrength total = new ProbableStrength(0, 0);
            double strengthFactor = total.ImproveStrengthStart();

            // Check if each attribute could describe the phrase
            foreach (PhraseAttribute attribute in anaphora.Attributes)
            {
                if (attribute is PartOSAttribute)
                    continue;   // ignore
                total.ImproveStrength(attribute.Describes(prime), ref strengthFactor);
            }

            // Check if subphrases could be anaphors for the given phrase
            foreach (InformedPhrase subphrase in anaphora.Phrases)
                total.ImproveStrength(AnaphoraOf(subphrase, prime).DownWeight(1.0 / anaphora.Phrases.Count), ref strengthFactor);

            total.ImproveStrengthFinish(strengthFactor);
            return total;
        }
        // Does this attribute describe the word?  Consider overriding this
        public ProbableStrength Describes(InformedPhrase word)
        {
            ProbableStrength total = new ProbableStrength(0, 0);
            double strengthFactor = total.ImproveStrengthStart();

            foreach (KeyValuePair<PhraseSense, double> sense in word.Senses)
                total.ImproveStrength(Describes(sense.Key).DownWeight(sense.Value), ref strengthFactor);

            if (strengthFactor == 0)
            {
                // We never found an appropriate attribute-- so guess!
                ProbableStrength result = Match(Guess(word));
                total.ImproveStrength(result, ref strengthFactor);
            }

            total.ImproveStrengthFinish(strengthFactor);
            return total;
        }
        public virtual ProbableStrength Describes(PhraseSense sense)
        {
            ProbableStrength total = new ProbableStrength(0, 0);
            double strengthFactor = total.ImproveStrengthStart();

            foreach (PhraseAttribute attribute in sense.Attributes)
                total.ImproveStrength(Match(attribute), ref strengthFactor);

            if (strengthFactor == 0)
            {
                // do we match subphrases then?
                foreach (InformedPhrase subphrase in sense.Phrases)
                    total.ImproveStrength(Describes(subphrase).DownWeight(1.0 / sense.Phrases.Count), ref strengthFactor);
            }

            if (strengthFactor == 0)
            {
                // We never found an appropriate attribute-- so guess!
                List<KeyValuePair<PhraseSense, double>> senses = new List<KeyValuePair<PhraseSense, double>>();
                senses.Add(new KeyValuePair<PhraseSense,double>(sense, 1.0));
                InformedPhrase dummy = new InformedPhrase(sense.Name(), senses);
                ProbableStrength result = Match(Guess(dummy));
                total.ImproveStrength(result, ref strengthFactor);
            }

            total.ImproveStrengthFinish(strengthFactor);
            return total;
        }
        // Guess whether or not a phrase is plural
        public static ProbableStrength SeemsPlural(InformedPhrase phrase)
        {
            ProbableStrength result = new ProbableStrength(0, 0);
            double strengthFactor = result.ImproveStrengthStart();

            // Noun count is well determined by ending in s
            ProbableStrength nounness = PartOSAttribute.SeemsA(phrase, SpeechPart.Noun);
            ProbableStrength nisplural;
            if (phrase.Name.ToLower().EndsWith("s"))
                nisplural = new ProbableStrength(1.0, 0.8);
            else
                nisplural = new ProbableStrength(0.0, 0.5);

            result.ImproveStrength(nounness.Relative(nisplural), ref strengthFactor);

            // Verbs that end in s are probably not plural
            ProbableStrength verbness = PartOSAttribute.SeemsA(phrase, SpeechPart.Verb);
            if (phrase.Name.ToLower().EndsWith("s"))
            {
                ProbableStrength visplural = new ProbableStrength(0.0, 0.8);
                result.ImproveStrength(verbness.Relative(visplural), ref strengthFactor);
            }

            result.ImproveStrengthFinish(strengthFactor);

            return result;
        }
        public static ProbableStrength SeemsReferencePhrase(InformedPhrase phrase, bool not)
        {
            ProbableStrength total = new ProbableStrength(0, 0);
            double strengthFactor = total.ImproveStrengthStart();

            foreach (KeyValuePair<PhraseSense, double> sense in phrase.Senses)
            {
                if (sense.Key.Phrases.Count == 1)
                    total.ImproveStrength(SeemsReferencialVerb(sense.Key.Phrases[0]), ref strengthFactor);
                else
                {
                    // Is this a "helper" verb followed by an anaphora?
                    ProbableStrength foundHelper = ProbableStrength.None, foundBoth = ProbableStrength.None;
                    foreach (InformedPhrase subphr in sense.Key.Phrases)
                    {
                        if (!not)
                        {
                            foundHelper = foundHelper.Better(SeemsReferencialVerb(subphr));
                            foundBoth = foundBoth.Better(foundHelper.Relative(SeemsAnaphora(subphr)));
                        }
                        else
                        {
                            foundHelper = foundHelper.Better(SeemsReferencialVerb(subphr).InverseProbability());
                            foundBoth = foundBoth.Better(foundHelper.Relative(SeemsAnaphora(subphr).InverseProbability()));
                        }
                    }

                    foundBoth.weight = foundBoth.weight + .5 - foundBoth.weight * .5;

                    // Use both our and the recursive result
                    total.ImproveStrength(foundBoth, ref strengthFactor);
                }
            }

            total.ImproveStrengthFinish(strengthFactor);

            return total;
        }