how to write ( A after max time B ) in CEP( Fusion ) Drools - drools

What is the best way to write a condition in drools CEP to infer ( A after max time B )
Example :
a : new A();
b : new B( this after [1m] )
The above example is not my need.
I need this :
a : new A();
b : new B( this after a , b.timestamp - a.timestamp <= 60000)
So i reformulate the question. Is another way to obtain the same result with less instructions ?
Thanks

Edit after clarification of Q
$a: A()
$b: B( this after[ 0s, 60s ] $a )
This fires if B comes after A but not later than 60 seconds.

Related

How does wavg work in depth using a vectorised approach?

The objective of the snippet below is to evaluate weighted mid for n levels of an order book. The code snippet is from the book Machine Learning and Big Data with kdb+/q (2020 Wiley).
n:10;
quote: ([] sym: n?`A`B; time: asc n?0t; bid1: n?10f; bidSize1: n?100 );
update bid2: 0 | bid1 - .1 * n ? 10, bidSize2: n?100, ask1: bid1 + .2 * n ? 10, askSize1: n?100 from quote;
update ask2: ask1 + .1 * n ? 10, askSize2: n?100 from `quote;
select sym,time, wmid: ( bidSize1; bidSize2; askSize1; askSize2 ) wavg (bid1; bid2; ask1; ask2) from quote
I would like to understand a generic rule for how the wavg method works in-depth for lists of vectors. Could you please help me? Appreciate your help.
There are docs here on wavg https://code.kx.com/q/ref/avg/#wavg.
From these docs we can see that calling wavg is the equivalent to the function {(sum x*y)%sum x}
Using your example:
q)res1:select sym,time, wmid: ( bidSize1; bidSize2; askSize1; askSize2 ) wavg (bid1; bid2; ask1; ask2) from quote;
q)res2:select sym,time, wmid:{(sum x*y)%sum x} [( bidSize1; bidSize2; askSize1; askSize2 );(bid1; bid2; ask1; ask2)] from quote;
q)res1 ~ res2
1b
So in the case of your example we multiply bidSize1bid, bidSize2bid2, etc. , sum this result, then divide by the sums of our sizes e.g. (bidSize1[0]+ bidSize2[0] + askSize1[0] + askSize2[0];(bidSize1[1]+ bidSize2[1] + askSize1[1] + askSize2[1]; etc...)
I'm not sure if there is a more a general way of describing this but the above may help understand the nuts and bolts of what's going on

In Perl , How to generate All Possible Patterns ,

may i know how to ( in Perl ) ,
generate below All Possible Patterns in a file and on screen output , and each slot in the pattern can be accessed , ?!
many thanks for all ,
input value ,
1 , no. of slots ,
2 , no. of objects ,
for example ,
no. of object = 2 , { a , b } ,
no. of slots = 4 ,
then , output ,
no. of all possible patterns = 2^4 = 16 ,
then ,
row is 16 ,
column is 8 ,
eachSlot[i][j] = allow assign or change its value ,
then , output format look like ,
a a a a
a a a b
a a b a
a a b b
a b a a
a b a b
a b b a
a b b b
b a a a
b a a b
b a b a
b a b b
b b a a
b b a b
b b b a
b b b b
and ,
if see 'a' , then do sth actionX ,
if see 'b' , then do sth actionY ,
many thanks for all the advices and helps ,
use Algorithm::Loops qw( NestedLoops );
my #syms = qw( a b );
my $num_slots = 4;
my $iter = NestedLoops([ ( \#syms ) x $num_slots ]);
while ( my #items = $iter->() ) {
say "#items";
}
I made Set::CrossProduct:
use v5.10;
use Set::CrossProduct;
my $set = Set::CrossProduct->new( [ [ qw(a b) ] x 4 ] );
while( my $next = $set->get ) {
say "#$next";
}
ikegami showed the Algorithm::Loops module, which is also fine to get all the combinations.

Drools variable binding: reassignment not allowed

Assume that MyObject is a Java Object with an integer property called integerProperty.
I would like to write a Drools rule like the following (syntactically incorrect):
rule "myRule"
when
MyObject( $integerProperty : integerProperty )
accumulate(
$o : MyObject(
integerProperty == $integerProperty + 1,
$integerProperty : this.integerProperty
);
$total : count($o);
$total > 10
)
then
[BLABLABLA]
end
I want to fire my rule when there is a set of more than 10 elements of type MyObject whose integerProperty values form an arithmetic sequence, e.g. 1, 2, 3, … In this case, I will assign a negative value to an HardMediumSoftLongScore object (hoping that information this helps).
I am sure that an MyObject having a given integerProperty is unique (eg. there is just one MyObject having integerProperty equal to, say, 2). The problem is that I'm not allowed to re-assign the variable binding $integerProperty. Is there a way around this?
Try implementing the below example and check whether you are getting your desired output. Before firing the rule insert the previous object as a global variable (prev in the example below) in the drool session.
global MyObject prev;
rule "myRule"
when
$total : Number(doubleValue > 10) from accumulate(
$o : MyObject( prev.getIntegerProperty() != null && $i : integerProperty == prev.getIntegerProperty() + 1),
init( double total = 0;),
action( total += 1; ),
reverse( total -= 1; ),
result( new Double( total ) ) )
then
[BLABLABLA]
end
In your java code before firing the rule set the previous object as a global object. Follow the code below :
kieSession.setGlobal("prev",myprevobject)
kieSession.insert(myobject)
kieSession.fireAllRules()

Drools - Accumulate logic

I need help in writing the accumulate logic for below requirement:
Requirement: Certain rules will provide the percentage to be applied for global value. Another set of rules should use the aggregate total percentage in determining the result.
For example: 0.75 is the global value passed as input(threshold).
Rule 1 might apply -10% of the fixed value ie. 0.75 - (0.75 * 0.10) = 0.675
Rule2 will apply + 20% off updated value. ie., 0.675 + (0.675 * 0.20) = 0.81
My global value is 0.75 (Threshold)
Using the below rules I am trying to applied the percentage applicable for a fixed value :
//class imports
global Double FIXED_THRESHOLD;
//Rules
rule "Prediction Rule_2"
lock-on-active true
no-loop true
salience (2)
when
LossInput (airBagDeployed == 'Y' , driveable == 'N')
result : RuleResult(predictedTotalsThreshold == 0)
then
insert(new ControlFact( -10.0 ) ); //Reduce -10% to global value 0.75 - 0.75* 0.10 = 0.675
System.err.println("New control fact added to working memory....");
end
rule "Prediction Rule_1"
lock-on-active true
no-loop true
salience (1)
when
LossInput (airBagDeployed == 'Y' , driveable == 'N', make == 'Honda' )
result : RuleResult(predictedTotalsThreshold == 0)
then
insert(new ControlFact( 20.0 ) ); // Add 20% to the updated aggregate (0.20 % of 0.675).
System.err.println("New control fact added to working memory....");
end
I tried the below accumulate logic but obviously it is wrong. It is applying only to fixed value always instead of the updated value.
rule "Aggregate All Threshold"
no-loop true
when
$aggregateTotalsThresholdPercentage : Number() from accumulate(
ControlFact( $totalsThreshold : totalsThresholdPercentage ),
sum( ( FIXED_THRESHOLD + ( FIXED_THRESHOLD * $totalsThreshold ) / 100 ) ) )
ruleResult: RuleResult(predictedTotalsThreshold == 0)
then
ruleResult.setPredictedTotalsThreshold($aggregateTotalsThresholdPercentage.doubleValue());
update(ruleResult);
end
POJO:
public class LossInput{
private String airBagDeployed;
private String driveable;
private String make;
}
public class ControlFact {
public double totalsThresholdPercentage;
}
public class RuleResult {
private double predictedTotalsThreshold;
}
//insert facts in working memory
kieSession.insert(lossInput);
kieSession.insert(ruleResult);
kieSession.setGlobal("FIXED_THRESHOLD", new Double(0.75));
kieSession.fireAllRules();
Please help on the accumulate logic to apply the updated value everytime when percentage threshold to be applied.
You cannot use accumulate/sum this way because you add the FIXED_THRESHOLD for each ControlFact.
Insert ControlFacts as you have in the "Prediction..." rules (without all the rule attributes). Use each ControlFact to update RuleResult's predictedTotalsThreshold. The "Aggregate" rule will fire repeatedly, and therefore you need to make sure to retract the used ControlFact.
rule "Aggregate All Threshold"
when
ControlFact( $ttp: totalsThresholdPercentage );
$res: RuleResult( $ptt: predictedTotalsThreshold)
then
double nt = $ptt + $ptt*$ttp/100;
modify( $res ){ setPredictedTotalsThreshold( $nt ) }
retract( $res );
end

accumulate from elements of a set - drools

I want to sum the weight of unique panelist having (at least) one active viewing. A viewing has a panelist, a panelist has a weight (int).
I obtain the set of Panelists having an active Viewing like this:
accumulate(
Viewing(active==true,
$p : panelist),
collectSet($p))
EDIT: Note that I am using a set as a way of getting the set of unique panelists.
I want to sum the weight of every panelist in this set.
My attempt (below) is returning
java.util.Collections$UnmodifiableSet cannot be cast to com...domain.Panelist
Basically, a set is not a panelist, duh.
How can I access elements of the set, ideally using idiomatic drools rather than a Java hack?
This is my attempt:
rule "targetLevelReach"
when
$actualReach : Number(intValue>10) from accumulate (
Panelist($weight : weight) from
accumulate(
Viewing(
active==true,
$p : panelist),
collectSet($p)),
sum($weight))
then
...
end
Building further on laune's idea:
rule "targetLevelReach"
when
$actualReach : Number(intValue>10) from
accumulate ( $p : Panelist
and exists Viewing( active==true, panelist == $p),
sum($p.getWeight() )
then
...
end
In the first rule, the inner accumulate collects a Set of objects that are accessible from a Viewing object using getPanelist. This (I suppose - because you couldn't be bothered to supply the info) returns a Panelist. But a Set of Panelist isn't a Panelist, which you have as a result of the accumulate:
Panelist(...) from accumulate ( Viewing(...$p:...), collectSet($p) )
Therefore, Set cannot be cast to ... Panelist.
The second version does have Set() as the result of the above accumulate.
As each Panelist has a weight, all you need to do is
rule "targetLevelReach"
when
$actualReach : Number(intValue>10) from
accumulate ( Viewing( active==true, $p : panelist),
sum($p.getWeight() )
then
...
end
Edit
Now that we know that we have to eliminate duplicates in the Set of Panelist, we know that we have to accumulate an intermediary Set:
rule "targetLevelReach"
when
$pset: Set() from accumulate ( Viewing( active==true, $p : panelist),
collectSet($p) )
$actualReach: Number(intValue>10) from
accumulate( Panelist( $weight : weight) from $pset,
sum( $weight ) )
then
...
end
rule "targetLevelReach"
when
accumulate ( Viewing( active==true, $p : panelist),
$pset: collectSet($p) )
accumulate( Panelist( $weight : weight) from $pset,
$actualReach: sum( $weight ),
$actualReach > 10 )
then
...
end
For some reason, it is working when I do not chain the accumulate but use an intermediate variable instead. Keen to have an explanation though.
This is a working way of accumulating from the set:
$viewers : Set() from accumulate(
Viewing(
active==true,
$p : panelist),
collectSet($p))
$actualReach : Number( ) from accumulate (
Panelist($weight : weight) from $viewers,
sum($weight))