[rules-users] Negation semantics in Drools

Paul Fodor paul.i.fodor at gmail.com
Thu Apr 16 11:43:00 EDT 2009


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() + ").";
 }
    }
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/rules-users/attachments/20090416/bac9aeb0/attachment.html 


More information about the rules-users mailing list