Geeks With Blogs

News
Charles Young

In this article, I want to explore and shed some light on a feature of the Microsoft Business Rules Engine which I consider to be important in understanding the semantics of rules.   This is the use of ‘or’ to create a group of conditions within a rule.   We will see that ‘or’ has a very specific meaning in Microsoft’s rule engine and that this meaning may not be quite what you might have expected.   We will also see how the MS BRE simplifies the model, making rule creation more intuitive than it might otherwise have been, and we will compare and contrast the use of ‘or’ in the Microsoft Business Rule Engine with the use of ‘or’ in a similar Java-based rules engine called Jess.

 

To support this article, I have used a very simple example rule throughout.   We will look at how this rule can be expressed in MS BRE and Jess, and some subtle, but important differences.   I also want to explore the basics of how both engines represent rule sets as networks of node objects at run-time.   Another aim is to underline the declarative, pattern-matching nature of MS BRE and Jess rules by comparing rule conditions to SQL Select statements.

 

The Example Rule

 

Before I introduce the example rule, consider an even more basic rule as a starting point:

if

  or

    FactA.X > 5

    FactB.Y <= 15

then

 

This rule follows Microsoft’s approach in representing rules in MS BRL (Microsoft Business Rule Language).    MS BRL, itself, is a rather verbose XML syntax which I will not use in this article.   The above representation is based broadly on the way MS BRL rules are presented visually in Microsoft’s Rule Composer application.

 

Lets say that we assert two facts to the rule engine at run time, as follows:

 

FactA (X=6, Z=1)

FactB (Y=12, Z=1)

 

The inclusion of Z attributes is irrelevant here, but will be used later on.

 

What would you expect to happen?   If you have been using pattern-matching rules engines for any time, you will probably realise that the engine will evaluate the rule against each of the facts in turn.   The rule will match FactA and will also match FactB.    Hence, two productions (instances of the rule) will be added to the agenda, and each will fire in turn.   Each production will work on a different set of data.   One production will perform actions on FactA, while the other will perform actions on FactB.

 

This is very different from what you might expect if you are used to procedural coding using a general purpose programming language.   Look at the following example rule written in a C-type language:

if (FactA.X > 5 || FactB.Y <= 15)

{

    ;

}

In this case, the ‘if’ is a conditional branch statement.   The body of the ‘if’ will just fire once, even if both FactA and FactB meet the criteria.   Based on this, many modern programming languages implement ‘short-circuiting’ in their conditions.   If the first part of the test expression is true (i.e., FactA.X > 5), there is no need to evaluate the second part.

 

This difference between pattern matching rules and procedural rules can take a little getting used to at first.   It is one of the barriers that can make engines like MS BRE seem hard to understand to the novice rule developer.   You have to learn to think a little differently when designing your rule logic.

 

Let’s look at the example rule we will use through the rest of this article.   Here it is, represented in the same pseudo-code form.

rule1

 

if

  and

    FactA.Z == FactB.Z

    or

      FactA.X > 5

      FactB.Y <= 15

then

  FactA.PrintMsg("\r\nGot Here\r\n")

I’ve included an action that invokes a method on FactA.   This is not relevant to this article, and you can happily ignore the fact that I am ‘re-using’ FactA in this way.

 

In order to clarify the rule further, let me again present an approximation to this using a C-type syntax:

if (FactA.Z == FactB.Z && (FactA.X > 5 || FactB.Y <= 15))

{

    FactA.PrintMsg("\r\nGot Here\r\n");

}

Again, this representation is rather misleading.   Some readers may expect that, when processing the rule, the engine will implement features such as short-circuiting.   However, our example rule is not procedural.   It is declarative.   It provides a number of patterns (conditions) which are matched to available data.   A rule engine will find every possible match amongst the available data (‘facts’) for each of the patterns included in the rule.

 

So what happens now when we assert our two facts?   Do we get one or two productions on the agenda?  The inclusion of the additional condition has introduced a join into the rule.  We join FactA and FactB on their ‘Z’ values.   Our example facts both have the same ‘Z’ value, and so match.   

 

