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 Implication RemoveNotDistinctLiteral(Implication rule) { while (rule != null && GetNotDistinctLiteral(rule) != null) rule = RemoveNotDistinctLiteral(rule, GetNotDistinctLiteral(rule)); return rule; }
public static AssignmentsImpl GetAssignmentsForRule(Implication rule, ISentenceDomainModel model, Dictionary<ISentenceForm, FunctionInfo> functionInfoMap, Dictionary<ISentenceForm, ICollection<Fact>> completedSentenceFormValues) { return new AssignmentsImpl(rule, SentenceDomainModels.GetVarDomains(rule, model, SentenceDomainModels.VarDomainOpts.IncludeHead), functionInfoMap, completedSentenceFormValues); }
public static AssignmentsImpl GetAssignmentsForRule(Implication rule, Dictionary<TermVariable, ISet<TermObject>> varDomains, Dictionary<ISentenceForm, FunctionInfo> functionInfoMap, Dictionary<ISentenceForm, ICollection<Fact>> completedSentenceFormValues) { return new AssignmentsImpl(rule, varDomains, functionInfoMap, completedSentenceFormValues); }
public void PreconditionMissing() { Assert.Throws <BREException>(() => { ImplicationBase ib = new ImplicationBase(); Implication impMedLow = new Implication("impMedLow", 25, String.Empty, "missing", imp2, new AtomGroup(AtomGroup.LogicalOperator.And, atom2_2, atom3)); ib.Add(impMedLow); ib.Add(new Implication("impMedHi", 25, String.Empty, String.Empty, imp2, new AtomGroup(AtomGroup.LogicalOperator.And, atom2_2, atom3))); new PreconditionManager(ib).AnalyzeImplications(); Assert.Fail("Should never reach me!"); }); }
private Expression GetExpression(ParserContext ctx) { skipWhiteSpace(ctx); var a = GetDisjunction(ctx); if (ctx.CurrentPosition != ctx.Text.Length && skipCharacter('-', ctx)) { skipASymbol(ctx); a = new Implication(a, GetExpression(ctx)); } skipWhiteSpace(ctx); return(a); }
public void OperateTwoTest() { Variable p = new Variable('p'); Variable q = new Variable('q'); Implication a = new Implication(); a.Operate(p, q); Assert.AreEqual(p, a.Childs[0]); Assert.AreEqual(q, a.Childs[1]); Assert.ThrowsException <ArgumentNullException>(() => a.Operate(null, null)); }
public void PreconditionIsMutex() { ImplicationBase ib = new ImplicationBase(); Implication impMedLow = new Implication("impMedLow", 25, "impMedHi", String.Empty, imp2, new AtomGroup(AtomGroup.LogicalOperator.And, atom2_2, atom3)); ib.Add(impMedLow); Implication impMedHi = new Implication("impMedHi", 25, String.Empty, "impMedLow", imp2, new AtomGroup(AtomGroup.LogicalOperator.And, atom2_2, atom3)); ib.Add(impMedHi); new MutexManager(ib).AnalyzeImplications(); new PreconditionManager(ib).AnalyzeImplications(); Assert.Fail("Should never reach me!"); }
public void OperateListTest() { List <Variable> vars = new List <Variable>() { new Variable('p'), new Variable('q') }; Implication a = new Implication(); a.Operate(vars); Assert.AreEqual(vars[0], a.Childs[0]); Assert.AreEqual(vars[1], a.Childs[1]); }
public ArrayList GetPreconditionChildren(Implication parentImplication) { ArrayList result = new ArrayList(); foreach (Implication implication in implications) { if (implication.PreconditionImplication == parentImplication) { result.Add(implication); } } return(result); }
/// <summary> /// Schedule a single implication. /// </summary> /// <param name="implication">The implication to schedule.</param> public void Schedule(Implication implication) { if (Logger.IsInferenceEngineVerbose) { Logger.InferenceEngineSource.TraceEvent(TraceEventType.Verbose, 0, "Scheduling one implication: " + implication); } if (!scheduledImplication.Contains(implication)) { scheduledImplication.Add(implication); } }
public void Visit(Implication visitable) { var nandRoot = new Disjunction(); var nandLeft = new Negation(); InsertNodeSingle(nandLeft, visitable.LeftNode); BinaryTree.InsertNode(nandRoot, nandLeft); BinaryTree.InsertNode(nandRoot, visitable.RightNode); Calculate(nandRoot); BinaryTree.Root = nandRoot.Nand; visitable.Nand = nandRoot.Nand; }
public void Agenda() { Agenda a = new Agenda(); Implication impLow = new Implication("impLow", ImplicationPriority.Minimum, String.Empty, String.Empty, imp2, new AtomGroup(AtomGroup.LogicalOperator.And, atom2_2, atom3)); Implication impLowMed = new Implication("impLowMed", 25, String.Empty, String.Empty, imp2, new AtomGroup(AtomGroup.LogicalOperator.And, atom2_2, atom3)); Implication impMed = new Implication("impMed", ImplicationPriority.Medium, String.Empty, String.Empty, imp2, new AtomGroup(AtomGroup.LogicalOperator.And, atom2_2, atom3)); Implication impMedSaLo = new Implication("impMedSaLo", ImplicationPriority.Medium, String.Empty, String.Empty, imp2, new AtomGroup(AtomGroup.LogicalOperator.And, atom2_2, atom3)); impMedSaLo.Salience = 1; Assert.AreEqual(5101, impMedSaLo.Weight, "Weight impMedSaLo"); Implication impMedSaHi = new Implication("impMedSaHi", ImplicationPriority.Medium, String.Empty, String.Empty, imp2, new AtomGroup(AtomGroup.LogicalOperator.And, atom2_2, atom3)); impMedSaHi.Salience = 99; Assert.AreEqual(5199, impMedSaHi.Weight, "Weight impMedSaLo"); Implication impMedHi = new Implication("impMedHi", 75, String.Empty, String.Empty, imp2, new AtomGroup(AtomGroup.LogicalOperator.And, atom2_2, atom3)); Implication impHi = new Implication("impHi", ImplicationPriority.Maximum, String.Empty, String.Empty, imp2, new AtomGroup(AtomGroup.LogicalOperator.And, atom2_2, atom3)); // schedule in any order a.Schedule(impMedSaHi); a.Schedule(impLow); a.Schedule(impMed); a.Schedule(impMedHi); a.Schedule(impMedSaLo); a.Schedule(impLowMed); a.Schedule(impHi); // prepare for execution, which should sort this mess out a.PrepareExecution(); Implication[] expected = new Implication[] { impHi, impMedHi, impMedSaHi, impMedSaLo, impMed, impLowMed, impLow }; int i = 0; Implication implicationParser; while (a.HasMoreToExecute) { implicationParser = a.NextToExecute; Assert.IsTrue(implicationParser.Equals(expected[i]), "Agenda not ordered: " + implicationParser.Label + "::" + implicationParser.Weight + " != " + expected[i].Label + "::" + expected[i].Weight); i++; } }
protected void WriteImplication(XmlElement target, Implication implication) { XmlElement implicationElement = Document.CreateElement("Implies", DatalogNamespaceURL); // action mapping String action = String.Empty; if (implication.Action != ImplicationAction.Assert) { action = implication.Action.ToString().ToLower(); } ImplicationProperties ip = new ImplicationProperties(implication.Label, implication.Priority, implication.Mutex, implication.Precondition, action); WriteLabel(implicationElement, ip.ToString()); if (syntax == SaveFormatAttributes.Compact) { // in compact mode, the order is forced to body,head (equivalent to if,then) WriteAtomGroup(implicationElement, implication.AtomGroup); WriteAtom(implicationElement, implication.Deduction, false); } else { XmlElement body = Document.CreateElement("body", DatalogNamespaceURL); WriteAtomGroup(body, implication.AtomGroup); implicationElement.AppendChild(body); XmlElement head = Document.CreateElement("head", DatalogNamespaceURL); WriteAtom(head, implication.Deduction, false); implicationElement.AppendChild(head); } if (syntax == SaveFormatAttributes.Expanded) { XmlElement formula = Document.CreateElement("formula", DatalogNamespaceURL); formula.AppendChild(implicationElement); target.AppendChild(formula); } else { target.AppendChild(implicationElement); } }
public RuleReference(Implication originalRule, IEnumerable<PropNetFlattener.Condition> conditions, IList<Term> productionTemplate = null) { OriginalRule = originalRule; ProductionTemplate = productionTemplate==null ? ImmutableList<Term>.Empty : productionTemplate.ToImmutableList(); Conditions = conditions.ToImmutableList(); int producttionTemplateHashCode = 1; if (productionTemplate != null) foreach (Term term in productionTemplate) producttionTemplateHashCode = 31 * producttionTemplateHashCode + (term == null ? 0 : term.GetHashCode()); int conditionsHashcode = Conditions.Aggregate(1, (current, cond) => 31 * current + (cond == null ? 0 : cond.GetHashCode())); _hashCode = producttionTemplateHashCode + conditionsHashcode; }
public void GetPreconditionChildren() { ImplicationBase ib = new ImplicationBase(); Implication impMedLow = new Implication("impMedLow", 25, String.Empty, String.Empty, imp2, new AtomGroup(AtomGroup.LogicalOperator.And, atom2_2, atom3)); ib.Add(impMedLow); Implication impMedHi = new Implication("impMedHi", 25, String.Empty, "impMedLow", imp2, new AtomGroup(AtomGroup.LogicalOperator.And, atom2_2, atom3)); ib.Add(impMedHi); new PreconditionManager(ib).AnalyzeImplications(); IList <Implication> preconditionChildren = ib.GetPreconditionChildren(impMedLow); Assert.AreEqual(1, preconditionChildren.Count, "preconditionChildren size"); Assert.IsTrue(preconditionChildren.Contains(impMedHi), "preconditionChildren content"); }
public void QueryIsNotImplication() { Query query = new Query("get spending", new AtomGroup(AtomGroup.LogicalOperator.And, new Atom("spending", new Variable("customer"), new Individual("min(5000,EUR)"), new Individual("previous year")))); Implication implication = new Implication("get spending", ImplicationPriority.Medium, String.Empty, String.Empty, atom2_2, query.AtomGroup); Assert.IsFalse(query.Equals(implication), "QueryIsNotImplication"); }
public static List<Formula> BuildProof(Formula f) { var variables = f.Variables.ToArray(); Array.Sort(variables); var result = new List<Formula>(); for (int i = 0; i < 1 << variables.Length; ++i) { bool[] values = new bool[variables.Length]; for (int j = variables.Length - 1; j >= 0; --j) values[variables.Length - 1 - j] = ((i >> j) & 1) == 1; var variablesEvaluation = new Dictionary<PropositionalVariable, bool>(); for (int j = 0; j < variables.Length; j++) variablesEvaluation.Add(variables[j], values[j]); var partialProof = WriteProofInPartsEvaluation(f, variablesEvaluation); var assumptions = variablesEvaluation.Select(x => (x.Value ? x.Key as Formula : new Inversion(x.Key))).ToList(); result.AddRange(ConvertAssumptions(assumptions, partialProof)); } for (int i = 0; i < variables.Length; ++i) { result.AddRange(Formula.InlineAll(ProofBuildingResources.TND, new Dictionary<PropositionalVariable, Formula> { {"A", variables[i]} })); for (int j = 0; j < 1 << variables.Length - 1 - i; ++j) { int otherVarsCount = variables.Length - 1 - i; Formula fWithOtherVars = f; bool[] values = new bool[otherVarsCount]; for (int k = 0; k<otherVarsCount; ++k) values[k] = ((j >> k) & 1) == 1; for (int k = 0; k < otherVarsCount; ++k) fWithOtherVars = new Implication( values[k]? variables[variables.Length-1-k] as Formula: new Inversion(variables[variables.Length-1-k]), fWithOtherVars); result.AddRange(Formula.InlineAll(ProofBuildingResources.AEx, new Dictionary<PropositionalVariable, Formula> { {"A", fWithOtherVars}, {"V", variables[i]} })); } } return result; }
private static Implication RemoveNotDistinctLiteral(Implication rule, Negation notDistinctLiteral) { //Figure out the substitution we want... //If we have two constantsin Either Remove one or //maybe get rid of the ___? //One is a variablein Replace the variable with the other thing //throughout the rule var distinct = (Fact)notDistinctLiteral.Negated; Term arg1 = distinct.GetTerm(0); Term arg2 = distinct.GetTerm(1); if (arg1 == arg2) { //Just Remove that literal var newBody = new List<Expression>(); newBody.AddRange(rule.Antecedents.Conjuncts); newBody.Remove(notDistinctLiteral); return new Implication(rule.Consequent, newBody.ToArray()); } var p1 = arg1 as TermVariable; if (p1 != null) { //What we return will still have the not-distinct literal, //but it will get replaced in the next pass. //(Even if we have two variables, they will be equal next time through.) var sub = new Substitution(); sub.AddMapping(p1, arg2); return (Implication)rule.ApplySubstitution(sub); } var variable = arg2 as TermVariable; if (variable != null) { var sub = new Substitution(); sub.AddMapping(variable, arg1); return (Implication)rule.ApplySubstitution(sub); } if (arg1 is TermObject || arg2 is TermObject) { //We have two non-equal constants, or a constant and a function. //The rule should have no effect. return null; } //We have two functions. Complicated! (Have to replace them with unified version.) //We pass on this case for now. //TODO: Implement correctly. throw new Exception("We can't currently handle (not (distinct <function> <function>))."); }
public void ImplicationConstructorTest1() { Variable p = new Variable('p'); Variable q = new Variable('q'); Implication a = new Implication(p, q); Assert.IsNotNull(a.Childs); Assert.AreEqual('>', a.Name); Assert.AreEqual(2, a.nOperand); Assert.AreEqual(SymbolType.operational, a.Type); Assert.AreEqual(p, a.Childs[0]); Assert.AreEqual(q, a.Childs[1]); // Assert.ThrowsException <ArgumentNullException>(() => new Implication(null, null)); }
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; }
private static Negation GetNotDistinctLiteral(Implication rule) { foreach (Expression literal in rule.Antecedents.Conjuncts) { var not = literal as Negation; if (not != null) { var negated = not.Negated as Fact; if (negated != null && (negated.RelationName == GameContainer.Parser.TokDistinct)) { //For now, we can only deal with this if not both are functions. //That means we have to skip that case at this point. if (!(negated.GetTerm(0) is TermFunction) || !(negated.GetTerm(1) is TermFunction)) return not; } } } return null; }
public void GetTruthValueArrayTest() { Variable p = new Variable('p'); Variable q = new Variable('q'); Implication a = new Implication(p, q); bool[] dict = new bool[130]; for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { dict['p'] = i == 1; dict['q'] = j == 1; Assert.AreEqual(((i ^ 1) | j) == 1, a.GetTruthValue(dict)); } } }
public void ToStringTest() { Variable p = new Variable('p'); Variable q = new Variable('q'); Implication a = new Implication(p, q); Assert.AreEqual("(p > q)", a.ToString()); Not Left = new Not(p); Or Right = new Or(p, q); a.Operate(Left, Right); Assert.AreEqual("(~p > (p | q))", a.ToString()); Left = new Not(new Nand(p, q)); a.Operate(Left, Right); Assert.AreEqual("(~(p % q) > (p | q))", a.ToString()); }
public void Constructor_CreateBetaRuleFromImplicationOfLiterals_SetOfLengthOneForEachChildWithOneNegatedLiteral() { // Arrange Implication implication = (Implication)PropositionGenerator.CreateBinaryConnectiveWithRandomSymbols(Implication.SYMBOL); HashSet <Proposition> propositions = new HashSet <Proposition>() { implication }; SemanticTableauxElement betaRuleElement = new SemanticTableauxElement(propositions); SemanticTableauxElement leftChild = betaRuleElement.LeftChild; SemanticTableauxElement rightChild = betaRuleElement.RightChild; // Act HashSet <Proposition> leftChildPropositions = leftChild.Propositions; HashSet <Proposition> rightChildPropositions = rightChild.Propositions; int actualNumberOfLiteralsInLeftChild = leftChildPropositions.Count; int actualNumberOfLiteralsInRightChild = rightChildPropositions.Count; int expectedNumberOfLiterals = 1; // Assert string message = "Because both proposition literals have been separated into two different sets"; actualNumberOfLiteralsInLeftChild.Should().Be(expectedNumberOfLiterals, message); actualNumberOfLiteralsInRightChild.Should().Be(expectedNumberOfLiterals, message); message = "Because based on the rule, the left child should be negated only."; foreach (Proposition proposition in leftChildPropositions) { proposition.Should().BeOfType <Negation>(message); } foreach (Proposition proposition in rightChildPropositions) { proposition.Should().Be(implication.RightSuccessor, message); } }
public void Constructor_CreateAlphaRuleFromNegationOfImplicationOfLiterals_SetOfLengthTwoReturnedWithRightSuccessorNegated() { // Arrange Implication implication = (Implication)PropositionGenerator.CreateBinaryConnectiveWithRandomSymbols(Implication.SYMBOL); Negation negatedImplication = new Negation(); negatedImplication.LeftSuccessor = implication; HashSet <Proposition> propositions = new HashSet <Proposition>() { negatedImplication }; SemanticTableauxElement alphaRuleElement = new SemanticTableauxElement(propositions); SemanticTableauxElement child = alphaRuleElement.LeftChild; // Act HashSet <Proposition> childPropositions = child.Propositions; int actualNumberOfLiterals = childPropositions.Count; int expectedNumberOfLiterals = 2; // Assert actualNumberOfLiterals.Should().Be(expectedNumberOfLiterals, "Because an implication of two literals was given"); foreach (Proposition proposition in childPropositions) { if (proposition.GetType() == typeof(Negation)) { Negation negatedLiteral = (Negation)proposition; negatedLiteral.LeftSuccessor.CompareTo(implication.RightSuccessor).Should().Be(0, "Because it is right negated successor of the implication."); } else { proposition.CompareTo(implication.LeftSuccessor).Should().Be(0, "Because it is the left not negated successor of the implication."); } } }
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 void GetTruthValueDictTest() { Variable p = new Variable('p'); Variable q = new Variable('q'); Implication a = new Implication(p, q); Dictionary <char, bool> dict = new Dictionary <char, bool>(); for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { dict['p'] = i == 1; dict['q'] = j == 1; Assert.AreEqual(((i ^ 1) | j) == 1, a.GetTruthValue(dict)); } } dict.Remove('p'); Assert.ThrowsException <KeyNotFoundException>( () => a.GetTruthValue(dict)); }
private static bool ImplicationsShareConsequent(Implication implication1, Implication implication2) { return(implication1.Consequent.Equals(implication2.Consequent)); }
private static Implication CleanParentheses(Implication rule) { Fact cleanedHead = CleanParentheses(rule.Consequent); Expression[] cleanedBody = rule.Antecedents.Conjuncts.Select(CleanParentheses).ToArray(); return new Implication(cleanedHead, cleanedBody); }
private static bool ImplicationsShareAntecedent(Implication implication1, Implication implication2) { return(implication1.Antecedent.Equals(implication2.Antecedent)); }
internal static IEventContext NewEventContext(IList <FactBase.PositiveMatchResult> facts, Implication implication) { IList <IList <Fact> > wrappedFacts = new List <IList <Fact> >(); wrappedFacts.Add(FactBase.ExtractFacts(facts)); return(new ImmutableEventContext(wrappedFacts, implication)); }
private bool NotApplicable <World>(Implication implication, World world) { return(EvaluateAgainst(implication.Antecedent, world) == false); }
private static bool IsRecursive(Implication rule) { return rule.Antecedents.Conjuncts.OfType<Fact>().Any(literal => literal.RelationName.Equals(rule.Consequent.RelationName)); }
public ImmutableEventContext(IList <IList <Fact> > facts, Implication implication) { this.facts = facts; this.implication = implication; }
public static Implication Substitute(Implication rule, Substitution theta) { return SubstituteRule(rule, theta); }
private static HashSet<TermVariable> GetVarsInLiveConjuncts(Implication rule, ISet<ISentenceForm> constantSentenceForms) { var result = new HashSet<TermVariable>(); foreach (var literal in rule.Antecedents.Constituents) { var fact = literal as Fact; if (fact != null) { if (!InSentenceFormGroup(fact, constantSentenceForms)) result.UnionWith(fact.VariablesOrEmpty); } else { var not = literal as Negation; if (not != null && !InSentenceFormGroup((Fact) not.Negated, constantSentenceForms)) result.UnionWith(not.VariablesOrEmpty); } } return result; }
public Implication Rename(Implication rule) { return RenameRule(rule, new Dictionary<TermVariable, TermVariable>()); }
private Implication RenameRule(Implication rule, Dictionary<TermVariable, TermVariable> renamings) { if (!rule.VariablesOrEmpty.Any()) return rule; Fact head = RenameSentence(rule.Consequent, renamings); List<Expression> body = new List<Expression>(); for (int i = 0; i < rule.NumAntecedents(); i++) body.Add(RenameLiteral(rule.Constituents[i], renamings)); return new Implication(head, body.ToArray()); }
private static ISet<Expression> GetCondensationSet(Implication rule, ISentenceDomain model, IConstantChecker checker, UnusedSentenceNameSource sentenceNameSource) { //We use each variable as a starting point List<TermVariable> varsInRule = rule.VariablesOrEmpty.ToList(); List<TermVariable> varsInHead = rule.Consequent.VariablesOrEmpty.ToList(); var varsNotInHead = new List<TermVariable>(varsInRule); varsNotInHead.RemoveAll(varsInHead.Contains); foreach (TermVariable var in varsNotInHead) { var minSet = new HashSet<Expression>(); foreach (Expression literal in rule.Antecedents.Conjuncts) if (literal.VariablesOrEmpty.Contains(var)) minSet.Add(literal); //#1 is already done //Now we try #2 var varsNeeded = new HashSet<TermVariable>(); var varsSupplied = new HashSet<TermVariable>(); foreach (Expression literal in minSet) { if (literal is Negation) { foreach (var variable in literal.VariablesOrEmpty) varsNeeded.Add(variable); } else if (literal is Fact) { if (((Fact)literal).RelationName == GameContainer.Parser.TokDistinct) foreach (var variable in literal.VariablesOrEmpty) varsNeeded.Add(variable); else foreach (var variable in literal.VariablesOrEmpty) varsSupplied.Add(variable); } } varsNeeded.RemoveWhere(varsSupplied.Contains); if (varsNeeded.Any()) continue; var candidateSuppliersList = new List<ISet<Expression>>(); foreach (TermVariable varNeeded in varsNeeded) { var suppliers = new HashSet<Expression>(); foreach (Expression literal in rule.Antecedents.Conjuncts) if (literal is Fact) if (literal.VariablesOrEmpty.Contains(varNeeded)) suppliers.Add(literal); candidateSuppliersList.Add(suppliers); } //TODO: Now... I'm not sure if we want to minimize the number of literals added, or the number of variables added //Right now, I don't have time to worry about optimization. Currently, we pick one at random //TODO: Optimize this var literalsToAdd = new HashSet<Expression>(); foreach (ISet<Expression> suppliers in candidateSuppliersList) if (!suppliers.Intersect(literalsToAdd).Any()) literalsToAdd.Add(suppliers.First()); minSet.UnionWith(literalsToAdd); if (GoodCondensationSetByHeuristic(minSet, rule, model, checker, sentenceNameSource)) return minSet; } return null; }
private static Implication ReorderRule(Implication oldRule) { var newBody = new List<Expression>(oldRule.Antecedents.Constituents); RearrangeDistinctsAndNots(newBody); return new Implication(oldRule.Consequent, newBody.ToArray()); }
private static Implication SubstituteRule(Implication rule, Substitution theta) { Fact head = Substitute(rule.Consequent, theta); return new Implication(head, rule.Constituents.Select(literal => SubstituteLiteral(literal, theta)).ToArray()); }
public IFormula visit(Implication f) { throw new Exception(); }
private static void VisitRule(Implication rule, GdlVisitor visitor) { visitor.VisitRule(rule); VisitAll(rule.Consequent, visitor); VisitAll(rule.Antecedents.Constituents, visitor); }
private void AddRule(int headRelation, Implication r) { if (!_rules.Contains(headRelation)) _rules[headRelation] = new List<Implication>(); _rules[headRelation].Add(r); }
private static Implication SortDistincts(Implication rule) { return new Implication(rule.Consequent, SortDistincts(rule.Antecedents.Conjuncts)); }
private static bool GoodCondensationSetByHeuristic(ICollection<Expression> minSet, Implication rule, ISentenceDomain model, IConstantChecker checker, UnusedSentenceNameSource sentenceNameSource) { //We actually want the sentence model here so we can see the domains //also, if it's a constant, ... //Anyway... we want to compare the heuristic for the number of assignments //and/or links that will be generated with or without the condensation set //Heuristic for a rule is A*(L+1), where A is the number of assignments and //L is the number of literals, unless L = 1, in which case the heuristic is //just A. This roughly captures the number of links that would be generated //if this rule were to be generated. //Obviously, there are differing degrees of accuracy with which we can //represent A. //One way is taking the product of all the variables in all the domains. //However, we can do better by actually asking the Assignments class for //its own heuristic of how it would implement the rule as-is. //The only tricky aspect here is that we need an up-to-date SentenceModel, //and in some cases this could be expensive to compute. Might as well try //it, though... //Heuristic for the rule as-is: long assignments = AssignmentsImpl.GetNumAssignmentsEstimate(rule, SentenceDomainModels.GetVarDomains(rule, model, SentenceDomainModels.VarDomainOpts.IncludeHead), checker); int literals = rule.Consequent.Arity; if (literals > 1) literals++; //We have to "and" the literals together //Note that even though constants will be factored out, we're concerned here //with getting through them in a reasonable amount of time, so we do want to //count them. TODO: Not sure if they should be counted in L, though... long curRuleHeuristic = assignments * literals; //And if we split them up... List<Implication> newRules = ApplyCondensation(minSet, rule, sentenceNameSource); Implication r1 = newRules[0], r2 = newRules[1]; //Augment the model ISentenceDomain newModel = AugmentModelWithNewForm(model, newRules); long a1 = AssignmentsImpl.GetNumAssignmentsEstimate(r1, SentenceDomainModels.GetVarDomains(r1, newModel, SentenceDomainModels.VarDomainOpts.IncludeHead), checker); long a2 = AssignmentsImpl.GetNumAssignmentsEstimate(r2, SentenceDomainModels.GetVarDomains(r2, newModel, SentenceDomainModels.VarDomainOpts.IncludeHead), checker); int l1 = r1.Consequent.Arity; if (l1 > 1) l1++; int l2 = r2.Consequent.Arity; if (l2 > 1) l2++; //Whether we split or not depends on what the two heuristics say long newRulesHeuristic = a1 * l1 + a2 * l2; return newRulesHeuristic < curRuleHeuristic; }
private void InferUntilNoNewFact(ArrayList positiveImplications) { long iniTime; if (HasLogListener) { ForceDispatchLog("(Starting) " + ((WM.Type == WorkingMemoryTypes.Global)?"Global":"Isolated") + "Working Memory contains: " + WM.FB.Count + " facts, " + IB.Count + " implications, " + QB.Count + " queries.", LogEventImpl.DEBUG); } iniTime = DateTime.Now.Ticks; ArrayList iterationPositiveImplications = null; bool iterate = true; Agenda agenda = new Agenda(); // Loop as long as there are new deduction made while (iterate) { if (iteration >= IterationLimit) { throw new BREException("Maximum limit of iterations reached: " + IterationLimit); } iterate = false; iteration++; // Schedule all implications matching the existing facts agenda.Schedule(iterationPositiveImplications, IB); agenda.PrepareExecution(); if (HasLogListener) { ForceDispatchLog("Iteration #" + iteration + ": " + agenda.Count + " implications in agenda, with " + positiveImplications.Count + " positive.", LogEventImpl.DEBUG); } iterationPositiveImplications = new ArrayList(); while (agenda.HasMoreToExecute) { Implication firedImplication = agenda.NextToExecute; // check if this implication is worth processing: // first: see if it is not mutexed by a previously positive implication if ((firedImplication.MutexChain != null) && (!positiveImplications.Contains(firedImplication)) && (Misc.AreIntersecting(firedImplication.MutexChain, positiveImplications))) { if (HasLogListener) { ForceDispatchLog("Mutexed: " + firedImplication.Label, LogEventImpl.DEBUG); } firedImplication = null; } // second: see if it is not pre-condition disabled by a previously negative implication if ((firedImplication != null) && (firedImplication.PreconditionImplication != null) && (!positiveImplications.Contains(firedImplication.PreconditionImplication))) { if (HasLogListener) { ForceDispatchLog("Negative Precondition: " + firedImplication.Label, LogEventImpl.DEBUG); } firedImplication = null; } if (firedImplication != null) { WM.FB.ModifiedFlag = false; int resultsCount = RunImplication(firedImplication); if (HasLogListener) { ForceDispatchLog("Fired Implication: " + firedImplication.ToString() + " returned: " + resultsCount, LogEventImpl.DEBUG); } // if processor has been positive, i.e an implication deducted at least one fact if (resultsCount > 0) { positiveImplications.Add(firedImplication); } // if the fact base has been anyhow modified if (WM.FB.ModifiedFlag) { iterationPositiveImplications.Add(firedImplication); } } } // while agenda has more // if at least one is accepted ask for another processing iteration iterate = (iterationPositiveImplications.Count > 0); } // while iterate // perform integrity checks foreach (Query integrityQuery in IntegrityQueries) { QueryResultSet qrs = RunQuery(integrityQuery); if (qrs.Count == 0) { throw new IntegrityException("Rulebase integrity violated: " + integrityQuery.Label); } } if (HasLogListener) { ForceDispatchLog("NxBRE Inference Engine Execution Time: " + (long)(DateTime.Now.Ticks - iniTime) / 10000 + " milliseconds", LogEventImpl.INFO); } if (HasLogListener) { ForceDispatchLog("(Finishing) " + ((WM.Type == WorkingMemoryTypes.Global)?"Global":"Isolated") + "Working Memory contains: " + WM.FB.Count + " facts, " + IB.Count + " implications, " + QB.Count + " queries.", LogEventImpl.DEBUG); } }
internal static IEventContext NewEventContext(IList <IList <FactBase.PositiveMatchResult> > facts, Implication implication) { return(new ImmutableEventContext(FactBase.ExtractFacts(facts), implication)); }
private bool AddRule(Implication rule) { // Stuff can make it into the head sentence form either as part of the head of the rule as presented or due to a // variable connected to the positive literals in the rule. (In the latter case, it should be in the intersection // of the models of all such positive literals.) For each slot in the body, we want to set up everything that will // be injected into it. Fact headSentence = rule.Consequent; // We need to get the possible contents of variables beforehand, to deal with the case of variables being inside functions. Dictionary<TermVariable, TermModel> varsToModelsMap = GetVarsToModelsMap(rule); return AddSentenceToModel(headSentence, varsToModelsMap); }
public IFormula visit(Implication f) { return(new And(f.f1.visit(p), f.f2.visit(n))); }
private Dictionary<TermVariable, TermModel> GetVarsToModelsMap(Implication rule) { var varsToUse = new HashSet<TermVariable>(rule.Consequent.VariablesOrEmpty); var varsToModelsMap = new Dictionary<TermVariable, TermModel>(); foreach (TermVariable var in varsToUse) varsToModelsMap[var] = new TermModel(); foreach (Expression literal in rule.Antecedents.Conjuncts) { var fact = literal as Fact; if (fact != null) { List<Term> literalBody = fact.GetTerms(); var nameAndArity = new NameAndArity(fact); SentencesModel.CreateIfRequired(nameAndArity); List<TermModel> literalModel = SentencesModel[nameAndArity]; AddVariablesToMap(literalBody, literalModel, varsToModelsMap); } } return varsToModelsMap; }
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); }
/// <summary> /// Converts a rule into equivalent PropNet Components by invoking the /// <tt>convertHead()</tt> method on the head, and the /// <tt>convertConjunct</tt> method on every literal in the body and /// joining the results by an and gate. /// </summary> /// <param name="rule">The rule to convert.</param> private void ConvertRule(Implication rule) { IProposition head = ConvertHead(rule.Consequent); IAnd and = _componentFactory.CreateAnd(); Link(and, head); _components.Add(head); _components.Add(and); foreach (Expression literal in rule.Antecedents.Conjuncts) Link(ConvertConjunct(literal), and); }
public void ImplicationToStringTest1() { var eq = new Implication(new Bool(true), new Bool(false)); Assert.Equal("True => False", eq.ToString(commoonFormatter)); }
/// <summary> /// Searches the description for statements that are needlessly treated as base propositions when they could be /// expressed as simple relations, and replaces them with these simpler forms. /// /// Some games have been written such that unchanging facts of the game are listed as base propositions. Often, this /// is so the fact can be accessed by a visualization. Gamers usually don't need this distinction, and can reduce /// the costs in time and memory of processing the game if these statements are instead transformed into sentences. /// </summary> /// <param name="description"></param> /// <returns></returns> public static List<Expression> Run(IList<Expression> description) { ImmutableSentenceFormModel model = SentenceFormModelFactory.Create(description); int next = GameContainer.Parser.TokNext; var nextFormsToReplace = new List<ISentenceForm>(); IEnumerable<ISentenceForm> nextForms = model.SentenceForms.Where(m => m.Name.Equals(next)); //Find the update rules for each "true" statement foreach (ISentenceForm nextForm in nextForms) { //See if there is exactly one update rule, and it is the persistence rule ISet<Implication> updateRules = model.GetRules(nextForm); if (updateRules.Count == 1) { Implication updateRule = updateRules.First(); //Persistence rule: Exactly one literal, the "true" form of the sentence if (updateRule.Antecedents.Constituents.Length == 1) { Expression literal = updateRule.Antecedents.Constituents[0]; var body = literal as Fact; if (body!=null) { //Check that it really is the true form ISentenceForm trueForm = nextForm.WithName(GameContainer.Parser.TokTrue); if (trueForm.Matches(body)) { Fact head = updateRule.Consequent; //Check that the tuples are the same, and that they consist of distinct variables List<Term> headTuple = head.NestedTerms.ToList(); List<Term> bodyTuple = body.NestedTerms.ToList(); if (headTuple.Equals(bodyTuple) && headTuple.Distinct().Count() == headTuple.Count) nextFormsToReplace.Add(nextForm); } } } } } var newDescription = new List<Expression>(description); //Now, replace the next forms foreach (ISentenceForm nextForm in nextFormsToReplace) { ISentenceForm initForm = nextForm.WithName(GameContainer.Parser.TokInit); ISentenceForm trueForm = nextForm.WithName(GameContainer.Parser.TokTrue); //Go through the rules and relations, making replacements as needed for (int i = 0; i < newDescription.Count; i++) { Expression gdl = newDescription[i]; var relation = gdl as Fact; if (relation != null) { //Replace initForm if (initForm.Matches(relation)) { var terms = relation.GetTerms(); var function = terms[0] as TermFunction; Debug.Assert(function != null); newDescription[i] = new VariableFact(true, function.FunctionName, function.Arguments); } } else if (gdl is Implication) { var rule = (Implication)gdl; //Remove persistence rule (i.e. rule with next form as head) Fact head = rule.Consequent; if (nextForm.Matches(head)) newDescription.RemoveAt(i--); else { //Replace true in bodies of rules with relation-only form List<Expression> body = rule.Antecedents.Constituents.ToList(); List<Expression> newBody = ReplaceRelationInBody(body, trueForm); if (!body.Equals(newBody)) newDescription[i] = new Implication(head, newBody.ToArray()); } } } } return newDescription; }
public double Satisfy (State s, Implication imply) { var satAntecedant = Satisfy (s, imply.Left); var satConsequent = Satisfy (s, imply.Right); return satAntecedant * satConsequent + (1 - satAntecedant); }
private int RunImplication(Implication implication) { int implicationResultsCount = 0; FactBase.ProcessResultSet processResults = WM.FB.ProcessAtomGroup(implication.AtomGroup); if (implication.Action == ImplicationAction.Count) { if (HasLogListener) { ForceDispatchLog("Counting Implication '" + implication.Label + "' counted: " + processResults.Count, LogEventImpl.DEBUG); } bool variableFound = false; IPredicate[] members = (IPredicate[])implication.Deduction.Members.Clone(); for (int i = 0; !variableFound && i < members.Length; i++) { if (members[i] is Variable) { members[i] = new Individual(processResults.Count); variableFound = true; break; } } if ((IEImpl.StrictImplication) && (!variableFound)) { throw new BREException("Strict counting implication rejected the assertion due to lack of variable predicate: " + implication.Deduction); } Fact deductedFact = new Fact(implication.Deduction.Type, members); implicationResultsCount++; // counting implication factbase action bool result = WM.FB.Assert(deductedFact); if ((result) && (NewFactHandler != null)) { NewFactHandler(new NewFactEventArgs(deductedFact)); } if (HasLogListener) { ForceDispatchLog((result?"Asserted":"Ignored Assertion of ") + " Fact: " + deductedFact.ToString(), LogEventImpl.DEBUG); } } else if ((implication.Action == ImplicationAction.Assert) || (implication.Action == ImplicationAction.Retract)) { // loop on each result and try to build a new fact out of the predicates coming for each result foreach (ArrayList processResult in processResults) { Fact deductedFact = BuildFact(implication.Deduction, processResult); if (deductedFact != null) { implicationResultsCount++; if (implication.Action == ImplicationAction.Retract) { // retracting implication factbase action bool result = WM.FB.Retract(deductedFact); if ((result) && (DeleteFactHandler != null)) { DeleteFactHandler(new NewFactEventArgs(deductedFact)); } if (HasLogListener) { ForceDispatchLog((result?"Retracted":"Ignored Retraction of ") + " Fact: " + deductedFact.ToString(), LogEventImpl.DEBUG); } } else { // asserting implication factbase action bool result = WM.FB.Assert(deductedFact); if ((result) && (NewFactHandler != null)) { NewFactHandler(new NewFactEventArgs(deductedFact)); } if (HasLogListener) { ForceDispatchLog((result?"Asserted":"Ignored Assertion of ") + " Fact: " + deductedFact.ToString(), LogEventImpl.DEBUG); } } } } } else if (implication.Action == ImplicationAction.Modify) { foreach (ArrayList processResult in processResults) { // look for facts to modify by: // - resolving variable predicates of the deduction // - replacing formulas with variables // and performing a search in the fact base Atom modificationTargetLookup = FactBase.BuildQueryFromDeduction(implication.Deduction, processResult); if (HasLogListener) { ForceDispatchLog("Modifying Implication '" + implication.Label + "' will target matches of: " + modificationTargetLookup, LogEventImpl.DEBUG); } foreach (Fact factToModify in FactBase.ExtractFacts(WM.FB.ProcessAtomGroup(new AtomGroup(AtomGroup.LogicalOperator.And, modificationTargetLookup)))) { if (HasLogListener) { ForceDispatchLog("-> found target: " + factToModify, LogEventImpl.DEBUG); } // for each fact, perform the modification Fact deductedFact = BuildFact(implication.Deduction, FactBase.EnrichResults(processResult, modificationTargetLookup, factToModify)); if (HasLogListener) { ForceDispatchLog("-> modified target: " + deductedFact, LogEventImpl.DEBUG); } if ((deductedFact != null) && (!factToModify.Equals(deductedFact))) { implicationResultsCount++; bool result = WM.FB.Modify(factToModify, deductedFact); if ((result) && (ModifyFactHandler != null)) { ModifyFactHandler(new NewFactEventArgs(factToModify, deductedFact)); } if (HasLogListener) { ForceDispatchLog((result?"Modified":"Ignored Modification of ") + " Fact: " + factToModify.ToString(), LogEventImpl.DEBUG); } } } } } else { throw new BREException("Implication action not supported: " + implication.Action); } return(implicationResultsCount); }
/// <summary> /// Analyzes the specified expression. /// </summary> /// <param name="exp">The expression.</param> /// <returns> /// The result of analysis. /// </returns> /// <exception cref="System.NotSupportedException">Always.</exception> public virtual TResult Analyze(Implication exp) { throw new NotSupportedException(); }
private static List<Implication> ApplyCondensation(ICollection<Expression> condensationSet, Implication rule, UnusedSentenceNameSource sentenceNameSource) { var varsInCondensationSet = new HashSet<TermVariable>(); foreach (Expression literal in condensationSet) foreach (var variable in literal.VariablesOrEmpty) varsInCondensationSet.Add(variable); var varsToKeep = new HashSet<TermVariable>(); //Which vars do we "keep" (put in our new condensed literal)? //Vars that are both: //1) In the condensation set, in a non-mutex literal //2) Either in the head or somewhere else outside the condensation set foreach (Expression literal in condensationSet) foreach (var variable in literal.VariablesOrEmpty) varsToKeep.Add(variable); var varsToKeep2 = new HashSet<TermVariable>(); foreach (var variable in rule.Consequent.VariablesOrEmpty) varsToKeep2.Add(variable); foreach (Expression literal in rule.Antecedents.Conjuncts) if (!condensationSet.Contains(literal)) foreach (var variable in literal.VariablesOrEmpty) varsToKeep2.Add(variable); varsToKeep.IntersectWith(varsToKeep2); //Now we're ready to split it apart //Let's make the new rule var orderedVars = new List<Term>(varsToKeep); int condenserName = sentenceNameSource.GetNameWithPrefix(rule.Consequent.RelationName); //Make the rule head var condenserHead = new VariableFact(false, condenserName, orderedVars.ToArray()); var condenserBody = new List<Expression>(condensationSet); var condenserRule = new Implication(condenserHead, condenserBody.ToArray()); //TODO: Look for existing rules matching the new one var remainingLiterals = rule.Antecedents.Conjuncts.Where(literal => !condensationSet.Contains(literal)).ToList(); remainingLiterals.Add(condenserHead); var modifiedRule = new Implication(rule.Consequent, remainingLiterals.ToArray()); var newRules = new List<Implication>(2) { condenserRule, modifiedRule }; return newRules; }