📄 lpbruleengine.java
字号:
/******************************************************************
* File: LPBRuleEngine.java
* Created by: Dave Reynolds
* Created on: 21-Jul-2003
*
* (c) Copyright 2003, 2004, 2005, 2006, 2007 Hewlett-Packard Development Company, LP
* [See end of file]
* $Id: LPBRuleEngine.java,v 1.12 2007/01/02 11:48:41 andy_seaborne Exp $
*****************************************************************/
package com.hp.hpl.jena.reasoner.rulesys.impl;
import com.hp.hpl.jena.graph.*;
import com.hp.hpl.jena.reasoner.*;
import com.hp.hpl.jena.reasoner.rulesys.*;
import com.hp.hpl.jena.util.iterator.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.util.*;
/**
* LP version of the core backward chaining engine. For each parent inference
* graph (whether pure backward or hybrid) there should be one LPBRuleEngine
* instance. The shared instance holds any common result caching, rule store
* and global state data. However, all the processing is done by instances
* of the LPInterpreter - one per query.
*
* @author <a href="mailto:der@hplb.hpl.hp.com">Dave Reynolds</a>
* @version $Revision: 1.12 $ on $Date: 2007/01/02 11:48:41 $
*/
public class LPBRuleEngine {
// =======================================================================
// variables
/** Store which holds the raw and compiled rules */
protected LPRuleStore ruleStore;
/** The parent inference graph to which this engine is attached */
protected BackwardRuleInfGraphI infGraph;
/** True if debug information should be written out */
protected boolean traceOn = false;
/** Set to true to flag that derivations should be logged */
protected boolean recordDerivations;
/** List of engine instances which are still processing queries */
protected List activeInterpreters = new ArrayList();
/** Table mapping tabled goals to generators for those goals.
* This is here so that partial goal state can be shared across multiple queries. */
protected HashMap tabledGoals = new HashMap();
/** Set of generators waiting to be run */
protected LinkedList agenda = new LinkedList();
// protected List agenda = new ArrayList();
// protected Collection agenda = new HashSet();
/** Optional profile of number of time each rule is entered, set to non-null to profile */
protected HashMap profile;
/** The number of generator cycles to wait before running a completion check.
* If set to 0 then checks will be done in the generator each time. */
public static final int CYCLES_BETWEEN_COMPLETION_CHECK = 3;
static Log logger = LogFactory.getLog(LPBRuleEngine.class);
// =======================================================================
// Constructors
/**
* Constructor.
* @param infGraph the parent inference graph which is using this engine
* @param rules the indexed set of rules to process
*/
public LPBRuleEngine(BackwardRuleInfGraphI infGraph, LPRuleStore rules) {
this.infGraph = infGraph;
ruleStore = rules;
}
/**
* Constructor. Creates an empty engine to which rules must be added.
* @param infGraph the parent inference graph which is using this engine
*/
public LPBRuleEngine(BackwardRuleInfGraphI infGraph) {
this.infGraph = infGraph;
ruleStore = new LPRuleStore();
}
// =======================================================================
// Control methods
/**
* Start a new interpreter running to answer a query.
* @param goal the query to be processed
* @return a closable iterator over the query results
*/
public synchronized ExtendedIterator find(TriplePattern goal) {
LPInterpreter interpreter = new LPInterpreter(this, goal);
activeInterpreters.add(interpreter);
return WrappedIterator.create( new LPTopGoalIterator(interpreter));
}
/**
* Clear all tabled results.
*/
public synchronized void reset() {
checkSafeToUpdate();
tabledGoals = new HashMap();
agenda.clear();
}
/**
* Add a single rule to the store.
* N.B. This will invalidate current partial results and the engine
* should be reset() before future queries.
*/
public synchronized void addRule(Rule rule) {
checkSafeToUpdate();
if (rule.headLength() > 1) {
throw new ReasonerException("Backward rules only allowed one head clause");
}
ruleStore.addRule(rule);
}
/**
* Remove a single rule from the store.
* N.B. This will invalidate current partial results and the engine
* should be reset() before future queries.
*/
public synchronized void deleteRule(Rule rule) {
checkSafeToUpdate();
ruleStore.deleteRule(rule);
}
/**
* Return an ordered list of all registered rules.
*/
public synchronized List getAllRules() {
checkSafeToUpdate();
return ruleStore.getAllRules();
}
/**
* Delete all the rules.
*/
public synchronized void deleteAllRules() {
checkSafeToUpdate();
ruleStore.deleteAllRules();
}
/**
* Stop the current work. Forcibly stop all current query instances over this engine.
*/
public synchronized void halt() {
ArrayList copy = new ArrayList(activeInterpreters);
// Copy because closing the LPInterpreter will detach it from this engine which affects activeInterpreters
for (Iterator i = copy.iterator(); i.hasNext(); ) {
((LPInterpreter)i.next()).close();
}
}
/**
* Set the state of the trace flag. If set to true then rule firings
* are logged out to the Log at "INFO" level.
*/
public void setTraceOn(boolean state) {
traceOn = state;
}
/**
* Return true if traces of rule firings should be logged.
*/
public boolean isTraceOn() {
return traceOn;
}
/**
* Set to true to enable derivation caching
*/
public void setDerivationLogging(boolean recordDerivations) {
this.recordDerivations = recordDerivations;
}
/**
* Return true in derivations should be logged.
*/
public boolean getDerivationLogging() {
return recordDerivations;
}
/** Return the rule store associated with the inference graph */
public LPRuleStore getRuleStore() {
return ruleStore;
}
/** Return the parent infernce graph associated with this engine */
public BackwardRuleInfGraphI getInfGraph() {
return infGraph;
}
/** Detatch the given engine from the list of active engines for this inf graph */
public synchronized void detach(LPInterpreter engine) {
activeInterpreters.remove(engine);
}
/**
* Check that there are no currently processing queries.
* Could throw an exception here but often this can be caused by simply leaving
* an unclosed iterator. So instead we try to close the iterators and assume the
* rest of the context will be reset by the add call.
*
* <p>Should be called from within a synchronized block.
*/
public void checkSafeToUpdate() {
if (!activeInterpreters.isEmpty()) {
ArrayList toClose = new ArrayList();
for (Iterator i = activeInterpreters.iterator(); i.hasNext(); ) {
LPInterpreter interpreter = (LPInterpreter)i.next();
if (interpreter.getContext() instanceof LPTopGoalIterator) {
toClose.add(interpreter.getContext());
}
}
for (Iterator i = toClose.iterator(); i.hasNext(); ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -