<p>Dear Sir,</p>
<p>I found a problem with negation in Drools when changing the order of the facts in the database also changes the final model. <br>Consider the classic win-nowin problem encoded in Drools as follows:</p>
<p>win.drl:</p>
<p>package tests;<br>import tests.Test.Win;<br>import tests.Test.Move;<br>rule &quot;direct&quot;<br>    when<br>        m : Move(x : first, y : second)<br>        not Win(first == y)<br>    then<br> insert(new Win(m.getFirst()));<br>
end</p>
<p>With two moves in the database: move(1,2) and move(2,3), <br>for one order of the facts in the input file we get one result: win(2), <br>while for the other order (i.e., move(2,3) and move(1,2)) we get 2 results: win(1) and win(2).</p>

<p>For win_upper1_drools.drools:<br>&gt; java tests.Test win_upper1_drools.drools win.drl result<br>reading rulefile: win.drl ...<br>reading datafile: win_upper1_drools.drools ...<br>computing cputime: 0.0<br>computing walltime: 0.0030<br>
Derived facts in memory:move(1, 2).<br>win(2).<br>move(2, 3).<br>3</p>
<p>For win_upper2_drools.drools:<br>&gt; java tests.Test win_upper2_drools.drools win.drl result<br>reading rulefile: win.drl ...<br>reading datafile: win_upper2_drools.drools ...<br>computing cputime: 0.0<br>computing walltime: 0.0040<br>
Derived facts in memory:win(1).<br>win(2).<br>move(1, 2).<br>move(2, 3).<br>4</p>
<p>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.</p>
<p>Regards,<br> Paul Fodor </p>
<p>win.drl:</p>
<p>package tests;<br>import tests.Test.Win;<br>import tests.Test.Move;<br>rule &quot;direct&quot;<br>    when<br>        m : Move(x : first, y : second)<br> not Win(first == y)<br>    then<br> insert(new Win(m.getFirst()));<br>
end</p>
<p><br>win_upper1_drools.drools:</p>
<p>move<br>1<br>2<br>move<br>2<br>3</p>
<p>win_upper2_drools.drools:</p>
<p>move<br>2<br>3<br>move<br>1<br>2</p>
<p>Test.java:</p>
<p>package tests;<br>import java.io.*;<br>import java.io.InputStreamReader;<br>import org.drools.RuleBase;<br>import org.drools.RuleBaseFactory;<br>import org.drools.StatefulSession;<br>import org.drools.compiler.PackageBuilder;<br>
import org.drools.FactHandle;<br>import java.util.Iterator;<br>import java.lang.management.ManagementFactory;<br>import java.lang.management.ThreadMXBean;<br>public class Test {<br>    public static void main (String args[]) {<br>
 if (args.length &lt; 3) {<br>     usage();<br> }<br> long starttime_cpu, endtime_cpu, starttime_sys, endtime_sys;<br> double cputime, walltime;<br> ThreadMXBean tb_cpu = ManagementFactory.getThreadMXBean();<br> // create rulebase<br>
 try {<br>     FileWriter output = new FileWriter(args[2]);<br>     BufferedWriter bufWrite = new BufferedWriter(output);<br>     bufWrite.write(args[0] + &quot;\n&quot;);<br>     bufWrite.flush();<br>     System.out.println(&quot;reading rulefile: &quot; + args[1] + &quot; ...&quot;);<br>
     Reader source = new InputStreamReader(Test.class.getResourceAsStream(args[1]));<br>     final PackageBuilder builder = new PackageBuilder();<br>     builder.addPackageFromDrl(source);<br>     if (builder.hasErrors()) {<br>
  System.out.println(builder.getErrors().toString());<br>  System.exit(0);<br>     }<br>     final RuleBase ruleBase = RuleBaseFactory.newRuleBase();<br>     ruleBase.addPackage(builder.getPackage());<br>     final StatefulSession session = ruleBase.newStatefulSession();<br>
     // loading datafile<br>     System.out.println(&quot;reading datafile: &quot; + args[0] + &quot; ...&quot;);<br>     FileReader input = new FileReader(args[0]);<br>     starttime_sys = System.nanoTime();<br>     starttime_cpu = tb_cpu.getCurrentThreadCpuTime();<br>
     BufferedReader bufRead = new BufferedReader(input);<br>     String first, second, line = bufRead.readLine();<br>     while (line != null) {<br>  if (line.compareTo(&quot;move&quot;) == 0) {<br>      first = bufRead.readLine();<br>
      second = bufRead.readLine();<br>      session.insert(new Move(first, second));<br>  }<br>  else if (line.compareTo(&quot;par&quot;) == 0) {<br>      first = bufRead.readLine();<br>      second = bufRead.readLine();<br>
      session.insert(new ClassPar(first, second));<br>  }<br>  else if (line.compareTo(&quot;sib&quot;) == 0) {<br>      first = bufRead.readLine();<br>      second = bufRead.readLine();<br>      session.insert(new ClassSib(first, second));<br>
  }<br>  line = bufRead.readLine();<br>     }<br>     endtime_cpu = tb_cpu.getCurrentThreadCpuTime();<br>     endtime_sys = System.nanoTime();<br>     cputime = (endtime_cpu - starttime_cpu) * 1e-9;<br>     cputime = Math.round(cputime * 1000) * 1e-3;<br>
     walltime = (endtime_sys - starttime_sys) * 1e-9;<br>     walltime = Math.round(walltime * 1000) * 1e-3;<br>     bufWrite.write(&quot;loading cputime: &quot; + cputime + &quot;\n&quot;);<br>     bufWrite.write(&quot;loading walltime: &quot; + walltime + &quot;\n&quot;);<br>
     bufWrite.flush();<br>     System.out.println(&quot;loading cputime: &quot; + cputime);<br>     System.out.println(&quot;loading walltime: &quot; + walltime);<br>     /*<br>     System.out.print(&quot;Facts in memory:&quot;);<br>
     long count = 0;<br>     for (Iterator it = session.iterateFactHandles(); it.hasNext(); ) {<br>  FactHandle factHandle = (FactHandle) it.next();<br>  count ++;<br>  //System.out.println(session.getObject(factHandle));<br>
     }<br>     System.out.println(count);<br>     */<br>     // computing<br>     System.out.println(&quot;calculating ...&quot;);<br>     starttime_sys = System.nanoTime();<br>     starttime_cpu = tb_cpu.getCurrentThreadCpuTime();<br>
     session.fireAllRules();<br>     endtime_cpu = tb_cpu.getCurrentThreadCpuTime();<br>     endtime_sys = System.nanoTime();<br>     cputime = (endtime_cpu - starttime_cpu) * 1e-9;<br>     cputime = Math.round(cputime * 1000) * 1e-3;<br>
     walltime = (endtime_sys - starttime_sys) * 1e-9;<br>     walltime = Math.round(walltime * 1000) * 1e-3;<br>     bufWrite.write(&quot;computing cputime: &quot; + cputime + &quot;\n&quot;);<br>     bufWrite.write(&quot;computing walltime: &quot; + walltime + &quot;\n&quot;);<br>
     bufWrite.flush();<br>     System.out.println(&quot;computing cputime: &quot; + cputime);<br>     System.out.println(&quot;computing walltime: &quot; + walltime);<br>     System.out.print(&quot;Derived facts in memory:&quot;);<br>
     long count1 = 0;<br>     for (Iterator it = session.iterateFactHandles(); it.hasNext(); ) {<br>  FactHandle factHandle = (FactHandle) it.next();<br>  count1 ++;<br>  System.out.println(session.getObject(factHandle));<br>
     }<br>     System.out.println(count1);<br>     bufWrite.close();<br>     session.dispose();<br> } catch (Exception e) {<br>     System.out.println(&quot;Exception encountered when computing:&quot;);<br>     System.out.println(e);<br>
     System.exit(0);<br> }<br>    }<br>    static void usage() {<br> System.out.println(&quot;usage:&quot;);<br> System.out.println(&quot;java Test &lt;data_file&gt; &lt;rule_file&gt; &lt;result_file&gt;&quot;);<br> System.exit(0);<br>
    }<br>    public static class General {<br> private String first;<br> private String second;<br> public General() {}<br> public General(String firstIn, String secondIn) {<br>     this.first  = firstIn;<br>     this.second = secondIn;<br>
 }<br> public String getFirst() {<br>     return this.first;<br> }<br> public String getSecond() {<br>     return this.second;<br> }<br>    }<br>    public static class Move extends General {<br> public Move() {<br>     super();<br>
 }<br> public Move(String firstIn, String secondIn) {<br>     super(firstIn, secondIn);<br> }<br> public String toString() {<br>     return &quot;move(&quot; + this.getFirst() + &quot;, &quot; + this.getSecond() + &quot;).&quot;;<br>
 }<br>    }<br>    public static class Win {<br> private String first;<br> public Win() {}<br> public Win(String firstIn) {<br>     this.first  = firstIn;<br> }<br> public String getFirst() {<br>     return this.first;<br>
 }<br> public String toString() {<br>     return &quot;win(&quot; + this.getFirst() + &quot;).&quot;;<br> }<br>    }<br>}<br></p>