Logic Problems in DROOLS
by Mark Armitage
I've been playing with DROOLS again and had another look at
LogicProblems. I am quite pleased with the program I have now created.
It's pretty simple and should be easily modifiable for any of the
magazine type logic problems. Anyway, just in case it's of interest to
anyone else:
The java is:
package com.mda.logic;
import java.io.InputStreamReader;
import org.drools.RuleBase;
import org.drools.RuleBaseFactory;
import org.drools.StatefulSession;
import org.drools.compiler.PackageBuilder;
public class MonkeyDROOLS {
/**
* @param args
*/
public static void main(final String[] args) throws Exception {
//Standard stuff to load in the DROOLS rules and set it all up
final PackageBuilder builder = new PackageBuilder();
builder.addPackageFromDrl( new
InputStreamReader( MonkeyDROOLS.class.getResourceAsStream( "/
MonkeyDROOLS.drl" ) ) );
final RuleBase ruleBase = RuleBaseFactory.newRuleBase();
ruleBase.addPackage( builder.getPackage() );
final StatefulSession session = ruleBase.newStatefulSession();
//Define the various names being used for he problem
String[] names = new String[] { "anna", "harriet",
"mike", "sam" };
String[] fruits = new String[] { "apple", "banana",
"orange", "pear" };
String[] positions = new String[] { "branch", "grass",
"rock", "stream" };
//Insert all the possible combinations
for ( int n = 0; n < names.length; n++ ) {
for ( int c = 0; c < fruits.length; c++ ) {
for ( int p = 0; p < positions.length; p++ ) {
session.insert( new GRID( names[n], fruits[c],
positions[p]) );
//System.out.printf("Insert:%7s %7s %7s
\n",names[n], fruits[c], positions[p]);
}
}
}
//System.out.println( "----------------------------------");
//Fire the rules and then clean-up
session.fireAllRules();
session.dispose();
}
//Storage for the logic problem items plus accessors to get each item
public static class GRID {
private String name;
private String fruit;
private String position;
public GRID(String name,
String fruit,
String position) {
super();
this.name = name;
this.fruit = fruit;
this.position = position;
}
/**
* @return the fruit
*/
public String getFruit() {
return this.fruit;
}
/**
* @return the name
*/
public String getName() {
return this.name;
}
/**
* @return the position
*/
public String getPosition() {
return this.position;
}
}
}
The rules file is:
//Monkey Puzzle Logic Problem
//
//Mark Armitage 2008
//
//The basic idea is, in the JAVA we assert every possible combination.
//Then we have rules that retract anything given by the problems data.
//If it's a negative, i.e. 'sam doesn't like bananas' then that will
//equate to one rule; 'GRID( name == "sam", fruit == "banana")'
//in other words; if the entry is for 'sam' and the fruit is 'banana'
then
//we know it can't be true so retract it.
//Positive rules are a bit more complicated, they require 2 rules ;-)
//So e.g. 'sam likes sitting on grass'. We are retracting remember, so
we
//want to remove entries where sam isn't sitting on grass, or where
someone
//else IS sitting on grass, we know both of those cases are false. So
the
//rules would be; 'GRID( name == "sam", position != "grass" )' &
// 'GRID( name != "sam", position == "grass" )'
//I've tried to make it all as simple as possible, basically so that it
//should be easy to modify for ANY of the Logic Problems in the
magazines.
//There is one final rule that has to be added; that's to remove
duplicates.
//Sam can't be sat in two places, the apple can't be liked by two
monkeys etc.
package com.mda.logic;
//So we can access the java GRID with the data
import com.mda.logic.MonkeyDROOLS.GRID;
//Salience 150 so it is printed first
//Just an introduction to the problem.
rule "Intro"
salience 150
when
then
System.out.println("Monkey Logic Problem from Puzzler's
Paradise");
System.out.println("============================================");
System.out.println("1) Sam doesn't like bananas, likes
sitting on grass.");
System.out.println("2) Monkey sat on the rock ate the apple.");
System.out.println(" Monkey who ate the pear didn't sit on
the tree branch.");
System.out.println("3) Anna sat by the stream but she didn't
eat the pear.");
System.out.println("4) Harriet didn't sit on the tree
branch.");
System.out.println(" Mike doesn't like oranges.");
System.out.println("");
end
//1) Sam doesn't like bananas, likes sitting on grass.
//[We're retracting, so if sam likes bananas then that can't be right,
// also if sam is not on the grass that has to come out,
// but so does anything on the grass that isn't sam.]
rule "#1"
salience 100
when
$fact: (GRID( name == "sam", fruit == "banana") or
GRID( name == "sam", position != "grass" ) or
GRID( name != "sam", position == "grass" ));
then
retract ($fact);
end
//2) Monkey sat on the rock ate the apple.
// Monkey who ate the pear didn't sit on the tree branch.
//[We're retracting, so if the position is rock but not an apple then
bin it,
// again you also have to do the other; if it is an apple but not on
the rock.
// positive facts such as pos=rock, fruit=apple will equate to two
retraction criteria,
// firstly the pos=rock but fruit<>apple; but also the other way
around, fruit=apple but pos<>rock.]
rule "#2"
salience 100
when
$fact: (GRID( position == "rock", fruit != "apple" ) or
GRID( fruit == "apple", position != "rock" ) or
GRID( fruit == "pear", position == "branch"));
then
retract ($fact);
end
//3) Anna sat by the stream but she didn't eat the pear.
rule "#3"
salience 100
when
$fact: (GRID( name == "anna", position != "stream") or
GRID( position == "stream", name != "anna" ) or
GRID( name == "anna", fruit == "pear" ));
then
retract ($fact);
end
//4) Harriet didn't sit on the tree branch.
// Mike doesn't like oranges.
rule "#4"
salience 100
when
$fact: (GRID( name == "harriet", position == "branch") or
GRID( name == "mike", fruit == "orange"));
then
retract ($fact);
end
//Ensure everything is used just once
//Find a solution but ensure that we don't have any duplicates.
rule "No duplicates"
salience 50
when
$sol1: GRID( name == "anna", $aP : position,
$aF : fruit);
$sol2: GRID( name == "harriet", $hP : position != $aP,
$hF : fruit != $aF);
$sol3: GRID( name == "mike", $mP : position != $aP,
position != $hP,
$mF : fruit != $aF, fruit != $hF);
$sol4: GRID( name == "sam", $sP : position != $aP,
position != $hP, position != $mP,
$sF : fruit != $aF, fruit != $hF, fruit != $mF);
then
printGrid( " ",$sol1,0);
printGrid( " 1:",$sol1,1);
printGrid( " 2:",$sol2,1);
printGrid( " 3:",$sol3,1);
printGrid( " 4:",$sol4,1);
end
//Salience -99 so it is printed last
rule "Summary"
salience -99
when
then
System.out.println("");
System.out.println("The solution should be:");
System.out.printf(" %-7.7s %-7.7s %-8.8s
\n","Name","Fruit","Position");
System.out.printf(" %-7.7s %-7.7s %-8.8s
\n","====","=====","========");
System.out.printf(" %-7.7s %-7.7s %-8.8s
\n","anna","orange","stream");
System.out.printf(" %-7.7s %-7.7s %-8.8s
\n","harriet","apple","rock");
System.out.printf(" %-7.7s %-7.7s %-8.8s
\n","mike","banana","branch");
System.out.printf(" %-7.7s %-7.7s %-8.8s
\n","sam","pear","grass");
end
function void printGrid( String tmp, GRID summary, int mode)
{
if (mode == 0)
{
System.out.println("");
System.out.println("The solution from DROOLS:");
System.out.printf(tmp+"%-7.7s %-7.7s %-8.8s
\n","Name","Fruit","Position");
System.out.printf(tmp+"%-7.7s %-7.7s %-8.8s
\n","====","=====","========");
}
else
{
System.out.printf(tmp+"%-7.7s %-7.7s %-8.8s
\n",summary.getName(),summary.getFruit(),summary.getPosition());
}
}
A sample run is:
Monkey Logic Problem from Puzzler's Paradise
============================================
1) Sam doesn't like bananas, likes sitting on grass.
2) Monkey sat on the rock ate the apple.
Monkey who ate the pear didn't sit on the tree branch.
3) Anna sat by the stream but she didn't eat the pear.
4) Harriet didn't sit on the tree branch.
Mike doesn't like oranges.
The solution from DROOLS:
Name Fruit Position
==== ===== ========
1:anna orange stream
2:harriet apple rock
3:mike banana branch
4:sam pear grass
The solution should be:
Name Fruit Position
==== ===== ========
anna orange stream
harriet apple rock
mike banana branch
sam pear grass
17 years, 8 months
ClassLoader Problem
by Yann Massard
Hi,
I am using version 4.0.7 of Drools.
I am trying to load facts with a particular ClassLoader and compiling
the rules using the same ClassLoader:
------
Reader source = new FileReader("plugin/Sample.drl");
ClassLoader pluginClassLoader = new PluginClassLoader();
Thread.currentThread().setContextClassLoader( pluginClassLoader );
PackageBuilder builder = new PackageBuilder(new
PackageBuilderConfiguration(pluginClassLoader));
builder.addPackageFromDrl(source);
Package pkg = builder.getPackage();
RuleBase ruleBase = RuleBaseFactory.newRuleBase();
ruleBase.addPackage(pkg);
------
This works fine for usage of the fact types in the LHS of rules and for
field extraction.
But when I add a method invocation or an update statement on a fact to
the RHS of a rule I get a rule compilation error:
-------
org.drools.rule.InvalidRulePackage: Rule Compilation error : [Rule
name=Hello World, agendaGroup=MAIN, salience=0, no-loop=false]
com/sample/Rule_Hello_World_0.java (6:267) : plugin.Message cannot be
resolved to a type
-------
I have reduced the problem to a minimal complexity (see attachments).
Any ideas?
By the way: do I really need to set both the ClassLoader in the
PackageBuilderConfiguration AND the ContextClassLoader (as described in
http://blog.athico.com/2006/12/dynamically-generated-class-beans-as.html)?
Thanks in advance!
Best regards
Yann Massard
package com.sample
import plugin.*; // change to plugin.Message and it won't work!
rule "Hello World"
when
m : Message( status == Message.HELLO, message : message )
then
System.out.println( message );
// NONE OF THE FOLLOWING WORKS:
m.setMessage( "Goodbye cruel world" );
m.setStatus( Message.GOODBYE );
update( m );
end
rule "GoodBye"
no-loop true
when
m : Message( status == Message.GOODBYE, message : message )
then
System.out.println( message );
// NONE OF THE FOLLOWING WORKS:
m.setMessage( message );
end
17 years, 8 months
Delivery reports about your e-mail
by Mail Administrator
Dear user rules-users(a)lists.jboss.org, administration of lists.jboss.org would like to let you know the following:
We have received reports that your email account has been used to send a huge amount of spam during this week.
Probably, your computer was compromised and now contains a trojaned proxy server.
We recommend that you follow instructions in order to keep your computer safe.
Best wishes,
The lists.jboss.org team.
17 years, 8 months
null checking
by samd
How do I evaluate null conditions in the following case for example?
seller: ( seller.cheese != null && seller.active == true )
cheese: ( cheese.type == "chedder" ) from seller.cheese
In the above example seller.cheese is null but seller is used in the second
part of the rule since we can't evaluate facts for null for some reason how
do you check for a null condition.
--
View this message in context: http://www.nabble.com/null-checking-tp20015953p20015953.html
Sent from the drools - user mailing list archive at Nabble.com.
17 years, 8 months
Eclipse plug-in and peculiar problem with import statements
by Beck, Eivind
I’m experiencing a peculiar problem with import statements using the Drools Eclipse plug-in.
When importing domain objects from a specific package, the editor gives an error for all rule statements within the rule file, saying that the import can not be resolved.
The classes that give this problem have the fully qualified class name pattern: no.vps.dom.fund.*.* - example: no.vps.dom.fund.fund.SalesPerson
The error message in the Eclipse editor says: “The import no.vps.dom.fund cannot be resolved.
The problem is definitely not errors in the package names, as using the fully qualified class names within the rules works just fine. Also – using the import statements works fine within the rule engine, even if the Eclipse editor gives compilation errors.
I’ve tried to do some changes to the package name, and changing a single character in any of the first four element of the fully qualified class name solves the problem – example: so.vps.dom.fund.fund.SalesPerson works fine.
Unfortunately, we’re not allowed to change the package names for the domain objects – so that not an option. I’ve tried to figure out if there is some kind of conflict between the package name and the list of reserved Drools keywords, but I’m not able to see that “no.vps.dom.fund” can possibly match any of the keywords.
Currently the only options I see are:
1) Ignoring the editors errors. This is extremely annoying as it seems like we have a lot of problems, and it is easy to overlook actual problems in-between all the “red dots”….
2) Using fully qualified class names within the rules for the domain objects within no.vps.dom.fund.* - which is also a bit cumbersome and annoying
If anybody has some suggestions to workarounds, or something that can be “tweaked within the Eclipse plug-in” this will be much appreciated.
For the reference we’re using:
- Eclipse version 3.3.1.1
- Drools 4.0.7-eclipse-3.3
- Java Runtime Environment 1.6.0_07
- Windows XP Professional
- eivind -
________________________________
Capgemini is a trading name used by the Capgemini Group of companies which includes Capgemini Norge AS, a company registered in Norway (number 943574537) whose registered office is at Hoffsveien 1 D - Pb. 475, Skøyen – 0214 Oslo.
This message contains information that may be privileged or confidential and is the property of the Capgemini Group. It is
intended only for the person to whom it is addressed. If you are not the intended recipient, you are not authorized to
read, print, retain, copy, disseminate, distribute, or use this message or any part thereof. If you receive this message
in error, please notify the sender immediately and delete all copies of this message.
17 years, 8 months
Drools indexing
by Senlin Liang
Hi all,
I got one question: How does drools index the objects in memory? Does
it use hashing index, based on what? Or drools uses adaptive indexing?
Thanks a lot,
Senlin
17 years, 8 months
ClassLoader Problem
by Yann Massard
Hi,
I am using version 4.0.7 of Drools.
I am trying to load facts with a particular ClassLoader and compiling
the rules using the same ClassLoader:
------
Reader source = new FileReader("plugin/Sample.drl");
ClassLoader pluginClassLoader = new PluginClassLoader();
Thread.currentThread().setContextClassLoader( pluginClassLoader );
PackageBuilder builder = new PackageBuilder(new
PackageBuilderConfiguration(pluginClassLoader));
builder.addPackageFromDrl(source);
Package pkg = builder.getPackage();
RuleBase ruleBase = RuleBaseFactory.newRuleBase();
ruleBase.addPackage(pkg);
------
This works fine for usage of the fact types in the LHS of rules and for
field extraction.
But when I add a method invocation or an update statement on a fact to
the RHS of a rule I get a rule compilation error:
-------
org.drools.rule.InvalidRulePackage: Rule Compilation error : [Rule
name=Hello World, agendaGroup=MAIN, salience=0, no-loop=false]
com/sample/Rule_Hello_World_0.java (6:267) : plugin.Message cannot be
resolved to a type
-------
I have reduced the problem to a minimal complexity (see attachments).
Any ideas?
By the way: do I really need to set both the ClassLoader in the
PackageBuilderConfiguration AND the ContextClassLoader (as described in
http://blog.athico.com/2006/12/dynamically-generated-class-beans-as.html)?
Thanks in advance!
Best regards
Yann Massard
package com.sample
import plugin.*; // change to plugin.Message and it won't work!
rule "Hello World"
when
m : Message( status == Message.HELLO, message : message )
then
System.out.println( message );
// NONE OF THE FOLLOWING WORKS:
m.setMessage( "Goodbye cruel world" );
m.setStatus( Message.GOODBYE );
update( m );
end
rule "GoodBye"
no-loop true
when
m : Message( status == Message.GOODBYE, message : message )
then
System.out.println( message );
// NONE OF THE FOLLOWING WORKS:
m.setMessage( message );
end
17 years, 8 months
RHS start ruleflow not executing associated rules
by djouki
env: fedora5, eclipse3.3, drools4.0.7. jdk1.5
I've created a ruleflow hierarchy where the execution of a rule associated
with one ruleflow starts a second ruleflow.
rule "Main - Entry"
ruleflow-group "checkData"
when
exists Root(itemReq:itemRequest)
then
logger.debug("Main - Entry");
System.out.println("Main - Entry");
drools.getWorkingMemory().startProcess("com.it.checkData");
end
At issue, the rules within the second ruleflow, though activated, are not
being executed. The audit view shows the secondary ruleflow start and stop
without the interim execution of an activated rule within it. The contained
rules are valid and should fire (tried empty when clause). Attribute-wise,
all rules are similar to the one shown above; that is, the only attribute
set is ruleflow-group, with the occasional salience.
In an effort to resolve this issue, I tried calling the ruleflow via a
subprocess node, but it gave the same result.
Any assitance would be appreicated.
http://www.nabble.com/file/p19804474/rule.log rule.log
--
View this message in context: http://www.nabble.com/RHS-start-ruleflow-not-executing-associated-rules-t...
Sent from the drools - user mailing list archive at Nabble.com.
17 years, 8 months