[rules-users] Negation semantics in Drools
Paul Fodor
paul.i.fodor at gmail.com
Thu Apr 16 14:30:17 EDT 2009
On Thu, Apr 16, 2009 at 1:18 PM, Greg Barton <greg_barton at yahoo.com> wrote:
>
> This is not a problem with negation. I don't think you understand rule
> conflict resolution.
>
> Here's your rule:
>
> rule "direct"
> when
> m : Move(x : first, y : second)
> not Win(first == y)
> then
> insert(new Win(m.getFirst()));
> end
>
> This rule, regardles of whether it uses negation, will be affected by fact
> insertion order. This is because the first condition will match on any Move
> in working memory. When all of the potential firings of this rule are put
> on the agenda, which will initially be one for each Move in working memory,
> one must be selected to fire. The order of fact insertion (recency) is one
> of the ways Drools resolves this by default.
Thank you. I see.
> If you don't want that behavior you can change it by using a different
> conflict resolver instance. See classes in the package org.drools.conflict:
>
>
> https://hudson.jboss.org/hudson/job/drools/lastSuccessfulBuild/artifact/trunk/target/javadocs/unstable/drools-core/org/drools/conflict/package-summary.html
Or define your own.
That is very dificult task. The win-nowin test was just an example of use of
the default negation. My requirement covers stratified or non-stratified
logic programs, and not one example in particular.
I don't really think that it is possible to implement a general "rule
conflict resolution" resolver for default negation. This is hard
in production rule systems.
Paul.
> You can install a new one by calling either of these methods on your
> RuleBaseConfiguration:
>
> setProperty("drools.conflictResolver", <resolver class name>)
>
> or
>
> setConflictResolver(<an instance of ConflictResolver>)
>
> --- On Thu, 4/16/09, Paul Fodor <paul.i.fodor at gmail.com> wrote:
>
> > From: Paul Fodor <paul.i.fodor at gmail.com>
> > Subject: [rules-users] Negation semantics in Drools
> > To: "Rules Users List" <rules-users at lists.jboss.org>
> > Date: Thursday, April 16, 2009, 10:43 AM
> > 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 at lists.jboss.org
> > https://lists.jboss.org/mailman/listinfo/rules-users
>
>
>
> _______________________________________________
> rules-users mailing list
> rules-users at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/rules-users
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/rules-users/attachments/20090416/128f4e94/attachment.html
More information about the rules-users
mailing list