Let’s assume for a moment that two productions are added to the agenda.   In the earlier rule, each production worked on different data.   However, because of the join, each of our two productions will now process identical data.   This will be a combination of all matching facts – i.e., FactA and FactB.    This is why, if you have been using MS BRE for a little while, you may have ‘intuitively’ felt that just one production will be added to the agenda.   Unlike the first example, a second production would seem redundant.

 

Generally, what most rule developers would like to happen in this case is for the rule to be treated rather like the following SQL statement:

SELECT FactA.X, FactA.Z, FactB.Y, FactB.Z

  FROM FactA JOIN FactB

    ON FactA.Z = FactB.Z

 WHERE FactA.X > 5

    OR FactB.Y <= 15

There is a strong association between pattern matching rules and SQL Select statements.  SQL Selects operate on multiple data tuples (rows) contained in relations (tables), and produce data sets containing all the data that matches the declarative Select statement.  

 

Our example rule is used in a fairly similar fashion.   The facts asserted to the rule engine are tuples, and facts are distinguished and categorised by their type (or their ‘head’, in Jess terms) in a fashion that is fairly analogous to the use of tables in relational databases.   When the rule is processed, the engine will perform selections, joins and conditional evaluation in order to find all the matching data.   Each complete match is called a ‘production’, and the processing of a single rule may result in a set containing many productions.

 

We will see that the SQL statement above is not an entirely accurate representation of our rule.   However, for the time being, you can consider this to be a reasonably close equivalent to the conditions contained in the example MS BRE rule.   I would suggest that it provides a better insight into the true nature of the example rule than the C-type representation we saw earlier.   

 

Most developers, when encountering pattern-matching rules engines for the first time, tend to make the common mistake of treating rules as procedural.   If, instead, you grasp the deep similarity between pattern-matching rules and SQL Selects, you are far more likely to rapidly gain a practical proficiency in using these engines.   For some developers, another useful parallel might be to consider XSLT templates.   It is true that you can ‘call’ XSLT templates in a procedural fashion, but they are more generally used to match patterns within XML data.   If you know XSLT, it may be helpful to think of a rule as being rather like a template.

 

Microsoft’s approach to rule representation in MS BRL is open to some potential criticism here.   The ‘if…then…’ representation which Microsoft uses both in the Rule Composer UI, and also in their XML syntax, is prone to misinterpretation by novice rule developers because they will tend to associate this representation with conditional branching in general purpose, procedural, programming languages.   It may be a simple and familiar way to represent rules, but that very familiarity can be misleading.   I note, though, that Charles Forgy, who first described the algorithm used by most pattern-matching rules engines (including MS BRE) over quarter of a century ago, defines rules in his 1982 paper as “If-Then statements”.

 

We haven’t yet answered the question.   Do we get one production or two?   Before I provide an answer, let’s explore the representation of rules in MS BRE a little further.

 

Representing rule sets in MS BRE

 

The MS BRE (Microsoft Business Rule Engine) does not understand MS BRL directly.   Instead, MS BRL rule sets pass through two transformations before being processed.   First, they are transformed in a very straightforward manner into an object graph.    This graph represents the MS BRL in a direct fashion using classes defined as part of a document object model for Microsoft’s XML rule language.   The root node of the graph is a RuleSet object, and Microsoft has created a small library of ‘provider’ classes for obtaining RuleSets directly from files, a SQL Server rule repository, the Remote Rule Update service or from an OLE DB data source.

 

The runtime representation of rule sets is not executed directly by Microsoft’s rule engine If you are familiar with the details of Microsoft’s API, you may be aware that, when you call Execute() on a Policy object, that object interacts with an instance of a class called TranslateRulesetToRete.   This, in turn, interacts with the rules engine represented by an instance of the Executor class.   The job of the TrasnslateRulesetToRete object is specified clearly by the name of the class.   It performs the second transformation, translating the rule set object graph into a network called a Rete (pronounced ‘Ree-tee’).  A Rete is also an object graph containing ‘node’ objects and ‘memories’.   Microsoft’s engine executes the Rete directly.

 

