public ActionExpression(string ID, string operatingId, string equation, int priority) : base(ID, priority) { this.equation = equation; this.operatingId = operatingId; //determine the dependent facts ExpressionEvaluator e = new ExpressionEvaluator(); e.Parse(equation); //this method is slow, do it only when needed string[] dependents = ExpressionEvaluator.RelatedEvidence(e.Infix); dependentEvidence = dependents; //assing a value Naked naked = new Naked(null, typeof(string)); this.EvidenceValue = naked; //this is expensive and static, so compute now evaluator = new ExpressionEvaluator(); evaluator.Parse(equation); //this method is slow, do it only when needed evaluator.InfixToPostfix(); //this method is slow, do it only when needed evaluator.GetEvidence += delegate(object sender, EvidenceLookupArgs args) { return RaiseEvidenceLookup(sender, args); }; }
public Rule(string ID, string equation, List<EvidenceSpecifier> actions, int priority, bool chainable) : base(ID, priority) { if (actions == null || actions.Count < 1) throw new Exception("Rules must have at least one action."); foreach (EvidenceSpecifier action in actions) { if (!action.truthality && chainable) throw new Exception("Chainable rules are not allowed to contain actions whos result is false."); } this.actions = actions; this.chainable = chainable; this.equation = equation; ArrayList al = new ArrayList(); foreach (EvidenceSpecifier es in actions) { al.Add(es.evidenceID); } this.clauseEvidence = (string[])al.ToArray(typeof(string)); //this is expensive and static, so compute now ExpressionEvaluator e = new ExpressionEvaluator(); e.Parse(equation); //this method is slow, do it only when needed e.InfixToPostfix(); //this method is slow, do it only when needed this.postfixExpression = e.Postfix; //this method is slow, do it only when needed //determine the dependent facts string[] dependents = ExpressionEvaluator.RelatedEvidence(e.Postfix); dependentEvidence = dependents; //change event could set its value when a model is attached Naked naked = new Naked(false, typeof(bool)); base.EvidenceValue = naked; }
public void TestEvaluateFunctionality() { //get a datareader stream from the xml file XmlReaderSettings xrs = new XmlReaderSettings(); xrs.ConformanceLevel = ConformanceLevel.Document; xrs.IgnoreComments = true; xrs.IgnoreProcessingInstructions = true; xrs.IgnoreWhitespace = true; Stream s = new StreamReader(AppDomain.CurrentDomain.BaseDirectory + @"\..\..\Expression\ExpressionEvaluator.xml").BaseStream; XmlReader reader = XmlReader.Create(s, xrs); //advance the reader to the first test element string comment = ""; string condition = ""; string result = ""; while (!reader.EOF) { Debug.Flush(); if (reader.IsStartElement("Tests")) { reader.Read(); continue; } if (reader.IsStartElement("Test")) { comment = ""; condition = ""; result = ""; reader.Read(); continue; } if (reader.IsStartElement()) { switch (reader.Name) { case "Comment": comment = reader.ReadElementString(); break; case "Condition": condition = reader.ReadElementString(); break; case "Result": result = reader.ReadElementString(); break; } continue; } //run the test on test end element if (reader.Name == "Test" && !reader.IsStartElement()) { Debug.WriteLine(""); Debug.Write("Test Case: "); Debug.WriteLine(comment); Debug.WriteLine(condition); Debug.WriteLine(result); //facts and rules available to these text cases RuleEngine.Evidence.Fact f1 = new RuleEngine.Evidence.Fact("F1", 1, 2d, typeof(double)); RuleEngine.Evidence.Fact f2 = new RuleEngine.Evidence.Fact("F2", 1, 4d, typeof(double)); RuleEngine.Evidence.Fact s1 = new RuleEngine.Evidence.Fact("String", 1, "String", typeof(string)); RuleEngine.Evidence.Fact in1 = new RuleEngine.Evidence.Fact("In", 1, 2d, typeof(double)); RuleEngine.Evidence.Fact out1 = new RuleEngine.Evidence.Fact("Out", 1, null, typeof(double)); f1.IsEvaluatable = true; f2.IsEvaluatable = true; s1.IsEvaluatable = true; RuleEngine.Evidence.ExpressionEvaluator e = new RuleEngine.Evidence.ExpressionEvaluator(); e.Parse(condition); e.InfixToPostfix(); e.GetEvidence += delegate(object source, EvidenceLookupArgs args) { if (args.Key == "F1") { return(f1); } else if (args.Key == "F2") { return(f2); } else if (args.Key == "String") { return(s1); } else if (args.Key == "In") { return(in1); } else if (args.Key == "Out") { return(out1); } else { throw new Exception("Unknown evidence: " + args.Key); } }; RuleEngine.Evidence.ExpressionEvaluator.Symbol r = e.Evaluate(); //throw exception up stack if an error was present Assert.IsFalse(r.type == RuleEngine.Evidence.ExpressionEvaluator.Type.Invalid && result != "Invalid"); Assert.AreEqual(result, r.value.Value.ToString().ToLower()); reader.Read(); continue; } //junk gos here reader.Read(); } }
public void TestEvaluateFunctionality() { //get a datareader stream from the xml file XmlReaderSettings xrs = new XmlReaderSettings(); xrs.ConformanceLevel = ConformanceLevel.Document; xrs.IgnoreComments = true; xrs.IgnoreProcessingInstructions = true; xrs.IgnoreWhitespace = true; Stream s = new StreamReader(AppDomain.CurrentDomain.BaseDirectory + @"\..\..\Expression\ExpressionEvaluator.xml").BaseStream; XmlReader reader = XmlReader.Create(s, xrs); //advance the reader to the first test element string comment=""; string condition=""; string result=""; while (!reader.EOF) { Debug.Flush(); if (reader.IsStartElement("Tests")) { reader.Read(); continue; } if (reader.IsStartElement("Test")) { comment = ""; condition = ""; result = ""; reader.Read(); continue; } if (reader.IsStartElement()) { switch (reader.Name) { case "Comment": comment = reader.ReadElementString(); break; case "Condition": condition = reader.ReadElementString(); break; case "Result": result = reader.ReadElementString(); break; } continue; } //run the test on test end element if (reader.Name == "Test" && !reader.IsStartElement()) { Debug.WriteLine(""); Debug.Write("Test Case: "); Debug.WriteLine(comment); Debug.WriteLine(condition); Debug.WriteLine(result); //facts and rules available to these text cases RuleEngine.Evidence.Fact f1 = new RuleEngine.Evidence.Fact("F1", 1, 2d, typeof(double)); RuleEngine.Evidence.Fact f2 = new RuleEngine.Evidence.Fact("F2", 1, 4d, typeof(double)); RuleEngine.Evidence.Fact s1 = new RuleEngine.Evidence.Fact("String", 1, "String", typeof(string)); RuleEngine.Evidence.Fact in1 = new RuleEngine.Evidence.Fact("In", 1, 2d, typeof(double)); RuleEngine.Evidence.Fact out1 = new RuleEngine.Evidence.Fact("Out", 1, null, typeof(double)); f1.IsEvaluatable = true; f2.IsEvaluatable = true; s1.IsEvaluatable = true; RuleEngine.Evidence.ExpressionEvaluator e = new RuleEngine.Evidence.ExpressionEvaluator(); e.Parse(condition); e.InfixToPostfix(); e.GetEvidence += delegate(object source, EvidenceLookupArgs args) { if (args.Key == "F1") { return f1; } else if (args.Key == "F2") { return f2; } else if (args.Key == "String") { return s1; } else if (args.Key == "In") { return in1; } else if (args.Key == "Out") { return out1; } else throw new Exception("Unknown evidence: " + args.Key); }; RuleEngine.Evidence.ExpressionEvaluator.Symbol r = e.Evaluate(); //throw exception up stack if an error was present Assert.IsFalse(r.type == RuleEngine.Evidence.ExpressionEvaluator.Type.Invalid && result != "Invalid"); Assert.AreEqual(result, r.value.Value.ToString().ToLower()); reader.Read(); continue; } //junk gos here reader.Read(); } }
public override void Evaluate() { ExpressionEvaluator e = new ExpressionEvaluator(); e.GetEvidence += new EvidenceLookupHandler(RaiseEvidenceLookup); e.Postfix = this.postfixExpression; ExpressionEvaluator.Symbol o = e.Evaluate(); //PERFORMANCE: this method is slow. base.EvidenceValue.Reset(); //clear previous values //result must be of this type or the expression is invalid, throw exception IEvidenceValue result = o.value as IEvidenceValue; //exit if null returned if (o.type == ExpressionEvaluator.Type.Invalid) { return; } //see if its value has changed, if so then set the value and call the events if (base.Value.Equals(result.Value)) return; //no change in value, dont raise an event base.Value = result.Value; RaiseChanged(this, new ChangedArgs()); }