001: /*
002: * Copyright (C) 1999-2004 <A href="http://www-ist.massey.ac.nz/JBDietrich" target="_top">Jens Dietrich</a>
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */
018:
019: package org.mandarax.examples.family.performance;
020:
021: import org.apache.log4j.BasicConfigurator;
022: import org.apache.log4j.Category;
023: import org.apache.log4j.Level;
024: import org.mandarax.kernel.InferenceEngine;
025: import org.mandarax.kernel.KnowledgeBase;
026: import org.mandarax.kernel.Predicate;
027: import org.mandarax.kernel.Query;
028: import org.mandarax.kernel.ResultSet;
029: import org.mandarax.kernel.Rule;
030: import org.mandarax.kernel.SimplePredicate;
031: import org.mandarax.reference.AdvancedKnowledgeBase;
032: import org.mandarax.reference.ResolutionInferenceEngine3;
033: import org.mandarax.util.LogicFactorySupport;
034:
035: /**
036: * Performance test based on a tree model with one root, NUMBER_OF_SONS children
037: * and NUMBER_OF_GRANDCHILDREN_PER_SON children for each child node.
038: * The tree is described by father facts, and there is one rule describing
039: * what it means to be sibling (brother). The number of expected results is:
040: * (using N for NUMBER_OF_SONS and G for NUMBER_OF_GRANDCHILDREN_PER_SON)
041: * <tt>N*(N-1) + N*G+(G-1)</tt>.
042: * E.g., in this class we use N=25 and G=3, this yields 750.
043: * <br>
044: * We run the computation 3 times to give JIT compilers time to optimize code execution.
045: * <br.
046: * This version uses 'optimized' constant and variable names that are easy to match (see String#equals).
047: * Here is the result obtained using a Pentium 4 1.8, 512 MB RAM, Win XP Pro, SUN JDK 1.4.2, (version 3.3, 19 Feb 2004):<p>
048: * 1st run solutions found: 750 time (in millis): 511<br>
049: * 2nd run solutions found: 750 time (in millis): 320<br>
050: * 3nd run solutions found: 750 time (in millis): 280<p>
051: * <p>
052: * Same as before, but uses BEA's jrockit 81 sp2_141_05 JVM:<p>
053: * 1st run solutions found: 750 time (in millis): 420<br>
054: * 2nd run solutions found: 750 time (in millis): 231<br>
055: * 3nd run solutions found: 750 time (in millis): 360<p>
056: * @author <A href="http://www-ist.massey.ac.nz/JBDietrich" target="_top">Jens Dietrich</A>
057: * @version 3.4 <7 March 05>
058: * @since 2.1
059: */
060: public class PerformanceTest1 {
061: public static final String FAMILY_ROOT = "root";
062: public static final int NUMBER_OF_SONS = 25;
063: public static final int NUMBER_OF_GRANDCHILDREN_PER_SON = 3;
064:
065: public static void main(String[] args) {
066:
067: // disable deep level logging
068: BasicConfigurator.configure();
069: Category.getRoot().setLevel(Level.INFO);
070:
071: System.out.println("Run performance test "
072: + PerformanceTest1.class.getName());
073:
074: // get kb
075: KnowledgeBase kb = createKB();
076: System.out.println("kb created");
077:
078: // issue query
079: InferenceEngine ie = new ResolutionInferenceEngine3();
080: Query query = kb.getQuery("query");
081:
082: System.out.println("Inference engine performance test");
083: System.out.println("ie tested: " + ie);
084: System.out.println("kb size: " + kb.getClauseSets().size());
085:
086: System.out.println("1st run");
087: run(ie, query, kb, false);
088: System.out.println("2nd run");
089: run(ie, query, kb, false);
090: System.out.println("3nd run");
091: run(ie, query, kb, false);
092:
093: System.out.println("Computation finished !");
094: System.exit(0);
095:
096: }
097:
098: /**
099: * Run and time the computation.
100: */
101: private static void run(InferenceEngine ie, Query q,
102: KnowledgeBase kb, boolean logResults) {
103: try {
104: long before = System.currentTimeMillis();
105: ResultSet rs = ie.query(q, kb, InferenceEngine.ALL,
106: InferenceEngine.BUBBLE_EXCEPTIONS);
107: long after = System.currentTimeMillis();
108:
109: // count results
110: int solutions = 0;
111: while (rs.next()) {
112: solutions = solutions + 1;
113: if (logResults) {
114: System.out.print(rs.getResult(String.class, "x"));
115: System.out.print(" is brother of ");
116: System.out.println(rs.getResult(String.class, "y"));
117: }
118: }
119:
120: // report
121: System.out.println("solutions found: " + solutions);
122: System.out.println("time (in millis): " + (after - before));
123: } catch (Exception x) {
124: x.printStackTrace();
125: }
126: }
127:
128: /**
129: * Set up the knowledge base.
130: * @return the knowledge base.
131: */
132: private static KnowledgeBase createKB() {
133: LogicFactorySupport lfs = new LogicFactorySupport();
134:
135: // init predicates
136: Class[] struct = { String.class, String.class };
137: Predicate predicate_is_father = new SimplePredicate("father",
138: struct);
139: Predicate predicate_is_brother = new SimplePredicate("brother",
140: struct);
141:
142: // add knowledge - rule
143: KnowledgeBase kb = new AdvancedKnowledgeBase();
144: Rule rule = lfs.rule(lfs.prereq(predicate_is_father, lfs
145: .variable("s"), lfs.variable("f")), lfs.prereq(
146: predicate_is_father, lfs.variable("t"), lfs
147: .variable("f")), lfs.prereq(
148: org.mandarax.lib.text.StringArithmetic.NOT_EQUAL, lfs
149: .variable("s"), lfs.variable("t")), lfs.fact(
150: predicate_is_brother, lfs.variable("s"), lfs
151: .variable("t")));
152: kb.add(rule);
153:
154: // add facts for family tree
155: for (int i = 0; i < NUMBER_OF_SONS; i++) {
156: kb
157: .add(lfs.fact(predicate_is_father, lfs.cons("" + i,
158: String.class), lfs.cons(FAMILY_ROOT,
159: String.class)));
160: for (int j = 0; j < NUMBER_OF_GRANDCHILDREN_PER_SON; j++) {
161: kb.add(lfs.fact(predicate_is_father, lfs.cons("" + i
162: + "." + j, String.class), lfs.cons("" + i,
163: String.class)));
164: }
165: }
166: // add query
167: kb.addQuery(lfs.query(lfs.fact(predicate_is_brother, lfs
168: .variable("x", String.class), lfs.variable("y",
169: String.class)), "query"));
170:
171: // return
172: return kb;
173: }
174: }
|