This article is not the place to describe Charles Forgy’s Rete algorithm in detail.   However, note that the Rete is really just another way to represent rules.   It is rather different to the rule representations we are exploring because it combines all the rules contained in a rule set into a single graph (strictly, a Rete contains two distinct node graphs, termed ‘alpha’ and ‘beta’ respectively).   Individual rules largely loose their identity within the Rete.  However, the leaf nodes of the beta node graph, which are called ‘terminal’ nodes, or ‘p-nodes’ (‘p’ stands for ‘production’) represent individual rules in a direct fashion.

 

Let’s take a look at the Rete created by MS BRE for our sample rule.   The following diagram was generated using a reflection tool we developed to visualise the Rete networks produced by MS BRE.  We reflect on the actual Rete created at runtime, so this is a true representation of what the engine is doing.  The diagram shows nodes, but not memories.   I’m sorry, but for commercial reasons I can’t make the code available.

 

 MS BRE Rete - 1

  • The black node is the root of the Rete. 

  • The red nodes are ‘class’ nodes which select facts by type.   One node filters all the FactA facts, and the other filters the FactB facts.

  • The blue nodes are ‘select’ nodes which select facts, optionally using simple tests.   The two outer select nodes perform no tests.   They simply pass all the data on to the green nodes.  The inner select nodes perform the ‘x > 5’ and ‘y <= 15’ tests respectively.

  • The green nodes are ‘join’ nodes.   Each has two inputs (left and right activations), and performs a join on the facts that arrive via these inputs.   In each case, the join is done conditionally by testing for ‘FactA.Z == FactB.Z’

  • The grey node is a ‘terminal’ node representing the rule.   These nodes create ‘productions’.  Each production represents an instance of the rule together with a collection of facts which match all the conditions of the proceeding nodes.   The engine creates a production of each complete match it finds.

The ‘join’ and ‘terminal’ nodes represent the beta network.   The other nodes represent the ‘alpha’ network.

 

Consider a scenario where we assert our two example facts to the engine:

 

FactA (X=6, Z=1)

FactB (Y=12, Z=1)

 

When these facts are asserted, they enter the Rete at the root node, and pass through the network according to the directed arcs (arrow lines) shown in the diagram.  If you trace these facts through, you should be able to work out how the Rete executes the example rule.   Nodes with conditions only pass facts on where their conditions evaluate to true against those facts.   Join nodes perform joins between all facts that arrive from one input and all the facts that arrive at the other input.

 

We can now see that, given our two facts, the network results in two identical productions being created at the single terminal node.   This means, in this very simple example, that the one rule should ‘fire’ twice for our two example facts.   This is probably not what you would have expected or hoped as the rule developer.  The problem is that, for our two example facts, there are complete matches for both of the alternative conditions in the ‘or’ group.   Pattern-matching engines exhaustively find every possible match.   They don’t (naturally) perform short circuiting.

 

Try it out and see what happens.   If you do, you will think I have made some mistake.   MS BRE will ‘fire’ the rule exactly once for our two example facts, just as we might have hoped.   The Rete creates two productions, for certain, but only one is placed on the agenda.

 

Understanding ‘or’

 

In a declarative, pattern-matching rule, the semantics of ‘or’ are not the same as in a procedural rule.   We are used to thinking of ‘or’ as a conditional branching test in which we follow a particular route through code if either of two expressions linked by an ‘or’ equates to ‘true’.   Very often, procedural rules enhance efficiency by using short-circuiting.   If the first expression is evaluated as ‘true’, the procedural code does not evaluate the second expression.   In some cases, we may wish to force the evaluation of both expressions in order to invoke side-effects.   Many modern general purpose languages allow the developer to decide if they wish to use short-circuiting or not.

 

So much for procedural rules.   In the pattern-matching world, ‘or’ is different.   It is used to create a group of patterns within a rule.   There may be more than two such patterns.  Each pattern is treated rather like a sub-rule.   The results of the ‘or’ are the combined results of evaluating the rule multiple times, substituting different ‘sub-rules’ each time.

 

