Activation Group and Salience - wrong rule being fired - drools

I have the following 3 rules in my system. The facts match all 3 rules. Based on the salience and activation group I would expect either rule 10 or 11 to fire. However rule 12 is always firing.
To complicate matters I have 3 systems this runs on. It runs with the expected rule 10 or 11 firing on one system and the other two systems rule 12 is firing.
Any ideas?
rule "dimensionConfigMotorTubeDefault_10"
salience 390
activation-group "ag_R238_r28-wirefree"
no-loop true
lock-on-active true
when
p: Product(sku != 1)
$mm : InventoryChoiceOption(sku == "mm")
exists (NII(internalPattern in ("R238")) from $mm.value)
$opt : TextChoiceOption(sku == "motorControl")
exists (OptionValue(optionValueValue in ("r28-wirefree")) from $opt.value)
DimensionOption(sku == "dim", widthValue <= "72", heightValue <= "120")
$edi : TextOption(sku == "default_tube_size")
then
$edi.setValue("1.5"); update($edi);
end
rule "dimensionConfigMotorTubeDefault_11"
salience 390
activation-group "ag_R238_r28-wirefree"
no-loop true
lock-on-active true
when
p: Product(sku != 1)
$mm : InventoryChoiceOption(sku == "mm")
exists (NII(internalPattern in ("R238")) from $mm.value)
$opt : TextChoiceOption(sku == "motorControl")
exists (OptionValue(optionValueValue in ("r28-wirefree")) from $opt.value)
DimensionOption(sku == "dim", widthValue <= "96", heightValue <= "96")
$edi : TextOption(sku == "default_tube_size")
then
$edi.setValue("1.5"); update($edi);
end
rule "dimensionConfigMotorTubeDefault_12"
salience 380
activation-group "ag_R238_r28-wirefree"
no-loop true
lock-on-active true
when
p: Product(sku != 1)
$mm : InventoryChoiceOption(sku == "mm")
exists (NII(internalPattern in ("R238")) from $mm.value)
$opt : TextChoiceOption(sku == "motorControl")
exists (OptionValue(optionValueValue in ("r28-wirefree")) from $opt.value)
DimensionOption(sku == "dim", widthValue <= "102", heightValue <= "120")
$edi : TextOption(sku == "default_tube_size")
then
$edi.setValue("2"); update($edi);
end

Related

Use of a control fact

UPDATE
Introduced a control fact to control rules from firing. Facts are
Product (sku="zzz")
TextChoiceOption (sku="control", optionValueValue = "xxx")
DimensionOption (sku="dim", widthValue = 29, heightValue = 71)
TextOption (sku="default_tube_size", value="")
TextOption (sku="motorTubeRule", value="N")
Only one rule is firing by rule 12 is firing instead of rule 10 or 11. Based on Salience level rule 10 or 11 should fire with LIFO firing rule 11 but that is not the case. What is the problem?
rule "rule_10"
salience 390
no-loop true
when
p: Product(sku != 1)
TextOption(sku="motorTubeRule", value == "N")
$opt : TextChoiceOption(sku == "motorControl")
exists (OptionValue(optionValueValue in ("xxx")) from $opt.value)
DimensionOption(sku == "dim", widthValue <= "72", heightValue <= "120")
$edi : TextOption(sku == "default_tube_size")
$ruleFire : TextOption(sku == "motorTubeRule")
then
$edi.setValue("1.5"); update($edi);
$ruleFire.setValue("Y"); update($ruleFire);
end
rule "rule_11"
salience 390
no-loop true
when
p: Product(sku != 1)
TextOption(sku="motorTubeRule", value == "N")
$opt : TextChoiceOption(sku == "motorControl")
exists (OptionValue(optionValueValue in ("xxx")) from $opt.value)
DimensionOption(sku == "dim", widthValue <= "96", heightValue <= "96")
$edi : TextOption(sku == "default_tube_size")
$ruleFire : TextOption(sku == "motorTubeRule")
then
$edi.setValue("1.5"); update($edi);
$ruleFire.setValue("Y"); update($ruleFire);
end
rule "rule_12"
salience 380
no-loop true
when
p: Product(sku != 1)
TextOption(sku="motorTubeRule", value == "N")
$opt : TextChoiceOption(sku == "motorControl")
exists (OptionValue(optionValueValue in ("xxx")) from $opt.value)
DimensionOption(sku == "dim", widthValue <= "102", heightValue <= "120")
$edi : TextOption(sku == "default_tube_size")
$ruleFire : TextOption(sku == "motorTubeRule")
then
$edi.setValue("2"); update($edi);
$ruleFire.setValue("Y"); update($ruleFire);
end

