<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 "direct"<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>> 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>> 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 "direct"<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 < 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] + "\n");<br> bufWrite.flush();<br> System.out.println("reading rulefile: " + args[1] + " ...");<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("reading datafile: " + args[0] + " ...");<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("move") == 0) {<br> first = bufRead.readLine();<br>
second = bufRead.readLine();<br> session.insert(new Move(first, second));<br> }<br> else if (line.compareTo("par") == 0) {<br> first = bufRead.readLine();<br> second = bufRead.readLine();<br>
session.insert(new ClassPar(first, second));<br> }<br> else if (line.compareTo("sib") == 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("loading cputime: " + cputime + "\n");<br> bufWrite.write("loading walltime: " + walltime + "\n");<br>
bufWrite.flush();<br> System.out.println("loading cputime: " + cputime);<br> System.out.println("loading walltime: " + walltime);<br> /*<br> System.out.print("Facts in memory:");<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("calculating ...");<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("computing cputime: " + cputime + "\n");<br> bufWrite.write("computing walltime: " + walltime + "\n");<br>
bufWrite.flush();<br> System.out.println("computing cputime: " + cputime);<br> System.out.println("computing walltime: " + walltime);<br> System.out.print("Derived facts in memory:");<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("Exception encountered when computing:");<br> System.out.println(e);<br>
System.exit(0);<br> }<br> }<br> static void usage() {<br> System.out.println("usage:");<br> System.out.println("java Test <data_file> <rule_file> <result_file>");<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 "move(" + this.getFirst() + ", " + this.getSecond() + ").";<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 "win(" + this.getFirst() + ").";<br> }<br> }<br>}<br></p>