Hi,
I am conducting a test of Jess where I am inserting 10,000 rules -
each matching a particular modulus of a prime number and then calling
code to aggregate prime roots of those numbers being matched. The test
submits 100 random numbers one by one - each matching against one of
the 10,000 rules - and the result is timed. It is a test I grabbed
from one of the tests in the drools package which basically stress
tests the rule engine and outputs timing results. I am doing this to
compare the total computation time between Drools and Jess - and Jess
is about 6 times slower, but I think the problem may not be Jess
itself but either how my rules are constructed or some problem where
Jess isn't flushing the I/O stream properly.
Of particular note are the prepareConstructs() method where the rules
are being built, and the execute() method where the rule engine is
iteratively being invoked.
I am attaching an executable Jar file which can be run via the
command: java -jar primeNumTest.jar -or- java -cp primeNumTest.jar
PrimeFactorsTest
Also, I am attaching the two java source files to this message.
Program flow is pretty easy to follow looking at the "main" method in
PrimeFactorsTest.java.
I am very interested in using Jess and am evaluating its usage for my
company, but this initial test presents some problems...
Can anyone take a look at this and maybe tell me or point to what the
problem may be?
I'm a first-time majordomo user, and I seem to have a problem with
posting (I guess
you can't use attachments?) So I'm posting the 2 java source files inline below,
which can be compiled and run against jess.jar
Thanks ahead of time,
David
====================
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Random;
import jess.JessException;
import jess.Rete;
import jess.Value;
/**
* By default, creates 10,000 rules each matching a single prime number -
* then inserts 100 random integers into the engine and collects those
* rules which have fired, and all their roots outputting the timing
* for each stage and each calculation.
*
* See the main() method (at the bottom) for program flow.
*
* @author David Ray
*/
public class PrimeFactorsTest
{
private long seed;
private long start;
private long total;
private int numRules;
private int[] primes;
private int[] randomNumbers;
private Rete rete;
private static long[] timepoint = new long[2];
PrimeFactorsTest(int seed)
{
this.seed = seed;
this.rete = new Rete();
}
/**
* Generates "numFacts" number of random numbers.
*
* @param numFacts
*/
public void createRandomNums(int numFacts)
{
System.out.println("Generating random number knowledge...");
Random rand = new Random(seed);
randomNumbers = new int[numFacts];
start = System.currentTimeMillis();
for(int i = 0;i < numFacts;i++) {
int nextRand = rand.nextInt(primes[numRules - 1]) + 1;
if(nextRand < 1) {--i; continue;}
randomNumbers[i] = nextRand;
}
total = (System.currentTimeMillis() - start);
System.out.println("Generated "+numFacts+" random numbers in
["+total+" msecs.]");
}
/**
* Inserts a "Jess" formatted command into the Jess Rete engine.
*
* @param statement
* @return Value A jess.Value object representing the
result obtained
* from executing the
specified statement.
*/
public Value insertStatement(String statement)
{
Value retVal = null;
try {
retVal = rete.eval(statement);
}catch(JessException e) {
e.printStackTrace();
}
return retVal;
}
/**
* Inserts 10,000 rules into the working memory - each representing
* a "pattern" which will only activate if the LHS is true (meaning
* that the unique prime number correlated with each rule is a prime
* root of the asserted random number).
*/
public void prepareConstructs()
{
/////////////////////////////////////////////
//Used for debugging
//String statement = "(watch all)";
//insertStatement(statement);
System.out.println("-----------------------");
System.out.println("Creating New RuleBase...");
start = System.currentTimeMillis();
String statement = "(deftemplate RandomNumber (declare
(from-class
RandomNumber)))";
insertStatement(statement);
for(int divisor : primes)
{
statement = "(defrule modulus"+divisor+
" (RandomNumber (value ?x))" +
" (test (eq 0 (mod ?x "+divisor+")))"+
"=>"+
"(call ?a extractRoots "+divisor+"))";
insertStatement(statement);
}
total = (System.currentTimeMillis() - start) / 1000;
System.out.println("Created new RuleBase with "+numRules+" rules
in ["+total+" secs.]");
}
/**
* Binds a new RandomNumber object containing a unique random
* number. Then adds the random number fact causing the matching
* rules to activate. Following this, "run" is called to actually
* fire the rules. The "bound" RandomNumber (and the contained
* prime roots) are then printed out and "retract" is called to
* "clear" the working memory of the last fact and the process
* then continues until all RandomNumbers have been processed.
*/
public void execute()
{
System.out.println("-----------------------");
System.out.println("Starting test...");
total = 0;
stopwatch(0);
for(int randNum : randomNumbers)
{
stopwatch( 1 );
String statement = "(bind ?a (new RandomNumber
"+randNum+"))";
insertStatement(statement);
//Add a Fact causing Activation to happen here.
statement = "(add ?a)";
insertStatement(statement);
//Rule Fire happens here.
statement = "(run)";
insertStatement(statement);
statement = "(printout t (call ?a toString) :
"+stopwatch( 1 )+" crlf)";
insertStatement(statement);
statement = "(retract 1)";
insertStatement(statement);
}
System.out.println("Total Engine Time: " + stopwatch(0));
}
/**
* Reads a file containing "numRules" number of prime numbers into
* an array which is later used to generate a unique rule for each
* prime number.
*
* @param numRules
*/
public void loadPrimeList(int numRules)
{
this.numRules = numRules;
BufferedReader buf = null;
try {
buf = new BufferedReader(
new InputStreamReader(
getClass().getClassLoader().getResourceAsStream("1100000-primes.txt")));
String line = null;
int count = 0;
System.out.println("Reading "+numRules+" Prime Numbers");
start = System.currentTimeMillis();
primes = new int[numRules];
while((line = buf.readLine()) != null && ((count) <
numRules)) {
primes[count++] = Integer.parseInt(line.trim());
}
total = (System.currentTimeMillis() - start);
System.out.println("Read "+primes.length+" Prime Numbers
["+total+" msecs.]");
}
catch(Exception e) { e.printStackTrace(); }
finally {
try { buf.close(); }catch(Exception ignore) {}
}
}
/**
* Returns and records time points specified by the index "i"
* passed in.
*
* @param i
* @return message A formatted String containing the
specified time point.
*/
private static String stopwatch(int i)
{
long now = System.currentTimeMillis( );
String message = " [" + ( now - timepoint[i] ) + " msecs]";
timepoint[i] = now;
return message;
}
public static void main(String[] args)
{
int seed = 0;
int numRules = 10000;
int numFacts = 100;
if(args != null && args.length == 3) {
seed = Integer.parseInt(args[2]);
numRules = Integer.parseInt(args[0]);
numFacts = Integer.parseInt(args[1]);
}
PrimeFactorsTest pft = new PrimeFactorsTest(seed);
System.out.println("Number of Rules: "+numRules);
System.out.println("Number of Facts: "+numFacts);
System.out.println("Random Seed: "+seed);
pft.loadPrimeList(numRules);
pft.createRandomNums(numFacts);
pft.prepareConstructs();
pft.execute();
}
}
===================
import java.util.ArrayList;
import java.util.List;
/**
* Stores a random integer value and can extract and store multiples of
* a specified prime root correlated to the original initialized value.
*
* @author davidray
*/
public class RandomNumber {
Integer value;
int quotient = 1;
List<Integer> primeList = new ArrayList<Integer>();
public RandomNumber() {}
public RandomNumber(Integer number)
{
this.value = number;
this.quotient = number.intValue();
}
/**
* Operates on this <code>RandomNumber</code>'s value using the
* specified prime root by extracting the greatest number of the
* specified prime root, saving each root in a list of roots.
*
* @param primeRoot
*/
public void extractRoots(Integer primeRoot)
{
quotient = value.intValue();
int pFactor = primeRoot.intValue();
do {
primeList.add(primeRoot);
quotient = quotient / pFactor;
} while(quotient % pFactor == 0);
}
/**
* Returns the original value with which this
<code>RandomNumber</code> was
* initialized.
*
* @return Integer the original value.
*/
public Integer getValue()
{
return value;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((value == null) ? 0 :
value.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
RandomNumber other = (RandomNumber) obj;
if (value == null) {
if (other.value != null)
return false;
} else if (!value.equals(other.value))
return false;
return true;
}
@Override
public String toString()
{
return "Number ("+value+") Prime Numbers: "+primeList;
}
}
=======================
--------------------------------------------------------------------
To unsubscribe, send the words 'unsubscribe jess-users [email protected]'
in the BODY of a message to [email protected], NOT to the list
(use your own address!) List problems? Notify [email protected].
--------------------------------------------------------------------