Beispiel #1
0
		/// <summary>
		/// A helper method for easily creating an array of Individual predicates.
		/// </summary>
		/// <param name="predicates">The array of predicate values.</param>
		/// <returns>The array of Individual built on the predicate values.</returns>
		public static Individual[] NewArray(params object[] predicates) {
			Individual[] individuals = new Individual[predicates.Length];
			
			for (int i=0; i<predicates.Length; i++)
				individuals[i] = new Individual(predicates[i]);
				
			return individuals;
		}
Beispiel #2
0
		/// <summary>
		/// Checks if an Individual matches the current Function by either calling a NxBRE helper method
		/// or using a binder.
		/// </summary>
		/// <param name="individual">The Individual to check.</param>
		/// <returns>True if the Individual matches the Function.</returns>
		public bool Evaluate(Individual individual) {
			if (resolutionType == FunctionResolutionType.NxBRE)
				return EvaluateNxBREOperator(individual.Value, name, arguments);
			else if (resolutionType == FunctionResolutionType.Binder)
				return bob.Evaluate(individual.Value, functionSignature, arguments);
			else
				throw new BREException("Function evaluation mode not supported: " + resolutionType);
		}
Beispiel #3
0
		/// <summary>
		/// Called by the Inference Engine whenever an Individual predicate is found in the
		/// rule base and must be evaluated to determine if it is a function.
		/// </summary>
		/// <param name="individual">The Individual found in the rule base.</param>
		/// <returns>The unchanged Individual if it is not a function, else a Function predicate.</returns>
		public IPredicate AnalyzeIndividualPredicate(Individual individual) {
			if (individual.Value is string) {
				// Match the regular expression pattern against a text string.
				Match m = RegexFunction.Match((string)individual.Value);
				if (m.Success) {
					// Create a function predicate with 
					ArrayList arguments = new ArrayList();
					foreach (Capture c2 in m.Groups[2].Captures)
						arguments.Add(c2.ToString().Trim());

					return new Function(Function.FunctionResolutionType.Binder,
					                    (string)individual.Value,
					                    this,
					                    m.Groups[1].Captures[0].ToString(),
					                    (string[])arguments.ToArray(typeof(string)));
				}		
			}
			
			return individual;
		}
Beispiel #4
0
        // ----------------- Static methods ----------------
        /// <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>
        public static Atom ResolveFunctions(Atom atom)
        {
            if (atom.HasFunction) {
                IPredicate[] predicates = new IPredicate[atom.predicates.Length];

                for(int i=0; i<atom.predicates.Length; i++)
                    if (atom.predicates[i] is Function) predicates[i] = new Individual(atom.predicates[i].ToString());
                    else predicates[i] = atom.predicates[i];
                return new Atom(atom.Negative, atom.Type, predicates);
            }
            else
                return (Atom)atom.Clone();
        }
Beispiel #5
0
		/// <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 reprentation of these function predicates,
		/// -  all the predicates that match individual predicates in the passed atom with 
		///   the string reprentation 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>
		public static Fact Resolve(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)
				    || ((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 new Fact(factToResolve.Type, predicates);
		}
Beispiel #6
0
        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;
        }