This may seem strange to the novice rule developer.   In one way, ‘or’ in pattern-matching rules is somewhat analogous to a bitwise ‘or’ operator.   A bitwise ‘or’ combines the bits from two inputs into a single output.   This analogy is very partial however.   In a pattern-matching rule, ‘or’ can be used to combine many patterns, rather than just two, and it does not combine the input, but instead provides a combination of multiple outputs.

 

A much better analogy is provided by considering a SQL equivalent.   A pattern-matching ‘or’ is strongly associated with the notion of UNION in SQL.   It is not identical.  For example, a single ‘or’ can group more than two patterns, whereas a single UNION combines just two SQL Select statements.   However, there is a strong connection between the two concepts.   In SQL, UNION is used to combine the results of multiple Select statements.   In effect, it allows a single SQL statement to comprise multiple Selects.   Each Select is processed, and the resulting data set is added to the overall data set returned by the SQL statement.

 

When you use an ‘or’ in a pattern-matching rule, it is as if you are cloning the single rule to make multiple rules.   For each of these notional cloned rules, the engine substitutes the ‘or’ group with one of the patterns contained in that group.   The results of processing the real rule is the same as processing a rule set containing the cloned rules.

 

To illustrate this, we can now ‘correct’ our SQL equivalent for the example rule.

SELECT FactA.X, FactA.Z, FactB.Y, FactB.Z

  FROM FactA JOIN FactB

    ON FactA.Z = FactB.Z

 WHERE FactA.X > 5

UNION ALL

SELECT FactA.X, FactA.Z, FactB.Y, FactB.Z

  FROM FactB JOIN FactA

    ON FactB.Z = FactA.Z

 WHERE FactB.Y <= 15

If you look carefully, you will see that I have used ‘UNION ALL’, rather than ‘UNION’.   This is deliberate.   We have seen that if our two example facts are traced through the Rete network, the Rete creates two identical productions at the terminal node.   Each production contains the same data (the two facts).   There is no de-duplication of these identical productions within the Rete.

 

De-Duplication In MS-BRE

 

Although UNION ALL is sometimes useful in SQL, the use of UNION is probably more common.   UNION de-duplicates the rows in the final result set.   In our example rule, we get two identical productions at the terminal node.  They are identical in that they belong to the same rule and act on the same data (FactA and FactB)

 

Although the Rete for our example rule results in two identical productions for the example facts, MS BRE implements an additional de-duplication stage.   This is implemented outside of the Rete network as part of the engine’s agenda.   An agenda is a combined, and prioritized, list of productions created by all the terminal nodes in a Rete.     Because we have just the one rule, there is only a single terminal node in our example, but most Retes will have multiple terminal nodes.

 

The set of productions created by any single terminal node is analogous to the final result set of a SQL statement containing Selects combined with UNION ALL.   When these productions are passed to the agenda, each set (on a per-rule basis) is de-duplicated.

 

MS BRE implements a fairly straightforward and intelligent approach to de-duplication.   Whenever a production is handed off to the agenda, the agenda attempts to add the production to a hashtable using the production object itself as the key.   This, of course, means that the production object is interrogated for its hash code.   The hash code is created over the name of the rule represented by the production (‘rule1’ in our case), the priority of the rule (which appears to be redundant), and on each working memory element (WME) associated with the production.   WMEs are objects which hold fact data (FactA and FactB, in our case), and each production is associated with a linked list of WMEs.   When a production is executed (we normally refer to this as ‘firing’ a rule), it processes the data stored in the WMEs using a list of actions.   The production key value is based in part on the hash code for each WME, which in turn is based on the hash code of the fact object contained by the WME.

 

If the key for a production matches the key of an existing production on the agenda, it is deemed a duplicate, and discarded.   If two or more productions share identical WMEs (i.e., references to the same fact objects) but are associated with different rules, they will not be deemed duplicates.   If they belong to the same rule, they will be deemed duplicates.   Note that two fact objects of the same type, containing identical data, will not, by default, have identical hash codes.   You could, of course, create a custom fact class and override the GetHashCode() method to return a hash code based on the data contained by fact class.   This would be very bad practice unless you can ensure that the data used to calculate a hash code is unique for each fact object.

 

