public static ImmutableSentenceDomainModel CopyUsingCartesianDomains(ISentenceDomainModel otherModel)
        {
            var immutableSentenceDomainModel = otherModel as ImmutableSentenceDomainModel;
            if (immutableSentenceDomainModel != null)
                return immutableSentenceDomainModel;

            var domains = ImmutableDictionary.CreateBuilder<ISentenceForm, ISentenceFormDomain>();
            foreach (ISentenceForm form in otherModel.SentenceForms)
            {
                ISentenceFormDomain otherDomain = otherModel.GetDomain(form);
                var domainsForSlots = new List<ISet<TermObject>>();
                for (int i = 0; i < form.TupleSize; i++)
                    domainsForSlots.Add(otherDomain.GetDomainForSlot(i));
                domains[form] = new CartesianSentenceFormDomain(form, domainsForSlots);
            }
            return new ImmutableSentenceDomainModel(ImmutableSentenceFormModel.CopyOf(otherModel), domains.ToImmutable());
        }
예제 #2
0
        public void AddSentenceForm(ISentenceForm form, ISentenceDomainModel model,
            IDictionary<Fact, IComponent> components,
            IDictionary<Fact, IComponent> negations, IConstant trueComponent, IConstant falseComponent,
            bool usingBase, bool usingInput, ISet<ISentenceForm> recursionForms,
            IDictionary<Fact, IComponent> temporaryComponents, IDictionary<Fact, IComponent> temporaryNegations,
            Dictionary<ISentenceForm, FunctionInfo> functionInfoMap, IConstantChecker constantChecker,
            Dictionary<ISentenceForm, ICollection<Fact>> completedSentenceFormValues)
        {
            //This is the meat of it (along with the entire Assignments class).
            //We need to enumerate the possible propositions in the sentence form...
            //We also need to hook up the sentence form to the inputs that can make it true.
            //We also try to optimize as we go, which means possibly removing the
            //proposition if it isn't actually possible, or replacing it with
            //true/false if it's a constant.

            ISet<Fact> alwaysTrueSentences = model.GetSentencesListedAsTrue(form);
            ISet<Implication> rules = model.GetRules(form);

            foreach (Fact alwaysTrueSentence in alwaysTrueSentences)
            {
                //We add the sentence as a constant
                if (alwaysTrueSentence.RelationName == GameContainer.Parser.TokLegal
                    || alwaysTrueSentence.RelationName == GameContainer.Parser.TokNext
                    || alwaysTrueSentence.RelationName == GameContainer.Parser.TokGoal)
                {
                    var prop = _componentFactory.CreateProposition(alwaysTrueSentence);
                    //Attach to true
                    trueComponent.AddOutput(prop);
                    prop.AddInput(trueComponent);
                    //Still want the same components;
                    //we just don't want this to be anonymized
                }
                //Assign as true
                components[alwaysTrueSentence] = trueComponent;
                negations[alwaysTrueSentence] = falseComponent;
            }

            //For does/true, make nodes based on input/base, if available
            if (usingInput && form.Name.Equals(GameContainer.Parser.TokDoes))
            {
                //Add only those propositions for which there is a corresponding INPUT
                ISentenceForm inputForm = form.WithName(GameContainer.SymbolTable["input"]);
                foreach (Fact inputSentence in constantChecker.GetTrueSentences(inputForm))
                {
                    Fact doesSentence = _doesProcessor.ProcessBaseFact(inputSentence);
                    var prop = _componentFactory.CreateProposition(doesSentence);
                    components[doesSentence] = prop;
                }
                return;
            }
            if (usingBase && form.Name.Equals(GameContainer.Parser.TokTrue))
            {
                ISentenceForm baseForm = form.WithName(GameContainer.SymbolTable["base"]);
                foreach (Fact baseSentence in constantChecker.GetTrueSentences(baseForm))
                {
                    Fact trueSentence = _trueProcessor.ProcessBaseFact(baseSentence);
                    IProposition prop = _componentFactory.CreateProposition(trueSentence);
                    components[trueSentence] = prop;
                }
                return;
            }

            //var recursiveFormCache = new RecursionFormsCache(recursionForms);

            var inputsToOr = new Dictionary<Fact, HashSet<IComponent>>();
            foreach (Implication rule in rules)
            {
                AssignmentsImpl assignments = AssignmentsFactory.GetAssignmentsForRule(rule, model, functionInfoMap,
                    completedSentenceFormValues);

                //Calculate vars in live (non-constant, non-distinct) conjuncts
                ISet<TermVariable> varsInLiveConjuncts = GetVarsInLiveConjuncts(rule,
                    constantChecker.ConstantSentenceForms);
                foreach (var head in rule.Consequent.VariablesOrEmpty)
                    varsInLiveConjuncts.Add(head);
                var varsInRule = new HashSet<TermVariable>(rule.VariablesOrEmpty);
                bool preventDuplicatesFromConstants = varsInRule.Count > varsInLiveConjuncts.Count;

                bool[] constantFormCheck = new bool[rule.Antecedents.Constituents.Length];
                for (int i = 0; i < rule.Antecedents.Constituents.Length; i++)
                {
                    Expression literal = rule.Antecedents.Constituents[i];
                    var fact = literal as Fact;
                    var negated = literal as Negation;
                    if (fact != null || negated != null)
                    {
                        if (negated != null)
                            fact = (Fact) negated.Negated;

                        ISentenceForm conjunctForm = model.GetSentenceForm(fact);
                        if (constantChecker.IsConstantForm(conjunctForm))
                            constantFormCheck[i] = true;
                    }
                }

                for (var asnItr = (AssignmentIteratorImpl) assignments.GetEnumerator(); asnItr.MoveNext();)
                {
                    TermObjectSubstitution assignment = asnItr.Current;
                    if (assignment == null)
                        continue; //Not sure if this will ever happen

                    //ConcurrencyUtils.checkForInterruption();

                    var sentence = (Fact) rule.Consequent.ApplySubstitution(assignment);

                    //Now we go through the conjuncts as before, but we wait to hook them up.
                    var componentsToConnect = new List<IComponent>(rule.Consequent.Arity);
                    for (int i = 0; i < rule.Antecedents.Constituents.Length; i++)
                    {
                        Expression literal = rule.Antecedents.Constituents[i];
                        var fact = literal as Fact;
                        if (fact != null)
                        {
                            if (fact.RelationName != GameContainer.Parser.TokDistinct)
                            {
                                //Get the sentence post-substitutions
                                var transformed = (Fact) literal.ApplySubstitution(assignment);

                                //Check for constant-ness
                                //ISentenceForm conjunctForm = model.GetSentenceForm(transformed);
                                //if (constantChecker.IsConstantForm(conjunctForm))
                                if (constantFormCheck[i])
                                {
                                    if (!constantChecker.IsTrueConstant(transformed))
                                    {
                                        List<TermVariable> varsToChange = GetVarsInConjunct(literal);
                                        asnItr.ChangeOneInNext(varsToChange, assignment);
                                        componentsToConnect.Add(null);
                                    }
                                    continue;
                                }

                                //If conj is null and this is a sentence form we're still handling, hook up to a temporary sentence form
                                IComponent conj;
                                if (!components.TryGetValue(transformed, out conj))
                                    temporaryComponents.TryGetValue(transformed, out conj);

                                if (conj == null && InSentenceFormGroup(transformed, recursionForms))
                                {
                                    //Set up a temporary component
                                    var tempProp = _componentFactory.CreateProposition(transformed);
                                    temporaryComponents[transformed] = tempProp;
                                    conj = tempProp;
                                }
                                //Let's say this is false; we want to backtrack and change the right variable
                                if (conj == null || IsThisConstant(conj, falseComponent))
                                {
                                    List<TermVariable> varsInConjunct = GetVarsInConjunct(literal);
                                    asnItr.ChangeOneInNext(varsInConjunct, assignment);
                                    //These last steps just speed up the process
                                    //telling the factory to ignore this rule
                                    componentsToConnect.Add(null);
                                    continue; //look at all the other restrictions we'll face
                                }

                                componentsToConnect.Add(conj);
                            }
                        }
                        else
                        {
                            var negation = literal as Negation;
                            if (negation != null)
                            {
                                //Add a "not" if necessary
                                //Look up the negation
                                var inner = (Fact) negation.Negated;
                                var transformed = (Fact) inner.ApplySubstitution(assignment);

                                //Add constant-checking here...
                                //ISentenceForm conjunctForm = model.GetSentenceForm(transformed);
                                //if (constantChecker.IsConstantForm(conjunctForm))
                                if (constantFormCheck[i])
                                {
                                    if (constantChecker.IsTrueConstant(transformed))
                                    {
                                        List<TermVariable> varsToChange = GetVarsInConjunct(negation);
                                        asnItr.ChangeOneInNext(varsToChange, assignment);
                                        componentsToConnect.Add(null);
                                    }
                                    continue;
                                }

                                IComponent conj;
                                negations.TryGetValue(transformed, out conj);
                                if (IsThisConstant(conj, falseComponent))
                                {
                                    //We need to change one of the variables inside
                                    List<TermVariable> varsInConjunct = GetVarsInConjunct(inner);
                                    asnItr.ChangeOneInNext(varsInConjunct, assignment);
                                    //ignore this rule
                                    componentsToConnect.Add(null);
                                    continue;
                                }
                                if (conj == null)
                                    temporaryNegations.TryGetValue(transformed, out conj);

                                //Check for the recursive case:
                                if (conj == null && InSentenceFormGroup(transformed, recursionForms))
                                {
                                    IComponent positive;
                                    if (!components.TryGetValue(transformed, out positive))
                                        temporaryComponents.TryGetValue(transformed, out positive);

                                    if (positive == null)
                                    {
                                        //Make the temporary proposition
                                        var tempProp = _componentFactory.CreateProposition(transformed);
                                        temporaryComponents[transformed] = tempProp;
                                        positive = tempProp;
                                    }
                                    //Positive is now set and in temporaryComponents
                                    //Evidently, wasn't in temporaryNegations
                                    //So we add the "not" gate and set it in temporaryNegations
                                    var not = _componentFactory.CreateNot();
                                    //Add positive as input
                                    not.AddInput(positive);
                                    positive.AddOutput(not);
                                    temporaryNegations[transformed] = not;
                                    conj = not;
                                }
                                if (conj == null)
                                {
                                    IComponent positive;
                                    components.TryGetValue(transformed, out positive);
                                    //No, because then that will be attached to "negations", which could be bad

                                    if (positive == null)
                                    {
                                        //So the positive can't possibly be true (unless we have recurstion)
                                        //and so this would be positive always
                                        //We want to just skip this conjunct, so we continue to the next

                                        continue; //to the next conjunct
                                    }

                                    //Check if we're sharing a component with another sentence with a negation
                                    //(i.e. look for "nots" in our outputs and use those instead)
                                    INot existingNotOutput = GetNotOutput(positive);
                                    if (existingNotOutput != null)
                                    {
                                        componentsToConnect.Add(existingNotOutput);
                                        negations[transformed] = existingNotOutput;
                                        continue; //to the next conjunct
                                    }

                                    var not = _componentFactory.CreateNot();
                                    not.AddInput(positive);
                                    positive.AddOutput(not);
                                    negations[transformed] = not;
                                    conj = not;
                                }
                                componentsToConnect.Add(conj);
                            }
                            else
                            {
                                throw new Exception("Unwanted Expression type");
                            }
                        }
                    }
                    if (!componentsToConnect.Contains(null))
                    {
                        //Connect all the components
                        IProposition andComponent = _componentFactory.CreateProposition(_tempFact);

                        Andify(componentsToConnect, andComponent, trueComponent);
                        if (!IsThisConstant(andComponent, falseComponent))
                        {
                            if (!inputsToOr.ContainsKey(sentence))
                                inputsToOr[sentence] = new HashSet<IComponent>();
                            inputsToOr[sentence].Add(andComponent);
                            //We'll want to make sure at least one of the non-constant
                            //components is changing
                            if (preventDuplicatesFromConstants)
                                asnItr.ChangeOneInNext(varsInLiveConjuncts, assignment);
                        }
                    }
                }
            }

            //At the end, we hook up the conjuncts
            foreach (var entry in inputsToOr)
            {
                //ConcurrencyUtils.checkForInterruption();

                Fact sentence = entry.Key;
                HashSet<IComponent> inputs = entry.Value;
                var realInputs = new HashSet<IComponent>();
                foreach (IComponent input in inputs)
                    if (input is IConstant || !input.Inputs.Any())
                        realInputs.Add(input);
                    else
                    {
                        realInputs.Add(input.GetSingleInput());
                        input.GetSingleInput().RemoveOutput(input);
                        input.RemoveAllInputs();
                    }

                var prop = _componentFactory.CreateProposition(sentence);
                Orify(realInputs, prop, falseComponent);
                components[sentence] = prop;
            }

            //True/does sentences will have none of these rules, but
            //still need to exist/"float"
            //We'll do this if we haven't used base/input as a basis
            if (form.Name.Equals(GameContainer.Parser.TokTrue) || form.Name.Equals(GameContainer.Parser.TokDoes))
                foreach (Fact sentence in model.GetDomain(form)) //ConcurrencyUtils.checkForInterruption();
                    components[sentence] = _componentFactory.CreateProposition(sentence);
        }