Give the results of the following Boolean operations

Assuming that A = True, B = False and C = True.
Give the results of the following Boolean operations
AB + BC’ (A + B’C) + B
(b) ABC’ + (B + AC’)B + A’
in boolean multiply operation is AND (&&) operation
and plus + operation is OR(||) operation
and ' operator measn NOT(!)
so,
AB + BC’ (A + B’C) + B
can be written as
(A && B) || [(B && (!C)) && (A || ((!B) && C))] || B
PUTTING THE VALUE IN THE ABOVE EQUATION
= (1 && 0) || [(0 && (!0)) && (1 || ((!1) && 1))] || 1
= 0 || [(0 && 1 )&& (1 || (0 && 1)] ||1
= 0 || [(0 && 1) && (1 || 0)] ||1
= 0 || [0 && 1] ||1
= 0 || 0 || 1
= 1
I KNOW IT IS HARD TO FOLLOW BUT THE ANSWER WILL BE 1
AND FOLLOWING THE SAME LOGIC THE ANSWER TO THE 2ND STATEMENT WILL ALSO BE 1
IF YOU WANT TO UNDERSTAND HOW THIS WORKS PLEASE READ THE DOCS

drools how to fire specified group dynamically

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.
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;
...
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

Drools: how to use abbreviated condition notation together with further conditions?

Using Drools 6.5.0.Final
I want to use abbreviated combined relation condition (e.g. Person( age > 30 && < 40 )) in combination with additional conditions.
I tried it, but the resulting rules are executed more than once.
I have a small example, where temperature deviation from a setpoint is checked and the allowed deviations depend on the setpoint. The allowed deviations are configured with Param facts, see below.
If I execute the example (fire-all-rules):
rule 1 fires two times (bug?)
rule 2 fires once as expected (without abbreviated notation).
Is my usage of the abbreviated notation wrong or is this a bug?
Example rules:
declare Param
from : float
to : float
low : float
high : float
end
declare TemperatureEvent
#role( event )
id : String
setpoint : float
t : float
end
rule "Init abbreviated conditions test"
when
then
insert(new Param(0, 10, 1, 1));
insert(new Param(10,20, 2, 3));
insert(new TemperatureEvent("id1", 13.7f,11.5f));
// rule 1 and rule 2 should fire exactly once
end
rule "rule 1"
when
$p: Param()
$x : TemperatureEvent($p.from <= setpoint && < $p.to, (t < setpoint+$p.low || t > setpoint+$p.high))
then
System.out.println("rule 1: "+$x.getId()+" "+$x.getSetpoint()+" "+$x.getT());
end
rule "rule 2"
when
$p: Param()
$x : TemperatureEvent($p.from <= setpoint, setpoint < $p.to, (t < setpoint+$p.low || t > setpoint+$p.high))
then
System.out.println("rule 2: "+$x.getId()+" "+$x.getSetpoint()+" "+$x.getT());
end
The abbreviated restriction
$p.from <= setpoint && < $p.to
is equivalent to
$p.from <= setpoint && $p.from < $p.to
What you want is
setpoint >= $p.from && < $p.to

Locating syntax error in Drools

I have a drool file where rule 2 is always coming out to true.
rule "R2"
salience 1000
when
((residence status = "US Citizen") || ((residence status = "Lawfully-entered Alien") and (residence duration >= 5))) and (fpl <= 133)
then
Add to Programs List "3"
end
the value of
residence status is US Citizen
residence status is null
residence duration is 0
fpl is 278.77
Why it is going into it always though for specified value the condition is false .
Kindly find the all files.
package com.eligibility.service;
import com.platform.enrollment.domain.BasicInfo;
import com.platform.enrollment.domain.FamilyMember;
global java.util.List prog_id_list;
global java.lang.Double fpl;
[condition][] and=and
[condition][] or=or
[condition][]residence status \= "{value}"=FamilyMember(basicInfo.citizenshipStatus == "{value}")
[condition][]residence duration >\= {value}=FamilyMember(basicInfo.permanentResidenceDuration >= {value})
[condition][]job status \= "{value}"=FamilyMember(basicInfo.jobStatus == "{value}")
[condition][]large business status \= "{value}"=FamilyMember(basicInfo.largeBusinessStatus == "{value}")
[condition][]false=eval(false)
[condition][]true=eval(true)
[condition][]age \= {value}=FamilyMember(basicInfo.getAge=={value})
[condition][]age < {value}=FamilyMember(basicInfo.getAge<{value})
[condition][]age > {value}=FamilyMember(basicInfo.getAge>{value})
[condition][]age <\= {value}=FamilyMember(basicInfo.getAge<={value})
[condition][]age >\= {value}=FamilyMember(basicInfo.getAge>={value})
[condition][]fpl \= {value}=eval(fpl=={value})
[condition][]fpl < {value}=eval(fpl<{value})
[condition][]fpl > {value}=eval(fpl>{value})
[condition][]fpl <\= {value}=eval(fpl<={value})
[condition][]fpl >\= {value}=eval(fpl>={value})
[condition][]gender \= "{value}"=FamilyMember(basicInfo.gender == "{value}")
[condition][]pregnant \= true=Applicant(eval(pregnant))
[condition][]pregnant \= false=Applicant(eval(!pregnant))
[condition][]Family member age greater than or equal to 60 \= true=eval(any_member_greater_than_equal_to_60)
[condition][]Family member age greater than or equal to 60 \= false=eval(!any_member_greater_than_equal_to_60)
[condition][]job status \= "{value}"=Applicant(eval(job_status.contains("{value}")))
[condition][]large business status \= "{value}"=Applicant(eval(large_business_status.contains("{value}")))
[condition][]employer benefits \= "{value}"=Applicant(eval(large_business_status.contains("{value}")))
[condition][]spouse \= true=eval(spouse)
[condition][]spouse \= false=eval(!spouse)
[condition][]total assets \= {value}=eval(total_assets=={value})
[condition][]total assets < {value}=eval(total_assets<{value})
[condition][]total assets > {value}=eval(total_assets>{value})
[condition][]total assets <\= {value}=eval(total_assets<={value})
[condition][]total assets >\= {value}=eval(total_assets>={value})
[condition][] Question with code "{code}" has answer "{answer}"=Question(code=="{code}"&& eval(answer.contains("{answer}")))
[consequence][]Add to Programs List {id}=prog_id_list.add({id});
rule "R0"
salience 1000
when
(age <= 0) and ((residence status = "US Citizen") || (residence status = "Lawfully-entered Alien")) and (fpl <= 200)
then
Add to Programs List "1"
end
rule "R1"
salience 1000
when
((residence status = "US Citizen") || (residence status = "Lawfully-entered Alien")) and (fpl >= 400)
then
Add to Programs List "2"
end
rule "R2"
salience 1000
when
((residence status = "US Citizen") || ((residence status = "Lawfully-entered Alien") and (residence duration >= 5))) and (fpl <= 133)
then
Add to Programs List "3"
end
rule "R3"
salience 1000
when
((residence status = "US Citizen") || (residence status = "Lawfully-entered Alien")) and (fpl > 133) and (fpl < 400)
then
Add to Programs List "4"
end
Can anybody help me why it is enetring is list3 though data as provided above is not making it valid
It could also be helpful to look at the generated java class for your rule and see what the issue might be.
Use:
-Ddrools.dump.dir=
to set path for the generated code.
It could also be helpful to set a rules listener and look at the fact insertions updates and rules firing sequence.
Also you could try to break the problematic rule into two rules without DSL as follows for debug purpose:
when
FamilyMember(basicInfo.citizenshipStatus == "US Citizen")
Fact(eval(fpl <= 133))
when
FamilyMember(basicInfo.citizenshipStatus == "Lawfully-entered Alien")
FamilyMember(basicInfo.permanentResidenceDuration >= 5)
Fact(eval(fpl <= 133))
Hope this helps.