This built-in de-duplication feature of MS BRE is undocumented.   However, it is an important aspect of the rules engine, and helps ensure that rules are processed in a way that most developers will find reasonably intuitive.   MS BRE forces a single rule with ‘or’ groups to be processed rather like multiple SQL Selects combined with a UNION, even though the Rete network itself performs the equivalent of a ‘UNION ALL’.

 

Here, then, is the final version of our SQL equivalent to the conditions contained in our simple example rule, taking into account the additional de-duplication feature of the agenda:

SELECT FactA.X, FactA.Z, FactB.Y, FactB.Z

  FROM FactA JOIN FactB

    ON FactA.Z = FactB.Z

 WHERE FactA.X > 5

UNION

SELECT FactA.X, FactA.Z, FactB.Y, FactB.Z

  FROM FactB JOIN FactA

    ON FactB.Z = FactA.Z

 WHERE FactB.Y <= 15

A Jess Comparison

 

By way of comparison, we will now look at the approach used for a well-known Java-based pattern-matching engine called Jess.   Jess, I should note, is really rather more than a rules engine.   It provides an entire scriptable rule processing environment and language.

 

Jess implements the same Rete algorithm used in MS BRE.   It stands, however, in a different ‘tradition’ to MS BRE, and traces its lineage through CLIPS (a public domain Rete rules engine written in C) to OPS5.   OPS5 is about twenty five years old, and is a Rete engine written in LISP.   Rules (and other constructs) are expressed in a LISP-like syntax for all three engines.  

 

A port of the example rule to Jess is shown below.   The rule is represented in Jess’ syntax, rather than a pseudo code.   As well as the rule definition (defrule), there are two template definitions (deftemplate) for the two fact types and the ‘slots’ they contain.

(deftemplate FactA (slot X) (slot Z))

(deftemplate FactB (slot Y) (slot Z))

 

(defrule rule1

  (or (and (FactA (Z ?z) (X ?x&:(> ?x 5)))

           (FactB (Z ?z)))

      (and (FactA (Z ?z))

           (FactB (Z ?z) (Y ?y&:(<= ?y 15)))))

  =>

  (printout t crlf "Got Here" crlf))

If you are unfamiliar with engines such as Jess and CLIPS, the syntax is unlikely to make much sense at first.   The important thing is always to remember that this rule is defined for a pattern matching engine.  

 

The rule is expressed in a freeform syntax, and is divided into a left hand side (LHS) and right hand side (RHS) around the ‘=>’ symbol.   The LHS is broadly equivalent to the ‘if’ section of an MS BRL rule, and the RHS is broadly equivalent to the ‘then’ section[1].   The LHS contains a number of patterns.    To understand the rule, consider that the engine will find as many matches as possible amongst the available facts for each of the patterns in the LHS.   For each distinct set of matches for all the patterns, a ‘production’ will be added to the rule engine agenda.   Each production will be executed in turn, and will perform the actions specified in the RHS of the rule[2].

 

Consider the inner pattern in the first line of the rule which is as follows:

 

(FactA (Z ?z) (X ?x&:(> ?x 5)))

 

This pattern matches all FactA facts which contain Z and X slots.   A slot is a named attribute of a fact.  The pattern binds the Z slot to a variable (‘?z’), and binds the X slot to another variable (‘?x’).  These variables are used in later patterns within the rule. 

 

As you can see, the part of the pattern which binds the X slot to ?x is followed by some additional content.   This extends the basic test for the existence of the X slot with an additional test.   These two tests are combined using the ‘&’ (and) operator.  The second condition is :(> ?x 5) which represents a function which tests the ?x variable to see if it is greater than 5.

 

In plain English, the pattern represents a condition expressed as ‘If a FactA fact has a Z slot and an X slot, and the value of the X slot is greater than 5…’.

 

I’ll leave you to work out the rest of the rule.   Note the use of (and) and (or) conditional elements to combine the various patterns.   Also, note the way in which the use of the same variable in different patterns results in conditional joins.

 

Here is the resulting Rete.   In this case, the diagram was generated using a Rete network viewer supplied as part of Jess:

 

 Jess Rete - 1

