|
|
Comments and Discussions
|
|
 |

|
Do you have any updated version of the engine? Or the most recent is posted here.
As a side note, the evaluation for >, >=, <, <= should be using TotalMinutes and not TotalDays for DateTime objects. Otherwise, a DateTime that has time will not properly evaluate.
/Z
|
|
|
|

|
Hello.
The article is very good and I like to use the Evaluation Engine on a system I'm doing, I wonder if you could support me on your core if you would take ...
regards
|
|
|
|

|
I have a table containing objects size and weight and I need a result based on this formula
sumofAll((size+weight)/sumofAll(Weight))
e.g
Object1 size 2 weight=3
Object2 size 4 weight=4
Object3 size 3 weight=5
result = (((2+3)/(3+4+5))+ ((4+4)/(3+4+5))+((3+5)/(3+4+5)))
Is there any way to tweak this engine and get appropriate result?
modified 21 Nov '11 - 0:27.
|
|
|
|

|
Great work! Very clear! Just wanted to point out one very, very minor tweak that increases performance by a lot. Remove statement "System.Diagnostics.Debug.WriteLine(item.TokenName);" from the Evaluator.Evaluate method. Really appreciate the hard work put into this!
-- Modified Wednesday, June 15, 2011 4:34 PM
|
|
|
|
|

|
Hi, you have done a great job!
How can we define a variable? (not in runtime)
I want to define some constants like pi, e, .... How should I do that?
|
|
|
|

|
It�s a great job Parsing the expressions. It�s a wonderful job Evaluating the expression and its helpful in a project in my work.
|
|
|
|
|
|

|
There is this little bug to be noted, if your culture has different datetime formatting, currency formatting etc. Evaluation Engine fails.
To get rid of that totally, i used
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
Consider it as a bug. Also If you Try To Add a Variable Named ORTALAMA (meaning average in Turkish) Evaluation Engine Parses This as [OR]TALAMA, considering [OR] as operator, to avoid this bug i renamed the variable to @ORTALAMA, which solved the issue.
Have a nice day.
Oh! But For God's Sake This Was One Hell Of A Code You Shared, Loved It. (Got My 5)
Thank You So Much
|
|
|
|

|
Thanks for a nice job, it does save much of my time.
Here I got "Invalid Rule Syntax" error for below code:
val := Replace[Substring["$1,000",1,5], ",", ""];
a:=IIF[val>0, 123, 0];
Any idea? Thanks in advance!!
|
|
|
|

|
This article sets the standard for how articles should be written. The explanation and examples were thorough and very well thought out.
|
|
|
|

|
Hi Donald.
No doubt this is a very interesting topic and u have done justice to it.
I had a similar requirement once but i chose the easy way out using already existing scripting languages.Most script languages like vbscript and javascript have a very handy function called Eval which can evaluate any string containing expressions and functions.You can call script engines from c# using Msscriptcontrol or alternatively create a dll in j# containing the eval function.would love to elaborate but am typing from my mobile.
I have found it quite satisfactory and highly performant.
|
|
|
|

