Nesting prefix-or and prefix-and causing parsing problem
by Patrik Dufresne
Hi,
I have a problem with nesting prefix-and and prefix-or. I found a bug in
JIRA but it been fixed in drools expert 5.0. Here is snippet to reproduce
the problem (based on the original rule). I get the following error :
java.lang.RuntimeException: [48,5]: [ERR 102] Line 48:5 mismatched input
'EmployeePreferredShift' in rule "assign-preferred-position"
declare EntityA
number : int
end
declare EntityB
number : int
end
declare EntityC
number : int
end
rule "and-or-snippet"
dialect "java"
when
EntityA(
$number : number)
not ( and
EntityB (
number == $number )
( or
( and
EntityC (
number < $number)
not EntityB (
number == 4)
)
not EntityC (
number == 10 )
)
EntityA (
number <= $number )
( or
not EntityC (
number >= $number)
( and
EntityC (
number == 4 || number >=10 )
not EntityB (
number == -3)
not EntityB (
number == -10 )
)
)
not EntityB(
number == 0)
)
then
System.out.println("Working");
end
Patrik Dufresne
12 years, 9 months
Drools and Jersey
by mike
Hi there,
I am trying to make rest calls from Drools. For that I am using Jersey
http://jersey.java.net/. I cannot no get it to work if I use mvel,
otherwise it works fine.
Here is a sample rule:
----------------------------------------------------------
import com.sun.jersey.api.client.Client;
dialect "mvel"
rule "create Rest Client"
then new Client();
end
----------------------------------------------------------
I would love to be able to use mvel since it curves java syntax :)
Thank you
Mike
12 years, 9 months
drools arithmetics without eval()
by fx242
I have a question regarding eval() use. My rulebase is around ~3k rules, most
of them are auto-generated by templates, and they end up looking like this:
rule "CONFIG_114"
salience 0
when
client: Client()
contextProd: PortfolioProduct(prodAdded == true, productId ==
"PROFESSIONAL")
Number(qty_00001: intValue) from accumulate(pp:
PortfolioProduct(productId in ("BOX_001"), prodAdded == true), count(pp))
Number(qty_00002: intValue) from accumulate(pp:
PortfolioProduct(productId in ("BOX_002"), prodAdded == true), count(pp))
Number(qty_00003: intValue) from accumulate(pp:
PortfolioProduct(productId in ("BOX_003"), prodAdded == true), count(pp))
Number(qty_00004: intValue) from accumulate(pp:
PortfolioProduct(productId in ("BOX_004"), prodAdded == true), count(pp))
Number(qty_00005: intValue) from accumulate(pp:
PortfolioProduct(productId in ("BOX_005"), prodAdded == true), count(pp))
eval(qty_00001 == 1)
not(eval(qty_00002 >= (qty_00003 + qty_00004 + qty_00005)))
then
balance(kcontext, contextProd, qty_00002, ">=", (qty_00003 + qty_00004 +
qty_00005));
end
These rules have all one or two evals in the end, comparing product
quantities that are present in the Working Memory.
My question is: Is there any better way to write this kind of rules without
resorting to eval()?
I'm currently getting hit (in performance terms) by over-using these, so I
wonder if there is a better way to do this.
Thanks!
Tiago Lopes
--
View this message in context: http://drools.46999.n3.nabble.com/drools-arithmetics-without-eval-tp38232...
Sent from the Drools: User forum mailing list archive at Nabble.com.
12 years, 9 months
Problem with temporal operations spanning daylight to standard time
by lhorton
Most of the USA went from Standard Time to Daylight Time this past weekend.
We use some of the temporal operations in our rules, mainly to do
calculations of date differences by whole days, and some of the calculations
are wrong. The ones in error involve comparing dates where one is standard
time and one is daylight savings time. I wrote a small test case to prove
this.
I have a simple Person class:
public class Person {
private Date birthdate;
private int status;
public Date getBirthdate() {
return birthdate;
}
public void setBirthdate(Date birthdate) {
this.birthdate = birthdate;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
}
and a simple drl file:
package com.drools.resources;
import com.drools.person.Person;
import java.util.Date;
import java.util.Calendar;
global Long now
rule "Birthday Rule"
dialect "mvel"
when
$person : Person(birthdate != null)
Date($bDate : time before[3d] now) from $person.birthdate
then
$person.setStatus(3);
end
rule "Debug Birthday Rule"
dialect "mvel"
when
$person : Person(birthdate != null)
then
System.out.println("now is " + new Date(now));
System.out.println("birthdate is " + $person.getBirthdate());
end
and two tests:
@Test
public void testTemporalJanuary() throws Exception {
KnowledgeBase base =
createKnowledgeBaseFromRulesFile("src/com/drools/resources/temporal.drl");
StatelessKnowledgeSession kSession =
createStatelessKnowledgeSession(base);
// test january - both dates are standard time
Date now = new Date(2012-1900, 00, 13);
kSession.getGlobals().set("now", now.getTime());
Person p = new Person();
p.setStatus(0);
p.setBirthdate(new Date(2012-1900, 00, 10));
kSession.execute(p);
assertTrue(p.getStatus() == 3);
}
@Test
public void testTemporalMarch() throws Exception {
KnowledgeBase base =
createKnowledgeBaseFromRulesFile("src/com/drools/resources/temporal.drl");
StatelessKnowledgeSession kSession =
createStatelessKnowledgeSession(base);
// test March: one day standard, the other is daylight
Date now = new Date(2012-1900, 02, 13);
kSession.getGlobals().set("now", now.getTime());
Person p = new Person();
p.setStatus(0);
p.setBirthdate(new Date(2012-1900, 02, 10));
kSession.execute(p);
assertTrue(p.getStatus() == 3);
}
the first test (testTemporalJanuary) compares January 13 to January 10, and
it passes (matches the before[3d] condition).
the second test (testTemporalMarch, which is the same except for using March
instead of January) fails.
The output of the debug rule for these tests is:
now is Fri Jan 13 00:00:00 PST 2012
birthdate is Tue Jan 10 00:00:00 PST 2012
now is Tue Mar 13 00:00:00 PDT 2012
birthdate is Sat Mar 10 00:00:00 PST 2012
--
View this message in context: http://drools.46999.n3.nabble.com/Problem-with-temporal-operations-spanni...
Sent from the Drools: User forum mailing list archive at Nabble.com.
12 years, 9 months
Avoid propagation of update in a then block.
by Patrik Dufresne
Hi,
I have some trouble to figure out how to stop / start the propagation of
updates within a Then block.
Here is a snippet to represent the problem I have.
rule "my-rule"
when
$objects : List()
from accumulate( $entity : Entity(closed==false),
collectList($entity) )
then
for(Object obj : $objects) {
((Entity) obj).setClosed(true);
update(obj);
}
end
When this rule's consequence is called first, the first enity in the list
is 'update', but then update if propagated to immediately causing the rule
to be evaluated with all the entities minus the updated one. So I'm
wondering if there is a transaction like operation allowing me to update
all the entities in the list and then fire the rules.
According to the documentation no-loop should have help me for this.
Here is the original rules
rule "close-shift"
salience -1
when
$shift : Shift( )
$assignments : List( size > 0 )
from accumulate (
$assignment : PlanifEventAssignment(
close == false,
shift == $shift ),
collectList($assignment) )
$availables : List( size >= $assignments.size )
from accumulate ( ( and
ShiftAssignment(
shift == $shift,
$employee : employee)
$available : EmployeeAvailable (
employee == $employee,
assignment.shift == $shift) ),
collectList($available) )
eval( Dfs.search($assignments, $availables) != null )
then
// Recalculate the result.
Map table = Dfs.search($assignments, $availables);
for(Object entry : table.entrySet()) {
PlanifEventAssignment assignment =
(PlanifEventAssignment)((Entry)entry).getKey();
EmployeeValue employee = (EmployeeValue)((Entry)entry).getValue();
assignment.setClose(true);
assignment.setEmployee(employee);
update(assignment);
}
end
Patrik Dufresne
12 years, 9 months
[Drools Planner] Hard constraint appears to be ignored
by Reinis
Hello, it appears that hard constraint I have defined is being ignored
in some rare cases. Here's an example:
This is what my application logs after getting best solution after
solver has returned from solve():
2012-02-23 21:28:54,595 [main] INFO Project Project1 assignment
563:[2012-02-27T13:00:00.000/2012-02-27T17:00:00.000] was assigned to John
2012-02-23 21:28:54,597 [main] INFO Project Project2 assignment
508:[2012-02-27T13:00:00.000/2012-02-27T17:00:00.000] was assigned to John
(The log says that John was assigned twice in same time period to two
different assignments (assignment 563 and assignment 508)
Here short explanation of the relevant domain data
assignment.id = 563
assignment.interval = 2012-02-27T13:00:00.000/2012-02-27T17:00:00.000
assignment.project = Project1
assignment.resource = John
And this is rule that, to my opinion should've prohibited that two
assignments get assigned to the same resource:
rule "only one assignment within interval for the same resource"
when
$leftAssignment : Assignment($leftId : id, $interval :
interval, resource != null, $resource : resource)
$rightAssignment : Assignment(interval == $interval, resource
== $resource, id != $leftId)
then
insertLogical(new IntConstraintOccurrence("only one assignment
within interval for the same resource", ConstraintType.NEGATIVE_HARD, 1,
$leftAssignment, $rightAssignment));
end
The score looks like this:
2012-02-23 21:28:54,594 [main] DEBUG The hard score is: 0 and the soft
score is: -532
So no hard constraints are broken according to planner.
My question is not what is wrong with this particular example (unless it
is obvious for you), but if you can think of any anti-pattern that would
cause this behavior?
What I already checked is:
- this happens really sporadically (most of the time the result is
CORRECT but in 1 from 5 runs I get this kind of error);
- I checked, re-checked and re-re-checked all the hashCode, compareTo,
solutionHashCode, solutionCompare, clone, ... methods - they appear to
be correct;
- moves are simple and I tried to keep them consistent with the way
moves in drools-planner examples are constructed;
Would be great if you could give me a hint to what direction I should
look next.
br
Reinis
12 years, 9 months
logicalInsert and construction of an inferred fact.
by devan.vanreenen@gmail.com
Hi there,
Kindly assist.
I am playing around with Inference and Truth maintenance
I have 2 questions.
1) When doing a logicalInsert() in the consequence of a rule - is this the
same as doing a insertLogical()? The reason I ask is that when creating rule
in Guvnor it doesnt recognize logicalInsert() but recognizes
insertLogical()?
2) Is there a way for Guvnor to create the inferred fact (dynamically) or
must I create the inferred fact seperately and place in a jar and upload the
the POJO model jar to Guvnor before the inferred fact can be logically
inserted?
Any help would be much appreciated.
Thanks
Devan
--
View this message in context: http://drools.46999.n3.nabble.com/logicalInsert-and-construction-of-an-in...
Sent from the Drools: User forum mailing list archive at Nabble.com.
12 years, 9 months
NPE in FireAllRulesCommand (bug?)
by Mike Melton
Drools 5.3.1.Final.
I have a use case where I am executing a BatchExecutionCommand against a
stateless session. One of the sub-commands is a FireAllRulesCommand, from
which I would like to retrieve the number of rules actually fired. Since
there is no factory or constructor method to configure both a maximum rules
to fire and an out identifier, I have to use code like this to set up
my FireAllRulesCommand:
FireAllRulesCommand farc = (FireAllRulesCommand)
CommandFactory.newFireAllRules(maxRulesToFire);
farc.setOutIdentifier("num-rules-fired");
commands.add(farc); // commands is List<Command<?>> which I later use to
construct a BatchExecutionCommand
At runtime, when I execute the BatchExecutionCommand, I get an NPE
at FireAllRulesCommand:110. After some investigating, I determined that the
value returned from (ExecutionResultImpl) ((KnowledgeCommandContext)
context).getExecutionResults() is null, which causes the NPE.
As far as I can tell, the cause of this breaks down like so:
- StatelessKnowledgeSession.execute() fires with the batch command as input.
- It constructs a KnowledgeCommandContext, setting the ExecutionResults
parameter of the constructor to null (line 254).
- KnowledgeCommandContext.executionResults is a private member with no
setter so there is no way to give it a value after it's been instantiated.
- The FireAllRulesCommand fires as part of the batch, and when it tries to
access the execution results from the context, the NPE is thrown.
StatelessKnowledgeSession.execute() later gets the execution results from
the session itself, via the ExecutionResultsImpl instance which is
constructed and passed to the startBatchExecution() method on line 262. I
haven't had time to try this myself, but if we constructed
the ExecutionResultsImpl earlier and passed it to both
the KnowledgeCommandContext constructor and the startBatchExecution()
method, would the problem be alleviated?
In other words, something like this
(StatelessKnowledgeSessionImpl.java:251):
public <T> T execute(Command<T> command) {
StatefulKnowledgeSession ksession = newWorkingMemory();
ExecutionResults results = new ExecutionResultImpl();
KnowledgeCommandContext context = new KnowledgeCommandContext( new
ContextImpl( "ksession",
null ),
null,
null,
ksession,
results
);
try {
((StatefulKnowledgeSessionImpl)
ksession).session.startBatchExecution( results );
If this is indeed a bug and not something silly I'm missing, I'll be happy
to submit a JIRA and even a pull request with the fix.
Thanks
Mike
12 years, 9 months