How to extend the rules with ability to override existing ones - drools

I need to design a solution where a set of rules can be extended with another set of rules without having to modify the original set.
Problem:
There are possible conflicts when simply combining rules from different rule sets since multiple rules can be matched. The system should trigger only the extended rule when in conflict with the base rule.
Example:
An time tracking system for determining overtime has a threshold to decide when the extra time counts for overtime.
A base rule counts overtime as time exceeding min. 30 minutes.
An extended rule counts overtime as time exceeding min. 60 minutes.
So extended rule is more strict because you have to work for at least
60 minutes to be counted as extra time (otherwise you get 0) but the
original rules counts anything above 30 minutes.
So it both rules as present and you spent +45 minutes at work the base
rule will fire and count it. But we don't want that because the extended rule has higher threshold.

You could put each rule in a different agenda-group. When you want to use your 30 minute rule focus on the agenda-group that contains it. When you want to use your 60 minute rule focus on the agenda-group that contains that.
Alternatively focus both agenda-groups. The rules we be matched in the most recently focused agenda-group first.

Related

Different Pseudo Clock for groups of Facts

I am new to drools / fusion (7.x) and am not sure how to solve this requirement. Assume I have event objects as Event{long: timestamp, id: string} where id identifies a physical asset (like tractor) and timestamp represents the time the event fired relative to the asset. In my scenario these Events do not arrive in my system in 'real-time', meaning they can be seconds, minutes or even days late. And my rules system needs to monitor multiple assets. Given this, when rules are evaluate the clock needs to be relative to the asset being monitored, it can't be a clock that spans assets.
I'm aware of Pseudo Clock, is there a way to assign Pseudo clocks per Asset?
My assumption is that a clock must always progress forward or temporal functions will not work properly. Take for the example the following scenario:
Fact A for Asset 1 arrive at 1:00 it is inserted into memory and rules fired. Then Fact B arrives for same Asset 1 at 2:00. It too is inserted and rules fired. Now Fact Z arrives for Asset 2 at 1:30 (- 30 minutes from clock). I'm assuming I shouldn't simply progress the clock backwards and evaluate, furthermore I'd want to set the clock back to 2:00 since that was the "latest" data I received. Now assume I am monitoring thousands of assets, all sending data at different times...
The best way I can think to address this is to keep a clock per asset and then save the engine state when each assets data is evaluated. Can individual KieSession's have different clocks, or is it at a container level?
Sample rule: When Fact 1 arrives after Fact 2 for the same Asset.
You're approaching the problem incorrectly. Regardless of whether you're using a realtime or psuedo clock, you're using a clock. You can't say "Fact #1 use clock A, and Fact #2 use clock B."
Instead you should be leveraging the metadata tags for events, specifically the #timestamp tag. This tag indicates to Drools that a specific field inside of the event is actually the timestamp for the Event, rather than the actual time the fact enters working memory.
For example:
import com.example.SampleEvent
declare SampleEvent
#role( event )
// this field is actually in the object, it's not the time the fact was inserted
#timestamp( createdDateTime )
end
Not knowing anything about what your rules are actually doing, the major issue I can foresee here is that if your rules rely on the temporal operators or define an expiry (#expires), they're not going to work and you'll need to redesign them. Especially for expirations: once an event expires, it is removed from working memory; when your out-of-band events come in any previously expired events are already gone and can't be worked against.
Of course that concern would be true regardless of whether you use #timestamp or your original "different psuedo clock" plan. Either way you're going to have to manage the fact that events cannot live forever in working memory -- you will eventually run out of resources and your system will crash. Events must be evicted at some point, so you'll need to design around that in both your models and your rules.

How do I set random break times for each resource?

I would like to set a random break time of 2 hours everyday for each resource unit within a resource pool. I was able to add a schedule for break times set to 2 hours from 12 pm - 2 pm, however, I would like that time interval to be randomly selected for each resource everyday. Can anyone help me with this? I'm pretty new to AnyLogic.
Thanks!
AT
instead of using the break setting forcing you to define a schedule (which is not random), use the "failures/repairs" setting instead and apply randomness as below. Note that this may cause more than 1 break in a day, but on average, it will be 1 a day for 2 hrs. Note also that failures behave exactly like breaks functionally.
You can, of course, also apply your own custom ResourceTask, name it "breaks" and set it up there.
I will give you a solution that will ensure that your resources take 1 break per day:
Create a variable in your resource agent called timeForNextBreak with initial value uniform(0,22) ... since they take 2 hours break, you want this to happen between 00:00 and 22:00, this also assumes your simulation starts at 00:00
Creat a variable in your resource agent called timeRemainingInDay with initial value 24, this also assumes your simulation starts at 00:00
create a custom resource task called randomBreak and use it in your resource pool
In your randomBreak resource task, complete the data as follows.

Rules fired upon fact insert - Drools

I am very new to Drools, and started with the basics. Here is a setup;
Have a few rule files
Rules in different files belong to different Agenda groups
All the rules operate on the same fact
In my Unit Test, I obtain a particular "Agenda Group", set Focus (session.setFocus)
I insert the fact (Here is where I notice the rules within the other agenda group are getting evaluated even though the focus is not on them)
I fireAllRules()
Shouldn't the rules pertaining to the particular agenda group that is in focus be fired and not all rules from all the groups?
It is a fundamental law in many Rule Based Systems - especially those that follow Rete or similar algorithms - that the evaluation of conditions ("t
when", "left hand side") happens whenever there are changes in Working Memory: inserts, updates or deletes. In contrast, rule firing or the execution of consequences ("then", "right hand side") happens after fireAllRules or fireUntilHalt has been called.
The firing of rules - more precisely: of activations of rules - can be controlled in several ways. Here, it is indeed the focussed agenda group that limits what can be executed by the engine.
Keep this in mind: evaluation is not equal to execution.

iCalendar recurrence rule for event that occurs every two years in multiple months on first weekend day

Is it possible to specify an event to occur on the 1st weekend day of multiple months every 2 years in a single RRULE? Using February and September as a test case, my first thought was:
FREQ=YEARLY;DTSTART=20140320T070000Z;INTERVAL=2;BYSETPOS=1;BYMONTH=2,9;BYDAY=SA,SU
but BYSETPOS reduces the set down to February only. I thought changing the freq to monthly would do the trick after I posted here, but applying an interval of 2 for every other year messes things up because the interval is applied to a monthly freq instead of a yearly freq.
I made this a new question because I did not include interval in my original question.
I think splitting this into multiple rrules would work, but it would greatly increase the complexity of this area of my app so I was hoping for a single rrule with a yearly freq.
Thanks!
FWIW, and since you mention it as a potential workaround, RFC5545 has removed the ability to have multiple RRULE property in a single VEVENT/VTODO (https://www.rfc-editor.org/rfc/rfc5545#section-3.6.1). It was there in RFC2445.
Then, unless someone finds a very elegant and simple solution, you may be left with something that is so convoluted that most clients will barf on it (don't know how interoperability is important to you).
This leaves you with 2 choices I think:
either use 2 different events (maybe linked with a RELATED-TO property)
or, if you can bound the event to a certain number of instances, represent it as a set of RDATE (or RRULE + RDATE, or RRULE + EXDATE, etc...).
Adding BYSETPOS like this may work as you intend:
FREQ=YEARLY;INTERVAL=2;BYMONTH=2,9;BYDAY=+1SA,+1SU;BYSETPOS=1,3
what you could try is to take advantage of the fact that bysetpos allows you to select within the year the selected instances of your rule, then you could limit the number of instances to the first week of the month (by setting the days of the month to the first 6 ones) to avoid the cases where month have more or less weeks, which then allows you to select the first and third instance in your year.
Which then gives:
DTSTART:20140320T060000Z
FREQ=YEARLY;INTERVAL=2;WKST=MO;BYSETPOS=1,3;BYMONTH=2,9;BYMONTHDAY=1,2,3,4,5,6,7;BYDAY=SA,SU
which will be:
Sat 2014/Sept/6
Sat 2016/Feb/6
Sat 2016/Sep/3
...
Sun 2024/Sep/1
this was verified with dateutil-python and http://jkbr.github.io/,

Orderly execution of multiple rule defined in one DRL file

I defined multiples rules in one DRL file, how to set order, want to execute one after another (top to bottom).
Rules are fired automatically when the conditions are met when the inserted facts(objects) are updated. But if in case you want to run it from top to bottom, you can set a property called salience in the rule. The value it takes is an integer. The rule with the highest salience is executed first.
rule "First name mandatory"
salience 10
when
(Person(firstName=="" || firstName==null))
then
...
end
If you use salience you will be killing the rule engine, because you will be forcing the rule execution order instead of letting the engine decide.
Cheers
Setting priority to rules is the best form.
Use Salience to determine the priority of each rule, where a higher number denotes a higher priority.
The default Salience for rules is 0, and you can give negative Salience, for example,if you want a rule to be fired last.