some refactoring of SimpleReasoner

This commit is contained in:
stellamit 2012-06-16 23:41:13 +00:00
parent f327e91a3c
commit 491c4f6d9a
4 changed files with 516 additions and 404 deletions

View file

@ -0,0 +1,443 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.reasoner;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.ontology.OntProperty;
import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QueryFactory;
import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.query.Syntax;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.ResourceFactory;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.rdf.model.StmtIterator;
import com.hp.hpl.jena.shared.JenaException;
import com.hp.hpl.jena.shared.Lock;
import com.hp.hpl.jena.vocabulary.OWL;
import com.hp.hpl.jena.vocabulary.RDF;
public class ABoxRecomputer {
private static final Log log = LogFactory.getLog(ABoxRecomputer.class);
private OntModel tboxModel; // asserted and inferred TBox axioms
private OntModel aboxModel; // ABox assertions
private Model inferenceModel; // ABox inferences
private Model inferenceRebuildModel; // work area for recomputing all ABox inferences
private Model scratchpadModel; // work area for recomputing all ABox inferences
private SimpleReasoner simpleReasoner;
private Object lock1 = new Object();
private volatile boolean recomputing = false;
private boolean stopRequested = false;
/**
* @param tboxModel - input. This model contains both asserted and inferred TBox axioms
* @param aboxModel - input. This model contains asserted ABox statements
* @param inferenceModel - output. This is the model in which inferred (materialized) ABox statements are maintained (added or retracted).
* @param inferenceRebuildModel - output. This the model is temporarily used when the whole ABox inference model is rebuilt
* @param inferenceScratchpadModel - output. This the model is temporarily used when the whole ABox inference model is rebuilt
*/
public ABoxRecomputer(OntModel tboxModel,
OntModel aboxModel,
Model inferenceModel,
Model inferenceRebuildModel,
Model scratchpadModel,
SimpleReasoner simpleReasoner) {
this.tboxModel = tboxModel;
this.aboxModel = aboxModel;
this.inferenceModel = inferenceModel;
this.inferenceRebuildModel = inferenceRebuildModel;
this.scratchpadModel = scratchpadModel;
this.simpleReasoner = simpleReasoner;
recomputing = false;
stopRequested = false;
}
/**
* Returns true if the recomputer is in the process of recomputing
* all inferences.
*/
public boolean isRecomputing() {
return recomputing;
}
/**
* Recompute all inferences.
*/
public void recompute() {
synchronized (lock1) {
if (recomputing) {
return;
} else {
recomputing = true;
}
}
try {
recomputeABox();
} finally {
synchronized (lock1) {
recomputing = false;
}
}
}
/*
* Recompute the entire ABox inference graph. The new
* inference graph is built in a separate model and
* then reconciled with the inference graph in active
* use. The model reconciliation must be done
* without reading the whole inference models into
* memory in order to support very large ABox
* inference models.
*/
protected void recomputeABox() {
// recompute class subsumption inferences
inferenceRebuildModel.enterCriticalSection(Lock.WRITE);
try {
HashSet<String> unknownTypes = new HashSet<String>();
inferenceRebuildModel.removeAll();
log.info("Computing class subsumption ABox inferences.");
int numStmts = 0;
ArrayList<String> individuals = this.getAllIndividualURIs();
for (String individualURI : individuals) {
Resource individual = ResourceFactory.createResource(individualURI);
try {
addedABoxTypeAssertion(individual, inferenceRebuildModel, unknownTypes);
simpleReasoner.setMostSpecificTypes(individual, inferenceRebuildModel, unknownTypes);
StmtIterator sit = aboxModel.listStatements(individual, null, (RDFNode) null);
while (sit.hasNext()) {
Statement s = sit.nextStatement();
for (ReasonerPlugin plugin : simpleReasoner.getPluginList()) {
plugin.addedABoxStatement(s, aboxModel, inferenceRebuildModel, tboxModel);
}
}
} catch (NullPointerException npe) {
log.error("a NullPointerException was received while recomputing the ABox inferences. Halting inference computation.");
npe.printStackTrace();
return;
} catch (JenaException je) {
if (je.getMessage().equals("Statement models must no be null")) {
log.error("Exception while recomputing ABox inference model. Halting inference computation.", je);
return;
}
log.error("Exception while recomputing ABox inference model: ", je);
} catch (Exception e) {
log.error("Exception while recomputing ABox inference model: ", e);
}
numStmts++;
if ((numStmts % 10000) == 0) {
log.info("Still computing class subsumption ABox inferences...");
}
if (stopRequested) {
log.info("a stopRequested signal was received during recomputeABox. Halting Processing.");
return;
}
}
log.info("Finished computing class subsumption ABox inferences");
log.info("Computing inverse property ABox inferences");
Iterator<Statement> invStatements = null;
tboxModel.enterCriticalSection(Lock.READ);
try {
invStatements = tboxModel.listStatements((Resource) null, OWL.inverseOf, (Resource) null);
} finally {
tboxModel.leaveCriticalSection();
}
numStmts = 0;
while (invStatements.hasNext()) {
Statement stmt = invStatements.next();
try {
OntProperty prop1 = tboxModel.getOntProperty((stmt.getSubject()).getURI());
if (prop1 == null) {
//TODO make sure not to print out a million of these for the same property
log.debug("didn't find subject property in the tbox: " + (stmt.getSubject()).getURI());
continue;
}
OntProperty prop2 = tboxModel.getOntProperty(((Resource)stmt.getObject()).getURI());
if (prop2 == null) {
//TODO make sure not to print out a million of these for the same property
log.debug("didn't find object property in the tbox: " + ((Resource)stmt.getObject()).getURI());
continue;
}
simpleReasoner.addedInverseProperty(prop1, prop2, inferenceRebuildModel);
} catch (NullPointerException npe) {
log.error("a NullPointerException was received while recomputing the ABox inferences. Halting inference computation.");
npe.printStackTrace();
return;
} catch (JenaException je) {
if (je.getMessage().equals("Statement models must no be null")) {
log.error("Exception while recomputing ABox inference model. Halting inference computation.", je);
return;
}
log.error("Exception while recomputing ABox inference model: ", je);
} catch (Exception e) {
log.error("Exception while recomputing ABox inference model: ", e);
}
numStmts++;
if ((numStmts % 10000) == 0) {
log.info("Still computing inverse property ABox inferences...");
}
if (stopRequested) {
log.info("a stopRequested signal was received during recomputeABox. Halting Processing.");
return;
}
}
log.info("Finished computing inverse property ABox inferences");
log.info("Computing sameAs ABox inferences");
Iterator<Statement> sameAsStatements = null;
aboxModel.enterCriticalSection(Lock.READ);
try {
sameAsStatements = aboxModel.listStatements((Resource) null, OWL.sameAs, (Resource) null);
} finally {
aboxModel.leaveCriticalSection();
}
numStmts = 0;
while (sameAsStatements.hasNext()) {
Statement stmt = sameAsStatements.next();
try {
simpleReasoner.addedABoxSameAsAssertion(stmt, inferenceRebuildModel);
} catch (NullPointerException npe) {
log.error("a NullPointerException was received while recomputing the ABox inferences. Halting inference computation.");
npe.printStackTrace();
return;
} catch (JenaException je) {
if (je.getMessage().equals("Statement models must no be null")) {
log.error("Exception while recomputing ABox inference model. Halting inference computation.", je);
return;
}
log.error("Exception while recomputing ABox inference model: ", je);
} catch (Exception e) {
log.error("Exception while recomputing ABox inference model: ", e);
}
numStmts++;
if ((numStmts % 10000) == 0) {
log.info("Still computing sameAs ABox inferences...");
}
if (stopRequested) {
log.info("a stopRequested signal was received during recomputeABox. Halting Processing.");
return;
}
}
log.info("Finished computing sameAs ABox inferences");
try {
if (updateInferenceModel(inferenceRebuildModel)) {
log.info("a stopRequested signal was received during updateInferenceModel. Halting Processing.");
return;
}
} catch (Exception e) {
log.error("Exception while reconciling the current and recomputed ABox inference model for class subsumption inferences. Halting processing." , e);
}
} catch (Exception e) {
log.error("Exception while recomputing ABox inferences. Halting processing.", e);
} finally {
inferenceRebuildModel.removeAll();
inferenceRebuildModel.leaveCriticalSection();
}
}
/*
* Get the URIs for all individuals in the system
*/
protected ArrayList<String> getAllIndividualURIs() {
String queryString = "select distinct ?subject where {?subject <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> ?type}";
return getIndividualURIs(queryString);
}
protected ArrayList<String> getIndividualURIs(String queryString) {
ArrayList<String> individuals = new ArrayList<String>();
aboxModel.enterCriticalSection(Lock.READ);
try {
try {
Query query = QueryFactory.create(queryString, Syntax.syntaxARQ);
QueryExecution qe = QueryExecutionFactory.create(query, aboxModel);
ResultSet results = qe.execSelect();
while (results.hasNext()) {
QuerySolution solution = results.next();
Resource resource = solution.getResource("subject");
if ((resource != null) && !resource.isAnon()) {
individuals.add(resource.getURI());
}
}
} catch (Exception e) {
log.error("exception while retrieving list of individuals ",e);
}
} finally {
aboxModel.leaveCriticalSection();
}
return individuals;
}
protected void addedABoxTypeAssertion(Resource individual, Model inferenceModel, HashSet<String> unknownTypes) {
StmtIterator iter = null;
aboxModel.enterCriticalSection(Lock.READ);
try {
iter = aboxModel.listStatements(individual, RDF.type, (RDFNode) null);
while (iter.hasNext()) {
Statement stmt = iter.next();
simpleReasoner.addedABoxTypeAssertion(stmt, inferenceModel, unknownTypes);
}
} finally {
iter.close();
aboxModel.leaveCriticalSection();
}
}
/*
* reconcile a set of inferences into the application inference model
*/
protected boolean updateInferenceModel(Model inferenceRebuildModel) {
log.info("Updating ABox inference model");
StmtIterator iter = null;
// Remove everything from the current inference model that is not
// in the recomputed inference model
int num = 0;
scratchpadModel.enterCriticalSection(Lock.WRITE);
scratchpadModel.removeAll();
try {
inferenceModel.enterCriticalSection(Lock.READ);
try {
iter = inferenceModel.listStatements();
while (iter.hasNext()) {
Statement stmt = iter.next();
if (!inferenceRebuildModel.contains(stmt)) {
scratchpadModel.add(stmt);
}
num++;
if ((num % 10000) == 0) {
log.info("Still updating ABox inference model (removing outdated inferences)...");
}
if (stopRequested) {
return true;
}
}
} finally {
iter.close();
inferenceModel.leaveCriticalSection();
}
try {
iter = scratchpadModel.listStatements();
while (iter.hasNext()) {
Statement stmt = iter.next();
inferenceModel.enterCriticalSection(Lock.WRITE);
try {
inferenceModel.remove(stmt);
} finally {
inferenceModel.leaveCriticalSection();
}
}
} finally {
iter.close();
}
// Add everything from the recomputed inference model that is not already
// in the current inference model to the current inference model.
try {
scratchpadModel.removeAll();
iter = inferenceRebuildModel.listStatements();
while (iter.hasNext()) {
Statement stmt = iter.next();
inferenceModel.enterCriticalSection(Lock.READ);
try {
if (!inferenceModel.contains(stmt)) {
scratchpadModel.add(stmt);
}
} finally {
inferenceModel.leaveCriticalSection();
}
num++;
if ((num % 10000) == 0) {
log.info("Still updating ABox inference model (adding new inferences)...");
}
if (stopRequested) {
return true;
}
}
} finally {
iter.close();
}
iter = scratchpadModel.listStatements();
while (iter.hasNext()) {
Statement stmt = iter.next();
inferenceModel.enterCriticalSection(Lock.WRITE);
try {
inferenceModel.add(stmt);
} finally {
inferenceModel.leaveCriticalSection();
}
}
} finally {
iter.close();
scratchpadModel.removeAll();
scratchpadModel.leaveCriticalSection();
}
log.info("ABox inference model updated");
return false;
}
/**
* This is called when the application shuts down.
*/
public void setStopRequested() {
this.stopRequested = true;
}
}

