/* Equivalent Utils */ /// <summary> /// Internal method used for exploring the potential hierarchy of equivalence and building the complete /// list of atoms equivalent to one atom. /// </summary> internal static ArrayList GetAll(IList<Equivalent> equivalentPairs, Atom atom, ArrayList equivalentAtoms) { if ((atom != null) && (!equivalentAtoms.Contains(atom))) { equivalentAtoms.Add(atom); foreach(Equivalent equivalentPair in equivalentPairs) GetAll(equivalentPairs, equivalentPair.Get(atom), equivalentAtoms); } // returning the list is not necessary at all but just convenient for the calling methods return equivalentAtoms; }
/// <summary> /// Instantiates a new Implication. /// </summary> /// <param name="label">The label of the new implication.</param> /// <param name="priority">The priority of the new implication.</param> /// <param name="mutex">String.Empty or the label of an implication mutexed by the new one.</param> /// <param name="precondition">String.Empty or the label of an implication that preconditions the new one.</param> /// <param name="deduction">The Atom used as a prototype for what this Implication tries to proove.</param> /// <param name="atomGroup">The top level group of atoms used in the query part (pattern matching) of the new Implication.</param> /// <see cref="NxBRE.InferenceEngine.Rules.ImplicationPriority"/> public Implication(string label, ImplicationPriority priority, string mutex, string precondition, Atom deduction, AtomGroup atomGroup) : this(label, (int)priority, mutex, precondition, deduction, atomGroup) { }
/* Fact Utils */ /// <summary> /// Populates the Variable predicates of a target Atom, using another Atom as a template /// and a Fact as the source of data, i.e. Individual predicates. /// </summary> /// <param name="data">The data for populating the Atom.</param> /// <param name="template">The template of Atom being populated.</param> /// <param name="members">The members to populate.</param> internal static void Populate(Fact data, Atom template, IPredicate[] members) { for(int i=0;i<members.Length;i++) if (members[i] is Variable) { // try to locate a Variable with the same name in the template int j = Array.IndexOf(template.Members, members[i]); if (j >= 0) { members[i] = data.Members[j]; } else { // try to locate a Slot with the same name in the template j = Array.IndexOf(template.SlotNames, members[i].Value); if (j >= 0) members[i] = data.Members[j]; } } }
/// <summary> /// Instantiates a new Implication. /// </summary> /// <param name="label">The label of the new implication.</param> /// <param name="priority">The priority of the new implication.</param> /// <param name="mutex">String.Empty or the label of an implication mutexed by the new one.</param> /// <param name="precondition">String.Empty or the label of an implication that preconditions the new one.</param> /// <param name="deduction">The Atom used as a prototype for what this Implication tries to proove.</param> /// <param name="atomGroup">The top level group of atoms used in the query part (pattern matching) of the new Implication.</param> /// <param name="action">The implication action.</param> /// <see cref="NxBRE.InferenceEngine.Rules.ImplicationAction"/> /// <see cref="NxBRE.InferenceEngine.Rules.ImplicationPriority"/> public Implication(string label, int priority, string mutex, string precondition, Atom deduction, AtomGroup atomGroup, ImplicationAction action) : base(label, atomGroup) { if (deduction.HasFunction) throw new BREException("Can not create Implication with functions in the Deduction: " + deduction.ToString()); if ((mutex != null) && (mutex == label)) throw new BREException("An Implication can not Mutex itself: " + mutex); if ((precondition != null) && (precondition == label)) throw new BREException("An Implication can not Pre-Condition itself: " + precondition); /* Commented out to solve bug #1469851 : this test was not necessary anymore as the engine can now handle typed data in implications foreach(object member in AtomGroup.Members) if ((member is Atom) && (((Atom)member).HasNotStringIndividual)) throw new BREException("Can not create Implication with non-String individuals in the atoms: " + member.ToString()); */ if ((priority < (int)ImplicationPriority.Minimum) || (priority > (int)ImplicationPriority.Maximum)) throw new ArgumentOutOfRangeException("Priority must be in the [" + ImplicationPriority.Minimum + "-" + ImplicationPriority.Maximum + "] range."); if (action == ImplicationAction.Count) { if (deduction.IsFact) throw new BREException("A counting Implication must have one Variable predicate in its deduction atom."); int varCount = 0; foreach(IPredicate member in deduction.Members) { if (member is Variable) varCount++; if (varCount > 1) throw new BREException("A counting Implication must have only one Variable predicate in its deduction atom."); } } this.priority = priority; this.deduction = deduction; this.mutex = mutex; this.precondition = precondition; this.action = action; hasNaf = false; foreach(Atom atom in AtomGroup.AllAtoms) { if (atom.Negative) { hasNaf = true; break; } } }
public void PredicateNxBREFunction() { FactBase fb = new FactBase(); PopulateFactBase(fb); Atom filter = new Atom("spending", new Variable("name"), new Function(Function.FunctionResolutionType.NxBRE, "foo", null, "GreaterThan", "5000"), new Individual("previous year")); Assert.AreEqual(1, CountEnumerator(fb.Select(filter, null)), "Query with NxBRE function"); }
protected override void WriteAtom(XmlElement target, Atom atom, bool inFact) { XmlElement eAtom = eAtom = Document.CreateElement("Atom", DatalogNamespaceURL); if (atom is Fact) WriteLabel(eAtom, ((Fact)atom).Label); XmlElement rel = Document.CreateElement("Rel", DatalogNamespaceURL); rel.InnerText = atom.Type; if (atom is AtomFunction) { switch (((AtomFunction)atom).ResolutionType) { case AtomFunction.RelationResolutionType.Binder: rel.SetAttribute("uri", "nxbre://binder"); break; case AtomFunction.RelationResolutionType.NxBRE: rel.SetAttribute("uri", "nxbre://operator"); break; case AtomFunction.RelationResolutionType.Expression: rel.SetAttribute("uri", "nxbre://expression"); break; } } if (syntax != SaveFormatAttributes.Compact) { XmlElement opr = Document.CreateElement("op", DatalogNamespaceURL); opr.AppendChild(rel); eAtom.AppendChild(opr); } else { eAtom.AppendChild(rel); } for(int i=0; i<atom.Members.Length; i++) { IPredicate pre = atom.Members[i]; // build the predicate element depending on its type XmlElement predicate; if (pre is Variable) { predicate = Document.CreateElement("Var", DatalogNamespaceURL); predicate.InnerText = pre.Value.ToString(); } else if (pre is Individual) { if (pre.Value is HyperLink) { // we deal with the special case of hyperlinks HyperLink hl = (HyperLink)pre.Value; predicate = Document.CreateElement("Ind", DatalogNamespaceURL); predicate.SetAttribute("uri", hl.Uri); predicate.InnerText = hl.Text; } else { string sourceType = ((Individual)pre).SourceType; if ((forceDataTyping) && (!(pre.Value is string)) && ((sourceType == null) || (sourceType == String.Empty))) sourceType = Xml.GetSchemaTypeFromClr(pre.Value); if ((sourceType != null) && (sourceType != String.Empty)) { // we persist as a typed data predicate = Document.CreateElement("Data", DatalogNamespaceURL); predicate.SetAttribute("type", Xml.NS_URI, "xs:" + sourceType); predicate.InnerText = Xml.FromClr(pre.Value, sourceType); } else { // we persist as a String based individual predicate = Document.CreateElement("Ind", DatalogNamespaceURL); predicate.InnerText = pre.Value.ToString(); } } } else if (pre is Formula) { predicate = Document.CreateElement("Ind", DatalogNamespaceURL); predicate.SetAttribute("uri", (((Formula)pre).ResolutionType == Formula.FormulaResolutionType.Binder)?"nxbre://binder":"nxbre://expression"); predicate.InnerText = pre.Value.ToString(); } else if (pre is Function) { Function function = (Function)pre; predicate = Document.CreateElement("Ind", DatalogNamespaceURL); predicate.SetAttribute("uri", (function.ResolutionType == Function.FunctionResolutionType.NxBRE)?"nxbre://operator":(IsExpressionBinder(function.Binder)?"nxbre://expression":"nxbre://binder")); predicate.InnerText = pre.Value.ToString(); } else { // should never happen throw new BREException("Can not persist a rulebase containing a predicate of type: " + pre.GetType().FullName); } // add wrapper elements if necessary: if there is one or more slot, args can not be used string slotName = atom.SlotNames[i]; if (slotName != String.Empty) { XmlElement slot = Document.CreateElement("slot", DatalogNamespaceURL); XmlElement slotInd = Document.CreateElement("Ind", DatalogNamespaceURL); slotInd.InnerText = slotName; slot.AppendChild(slotInd); slot.AppendChild(predicate); eAtom.AppendChild(slot); } else if ((!atom.HasSlot) && (syntax == SaveFormatAttributes.Expanded)) { XmlElement argument = Document.CreateElement("arg", DatalogNamespaceURL); argument.SetAttribute("index", (i+1).ToString()); argument.AppendChild(predicate); eAtom.AppendChild(argument); } else { eAtom.AppendChild(predicate); } } if (atom.Negative) { XmlElement naf = Document.CreateElement("Naf", DatalogNamespaceURL); if (syntax == SaveFormatAttributes.Expanded) { XmlElement weak = Document.CreateElement("weak", DatalogNamespaceURL); weak.AppendChild(eAtom); naf.AppendChild(weak); } else { naf.AppendChild(eAtom); } target.AppendChild(naf); } else { target.AppendChild(eAtom); } }
/// <summary> /// Checks if the signature of the current Atom matches with the signature of another one. /// </summary> /// <param name="atom">The other atom to determine the signature matching.</param> /// <returns>True if the two atoms have the same signature, False otherwise.</returns> public bool BasicMatches(Atom atom) { return (atom.Signature == Signature); }
private Fact BuildFact(Atom targetAtom, IList<FactBase.PositiveMatchResult> processResult) { Atom factBuilder = FactBase.Populate(targetAtom, processResult, true); if (!factBuilder.IsFact) { if (strictImplication) throw new BREException("Strict implication rejected the assertion of incompletely resolved fact: " + factBuilder); } else { return new Fact(factBuilder); } return null; }
/// <summary> /// Instantiates a new labelled Fact based on an existing Atom and a provided Label. /// </summary> /// <param name="label">The Label of the new Fact.</param> /// <param name="atom">The Atom that the Fact will be built on.</param> public Fact(string label, Atom atom) : base(atom) { if ((label != null) && (label == String.Empty)) this.label = null; else this.label = label; }
/// <summary> /// Check if the current intersects with another one, which means that: /// - they Match() together, /// - their predicate types are similar, /// - if there are variables, at least one should be equal to the corresponding one. /// </summary> /// <param name="atom">The other atom to determine the intersection.</param> /// <returns>True if the two atoms intersect.</returns> /// <remarks>IsIntersecting calls Matches first.</remarks> public bool IsIntersecting(Atom atom) { if (!Matches(atom)) return false; for(int i=0; i<predicates.Length; i++) if (predicates[i].GetType() != atom.predicates[i].GetType()) return false; if (!HasVariable) return true; int nonMatchingVariables = 0; int variableCount = 0; for(int i=0; i<predicates.Length; i++) { variableCount++; if (predicates[i] is Variable) { if (!(predicates[i].Equals(atom.predicates[i]))) nonMatchingVariables++; } } if (variableCount < predicates.Length) return true; else return (nonMatchingVariables < variableCount); }
/// <summary> /// Prepare the atom to be pattern matched by replacing in a fact: /// - all the predicates that match function predicates in the passed atom with /// the string representation of these function predicates, /// - all the predicates that match individual predicates in the passed atom with /// the string representation of these individual predicates. /// </summary> /// <remarks> /// This operation must be done *if and only if* the fact matches the atom. /// </remarks> /// <param name="factToResolve">The fact that must be resolved.</param> /// <param name="atom">The atom with which the current fact matches.</param> /// <returns>A new fact with only String individuals.</returns> internal static Fact Resolve(Fact factToResolve, Atom atom) { return Resolve(true, factToResolve, atom); }
public void Init() { atom2_2 = new Atom("luxury", new Variable("product")); atom3 = new Atom("spending", new Variable("customer"), new Individual("min(5000,EUR)"), new Individual("previous year")); atomF = new Atom("spending", new Variable("customer"), new Function(Function.FunctionResolutionType.Binder, "min(5000,EUR)", null, "min", new string[]{"5000","EUR"}), new Individual("previous year")); fact1 = new Fact("premium", new Individual("Peter Miller")); fact2 = new Fact("spending", new Individual("Peter Miller"), new Individual("min(5000,EUR)")); fact3 = new Fact("spending", new Individual("Peter Miller"), new Individual("min(5000,EUR)"), new Individual("previous year")); fact3bis = new Fact("spending", new Individual("Peter Miller"), new Individual("min(5000,EUR)"), new Individual("previous year")); factX = new Fact("spending", new Individual("John Q. Doe"), new Individual("min(5000,EUR)"), new Individual("previous year")); imp2 = new Atom("discount", new Variable("customer"), new Variable("product"), new Individual("7.5 percent")); imp2bis = new Atom("discount", new Variable("buyer"), new Variable("product"), new Individual("7.5 percent")); impX = new Atom("discount", new Variable("buyer"), new Variable("product"), new Individual("6.5 percent")); }
/* Atom Utils */ /// <summary> /// Resolves all Function predicates by replacing them by their String representations. /// </summary> /// <param name="atom">The Atom to resolve.</param> /// <returns>A new Atom where all Function predicates have been resolved. If no /// Function predicate exists, it returns a clone of the current Atom.</returns> internal static Atom ResolveFunctions(Atom atom) { if (atom.HasFunction) { IPredicate[] predicates = new IPredicate[atom.Members.Length]; for(int i=0; i<atom.Members.Length; i++) if (atom.Members[i] is Function) predicates[i] = new Individual(atom.Members[i].ToString()); else predicates[i] = atom.Members[i]; return new Atom(atom.Negative, atom.Type, predicates); } else return (Atom)atom.Clone(); }
public void FactBaseCloning() { FactBase fb = new FactBase(); PopulateFactBase(fb); FactBase clone = (FactBase)fb.Clone(); Assert.AreEqual(fb.Count, clone.Count, "Same number of facts"); Fact jqdSpending = clone.GetFact("JQD Spending"); Assert.AreEqual("JQD Spending", jqdSpending.Label, "Correct fact label"); int countBefore = clone.Count; Assert.IsTrue(clone.Retract(jqdSpending), "Retracted 'JQD Spending'"); Assert.AreEqual(countBefore-1, clone.Count, "Count after retraction"); Assert.IsFalse(clone.Exists(jqdSpending), "'JQD Spending' really retracted"); Assert.IsTrue(fb.Exists(jqdSpending), "'JQD Spending' still in original"); Atom filter = new Atom("spending", new Variable("name"), new Function(Function.FunctionResolutionType.NxBRE, "foo", null, "GreaterThan", "5000"), new Individual("previous year")); Assert.AreEqual(1, CountEnumerator(fb.Select(filter, null)), "Query on the original"); Assert.AreEqual(0, CountEnumerator(clone.Select(filter, null)), "Query on the clone"); }
public void ExcludeFactsFromSelection() { FactBase fb = new FactBase(); Assert.IsTrue(fb.Assert(new Fact("spending", new Individual("Peter Miller"), new Individual(5000), new Individual("previous year"))), "Assert 'P.Miller Spending'"); Fact jqdSpending = new Fact("JQD Spending", "spending", new Individual("John Q.Clone Doe"), new Individual(7000), new Individual("previous year")); Assert.IsTrue(fb.Assert(jqdSpending), "Assert 'JQD Spending'"); Atom filter = new Atom("spending", new Variable("name"), new Function(Function.FunctionResolutionType.NxBRE, "foo", null, "GreaterThanEqualTo", "5000"), new Individual("previous year")); Assert.AreEqual(2, CountEnumerator(fb.Select(filter, null)), "Query with NxBRE function and no fact exclusion"); IList<Fact> excludedFacts = new List<Fact>(); excludedFacts.Add(jqdSpending); Assert.AreEqual(1, CountEnumerator(fb.Select(filter, excludedFacts)), "Query with NxBRE function with fact exclusion"); }
public void AtomSlots() { Atom atom = new Atom("spending", new Slot("client", new Variable("buyer")), new Function(Function.FunctionResolutionType.Binder, "min(5000,EUR)", null, "min", new string[]{"5000","EUR"})); Assert.AreEqual(typeof(Variable), atom.GetPredicate("client").GetType(), "Slot predicate"); Atom clone = (Atom)atom.Clone(); atom = null; Assert.AreEqual(typeof(Variable), clone.GetPredicate("client").GetType(), "Slot predicate after cloning"); }
/// <summary> /// Checks if the predicates of the current Atom match with the predicates of another one, i.e. are equal or functions resolve to True. /// </summary> /// <param name="atom">The other atom to determine the predicates matching.</param> /// <param name="strictTyping">True if String individual predicate are not considered as potential representations of other types.</param> /// <param name="ignoredPredicates">A list of predicate positions to exclude from comparison, or null if all predicates must be matched</param> /// <returns>True if the two atoms have matching predicates, False otherwise.</returns> internal bool PredicatesMatch(Atom atom, bool strictTyping, IList<int> ignoredPredicates) { for(int position=0; position<predicates.Length; position++) { if ((ignoredPredicates == null) || ((ignoredPredicates != null) && (!ignoredPredicates.Contains(position)))) { if ((predicates[position] is Individual) && (atom.predicates[position] is Function) && (!((Function)atom.predicates[position]).Evaluate((Individual)predicates[position]))) { return false; } else if ((predicates[position] is Function) && (atom.predicates[position] is Individual) && (!((Function)predicates[position]).Evaluate((Individual)atom.predicates[position]))) { return false; } else if ((predicates[position] is Function) && (atom.predicates[position] is Function) && (!(predicates[position].Equals(atom.predicates[position])))) { return false; } else if ((predicates[position] is Individual) && (atom.predicates[position] is Individual)) { // we have two individuals if (predicates[position].Value.GetType() == atom.predicates[position].Value.GetType()) { if (!predicates[position].Equals(atom.predicates[position])) // the two individuals are of same types: if equals fail, no match return false; } else { if (!strictTyping) { // the two individuals are of different types and we are not in strict typing, so // we try to cast to stronger type and compare ObjectPair pair = new ObjectPair(predicates[position].Value, atom.predicates[position].Value); Reflection.CastToStrongType(pair); if (!pair.First.Equals(pair.Second)) return false; } else { return false; } } } } } // we went through all the comparisons without a scratch, it means the atoms do match return true; }
/// <summary> /// Checks if the current Atom matches with another one, i.e. if they are of same type, /// contain the same number of predicates, and if their Individual predicates are equal. /// </summary> /// <description> /// This functions takes care of casting as it always tries to cast to the strongest type /// of two compared individuals. Since predicates can come from weakly-typed rule files /// (Strings) and other predicates can be generated by the user, this function tries to /// convert from String to the type of the other predicate (as String is considered not /// strongly typed). /// </description> /// <param name="atom">The other atom to determine the matching.</param> /// <returns>True if the two atoms match.</returns> public bool Matches(Atom atom) { if (!BasicMatches(atom)) return false; return PredicatesMatch(atom, false, null); }
/// <summary> /// Translates variable names of a target atom with names from a template atom matching the position of a /// source atom. /// </summary> /// <remarks>Template and source atoms must match together else unpredictible result may occur.</remarks> /// <param name="template"></param> /// <param name="source"></param> /// <param name="target"></param> /// <returns></returns> internal static Atom TranslateVariables(Atom template, Atom source, Atom target) { IPredicate[] resultMembers = new IPredicate[target.Members.Length]; for(int i=0; i<target.Members.Length; i++) { IPredicate targetMember = target.Members[i]; if (targetMember is Variable) { int indexOfSourceMember = Array.IndexOf(source.Members, targetMember); if (indexOfSourceMember >= 0) resultMembers[i] = template.Members[indexOfSourceMember]; else resultMembers[i] = targetMember; } else resultMembers[i] = targetMember; } return new Atom(template.Negative, target.Type, resultMembers); }
public void ProcessAnd() { FactBase fb = new FactBase(); PopulateFactBase(fb); Atom atom1 = new Atom("spending", new Variable("name"), new Function(Function.FunctionResolutionType.NxBRE, "foo", null, "GreaterThan", "5000"), new Individual("previous year")); Atom atom2 = new Atom("lending", new Variable("name"), new Function(Function.FunctionResolutionType.NxBRE, "foo", null, "GreaterThan", "5000"), new Individual("previous year")); IList<IList<FactBase.PositiveMatchResult>> result = fb.ProcessAtomGroup(new AtomGroup(AtomGroup.LogicalOperator.And, atom1, atom2)); Assert.AreEqual(1, result.Count, "2 positive atoms"); atom2 = new Atom("lending", new Variable("name"), new Function(Function.FunctionResolutionType.NxBRE, "foo", null, "GreaterThan", "15000"), new Individual("previous year")); result = fb.ProcessAtomGroup(new AtomGroup(AtomGroup.LogicalOperator.And, atom1, atom2)); Assert.AreEqual(0, result.Count, "1 positive and 1 negative atoms"); atom2 = new Atom("spending", new Variable("otherName"), new Variable("whateverAmount"), new Individual("previous year")); result = fb.ProcessAtomGroup(new AtomGroup(AtomGroup.LogicalOperator.And, atom1, atom2)); Assert.AreEqual(2, result.Count, "2 positive combinatorial atoms"); atom2 = new Atom("spending", new Variable("otherName"), new Variable("whateverAmount"), new Individual("unknown year")); result = fb.ProcessAtomGroup(new AtomGroup(AtomGroup.LogicalOperator.And, atom1, atom2)); Assert.AreEqual(0, result.Count, "1 positive and 1 negative combinatorial atoms"); }
public void ProcessOr() { FactBase fb = new FactBase(); PopulateFactBase(fb); Atom atom1 = new Atom("spending", new Variable("name"), new Function(Function.FunctionResolutionType.NxBRE, "foo", null, "GreaterThan", "1000"), new Individual("previous year")); Atom atom2 = new Atom("lending", new Variable("name"), new Function(Function.FunctionResolutionType.NxBRE, "foo", null, "GreaterThan", "5000"), new Individual("previous year")); IList<IList<FactBase.PositiveMatchResult>> result = fb.ProcessAtomGroup(new AtomGroup(AtomGroup.LogicalOperator.Or, atom1, atom2)); Assert.AreEqual(3, result.Count, "2 positive atoms"); atom1 = new Atom("spending", new Variable("name"), new Function(Function.FunctionResolutionType.NxBRE, "foo", null, "GreaterThan", "9999"), new Individual("previous year")); result = fb.ProcessAtomGroup(new AtomGroup(AtomGroup.LogicalOperator.Or, atom1, atom2)); Assert.AreEqual(1, result.Count, "1 positive atom"); }
public void VariableTranslation() { Atom template = new Atom("own", new Variable("person"), new Variable("object")); Atom source = new Atom("own", new Variable("person"), new Variable("stuff")); Atom target = new Atom("belongs", new Variable("person"), new Variable("stuff")); Atom expected = new Atom("belongs", new Variable("person"), new Variable("object")); Assert.AreEqual(expected, RulesUtil.TranslateVariables(template, source, target)); }
/// <summary> /// Prepare the atom to be pattern matched by replacing in a fact: /// - all the predicates that match function predicates in the passed atom with /// the string representation of these function predicates, /// - in fully mode, all the predicates that match individual predicates in the passed atom with /// the string representation of these individual predicates. /// </summary> /// <remarks> /// This operation must be done *if and only if* the fact matches the atom. /// </remarks> /// <param name="fully">Forces resolution of non-string individual to String.</param> /// <param name="factToResolve">The fact that must be resolved.</param> /// <param name="atom">The atom with which the current fact matches.</param> /// <returns>A new fact with only String individuals.</returns> internal static Fact Resolve(bool fully, Fact factToResolve, Atom atom) { IPredicate[] predicates = new IPredicate[factToResolve.Members.Length]; for(int i=0; i<factToResolve.Members.Length; i++) { if ((atom.Members[i] is Function) || ((fully) && (atom.Members[i] is Individual) && (!(factToResolve.Members[i].Value is System.String)))) { predicates[i] = new Individual(atom.Members[i].ToString()); } else { predicates[i] = factToResolve.Members[i]; } } return (Fact)factToResolve.CloneWithNewMembers(predicates); }
private int RunStrictTypingFactBaseTest(bool strictTyping) { FactBase fb = new FactBase(); fb.strictTyping = strictTyping; Assert.IsTrue(fb.Assert(new Fact("spending", new Individual("foo"), new Individual(7000))), "Assert 'foo Spending'"); Assert.IsTrue(fb.Assert(new Fact("spending", new Individual("bar"), new Individual("7000"))), "Assert 'bar Spending'"); Atom filter = new Atom("spending", new Variable("name"), new Individual("7000")); return CountEnumerator(fb.Select(filter, null)); }
/// <summary> /// Instantiates a new anonymous (not labelled) Fact based on an existing Atom. /// </summary> /// <param name="atom">The Atom that the fact will be built on.</param> public Fact(Atom atom) : this(null, atom) { }
protected abstract void WriteAtom(XmlElement target, Atom atom, bool inFact);
///<summary>Predicate persistence relies on ToString() /// Do not expect business object persistence with this adapter!</summary> protected override void WriteAtom(XmlElement target, Atom atom, bool inFact) { XmlElement eAtom = eAtom = Document.CreateElement("atom", DatalogNamespaceURL); XmlElement rel = Document.CreateElement("rel", DatalogNamespaceURL); rel.InnerText = atom.Type; XmlElement opr = Document.CreateElement("_opr", DatalogNamespaceURL); opr.AppendChild(rel); eAtom.AppendChild(opr); foreach(IPredicate pre in atom.Members) { XmlElement predicate = Document.CreateElement((pre is Variable)?"var":"ind", DatalogNamespaceURL); object predicateValue = pre.Value; if ((inFact) && (supportTypedFacts) && (!(predicateValue is string))) { if (predicateValue is IConvertible) predicate.InnerText = "expr:System.Convert.To" + predicateValue.GetType().Name + "(\"" + predicateValue.ToString() + "\")"; else throw new BREException(predicateValue.GetType().FullName + " is not IConvertible hence can not be persisted as a typed fact: " + atom); } else { predicate.InnerText = predicateValue.ToString(); } eAtom.AppendChild(predicate); } if (atom.Negative) { XmlElement naf = Document.CreateElement("naf", DatalogNamespaceURL); naf.AppendChild(eAtom); target.AppendChild(naf); } else { target.AppendChild(eAtom); } }
/// <summary> /// Instantiates a new Implication. /// </summary> /// <param name="label">The label of the new implication.</param> /// <param name="priority">The priority of the new implication.</param> /// <param name="mutex">String.Empty or the label of an implication mutexed by the new one.</param> /// <param name="precondition">String.Empty or the label of an implication that preconditions the new one.</param> /// <param name="deduction">The Atom used as a prototype for what this Implication tries to proove.</param> /// <param name="atomGroup">The top level group of atoms used in the query part (pattern matching) of the new Implication.</param> /// <see cref="NxBRE.InferenceEngine.Rules.ImplicationPriority"/> public Implication(string label, int priority, string mutex, string precondition, Atom deduction, AtomGroup atomGroup) : this(label, priority, mutex, precondition, deduction, atomGroup, ImplicationAction.Assert) { }
private void WriteEquivalentAtom(XmlElement target, Atom atom) { if (syntax == SaveFormatAttributes.Expanded) { XmlElement torso = Document.CreateElement("torso", DatalogNamespaceURL); WriteAtom(torso, atom, false); target.AppendChild(torso); } else { WriteAtom(target, atom, false); } }
/// <summary> /// Protected constructor used for cloning purpose. /// </summary> /// <param name="source"></param> protected Atom(Atom source) : this(source, (IPredicate[])source.predicates.Clone()) { }