Hi Wolfgang,
I guess this is why having a second pair of eyes (aka code review)
is a good thing! :P
Thank you very much for your prompt reply, and yes I can see that
executing the command parsing in a loop
would be errr... kinda slow :) I'll take a look at the API and see if
I can pull together the corresponding commands
in java and see how that works.
Thanks again!
David
On Wed, Feb 18, 2009 at 4:43 PM, Wolfgang Laun <[email protected]> wrote:
> I've had a look at execute(). It uses (indirectly) the API call Rete.eval()
> for performing
> the add-run-retract cycle. This loop, written in Jess and called from the
> Jess prompt,
> would be slow; but calling the Jess parser, repeatedly, is even slower.
> Comparing
> this to any other system would only be fair, if you'd tone down that other
> system
> likewise. Anyway, this style of coding isn't anywhere near what you'd do in
> a production
> system. I suggest that you rewrite the add-run-retract cycle to use the
> corresponding
> API calls.
>
> Cheers
> Wolfgang
>
>
> On Wed, Feb 18, 2009 at 10:28 PM, David Ray <[email protected]>
> wrote:
>>
>> 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].
>> --------------------------------------------------------------------
>>
>
>
--------------------------------------------------------------------
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].
--------------------------------------------------------------------