|
I've tried your great library, but I was still receiving errors: "Syntax Error: Expecting numeric values..."
After step-by-step debugging I've found place where double result is converted to string: Result = new Parser.TokenItem(dResult.ToString()...
This is culture dependent. In polish culture the decimal point is coma.
So string with double result with coma decimal point was rejected by the:
if ((Support.DataTypeCheck.IsDouble(LeftOperand.TokenName) == true) && (Support.DataTypeCheck.IsDouble(RightOperand.TokenName) == true))
I've applied simple solution:
In the Evaluator class I've addded a NumberFormatInfo private variable:
System.Globalization.NumberFormatInfo nfi;
Then set it up in the constructor:
public Evaluator(Parser.Token Tokens)
{
token = Tokens;
this.nfi = new System.Globalization.NumberFormatInfo();
this.nfi.NumberDecimalSeparator = ".";
}
Then I've applied this format provider into every dResult.ToString():
Result = new Parser.TokenItem(dResult.ToString(nfi)...
And that's all. Now works perfect for me.
Thank you very much for your hard work.
Best regards.
|
|
|
|

|
Hi,
U done a great job.
I just wondering inside the rule, is there any function that support variable input and output for example rule header like:
~Rule~
OutputVar := functionName(InputVar);
return 2*InputVar;
~EndRule~
maybe something like this
Fauzi
|
|
|
|

|
You can check FlexRule for more options.
|
|
|
|

|
Thanks a lot for the good job you have done. It's great.
I noticed that it's banned to write an assignment in an operandfunction. Is there any possibility for this little flaw improved?
|
|
|
|

|
I would be interested in this functionality as well. Especially in the If-else-end where I would like to set a variable for further processing.
*EDIT* Nevermind, I figured out how to accomplish this after looking at it for little bit. I just used an assignment to an IIF.
Example:
wc := ((((R4 - R3)/R4)*100000) - .26 * (((R3 - R2)/R4)*100000) - 11000) * 1.69;
wc2 := iif[wc<10000, 10000, wc];
modified on Wednesday, December 3, 2008 7:40 AM
|
|
|
|

|
This is an impressive body of work, and I appreciate how much effort has gone into this. I have been looking around for an embeddable expression engine for a couple of years and tried several from this web site. None of them really met my needs for reliability, accuracy and simplicity.
Then I stumbled on an expression engine right under my nose, and built into .NET framework - the ADO DataTable Expression column!!
I used this in a recent project and it worked great. Its fast, easy to use, and requires no additional libraries.
Basically, you do this:
1. create an empty ADO Datatable
2. define some columns to hold data
3. make one or more columns expression columns.
4. Add a datarow
5. Set the input columns with data
6. Extract the expression value from your expression column.
To be sure, this expression engine has a limited number of functions, but it does support the powerful LIKE and IN operators (SQL syntax). You can use SUBSTRING, TRIM, LIKE, LEN, LIKE, and IN.
For most application needs, this basic set of functions and operators are quite adequate.
So here is simple example of how to use the expression engine to concatenate three variables:
Dim oDatatable As New DataTable("MyTable")
oDatatable.Columns.Add(New DataColumn("result", GetType(String)))
oDatatable.Columns.Add(New DataColumn("A1", GetType(String)))
oDatatable.Columns.Add(New DataColumn("B1", GetType(String)))
oDatatable.Columns.Add(New DataColumn("C1", GetType(String)))
oDatatable.Columns("result").Expression = "A1 + ',' + B1 + ' ' + C1 "
Dim oDataRow As DataRow = oDatatable.NewRow
oDataRow("A1") = "Raleigh"
oDataRow("B1") = "NC"
oDataRow("C1") = "USA"
oDatatable.Rows.Add(oDataRow)
MsgBox("Expression result = " & oDataRow("result"))
Tip: I use Excel notation for column names, but you can use any valid ADO Datatable column name.
Here is a second example that makes use of the inline IF statement to determine if all three values are not null:
Dim oDatatable As New DataTable("MyTable")
oDatatable.Columns.Add(New DataColumn("result", GetType(Boolean)))
oDatatable.Columns.Add(New DataColumn("A1", GetType(String)))
oDatatable.Columns.Add(New DataColumn("B1", GetType(String)))
oDatatable.Columns.Add(New DataColumn("C1", GetType(String)))
oDatatable.Columns("result").Expression = "IIF((LEN(A1) + Len(B1) + Len(C1)) > 0, True,False)"
Dim oDataRow As DataRow = oDatatable.NewRow
oDataRow("A1") = "Raleigh"
oDataRow("B1") = "NC"
oDataRow("C1") = "USA"
oDatatable.Rows.Add(oDataRow)
MsgBox("Expression result = " & oDataRow("result"))
Features:
1. You can nest expression to almost any depth
2. The result column type includes Boolean, numeric, date or string.
3. You can refer to multiple datatables in the expression.
4. The datatable can have multiple rows and then you can use aggregate functions like AVG, SUM, etc.
We built a nice user interface to allow the user to pick the data elements, operator and test values. It worked great.
I did some performance tests on this, and found this engine was adequately fast for all my needs.
I hope this helps others who may be looking for a simple, fast, and built-in engine.
Mitch Stephens
modified on Sunday, November 2, 2008 9:23 AM
|
|
|
|

|
Great! Thanks for the comment (and vote?) Mitch.
Does this ADO solution handle an expression like this?
IIF((A1/0)>0,true,false)
Thanks,
Donald.
|
|
|
|

|
Don,
Yes, the ADO column expression engine does support this expression:
IIF((A1/0)>0,true,false)
Actually, if you do this: (A1/0) and return it as a string, the result is 'Infinity'.
Of course you can't cast this expression to any numeric data type (Int, Long, etc), since Infinity is larger than all of the max values.
Mitch
Mitch@actmate.com
|
|
|
|

|
Brilliant!!! Thank you very much.
|
|
|
|

|
the ADO for an expression engine is indeed a good tool but it is very poor when it comes to date calculations
|
|
|
|

|
Excellent article.
By using the following function
abs[year[now[]]* -1] > 2000
I have an error
function Year[]: Operand Function requires at least 1 parameter
Thank's
|
|
|
|

|
Hmmm.....I just downloaded the code and tried your expression. It gave me the correct result. I also tried this expression and got the correct result:
iif[abs[year[now[]]*-1]>2000, "True Condition", "False Condition"]
|
|
|
|

|
With the function iff working properly, but not with other features. For Example
year[now[]] or month[now[]]
Thank's
|
|
|
|
|

|
Did anyone manage to locate InsPolicyA.Rule or have a copy of it?
Thanks
|
|
|
|

|
I'm sorry Malcolm....I had to re-build/re-image my development computer and I lost the InsPolicyA.Rule file; so I don't have it.
|
|
|
|

|
Great code. But i gotta tell ya, it has some serious bugs. For example, you at least could of make your algorithm smart enough to filter out white spaces. Another thing, you have all kinds of non-standard functions built-in to your evaluator, but hardly any of the standard mathematical functions like Log, In, Arc Tangent, Hyperbolic Tangent, and most importantly the Factorial sign (n!). It also has some bugs with basic math expressions. However, this is the third math parsing code i've downloaded, and yours is the best by far. The first one couldn't even do negative numbers , and the next one just plain sucked. I finally decided the best way to get code to do exactly what i want is to make it myself, so i made my own math parsing algorithm. It can support nesting, binary operators (^*/+-), has built-in functions like tan, sin, cos, atan, log, ect., and is even able to parse the input of numbers such as 5.3534534E+534. I have integrated it into a simple calculator app and am rigorously testing it with the most complicated expressions i can think of. I have a handheld calc that has one of those natural displays, but i lost it and until i find it, i've been using your code to double-check mine (at least with the expressions it will evaluate). Once i'm sure it has NO BUGS AT ALL, i will put it on Code Project as an article. A math parsing algorithm is one of those things that you just can't do half way, you get what i'm saying?
void Play() { try { throw Ball(); } catch (Glove) { } finally { Play(); } }
"Failure is only the opportunity to begin again, this time more wisely."
"Don't ask for a light load, but rather ask for a strong back."
|
|
|
|

|
Hi Donald,
It is a great example of using expressions with rule engine. given you 5/5
Could you attach InsPolicyA.rule file which is missing while running
the Console test application.
Thanks
Paresh.
|
|
|
|

|
Expression like 0.5*2 gives the error (result = 0).
Expression like 0.5+2 gives the error too (result = 2).
Is it planned to support float constants and variables?
|
|
|
|

|
I've looked at your source code and have found out where the bug is.
Please take a look into the code listed below.
This code is region depended. Please fix this.
public double TokenName_Double
{
get
{
double result = 0;
if (Double.TryParse(tokenName, out result) == true)
return result;
else
return 0;
}
}
i think code listed below is more correct:
if (Double.TryParse(tokenName, NumberStyles.Any, new CultureInfo("en-Us"), out result) == true)
|
|
|
|

|
I just tried your 2 expressions (0.5*2 and 0.5+2) and they worked fine. Please remember that you need to click on the "Parse" button in the toolbar every time you change the expression.
|
|
|
|

|
First off, Great job, this is great work and saves me hours of work. The degree of difficulty is high, I know because I started down this path to solve my current problem and decided to look elsewhere for the solution because of how hard it is to parse expressions.
I did notice one problem. I haven't had time to confirm this one and I did run across a comment inside the code that this should now be working, but in testing one IIF embeded in another, I didn't get the result I expected.
When I type in:
iif[iif[True,True,False]=True,1,2] which should return 1
Instead I get a rules syntax error. Am I doing this wrong?
I also tried
a := iif[false,true,false];
iif[a,1,2]
Which does work, so I am able to get around the problem, but I would rather tell the users that the first one should have worked as well.
Thanks for the good work.
Peter
|
|
|
|

|
Hi Donald,
I am looking for a rules engine, I only have abot 200 rules and this rules are very simple. The 'big' products out are overkill, maybe yor product fits. Please send me some details. Thanks. (gerhard.kreuzer@liftoff.at)
With best regards
Gerhard
|
|
|
|

|
I'm sorry Gerhard, my Rules Engine is still under development and I'm not sure I will be releasing it as open source.
I'll keep you posted.
Donald.
|
|
|
|

|
Hi Donald,
I didnt say, I want it for free, so if the licence model is reasonable for me, and the product meets my specs, you just talked to your first customer .....
With best regards
Gerhard
PS: Please keep me informed, Thanks a lot.
|
|
|
|

|
Check http://www.flexrule.com the express version will be available to download very soon.
It supports execution and RETE-based inference engine.
|
|
|
|

|
Thanks, I keep my eyes on it ....
|
|
|
|

|
Hey,
Have you got a chance to take a look at it yet?
|
|
|
|

|
Hi,
I am so sorry, but I dont have a look at it. I have to finish a project before the weather get cold here in Austria, because the equipment have to be in place, later on, nobody can reach it. Unfortunately the cold weather starts unusually early this year and now panic rules my customer .....
But as soon as I have done it, I start checking ...
Sorry about that
Gerhard
|
|
|
|

|
If you are still looking for an effective solution, check out www.awfulogic.com.
|
|
|
|

|
You can just check my rule engine here: FlexRule
|
|
|
|

|
Great article, 5 starts.
I am unable to fine the file "InsPolicyA.rule", where do I find it.
Thanks
|
|
|
|

|
You right....It's missing. I must have forgot to included it in the update. I'll get it posted.
Thanks,
Donald.
|
|
|
|
|

|
This has been a fascinating article, and while I am normally read-only, both WTJW's comment (general-purpose programming language) and BooGhost's comment (nobody but a programmer is going to be writing rules) raised questions in two areas that I hope you can clarify.
1. These comments brought to mind domain specific languages (DSLs -- for the sake of discussion, I consider a DSL as a language tailored such that computer literate domain experts could essentially write small programs; e.g., consider a rule for a medical application -- if patient has a high fever, alert emergency services).
Is it your intent that your engine be able to support DSLs? If so, what aspects of your engine would facilitate that? Have you considered how your engine might support a GUI to enable a domain expert (who has essentially adopted the role of programmer) to be more productive?
2. As I'm sure you're well aware of, there are a number of rules engines available, so a reasonable question would be how you see your rules engine interoperating with them? For example, would your engine support import and export in one of the common formats (say, for example, RuleML)?
Regards,
arh
|
|
|
|

|
I'm not sure I understand what you're trying to achieve here... In what way is your creation different from a general-purpose programming language such as Perl or Python? Is it perhaps going to be part of a BRE that combines "facts" (using e.g. the Rete algorithm) to produce new facts? In either case, it seems to me that you are reinventing the wheel -- surely it would be better to harness an existing language (perhaps an interpreted one with nice clean syntax such as Python) and use that? The advantages of that are (a) features (e.g. loops, arrays etc.), (b) proven reliability and (c) the enormous support base of existing users. From reading your article, which I must say is comprehensive and well-written, and the replies so far, I can't (yet) see what advantages your "invent a brand new language" approach has.
That's not to say that reinventing the wheel (here, developing your own language and the tools to parse it) is not fun -- it is!
WTJW
|
|
|
|

|
Wow. With all the CodeDom and language compilation features already built into .NET, you just HAD to go and write your own. I know, I know, .NET's code services just suck ass.
Seriously, nobody but a programmer is going to be writing rules. You think your new "language" is going to be somehow more... idiot friendly? fun? what?
And lets say, for the sake of argument, that you did manage to make this holy grail of languages.. a language capable of expressing complex concepts that can be manipulated by the average human being... do you REALLY want the average human being writing rules? I can't think of a single scenario where your code would be of any practical use.
That's not to say you didnt do well.. I have no comment regarding the quality of your code.. I'm sure if you say it works then it works. That's not the point I'm making. Your time could be spent in much more productive persuits.
|
|
|
|
 |
|
|
General News Suggestion Question Bug Answer Joke Rant Admin
|
The Evaluation Engine is a parser and interpreter that can be used to build a Business Rules Engine. It allows for mathematical and boolean expressions, operand functions, variables, variable assignment, comments, and short-circuit evaluation. A syntax editor is also included.
| Type | Article |
| Licence | CC (ASA 2.5) |
| First Posted | 23 May 2008 |
| Views | 116,840 |
| Downloads | 2,065 |
| Bookmarked | 341 times |
|
|