Beispiel #7
0
        /// <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>
        public 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);
        }
        protected override IPredicate BuildPredicate(XPathNavigator predicateElement, bool inHead, bool resolveImmediatly)
        {
            IPredicate predicate;
            string predicateName = predicateElement.Name;
            string predicateValue = predicateElement.Value;

            switch(predicateName) {
                // --------- IND predicates --------
                case "Ind":
                    string predicateURI = predicateElement.GetAttribute("uri", String.Empty).ToLower();

                    switch(predicateURI) {
                        case "nxbre://expression":
                            if (inHead) {
                                if (resolveImmediatly) predicate = new Individual(Compilation.Evaluate(predicateValue));
                                else predicate = new Formula(Formula.FormulaResolutionType.NxBRE,
                                                             Binder,
                                                             predicateValue);
                            }
                            else {
                                predicate = new Function(Function.FunctionResolutionType.Binder,
                                                         predicateValue,
                                                         new ExpressionEvaluator(predicateValue),
                                                       	 String.Empty,
                                                      	 String.Empty);
                            }
                            break;

                        case "nxbre://operator":
                            // NxBRE operators must follow this pattern: operator(uniqueargument)
                            string[] split = predicateValue.Split(Parameter.PARENTHESIS);
                            predicate = new Function(Function.FunctionResolutionType.NxBRE,
                                                     predicateValue,
                                                     null,
                                                                             split[0],
                                                                             split[1]);
                            break;

                        case "nxbre://binder":
                            if (Binder == null) throw new BREException("No binder available for Individual: " + predicateValue);

                            if (inHead) predicate = new Formula(Formula.FormulaResolutionType.Binder,
                                                                            Binder,
                                                   							predicateValue);
                            else predicate = Binder.AnalyzeIndividualPredicate(new Individual(predicateValue));

                            break;

                        case "":
                            predicate = new Individual(predicateValue);
                            break;

                        default:
                            // there is a predicateURI but it is not recognized by the engine so we assimilate it as
                            // a web reference
                            predicate = new Individual(new HyperLink(predicateValue, predicateURI));
                            break;
                    }
                    break;

            // --------- VAR predicates --------
            case "Var":
                predicate = new Variable(predicateValue);
                break;

            // --------- DATA predicates --------
            case "Data":
                string schemaType = predicateElement.GetAttribute("type", "http://www.w3.org/2001/XMLSchema-instance");
                if (schemaType != String.Empty) {
                    // remove any preceding namespace, like in "xs:string"
                    if (schemaType.IndexOf(':')>=0) schemaType = schemaType.Split(':')[1];

                    // this is a strongly typed individual
                    predicate = new Individual(Schema.ToClr(predicateValue, schemaType), schemaType);
                }
                else {
                    // this is just a string based predicate, using Data was not so wise...
                    predicate = new Individual(predicateValue);
                }

                break;

            // --------- SLOT predicates --------
            case "slot":
                // the first child must be an Ind, we do not support other slot name holders
                if (predicateElement.MoveToFirstChild()) {
                    if (predicateElement.Name != "Ind") throw new BREException("Only Ind is accepted as a slot name holder");
                    string slotName = predicateElement.Value;
                    if (!predicateElement.MoveToNext()) throw new BREException("A slot should contain two children");
                    predicate = new Slot(slotName, BuildPredicate(predicateElement, inHead, resolveImmediatly));
                }
                else {
                    throw new BREException("A slot can not be empty");
                }

                break;

            // --------- UNKNOWN predicates --------
            default:
                throw new BREException("Unsupported predicate type: " + predicateName);
            }

            return predicate;
        }
        public void Gedcom()
        {
            deductionsToCheck = new string[]{
                "sibling{Girl,Boy}", "sibling{Boy,Girl}", "parent{Girl,Daddy}",
                "parent{Girl,Mummy}", "parent{Boy,Daddy}", "parent{Boy,Mummy}", "ancestor{Girl,Daddy}",
                "ancestor{Girl,Mummy}", "ancestor{Boy,Daddy}", "ancestor{Boy,Mummy}", "descendent{Daddy,Girl}",
                "descendent{Mummy,Girl}", "descendent{Daddy,Boy}", "descendent{Mummy,Boy}", "child{Daddy,Girl}",
                "child{Mummy,Girl}", "child{Daddy,Boy}", "child{Mummy,Boy}", "spouse{Daddy,Mummy}", "spouse{Mummy,Daddy}",
                "wife{Daddy,Mummy}", "daughter{Daddy,Girl}", "daughter{Mummy,Girl}", "mother{Girl,Mummy}",
                "mother{Boy,Mummy}", "sister{Boy,Girl}", "son{Daddy,Boy}", "son{Mummy,Boy}", "father{Girl,Daddy}",
                "father{Boy,Daddy}", "brother{Girl,Boy}", "husband{Mummy,Daddy}", "ancestor{Daddy,Old'Pa}",
                "descendent{Old'Pa,Daddy}", "ancestor{Girl,Old'Pa}", "ancestor{Boy,Old'Pa}", "descendent{Old'Pa,Girl}",
                "descendent{Old'Pa,Boy}", "grandparent{Girl,Old'Pa}", "grandparent{Boy,Old'Pa}", "granddaughter{Girl,Old'Pa}",
                "grandchild{Old'Pa,Girl}", "grandchild{Old'Pa,Boy}", "child{Old'Pa,Daddy}", "grandson{Old'Pa,Boy}",
                "son{Old'Pa,Daddy}", "grandfather{Girl,Old'Pa}", "grandfather{Boy,Old'Pa}", "father{Daddy,Old'Pa}",
                "ancestor{Uncle,Old'Pa}", "sibling{Daddy,Uncle}", "father{Uncle,Old'Pa}", "child{Old'Pa,Uncle}",
                "brother{Uncle,Daddy}", "brother{Daddy,Uncle}", "descendent{Old'Pa,Uncle}", "niece{Uncle,Girl}",
                "nephew{Uncle,Boy}", "son{Old'Pa,Uncle}", "uncle{Girl,Uncle}", "uncle{Boy,Uncle}",
                "firstCousin{Girl,Cousin}", "firstCousin{Boy,Cousin}", "firstCousin{Cousin,Girl}", "firstCousin{Cousin,Boy}",
                "ancestor{Cousin,Uncle}", "ancestor{Cousin,Old'Pa}", "father{Cousin,Uncle}", "child{Uncle,Cousin}",
                "grandparent{Cousin,Old'Pa}", "uncle{Cousin,Daddy}", "descendent{Uncle,Cousin}", "descendent{Old'Pa,Cousin}",
                "aunt{Cousin,Mummy}", "grandchild{Old'Pa,Cousin}", "cousin{Cousin,Girl}", "cousin{Cousin,Boy}",
                "cousin{Girl,Cousin}", "cousin{Boy,Cousin}", "grandfather{Cousin,Old'Pa}", "daughter{Uncle,Cousin}",
                "granddaughter{Cousin,Old'Pa}", "niece{Daddy,Cousin}"
            };

              	NewFactEvent henf = new NewFactEvent(HandleExpectedNewFact);
              	ie.NewFactHandler += henf;

              	ie.LoadRuleBase(NewGedcomAdapter());
            Individual male = new Individual("M");
            Individual female = new Individual("F");
            Individual happyFamily = new Individual("Happy");
            Individual daddy = new Individual("Daddy");
            Individual mummy = new Individual("Mummy");
            Individual girl = new Individual("Girl");
            Individual boy = new Individual("Boy");

            ie.Assert(new Fact("sex", daddy, male));
            ie.Assert(new Fact("sex", mummy, female));
            ie.Assert(new Fact("sex", girl, female));
            ie.Assert(new Fact("sex", boy, male));

            ie.Assert(new Fact("spouseIn", daddy, happyFamily));
            ie.Assert(new Fact("spouseIn", mummy, happyFamily));
            ie.Assert(new Fact("childIn", girl, happyFamily));
            ie.Assert(new Fact("childIn", boy, happyFamily));
            Process();

            Assert.AreEqual(32, deducted, "(1) Deducted");
            Assert.IsFalse(wrongDeduction, "(1) Deductions OK");

            Individual oldpa = new Individual("Old'Pa");
            ie.Assert(new Fact("sex", oldpa, male));
            ie.Assert(new Fact("parent", daddy, oldpa));
            Process();

            Assert.AreEqual(17, deducted, "(2) Deducted");
            Assert.IsFalse(wrongDeduction, "(2) Deductions OK");

            Individual uncle = new Individual("Uncle");
            ie.Assert(new Fact("sex", uncle, male));
            ie.Assert(new Fact("parent", uncle, oldpa));
            ie.Assert(new Fact("sibling", uncle, daddy));
            Process();

            Assert.AreEqual(12, deducted, "(3) Deducted");
            Assert.IsFalse(wrongDeduction, "(3) Deductions OK");

            Individual cousin = new Individual("Cousin");
            ie.Assert(new Fact("sex", cousin, female));
            ie.Assert(new Fact("parent", cousin, uncle));
            Process();

            Assert.AreEqual(22, deducted, "(4) Deducted");
            Assert.IsFalse(wrongDeduction, "(4) Deductions OK");

            ie.NewFactHandler -= henf;
              	deductionsToCheck = null;
        }
