-1

i am using drools 7.x.

my logic looks like following:

if(variableA == 1) {

    if(variableA1 == 2) {
        ....
    } else if(variableA1 == 3) {
        ....
    }
}else {

    if(variableB1 == 1) {
        ....
    }else if(variableB1 == 2) {

        if(variableN == 1) {

        }else if(variableN == 2) {

        }
    }
}

by the way, these variables not in the same class, i intend to insert them as fact in drl.

how can i define the rules? or how can i define rules like :

rule 1
    when
    then
end

rule 2
    when
    then
end

rule 1-1
    when
    then
end

rule 1-2
    when
    then
end

rule 2-1
    when
    then
end

rule 2-2
    when
    then
end

wherein, only one of rules will be fired in rule 1 and rule 2, rule 1-1 and rule 1-2 is group1, rule 2-1 and rule 2-2 is group2.

if rule 1 is fired, then only one of rules is fired in group1, there is no need to test group2. While if rule 2 is fired, then only one of rules is fired in group2, there is no need to test group1.

frank
  • 1,169
  • 18
  • 43

2 Answers2

1
  • salience for rules priority
  • logical insertions to depend on other rule
  • activation-group for xor logic

rule "1"
  salience 1
  activation-group "group 0"
  when
    $model : Model(a == 1)
  then
    insertLogical(new GroupActivation("group 1", $model));
    System.out.println("rule 1");
end

rule "2"
  salience 1
  activation-group "group 0"
  when
    $model : Model(b == 1)
  then
    insertLogical(new GroupActivation("group 2", $model));
    System.out.println("rule 2");
end

rule "1-1"
  activation-group "group 1"
  when
    GroupActivation(name == "group 1", $model : model)
    Model(this == $model, a1 == 1)
  then
    System.out.println("rule 1-1");
end

rule "1-2"
  activation-group "group 1"
  when
    GroupActivation(name == "group 1", $model : model)
    Model(this == $model, a2 == 1)
  then
    System.out.println("rule 1-2");
end

rule "2-1"
  activation-group "group 2"
  when
    GroupActivation(name == "group 2", $model : model)
    Model(this == $model, b1 == 1)
  then
    System.out.println("rule 2-1");
end

rule "2-2"
  activation-group "group 2"
  when
    GroupActivation(name == "group 2", $model : model)
    Model(this == $model, b2 == 1)
  then
    System.out.println("rule 2-2");
end

Model.java

public class Model {
    
    private int a;
    private int a1;
    private int a2;
    private int b;
    private int b1;
    private int b2;
...

GroupActivation.java

public class GroupActivation {
    
    private String name;
    private Model model;
...
Mike
  • 20,010
  • 25
  • 97
  • 140
  • `GroupActivation` is a custom class which includes `name` and `Model`? And in this example, if `rule1` is fired, then one of `rule 1-1` and `rule 1-2` will be fired, but `rule 2-1` and `rule 2-2` still will be tested thought they will not be fired, right? – frank Oct 11 '21 at 02:33
  • hi frank, added model definitions. Yes rule1 and rule2 (and respective groups) are not mutually exclusive. Do you need them to be? – Mike Oct 11 '21 at 06:14
  • Hi Mike, yes I want them to be exclusive, if `rule1` is fired, then only test `rule 1-1` and `rule 1-2`, ignore `rule 2-1` and `rule 2-2`, vice versa. So the only solution is set `activation group` of `rule 1-1, rule 1-2, rule 2-1, rule 2-1` are the same? – frank Oct 11 '21 at 09:07
  • just add another `activation-group` to `xor` them, updated my answer – Mike Oct 11 '21 at 11:03
  • Also please note that logical insertions rely on equals method with all respective outcome. First class use case for logical events is to rely on some condition (single) supported by multiple facts/conditions. Logical event is automatically removed if there were left no single fact/condition to support it – Mike Oct 11 '21 at 11:06
0

I'm going to assume all of these variables exist inside of an class which I'm going to call Inputs. You'd call these rules by passing an instance of Inputs into the rules.

I'm also going to assume that the last 'else if' in your example was a type and you're actually checking that variableN == 2.

rule "A1-2"
when
  Inputs( variableA == 1,
          variableA1 == 2 )
then
  // ...
end

rule "A1-3"
when
  Inputs( variableA == 1,
          variableA1 == 3 )
then
  // ...
end

rule "B1"
when
  Inputs( variableA != 1,
          variableB1 == 1 )
then
  // ...
end

rule "B2-N1"
when
  Inputs( variableA != 1,
          variableB1 == 2,
          variableN == 1 )
then
  // ...
end

rule "B2-N2"
when
  Inputs( variableA != 1,
          variableB1 == 2,
          variableN == 2 )
then
  // ...
end

Rather straight forward. The key is that you need to check that the condition for variableA ==1 is not true for the rules that deal with B. Basically when you're converting an if/elsif/else into rules, you need to negate the conditions from the previous if-clauses on your left-hand-side.

There's no "specified groups" involved. Mostly because there's no explanation about what you mean by these words.

Drools also has inheritance. There's no real reason to use it here, but you could if you wanted to:

rule "A1"
when
  $i: Inputs(variableA == 1)
then // notice empty "then"
end

rule "A1 = 2" extends "A1"
when
  Inputs( variableA1 == 2 ) from $i
then
  //
end
Roddy of the Frozen Peas
  • 14,380
  • 9
  • 49
  • 99
  • Thanks for your reply. Sorry to forget to mention that these variables are not in the same class, and i intend to set them as global in drl. Another point is : if `ruleA` is fired, then just rules of `groupA` will be tested, ignore rules of `groupB`, vice versa, could I? – frank Oct 09 '21 at 02:38
  • You can't reference globals in the "when". – Roddy of the Frozen Peas Oct 09 '21 at 02:42
  • And your "group a", whatever that is, just needs to key on the same condition as rule a and exclude the condition of rule b. You're making this overly complicated,tbh. – Roddy of the Frozen Peas Oct 09 '21 at 02:46
  • Sorry, not global, i intend to insert them as fact. – frank Oct 09 '21 at 02:47
  • Yes but they will be in some sort of container object, otherwise how do you know what's a or b? It's not like they'll have variable names should you insert them standalone. – Roddy of the Frozen Peas Oct 09 '21 at 02:49
  • that is: if `ruleA` is fired, then go to test rules of `groupA` and ignore rules of `groupB`; if `ruleB` is fired, then go to test rules of `groupB` and ignore rules of `grouupA` is impossible, i have to `key on the same condition as rule a and exclude the condition of rule b`, right? – frank Oct 09 '21 at 02:53
  • what are these groups? activation groups? rule flow groups? random rules you're just calling "group a" and "group b"?? – Roddy of the Frozen Peas Oct 09 '21 at 03:02
  • rules of `groupA` like the children of `ruleA`, if `ruleA` is fired, then need to test `groupA` and only one of rule will be fired in `groupA`, the same as `ruleB` and `groupB`. – frank Oct 09 '21 at 03:09
  • So basically an arbitrary collection of rules you're calling a "group". Is there a reason you're not actually using activation groups or rule flow groups (eg. actual drools 'groups')? Or heck, why not just make "group A" a kiebase of its own? – Roddy of the Frozen Peas Oct 09 '21 at 03:35