A brief comparison of the graphical representation of the Rete networks may suggest several differences between the Jess network and the corresponding MS BRE network.   In fact, there are no very significant differences.   Jess and MS BRE have different implementation details in the way they perform left activations on beta nodes from alpha memories.   That statement may not make much sense to the average reader, as it requires a detailed understanding of the Rete algorithm, but please accept that the two networks are logically equivalent in this respect.   Jess uses special adapter nodes (shown in orange) to perform left activations directly from alpha memories.   These nodes do not perform any conditional tests.   Microsoft has implemented the same functionality directly within their ‘select’ nodes, which is why two of the select nodes in the MS BRE Rete have no conditional tests.

 

Another obvious difference is that the Jess network contains two terminal nodes, whereas the MS BRE network contains just one.    A terminal node represents a ‘production’, and productions are largely synonymous with rules.   However, Jess treats our example rule as if it were two rules.  The network viewer used to create the graphical representation of the Rete also allows us to inspect these two internal rules, represented by the two terminal nodes.   Here are those rules:

(defrule MAIN::rule1

   (MAIN::FactA (X ?x&:(> ?x 5)) (Z ?z))

   (MAIN::FactB (Z ?z))

   =>

   (printout t crlf "Got Here" crlf))

 

(defrule MAIN::rule1&1

   (MAIN::FactA (Z ?z))

   (MAIN::FactB (Y ?y&:(<= ?y 15)) (Z ?z))

   =>

   (printout t crlf "Got Here" crlf))

The Rete produced by Jess shows us clearly how ‘or’ is interpreted by a pattern matching engine.   Logically, there is no significant difference between the Jess and MS BRE Retes.   Both undertake exactly the same evaluations in order to produce identical results.   Given the same two example facts, they both create two productions containing identical data.  MS BRE, however, then de-duplicates these results, whereas Jess does not.   When our example rule is executed using MS BRE, a single production will be placed on the agenda.   When the Jess equivalent is run, both productions will be placed on the agenda, and each will ‘fire’ in turn.

 

Avoiding de-duplication in MS BRE

 

Armed with a more detailed understanding of the nature of ‘or’, there may be times when you would like to avoid de-duplication in MS BRE.   The solution is obvious.   There is no way of switching off the de-duplication feature, so the only other approach is to create multiple rules, just like Jess does internally.   Here are two rules which are equivalent to the two productions created internally by Jess:

rule1

 

if

  and

    FactA.Z == FactB.Z

    FactA.X > 5

then

  FactA.PrintMsg("\r\nGot Here\r\n")

 

rule1_1

 

if

  and

    FactA.Z == FactB.Z

    FactB.Y <= 15

then

  FactA.PrintMsg("\r\nGot Here\r\n")

Here is the Rete created by MS BRE for a rule set containing these two rules.

 

 MS BRE Rete - 2

Note that this Rete is just like the original, except that it has two terminal nodes.   It is logically equivalent to the original Rete.   However, the use of two terminal nodes will prevent de-duplication from occurring, and, given our two example facts, two productions, rather than one, will be added to the agenda, each containing identical data.   The Rete is identical to the Jess Rete except for the (entirely insignificant) difference in implementation at the boundary between the alpha and beta networks.

                                            

Avoiding Duplicates in Jess

 

What if you want to avoid duplicates in Jess?   To the best of my knowledge, Jess does not offer any equivalent form of automatic de-duplication (I will be glad to be corrected if anyone knows differently). 

 

Older versions of Jess supported a ‘unique’ conditional element which could be used to short-circuit matching in the Rete.   This could probably have been used to create a rule which would exhibit the same behaviour as the MS BRL rule.   However, in the current version, this feature is no longer supported.   Instead, the only approach I am aware of is to use the ‘exists’ conditional element.   Here is a rule that provides the same results as for MS BRL

(deftemplate FactA (slot Z) (slot X))

(deftemplate FactB (slot Z) (slot Y))

 

(defrule rule1

  (FactA (X ?x) (Z ?z))

  (FactB (Y ?y) (Z ?z))

  (exists (or (test (> ?x 5))

              (test (<= ?y 15))))

  =>

  (printout t crlf "Got Here" crlf)) 