Beispiel #10
0
        /// <summary>
        /// Creates a new Fact.
        /// </summary>
        /// <remarks>
        /// This method is an helper of the regular Fact instantiation.
        /// </remarks>
        /// <param name="type">The Type of the new Fact to assert.</param>
        /// <param name="individuals">The Array of Individual predicates or the Individual predicate that the Fact will contain.</param>
        /// <returns>A new Fact of desired Type and individuals.</returns>
        public Fact NewFact(string type, object individuals)
        {
            Fact newFact;

            if (individuals.GetType().IsArray) {
                Array individualsArray = (Array) individuals;
                Individual[] members = new Individual[individualsArray.Length];

                for (int i=0; i<individualsArray.Length; i++)
                    members[i] = new Individual(individualsArray.GetValue(i));

                newFact = new Fact(type, members);
            }
            else
                newFact = new Fact(type, new Individual(individuals));

            return newFact;
        }
        protected override IPredicate BuildPredicate(XPathNavigator predicateElement, bool inHead, bool resolveImmediatly)
        {
            IPredicate predicate;
            string predicateName = predicateElement.Name;
            string predicateValue = predicateElement.Value;

            switch(predicateName) {
                // --------- IND predicates --------
                case "ind":
                    if (predicateValue.ToLower().StartsWith("expr:")) {
                        if (inHead) {
                            if (resolveImmediatly) predicate = new Individual(Compilation.Evaluate(predicateValue));
                            else predicate = new Formula(Formula.FormulaResolutionType.NxBRE,
                                                         Binder,
                                                         predicateValue);
                        }
                        else {
                            predicate = new Function(Function.FunctionResolutionType.Binder,
                                                     predicateValue,
                                                     new ExpressionEvaluator(predicateValue),
                                                   	 String.Empty,
                                                  	 String.Empty);
                        }
                    }
                    else if (predicateValue.ToLower().StartsWith("nxbre:")) {
                        // NxBRE functions must follow this pattern: NxBRE:Function(uniqueargument)
                        string[] split = predicateValue.Split(Parameter.PARENTHESIS);
                        predicate = new Function(Function.FunctionResolutionType.NxBRE,
                                                 predicateValue,
                                                 null,
                                                                         split[0],
                                                                         split[1]);
                    }
                    else if (Binder == null) {
                        predicate = new Individual(predicateValue);
                    }
                    else if ((inHead) && (predicateValue.ToLower().StartsWith("binder:"))) {
                        predicate = new Formula(Formula.FormulaResolutionType.Binder,
                                                Binder,
                                                predicateValue);
                    }
                    else if ((inHead) && (predicateValue.EndsWith("()"))) {
                        predicate = new Formula(Formula.FormulaResolutionType.Binder,
                                                Binder,
                                                predicateValue);
                    }
                    else {
                        predicate = Binder.AnalyzeIndividualPredicate(new Individual(predicateValue));
                    }

                break;

            // --------- VAR predicates --------
            case "var":
                predicate = new Variable(predicateValue);
                break;

            // --------- UNKNOWN predicates --------
            default:
                throw new BREException("Unsupported predicate type: " + predicateName);
            }

            return predicate;
        }