View file

@ -16,13 +16,6 @@ import com.hp.hpl.jena.ontology.OntClass;
import com.hp.hpl.jena.ontology.OntModel; import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.ontology.OntModelSpec; import com.hp.hpl.jena.ontology.OntModelSpec;
import com.hp.hpl.jena.ontology.OntProperty; import com.hp.hpl.jena.ontology.OntProperty;
import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QueryFactory;
import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.query.Syntax;
import com.hp.hpl.jena.rdf.listeners.StatementListener; import com.hp.hpl.jena.rdf.listeners.StatementListener;
import com.hp.hpl.jena.rdf.model.Literal; import com.hp.hpl.jena.rdf.model.Literal;
import com.hp.hpl.jena.rdf.model.Model; import com.hp.hpl.jena.rdf.model.Model;
@ -33,7 +26,6 @@ import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.ResourceFactory; import com.hp.hpl.jena.rdf.model.ResourceFactory;
import com.hp.hpl.jena.rdf.model.Statement; import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.rdf.model.StmtIterator; import com.hp.hpl.jena.rdf.model.StmtIterator;
import com.hp.hpl.jena.shared.JenaException;
import com.hp.hpl.jena.shared.Lock; import com.hp.hpl.jena.shared.Lock;
import com.hp.hpl.jena.util.iterator.ExtendedIterator; import com.hp.hpl.jena.util.iterator.ExtendedIterator;
import com.hp.hpl.jena.vocabulary.OWL; import com.hp.hpl.jena.vocabulary.OWL;
@ -62,17 +54,18 @@ public class SimpleReasoner extends StatementListener {
private OntModel tboxModel; // asserted and inferred TBox axioms private OntModel tboxModel; // asserted and inferred TBox axioms
private OntModel aboxModel; // ABox assertions private OntModel aboxModel; // ABox assertions
private Model inferenceModel; // ABox inferences private Model inferenceModel; // ABox inferences
private Model inferenceRebuildModel; // work area for re-computing all ABox inferences
private Model scratchpadModel; // work area for re-computing all ABox inferences
private static final String mostSpecificTypePropertyURI = "http://vitro.mannlib.cornell.edu/ns/vitro/0.7#mostSpecificType"; private static final String mostSpecificTypePropertyURI = "http://vitro.mannlib.cornell.edu/ns/vitro/0.7#mostSpecificType";
private static final AnnotationProperty mostSpecificType = (ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM)).createAnnotationProperty(mostSpecificTypePropertyURI); private static final AnnotationProperty mostSpecificType = (ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM)).createAnnotationProperty(mostSpecificTypePropertyURI);
//TODO check this for thread safety // DeltaComputer
private CumulativeDeltaModeler aBoxDeltaModeler1 = null; private CumulativeDeltaModeler aBoxDeltaModeler1 = null;
private CumulativeDeltaModeler aBoxDeltaModeler2 = null; private CumulativeDeltaModeler aBoxDeltaModeler2 = null;
private volatile boolean batchMode1 = false; private int batchMode = 0; // values: 0, 1 and 2
private volatile boolean batchMode2 = false;
// Recomputer
private ABoxRecomputer recomputer = null;
private boolean stopRequested = false; private boolean stopRequested = false;
private List<ReasonerPlugin> pluginList = new CopyOnWriteArrayList<ReasonerPlugin>(); private List<ReasonerPlugin> pluginList = new CopyOnWriteArrayList<ReasonerPlugin>();
@ -84,20 +77,24 @@ public class SimpleReasoner extends StatementListener {
* @param inferenceRebuildModel - output. This the model is temporarily used when the whole ABox inference model is rebuilt * @param inferenceRebuildModel - output. This the model is temporarily used when the whole ABox inference model is rebuilt
* @param inferenceScratchpadModel - output. This the model is temporarily used when the whole ABox inference model is rebuilt * @param inferenceScratchpadModel - output. This the model is temporarily used when the whole ABox inference model is rebuilt
*/ */
public SimpleReasoner(OntModel tboxModel, RDFService rdfService, Model inferenceModel, public SimpleReasoner(OntModel tboxModel,
Model inferenceRebuildModel, Model scratchpadModel) { RDFService rdfService,
Model inferenceModel,
Model inferenceRebuildModel,
Model scratchpadModel) {
this.tboxModel = tboxModel; this.tboxModel = tboxModel;
this.aboxModel = ModelFactory.createOntologyModel( this.aboxModel = ModelFactory.createOntologyModel(
OntModelSpec.OWL_MEM, ModelFactory.createModelForGraph( OntModelSpec.OWL_MEM, ModelFactory.createModelForGraph(
new DifferenceGraph(new RDFServiceGraph(rdfService), inferenceModel.getGraph()))); new DifferenceGraph(new DifferenceGraph(new RDFServiceGraph(rdfService),inferenceModel.getGraph()),
tboxModel.getGraph())));
this.inferenceModel = inferenceModel; this.inferenceModel = inferenceModel;
this.inferenceRebuildModel = inferenceRebuildModel; this.batchMode = 0;
this.scratchpadModel = scratchpadModel;
this.batchMode1 = false;
this.batchMode2 = false;
aBoxDeltaModeler1 = new CumulativeDeltaModeler(); aBoxDeltaModeler1 = new CumulativeDeltaModeler();
aBoxDeltaModeler2 = new CumulativeDeltaModeler(); aBoxDeltaModeler2 = new CumulativeDeltaModeler();
recomputer = new ABoxRecomputer(tboxModel,this.aboxModel,inferenceModel,inferenceRebuildModel,scratchpadModel,this);
stopRequested = false; stopRequested = false;
if (rdfService == null) { if (rdfService == null) {
@ -122,13 +119,11 @@ public class SimpleReasoner extends StatementListener {
this.tboxModel = tboxModel; this.tboxModel = tboxModel;
this.aboxModel = aboxModel; this.aboxModel = aboxModel;
this.inferenceModel = inferenceModel; this.inferenceModel = inferenceModel;
this.inferenceRebuildModel = ModelFactory.createDefaultModel();
this.scratchpadModel = ModelFactory.createDefaultModel();
aBoxDeltaModeler1 = new CumulativeDeltaModeler(); aBoxDeltaModeler1 = new CumulativeDeltaModeler();
aBoxDeltaModeler2 = new CumulativeDeltaModeler(); aBoxDeltaModeler2 = new CumulativeDeltaModeler();
this.batchMode1 = false; this.batchMode = 0;
this.batchMode2 = false;
stopRequested = false; stopRequested = false;
recomputer = new ABoxRecomputer(tboxModel,this.aboxModel,inferenceModel,ModelFactory.createDefaultModel(),ModelFactory.createDefaultModel(),this);
} }
public void setPluginList(List<ReasonerPlugin> pluginList) { public void setPluginList(List<ReasonerPlugin> pluginList) {
@ -160,8 +155,7 @@ public class SimpleReasoner extends StatementListener {
} catch (Exception e) { } catch (Exception e) {
// don't stop the edit if there's an exception // don't stop the edit if there's an exception
log.error("Exception while computing inferences: " + e.getMessage()); log.error("Exception while computing inferences: ",e);
e.printStackTrace(); //TODO remove this for release
} }
} }
@ -174,9 +168,6 @@ public class SimpleReasoner extends StatementListener {
public void removedStatement(Statement stmt) { public void removedStatement(Statement stmt) {
try { try {
// if (!isInterestedInRemovedStatement(stmt)) { return; }
// interested in all of them now that we are doing inverse
// property reasoning
handleRemovedStatement(stmt); handleRemovedStatement(stmt);
} catch (Exception e) { } catch (Exception e) {
@ -191,11 +182,11 @@ public class SimpleReasoner extends StatementListener {
* with DeltaComputer. * with DeltaComputer.
*/ */
protected synchronized void handleRemovedStatement(Statement stmt) { protected synchronized void handleRemovedStatement(Statement stmt) {
if (batchMode1) { if (batchMode == 1) {
aBoxDeltaModeler1.removedStatement(stmt); aBoxDeltaModeler1.removedStatement(stmt);
} else if (batchMode2) { } else if (batchMode == 2) {
aBoxDeltaModeler2.removedStatement(stmt); aBoxDeltaModeler2.removedStatement(stmt);
} else { } else { // batchMode == 0
if (stmt.getPredicate().equals(RDF.type)) { if (stmt.getPredicate().equals(RDF.type)) {
removedABoxTypeAssertion(stmt, inferenceModel); removedABoxTypeAssertion(stmt, inferenceModel);
setMostSpecificTypes(stmt.getSubject(), inferenceModel, new HashSet<String>()); setMostSpecificTypes(stmt.getSubject(), inferenceModel, new HashSet<String>());
@ -348,27 +339,6 @@ public class SimpleReasoner extends StatementListener {
log.error("Exception while removing inference(s): " + e.getMessage()); log.error("Exception while removing inference(s): " + e.getMessage());
} }
} }
/*
* This signature used when recomputing the whole ABox
*/
protected void addedABoxTypeAssertion(Resource individual, Model inferenceModel, HashSet<String> unknownTypes) {
StmtIterator iter = null;
aboxModel.enterCriticalSection(Lock.READ);
try {
iter = aboxModel.listStatements(individual, RDF.type, (RDFNode) null);
while (iter.hasNext()) {
Statement stmt = iter.next();
addedABoxTypeAssertion(stmt, inferenceModel, unknownTypes);
}
} finally {
iter.close();
aboxModel.leaveCriticalSection();
}
}
/* /*
* Performs incremental reasoning based on a new type assertion * Performs incremental reasoning based on a new type assertion
@ -942,8 +912,7 @@ public class SimpleReasoner extends StatementListener {
// Returns true if the triple is entailed by inverse property // Returns true if the triple is entailed by inverse property
// reasoning or sameAs reasoning; otherwise returns false. // reasoning or sameAs reasoning; otherwise returns false.
protected boolean entailedStatement(Statement stmt) { protected boolean entailedStatement(Statement stmt) {
//TODO think about checking class subsumption here (for convenience)
//TODO think about checking class subsumption here
// Inverse properties // Inverse properties
List<OntProperty> inverses = getInverseProperties(stmt); List<OntProperty> inverses = getInverseProperties(stmt);
@ -1324,345 +1293,29 @@ public class SimpleReasoner extends StatementListener {
* Returns true if the reasoner is in the process of recomputing all * Returns true if the reasoner is in the process of recomputing all
* inferences. * inferences.
*/ */
private boolean recomputing = false;
public boolean isRecomputing() { public boolean isRecomputing() {
return recomputing; if (recomputer == null) {
} return false;
/**
* Recompute all inferences.
*/
public synchronized void recompute() {
recomputing = true;
try {
recomputeABox();
} finally {
recomputing = false;
}
}
/*
* Recompute the entire ABox inference graph. The new
* inference graph is built in a separate model and
* then reconciled with the inference graph in active
* use. The model reconciliation must be done
* without reading the whole inference models into
* memory in order to support very large ABox
* inference models.
*/
protected synchronized void recomputeABox() {
// recompute class subsumption inferences
inferenceRebuildModel.enterCriticalSection(Lock.WRITE);
try {
HashSet<String> unknownTypes = new HashSet<String>();
inferenceRebuildModel.removeAll();
log.info("Computing class subsumption ABox inferences.");
int numStmts = 0;
ArrayList<String> individuals = this.getAllIndividualURIs();
for (String individualURI : individuals) {
Resource individual = ResourceFactory.createResource(individualURI);
try {
addedABoxTypeAssertion(individual, inferenceRebuildModel, unknownTypes);
setMostSpecificTypes(individual, inferenceRebuildModel, unknownTypes);
StmtIterator sit = aboxModel.listStatements(individual, null, (RDFNode) null);
while (sit.hasNext()) {
Statement s = sit.nextStatement();
for (ReasonerPlugin plugin : getPluginList()) {
plugin.addedABoxStatement(s, aboxModel, inferenceRebuildModel, tboxModel);
}
}
} catch (NullPointerException npe) {
log.error("a NullPointerException was received while recomputing the ABox inferences. Halting inference computation.");
return;
} catch (JenaException je) {
if (je.getMessage().equals("Statement models must no be null")) {
log.error("Exception while recomputing ABox inference model. Halting inference computation.", je);
return;
}
log.error("Exception while recomputing ABox inference model: ", je);
} catch (Exception e) {
log.error("Exception while recomputing ABox inference model: ", e);
}
numStmts++;
if ((numStmts % 10000) == 0) {
log.info("Still computing class subsumption ABox inferences...");
}
if (stopRequested) {
log.info("a stopRequested signal was received during recomputeABox. Halting Processing.");
return;
}
}
log.info("Finished computing class subsumption ABox inferences");
log.info("Computing inverse property ABox inferences");
Iterator<Statement> invStatements = null;
tboxModel.enterCriticalSection(Lock.READ);
try {
invStatements = tboxModel.listStatements((Resource) null, OWL.inverseOf, (Resource) null);
} finally {
tboxModel.leaveCriticalSection();
}
numStmts = 0;
while (invStatements.hasNext()) {
Statement stmt = invStatements.next();
try {
OntProperty prop1 = tboxModel.getOntProperty((stmt.getSubject()).getURI());
if (prop1 == null) {
//TODO make sure not to print out a million of these for the same property
log.debug("didn't find subject property in the tbox: " + (stmt.getSubject()).getURI());
continue;
}
OntProperty prop2 = tboxModel.getOntProperty(((Resource)stmt.getObject()).getURI());
if (prop2 == null) {
//TODO make sure not to print out a million of these for the same property
log.debug("didn't find object property in the tbox: " + ((Resource)stmt.getObject()).getURI());
continue;
}
addedInverseProperty(prop1, prop2, inferenceRebuildModel);
} catch (NullPointerException npe) {
log.error("a NullPointerException was received while recomputing the ABox inferences. Halting inference computation.");
return;
} catch (JenaException je) {
if (je.getMessage().equals("Statement models must no be null")) {
log.error("Exception while recomputing ABox inference model. Halting inference computation.", je);
return;
}
log.error("Exception while recomputing ABox inference model: ", je);
} catch (Exception e) {
log.error("Exception while recomputing ABox inference model: ", e);
}
numStmts++;
if ((numStmts % 10000) == 0) {
log.info("Still computing inverse property ABox inferences...");
}
if (stopRequested) {
log.info("a stopRequested signal was received during recomputeABox. Halting Processing.");
return;
}
}
log.info("Finished computing inverse property ABox inferences");
log.info("Computing sameAs ABox inferences");
Iterator<Statement> sameAsStatements = null;
aboxModel.enterCriticalSection(Lock.READ);
try {
sameAsStatements = aboxModel.listStatements((Resource) null, OWL.sameAs, (Resource) null);
} finally {
aboxModel.leaveCriticalSection();
}
numStmts = 0;
while (sameAsStatements.hasNext()) {
Statement stmt = sameAsStatements.next();
try {
addedABoxSameAsAssertion(stmt, inferenceRebuildModel);
} catch (NullPointerException npe) {
log.error("a NullPointerException was received while recomputing the ABox inferences. Halting inference computation.");
return;
} catch (JenaException je) {
if (je.getMessage().equals("Statement models must no be null")) {
log.error("Exception while recomputing ABox inference model. Halting inference computation.", je);
return;
}
log.error("Exception while recomputing ABox inference model: ", je);
} catch (Exception e) {
log.error("Exception while recomputing ABox inference model: ", e);
}
numStmts++;
if ((numStmts % 10000) == 0) {
log.info("Still computing sameAs ABox inferences...");
}
if (stopRequested) {
log.info("a stopRequested signal was received during recomputeABox. Halting Processing.");
return;
}
}
log.info("Finished computing sameAs ABox inferences");
try {
if (updateInferenceModel(inferenceRebuildModel)) {
log.info("a stopRequested signal was received during updateInferenceModel. Halting Processing.");
return;
}
} catch (Exception e) {
log.error("Exception while reconciling the current and recomputed ABox inference model for class subsumption inferences. Halting processing." , e);
}
} catch (Exception e) {
log.error("Exception while recomputing ABox inferences. Halting processing.", e);
} finally {
inferenceRebuildModel.removeAll();
inferenceRebuildModel.leaveCriticalSection();
}
}
/*
* Get the URIs for all individuals in the system
*/
protected ArrayList<String> getAllIndividualURIs() {
String queryString = "select distinct ?subject where {?subject <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> ?type}";
return getIndividualURIs(queryString);
}
protected ArrayList<String> getIndividualURIs(String queryString) {
ArrayList<String> individuals = new ArrayList<String>();
aboxModel.enterCriticalSection(Lock.READ);
try {
try {
Query query = QueryFactory.create(queryString, Syntax.syntaxARQ);
QueryExecution qe = QueryExecutionFactory.create(query, aboxModel);
ResultSet results = qe.execSelect();
while (results.hasNext()) {
QuerySolution solution = results.next();
Resource resource = solution.getResource("subject");
if ((resource != null) && !resource.isAnon()) {
individuals.add(resource.getURI());
}
}
} catch (Exception e) {
log.error("exception while retrieving list of individuals ",e);
}
} finally {
aboxModel.leaveCriticalSection();
} }
return individuals; return recomputer.isRecomputing();
}
/*
* reconcile a set of inferences into the application inference model
*/
protected boolean updateInferenceModel(Model inferenceRebuildModel) {
log.info("Updating ABox inference model");
StmtIterator iter = null;
// Remove everything from the current inference model that is not
// in the recomputed inference model
int num = 0;
scratchpadModel.enterCriticalSection(Lock.WRITE);
scratchpadModel.removeAll();
try {
inferenceModel.enterCriticalSection(Lock.READ);
try {
iter = inferenceModel.listStatements();
while (iter.hasNext()) {
Statement stmt = iter.next();
if (!inferenceRebuildModel.contains(stmt)) {
scratchpadModel.add(stmt);
}
num++;
if ((num % 10000) == 0) {
log.info("Still updating ABox inference model (removing outdated inferences)...");
}
if (stopRequested) {
return true;
}
}
} finally {
iter.close();
inferenceModel.leaveCriticalSection();
}
try {
iter = scratchpadModel.listStatements();
while (iter.hasNext()) {
Statement stmt = iter.next();
inferenceModel.enterCriticalSection(Lock.WRITE);
try {
inferenceModel.remove(stmt);
} finally {
inferenceModel.leaveCriticalSection();
}
}
} finally {
iter.close();
}
// Add everything from the recomputed inference model that is not already
// in the current inference model to the current inference model.
try {
scratchpadModel.removeAll();
iter = inferenceRebuildModel.listStatements();
while (iter.hasNext()) {
Statement stmt = iter.next();
inferenceModel.enterCriticalSection(Lock.READ);
try {
if (!inferenceModel.contains(stmt)) {
scratchpadModel.add(stmt);
}
} finally {
inferenceModel.leaveCriticalSection();
}
num++;
if ((num % 10000) == 0) {
log.info("Still updating ABox inference model (adding new inferences)...");
}
if (stopRequested) {
return true;
}
}
} finally {
iter.close();
}
iter = scratchpadModel.listStatements();
while (iter.hasNext()) {
Statement stmt = iter.next();
inferenceModel.enterCriticalSection(Lock.WRITE);
try {
inferenceModel.add(stmt);
} finally {
inferenceModel.leaveCriticalSection();
}
}
} finally {
iter.close();
scratchpadModel.removeAll();
scratchpadModel.leaveCriticalSection();
} }
log.info("ABox inference model updated"); public void recompute() {
return false; if (recomputer != null) {
recomputer.recompute();
}
} }
/** /**
* This is called when the application shuts down. * This is called when the application shuts down.
*/ */
public void setStopRequested() { public void setStopRequested() {
if (recomputer != null) {
recomputer.setStopRequested();
}
this.stopRequested = true; this.stopRequested = true;
} }
@ -1681,7 +1334,7 @@ public class SimpleReasoner extends StatementListener {
* Asynchronous reasoning mode (DeltaComputer) is used in the case of batch removals. * Asynchronous reasoning mode (DeltaComputer) is used in the case of batch removals.
*/ */
public boolean isABoxReasoningAsynchronous() { public boolean isABoxReasoningAsynchronous() {
if (batchMode1 || batchMode2) { if (batchMode > 0) {
return true; return true;
} else { } else {
return false; return false;
@ -1710,9 +1363,7 @@ public class SimpleReasoner extends StatementListener {
log.info("received a bulk update begin event while processing in asynchronous mode. Event count = " + eventCount); log.info("received a bulk update begin event while processing in asynchronous mode. Event count = " + eventCount);
return; return;
} else { } else {
batchMode1 = true; batchMode = 1;
batchMode2 = false;
if (aBoxDeltaModeler1.getRetractions().size() > 0) { if (aBoxDeltaModeler1.getRetractions().size() > 0) {
log.warn("Unexpected condition: the aBoxDeltaModeler1 retractions model was not empty when entering batch mode."); log.warn("Unexpected condition: the aBoxDeltaModeler1 retractions model was not empty when entering batch mode.");
} }
@ -1738,34 +1389,32 @@ public class SimpleReasoner extends StatementListener {
private synchronized boolean switchBatchModes() { private synchronized boolean switchBatchModes() {
if (batchMode1) { if (batchMode == 1) {
aBoxDeltaModeler2.getRetractions().removeAll(); aBoxDeltaModeler2.getRetractions().removeAll();
if (aBoxDeltaModeler1.getRetractions().size() > 0) { if (aBoxDeltaModeler1.getRetractions().size() > 0) {
batchMode2 = true; batchMode = 2;
batchMode1 = false; log.info("entering batch mode " + batchMode);
log.info("entering batch mode 2");
} else { } else {
deltaComputerProcessing = false; deltaComputerProcessing = false;
if (eventCount == 0) { if (eventCount == 0) {
batchMode1 = false; batchMode = 0;
} }
} }
} else if (batchMode2) { } else if (batchMode == 2) {
aBoxDeltaModeler1.getRetractions().removeAll(); aBoxDeltaModeler1.getRetractions().removeAll();
if (aBoxDeltaModeler2.getRetractions().size() > 0) { if (aBoxDeltaModeler2.getRetractions().size() > 0) {
batchMode1 = true; batchMode = 1;
batchMode2 = false; log.info("entering batch mode " + batchMode);
log.info("entering batch mode 1");
} else { } else {
deltaComputerProcessing = false; deltaComputerProcessing = false;
if (eventCount == 0) { if (eventCount == 0) {
batchMode2 = false; batchMode = 0;
} }
} }
} else { } else {
log.warn("unexpected condition, invoked when batchMode1 and batchMode2 are both false"); log.warn("unexpected condition, invoked when batchMode is neither 1 nor 2. batchMode = " + batchMode);
deltaComputerProcessing = false; deltaComputerProcessing = false;
} }
@ -1786,10 +1435,10 @@ public class SimpleReasoner extends StatementListener {
while (deltaComputerProcessing && !stopRequested) { while (deltaComputerProcessing && !stopRequested) {
if (switchBatchModes()) { if (switchBatchModes()) {
if (batchMode1) { if (batchMode == 1) {
qualifier = "2"; qualifier = "2";
retractions = aBoxDeltaModeler2.getRetractions(); retractions = aBoxDeltaModeler2.getRetractions();
} else if (batchMode2) { } else if (batchMode == 2) {
qualifier = "1"; qualifier = "1";
retractions = aBoxDeltaModeler1.getRetractions(); retractions = aBoxDeltaModeler1.getRetractions();
} }
@ -1853,7 +1502,7 @@ public class SimpleReasoner extends StatementListener {
log.debug("\t--> processed " + num + " statements"); log.debug("\t--> processed " + num + " statements");
} }
log.info("ending DeltaComputer.run. batchMode1 = " + batchMode1 + ", batchMode2 = " + batchMode2); log.info("ending DeltaComputer.run. batchMode = " + batchMode);
} }
} }
} }

View file

@ -28,6 +28,7 @@ public class SimpleReasonerInversePropertyTest extends AbstractTestClass {
//Turn off log messages to console //Turn off log messages to console
setLoggerLevel(SimpleReasoner.class, Level.OFF); setLoggerLevel(SimpleReasoner.class, Level.OFF);
setLoggerLevel(SimpleReasonerTBoxListener.class, Level.OFF); setLoggerLevel(SimpleReasonerTBoxListener.class, Level.OFF);
setLoggerLevel(ABoxRecomputer.class, Level.OFF);
} }
/* /*
@ -447,6 +448,12 @@ public class SimpleReasonerInversePropertyTest extends AbstractTestClass {
aBox.add(a,P,b); aBox.add(a,P,b);
aBox.add(c,X,d); aBox.add(c,X,d);
Assert.assertTrue(inf.contains(b,Q,a));
Assert.assertTrue(inf.contains(d,Y,c));
inf.remove(b,Q,a);
inf.remove(d,Y,c);
//recompute whole abox //recompute whole abox
simpleReasoner.recompute(); simpleReasoner.recompute();

View file

@ -35,6 +35,7 @@ public class SimpleReasonerSameAsTest extends AbstractTestClass {
//Turn off log messages to console //Turn off log messages to console
setLoggerLevel(SimpleReasoner.class, Level.OFF); setLoggerLevel(SimpleReasoner.class, Level.OFF);
setLoggerLevel(SimpleReasonerTBoxListener.class, Level.OFF); setLoggerLevel(SimpleReasonerTBoxListener.class, Level.OFF);
setLoggerLevel(ABoxRecomputer.class, Level.OFF);
} }
/* /*
@ -674,7 +675,19 @@ public class SimpleReasonerSameAsTest extends AbstractTestClass {
aBox.add(b,Q,d); aBox.add(b,Q,d);
aBox.add(b,T,literal2); aBox.add(b,T,literal2);
aBox.add(a,OWL.sameAs,b); aBox.add(a,OWL.sameAs,b);
Assert.assertTrue(inf.contains(b,OWL.sameAs,a));
Assert.assertTrue(inf.contains(b,P,c));
Assert.assertTrue(inf.contains(b,S,literal1));
Assert.assertTrue(inf.contains(a,Q,d));
Assert.assertTrue(inf.contains(a,T,literal2));
inf.remove(b,OWL.sameAs,a);
inf.remove(b,P,c);
inf.remove(b,S,literal1);
inf.remove(a,Q,d);
inf.remove(a,T,literal2);
simpleReasoner.recompute(); simpleReasoner.recompute();
while (simpleReasoner.isRecomputing()) { while (simpleReasoner.isRecomputing()) {