public CartesianSentenceFormDomain(ISentenceForm form, IDictionary<int, ICollection<TermObject>> setMultimap) { Debug.Assert(setMultimap != null); var domainsForSlots = new List<ISet<TermObject>>(); for (int i = 0; i < form.TupleSize; i++) { ICollection<TermObject> possibleDomain; if (!setMultimap.TryGetValue(i, out possibleDomain)) possibleDomain = new List<TermObject>(); domainsForSlots.Add(new HashSet<TermObject>(possibleDomain)); } _form = form; _domainsForSlots = domainsForSlots.Select(s => new JavaHashSet<TermObject>(s)).ToImmutableList(); }
public FunctionInfoImpl(ISentenceForm form, ISet<Fact> trueSentences) { _form = form; int numSlots = form.TupleSize; for (int i = 0; i < numSlots; i++) { //We want to establish whether or not this is a constant... IDictionary<AssignmentFunctionQueryTuple, TermObject> functionMap = new Dictionary<AssignmentFunctionQueryTuple, TermObject>(); bool functional = true; foreach (Fact sentence in trueSentences) { //ConcurrencyUtils.checkForInterruption(); List<TermObject> tuple = sentence.TermObjects.ToList(); var tuplePart = new AssignmentFunctionQueryTuple(tuple.Count - 1); tuplePart.AddRange(tuple.GetRange(0, i)); tuplePart.AddRange(tuple.GetRange(i + 1, tuple.Count - i - 1)); if (functionMap.ContainsKey(tuplePart)) { //We have two tuples with different values in just this slot functional = false; break; } //Otherwise, we record it functionMap[new AssignmentFunctionQueryTuple(tuplePart)] = tuple[i]; } if (functional) { //Record the function _dependentSlots.Add(true); _valueMaps.Add(functionMap); } else { //Forget it _dependentSlots.Add(false); _valueMaps.Add(null); } } }
public static AssignmentsImpl GetAssignmentsWithRecursiveInput(Implication rule, ISentenceDomainModel model, ISentenceForm form, Fact input, Dictionary<ISentenceForm, FunctionInfo> functionInfoMap, Dictionary<ISentenceForm, ICollection<Fact>> completedSentenceFormValues) { //Look for the literal(s) in the rule with the sentence form of the //recursive input. This can be tricky if there are multiple matching //literals. var matchingLiterals = rule.Antecedents.Conjuncts.OfType<Fact>().Where(form.Matches).ToList(); var assignmentsList = new List<AssignmentsImpl>(); foreach (Fact matchingLiteral in matchingLiterals) { var preassignment = new TermObjectSubstitution(); preassignment.Add(matchingLiteral.Unify(input)); if (preassignment.NumMappings() > 0) { var assignments = new AssignmentsImpl( preassignment, rule, //TODO: This one getVarDomains call is why a lot of //SentenceModel/DomainModel stuff is required. Can //this be better factored somehow? SentenceDomainModels.GetVarDomains(rule, model, SentenceDomainModels.VarDomainOpts.IncludeHead), functionInfoMap, completedSentenceFormValues); assignmentsList.Add(assignments); } } if (assignmentsList.Count == 0) return new AssignmentsImpl(); if (assignmentsList.Count == 1) return assignmentsList[0]; throw new Exception("Not yet implemented: assignments for recursive functions with multiple recursive conjuncts"); //TODO: Plan to implement by subclassing TermObjectSubstitution into something //that contains and iterates over multiple TermObjectSubstitution }
public ISet<Implication> GetRules(ISentenceForm form) { return new HashSet<Implication>(_rulesByForm[form]); }
public static FunctionInfo Create(ISentenceForm form, ISet<Fact> set) { return new FunctionInfoImpl(form, set); }
public static FunctionInfo Create(ISentenceForm form, IConstantChecker constantChecker) { return new FunctionInfoImpl(form, constantChecker.GetTrueSentences(form)); }
public CondensorSentenceDomainModel(ISentenceForm newForm, ISentenceFormDomain newFormDomain, ISentenceDomain oldModel) { _newForm = newForm; _newFormDomain = newFormDomain; _oldModel = oldModel; }
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); }
public override ISentenceFormDomain GetDomain(ISentenceForm form) { ISentenceFormDomain result; _domains.TryGetValue(form, out result); return result; }
public ISet<Implication> GetRules(ISentenceForm form) { return _formModel.GetRules(form); }
private static Expression ReplaceRelationInLiteral(Expression literal, ISentenceForm trueForm) { var sentence = literal as Fact; if (sentence != null) if (trueForm.Matches(sentence)) { var terms = sentence.GetTerms(); var function = terms[0] as TermFunction; Debug.Assert(function != null); return new VariableFact(true, function.FunctionName, function.Arguments); } else return literal; var not = literal as Negation; if (not != null) return new Negation(ReplaceRelationInLiteral(not.Negated, trueForm)); var or = literal as Disjunction; if (or != null) { var newOrBody = new List<Expression>(); for (int i = 0; i < or.GetDisjuncts().Count(); i++) newOrBody.Add(ReplaceRelationInLiteral(or.Constituents[i], trueForm)); return new Disjunction(newOrBody.ToArray()); } throw new Exception(string.Format("Unanticipated GDL literal type {0} encountered in Relationizer", literal.GetType())); }
private static List<Expression> ReplaceRelationInBody(IEnumerable<Expression> body, ISentenceForm trueForm) { return body.Select(literal => ReplaceRelationInLiteral(literal, trueForm)).ToList(); }
public Ambiguity(ISentenceForm original, Dictionary<int, TermFunction> replacementsByOriginalTupleIndex, ISentenceForm replacement) { Debug.Assert(original != null); Debug.Assert(replacementsByOriginalTupleIndex != null); Debug.Assert(replacementsByOriginalTupleIndex.Any()); Debug.Assert(replacement != null); foreach (int varIndex in replacementsByOriginalTupleIndex.Keys) Debug.Assert(varIndex < original.TupleSize); Original = original; _replacementsByOriginalTupleIndex = replacementsByOriginalTupleIndex.ToImmutableDictionary(); Replacement = replacement; }
private static List<Ambiguity> GetAmbiguities(ISentenceForm original, IEnumerable<ISentenceForm> forms) { return forms.Select(form => FindAmbiguity(original, form)).Where(ambiguity => ambiguity != null).ToList(); }
private static Ambiguity FindAmbiguity(ISentenceForm original, ISentenceForm replacement) { Debug.Assert(original.Name == replacement.Name); if (original.Equals(replacement)) return null; var replacementsByOriginalTupleIndex = new Dictionary<int, TermFunction>(); //Make the arguments ?v0, ?v1, ?v2, ... so we can find the tuple indices easily Fact originalSentence = original.GetSentenceFromTuple(GetNumberedTuple(original.TupleSize)); Fact replacementSentence = replacement.GetSentenceFromTuple(GetNumberedTuple(replacement.TupleSize)); bool success = FindAmbiguity(originalSentence.GetTerms(), replacementSentence.GetTerms(), replacementsByOriginalTupleIndex); return success ? new Ambiguity(original, replacementsByOriginalTupleIndex, replacement) : null; }
public ISet<Fact> GetSentencesListedAsTrue(ISentenceForm form) { return new HashSet<Fact>(_trueSentencesByForm[form]); }
public CartesianSentenceFormDomain(ISentenceForm form, IEnumerable<ISet<TermObject>> domainsForSlots) { _form = form; _domainsForSlots = domainsForSlots.Select(s => new JavaHashSet<TermObject>(s)).ToImmutableList(); }
public abstract ISentenceFormDomain GetDomain(ISentenceForm form);
private static void AddFormToCompletedValues(ISentenceForm form, Dictionary<ISentenceForm, ICollection<Fact>> completedSentenceFormValues, IConstantChecker constantChecker) { completedSentenceFormValues[form] = new List<Fact>(constantChecker.GetTrueSentences(form)); }
public ISet<Fact> GetSentencesListedAsTrue(ISentenceForm form) { return _formModel.GetSentencesListedAsTrue(form); }
public ISet<Fact> GetTrueSentences(ISentenceForm form) { return new HashSet<Fact>(_sentencesByForm[form]); }
private static void AddConstantsToFunctionInfo(ISentenceForm form, IConstantChecker constantChecker, IDictionary<ISentenceForm, FunctionInfo> functionInfoMap) { functionInfoMap[form] = FunctionInfoImpl.Create(form, constantChecker); }
public ISentenceFormDomain GetDomain(ISentenceForm form) { return form.Equals(_newForm) ? _newFormDomain : _oldModel.GetDomain(form); }
private static void AddFormToCompletedValues(ISentenceForm form, IDictionary<ISentenceForm, ICollection<Fact>> completedSentenceFormValues, Dictionary<Fact, IComponent> components) { //Kind of inefficient. Could do better by collecting these as we go, //then adding them back into the CSFV map once the sentence forms are complete. //completedSentenceFormValues.put(form, new ArrayList<Fact>()); completedSentenceFormValues[form] = components.Keys.Where(form.Matches).ToList(); }
private CartesianSentenceFormDomain GetDomain(ISentenceForm form, Fact sentence) { var domainContents = new List<ISet<TermObject>>(); GetDomainInternal(sentence.GetTerms(), _sentencesModel.GetBodyModel(sentence), domainContents); return new CartesianSentenceFormDomain(form, domainContents); }
public bool IsConstantForm(ISentenceForm form) { return _sentenceModel.ConstantSentenceForms.Contains(form); }
private static ISentenceFormDomain GetNewFormDomain(Implication condensingRule, ISentenceDomain oldModel, ISentenceForm newForm) { var varDomains = SentenceDomainModels.GetVarDomains(condensingRule, oldModel, SentenceDomainModels.VarDomainOpts.BodyOnly); var domainsForSlots = new List<ISet<TermObject>>(); foreach (Term term in condensingRule.Consequent.NestedTerms) { if (!(term is TermVariable)) throw new Exception("Expected all slots in the head of a condensing rule to be variables, but the rule was: " + condensingRule); domainsForSlots.Add(varDomains[(TermVariable)term]); } return new CartesianSentenceFormDomain(newForm, domainsForSlots); }