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()); }
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); }