What is inference and how does it facilitate good rule design and maintenance
The summary of this was:
- De-couple knowledge responsibilities
- Encapsulate knowledge
- Provide semantic abstractions for those encapsulations
The previous example was issuing ID cards to over 18s, in this example we now issue bus passes, either a child or adult pass.
rule "Issue Child Bus Pass" whenAs before the above example is considered monolithic, leaky and providing poor separation of concerns.
$p : Person( age < 16 )
then
insert(new ChildBusPass( $p ) );
end
rule "Issue Adult Bus Pass" when
$p : Person( age >= 16 )
then
insert(new AdultBusPass( $p ) );
end
As before we can provide a more robust application with a separation of concerns using inference. Notice this time we don't just insert the inferred object, we use "logicalInsert":
rule "Infer Child" whenA "logicalInsert" is part of the Drools Truth Maintenance System (TMS). Here the fact is logically inserted, this fact is dependant on the truth of the "when" clause. It means that when the rule becomes false the fact is automatically retracted. This works particularly well as the two rules are mutually exclusive. So in the above rules if the person is under 16 it inserts an IsChild fact, once the person is 16 or over the IsChild fact is automatically retracted and the IsAdult fact inserted.
$p : Person( age < 16 )
then
logicalInsert( new IsChild( $p ) )
end
rule "Infer Adult" when
$p : Person( age >= 16 )
then
logicalInsert( new IsAdult( $p ) )
end
We can now bring back in the code to issue the passes, these two can also be logically inserted, as the TMS supports chaining of logical insertions for a cascading set of retracts.
rule "Issue Child Bus Pass" whenNow when the person changes from being 15 to 16, not only is the IsChild fact automatically retracted, so is the person's ChildBusPass fact. For bonus points we can combine this with the 'not' conditional element to handle notifications, in this situation a request for the returning of the pass. So when the TMS automatically retracts the ChildBusPass object, this rule triggers and sends a request to the person:
$p : Person( )
IsChild( person =$p )
then
logicalInsert(new ChildBusPass( $p ) );
end
rule "Issue Adult Bus Pass" when
$p : Person( age >= 16 )
IsAdult( person =$p )
then
logicalInsert(new AdultBusPass( $p ) );
end
rule "Return ChildBusPass Request "when
$p : Person( )
not( ChildBusPass( person == $p ) )
then
requestChildBusPass( $p );
end

Truth maintenance is so awesome, but it seems almost to hidden away for people to discover - need more articles like this to show how it can help.
ReplyDeleteI think TMS really comes into it's own once you have opportunistic backward chaining, aka NExpert:
ReplyDeletehttp://blog.athico.com/2009/08/nexpert-review-mactech.html
Wouldn't it be cool if the "Infer Child" and "Infer Adult" rules could be combined into one rule using an else clause? :)
ReplyDeleteOPSJ does an "else" on our equivalent of an eval. I think the concept can be extended for more generic capabilities using 'or' CE, here we call this "branch" for more conciseness.
ReplyDeleterule "multi value assignment" when
(branch $p : Person( age < 5 )
[b1] $p : Person( age >= 5 < 15 )
[b2] $p : Person( age >= 15 < 25 )
[b3] $p : Person( age >= 25 < 40 ) )
then
....
then[b1]
....
then[b2]
...
then[b3]
....
end
So then any "else" can be implemented as:
rule "...."
[else1] $p : Person( age < 16 )
then
...
then[else1]
...
end
Which is rewritten internally as:
rule "multi value assignment" when
(branch $p : Person( age < 16 )
[b1] ( $p : Person()
not Person( this == $p, age >= 16 ) )
then
....
then[b1]
....
end
Werks fer me!
ReplyDeleteDo I see a community patch coming?
ReplyDelete;)
In third code block, should it read:
ReplyDeleterule "Issue Adult Bus Pass" when
$p : Person( )
IsAdult( person =$p )
In the last rule to request the return of the pass, what if the Person was never a child (ie, the inserted Person was initially an adult)? Will then adults get a request to return the child pass they never had?
ReplyDelete"In the last rule to request the return of the pass, what if the Person was never a child (ie, the inserted Person was initially an adult)? Will then adults get a request to return the child pass they never had?"
ReplyDeleteYes additional logic would need to be added.
Hi Marc, what is your rule of thumb wether to use a "declare" or a Java fact? For IsAdult we would use a declare. This solution seems to us more natural.
ReplyDeleteDissimilar to precaution maintenance which is finished with the objective of forestalling an issue, remedial maintenance is done to address an issue or deficiency once it has been recognized. Its will likely reestablish operability. read full article
ReplyDelete