Drools : how to specify value in range? - drools

is there a better way to express this condition ?
$data : Data ( value > 20 && value < 50)
Something like :
$data : Data ( value in [20,50] )

DRL
No, the appropriate way of determining if a numeric value is between two other numeric values is how you've indicated -- by using two coditionals:
Data( value > 20, value < 50 )
There is an in operator, but it's not for this. It's for determining if a value is one of a set of other values:
Car( color in ( "red", "green", "blue"))
Animal( species not in ("lion", "tiger", "bear"))
If you're using the temporal operators, there's a syntax similar to what you've proposed for time ranges:
$eventA : EventA(this after[3m30s, 4m] $eventB)
... which is equivalent to:
3m30s <= $eventA.startTimestamp - $eventB.endTimeStamp <= 4m
But for determining the bounds of simple integers? No, just use two conditions.
FEEL
The Friendly Enough Expression Language (FEEL) supports something like this according to the Drools documentation. Since I don't use FEEL, or DMN, or Business Central, I can't speak to it. But according to the docs you should be able to do something like x in [ 1 .. 100 ].
But this is definitely DMN-only.

Related

In Yang Modelling, I want to implement a leaf which can accept values from range 10 to 1000 in multiples of 10

In Yang Modelling, I want to implement a leaf(as shown below) which can accept values ranging from 10 to 1000. The catch here is the value should be in multiple of 10's. Ex : 10,20,30,40...1000
My current leaf structure is :
leaf range-limit {
type uint16 {
range "10..1000";
}
default 100;
}
To implement this requirement, I thought if defining an enum which would hold all these values beginning from 10,20,30 etc....uptil 1000.
But this enum would look too long and though might not be the ideal way of doing it.
Please let me know if there is a way of accomplishing this ?
Thanks,
Vinayak
The solution for this would be using "mod" operator.
leaf range-limit {
type uint16 {
range "10..1000";
}
must ". mod 10 = 0" {
error-message "Value should be multiple of 10";
}
default 100;
}

Set/sequence summation operator?

I have a set, S = { 1, 2, 3, 4, 5 }.
If I wanted to sum this in standard logic it's just ∑S (no MathJax on SO so I can't format this nicely).
What's the VDM equivalent? I don't see anything in the numerics/sets section of the language reference.
There isn't a standard library function to do this (though perhaps there should be). You would sum a set with a simple recursive function:
sum: set of nat +> nat
sum(s) ==
if s = {}
then 0
else let e in set s in
e + sum(s \ {e})
measure card s;
The "let" selects an arbitrary element from the set, and then add that to the sum of the remainder. The measure says that the recursion always deals with smaller sets.
This should work:
sum(S)
But you could find this very easily.

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?

MDX Calculated member filter by dimension attribute and member value

I have MDX (similar to one questioned and answered here):
(
[PX Market].[PX MARKET NAME].&[Elbas],
[Measures].[PX QUANTITY]
)
It works for me (it filters measures to value "Elbas" only). But I need another filtering - to have only values which are < or > than 0. There shoud be some condition similar to "[Measures].[PX QUANTITY] < 0". But I do not know how to implement it.
Thank for any of your advice.
Ondra
Table looks similar like this:
PX_MARKET_NAME; PX_QUANTITY
Elbas; 5
Elbas; -3
Elspot; 4
In result I need only 2nd value (-3). Which belongs to Elbas and is smaller then 0.
So far I tried this, but it is now working :(
FILTER
(
[PX Market].[PX MARKET NAME].&[Elbas],
[Measures].[PX PURCHASE]
) < 0
Try that:
IIF(
([PX Market].[PX MARKET NAME].&[Elbas],[Measures].[PX QUANTITY]) < 0,
([PX Market].[PX MARKET NAME].&[Elbas],[Measures].[PX QUANTITY]),
NULL
)

Latest n events, matching a certain pattern

Is there a built-in feature in Drools, selecting the latest n events, matching a certain pattern? I've read about sliding length windows in the documentation and the stock tick example seemed to be exactly what I wanted:
"For instance, if the user wants to consider only the last 10 RHT Stock Ticks, independent of how old they are, the pattern would look like this:"
StockTick( company == "RHT" ) over window:length( 10 )
When testing the example, it seems to me that it is evaluted more like a
StockTick( company == "RHT" ) from StockTick() over window:length( 10 )
selecting the latest 10 StockTick events and afterwards filtering them by company == "RTH", resulting in 0 to 10 RHT-Ticks, event though the stream contains more then 10 RTH-events.
A workaround is something like:
$tick : StockTick( company == "RHT" )
accumulate(
$other : StockTick(this after $tick, company == "RHT" );
$cnt : count(other);
$cnt < 10)
which has bad performance and readability.
Most likely you are seeing an initial phase where the count of events in the window and according to the constraints hasn't reached the length specified in window:length yet. For instance,
rule "Your First Rule"
when
accumulate( $st : Applicant($age: age > 5) over window:length(10)
from entry-point X,
$avg: average ( $age ), $cnt: count( $st ))
then
System.out.println("~~~~~avg~~~~~");
System.out.println($avg + ", count=" + $cnt);
System.out.println("~~~~~avg~~~~~");
end
displays an output even before there are 10 matching Applicants but later on, $cnt never falls below 10, even though $age ranges from 0 to 9, periodically.
If you do think you have found an example supporting your claim, please provide full code for reproduction and make sure to indicate the Drools version.
Your workaround is very bad indeed, as it accumulates for each StockTick. But a window:length(n) can be very efficiently implemented by using an auxiliary fact maintaining a list of n events. This may even be more advantageous than window:length.