Drools-Compare properties of 2 objects - drools

I have a requirement to determine which train to choose to assign an Employee to.
Let's say I have 2 trains with properties as:
Train 1 Train 2
trainID=1 trainID=2
passengerCount=100 passengerCount=150
numberOfBoxes=12 numberOfBoxes=7
If I pass both these objects to Drools and check like
$train1 : TrainProperties($pasCnt : passengerCount)
$train2 : TrainProperties($pasCnt2 : passengerCount > $pasCnt)
then
Sysout("Train 2 is more important")
end
Now I have to add more conditions based on numberOfBoxes. How can I do it?

As stated in Drools Documentation, you can use a , to create multiple AND conditions inside a pattern. You can also use || to create OR.
So, in your case, you could do something like this:
when
$train1 : TrainProperties($pasCnt : passengerCount, $boxes: numberOfBoxes)
$train2 : TrainProperties($pasCnt2 : passengerCount > $pasCnt, numberOfBoxes > $boxes )
then
Sysout("Train 2 is more important")
end
Hope it helps,

Related

I want to sum two different attributes based on some condition in drools

I want to add two different attributes using some condition in drools engine.
Below Sample condition need to convert into drools rule,
CASE WHEN (XXX='1' OR YYY <> '#' OR
(cast(coalesce(cast(abc as integer),0)+coalesce(cast(cdf as integer),0)as integer)>=1)
OR aaa='1' OR abc='1' OR dfs='1'
OR dfds='1' OR dfsde ='1' OR adbc='1' )THEN 1
ELSE 0
END

create subset and use each atom only once

I am totally new in asp. I need to create a group of teams. Each group must consist of 3 randomly chosen teams. A team can be in only one group.
Thanks in advance. Here is my code
team(fener;galata;besik;van;adana;mardin).
neq(X,Y) :- X!=Y,team(X),team(Y).
count(C) :- C = #count{ T : team(T)}.
C/3 {group(X,Y,Z):team(X),team(Y),team(Z), neq(X,Y),neq(X,Z),neq(Z,Y) } C/3 :- count(C).
#show group/3.
a possible output could be
group(fener;besik;van) group(galata;mardin;adana)
The output you want is not possible:
group(a;b;c).
implies:
group(a). group(b). group(c).
A possible output would be:
group(a,b,c).
But ASP is not really friendly with variable arguments atoms, or list elements as parameters. A simpler output to manage would be:
group(1,a). group(1,b). group(1,c).
And this is very easy to generate, and allows us to avoid the costly #count:
% Data
#const nb_group=2.
group(1..nb_group).
team(fener;galata;besik;van;adana;mardin).
% Assign 3 teams to each group
3{ group(G,T): team(T) }3 :- group(G).
% Two (almost) equilavent constraints:
1{ group(G,T): group(G) }1:- team(T). % a team is in only one group
OR
:- team(T) ; not group(_,T). % a team has no group
I think, have found the solution.
team(fener;galata;besik;van;adana;mardin).
neq(X,Y) :- X!=Y,team(X),team(Y).
count(C) :- C = #count{ T : team(T)}.
C/3 {group(X,Y,Z):team(X),team(Y),team(Z), neq(X,Y),neq(X,Z),neq(Z,Y) } C/3 :- count(C).
exist_in_group(T) :- group(T,_,_).
exist_in_group(T) :- group(_,T,_).
exist_in_group(T) :- group(_,_,T).
:- team(T), not exist_in_group(T).
#show group/3.
The output:
clingo version 5.0.0
Solving...
Answer: 1
group(besik,fener,adana) group(galata,mardin,van)
SATISFIABLE
Models : 1+
Calls : 1
Time : 0.011s (Solving: 0.00s 1st Model: 0.00s Unsat: 0.00s)
CPU Time : 0.000s

KDB - How to return all values in functional select with aggregation

I have a trade table :
trade:([]time:`time$();sym:`symbol$();price:`float$();size:`int$())
`trade insert(5?09:30:00.000;5?`a`b;5?10.75;5?100)
and aggregate(aggr) function :
aggr:{[f;c;tab] ?[tab;();`sym;c!(f),'c] }
It works fine for the following :
aggr[(last;min;max);(`time`size`price);`trade]
However I want all the prices rather than just the max, like the following :
?[trade;();`sym;(`time`size`price!((last;`time);( min;`size);(`price)))]
What is the best way to achieve this?
You can use :: (identity function) for this:
aggr[(last;min;::);(`time`size`price);`trade]
which is same as :
aggr[(last;min;{x});(`time`size`price);`trade]
:: is overloaded to be used as monadic identity function :
q)(::)1
1
q){x}1
1

Drools rule using accumulate

Hello I it is my first time involved in drools project. I have created some simple rules that work fine, however I have trouble with more complex rules that use the accumulate function. Below I have this rule.
rule "1"
no-loop
when
$msg : Declaration(header.totalGrossMassMeasure != null,
header.totalGrossMassMeasure.compareTo(BigDecimal.ZERO) > 0 )
result : ValidationResult()
$netValue : Number() from accumulate (
GoodsItemsType($net : netNetWeightMeasure),
sum($net.doubleValue())
)
eval($netValue.doubleValue() > ($msg.getHeader().getTotalGrossMassMeasure().doubleValue() + (0.45 * $msg.getGoodsItems().size())))
then
RulesValidationError error = new RulesValidationError();
error.setErrorType(ErrorType.INCORECT_VALUE);
result.getErrorsList().add(error);
end
the concept is to sum the net value from a list of goodsItemType object and compare the sum to the total gross mass measure multiplied by one buffer number. The problem is I have been trying last couple of days not being able to fire the rule with anything. Could someone please help me?

multiple if then else statement with arithmetic

I have a medical report that I need to alter the value of each appointment code.
If {Schedule.Activity} = "123"
then give it a value of 2,
if {Schedule.Activity} = "124"
then 1
else 1
The list is quite long of specific codes and what value they need to be for counting. Currently the report is counting all appointments as just 1.
I could do individual formulas but can anyone help with just one?
at the end of the report, they will all need to be summed as well.
I'm still new to CR so please have simple explanations and all the right syntax!
Thanks
Select {Schedule.Activity}
Case "123" : 1
Case "124" : 2
Case "125" : 3
///add as many Cases as you like
Default : 0 ;