KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > hp > hpl > jena > reasoner > rulesys > BasicForwardRuleInfGraph


1 /******************************************************************
2  * File: BasicForwardRuleInfGraph.java
3  * Created by: Dave Reynolds
4  * Created on: 30-Mar-03
5  *
6  * (c) Copyright 2003, 2004, 2005 Hewlett-Packard Development Company, LP
7  * [See end of file]
8  * $Id: BasicForwardRuleInfGraph.java,v 1.41 2005/03/23 13:58:14 der Exp $
9  *****************************************************************/

10 package com.hp.hpl.jena.reasoner.rulesys;
11
12 import com.hp.hpl.jena.mem.GraphMem;
13 import com.hp.hpl.jena.reasoner.*;
14 import com.hp.hpl.jena.reasoner.rulesys.impl.*;
15 import com.hp.hpl.jena.graph.*;
16
17 import java.util.*;
18
19 import com.hp.hpl.jena.util.OneToManyMap;
20 import com.hp.hpl.jena.util.iterator.*;
21
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24
25 /**
26  * An inference graph interface that runs a set of forward chaining
27  * rules to conclusion on each added triple and stores the entire
28  * result set.
29  * <p>
30  * This implementation has a horribly inefficient rule chainer built in.
31  * Once we have this working generalize this to an interface than
32  * can call out to a rule engine and build a real rule engine (e.g. Rete style). </p>
33  *
34  * @author <a HREF="mailto:der@hplb.hpl.hp.com">Dave Reynolds</a>
35  * @version $Revision: 1.41 $ on $Date: 2005/03/23 13:58:14 $
36  */

