/// <summary> /// Build an atom for querying facts on the basis of an implication deduction, whose individual /// predicates will be replaced by variables and whose variables will be resolved from values /// coming from an implication result stack. /// </summary> /// <param name="targetAtom">The implication deduction atom.</param> /// <param name="resultStack">The implication result stack.</param> /// <returns>The atom ready for querying facts.</returns> public static Atom BuildQueryFromDeduction(Atom targetAtom, ArrayList resultStack) { IPredicate[] members = (IPredicate[])targetAtom.Members.Clone(); // populate the variable elements with predicate values coming // from the query part of the implication foreach(ResultPocket rp in resultStack) Fact.Populate(rp.fact, rp.source, members); if ((targetAtom.HasFormula) || (targetAtom.HasIndividual)) { // formulas and individuals must be replaced by variables // named after the position of the predicate for(int i=0; i<members.Length; i++) { if (members[i] is Formula) members[i] = new Variable(i); // Individuals present in the deduction are static values (compared to values coming from // variables) and must be transformed into variables in order to perform a selection of // potentially matching facts. // To the contrary, Variables, resolved with values coming from the body part of the implication // must be used to search matching facts. else if (targetAtom.Members[i] is Individual) members[i] = new Variable(i.ToString()); } } // clone the target with new members, because atom is immutable return targetAtom.CloneWithNewMembers(members); }
public static Atom Populate(Atom targetAtom, ArrayList resultStack, bool evaluateFormulas) { IPredicate[] members = (IPredicate[])targetAtom.Members.Clone(); // populate the variable elements with predicate values coming // from the query part of the implication foreach(ResultPocket rp in resultStack) if (!(rp.fact is FactBase.NegativeFact)) Fact.Populate(rp.fact, rp.source, members); // if there are formulas in the atom, resolve these expressions, passing // the variable values as arguments if (targetAtom.HasFormula) { if (evaluateFormulas) { // formulas must be evaluated and the results placed in individual predicates IDictionary arguments = new Hashtable(); foreach(ResultPocket rp in resultStack) { if (!(rp.fact is FactBase.NegativeFact)) { for(int i=0; i<rp.source.Members.Length; i++) { object sourcePredicateKey = null; if (rp.source.Members[i] is Variable) { sourcePredicateKey = rp.source.Members[i].Value; } else if (rp.source.SlotNames[i] != String.Empty) { sourcePredicateKey = rp.source.SlotNames[i]; } if ((sourcePredicateKey != null) && (!arguments.Contains(sourcePredicateKey))) arguments.Add(sourcePredicateKey, rp.fact.Members[i].Value); } } } for(int i=0; i<members.Length; i++) if (members[i] is Formula) members[i] = new Individual(((Formula) members[i]).Evaluate(arguments)); } else { // formulas must be replaced by variables named after the position of the predicate for(int i=0; i<members.Length; i++) if (members[i] is Formula) members[i] = new Variable(i.ToString()); } } // clone the target with new members, because atom is immutable return targetAtom.CloneWithNewMembers(members); }
public void Predicates() { IPredicate v1 = new Variable("one"); IPredicate v2 = new Variable("two"); IPredicate i1 = new Individual("one"); IPredicate i2 = new Individual("two"); Assert.AreEqual(v1, new Variable("one"), "Similar Variables"); Assert.IsFalse(v1.Equals(v2), "Different Variables"); Assert.IsFalse(v1.Equals(i2), "Variable differs from Individual"); Assert.AreEqual(i1, new Individual("one"), "Similar Individuals"); Assert.IsFalse(i1.Equals(i2), "Different Variables"); Assert.IsFalse(i2.Equals(v1), "Individual differs from Variable"); }