> 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() +
> ").";
> }
> }
> }
> _______________________________________________