public ImmutableSentenceDomainModel(ISentenceFormModel formModel, IDictionary<ISentenceForm, ISentenceFormDomain> domains)
     : base(ImmutableSentenceFormModel.CopyOf(formModel))
 {
     //if (!formModel.SentenceForms.SetEquals(domains.Keys))
     //    throw new Exception();
     _domains = domains.ToImmutableDictionary();
 }
        /// <summary>
        /// Returns an ImmutableSentenceFormModel with the same contents as the given SentenceFormModel.
        /// May not actually create a copy if the input is immutable.
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public static ImmutableSentenceFormModel CopyOf(ISentenceFormModel other)
        {
            var immutableSentenceDomainModel = other as ImmutableSentenceDomainModel;
            if (immutableSentenceDomainModel != null)
                return CopyOf(immutableSentenceDomainModel.FormModel);

            var immutableSentenceFormModel = other as ImmutableSentenceFormModel;
            if (immutableSentenceFormModel != null)
                return immutableSentenceFormModel;

            var rulesByForm = new MultiDictionary<ISentenceForm, Implication>(false);
            var trueSentencesByForm = new MultiDictionary<ISentenceForm, Fact>(false);
            foreach (ISentenceForm form in other.SentenceForms)
            {
                rulesByForm[form] = other.GetRules(form);
                trueSentencesByForm[form] = other.GetSentencesListedAsTrue(form);
            }

            var dependencyGraph = new MultiDictionary<ISentenceForm, ISentenceForm>(true);
            foreach (KeyValuePair<ISentenceForm, ICollection<ISentenceForm>> kv in other.DependencyGraph)
                dependencyGraph[kv.Key] = kv.Value;

            return new ImmutableSentenceFormModel(ImmutableList.CreateRange(other.Description),
                                                  ImmutableHashSet.CreateRange(other.SentenceForms),
                                                  ImmutableHashSet.CreateRange(other.ConstantSentenceForms),
                                                  ImmutableHashSet.CreateRange(other.IndependentSentenceForms),
                                                  dependencyGraph,
                                                  rulesByForm,
                                                  trueSentencesByForm);
        }
        private static IEnumerable<Implication> ApplyAmbiguitiesForLiteral(Expression literal, Implication rule,
            IDictionary<ISentenceForm, ICollection<Ambiguity>> ambiguitiesByOriginalForm, ISentenceFormModel model)
        {
            var results = new List<Implication> { rule };
            var varGen = new UnusedVariableGenerator(rule);

            var fact = literal as Fact;
            if (fact != null)
            {
                ISentenceForm form = model.GetSentenceForm(fact);
                ICollection<Ambiguity> ambiguities;
                if (ambiguitiesByOriginalForm.TryGetValue(form, out ambiguities))
                {
                    IEnumerable<Ambiguity> applicableAmiguities = ambiguities.Where(ambiguity => ambiguity.Applies(fact));
                    IEnumerable<Substitution> substitutions = applicableAmiguities.Select(ambiguity => ambiguity.GetReplacementAssignment(fact, varGen));
                    IEnumerable<Implication> implications = substitutions.Select(substitution => (Implication)rule.ApplySubstitution(substitution));
                    results.AddRange(implications);
                }
            }
            else if (literal is Negation)
            {
                // Do nothing. Variables must appear in a positive literal in the
                // rule, and will be handled there.
            }
            else if (literal is Disjunction)
            {
                throw new Exception("ORs should have been removed");
                //} else if (literal is GdlDistinct) {
                // Do nothing
            }

            return results;
        }
 private static List<Implication> ApplyAmbiguities(Implication originalRule, MultiDictionary<ISentenceForm, Ambiguity> ambiguitiesByOriginalForm,
     ISentenceFormModel model)
 {
     var rules = new List<Implication> { originalRule };
     //Each literal can potentially multiply the number of rules we have, so we apply each literal separately to the entire list of rules so far.
     IEnumerable<Expression> originalSentences = ImmutableHashSet.Create(originalRule.Consequent).Concat(originalRule.Antecedents.Conjuncts);
     foreach (Expression literal in originalSentences)
     {
         var newRules = new List<Implication>();
         foreach (Implication rule in rules)
         {
             Debug.Assert(originalRule.Consequent.Arity == rule.Consequent.Arity);
             newRules.AddRange(ApplyAmbiguitiesForLiteral(literal, rule, ambiguitiesByOriginalForm, model));
         }
         rules = newRules;
     }
     return rules;
 }
 public static ImmutableConstantChecker Create(ISentenceFormModel sentenceModel, MultiDictionary<ISentenceForm, Fact> sentencesByForm)
 {
     return new ImmutableConstantChecker(ImmutableSentenceFormModel.CopyOf(sentenceModel), sentencesByForm);
 }
 /**
  * Precomputes the true sentences in every constant sentence form in the given
  * sentence model and returns the results in the form of a ConstantChecker.
  *
  * The implementation uses a forward-chaining reasoner.
  *
  * For accurate results, the rules used should have had the {@link NewVariableConstrainer}
  * transformation applied to them.
  *
  * On average, this approach is more efficient than {@link #createWithProver(SentenceFormModel)}.
  */
 //public static ImmutableConstantChecker createWithForwardChaining(SentenceDomainModel model)  {
 //    GdlChainingReasoner reasoner = GdlChainingReasoner.create(model);
 //    GdlSentenceSet sentencesByForm = reasoner.getConstantSentences();
 //    addSentencesTrueByRulesDifferentially(sentencesByForm, model, reasoner);
 //    return ImmutableConstantChecker.create(model,
 //            Multimaps.filterKeys(sentencesByForm.getSentences(), Predicates.in(model.getConstantSentenceForms())));
 //}
 //private static void addSentencesTrueByRulesDifferentially(
 //        GdlSentenceSet sentencesByForm,
 //        SentenceDomainModel domainModel, GdlChainingReasoner reasoner)  {
 //    SentenceFormModel model = domainModel;
 //    Set<SentenceForm> constantForms = model.getConstantSentenceForms();
 //    //Find the part of the dependency graph dealing only with the constant forms.
 //    MultiDictionary<SentenceForm, SentenceForm> dependencySubgraph =
 //            Multimaps.filterKeys(model.getDependencyGraph(), Predicates.in(constantForms));
 //    dependencySubgraph = Multimaps.filterValues(model.getDependencyGraph(), Predicates.in(constantForms));
 //    dependencySubgraph = ImmutableMultimap.copyOf(dependencySubgraph);
 //    List<Set<SentenceForm>> ordering = DependencyGraphs.toposortSafe(constantForms, dependencySubgraph);
 //    foreach (Set<SentenceForm> stratum in ordering) {
 //        // One non-differential pass, collecting the changes
 //        GdlSentenceSet newlyTrueSentences = GdlSentenceSet.create();
 //        foreach (SentenceForm form in stratum) {
 //            foreach (Implication rule in model.getRules(form)) {
 //                GdlSentenceSet ruleResults =
 //                        reasoner.getRuleResults(rule, domainModel, sentencesByForm);
 //                if (!reasoner.isSubsetOf(sentencesByForm, ruleResults)) {
 //                    sentencesByForm = reasoner.getUnion(sentencesByForm, ruleResults);
 //                    newlyTrueSentences = reasoner.getUnion(newlyTrueSentences, ruleResults);
 //                }
 //            }
 //        }
 //        // Now a lot of differential passes to deal with recursion efficiently
 //        bool somethingChanged = true;
 //        while (somethingChanged) {
 //            somethingChanged = false;
 //            GdlSentenceSet newStuffInThisPass = GdlSentenceSet.create();
 //            foreach (SentenceForm form in stratum) {
 //                foreach (Implication rule in model.getRules(form)) {
 //                    GdlSentenceSet ruleResults =
 //                            reasoner.getRuleResultsForNewSentences(rule, domainModel, sentencesByForm,
 //                                    newlyTrueSentences);
 //                    if (!reasoner.isSubsetOf(sentencesByForm, ruleResults)) {
 //                        somethingChanged = true;
 //                        newStuffInThisPass = reasoner.getUnion(newStuffInThisPass, ruleResults);
 //                    }
 //                }
 //            }
 //            sentencesByForm = reasoner.getUnion(sentencesByForm, newStuffInThisPass);
 //            newlyTrueSentences = newStuffInThisPass;
 //        }
 //    }
 //}
 /**
  * Precomputes the true sentences in every constant sentence form in the given
  * sentence model and returns the results in the form of a ConstantChecker.
  *
  * The implementation uses a backwards-chaining theorem prover.
  *
  * In most (but not all) cases, {@link #createWithForwardChaining(SentenceDomainModel)}
  * is more efficient.
  */
 public static ImmutableConstantChecker CreateWithProver(ISentenceFormModel model)
 {
     var sentencesByForm = new MultiDictionary<ISentenceForm, Fact>(false);
     AddSentencesTrueByRules(sentencesByForm, model);
     return ImmutableConstantChecker.Create(model, sentencesByForm);
 }
 //INFO: using the old BasicReasoner which appears to be much slower
 //private static void AddSentencesTrueByRules(
 //    MultiDictionary<ISentenceForm, Fact> sentencesByForm,
 //    ISentenceFormModel model)
 //{
 //    BasicReasoner prover = GameContainer.Reasoner;
 //    var context = new ProofContext(new BasicKB(), GameContainer.Parser);
 //    foreach (ISentenceForm form in model.ConstantSentenceForms)
 //    {
 //        Fact query = form.GetSentenceFromTuple(GetVariablesTuple(form.TupleSize));
 //        IEnumerable<GroundFact> answers = prover.GetAllAnswers(query, context);
 //        foreach (GroundFact result in answers)
 //        {
 //            //ConcurrencyUtils.checkForInterruption();
 //            //Variables may end up being replaced with functions, which is not what we want here, so we have to double-check that the form is correct.
 //            if (form.Matches(result))
 //                sentencesByForm.Add(form, result);
 //        }
 //    }
 //}
 private static void AddSentencesTrueByRules(MultiDictionary<ISentenceForm, Fact> sentencesByForm, ISentenceFormModel model)
 {
     AimaProver prover = new AimaProver(model.Description);
     foreach (ISentenceForm form in model.ConstantSentenceForms)
     {
         Fact query = form.GetSentenceFromTuple(GetVariablesTuple(form.TupleSize));
         HashSet<Fact> context = new HashSet<Fact>();
         foreach (Fact result in prover.AskAll(query, context))
             if (form.Matches(result))
                 sentencesByForm.Add(form, result);
     }
 }
 protected AbstractSentenceDomainModel(ISentenceFormModel formModel)
 {
     _formModel = formModel;
 }
 private static MultiDictionary<int, ISentenceForm> GetFormsByName(ISentenceFormModel model)
 {
     var result = new MultiDictionary<int, ISentenceForm>(true);
     foreach (ISentenceForm value in GetAllSentenceForms(model))
         result.Add(value.Name, value);
     return result;
 }
        private static MultiDictionary<ISentenceForm, Ambiguity> GetAmbiguitiesByOriginalForm(ISentenceFormModel model)
        {
            var result = new MultiDictionary<ISentenceForm, Ambiguity>(true);
            MultiDictionary<int, ISentenceForm> formsByName = GetFormsByName(model);

            foreach (int name in formsByName.Keys)
            {
                ICollection<ISentenceForm> forms = formsByName[name];
                foreach (ISentenceForm form in forms)
                    result[form] = GetAmbiguities(form, forms);
            }

            ISet<ISentenceForm> allForms = formsByName.Values.ToImmutableHashSet();
            foreach (Ambiguity ambiguity in result.Values)
            {
                Debug.Assert(allForms.Contains(ambiguity.Original));
                Debug.Assert(allForms.Contains(ambiguity.Replacement));
            }

            return result;
        }
 private static IEnumerable<ISentenceForm> GetAllSentenceForms(ISentenceFormModel model)
 {
     // The model may only have sentence forms for sentences that can actually be true. It may be missing sentence forms that are used in
     // the rules only, with no actual corresponding sentences. We want to make sure these are included.
     var forms = new HashSet<ISentenceForm>(model.SentenceForms);
     GdlVisitors.VisitAll(model.Description, new GdlVisitor { VisitSentence = sentence => forms.Add(new SimpleSentenceForm(sentence)) });
     return forms;
 }
        private static IList<Expression> ApplyAmbiguitiesToRules(IEnumerable<Expression> description,
            MultiDictionary<ISentenceForm, Ambiguity> ambiguitiesByOriginalForm, ISentenceFormModel model)
        {
            ImmutableList<Expression>.Builder result = ImmutableList.CreateBuilder<Expression>();
            foreach (Expression gdl in description)
            {
                var implication = gdl as Implication;
                if (implication != null)
                    ApplyAmbiguities(implication, ambiguitiesByOriginalForm, model).ForEach(result.Add);
                else
                    result.Add(gdl);
            }

            return result.ToImmutable();
        }
 internal UnusedSentenceNameSource(ISentenceFormModel model)
 {
     ISet<String> initialNames = SentenceForms.GetNames(model.SentenceForms);
     _allNamesSoFar = new HashSet<string>(initialNames);
 }