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.mandarax.kernel.InferenceEngine;
022: import org.mandarax.kernel.KnowledgeBase;
023: import org.mandarax.kernel.Predicate;
024: import org.mandarax.kernel.Query;
025: import org.mandarax.kernel.ResultSet;
026: import org.mandarax.kernel.Rule;
027: import org.mandarax.kernel.SimplePredicate;
028: import org.mandarax.reference.AbstractResolutionInferenceEngine;
029: import org.mandarax.reference.AdvancedKnowledgeBase;
030: import org.mandarax.reference.ResolutionInferenceEngine3;
031: import org.mandarax.util.LogicFactorySupport;
032: import org.mandarax.util.logging.NullLoggerFactory;
033:
034: /**
035: * Performance test based on a tree model with one root, NUMBER_OF_SONS children
036: * and NUMBER_OF_GRANDCHILDREN_PER_SON children for each child node.
037: * The tree is described by father facts, and there is one rule describing
038: * what it means to be sibling (brother). The number of expected results is:
039: * (using N for NUMBER_OF_SONS and G for NUMBER_OF_GRANDCHILDREN_PER_SON)
040: * <tt>N*(N-1) + N*G+(G-1)</tt>.
041: * E.g., in this class we use N=50 and G=3, this yields 2750.
042: * <br>
043: * We run the computation 3 times to give JIT compilers time to optimize code execution.
044: * <br.
045: * This version uses 'optimized' constant and variable names that are easy to match (see String#equals).
046: * 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>
047: * 1st run solutions found: 2750 time (in millis): 2173<br>
048: * 2nd run solutions found: 2750 time (in millis): 1913<br>
049: * 3nd run solutions found: 2750 time (in millis): 1883<p>
050: * <p>
051: * Same as before, but uses BEA's jrockit 81 sp2_141_05 JVM:<p>
052: * 1st run solutions found: 2750 time (in millis): 3295<br>
053: * 2nd run solutions found: 2750 time (in millis): 1602<br>
054: * 3nd run solutions found: 2750 time (in millis): 1152<p>
055: * @author <A href="http://www-ist.massey.ac.nz/JBDietrich" target="_top">Jens Dietrich</A>
056: * @version 3.4 <7 March 05>
057: * @since 2.1
058: */
059: public class PerformanceTest3 {
060: public static final String FAMILY_ROOT = "root";
061: public static final int NUMBER_OF_SONS = 50;
062: public static final int NUMBER_OF_GRANDCHILDREN_PER_SON = 3;
063:
064: public static void main(String[] args) {
065: // disable deep level logging
066: //BasicConfigurator.configure();
067: //Category.getRoot().setLevel(Level.INFO);
068: (new NullLoggerFactory()).install();
069:
070: System.out.println("Run performance test "
071: + PerformanceTest3.class.getName());
072:
073: // get kb
074: KnowledgeBase kb = createKB();
075: System.out.println("kb created");
076:
077: // issue query
078: AbstractResolutionInferenceEngine ie = new ResolutionInferenceEngine3();
079: ie.setMaxNumberOfProofSteps(100000);
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:
111: int solutions = 0;
112: while (rs.next()) {
113: solutions = solutions + 1;
114:
115: if (logResults) {
116: System.out.print(rs.getResult(String.class, "x"));
117: System.out.print(" is brother of ");
118: System.out.println(rs.getResult(String.class, "y"));
119: }
120: }
121:
122: // report
123: System.out.println("solutions found: " + solutions);
124: System.out.println("time (in millis): " + (after - before));
125: } catch (Exception x) {
126: x.printStackTrace();
127: }
128: }
129:
130: /**
131: * Set up the knowledge base.
132: * @return the knowledge base.
133: */
134: private static KnowledgeBase createKB() {
135: LogicFactorySupport lfs = new LogicFactorySupport();
136:
137: // init predicates
138: Class[] struct = { String.class, String.class };
139: Predicate predicate_is_father = new SimplePredicate("father",
140: struct);
141: Predicate predicate_is_brother = new SimplePredicate("brother",
142: struct);
143:
144: // add knowledge - rule
145: KnowledgeBase kb = new AdvancedKnowledgeBase();
146: Rule rule = lfs.rule(lfs.prereq(predicate_is_father, lfs
147: .variable("s"), lfs.variable("f")), lfs.prereq(
148: predicate_is_father, lfs.variable("t"), lfs
149: .variable("f")), lfs.prereq(
150: org.mandarax.lib.text.StringArithmetic.NOT_EQUAL, lfs
151: .variable("s"), lfs.variable("t")), lfs.fact(
152: predicate_is_brother, lfs.variable("s"), lfs
153: .variable("t")));
154: kb.add(rule);
155:
156: // add facts for family tree
157: for (int i = 0; i < NUMBER_OF_SONS; i++) {
158: kb
159: .add(lfs.fact(predicate_is_father, lfs.cons("" + i,
160: String.class), lfs.cons(FAMILY_ROOT,
161: String.class)));
162: for (int j = 0; j < NUMBER_OF_GRANDCHILDREN_PER_SON; j++) {
163: kb.add(lfs.fact(predicate_is_father, lfs.cons("" + i
164: + "." + j, String.class), lfs.cons("" + i,
165: String.class)));
166: }
167: }
168: // add query
169: kb.addQuery(lfs.query(lfs.fact(predicate_is_brother, lfs
170: .variable("x", String.class), lfs.variable("y",
171: String.class)), "query"));
172:
173: // return
174: return kb;
175: }
176: }
|