Beispiel #12
0
        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);
        }
Beispiel #13
0
        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");
        }
		private Atom GetAtom(XPathNavigator atom, bool negative, bool inHead, bool resolveImmediatly) {
			ArrayList relationPredicates;
			XPathNodeIterator rel;
			XPathNodeIterator predicates;
			
			relationPredicates = new ArrayList();
			rel = atom.Select(GetXPathExpression("dl:_opr/dl:rel"));
			rel.MoveNext();
			String atomRelation = rel.Current.Value;
			
			predicates = atom.Select(GetXPathExpression("dl:ind | dl:var"));
			while(predicates.MoveNext()) {
				IPredicate predicate;
				string predicateValue = predicates.Current.Value;
				
				if (predicates.Current.Name == "ind") {
					if (predicateValue.ToLower().StartsWith("expr:")) {
						if (inHead) {
							if (resolveImmediatly) predicate = new Individual(Compilation.Evaluate(predicateValue));
							else predicate = new Formula(Formula.FormulaResolutionType.NxBRE,
							                             Binder,
							                             predicateValue);
						}
						else {
							predicate = new Function(Function.FunctionResolutionType.Binder,
							                         predicateValue,
							                         new ExpressionEvaluator(predicateValue),
							                       	 String.Empty,
							                      	 String.Empty);
						}
					}
					else if (predicateValue.ToLower().StartsWith("nxbre:")) {
						// NxBRE functions must follow this pattern: NxBRE:Function(uniqueargument)
						string[] split = predicateValue.Split(Parameter.PARENTHESIS);
						predicate = new Function(Function.FunctionResolutionType.NxBRE,
						                         predicateValue,
						                         null,
																		 split[0],
																		 split[1]);
					}
					else if (Binder == null)
						predicate = new Individual(predicateValue);
					else if ((inHead) && ((predicateValue.ToLower().StartsWith("binder:")) || (predicateValue.EndsWith("()"))))
						predicate = new Formula(Formula.FormulaResolutionType.Binder,
						                        Binder,
						                        predicateValue);
					else
						predicate = Binder.AnalyzeIndividualPredicate(new Individual(predicateValue));
				}
				else if (predicates.Current.Name == "var") {
					predicate = new Variable(predicateValue);
				}
				else
					throw new BREException("Unsupported predicate type: " + predicates.Current.Name);
				
				relationPredicates.Add(predicate);
			}
			
			// build the array of predicates
			IPredicate[] predicatesArray = (IPredicate[])relationPredicates.ToArray(typeof(IPredicate));
			
			// identify function based atom relations
			AtomFunction.RelationResolutionType resolutionType = AtomFunction.RelationResolutionType.None;
			if (atomRelation.ToLower().StartsWith("nxbre:"))
				resolutionType = AtomFunction.RelationResolutionType.NxBRE;
			else if ((atomRelation.ToLower().StartsWith("binder:")) || (atomRelation.EndsWith("()")))
				resolutionType = AtomFunction.RelationResolutionType.Binder;
			else if (atomRelation.ToLower().StartsWith("expr:"))
				resolutionType = AtomFunction.RelationResolutionType.Expression;
			
			if ((resolutionType == AtomFunction.RelationResolutionType.NxBRE) ||
			    (resolutionType == AtomFunction.RelationResolutionType.Binder))
				return new AtomFunction(resolutionType,
				                        negative,
				                        Binder,
				                        atomRelation,
					          	  				predicatesArray);
			
			else if (resolutionType == AtomFunction.RelationResolutionType.Expression)
				return new AtomFunction(resolutionType,
				                        negative,
				                        new ExpressionRelater(atomRelation, predicatesArray),
				                        atomRelation,
					          	  				predicatesArray);
			else
				return new Atom(negative,
	              				atomRelation,
	          	  				predicatesArray);
		}