Features
Engine
- Full Rete Implementation -- with high performance indexing
- Dynamic RuleBases
- Stateful and Stateless Execution Modes
- Async operations
- Rete and Sequential Rete
- Rule Agent
- Optional Data Shadowing
- Pluggeable Dialects
Propositional Logic
- Literal Restriction
- Variable Restriction
- Return Value Restriction
- Jointed and dis-jointed Connectives allowed - '&&' '||'
- inline-Eval
First Order Logic (Quantifiers)
- And
- Or
- Exists
- Not
- Accumulate
- Collect
- From
- Forall
- Nesting of any CE inside of 'and' and 'or'
- Support for both infix and prefix 'and'/'or' CEs
- Nesting and Chaining of 'from', 'accumulate', 'collect'
Execution Control
- Conflict Resolution (salience) Now pluggeable
- Agenda Filters
- Agenda Groups
- Activation Groups
- Rule Flow
- Attributes ( no-loop, lock-on-active )
Temporal Rules
- Scheduler for rule duration will fire when a rule is true for X duration
Truth maintenance with Logical Insertions
Event Model
- Working Memory, Agenda and Rule Flow
Configurable
- All Rete optimizations and execution behavior can be configured
Authoring
- Technical rules: DRL and XML formats supported
- Template based DSLs
- Guided Editor
- BRMS and Eclipse
- Decision Tables (Excel, Open Office)
BRMS (Knowledge Asset Management System)
- Authoring and Storage DRLs, RuleFlows, Decision Tables, Business Rules (Guided Editor)
- Multi level Versioning, at both the rule and package level
- Classification
- Deployment
- Built on Standards and Open APIs - JCR (JSR 170) Dublin Core, GWT
More Expression flexibility
3.0.x only allows comma separated field constraints. 'or' could be used at the CE level, but resulted in subrule generation.
- Can now use && and || inside the pattern for multiple values on the same field and across files – no subrule generation.
- Can be as deeply nested as you like...
OLD:
Person(age > 30, age < 40 ) OR Person (hair == “black”)
NEW:
Person(age > 30 && < 40 || hair == “black”)
Auto vivification of variables in dialect
OLD:
Cheese(oldPrice : oldPrice, new Price == (oldPrice * 1.10))
NEW:
Cheese(newPrice == ( oldPrice * 1.10 ))
Drools 3.0 only supported infix 'and'/'or' constraints, which is idea for some situations but more complicated to read for others
OLD
Person(name == "matthew") or Person(name == "john")
Drools 4.0 allows for both infix and prefix:
NEW:
(or Person(name == "matthew")
Person(name == "john") )
3.0.x had to always declare the variable, causing clutter, can now access direct properties of pattern variables.
OLD:
p: Person (personId : id)
i: Item (id == personId, value > 100)
NEW:
p: Person()
i: Item(id == p.id, value > 100)
Eval rewrite for complex expressions, engine works out best way to do it – of course, flat models work best for performance.
OLD:
Person($pets : pets) eval ($pets[’rover’].type = “dog”)
NEW:
Person(pets[’rover’].type == “dog”)
More Powerful CEs
3.0:
- 'and'
- 'or'
- 'not' Could only nest a single Pattern
- 'exists’ Could only nest a single Pattern
4.0:
- 'forall'
- ‘from’
- ‘collect’
- ‘accumulate’
- 'not' - Now allows any nested CE
- 'exists' - Now allows any nested CE
Forall, true when the pattern is true for all facts
forall(Bus (color==”red”))
From, Pulls and unifies against non-working memory data ( can call Hibernate queries )
Restaurant ( rating == “fivestar” )
from hbSession
.getNamedQuery (”restaurant query”)
.setProperties ([key1 : value1, key2 : value2])
.list()
Collect - Allows you to use cardinality eg: when there are more than 6 red buses:
List(size > 6) from collect ( Bus(color == “red”) )
'from' can be chained. Following is true if all items in a cart have a price greater than 10
List(size == ($list.size)) from collect(Item(price > 10 )) from $cart.items Accumulate,
More powerful 'Accumulate' allows you to execute actions on each matched fact in the set
$total : Integer() from accumulate( $item : Item( )
init(count = 0; total=0)
action(count++;total += $item.price)
result( return total/count )
)
You can also use multiple patterns in your 'Accumulate'
$cheesery : Cheesery( totalAmount > 30 )
from accumulate( $person : Person( $likes: likes) and $cheese : Cheese( type == $likes ),
init( Cheesery cheesery = new Cheesery(); ),
action( cheesery.addCheese( $cheese ); ),
reverse( cheesery.removeCheese( $cheese ); ),
result( cheesery ) );
Line Debugger and new Rete Viewer
click to enlarge
Debug views
New rule “perspective” to configure IDE for rules as needed
click to enlarge
Debugging Pluggeable Dialects
click to enlarge
Eclipse Guided Editor
Template based DSLs
click to enlarge
Decision Tables

click to enlarge
Rule Flow

click to enlarge

click to enlarge
Categorization
Version History
Rule explorer with categorization

click to enlarge

click to enlarge
Friendly rule editing with web guided editor
Friendly rule editing

click to enlarge
BRMS Decision Tables

click to enlarge