/// <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, IList <PositiveMatchResult> resultStack) { IPredicate[] members = (IPredicate[])targetAtom.Members.Clone(); // populate the variable elements with predicate values coming // from the query part of the implication foreach (PositiveMatchResult pmr in resultStack) { RulesUtil.Populate(pmr.Fact, pmr.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)); }
/// <summary> /// Replaces non-fixed elements of an atom (variables, formulas...) with fixed values (individuals) when possible /// </summary> /// <param name="targetAtom"></param> /// <param name="resultStack"></param> /// <param name="evaluateFormulas"></param> /// <returns></returns> public static Atom Populate(Atom targetAtom, IList <PositiveMatchResult> 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 (PositiveMatchResult pmr in resultStack) { if (!(pmr.Fact is FactBase.NegativeFact)) { RulesUtil.Populate(pmr.Fact, pmr.Source, members); } } // if there are formulas in the atom, resolve these expressions, passing // the variable values as arguments if ((evaluateFormulas) && (targetAtom.HasFormula)) { // formulas must be evaluated and the results placed in individual predicates IDictionary arguments = new Hashtable(); foreach (PositiveMatchResult pmr in resultStack) { if (!(pmr.Fact is FactBase.NegativeFact)) { for (int i = 0; i < pmr.Source.Members.Length; i++) { object sourcePredicateKey = null; if (pmr.Source.Members[i] is Variable) { sourcePredicateKey = pmr.Source.Members[i].Value; } else if (pmr.Source.SlotNames[i] != String.Empty) { sourcePredicateKey = pmr.Source.SlotNames[i]; } if ((sourcePredicateKey != null) && (!arguments.Contains(sourcePredicateKey))) { arguments.Add(sourcePredicateKey, pmr.Fact.Members[i].Value); } } } } for (int i = 0; i < members.Length; i++) { if (members[i] is Formula) { try { members[i] = new Individual(((Formula)members[i]).Evaluate(arguments)); } catch (Exception ex) { // Chuck Cross added try/catch block with addtional info in new thrown exception StringBuilder sb = new StringBuilder("Error evaluating formula ") .Append(members[i]) .Append(" in atom: ") .Append(targetAtom.Type) .Append(".\r\n Arguments:"); foreach (DictionaryEntry entry in arguments) { sb.Append(" ") .Append(entry.Key.ToString()); if (entry.Value != null) { sb.Append("[") .Append(entry.Value.GetType().ToString()) .Append("] = ") .Append(entry.Value.ToString()); } else { sb.Append("[Null]"); } sb.Append("\r\n"); } throw new BREException(sb.ToString(), ex); } } } } // 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)); }