What is the outcome of several rules having the same salience? Is their order of execution just the order that they're listed in, or is that behaviour undefined - that is, are they checked in arbitrary order? I can't seem to find documentation of how this is handled internally.
The short answer is that you shouldn't rely on the order of rules firing of the same salience - if they are "in conflict" (ie both are eligible to fire). Rules with no salience are just salience of zero, BTW.
Of course it is deterministic - its just that the algorithm is subject to change between versions (not very likely though).
This is under the general area of "conflict resolution" and much has been written about it. I can't find a current article on Drools strategy - but I believe most of it is "recency" - ie the most recently modified/inserted fact "wins" - or rather the rules that refer to the most recent fact will win. If after all that it can't decide - it is usually the order in which they rules are loaded (which usually co-incides with how they are written in the file). If you have to have an order - use salience, or use rule-flow or similar, best not to second guess how it will work.
The Rete algorithm used recency and specificity of conditions.
My experience with Drools 5.1 is that it's last in, first out. That is, the rule defined last in your drl will be executed first.
But yes, relying on such behavior wouldn't be the best idea :)
Related
If any incorrect rule pushed to knowledgebase. Can we scan the knowledgeBase to filter out the bad rules, which may create problem later?
Not only does this not exist, but it's not possible.
Simple syntax errors
The really easy problems -- straight up syntax errors -- are caught at runtime when the Drools rules are compiled. The rules themselves won't be loaded at all, and the Kie classes will throw an exception.
So, for example, let's say you were in a rush and you forgot the "when" keyword:
rule "Example 1"
salience 9
$s: SomeObject( foo == "bar" )
then
$s.doSomething()
end
This will be caught quickly at the time your rules are loaded. Other syntax errors like missing imports will be caught as well.
If you're following unit testing best practices, this will be caught at the unit testing stage, which -- given proper CI practices -- should keep the bad rules from being merged into your main code line.
If you're loading your rules from a Maven repository as a kjar, you'll likely want to have some sort of testing harness before publishing that kjar so that you don't end up with a situation where your service pulls new rules and ends up with a nonfunctional artifact.
Logical errors
Unlike syntax errors which can be caught early, logical errors really can't. The problem boils down to the fact that Drools is a framework for business logic -- it doesn't actually understand your business logic. And it can't, and it shouldn't need to.
If you write bad rules that put yourself into a bad situation, Drools has no way of actually identifying this because it doesn't understand your business needs.
Consider the following rules:
rule "A"
when
$f: Foo( value == 0 )
then
$f.setValue(100);
update($f);
end
rule "B"
when
$f: Foo( value > 10 )
then
$f.setValue(0);
update($f);
end
Assuming your initial input is Foo(value: 50), rule B will fire, setting value to 0. Then rule A will fire, setting value to 100. Then rule B will fire, setting value to 0. And so on, forever, until you kill the process manually.
This simple infinite loop is poor rule design, but it's only a bug because of your data characteristics. The above example is obvious and contrived, but that's because I'm just using it as an example. In practice, I once saw a set of 27 rules that triggered in a particular order given a very specific input and looped like that -- it took me a whole week to track down while manually tracing transactions through a customer system.
Drools can't "know" that this will cause an infinite loop because it doesn't understand your business rules or data. In the above Foo example with rules A and B, you could say "well obviously Drools could see that it's setting value in a way that'll trigger rules in a loop given the 'update' call" -- but you're making assumptions. What if I told you that there are situations where these rules don't loop? I never showed you the Foo model, maybe setValue has side effects.
The way you'd catch these is by actually validating your business logic. I usually start with unit tests and treat it as if I'm testing an "if" condition -- check the boundaries, check the edge cases, check the good value, check an obviously bad value, etc. Then I add end-to-end tests passing in real (sanitized) inputs collected from production -- the most common inputs, the weird inputs, the ones that have shown up in previous bug reports, etc.
And because that's not enough and you really need an understanding of all rules, we have internal style guidelines around DRL design to keep something like the above looping examples from happening. (We don't permit update, for example. There are specific rules around salience and retract as well.)
But built-in validation for this? Not actually possible; you need to do your own due diligence just like you would for your code.
My team has a plan to apply optaplanner to existing system.
Existing system has its own rule-sets.
it tries own rule-sets one by one and pick the one as best result.
We want to start from its result as heuristics
and start to solve the problem as meta-heuristics.
We have reviewed optaplanner manual especially in repeated planning section.
but we can't find the way.
Is there a way to accept existing system's result?
your cooperation would be highly appreciated
Best regards.
For OptaPlanner, it makes no difference where the input solution comes from. Consider the following code:
MyPlanningSolution solution = readSolution();
Solver<MyPlanningSolution> solver = SolverFactory.create(...)
.buildSolver();
solver.solve(solution);
Notice how solution comes from a custom method, readSolution(). Whether that method generates the initial solution randomly, reads it from a file, from a database etc., that does not matter to the solver. It also does not matter if it is initialized or not - construction heuristic, if configured, will just skip the initialized entities.
That means you have absolute freedom in how you create your initial solution and, to the solver, they all look the same.
I have a scenario wherein I need to add rules to a rule engine dynamically.
What if I add same rule twice/multiple times?
I am not able to get exact behavior of Drools by doing POC(I am a newbie to Drools).
Also, if a rule once inserted remain in knowledgeBase until I explicitly remove it?
You cannot add the save rule twice (which is sufficient to rule out "multiple times"). If it is the "same", it simply replaces the previous "same" rule. If only the titles differ, then (it isn't the same rule and) you have two rules with the same LHS and the same RHS. This may, or may not, produces the same reaction a second time: this depends on what the RHS does or does not.
You can and should clarify these things by reading the documentation and/or experimenting with a simple setup.
I am new to drools with a background in java. I have gained a basic undertanding of drools.
I have inherited a large drools project which works, but appears to be hacked together. Most of the rules have many and nested IF and ELSE statements in the "then" (consequence?). I believe this is bad practice. Can anyone confirm, references to materials on the internet would be useful.
Also what are the benefits in correcting this other than readability?
I'd have to dig for references but the general consent among rule programmers is that decisions should be made on the LHS/condition part of a rule. The simple reason is that the Engine is dedicated to the process of "many pattern/many object" pattern match problem. Even if there is one final condition where some action is necessary for both, true and false, Drools syntax provides a good solution, i.e., extending a rule twice, once with the positive and once with the negative condition.
That said, an occasional conditional statement may be tolerated or even fine, e.g., when it merely distinguishes between details in the works of the RHS/consequence part of a rule. But "many and nested" sounds rather bad - but maybe this "distinction of the details" does require such logic.
As for the benefits: nobody can tell without inspection, and then it'll need an experienced judge.
Since you've asked for references: http://www.redhat.com/rhecm/rest-rhecm/jcr/repository/collaboration/sites%20content/live/redhat/web-cabinet/home/resourcelibrary/whitepapers/brms-design-patterns/rh:pdfFile.pdf
One non-readability reasoning for putting as much evaluation in the LHS as possible is performance. For one thing it avoids unnecessary rule activations, but it also makes significant performance gains through caching the results of each of the matches, thereby avoiding re-evaluation.
This caching is not available to conditional logic on the RHS.
This is one reason why you invoke update/modify on a fact when you change it. This effectively instructs the engine that previously cached LHS evaluations relating to that fact can be discarded.
Nested "if/else" statements are generally not bad practice as logical operations are not stressful on the CPU, nor does it require copious amounts of memory.
I'm not a Drools programmer, but I imagine, since you alluded it to Java, it's an obj-oriented high-level prgramming language.
Howver, in the event that multiple if statements can be combined, it's recommended to do so for clear, clean coding, not necessarily performance.
Today I've been presented with a fun challenge and I want your input on how you would deal with this situation.
So the problem is the following (I've converted it to demo data as the real problem wouldn't make much sense without knowing the company dictionary by heart).
We have a decision table that has a minimum of 16 conditions. Because it is an impossible feat to manage all of them (2^16 possibilities) we've decided to only list the exceptions. Like this:
As an example I've only added 10 conditions but in reality there are (for now) 16. The basic idea is that we have one baseline (the default) which is valid for everyone and all the exceptions to this default.
Example:
You have a foreigner who is also a pirate.
If you go through all the exceptions one by one, and condition by condition you remove the exceptions that have at least one condition that fails. In the end you'll end up with the following two exceptions that are valid for our case. The match is on the IsPirate and the IsForeigner condition. But as you can see there are 2 results here, well 3 actually if you count the default.
Our solution
Now what we came up with on how to solve this is that in the GUI where you are adding these exceptions, there should run an algorithm which checks for such cases and force you to define the exception more specifically. This is only still a theory and hasn't been tested out but we think it could work this way.
My Question
I'm looking for alternative solutions that make the rules manageable and prevent the problem I've shown in the example.
Your problem seem to be resolution of conflicting rules. When multiple rules match your input, (your foreigner and pirate) and they end up recommending different things (your cangetjob and cangetevicted), you need a strategy for resolution of this conflict.
What you mentioned is one way of resolution -- which is to remove the conflict in the first place. However, this may not always be possible, and not always desirable because when a user adds a new rule that conflicts with a set of old rules (which he/she did not write), the user may not know how to revise it to remove the conflict.
Another possible resolution method is prioritization. Mark a priority on each rule (based on things like the user's own authority etc.), sort the matching rules according to priority, and apply in ascending sequence of priority. This usually works and is much simpler to manage (e.g. everybody knows that the top boss's rules are final!)
Prioritization may also be used to mark a certain rule as "global override". In your example, you may want to make "IsPirate" as an override rule -- which means that it overrides settings for normal people. In other words, once you're a pirate, you're treated differently. This make it very easy to design a system in which you have a bunch of normal business rules governing 90% of the cases, then a set of "exceptions" that are treated differently, automatically overriding certain things. In this case, you should also consider making "?" available in the output columns as well.
One other possible resolution method is to include attributes in each of your conditions. For example, certain conditions must have no "zeros" in order to pass (? doesn't matter). Some conditions must have at least one "one" in order to pass. In other words, mark each condition as either "AND", "OR", or "XOR". Some popular file-system security uses this model. For example, CanGetJob may be AND (you want to be stringent on rights-to-work). CanBeEvicted may be OR -- you may want to evict even a foreigner if he is also a pirate.
An enhancement on the AND/OR method is to provide a threshold that the total result must exceed before passing that condition. For example, putting CanGetJob at a threshold of 2 then it must get at least two 1's in order to return 1. This is sometimes useful on conditions that are not clearly black-and-white.
You can mix resolution methods: e.g. first prioritize, then use AND/OR to resolve rules with similar priorities.
The possibilities are limitless and really depends on what your actual needs are.
To me this problem reminds business rules engine where there is no known algorithm to define outputs from inputs (e.g. using boolean logic) but the user (typically some sort of administrator) has to define all or some the logic itself.
This might sound a bit of an overkill but OTOH this provides virtually limit-less extension capabilities: you don't have to code any new business logic, just define a new rule set.
As I understand your problem, you are looking for a nice way to visualise the editing for these rules. But this all depends on your programming language and the tool you select for this. Java, for example, has JBoss Drools. Quoting their page:
Drools Guvnor provides a (logically
centralized) repository to store you
business knowledge, and a web-based
environment that allows business users
to view and (within certain
constraints) possibly update the
business logic directly.
You could possibly use this generic tool or write your own.
Everything depends on what your actual rules will look like. Rules like 'IF has an even number of these properties THEN' would be painful to represent in this format, whereas rules like 'IF pirate and not geek THEN' are easy.
You can 'avoid the ambiguity' by stating that you'll always be taking the first actual match, in other words your rules have a priority. You'd then want to flag rules which have no effect because they are 'shadowed' by rules higher up. They're not hard to find, so it's something your program should do.
Your interface could also indicate groups of rules where rules within the group can be in any order without changing the outcomes. This will add clarity to what the rules are really saying.
If some of your outputs are relatively independent of the others, you will also get a more compact and much clearer table by allowing question marks in the output. In that design the scan for first matching rule is done once for each output. Consider for example if 'HasChildren' is the only factor relevant to 'Can Be Evicted'. With question marks in the outputs (= no effect) you could be halving the number of exception rules.
My background for this is circuit logic design, not business logic. What you're designing is similar to, but not the same as, a PLA. As long as your actual rules are close to sum of products then it can work well. If your rules aren't, for example the 'even number of these properties' rule, then the grid like presentation will break down in a combinatorial explosion of cases. Your best hope if your rules are arbitrary is to get a clearer more compact presentation with either equations or with diagrams like a circuit diagram. To be avoided, if you can.
If you are looking for a Decision Engine with a GUI, than you can try this one: http://gandalf.nebo15.com/
We just released it, it's open source and production ready.
You probably need some kind of inference engine. Think about doing it in prolog.