37 public class BasicForwardRuleInfGraph extends BaseInfGraph implements ForwardRuleInfGraphI {
38
39 //=======================================================================
40
// variables
41

42     /** Table of derivation records, maps from triple to RuleDerivation */
43     protected OneToManyMap derivations;
44     
45     /** The set of deduced triples, this is in addition to base triples in the fdata graph */
46     protected FGraph fdeductions;
47     
48     /** Reference to any schema graph data bound into the parent reasoner */
49     protected Graph schemaGraph;
50     
51     /** The forward rule engine being used */
52     protected FRuleEngineI engine;
53     
54     /** The original rule set as supplied */
55     protected List rules;
56     
57     /** Flag which, if true, enables tracing of rule actions to logger.info */
58     protected boolean traceOn = false;
59     
60     protected static Log logger = LogFactory.getLog(BasicForwardRuleInfGraph.class);
61     
62 //=======================================================================
63
// Core methods
64

65    /**
66     * Constructor. Creates a new inference graph to which a (compiled) rule set
67     * and a data graph can be attached. This separation of binding is useful to allow
68     * any configuration parameters (such as logging) to be set before the data is added.
69     * Note that until the data is added using {@link #rebind rebind} then any operations
70     * like add, remove, find will result in errors.
71     *
72     * @param reasoner the parent reasoner
73     * @param schema the (optional) schema data which is being processed
74     */

75    public BasicForwardRuleInfGraph(Reasoner reasoner, Graph schema) {
76        super(null, reasoner);
77        instantiateRuleEngine(null);
78        this.schemaGraph = schema;
79    }
80
81    /**
82     * Constructor. Creates a new inference graph based on the given rule set.
83     * No data graph is attached at this stage. This is to allow
84     * any configuration parameters (such as logging) to be set before the data is added.
85     * Note that until the data is added using {@link #rebind rebind} then any operations
86     * like add, remove, find will result in errors.
87     *
88     * @param reasoner the parent reasoner
89     * @param rules the list of rules to use this time
90     * @param schema the (optional) schema or preload data which is being processed
91     */

92    public BasicForwardRuleInfGraph(Reasoner reasoner, List rules, Graph schema) {
93        super(null, reasoner);
94        instantiateRuleEngine(rules);
95        this.rules = rules;
96        this.schemaGraph = schema;
97    }
98
99     /**
100      * Constructor. Creates a new inference graph based on the given rule set
101      * then processes the initial data graph. No precomputed deductions are loaded.
102      *
103      * @param reasoner the parent reasoner
104      * @param rules the list of rules to use this time
105      * @param schema the (optional) schema or preload data which is being processed
106      * @param data the data graph to be processed
107      */

108     public BasicForwardRuleInfGraph(Reasoner reasoner, List rules, Graph schema, Graph data) {
109         this(reasoner, rules, schema);
110         rebind(data);
111     }
112
113     /**
114      * Instantiate the forward rule engine to use.
115      * Subclasses can override this to switch to, say, a RETE imlementation.
116      * @param rules the rule set or null if there are not rules bound in yet.
117      */

118     protected void instantiateRuleEngine(List rules) {
119         if (rules != null) {
120             engine = new FRuleEngine(this, rules);
121         } else {
122             engine = new FRuleEngine(this);
123         }
124     }
125     
126     /**
127      * Attach a compiled rule set to this inference graph.
128      * @param ruleStore a compiled set of rules (i.e. the result of an FRuleEngine.compile).
129      */

130     public void setRuleStore(Object JavaDoc ruleStore) {
131         engine.setRuleStore(ruleStore);
132     }
133     
134     /**
135      * Replace the underlying data graph for this inference graph and start any
136      * inferences over again. This is primarily using in setting up ontology imports
137      * processing to allow an imports multiunion graph to be inserted between the
138      * inference graph and the raw data, before processing.
139      * @param data the new raw data graph
140      */

141     public void rebind(Graph data) {
142         fdata = new FGraph( data );
143         rebind();
144     }
145     
146     /**
147      * Cause the inference graph to reconsult the underlying graph to take
148      * into account changes. Normally changes are made through the InfGraph's add and
149      * remove calls are will be handled appropriately. However, in some cases changes
150      * are made "behind the InfGraph's back" and this forces a full reconsult of
151      * the changed data.
152      */

153     public void rebind() {
154         isPrepared = false;
155     }
156
157     /**
158      * Return the schema graph, if any, bound into this inference graph.
159      */

160     public Graph getSchemaGraph() {
161         return schemaGraph;
162     }
163         
164     /**
165      * Perform any initial processing and caching. This call is optional. Most
166      * engines either have negligable set up work or will perform an implicit
167      * "prepare" if necessary. The call is provided for those occasions where
168      * substantial preparation work is possible (e.g. running a forward chaining
169      * rule system) and where an application might wish greater control over when
170      * this prepration is done.
171      */

172     public synchronized void prepare() {
173         if (isPrepared) return;
174         isPrepared = true;
175         // initilize the deductions graph
176
fdeductions = new FGraph( new GraphMem() );
177         boolean rulesLoaded = false;
178         if (schemaGraph != null) {
179             rulesLoaded = preloadDeductions(schemaGraph);
180         }
181         if (rulesLoaded) {
182             engine.fastInit(fdata);
183         } else {
184             engine.init(true, fdata);
185         }
186     }
187
188     /**
189      * Adds a set of precomputed triples to the deductions store. These do not, themselves,
190      * fire any rules but provide additional axioms that might enable future rule
191      * firing when real data is added. Used to implement bindSchema processing
192      * in the parent Reasoner.
193      * @return return true if the rule set has also been loaded
194      */

195     protected boolean preloadDeductions(Graph preloadIn) {
196         Graph d = fdeductions.getGraph();
197         BasicForwardRuleInfGraph preload = (BasicForwardRuleInfGraph)preloadIn;
198         // If the rule set is the same we can reuse those as well
199
if (preload.rules == rules) {
200             // Load raw deductions
201
for (Iterator i = preload.find(null, null, null); i.hasNext(); ) {
202                 d.add((Triple)i.next());
203             }
204             engine.setRuleStore(preload.engine.getRuleStore());
205             return true;
206         } else {
207             return false;
208         }
209     }
210     
211     /**
212      * Add a new deduction to the deductions graph.
213      */

214     public void addDeduction(Triple t) {
215         getDeductionsGraph().add(t);
216     }
217    
218     /**
219      * Extended find interface used in situations where the implementator
220      * may or may not be able to answer the complete query. It will
221      * attempt to answer the pattern but if its answers are not known
222      * to be complete then it will also pass the request on to the nested
223      * Finder to append more results.
224      * @param pattern a TriplePattern to be matched against the data
225      * @param continuation either a Finder or a normal Graph which
226      * will be asked for additional match results if the implementor
227      * may not have completely satisfied the query.
228      */

229     public ExtendedIterator findWithContinuation(TriplePattern pattern, Finder continuation) {
230         checkOpen();
231         if (!isPrepared) prepare();
232         ExtendedIterator result = null;
233         if (fdata == null) {
234             result = fdeductions.findWithContinuation(pattern, continuation);
235         } else {
236             if (continuation == null) {
237                 result = fdata.findWithContinuation(pattern, fdeductions);
238             } else {
239                 result = fdata.findWithContinuation(pattern, FinderUtil.cascade(fdeductions, continuation) );
240             }
241         }
242         return result.filterDrop(Functor.acceptFilter);
243     }
244    
245     /**
246      * Returns an iterator over Triples.
247      * This implementation assumes that the underlying findWithContinuation
248      * will have also consulted the raw data.
249      */

250     public ExtendedIterator graphBaseFind(Node subject, Node property, Node object) {
251         return findWithContinuation(new TriplePattern(subject, property, object), null);
252     }
253
254     /**
255      * Basic pattern lookup interface.
256      * This implementation assumes that the underlying findWithContinuation
257      * will have also consulted the raw data.
258      * @param pattern a TriplePattern to be matched against the data
259      * @return a ExtendedIterator over all Triples in the data set
260      * that match the pattern
261      */

262     public ExtendedIterator find(TriplePattern pattern) {
263         return findWithContinuation(pattern, null);
264     }
265     
266
267     /**
268      * Add one triple to the data graph, run any rules triggered by
269      * the new data item, recursively adding any generated triples.
270      */

271     public synchronized void performAdd(Triple t) {
272         fdata.getGraph().add(t);
273         if (isPrepared) {
274             engine.add(t);
275         }
276     }
277
278     /**
279      * Return the number of triples in the inferred graph
280      */

281     public int graphBaseSize() {
282         checkOpen();
283         if (!isPrepared) {
284             prepare();
285         }
286         return fdata.getGraph().size() + fdeductions.getGraph().size();
287     }
288     
289     /**
290      * Removes the triple t (if possible) from the set belonging to this graph.
291      */

292     public void performDelete(Triple t) {
293         if (fdata != null) {
294             Graph data = fdata.getGraph();
295             if (data != null) {
296                 data.delete(t);
297             }
298         }
299         if (isPrepared) {
300             fdeductions.getGraph().delete(t);
301         }
302     }
303    
304     /**
305      * Free all resources, any further use of this Graph is an error.
306      */

307     public void close() {
308         if (!closed) {
309             engine = null;
310             fdeductions = null;
311             rules = null;
312             schemaGraph = null;
313             super.close();
314         }
315     }
316
317 // =======================================================================
318
// Implementation of ForwardRuleInfGraphI interface which is used by
319
// the forward rule engine to invoke functions in this InfGraph
320

321     /**
322      * Adds a new Backward rule as a rules of a forward rule process. Only some
323      * infgraphs support this.
324      */

325     public void addBRule(Rule brule) {
326         throw new ReasonerException("Forward reasoner does not support hybrid rules - " + brule.toShortString());
327     }
328         
329     /**
330      * Deletes a new Backward rule as a rules of a forward rule process. Only some
331      * infgraphs support this.
332      */

333     public void deleteBRule(Rule brule) {
334         throw new ReasonerException("Forward reasoner does not support hybrid rules - " + brule.toShortString());
335     }
336     
337     /**
338      * Return the Graph containing all the static deductions available so far.
339      */

340     public Graph getDeductionsGraph() {
341         prepare();
342         return fdeductions.getGraph();
343     }
344     
345     /**
346      * Return the Graph containing all the static deductions available so far.
347      * Does not trigger a prepare action.
348      */

349     public Graph getCurrentDeductionsGraph() {
350         return fdeductions.getGraph();
351     }
352     
353     /**
354      * Search the combination of data and deductions graphs for the given triple pattern.
355      * This may different from the normal find operation in the base of hybrid reasoners
356      * where we are side-stepping the backward deduction step.
357      */

358     public ExtendedIterator findDataMatches(Node subject, Node predicate, Node object) {
359         return find(subject, predicate, object);
360     }
361    
362
363     /**
364      * Log a dervivation record against the given triple.
365      */

366     public void logDerivation(Triple t, Object JavaDoc derivation) {
367         derivations.put(t, derivation);
368     }
369     
370     /**
371      * Assert a new triple in the deduction graph, bypassing any processing machinery.
372      */

373     public void silentAdd(Triple t) {
374         fdeductions.getGraph().add(t);
375     }
376
377 //=======================================================================
378
// support for proof traces
379

380     /**
381      * Set to true to enable derivation caching
382      */

383     public void setDerivationLogging(boolean recordDerivations) {
384         this.recordDerivations = recordDerivations;
385         engine.setDerivationLogging(recordDerivations);
386         if (recordDerivations) {
387             derivations = new OneToManyMap();
388         } else {
389             derivations = null;
390         }
391     }
392     
393     /**
394      * Return true if derivation logging is enabled.
395      */

396     public boolean shouldLogDerivations() {
397         return recordDerivations;
398     }
399     
400     /**
401      * Return the derivation of at triple.
402      * The derivation is a List of DerivationRecords
403      */

404     public Iterator getDerivation(Triple t) {
405         if (derivations == null) {
406             return new NullIterator();
407         } else {
408             return derivations.getAll(t);
409         }
410     }
411      
412     /**
413      * Set the state of the trace flag. If set to true then rule firings
414      * are logged out to the Log at "INFO" level.
415      */

416     public void setTraceOn(boolean state) {
417         traceOn = state;
418     }
419     
420     /**
421      * Return true if tracing should be acted on - i.e. if traceOn is true
422      * and we are past the bootstrap phase.
423      */

424     public boolean shouldTrace() {
425         return traceOn && engine.shouldTrace();
426     }
427     
428     /**
429      * Return the number of rules fired since this rule engine instance
430      * was created and initialized
431      */

432     public long getNRulesFired() {
433         return engine.getNRulesFired();
434     }
435             
436 }
437
438 /*
439     (c) Copyright 2003, 2004, 2005 Hewlett-Packard Development Company, LP
440     All rights reserved.
441
442     Redistribution and use in source and binary forms, with or without
443     modification, are permitted provided that the following conditions
444     are met:
445
446     1. Redistributions of source code must retain the above copyright
447        notice, this list of conditions and the following disclaimer.
448
449     2. Redistributions in binary form must reproduce the above copyright
450        notice, this list of conditions and the following disclaimer in the
451        documentation and/or other materials provided with the distribution.
452
453     3. The name of the author may not be used to endorse or promote products
454        derived from this software without specific prior written permission.
455
456     THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
457     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
458     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
459     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
460     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
461     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
462     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
463     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
464     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
465     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
466 */

467
Popular Tags