The ‘exists’ condition evaluates to ‘true’ if at least one match is found for the patterns it contains.   Even though, for our two example facts, there are two matches, this condition results in just one production at a single terminal node.   ‘Exists’ is actually represented in the Rete by using a couple of ‘not exists’ nodes.   The Rete effectively uses a double negative to test for existence (“ if ABC does not not exist…”).   Here is the resulting Rete with the ‘not exists’ nodes shown in yellow:

 

 Jess Rete - 2

I won’t describe this further in any detail.   Tests for existence and non-existence are an interesting subject in their own right, but I will keep that for another time.  Note, however, that this Rete is very different to the Retes we saw earlier.  

 

MS BRE cannot represent this Rete at all because the Microsoft’s engine unfortunately does not implement ‘not exists’ nodes.   Such nodes are specialised join nodes known as NotCE nodes in Jess, or more generally as ‘negated conjunction’ nodes.   Although MS BRE does have an ‘exists’ predicate, this only applies to XML facts, and is not an equivalent to Jess’ ‘exists’ conditional element.   It performs XPath evaluations on XML using non-specialised nodes.   This lack of support for so-called ‘weak negation’ is a significant limitation of MS BRE, and limits its expressivity.   I would hope that Microsoft finds a way to add this feature in some future version of their engine.   Almost every other Rete engine in existence supports negated conjunction.



[1] I say ‘broadly’ equivalent because there is a difference.   The rule definitions used by Jess, CLIPS, OPS5, etc., define all required patterns in the LHS.   In MS BRE, however, the ‘if’ section often does not contain all the patterns.   Some patterns are implied by the contents of the ‘then’ section.   Specifically, if an action uses a fact of a specific type, and no fact of that type is referenced anywhere in the ‘if’ section, the Rete will contain an additional class node to test for this fact type, and will feed these facts through to the terminal node representing the rule.    In Jess rules, there will be an explicit pattern in the LHS for facts of that type.   The presence of these implicit patterns often causes novice MS BRE rule developers problems because they fail to realise they need to assert facts of the required type.

[2] This is, of course, a gross simplification of the true approach taken by pattern-matching production engines.   For the sake of simplicity, I will not describe the match-resolve-act cycle here, or the way productions are added to and removed from the agenda in relation to this cycle.

Posted on Wednesday, May 24, 2006 10:15 PM | Back to top


Comments on this post: MS BRE: Using ‘OR’ in MS BRE Rules

# re: MS BRE: Using ‘OR’ in MS BRE Rules
Requesting Gravatar...
The orange Nodes in JESS is called LeftInputAdapterNode. The reason for this is purely a design decision. By using a LeftInputAdapterNode, all AlphaNodes just right activate subsequent BetaNodes. In pseudocode, it means when AlphaNodes propogate facts, it calls assertRight on BetaNodes. By making a LeftInputAdapterNode (LIANode), it keeps the design simple. LIANode calls assertLeft when facts are propogated to the first join of a rule with multiple conditional elements (aka object pattern).

To do this without a LIANode, the alphaNode would need to remember which nodes should propogate using assertLeft vs assertRight. Since a BetaNode will have either a Alpha or Beta Node above it in the network, the preceding node has to be the one to remember which side to activate. Activate in this case just means which method to call.

hopefully that will help other understand how CLIPS, JESS and other rule engines handles right vs left activation.
Left by Peter Lin on Jul 12, 2006 12:41 AM

# re: MS BRE: Using ‘OR’ in MS BRE Rules
Requesting Gravatar...
great article.. though will possibly take multiple readings to really digest all of this
Left by Atul Gupta on Sep 01, 2006 3:27 AM

# Using XPath to handling XML in the Microsoft Business Rules Engine
Requesting Gravatar...
A couple of days ago I found myself, yet again, introducing another BizTalk developer to the delights...
Left by Charles Young on Oct 16, 2006 4:17 AM

Your comment:
 (will show your gravatar)


Copyright © Charles Young | Powered by: GeeksWithBlogs.net