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