In this case, I think Paul's initial analysis is pertinent. Unless I am missing something obvious, the order of the facts may change the order in which the activations are executed, but not the number of executions. The end result should be the same with the same number of Win facts in the working memory.
We need to investigate if that is still happening in latest trunk. []s Edson 2009/4/16 Paul Fodor <paul.i.fo...@gmail.com> > On Thu, Apr 16, 2009 at 1:18 PM, Greg Barton <greg_bar...@yahoo.com>wrote: > >> >> This is not a problem with negation. I don't think you understand rule >> conflict resolution. >> >> Here's your rule: >> >> rule "direct" >> when >> m : Move(x : first, y : second) >> not Win(first == y) >> then >> insert(new Win(m.getFirst())); >> end >> >> This rule, regardles of whether it uses negation, will be affected by fact >> insertion order. This is because the first condition will match on any Move >> in working memory. When all of the potential firings of this rule are put >> on the agenda, which will initially be one for each Move in working memory, >> one must be selected to fire. The order of fact insertion (recency) is one >> of the ways Drools resolves this by default. > > > Thank you. I see. > > >> If you don't want that behavior you can change it by using a different >> conflict resolver instance. See classes in the package org.drools.conflict: >> >> >> https://hudson.jboss.org/hudson/job/drools/lastSuccessfulBuild/artifact/trunk/target/javadocs/unstable/drools-core/org/drools/conflict/package-summary.html > > Or define your own. > > > That is very dificult task. The win-nowin test was just an example of use > of the default negation. My requirement covers stratified or non-stratified > logic programs, and not one example in particular. > I don't really think that it is possible to implement a general "rule > conflict resolution" resolver for default negation. This is hard > in production rule systems. > > Paul. > > >> You can install a new one by calling either of these methods on your >> RuleBaseConfiguration: >> >> setProperty("drools.conflictResolver", <resolver class name>) >> >> or >> >> setConflictResolver(<an instance of ConflictResolver>) >> >> --- On Thu, 4/16/09, Paul Fodor <paul.i.fo...@gmail.com> wrote: >> >> > From: Paul Fodor <paul.i.fo...@gmail.com> >> > Subject: [rules-users] Negation semantics in Drools >> > To: "Rules Users List" <rules-users@lists.jboss.org> >> > Date: Thursday, April 16, 2009, 10:43 AM >> > Dear Sir, >> > >> > I found a problem with negation in Drools when changing the >> > order of the >> > facts in the database also changes the final model. >> > Consider the classic win-nowin problem encoded in Drools as >> > follows: >> > >> > win.drl: >> > >> > package tests; >> > import tests.Test.Win; >> > import tests.Test.Move; >> > rule "direct" >> > when >> > m : Move(x : first, y : second) >> > not Win(first == y) >> > then >> > insert(new Win(m.getFirst())); >> > end >> > >> > With two moves in the database: move(1,2) and move(2,3), >> > for one order of the facts in the input file we get one >> > result: win(2), >> > while for the other order (i.e., move(2,3) and move(1,2)) >> > we get 2 results: >> > win(1) and win(2). >> > >> > For win_upper1_drools.drools: >> > > java tests.Test win_upper1_drools.drools win.drl >> > result >> > reading rulefile: win.drl ... >> > reading datafile: win_upper1_drools.drools ... >> > computing cputime: 0.0 >> > computing walltime: 0.0030 >> > Derived facts in memory:move(1, 2). >> > win(2). >> > move(2, 3). >> > 3 >> > >> > For win_upper2_drools.drools: >> > > java tests.Test win_upper2_drools.drools win.drl >> > result >> > reading rulefile: win.drl ... >> > reading datafile: win_upper2_drools.drools ... >> > computing cputime: 0.0 >> > computing walltime: 0.0040 >> > Derived facts in memory:win(1). >> > win(2). >> > move(1, 2). >> > move(2, 3). >> > 4 >> > >> > I attached all the sources used in these tests in the >> > email. This example is >> > locally stratified. I am using the latest released version >> > of Drools. >> > >> > Regards, >> > Paul Fodor >> > >> > win.drl: >> > >> > package tests; >> > import tests.Test.Win; >> > import tests.Test.Move; >> > rule "direct" >> > when >> > m : Move(x : first, y : second) >> > not Win(first == y) >> > then >> > insert(new Win(m.getFirst())); >> > end >> > >> > >> > win_upper1_drools.drools: >> > >> > move >> > 1 >> > 2 >> > move >> > 2 >> > 3 >> > >> > win_upper2_drools.drools: >> > >> > move >> > 2 >> > 3 >> > move >> > 1 >> > 2 >> > >> > Test.java: >> > >> > package tests; >> > import java.io.*; >> > import java.io.InputStreamReader; >> > import org.drools.RuleBase; >> > import org.drools.RuleBaseFactory; >> > import org.drools.StatefulSession; >> > import org.drools.compiler.PackageBuilder; >> > import org.drools.FactHandle; >> > import java.util.Iterator; >> > import java.lang.management.ManagementFactory; >> > import java.lang.management.ThreadMXBean; >> > public class Test { >> > public static void main (String args[]) { >> > if (args.length < 3) { >> > usage(); >> > } >> > long starttime_cpu, endtime_cpu, starttime_sys, >> > endtime_sys; >> > double cputime, walltime; >> > ThreadMXBean tb_cpu = ManagementFactory.getThreadMXBean(); >> > // create rulebase >> > try { >> > FileWriter output = new FileWriter(args[2]); >> > BufferedWriter bufWrite = new BufferedWriter(output); >> > bufWrite.write(args[0] + "\n"); >> > bufWrite.flush(); >> > System.out.println("reading rulefile: " + >> > args[1] + " ..."); >> > Reader source = new >> > InputStreamReader(Test.class.getResourceAsStream(args[1])); >> > final PackageBuilder builder = new PackageBuilder(); >> > builder.addPackageFromDrl(source); >> > if (builder.hasErrors()) { >> > System.out.println(builder.getErrors().toString()); >> > System.exit(0); >> > } >> > final RuleBase ruleBase = >> > RuleBaseFactory.newRuleBase(); >> > ruleBase.addPackage(builder.getPackage()); >> > final StatefulSession session = >> > ruleBase.newStatefulSession(); >> > // loading datafile >> > System.out.println("reading datafile: " + >> > args[0] + " ..."); >> > FileReader input = new FileReader(args[0]); >> > starttime_sys = System.nanoTime(); >> > starttime_cpu = tb_cpu.getCurrentThreadCpuTime(); >> > BufferedReader bufRead = new BufferedReader(input); >> > String first, second, line = bufRead.readLine(); >> > while (line != null) { >> > if (line.compareTo("move") == 0) { >> > first = bufRead.readLine(); >> > second = bufRead.readLine(); >> > session.insert(new Move(first, second)); >> > } >> > else if (line.compareTo("par") == 0) { >> > first = bufRead.readLine(); >> > second = bufRead.readLine(); >> > session.insert(new ClassPar(first, second)); >> > } >> > else if (line.compareTo("sib") == 0) { >> > first = bufRead.readLine(); >> > second = bufRead.readLine(); >> > session.insert(new ClassSib(first, second)); >> > } >> > line = bufRead.readLine(); >> > } >> > endtime_cpu = tb_cpu.getCurrentThreadCpuTime(); >> > endtime_sys = System.nanoTime(); >> > cputime = (endtime_cpu - starttime_cpu) * 1e-9; >> > cputime = Math.round(cputime * 1000) * 1e-3; >> > walltime = (endtime_sys - starttime_sys) * 1e-9; >> > walltime = Math.round(walltime * 1000) * 1e-3; >> > bufWrite.write("loading cputime: " + cputime >> > + "\n"); >> > bufWrite.write("loading walltime: " + >> > walltime + "\n"); >> > bufWrite.flush(); >> > System.out.println("loading cputime: " + >> > cputime); >> > System.out.println("loading walltime: " + >> > walltime); >> > /* >> > System.out.print("Facts in memory:"); >> > long count = 0; >> > for (Iterator it = session.iterateFactHandles(); >> > it.hasNext(); ) { >> > FactHandle factHandle = (FactHandle) it.next(); >> > count ++; >> > //System.out.println(session.getObject(factHandle)); >> > } >> > System.out.println(count); >> > */ >> > // computing >> > System.out.println("calculating ..."); >> > starttime_sys = System.nanoTime(); >> > starttime_cpu = tb_cpu.getCurrentThreadCpuTime(); >> > session.fireAllRules(); >> > endtime_cpu = tb_cpu.getCurrentThreadCpuTime(); >> > endtime_sys = System.nanoTime(); >> > cputime = (endtime_cpu - starttime_cpu) * 1e-9; >> > cputime = Math.round(cputime * 1000) * 1e-3; >> > walltime = (endtime_sys - starttime_sys) * 1e-9; >> > walltime = Math.round(walltime * 1000) * 1e-3; >> > bufWrite.write("computing cputime: " + >> > cputime + "\n"); >> > bufWrite.write("computing walltime: " + >> > walltime + "\n"); >> > bufWrite.flush(); >> > System.out.println("computing cputime: " + >> > cputime); >> > System.out.println("computing walltime: " + >> > walltime); >> > System.out.print("Derived facts in >> > memory:"); >> > long count1 = 0; >> > for (Iterator it = session.iterateFactHandles(); >> > it.hasNext(); ) { >> > FactHandle factHandle = (FactHandle) it.next(); >> > count1 ++; >> > System.out.println(session.getObject(factHandle)); >> > } >> > System.out.println(count1); >> > bufWrite.close(); >> > session.dispose(); >> > } catch (Exception e) { >> > System.out.println("Exception encountered when >> > computing:"); >> > System.out.println(e); >> > System.exit(0); >> > } >> > } >> > static void usage() { >> > System.out.println("usage:"); >> > System.out.println("java Test <data_file> >> > <rule_file> <result_file>"); >> > System.exit(0); >> > } >> > public static class General { >> > private String first; >> > private String second; >> > public General() {} >> > public General(String firstIn, String secondIn) { >> > this.first = firstIn; >> > this.second = secondIn; >> > } >> > public String getFirst() { >> > return this.first; >> > } >> > public String getSecond() { >> > return this.second; >> > } >> > } >> > public static class Move extends General { >> > public Move() { >> > super(); >> > } >> > public Move(String firstIn, String secondIn) { >> > super(firstIn, secondIn); >> > } >> > public String toString() { >> > return "move(" + this.getFirst() + ", >> > " + this.getSecond() + ")."; >> > } >> > } >> > public static class Win { >> > private String first; >> > public Win() {} >> > public Win(String firstIn) { >> > this.first = firstIn; >> > } >> > public String getFirst() { >> > return this.first; >> > } >> > public String toString() { >> > return "win(" + this.getFirst() + >> > ")."; >> > } >> > } >> > } >> > _______________________________________________ >> > rules-users mailing list >> > rules-users@lists.jboss.org >> > https://lists.jboss.org/mailman/listinfo/rules-users >> >> >> >> _______________________________________________ >> rules-users mailing list >> rules-users@lists.jboss.org >> https://lists.jboss.org/mailman/listinfo/rules-users >> > > > _______________________________________________ > rules-users mailing list > rules-users@lists.jboss.org > https://lists.jboss.org/mailman/listinfo/rules-users > > -- Edson Tirelli JBoss Drools Core Development JBoss, a division of Red Hat @ www.jboss.com
_______________________________________________ rules-users mailing list rules-users@lists.jboss.org https://lists.jboss.org/mailman/listinfo/rules-users