From 9ce65c5a963b03ee97fe9cb6c5aa65a3c04a80a8 Mon Sep 17 00:00:00 2001 From: yzhou Date: Tue, 21 Apr 2015 10:34:27 +0100 Subject: initial version --- .../ox/cs/pagoda/reasoner/ConsistencyManager.java | 269 +++++++++++++++ .../ox/cs/pagoda/reasoner/ConsistencyManager2.java | 70 ++++ .../ox/cs/pagoda/reasoner/ELHOQueryReasoner.java | 96 ++++++ .../ox/cs/pagoda/reasoner/ELHOUQueryReasoner.java | 195 +++++++++++ .../ac/ox/cs/pagoda/reasoner/HermiTReasoner.java | 133 ++++++++ .../ox/cs/pagoda/reasoner/IterativeRefinement.java | 106 ++++++ .../ac/ox/cs/pagoda/reasoner/MyQueryReasoner.java | 331 +++++++++++++++++++ src/uk/ac/ox/cs/pagoda/reasoner/QueryEngine.java | 17 + src/uk/ac/ox/cs/pagoda/reasoner/QueryReasoner.java | 221 +++++++++++++ .../ac/ox/cs/pagoda/reasoner/RLQueryReasoner.java | 83 +++++ .../ac/ox/cs/pagoda/reasoner/RLUQueryReasoner.java | 134 ++++++++ src/uk/ac/ox/cs/pagoda/reasoner/full/Checker.java | 15 + .../ox/cs/pagoda/reasoner/full/HermitChecker.java | 237 +++++++++++++ .../cs/pagoda/reasoner/light/BasicQueryEngine.java | 366 +++++++++++++++++++++ .../reasoner/light/DLPredicateComparator.java | 24 ++ .../ac/ox/cs/pagoda/reasoner/light/KarmaQuery.java | 95 ++++++ .../cs/pagoda/reasoner/light/KarmaQueryEngine.java | 98 ++++++ .../pagoda/reasoner/light/RDFoxAnswerTuples.java | 100 ++++++ .../cs/pagoda/reasoner/light/RDFoxQueryEngine.java | 110 +++++++ .../pagoda/reasoner/light/RDFoxTripleManager.java | 249 ++++++++++++++ 20 files changed, 2949 insertions(+) create mode 100644 src/uk/ac/ox/cs/pagoda/reasoner/ConsistencyManager.java create mode 100644 src/uk/ac/ox/cs/pagoda/reasoner/ConsistencyManager2.java create mode 100644 src/uk/ac/ox/cs/pagoda/reasoner/ELHOQueryReasoner.java create mode 100644 src/uk/ac/ox/cs/pagoda/reasoner/ELHOUQueryReasoner.java create mode 100644 src/uk/ac/ox/cs/pagoda/reasoner/HermiTReasoner.java create mode 100644 src/uk/ac/ox/cs/pagoda/reasoner/IterativeRefinement.java create mode 100644 src/uk/ac/ox/cs/pagoda/reasoner/MyQueryReasoner.java create mode 100644 src/uk/ac/ox/cs/pagoda/reasoner/QueryEngine.java create mode 100644 src/uk/ac/ox/cs/pagoda/reasoner/QueryReasoner.java create mode 100644 src/uk/ac/ox/cs/pagoda/reasoner/RLQueryReasoner.java create mode 100644 src/uk/ac/ox/cs/pagoda/reasoner/RLUQueryReasoner.java create mode 100644 src/uk/ac/ox/cs/pagoda/reasoner/full/Checker.java create mode 100644 src/uk/ac/ox/cs/pagoda/reasoner/full/HermitChecker.java create mode 100644 src/uk/ac/ox/cs/pagoda/reasoner/light/BasicQueryEngine.java create mode 100644 src/uk/ac/ox/cs/pagoda/reasoner/light/DLPredicateComparator.java create mode 100644 src/uk/ac/ox/cs/pagoda/reasoner/light/KarmaQuery.java create mode 100644 src/uk/ac/ox/cs/pagoda/reasoner/light/KarmaQueryEngine.java create mode 100644 src/uk/ac/ox/cs/pagoda/reasoner/light/RDFoxAnswerTuples.java create mode 100644 src/uk/ac/ox/cs/pagoda/reasoner/light/RDFoxQueryEngine.java create mode 100644 src/uk/ac/ox/cs/pagoda/reasoner/light/RDFoxTripleManager.java (limited to 'src/uk/ac/ox/cs/pagoda/reasoner') diff --git a/src/uk/ac/ox/cs/pagoda/reasoner/ConsistencyManager.java b/src/uk/ac/ox/cs/pagoda/reasoner/ConsistencyManager.java new file mode 100644 index 0000000..a222645 --- /dev/null +++ b/src/uk/ac/ox/cs/pagoda/reasoner/ConsistencyManager.java @@ -0,0 +1,269 @@ +package uk.ac.ox.cs.pagoda.reasoner; + +import java.util.LinkedList; + +import org.semanticweb.HermiT.model.Atom; +import org.semanticweb.HermiT.model.AtomicConcept; +import org.semanticweb.HermiT.model.DLClause; +import org.semanticweb.HermiT.model.Variable; +import org.semanticweb.owlapi.model.OWLOntology; +import org.semanticweb.owlapi.model.OWLOntologyCreationException; +import org.semanticweb.owlapi.model.OWLOntologyManager; + +import uk.ac.ox.cs.pagoda.hermit.DLClauseHelper; +import uk.ac.ox.cs.pagoda.query.AnswerTuples; +import uk.ac.ox.cs.pagoda.query.QueryManager; +import uk.ac.ox.cs.pagoda.query.QueryRecord; +import uk.ac.ox.cs.pagoda.reasoner.full.Checker; +import uk.ac.ox.cs.pagoda.rules.UpperDatalogProgram; +import uk.ac.ox.cs.pagoda.summary.HermitSummaryFilter; +import uk.ac.ox.cs.pagoda.tracking.QueryTracker; +import uk.ac.ox.cs.pagoda.tracking.TrackingRuleEncoder; +import uk.ac.ox.cs.pagoda.util.Timer; +import uk.ac.ox.cs.pagoda.util.Utility; +import uk.ac.ox.cs.JRDFox.JRDFStoreException; +import uk.ac.ox.cs.JRDFox.store.DataStore; + +public class ConsistencyManager { + + protected MyQueryReasoner m_reasoner; + protected QueryManager m_queryManager; + + Timer t = new Timer(); + + public ConsistencyManager(MyQueryReasoner reasoner) { + m_reasoner = reasoner; + m_queryManager = reasoner.getQueryManager(); + } + + QueryRecord fullQueryRecord; + QueryRecord[] botQueryRecords; + + LinkedList toAddClauses; + + boolean checkRLLowerBound() { + fullQueryRecord = m_queryManager.create(QueryRecord.botQueryText, 0); + fullQueryRecord.updateLowerBoundAnswers(m_reasoner.rlLowerStore.evaluate(fullQueryRecord.getQueryText(), fullQueryRecord.getAnswerVariables())); + if (fullQueryRecord.getNoOfSoundAnswers() > 0) { + Utility.logInfo("Answers to bottom in the lower bound: ", fullQueryRecord.outputSoundAnswerTuple()); + return unsatisfiability(t.duration()); + } + return true; + } + + boolean checkELLowerBound() { + fullQueryRecord.updateLowerBoundAnswers(m_reasoner.elLowerStore.evaluate(fullQueryRecord.getQueryText(), fullQueryRecord.getAnswerVariables())); + if (fullQueryRecord.getNoOfSoundAnswers() > 0) { + Utility.logInfo("Answers to bottom in the lower bound: ", fullQueryRecord.outputSoundAnswerTuple()); + return unsatisfiability(t.duration()); + } + return true; + } + + boolean checkLazyUpper() { + if (m_reasoner.lazyUpperStore != null) { + AnswerTuples tuples = null; + try { + tuples = m_reasoner.lazyUpperStore.evaluate(fullQueryRecord.getQueryText(), fullQueryRecord.getAnswerVariables()); + if (!tuples.isValid()) { + Utility.logInfo("There are no contradictions derived in the lazy upper bound materialisation."); + return satisfiability(t.duration()); + } + } + finally { + if (tuples != null) tuples.dispose(); + } + } + return false; + } + + boolean check() { +// if (!checkRLLowerBound()) return false; +// if (!checkELLowerBound()) return false; +// if (checkLazyUpper()) return true; + + fullQueryRecord.updateUpperBoundAnswers(m_reasoner.trackingStore.evaluate(fullQueryRecord.getQueryText(), fullQueryRecord.getAnswerVariables())); + if (fullQueryRecord.getNoOfCompleteAnswers() == 0) + return satisfiability(t.duration()); + + extractBottomFragment(); + + try { + extractAxioms4Full(); + } catch (OWLOntologyCreationException e) { + e.printStackTrace(); + } + fullQueryRecord.saveRelevantClause(); + + boolean satisfiability; + + Checker checker; + for (QueryRecord r: getQueryRecords()) { + // TODO to be removed ... +// r.saveRelevantOntology("bottom" + r.getQueryID() + ".owl"); + checker = new HermitSummaryFilter(r); // m_reasoner.factory.getSummarisedReasoner(r); + satisfiability = checker.isConsistent(); + checker.dispose(); + if (!satisfiability) return unsatisfiability(t.duration()); + } + +// Checker checker = m_reasoner.factory.getSummarisedReasoner(fullQueryRecord); +// boolean satisfiable = checker.isConsistent(); +// checker.dispose(); +// if (!satisfiable) return unsatisfiability(t.duration()); + + return satisfiability(t.duration()); + } + + protected boolean unsatisfiability(double duration) { + fullQueryRecord.dispose(); + Utility.logDebug("The ontology and dataset is unsatisfiable."); + return false; + } + + protected boolean satisfiability(double duration) { + fullQueryRecord.dispose(); + Utility.logDebug("The ontology and dataset is satisfiable."); + return true; + } + + boolean fragmentExtracted = false; + + public void extractBottomFragment() { + if (fragmentExtracted) return ; + fragmentExtracted = true; + + UpperDatalogProgram upperProgram = m_reasoner.program.getUpper(); + int number = upperProgram.getBottomNumber(); + + if (number <= 1) { + botQueryRecords = new QueryRecord[] { fullQueryRecord }; + } + else { + QueryRecord[] tempQueryRecords = new QueryRecord[number - 1]; + QueryRecord record; + for (int i = 0; i < number - 1; ++i) { + tempQueryRecords[i] = record = m_queryManager.create(QueryRecord.botQueryText.replace("Nothing", "Nothing" + (i + 1)), 0, i + 1); + record.updateUpperBoundAnswers(m_reasoner.trackingStore.evaluate(record.getQueryText(), record.getAnswerVariables())); + } + + int bottomNumber = 0; + int[] group = new int[number - 1]; + for (int i = 0; i < number - 1; ++i) group[i] = i; + for (int i = 0; i < number - 1; ++i) + if (tempQueryRecords[i].processed()) tempQueryRecords[i].dispose(); + else if (group[i] == i) { + ++bottomNumber; + record = tempQueryRecords[i]; + for (int j = i + 1; j < number - 1; ++j) + if (record.hasSameGapAnswers(tempQueryRecords[j])) + group[j] = i; + } + + Utility.logInfo("There are " + bottomNumber + " different bottom fragments."); + toAddClauses = new LinkedList(); + int bottomCounter = 0; + botQueryRecords = new QueryRecord[bottomNumber]; + Variable X = Variable.create("X"); + for (int i = 0; i < number - 1; ++i) + if (!tempQueryRecords[i].processed()) + if (group[i] == i) { + botQueryRecords[bottomCounter] = record = tempQueryRecords[i]; + record.resetInfo(QueryRecord.botQueryText.replace("Nothing", "Nothing_final" + (++bottomCounter)), 0, group[i] = bottomCounter); + toAddClauses.add( + DLClause.create( + new Atom[] {Atom.create(AtomicConcept.create(AtomicConcept.NOTHING.getIRI() + "_final" + bottomCounter), X)}, + new Atom[] {Atom.create(AtomicConcept.create(AtomicConcept.NOTHING.getIRI() + (i + 1)), X)})); + } + else { + toAddClauses.add( + DLClause.create( + new Atom[] {Atom.create(AtomicConcept.create(AtomicConcept.NOTHING.getIRI() + "_final" + group[group[i]]), X)}, + new Atom[] {Atom.create(AtomicConcept.create(AtomicConcept.NOTHING.getIRI() + (i + 1)), X)})); + tempQueryRecords[i].dispose(); + } + + upperProgram.updateDependencyGraph(toAddClauses); + } + + String[] programs = collectTrackingProgramAndImport(); + if (programs.length == 0) + return ; + + DataStore store = m_reasoner.trackingStore.getDataStore(); + long oldTripleCount, tripleCount; + try { + Timer t1 = new Timer(); + oldTripleCount = store.getTriplesCount(); + for (String program: programs) + store.importRules(program); + store.applyReasoning(true); + tripleCount = store.getTriplesCount(); + + Utility.logInfo("tracking store after materialising tracking program: " + tripleCount + " (" + (tripleCount - oldTripleCount) + " new)", + "tracking store finished the materialisation of tracking program in " + t1.duration() + " seconds."); + + extractAxioms(); + store.clearRulesAndMakeFactsExplicit(); + } catch (JRDFStoreException e) { + e.printStackTrace(); + } catch (OWLOntologyCreationException e) { + e.printStackTrace(); + } + } + + private void extractAxioms4Full() throws OWLOntologyCreationException { + OWLOntologyManager manager = m_reasoner.encoder.getProgram().getOntology().getOWLOntologyManager(); + OWLOntology fullOntology = manager.createOntology(); + for (QueryRecord record: botQueryRecords) { + for (DLClause clause: record.getRelevantClauses()) { + fullQueryRecord.addRelevantClauses(clause); + } + manager.addAxioms(fullOntology, record.getRelevantOntology().getAxioms()); + } + fullQueryRecord.setRelevantOntology(fullOntology); + } + + private void extractAxioms() throws OWLOntologyCreationException { + OWLOntologyManager manager = m_reasoner.encoder.getProgram().getOntology().getOWLOntologyManager(); + for (QueryRecord record: botQueryRecords) { + record.setRelevantOntology(manager.createOntology()); + QueryTracker tracker = new QueryTracker(m_reasoner.encoder, m_reasoner.rlLowerStore, record); + m_reasoner.encoder.setCurrentQuery(record); + tracker.extractAxioms(m_reasoner.trackingStore); +// record.saveRelevantClause(); +// record.saveRelevantOntology("bottom" + record.getQueryID() + ".owl"); + Utility.logInfo("finish extracting axioms for bottom " + record.getQueryID()); + } + } + + private String[] collectTrackingProgramAndImport() { + String[] programs = new String[botQueryRecords.length]; + TrackingRuleEncoder encoder = m_reasoner.encoder; + + StringBuilder builder; + LinkedList currentClauses = new LinkedList(); + + for (int i = 0; i < botQueryRecords.length; ++i) { + encoder.setCurrentQuery(botQueryRecords[i]); + builder = new StringBuilder(encoder.getTrackingProgram()); +// encoder.saveTrackingRules("tracking_bottom" + (i + 1) + ".dlog"); + + for (DLClause clause: toAddClauses) + if (clause.getHeadAtom(0).getDLPredicate().toString().contains("_final" + (i + 1))) + currentClauses.add(clause); + + builder.append(DLClauseHelper.toString(currentClauses)); + programs[i] = builder.toString(); + + currentClauses.clear(); + } + + return programs; + } + + public QueryRecord[] getQueryRecords() { + return botQueryRecords; + } + +} diff --git a/src/uk/ac/ox/cs/pagoda/reasoner/ConsistencyManager2.java b/src/uk/ac/ox/cs/pagoda/reasoner/ConsistencyManager2.java new file mode 100644 index 0000000..67dc4fc --- /dev/null +++ b/src/uk/ac/ox/cs/pagoda/reasoner/ConsistencyManager2.java @@ -0,0 +1,70 @@ +package uk.ac.ox.cs.pagoda.reasoner; + +import org.semanticweb.owlapi.model.OWLOntologyCreationException; +import org.semanticweb.owlapi.model.OWLOntologyManager; + +import uk.ac.ox.cs.pagoda.query.QueryRecord; +import uk.ac.ox.cs.pagoda.reasoner.full.Checker; +import uk.ac.ox.cs.pagoda.summary.HermitSummaryFilter; +import uk.ac.ox.cs.pagoda.tracking.QueryTracker; +import uk.ac.ox.cs.pagoda.util.Utility; + +@Deprecated +public class ConsistencyManager2 extends ConsistencyManager { + + public ConsistencyManager2(MyQueryReasoner reasoner) { + super(reasoner); + fragmentExtracted = true; + } + + protected boolean unsatisfiability(double duration) { + Utility.logDebug("The ontology and dataset is unsatisfiable."); + return false; + } + + protected boolean satisfiability(double duration) { + Utility.logDebug("The ontology and dataset is satisfiable."); + return true; + } + + @Override + boolean check() { +// if (!checkRLLowerBound()) return false; +// if (!checkELLowerBound()) return false; + if (checkLazyUpper()) return true; + + fullQueryRecord.updateUpperBoundAnswers(m_reasoner.trackingStore.evaluate(fullQueryRecord.getQueryText(), fullQueryRecord.getAnswerVariables())); + if (fullQueryRecord.getNoOfCompleteAnswers() == 0) + return satisfiability(t.duration()); + + try { + extractAxioms(); + } catch (OWLOntologyCreationException e) { + e.printStackTrace(); + } + + Checker checker = new HermitSummaryFilter(fullQueryRecord); // m_reasoner.factory.getSummarisedReasoner(fullQueryRecord); +// fullQueryRecord.saveRelevantOntology("fragment_bottom.owl"); + boolean satisfiable = checker.isConsistent(); + checker.dispose(); + if (!satisfiable) return unsatisfiability(t.duration()); + + return satisfiability(t.duration()); + } + + private void extractAxioms() throws OWLOntologyCreationException { + OWLOntologyManager manager = m_reasoner.encoder.getProgram().getOntology().getOWLOntologyManager(); + fullQueryRecord.setRelevantOntology(manager.createOntology()); + QueryTracker tracker = new QueryTracker(m_reasoner.encoder, m_reasoner.rlLowerStore, fullQueryRecord); + m_reasoner.encoder.setCurrentQuery(fullQueryRecord); + tracker.extract(m_reasoner.trackingStore, null, true); + } + + @Override + public QueryRecord[] getQueryRecords() { + if (botQueryRecords == null) + botQueryRecords = new QueryRecord[] {fullQueryRecord}; + return botQueryRecords; + } + +} diff --git a/src/uk/ac/ox/cs/pagoda/reasoner/ELHOQueryReasoner.java b/src/uk/ac/ox/cs/pagoda/reasoner/ELHOQueryReasoner.java new file mode 100644 index 0000000..4ebe5f2 --- /dev/null +++ b/src/uk/ac/ox/cs/pagoda/reasoner/ELHOQueryReasoner.java @@ -0,0 +1,96 @@ +package uk.ac.ox.cs.pagoda.reasoner; + +import org.semanticweb.karma2.profile.ELHOProfile; +import org.semanticweb.owlapi.model.OWLOntology; + +import uk.ac.ox.cs.pagoda.constraints.UnaryBottom; +import uk.ac.ox.cs.pagoda.query.AnswerTuples; +import uk.ac.ox.cs.pagoda.query.QueryRecord; +import uk.ac.ox.cs.pagoda.query.QueryRecord.Step; +import uk.ac.ox.cs.pagoda.reasoner.light.KarmaQueryEngine; +import uk.ac.ox.cs.pagoda.rules.LowerDatalogProgram; +import uk.ac.ox.cs.pagoda.util.Timer; +import uk.ac.ox.cs.pagoda.util.Utility; + +public class ELHOQueryReasoner extends QueryReasoner { + + LowerDatalogProgram program; + + OWLOntology elho_ontology; + KarmaQueryEngine elLowerStore = null; + + private Timer t = new Timer(); + + public ELHOQueryReasoner() { + elLowerStore = new KarmaQueryEngine("el"); + } + + @Override + public void evaluate(QueryRecord queryRecord) { + AnswerTuples elAnswer = null; + t.reset(); + try { + elAnswer = elLowerStore.evaluate(queryRecord.getQueryText(), queryRecord.getAnswerVariables()); + queryRecord.updateLowerBoundAnswers(elAnswer); + } finally { + if (elAnswer != null) elAnswer.dispose(); + } + queryRecord.addProcessingTime(Step.ELLowerBound, t.duration()); + + queryRecord.setDifficulty(Step.ELLowerBound); + queryRecord.markAsProcessed(); + } + + @Override + public void evaluateUpper(QueryRecord queryRecord) { + evaluate(queryRecord); + } + + @Override + public void dispose() { + if (elLowerStore != null) elLowerStore.dispose(); + super.dispose(); + } + + @Override + public void loadOntology(OWLOntology ontology) { + program = new LowerDatalogProgram(!forSemFacet); + program.load(ontology, new UnaryBottom()); + program.transform(); + + importData(program.getAdditionalDataFile()); + + elho_ontology = new ELHOProfile().getFragment(ontology); + elLowerStore.processOntology(elho_ontology); + } + + @Override + public boolean preprocess() { + elLowerStore.importRDFData("data", importedData.toString()); + String rlLowerProgramText = program.toString(); +// program.save(); + elLowerStore.materialise("lower program", rlLowerProgramText); + elLowerStore.initialiseKarma(); + + if (!isConsistent()) { + Utility.logDebug("The dataset is not consistent with the ontology."); + return false; + } + return true; + } + + @Override + public boolean isConsistent() { + String[] X = new String[] {"X"}; + AnswerTuples ans = null; + try { + ans = elLowerStore.evaluate(QueryRecord.botQueryText, X); + if (ans.isValid()) return false; + } finally { + if (ans != null) ans.dispose(); + } + + return true; + } + +} diff --git a/src/uk/ac/ox/cs/pagoda/reasoner/ELHOUQueryReasoner.java b/src/uk/ac/ox/cs/pagoda/reasoner/ELHOUQueryReasoner.java new file mode 100644 index 0000000..62d238b --- /dev/null +++ b/src/uk/ac/ox/cs/pagoda/reasoner/ELHOUQueryReasoner.java @@ -0,0 +1,195 @@ +package uk.ac.ox.cs.pagoda.reasoner; + +import org.semanticweb.karma2.profile.ELHOProfile; +import org.semanticweb.owlapi.model.OWLOntology; + +import uk.ac.ox.cs.pagoda.multistage.MultiStageQueryEngine; +import uk.ac.ox.cs.pagoda.owl.EqualitiesEliminator; +import uk.ac.ox.cs.pagoda.owl.OWLHelper; +import uk.ac.ox.cs.pagoda.query.AnswerTuples; +import uk.ac.ox.cs.pagoda.query.QueryRecord; +import uk.ac.ox.cs.pagoda.query.QueryRecord.Step; +import uk.ac.ox.cs.pagoda.reasoner.light.BasicQueryEngine; +import uk.ac.ox.cs.pagoda.reasoner.light.KarmaQueryEngine; +import uk.ac.ox.cs.pagoda.rules.DatalogProgram; +import uk.ac.ox.cs.pagoda.util.Timer; +import uk.ac.ox.cs.pagoda.util.Utility; + +public class ELHOUQueryReasoner extends QueryReasoner { + + DatalogProgram program; + + BasicQueryEngine rlLowerStore; + BasicQueryEngine rlUpperStore; + + OWLOntology elho_ontology; + KarmaQueryEngine elLowerStore = null; + + boolean multiStageTag, equalityTag; + + public ELHOUQueryReasoner(boolean multiStageTag, boolean considerEqualities) { + this.multiStageTag = multiStageTag; + this.equalityTag = considerEqualities; + rlLowerStore = new BasicQueryEngine("rl-lower-bound"); + elLowerStore = new KarmaQueryEngine("el-lower-bound"); + + if (!multiStageTag) + rlUpperStore = new BasicQueryEngine("rl-upper-bound"); + else + rlUpperStore = new MultiStageQueryEngine("rl-upper-bound", false); + } + + private Timer t = new Timer(); + + @Override + public void evaluate(QueryRecord queryRecord) { + AnswerTuples rlAnswer = null; + t.reset(); + try { + rlAnswer = rlLowerStore.evaluate(queryRecord.getQueryText(), queryRecord.getAnswerVariables()); + queryRecord.updateLowerBoundAnswers(rlAnswer); + } finally { + if (rlAnswer != null) rlAnswer.dispose(); + } + queryRecord.addProcessingTime(Step.LowerBound, t.duration()); + + String extendedQueryText = queryRecord.getExtendedQueryText()[0]; + String[] toQuery = queryRecord.getQueryText().equals(extendedQueryText) ? + new String[] {queryRecord.getQueryText()} : + new String[] {queryRecord.getQueryText(), extendedQueryText}; + + for (String queryText: toQuery) { + rlAnswer = null; + t.reset(); + try { + rlAnswer = rlUpperStore.evaluate(queryText, queryRecord.getAnswerVariables()); + queryRecord.updateUpperBoundAnswers(rlAnswer); + } finally { + if (rlAnswer != null) rlAnswer.dispose(); + } + queryRecord.addProcessingTime(Step.UpperBound, t.duration()); + + if (queryRecord.processed()) { + queryRecord.setDifficulty(Step.UpperBound); + return ; + } + } + + AnswerTuples elAnswer = null; + t.reset(); + try { + elAnswer = elLowerStore.evaluate(extendedQueryText, queryRecord.getAnswerVariables(), queryRecord.getLowerBoundAnswers()); + queryRecord.updateLowerBoundAnswers(elAnswer); + } finally { + if (elAnswer != null) elAnswer.dispose(); + } + queryRecord.addProcessingTime(Step.ELLowerBound, t.duration()); + } + + @Override + public void evaluateUpper(QueryRecord queryRecord) { + AnswerTuples rlAnswer = null; + try { + rlAnswer = rlUpperStore.evaluate(queryRecord.getQueryText(), queryRecord.getAnswerVariables()); + queryRecord.updateUpperBoundAnswers(rlAnswer, true); + } finally { + if (rlAnswer != null) rlAnswer.dispose(); + } + } + + @Override + public void dispose() { + if (elLowerStore != null) elLowerStore.dispose(); + if (rlUpperStore != null) rlUpperStore.dispose(); + super.dispose(); + } + + @Override + public void loadOntology(OWLOntology o) { + if (!equalityTag) { + EqualitiesEliminator eliminator = new EqualitiesEliminator(o); + o = eliminator.getOutputOntology(); + eliminator.save(); + } + + OWLOntology ontology = o; + program = new DatalogProgram(ontology, !forSemFacet); + + importData(program.getAdditionalDataFile()); + + elho_ontology = new ELHOProfile().getFragment(ontology); + elLowerStore.processOntology(elho_ontology); + originalMarkProgram = OWLHelper.getOriginalMarkProgram(ontology); + } + + String originalMarkProgram; + + @Override + public boolean preprocess() { + String name = "data", datafile = importedData.toString(); + + String lowername = "lower program"; + String rlLowerProgramText = program.getLower().toString(); + + rlUpperStore.importRDFData(name, datafile); + rlUpperStore.materialise("saturate named individuals", originalMarkProgram); + + int flag = rlUpperStore.materialiseRestrictedly(program, null); + if (flag != 1) { + if (flag == -1) return false; + rlUpperStore.dispose(); + + if (!multiStageTag) + rlUpperStore = new BasicQueryEngine("rl-upper-bound"); + else + rlUpperStore = new MultiStageQueryEngine("rl-upper-bound", false); + rlUpperStore.importRDFData(name, datafile); + rlUpperStore.materialise("saturate named individuals", originalMarkProgram); + rlUpperStore.materialiseFoldedly(program, null); + } + Utility.logInfo("upper store ready."); + + rlLowerStore.importRDFData(name, datafile); + rlLowerStore.materialise(lowername, rlLowerProgramText); + Utility.logInfo("lower store ready."); + + elLowerStore.importRDFData(name, datafile); + elLowerStore.materialise("saturate named individuals", originalMarkProgram); + elLowerStore.materialise(lowername, rlLowerProgramText); + + elLowerStore.initialiseKarma(); + Utility.logInfo("EL lower store ready."); + + if (!isConsistent()) { + Utility.logInfo("The dataset is not consistent with the ontology."); + return false; + } + Utility.logInfo("The dataset is consistent."); + return true; + } + + @Override + public boolean isConsistent() { + Utility.logInfo("Start checking consistency... "); + String[] X = new String[] {"X"}; + AnswerTuples ans = null; + try { + ans = rlUpperStore.evaluate(QueryRecord.botQueryText, X); + if (!ans.isValid()) return true; + } finally { + if (ans != null) ans.dispose(); + } + + ans = null; + try { + ans = elLowerStore.evaluate(QueryRecord.botQueryText, X); + if (ans.isValid()) return false; + } finally { + if (ans != null) ans.dispose(); + } + + Utility.logDebug("The consistency of the data has not been determined yet."); + return true; + } + +} diff --git a/src/uk/ac/ox/cs/pagoda/reasoner/HermiTReasoner.java b/src/uk/ac/ox/cs/pagoda/reasoner/HermiTReasoner.java new file mode 100644 index 0000000..5511691 --- /dev/null +++ b/src/uk/ac/ox/cs/pagoda/reasoner/HermiTReasoner.java @@ -0,0 +1,133 @@ +package uk.ac.ox.cs.pagoda.reasoner; + +import java.io.File; +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; + +import org.semanticweb.HermiT.Reasoner; +import org.semanticweb.owlapi.model.OWLClassExpression; +import org.semanticweb.owlapi.model.OWLDataFactory; +import org.semanticweb.owlapi.model.OWLNamedIndividual; +import org.semanticweb.owlapi.model.OWLOntology; +import org.semanticweb.owlapi.model.OWLOntologyCreationException; +import org.semanticweb.owlapi.model.OWLOntologyStorageException; + +import uk.ac.ox.cs.JRDFox.model.Individual; +import uk.ac.ox.cs.pagoda.multistage.MultiStageQueryEngine; +import uk.ac.ox.cs.pagoda.owl.OWLHelper; +import uk.ac.ox.cs.pagoda.owl.QueryRoller; +import uk.ac.ox.cs.pagoda.query.AnswerTuple; +import uk.ac.ox.cs.pagoda.query.AnswerTuples; +import uk.ac.ox.cs.pagoda.query.AnswerTuplesImp; +import uk.ac.ox.cs.pagoda.query.GapByStore4ID; +import uk.ac.ox.cs.pagoda.query.QueryRecord; +import uk.ac.ox.cs.pagoda.reasoner.light.BasicQueryEngine; +import uk.ac.ox.cs.pagoda.rules.DatalogProgram; +import uk.ac.ox.cs.pagoda.util.Utility; + +public class HermiTReasoner extends QueryReasoner { + + Reasoner hermit; + + BasicQueryEngine upperStore = null; + + OWLOntology onto; + OWLDataFactory factory; + + String importedOntologyPath = null; + + QueryRoller roller; + boolean toCheckSatisfiability; + + public HermiTReasoner(boolean toCheckSatisfiability) { + this.toCheckSatisfiability = toCheckSatisfiability; + } + + @Override + public void loadOntology(OWLOntology ontology) { + onto = ontology; + } + + @Override + public boolean preprocess() { + OWLOntology tbox = onto; + try { + onto = OWLHelper.getImportedOntology(tbox, importedData.toString().split(ImportDataFileSeparator)); + importedOntologyPath = OWLHelper.getOntologyPath(onto); + } catch (OWLOntologyCreationException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (OWLOntologyStorageException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + DatalogProgram datalogProgram = new DatalogProgram(tbox, false); + importData(datalogProgram.getAdditionalDataFile()); + upperStore = new MultiStageQueryEngine("rl-upper", false); + upperStore.importRDFData("data", importedData.toString()); + GapByStore4ID gap = new GapByStore4ID(upperStore); + upperStore.materialiseFoldedly(datalogProgram, gap); + gap.clear(); + + factory = onto.getOWLOntologyManager().getOWLDataFactory(); + roller = new QueryRoller(factory); + + hermit = new Reasoner(onto); + return isConsistent(); + } + + @Override + public boolean isConsistent() { + if (toCheckSatisfiability) + return hermit.isConsistent(); + return true; + } + + @Override + public void evaluate(QueryRecord record) { + String[] disVars = record.getDistinguishedVariables(); + Set individuals = onto.getIndividualsInSignature(true); + if (disVars.length == 1) { + OWLClassExpression clsExp = roller.rollUp(record.getClause(), record.getAnswerVariables()[0]); + Set answers = new HashSet(); + for (OWLNamedIndividual individual: individuals) { + Utility.logDebug("checking ... " + individual); + if (hermit.isEntailed(factory.getOWLClassAssertionAxiom(clsExp, individual))) { + answers.add(new AnswerTuple(new Individual[] {Individual.create(individual.toStringID())})); + } + } + record.updateLowerBoundAnswers(new AnswerTuplesImp(record.getAnswerVariables(), answers)); + record.markAsProcessed(); + } + else { + // FIXME join here + record.markAsProcessed(); + } + } + + @Override + public void evaluateUpper(QueryRecord record) { + AnswerTuples rlAnswer = null; + try { + rlAnswer = upperStore.evaluate(record.getQueryText(), record.getAnswerVariables()); + record.updateUpperBoundAnswers(rlAnswer, true); + } finally { + if (rlAnswer != null) rlAnswer.dispose(); + } + } + + @Override + public void dispose() { + if (importedOntologyPath != null) { + File tmp = new File(importedOntologyPath); + if (tmp.exists()) tmp.delete(); + } + super.dispose(); + } + +} diff --git a/src/uk/ac/ox/cs/pagoda/reasoner/IterativeRefinement.java b/src/uk/ac/ox/cs/pagoda/reasoner/IterativeRefinement.java new file mode 100644 index 0000000..ba6a4d4 --- /dev/null +++ b/src/uk/ac/ox/cs/pagoda/reasoner/IterativeRefinement.java @@ -0,0 +1,106 @@ +package uk.ac.ox.cs.pagoda.reasoner; + +import java.io.File; + +import org.semanticweb.owlapi.model.OWLOntology; + +import uk.ac.ox.cs.pagoda.constraints.BottomStrategy; +import uk.ac.ox.cs.pagoda.constraints.UpperUnaryBottom; +import uk.ac.ox.cs.pagoda.multistage.MultiStageQueryEngine; +import uk.ac.ox.cs.pagoda.query.QueryRecord; +import uk.ac.ox.cs.pagoda.reasoner.light.BasicQueryEngine; +import uk.ac.ox.cs.pagoda.rules.GeneralProgram; +import uk.ac.ox.cs.pagoda.tracking.QueryTracker; +import uk.ac.ox.cs.pagoda.util.Utility; + +public class IterativeRefinement { + + private static final int depthLimit = 1; + + QueryRecord m_record; + QueryTracker m_tracker; + BasicQueryEngine m_trackingStore; + QueryRecord[] botQueryRecords; + + int m_depth = 0; + + public IterativeRefinement(QueryRecord queryRecord, QueryTracker tracker, BasicQueryEngine trackingStore, QueryRecord[] botQueryRecords) { + m_record = queryRecord; + m_tracker = tracker; + m_trackingStore = trackingStore; + this.botQueryRecords = botQueryRecords; + } + + String tempDataFile = "temp.ttl"; + + public OWLOntology extractWithFullABox(String dataset, BottomStrategy upperBottom) { + GeneralProgram program; + boolean update; + while (m_depth < depthLimit) { + ++m_depth; + program = new GeneralProgram(m_record.getRelevantClauses(), m_record.getRelevantOntology()); + + MultiStageQueryEngine tEngine = new MultiStageQueryEngine("query-tracking", true); + try { + tEngine.importRDFData("data", dataset); + if (tEngine.materialise4SpecificQuery(program, m_record, upperBottom) != 1) { + return m_record.getRelevantOntology(); + } + + update = m_record.updateUpperBoundAnswers(tEngine.evaluate(m_record.getQueryText())); + } finally { + tEngine.dispose(); + } + + if (m_record.processed()) + return null; + + if (!update) break; + + m_record.updateSubID(); + m_tracker.extract(m_trackingStore, botQueryRecords, true); + } + + return m_record.getRelevantOntology(); + } + + public OWLOntology extract(UpperUnaryBottom upperBottom) { + GeneralProgram program; + boolean update; + while (m_depth < depthLimit) { + m_record.saveABoxInTurtle(tempDataFile); + program = new GeneralProgram(m_record.getRelevantClauses(), m_record.getRelevantOntology()); + + MultiStageQueryEngine tEngine = new MultiStageQueryEngine("query-tracking", true); + try { + tEngine.importRDFData("fragment abox", tempDataFile); + if (tEngine.materialise4SpecificQuery(program, m_record, upperBottom) != 1) { + return m_record.getRelevantOntology(); + } + + update = m_record.updateUpperBoundAnswers(tEngine.evaluate(m_record.getQueryText())); + } finally { + tEngine.dispose(); + } + + if (m_record.processed()) + return null; + + if (!update) break; + + m_record.updateSubID(); + m_tracker.extract(m_trackingStore, botQueryRecords, true); + } + + return m_record.getRelevantOntology(); + } + + public void dispose() { + File file = new File(tempDataFile); + if (file.exists()) { + file.delete(); + Utility.logDebug(file.getAbsolutePath() + " is deleted."); + } + } + +} diff --git a/src/uk/ac/ox/cs/pagoda/reasoner/MyQueryReasoner.java b/src/uk/ac/ox/cs/pagoda/reasoner/MyQueryReasoner.java new file mode 100644 index 0000000..2c2feae --- /dev/null +++ b/src/uk/ac/ox/cs/pagoda/reasoner/MyQueryReasoner.java @@ -0,0 +1,331 @@ +package uk.ac.ox.cs.pagoda.reasoner; + +import java.util.Collection; + +import org.semanticweb.karma2.profile.ELHOProfile; +import org.semanticweb.owlapi.model.OWLOntology; + +import uk.ac.ox.cs.pagoda.multistage.*; +import uk.ac.ox.cs.pagoda.owl.EqualitiesEliminator; +import uk.ac.ox.cs.pagoda.owl.OWLHelper; +import uk.ac.ox.cs.pagoda.query.*; +import uk.ac.ox.cs.pagoda.query.QueryRecord.Step; +import uk.ac.ox.cs.pagoda.reasoner.full.Checker; +import uk.ac.ox.cs.pagoda.reasoner.light.BasicQueryEngine; +import uk.ac.ox.cs.pagoda.reasoner.light.KarmaQueryEngine; +import uk.ac.ox.cs.pagoda.rules.DatalogProgram; +import uk.ac.ox.cs.pagoda.summary.HermitSummaryFilter; +import uk.ac.ox.cs.pagoda.tracking.*; +import uk.ac.ox.cs.pagoda.util.Timer; +import uk.ac.ox.cs.pagoda.util.Utility; + +public class MyQueryReasoner extends QueryReasoner { + + OWLOntology ontology; + +// String additonalDataFile; + + DatalogProgram program; + + BasicQueryEngine rlLowerStore = null; + BasicQueryEngine lazyUpperStore = null; +// boolean[] namedIndividuals_lazyUpper; + + OWLOntology elho_ontology; + KarmaQueryEngine elLowerStore = null; + + BasicQueryEngine trackingStore = null; +// boolean[] namedIndividuals_tracking; + + boolean equalityTag; + boolean multiStageTag; + + public MyQueryReasoner() { + setup(true, true); + } + + public MyQueryReasoner(boolean multiStageTag, boolean considerEqualities) { + setup(multiStageTag, considerEqualities); + } + + private BasicQueryEngine getUpperStore(String name, boolean checkValidity) { + if (multiStageTag) + return new MultiStageQueryEngine(name, checkValidity); +// return new TwoStageQueryEngine(name, checkValidity); + else + return new BasicQueryEngine(name); + } + + public void setup(boolean multiStageTag, boolean considerEqualities) { + satisfiable = null; + this.multiStageTag = multiStageTag; + this.equalityTag = considerEqualities; + + rlLowerStore = new BasicQueryEngine("rl-lower-bound"); + elLowerStore = new KarmaQueryEngine("elho-lower-bound"); + + trackingStore = getUpperStore("tracking", false); + } + + protected void internal_importDataFile(String name, String datafile) { +// addDataFile(datafile); + rlLowerStore.importRDFData(name, datafile); + if (lazyUpperStore != null) + lazyUpperStore.importRDFData(name, datafile); + elLowerStore.importRDFData(name, datafile); + trackingStore.importRDFData(name, datafile); + } + + @Override + public void loadOntology(OWLOntology o) { + if (!equalityTag) { + EqualitiesEliminator eliminator = new EqualitiesEliminator(o); + o = eliminator.getOutputOntology(); + eliminator.save(); + } + + ontology = o; + program = new DatalogProgram(ontology, !forSemFacet); +// program.getLower().save(); +// program.getUpper().save(); +// program.getGeneral().save(); + + if (multiStageTag && !program.getGeneral().isHorn()) { + lazyUpperStore = getUpperStore("lazy-upper-bound", true); // new MultiStageQueryEngine("lazy-upper-bound", true); // + } + + importData(program.getAdditionalDataFile()); + + elho_ontology = new ELHOProfile().getFragment(ontology); + elLowerStore.processOntology(elho_ontology); + } + + private Collection predicatesWithGap = null; + + public Collection getPredicatesWithGap() { + return predicatesWithGap; + } + + @Override + public boolean preprocess() { + t.reset(); + Utility.logInfo("Preprocessing ... checking satisfiability ... "); + + String name = "data", datafile = importedData.toString(); + rlLowerStore.importRDFData(name, datafile); + rlLowerStore.materialise("lower program", program.getLower().toString()); +// program.getLower().save(); + if (!consistency.checkRLLowerBound()) return false; + Utility.logInfo("The number of sameAs assertions in RL lower store: " + rlLowerStore.getSameAsNumber()); + + String originalMarkProgram = OWLHelper.getOriginalMarkProgram(ontology); + + elLowerStore.importRDFData(name, datafile); + elLowerStore.materialise("saturate named individuals", originalMarkProgram); + elLowerStore.materialise("lower program", program.getLower().toString()); + elLowerStore.initialiseKarma(); + if (!consistency.checkELLowerBound()) return false; + + if (lazyUpperStore != null) { + lazyUpperStore.importRDFData(name, datafile); + lazyUpperStore.materialise("saturate named individuals", originalMarkProgram); + int tag = lazyUpperStore.materialiseRestrictedly(program, null); + if (tag != 1) { + lazyUpperStore.dispose(); + lazyUpperStore = null; + } + if (tag == -1) return false; + } + if (consistency.checkLazyUpper()) { + satisfiable = true; + Utility.logInfo("time for satisfiability checking: " + t.duration()); + } + + trackingStore.importRDFData(name, datafile); + trackingStore.materialise("saturate named individuals", originalMarkProgram); + +// materialiseFullUpper(); + GapByStore4ID gap = new GapByStore4ID(trackingStore); + trackingStore.materialiseFoldedly(program, gap); + predicatesWithGap = gap.getPredicatesWithGap(); + gap.clear(); + + if (program.getGeneral().isHorn()) + encoder = new TrackingRuleEncoderWithGap(program.getUpper(), trackingStore); + else + encoder = new TrackingRuleEncoderDisjVar1(program.getUpper(), trackingStore); +// encoder = new TrackingRuleEncoderDisj1(program.getUpper(), trackingStore); +// encoder = new TrackingRuleEncoderDisjVar2(program.getUpper(), trackingStore); +// encoder = new TrackingRuleEncoderDisj2(program.getUpper(), trackingStore); + + program.deleteABoxTurtleFile(); + + if (!isConsistent()) + return false; + + consistency.extractBottomFragment(); + return true; + } + + private Boolean satisfiable; + private ConsistencyManager consistency = new ConsistencyManager(this); + + TrackingRuleEncoder encoder; + + @Override + public boolean isConsistent() { + if (satisfiable == null) { + satisfiable = consistency.check(); + Utility.logInfo("time for satisfiability checking: " + t.duration()); + } + return satisfiable; + } + + Timer t = new Timer(); + + private OWLOntology relevantPart(QueryRecord queryRecord) { + AnswerTuples rlAnswer = null, elAnswer = null; + + t.reset(); + try { + rlAnswer = rlLowerStore.evaluate(queryRecord.getQueryText(), queryRecord.getAnswerVariables()); + Utility.logDebug(t.duration()); + queryRecord.updateLowerBoundAnswers(rlAnswer); + } finally { + if (rlAnswer != null) rlAnswer.dispose(); + } + queryRecord.addProcessingTime(Step.LowerBound, t.duration()); + rlAnswer = null; + + t.reset(); + BasicQueryEngine upperStore = queryRecord.isBottom() || lazyUpperStore == null ? trackingStore : lazyUpperStore; + + String[] extendedQuery = queryRecord.getExtendedQueryText(); + + queryUpperBound(upperStore, queryRecord, queryRecord.getQueryText(), queryRecord.getAnswerVariables()); + if (!queryRecord.processed() && !queryRecord.getQueryText().equals(extendedQuery[0])) + queryUpperBound(upperStore, queryRecord, extendedQuery[0], queryRecord.getAnswerVariables()); + if (!queryRecord.processed() && queryRecord.hasNonAnsDistinguishedVariables()) + queryUpperBound(upperStore, queryRecord, extendedQuery[1], queryRecord.getDistinguishedVariables()); + + queryRecord.addProcessingTime(Step.UpperBound, t.duration()); + if (queryRecord.processed()) { + queryRecord.setDifficulty(Step.UpperBound); + return null; + } + + t.reset(); + try { + elAnswer = elLowerStore.evaluate(extendedQuery[0], queryRecord.getAnswerVariables(), queryRecord.getLowerBoundAnswers()); + Utility.logDebug(t.duration()); + queryRecord.updateLowerBoundAnswers(elAnswer); + } finally { + if (elAnswer != null) elAnswer.dispose(); + } + queryRecord.addProcessingTime(Step.ELLowerBound, t.duration()); + + if (queryRecord.processed()) { + queryRecord.setDifficulty(Step.ELLowerBound); + return null; + } + + t.reset(); + + QueryTracker tracker = new QueryTracker(encoder, rlLowerStore, queryRecord); + + OWLOntology knowledgebase; + t.reset(); +// if (program.getGeneral().isHorn()) { +// knowledgebase = tracker.extract(lazyUpperStore, consistency.getQueryRecords(), true); +// queryRecord.addProcessingTime(Step.Fragment, t.duration()); +// return knowledgebase; +// } +// else { + knowledgebase = tracker.extract(trackingStore, consistency.getQueryRecords(), true); + queryRecord.addProcessingTime(Step.Fragment, t.duration()); +// } + + if (knowledgebase.isEmpty() || queryRecord.isBottom()) + return knowledgebase; + + if (program.getGeneral().isHorn()) return knowledgebase; + +// t.reset(); +// if (queryRecord.isHorn() && lazyUpperStore != null) { +//// knowledgebase = tracker.extract(lazyUpperStore, consistency.getQueryRecords(), true); +// } else if (queryRecord.getArity() < 3) { +// IterativeRefinement iterativeRefinement = new IterativeRefinement(queryRecord, tracker, trackingStore, consistency.getQueryRecords()); +// knowledgebase = iterativeRefinement.extractWithFullABox(importedData.toString(), program.getUpperBottomStrategy()); +// } +// +// queryRecord.addProcessingTime(Step.FragmentRefinement, t.duration()); +// +// if (knowledgebase == null) +// queryRecord.setDifficulty(Step.FragmentRefinement); + + return knowledgebase; + } + +// int counter = 0; + + private void queryUpperBound(BasicQueryEngine upperStore, QueryRecord queryRecord, String queryText, String[] answerVariables) { + AnswerTuples rlAnswer = null; + try { + Utility.logDebug(queryText); + rlAnswer = upperStore.evaluate(queryText, answerVariables); + Utility.logDebug(t.duration()); + queryRecord.updateUpperBoundAnswers(rlAnswer); + rlAnswer.dispose(); + } finally { + if (rlAnswer != null) rlAnswer.dispose(); + } + rlAnswer = null; + } + + @Override + public void evaluate(QueryRecord queryRecord) { + OWLOntology knowledgebase = relevantPart(queryRecord); + + if (knowledgebase == null) { + Utility.logDebug("Difficulty of this query: " + queryRecord.getDifficulty()); + return ; + } + + int aboxcount = knowledgebase.getABoxAxioms(true).size(); + Utility.logDebug("ABox axioms: " + aboxcount + " TBox axioms: " + (knowledgebase.getAxiomCount() - aboxcount)); +// queryRecord.saveRelevantOntology("fragment_query" + queryRecord.getQueryID() + ".owl"); + + Timer t = new Timer(); + Checker summarisedChecker = new HermitSummaryFilter(queryRecord); + int validNumber = summarisedChecker.check(queryRecord.getGapAnswers()); + summarisedChecker.dispose(); + Utility.logDebug("Total time for full reasoner: " + t.duration()); + if (!forSemFacet || validNumber == 0) { + queryRecord.markAsProcessed(); + Utility.logDebug("Difficulty of this query: " + queryRecord.getDifficulty()); + } + } + + @Override + public void evaluateUpper(QueryRecord queryRecord) { + AnswerTuples rlAnswer = null; + boolean useFull = queryRecord.isBottom() || lazyUpperStore == null; + try { + rlAnswer = (useFull ? trackingStore: lazyUpperStore).evaluate(queryRecord.getQueryText(), queryRecord.getAnswerVariables()); + queryRecord.updateUpperBoundAnswers(rlAnswer, true); + } finally { + if (rlAnswer != null) rlAnswer.dispose(); + } + } + + @Override + public void dispose() { + if (encoder != null) encoder.dispose(); + if (rlLowerStore != null) rlLowerStore.dispose(); + if (lazyUpperStore != null) lazyUpperStore.dispose(); + if (elLowerStore != null) elLowerStore.dispose(); + if (trackingStore != null) trackingStore.dispose(); + super.dispose(); + } + +} diff --git a/src/uk/ac/ox/cs/pagoda/reasoner/QueryEngine.java b/src/uk/ac/ox/cs/pagoda/reasoner/QueryEngine.java new file mode 100644 index 0000000..b9abf07 --- /dev/null +++ b/src/uk/ac/ox/cs/pagoda/reasoner/QueryEngine.java @@ -0,0 +1,17 @@ +package uk.ac.ox.cs.pagoda.reasoner; + +import java.util.Collection; + +import uk.ac.ox.cs.pagoda.query.AnswerTuples; + +public interface QueryEngine { + + public void evaluate(Collection queryTexts, String answerFile); + + public AnswerTuples evaluate(String queryText); + + public AnswerTuples evaluate(String queryText, String[] answerVariables); + + public void dispose(); + +} diff --git a/src/uk/ac/ox/cs/pagoda/reasoner/QueryReasoner.java b/src/uk/ac/ox/cs/pagoda/reasoner/QueryReasoner.java new file mode 100644 index 0000000..0c009a2 --- /dev/null +++ b/src/uk/ac/ox/cs/pagoda/reasoner/QueryReasoner.java @@ -0,0 +1,221 @@ +package uk.ac.ox.cs.pagoda.reasoner; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.util.Collection; + +import org.semanticweb.owlapi.model.OWLOntology; + +import uk.ac.ox.cs.pagoda.owl.OWLHelper; +import uk.ac.ox.cs.pagoda.query.AnswerTuples; +import uk.ac.ox.cs.pagoda.query.QueryManager; +import uk.ac.ox.cs.pagoda.query.QueryRecord; +import uk.ac.ox.cs.pagoda.util.Timer; +import uk.ac.ox.cs.pagoda.util.Utility; + +public abstract class QueryReasoner { + + protected boolean forSemFacet = false; + + public static enum Type { Full, RLU, ELHOU }; + + public static QueryReasoner getInstanceForSemFacet(OWLOntology o) { + QueryReasoner reasoner = getInstance(Type.Full, o, true, true); + reasoner.forSemFacet = true; + return reasoner; + } + + + public static QueryReasoner getInstance(OWLOntology o) { + return getInstance(Type.Full, o, true, true); + } + + public static QueryReasoner getInstance(Type type, OWLOntology o, boolean performMultiStages, boolean considerEqualities) { + Utility.initialise(); + QueryReasoner reasoner; + if (OWLHelper.isInOWL2RL(o)) reasoner = new RLQueryReasoner(); + else if (OWLHelper.isInELHO(o)) reasoner = new ELHOQueryReasoner(); + else + switch (type) { + case RLU: + reasoner = new RLUQueryReasoner(performMultiStages, considerEqualities); break; + case ELHOU: + reasoner = new ELHOUQueryReasoner(performMultiStages, considerEqualities); break; + default: + reasoner = new MyQueryReasoner(performMultiStages, considerEqualities); + } + return reasoner; + } + + public static final String ImportDataFileSeparator = ";"; + protected StringBuilder importedData = new StringBuilder(); + + public void importData(String datafile) { + if (datafile != null && !datafile.equalsIgnoreCase("null")) + importData(datafile.split(ImportDataFileSeparator)); + } + + public void importData(String[] datafiles) { + if (datafiles != null) { + for (String datafile: datafiles) { + File file = new File(datafile); + if (file.exists()) { + if (file.isFile()) importDataFile(file); + else importDataDirectory(file); + } + else { + Utility.logError("warning: file " + datafile + " doesn't exists."); + } + } + } + } + + private void importDataDirectory(File file) { + for (File child: file.listFiles()) + if (child.isFile()) importDataFile(child); + else importDataDirectory(child); + } + + private void importDataFile(File file) { + String datafile; + try { + datafile = file.getCanonicalPath(); + } catch (IOException e) { + e.printStackTrace(); + return ; + } + importDataFile(datafile); + } + + protected final void importDataFile(String datafile) { + if (importedData.length() == 0) + importedData.append(datafile); + else + importedData.append(ImportDataFileSeparator).append(datafile); + + } + + public abstract void loadOntology(OWLOntology ontology); + + public abstract boolean preprocess(); + + public abstract boolean isConsistent(); + + public boolean fullReasoner = this instanceof MyQueryReasoner; + + public abstract void evaluate(QueryRecord record); + + public abstract void evaluateUpper(QueryRecord record); + + public AnswerTuples evaluate(String queryText, boolean forFacetGeneration) { + if (forFacetGeneration) { + QueryRecord record = m_queryManager.create(queryText); + Utility.logInfo("---------- start evaluating upper bound for Query " + record.getQueryID() + " ----------", queryText); + if (!record.processed()) + evaluateUpper(record); +// AnswerTuples tuples = record.getUpperBoundAnswers(); +// for (AnswerTuple tuple; tuples.isValid(); tuples.moveNext()) { +// tuple = tuples.getTuple(); +// if (tuple.toString().contains("NC")) +// System.out.println(tuple.toString()); +// } + return record.getUpperBoundAnswers(); + } + else + return evaluate(queryText); + } + + public AnswerTuples evaluate(String queryText) { + QueryRecord record = m_queryManager.create(queryText); + Utility.logInfo("---------- start evaluating Query " + record.getQueryID() + " ----------", queryText); + if (!record.processed()) + evaluate(record); + AnswerTuples answer = record.getAnswers(); + record.dispose(); + return answer; + + } + + public void evaluate_shell(String queryText) { + QueryRecord record = m_queryManager.create(queryText); + Utility.logInfo("---------- start evaluating Query " + record.getQueryID() + " ----------", queryText); + if (!record.processed()) + evaluate(record); + Utility.logInfo("Answers to this query: ", record.outputSoundAnswerTuple()); + record.dispose(); + + } + + public void evaluate(Collection queryRecords) { + evaluate(queryRecords, null); + } + + BufferedWriter answerWriter = null; + + public void evaluate(Collection queryRecords, String answerFile) { + if (!isConsistent()) { + Utility.logDebug("The ontology and dataset is inconsistent."); + return ; + } + + if (answerWriter == null && answerFile != null) { + try { + answerWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(answerFile))); + } catch (FileNotFoundException e) { + Utility.logInfo("The answer file not found! " + answerFile); + return ; + } + } + + Timer t = new Timer(); + for (QueryRecord record: queryRecords) { +// if (Integer.parseInt(record.getQueryID()) != 218) continue; + Utility.logInfo("---------- start evaluating Query " + record.getQueryID() + " ----------", + record.getQueryText()); + if (!record.processed()) { + t.reset(); + if (!record.processed()) + evaluate(record); + Utility.logInfo("Total time to answer this query: " + t.duration()); + if (!fullReasoner && !record.processed()) { + Utility.logInfo("The query has not been fully answered in " + t.duration() + " seconds."); + continue; + } + } + // FIXME: change the argument below + try { + record.outputAnswers(answerWriter); + } catch (IOException e) { + Utility.logInfo("Error in outputing answers " + answerFile); + } + record.outputTimes(); + record.dispose(); + } + } + + public void dispose() { + if (answerWriter != null) + try { + answerWriter.close(); + } catch (IOException e) { + e.printStackTrace(); + } + Utility.cleanup(); + } + + private QueryManager m_queryManager = new QueryManager(); + + public QueryManager getQueryManager() { + return m_queryManager; + } + + + public static QueryReasoner getHermiTReasoner(boolean toCheckSatisfiability) { + return new HermiTReasoner(toCheckSatisfiability); + } + +} diff --git a/src/uk/ac/ox/cs/pagoda/reasoner/RLQueryReasoner.java b/src/uk/ac/ox/cs/pagoda/reasoner/RLQueryReasoner.java new file mode 100644 index 0000000..3894874 --- /dev/null +++ b/src/uk/ac/ox/cs/pagoda/reasoner/RLQueryReasoner.java @@ -0,0 +1,83 @@ +package uk.ac.ox.cs.pagoda.reasoner; + +import org.semanticweb.owlapi.model.OWLOntology; +import uk.ac.ox.cs.pagoda.constraints.UnaryBottom; +import uk.ac.ox.cs.pagoda.query.AnswerTuples; +import uk.ac.ox.cs.pagoda.query.QueryRecord; +import uk.ac.ox.cs.pagoda.query.QueryRecord.Step; +import uk.ac.ox.cs.pagoda.reasoner.light.BasicQueryEngine; +import uk.ac.ox.cs.pagoda.reasoner.light.RDFoxQueryEngine; +import uk.ac.ox.cs.pagoda.rules.LowerDatalogProgram; +import uk.ac.ox.cs.pagoda.util.Timer; + +public class RLQueryReasoner extends QueryReasoner { + + RDFoxQueryEngine rlLowerStore = null; + + LowerDatalogProgram program; + + public RLQueryReasoner() { + rlLowerStore = new BasicQueryEngine("rl"); + } + + Timer t = new Timer(); + + @Override + public void evaluate(QueryRecord queryRecord) { + AnswerTuples rlAnswer = null; + t.reset(); + try { + rlAnswer = rlLowerStore.evaluate(queryRecord.getQueryText(), queryRecord.getAnswerVariables()); + queryRecord.updateLowerBoundAnswers(rlAnswer); + } finally { + if (rlAnswer != null) rlAnswer.dispose(); + } + queryRecord.addProcessingTime(Step.LowerBound, t.duration()); + queryRecord.setDifficulty(Step.LowerBound); + queryRecord.markAsProcessed(); + } + + @Override + public void dispose() { + if (rlLowerStore != null) rlLowerStore.dispose(); + super.dispose(); + } + + @Override + public void loadOntology(OWLOntology ontology) { + program = new LowerDatalogProgram(); + program.load(ontology, new UnaryBottom()); + program.transform(); + + importData(program.getAdditionalDataFile()); + } + + @Override + public boolean preprocess() { + rlLowerStore.importRDFData("data", importedData.toString()); + rlLowerStore.materialise("lower program", program.toString()); + + if (!isConsistent()) + return false; + return true; + } + + @Override + public boolean isConsistent() { + AnswerTuples ans = null; + try { + ans = rlLowerStore.evaluate(QueryRecord.botQueryText, new String[] {"X"}); + return !ans.isValid(); + } finally { + if (ans != null) ans.dispose(); + + } + + } + + @Override + public void evaluateUpper(QueryRecord record) { + evaluate(record); + } + +} diff --git a/src/uk/ac/ox/cs/pagoda/reasoner/RLUQueryReasoner.java b/src/uk/ac/ox/cs/pagoda/reasoner/RLUQueryReasoner.java new file mode 100644 index 0000000..fe4022d --- /dev/null +++ b/src/uk/ac/ox/cs/pagoda/reasoner/RLUQueryReasoner.java @@ -0,0 +1,134 @@ +package uk.ac.ox.cs.pagoda.reasoner; + +import org.semanticweb.owlapi.model.OWLOntology; + +import uk.ac.ox.cs.pagoda.multistage.MultiStageQueryEngine; +import uk.ac.ox.cs.pagoda.owl.EqualitiesEliminator; +import uk.ac.ox.cs.pagoda.query.AnswerTuples; +import uk.ac.ox.cs.pagoda.query.QueryRecord; +import uk.ac.ox.cs.pagoda.query.QueryRecord.Step; +import uk.ac.ox.cs.pagoda.reasoner.light.BasicQueryEngine; +import uk.ac.ox.cs.pagoda.rules.DatalogProgram; +import uk.ac.ox.cs.pagoda.util.Timer; +import uk.ac.ox.cs.pagoda.util.Utility; + +public class RLUQueryReasoner extends QueryReasoner { + + DatalogProgram program; + + BasicQueryEngine rlLowerStore, rlUpperStore; + + boolean multiStageTag, equalityTag; + + public RLUQueryReasoner(boolean multiStageTag, boolean considerEqualities) { + this.multiStageTag = multiStageTag; + this.equalityTag = considerEqualities; + rlLowerStore = new BasicQueryEngine("rl-lower-bound"); + if (!multiStageTag) + rlUpperStore = new BasicQueryEngine("rl-upper-bound"); + else + rlUpperStore = new MultiStageQueryEngine("rl-upper-bound", false); + } + + Timer t = new Timer(); + + @Override + public void evaluate(QueryRecord queryRecord) { + AnswerTuples ans = null; + t.reset(); + try { + ans = rlLowerStore.evaluate(queryRecord.getQueryText(), queryRecord.getAnswerVariables()); + Utility.logDebug(t.duration()); + queryRecord.updateLowerBoundAnswers(ans); + } finally { + if (ans != null) ans.dispose(); + } + queryRecord.addProcessingTime(Step.LowerBound, t.duration()); + + ans = null; + t.reset(); + try { + ans = rlUpperStore.evaluate(queryRecord.getQueryText(), queryRecord.getAnswerVariables()); + Utility.logDebug(t.duration()); + queryRecord.updateUpperBoundAnswers(ans); + } finally { + if (ans != null) ans.dispose(); + } + queryRecord.addProcessingTime(Step.UpperBound, t.duration()); + + if (queryRecord.processed()) + queryRecord.setDifficulty(Step.UpperBound); + } + + @Override + public void evaluateUpper(QueryRecord queryRecord) { + AnswerTuples ans = null; + try { + ans = rlUpperStore.evaluate(queryRecord.getQueryText(), queryRecord.getAnswerVariables()); + Utility.logDebug(t.duration()); + queryRecord.updateUpperBoundAnswers(ans, true); + } finally { + if (ans != null) ans.dispose(); + } + } + + @Override + public void dispose() { + if (rlLowerStore != null) rlLowerStore.dispose(); + if (rlUpperStore != null) rlUpperStore.dispose(); + super.dispose(); + } + + @Override + public void loadOntology(OWLOntology o) { + if (!equalityTag) { + EqualitiesEliminator eliminator = new EqualitiesEliminator(o); + o = eliminator.getOutputOntology(); + eliminator.save(); + } + + OWLOntology ontology = o; + program = new DatalogProgram(ontology); + importData(program.getAdditionalDataFile()); + } + + @Override + public boolean preprocess() { + String datafile = importedData.toString(); + rlLowerStore.importRDFData("data", datafile); + rlLowerStore.materialise("lower program", program.getLower().toString()); + + rlUpperStore.importRDFData("data", datafile); + rlUpperStore.materialiseRestrictedly(program, null); + + if (!isConsistent()) + return false; + + return true; + } + + @Override + public boolean isConsistent() { + String[] X = new String[] { "X" }; + AnswerTuples ans = null; + try { + ans = rlLowerStore.evaluate(QueryRecord.botQueryText, X); + if (ans.isValid()) return false; + } finally { + if (ans != null) ans.dispose(); + } + + ans = null; + try { + ans = rlUpperStore.evaluate(QueryRecord.botQueryText, X); + if (!ans.isValid()) return true; + } finally { + if (ans != null) ans.dispose(); + } + + Utility.logDebug("The consistency of the data has not been determined yet."); + return true; + } + + +} diff --git a/src/uk/ac/ox/cs/pagoda/reasoner/full/Checker.java b/src/uk/ac/ox/cs/pagoda/reasoner/full/Checker.java new file mode 100644 index 0000000..849b971 --- /dev/null +++ b/src/uk/ac/ox/cs/pagoda/reasoner/full/Checker.java @@ -0,0 +1,15 @@ +package uk.ac.ox.cs.pagoda.reasoner.full; + +import uk.ac.ox.cs.pagoda.query.AnswerTuple; +import uk.ac.ox.cs.pagoda.query.AnswerTuples; + +public interface Checker { + + public int check(AnswerTuples answers); + + public boolean check(AnswerTuple answer); + + public boolean isConsistent(); + + public void dispose(); +} diff --git a/src/uk/ac/ox/cs/pagoda/reasoner/full/HermitChecker.java b/src/uk/ac/ox/cs/pagoda/reasoner/full/HermitChecker.java new file mode 100644 index 0000000..6f5d363 --- /dev/null +++ b/src/uk/ac/ox/cs/pagoda/reasoner/full/HermitChecker.java @@ -0,0 +1,237 @@ +package uk.ac.ox.cs.pagoda.reasoner.full; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.semanticweb.HermiT.Reasoner; +import org.semanticweb.HermiT.model.DLClause; +import org.semanticweb.HermiT.model.Term; +import org.semanticweb.HermiT.model.Variable; +import org.semanticweb.owlapi.model.IRI; +import org.semanticweb.owlapi.model.OWLAxiom; +import org.semanticweb.owlapi.model.OWLClassAssertionAxiom; +import org.semanticweb.owlapi.model.OWLDataFactory; +import org.semanticweb.owlapi.model.OWLDataPropertyAssertionAxiom; +import org.semanticweb.owlapi.model.OWLIndividual; +import org.semanticweb.owlapi.model.OWLObjectPropertyAssertionAxiom; +import org.semanticweb.owlapi.model.OWLOntology; +import org.semanticweb.owlapi.model.OWLOntologyManager; + +import uk.ac.ox.cs.pagoda.endomorph.Clique; +import uk.ac.ox.cs.pagoda.endomorph.DependencyGraph; +import uk.ac.ox.cs.pagoda.hermit.DLClauseHelper; +import uk.ac.ox.cs.pagoda.query.AnswerTuple; +import uk.ac.ox.cs.pagoda.query.AnswerTuples; +import uk.ac.ox.cs.pagoda.query.QueryRecord; +import uk.ac.ox.cs.pagoda.query.rollup.QueryGraph; +import uk.ac.ox.cs.pagoda.util.ConjunctiveQueryHelper; +import uk.ac.ox.cs.pagoda.util.Namespace; +import uk.ac.ox.cs.pagoda.util.Timer; +import uk.ac.ox.cs.pagoda.util.Utility; + +public class HermitChecker implements Checker { + + protected OWLDataFactory factory; + + private String queryText; + private DLClause queryClause; + + private Reasoner hermit; + protected String[][] answerVariable; + protected OWLOntology ontology; + protected QueryRecord record; + protected QueryGraph qGraph = null; + + public HermitChecker(Checker checker) { + if (checker instanceof HermitChecker) { + HermitChecker other = (HermitChecker) checker; + factory = other.factory; + queryText = other.queryText; + queryClause = other.queryClause; + answerVariable = other.answerVariable; + ontology = other.ontology; +// record = other.record; + } + + hermit = new Reasoner(ontology); + } + + public HermitChecker(OWLOntology ontology, QueryRecord record) { + this.ontology = ontology; + queryText = record.getQueryText(); + answerVariable = record.getVariables(); + queryClause = record.getClause(); +// this.record = record; + } + + public HermitChecker(OWLOntology ontology, String queryText) { + this.ontology = ontology; + this.queryText = queryText; + answerVariable = queryText == null ? null : ConjunctiveQueryHelper.getAnswerVariables(queryText); + queryClause = DLClauseHelper.getQuery(queryText, null); +// this.record = null; + } + + private int tag = 0; + AnswerTuple topAnswerTuple = null, botAnswerTuple = null; + + private void initialiseReasoner() { + qGraph = new QueryGraph(queryClause.getBodyAtoms(), answerVariable[1], ontology); + OWLOntologyManager manager = ontology.getOWLOntologyManager(); + factory = manager.getOWLDataFactory(); + + if (hermit != null) hermit.dispose(); + + if (dGraph != null && answerVariable[1].length == 1 && (dGraph.getExits().size() > 1 || dGraph.getEntrances().size() > 1)) { + Set axioms = new HashSet(); + addTopAndBotTuple(axioms); + manager.addAxioms(ontology, axioms); + hermit = new Reasoner(ontology); + if (!hermit.isConsistent()) { + hermit.dispose(); + manager.removeAxioms(ontology, axioms); + hermit = new Reasoner(ontology); + } else { + if (topAnswerTuple != null && !check(topAnswerTuple)) tag = -1; + else if (botAnswerTuple != null && check(botAnswerTuple)) tag = 1; + } + } + else + hermit = new Reasoner(ontology); + } + + private void addTopAndBotTuple(Set axioms) { + String top_str = Namespace.PAGODA_ANONY + "top", bot_str = Namespace.PAGODA_ANONY + "bot"; + topAnswerTuple = new AnswerTuple(new uk.ac.ox.cs.JRDFox.model.Individual[] { uk.ac.ox.cs.JRDFox.model.Individual.create(top_str) } ); + botAnswerTuple = new AnswerTuple(new uk.ac.ox.cs.JRDFox.model.Individual[] { uk.ac.ox.cs.JRDFox.model.Individual.create(bot_str) } ); + OWLIndividual top_ind = factory.getOWLNamedIndividual(IRI.create(top_str)), bot_ind = factory.getOWLNamedIndividual(IRI.create(bot_str)); + Map counter = new HashMap(); + + Set topAnswers = new HashSet(), botAnswers = new HashSet(); + OWLIndividual sub, obj; + if (dGraph.getExits().size() > 1) { + for (Clique answerClique: dGraph.getExits()) + topAnswers.add(((uk.ac.ox.cs.JRDFox.model.Individual) answerClique.getRepresentative().getAnswerTuple().getGroundTerm(0)).getIRI()); + } + else topAnswerTuple = null; + + if (dGraph.getEntrances().size() > 1) { + for (Clique answerClique: dGraph.getEntrances()) + botAnswers.add(((uk.ac.ox.cs.JRDFox.model.Individual) answerClique.getRepresentative().getAnswerTuple().getGroundTerm(0)).getIRI()); + } + else botAnswerTuple = null; + + for (OWLAxiom axiom: ontology.getABoxAxioms(true)) + if (axiom instanceof OWLClassAssertionAxiom) { + OWLClassAssertionAxiom ca = (OWLClassAssertionAxiom) axiom; + sub = ca.getIndividual(); + if (topAnswers.contains(sub.toStringID())) + axioms.add(factory.getOWLClassAssertionAxiom(ca.getClassExpression(), top_ind)); + if (botAnswers.contains(sub.toStringID())) + inc(counter, factory.getOWLClassAssertionAxiom(ca.getClassExpression(), bot_ind)); + } + else if (axiom instanceof OWLObjectPropertyAssertionAxiom) { + OWLObjectPropertyAssertionAxiom oa = (OWLObjectPropertyAssertionAxiom) axiom; + sub = oa.getSubject(); obj = oa.getObject(); + if (topAnswers.contains(sub.toStringID())) + if (topAnswers.contains(obj.toStringID())) + axioms.add(factory.getOWLObjectPropertyAssertionAxiom(oa.getProperty(), top_ind, top_ind)); + else + axioms.add(factory.getOWLObjectPropertyAssertionAxiom(oa.getProperty(), top_ind, obj)); + else { + if (topAnswers.contains(obj.toStringID())) + axioms.add(factory.getOWLObjectPropertyAssertionAxiom(oa.getProperty(), sub, top_ind)); + } + + if (botAnswers.contains(sub.toStringID())) + if (botAnswers.contains(obj.toStringID())) + inc(counter, factory.getOWLObjectPropertyAssertionAxiom(oa.getProperty(), bot_ind, bot_ind)); + else + inc(counter, factory.getOWLObjectPropertyAssertionAxiom(oa.getProperty(), bot_ind, obj)); + else { + if (botAnswers.contains(obj.toStringID())) + inc(counter, factory.getOWLObjectPropertyAssertionAxiom(oa.getProperty(), sub, bot_ind)); + } + + } + else if (axiom instanceof OWLDataPropertyAssertionAxiom) { + OWLDataPropertyAssertionAxiom da = (OWLDataPropertyAssertionAxiom) axiom; + sub = da.getSubject(); + if (topAnswers.contains(sub.toStringID())) + axioms.add(factory.getOWLDataPropertyAssertionAxiom(da.getProperty(), top_ind, da.getObject())); + + if (botAnswers.contains(sub.toStringID())) + inc(counter, factory.getOWLDataPropertyAssertionAxiom(da.getProperty(), bot_ind, da.getObject())); + } + + int number = botAnswers.size(); + for (Map.Entry entry: counter.entrySet()) { + if (entry.getValue() == number) + axioms.add(entry.getKey()); + } + } + + private void inc(Map counter, OWLAxiom newAxiom) { + Integer number = counter.get(newAxiom); + if (number == null) counter.put(newAxiom, 1); + else counter.put(newAxiom, number + 1); + } + + @Override + public int check(AnswerTuples answers) { + if (hermit == null) initialiseReasoner(); + int answerCounter = 0, counter = 0; + for (; answers.isValid(); answers.moveNext()) { + ++counter; + if (check(answers.getTuple())) ++answerCounter; + } + answers.dispose(); + + Utility.logDebug("The number of individuals to be checked by HermiT: " + counter, + "The number of correct answers: " + answerCounter); + return answerCounter; + } + + private int counter = 0; + + @Override + public boolean check(AnswerTuple answerTuple) { + if (hermit == null) initialiseReasoner(); + if (tag != 0) return tag == 1; + ++counter; + Timer t = new Timer(); + Map sub = answerTuple.getAssignment(answerVariable[1]); + Set toCheckAxioms = qGraph.getAssertions(sub); + +// for (OWLAxiom axiom: toCheckAxioms) System.out.println(axiom.toString()); + + if (hermit.isEntailed(toCheckAxioms)) { + Utility.logDebug("@TIME to check one tuple: " + t.duration()); + return true; + } + Utility.logDebug("@TIME to check one tuple: " + t.duration()); + return false; + } + + @Override + public boolean isConsistent() { + if (hermit == null) initialiseReasoner(); + return hermit.isConsistent(); + } + + + public void dispose() { + Utility.logInfo("Hermit was called " + counter + " times."); + if (hermit != null) hermit.dispose(); + hermit = null; + } + + private DependencyGraph dGraph = null; + + public void setDependencyGraph(DependencyGraph dGraph) { + this.dGraph = dGraph; + } + +} diff --git a/src/uk/ac/ox/cs/pagoda/reasoner/light/BasicQueryEngine.java b/src/uk/ac/ox/cs/pagoda/reasoner/light/BasicQueryEngine.java new file mode 100644 index 0000000..3207ff1 --- /dev/null +++ b/src/uk/ac/ox/cs/pagoda/reasoner/light/BasicQueryEngine.java @@ -0,0 +1,366 @@ +package uk.ac.ox.cs.pagoda.reasoner.light; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import org.semanticweb.HermiT.model.DLClause; + +import uk.ac.ox.cs.pagoda.hermit.DLClauseHelper; +import uk.ac.ox.cs.pagoda.query.AnswerTuples; +import uk.ac.ox.cs.pagoda.query.GapByStore4ID; +import uk.ac.ox.cs.pagoda.rules.DatalogProgram; +import uk.ac.ox.cs.pagoda.rules.Program; +import uk.ac.ox.cs.pagoda.util.ConjunctiveQueryHelper; +import uk.ac.ox.cs.pagoda.util.Namespace; +import uk.ac.ox.cs.pagoda.util.Timer; +import uk.ac.ox.cs.pagoda.util.UFS; +import uk.ac.ox.cs.pagoda.util.Utility; +import uk.ac.ox.cs.JRDFox.JRDFStoreException; +import uk.ac.ox.cs.JRDFox.store.DataStore; +import uk.ac.ox.cs.JRDFox.store.Parameters; +import uk.ac.ox.cs.JRDFox.store.TripleStatus; +import uk.ac.ox.cs.JRDFox.store.TupleIterator; +import uk.ac.ox.cs.JRDFox.store.DataStore.UpdateType; + +public class BasicQueryEngine extends RDFoxQueryEngine { + + protected DataStore store; + protected Parameters parameters = new Parameters(); + + public BasicQueryEngine(String name) { + super(name); + store = RDFoxQueryEngine.createDataStore(); + parameters.m_allAnswersInRoot = true; + parameters.m_useBushy = true; + } + + public void materialiseFoldedly(DatalogProgram dProgram, GapByStore4ID gap) { + if (gap != null) { + materialise("lower program", dProgram.getLower().toString()); + String program = dProgram.getUpper().toString(); + try { + gap.compile(program); + gap.addBackTo(); + getDataStore().clearRulesAndMakeFactsExplicit(); + } catch (JRDFStoreException e) { + e.printStackTrace(); + gap.clear(); + } finally { + } + } + else + materialise("upper program", dProgram.getUpper().toString()); + } + + public int materialiseRestrictedly(DatalogProgram dProgram, GapByStore4ID gap) { + if (gap != null) { + materialise("lower program", dProgram.getLower().toString()); + String program = dProgram.getUpper().toString(); + try { + gap.compile(program); + gap.addBackTo(); + getDataStore().clearRulesAndMakeFactsExplicit(); + } catch (JRDFStoreException e) { + e.printStackTrace(); + } finally { + gap.clear(); + } + } + else + materialise("upper program", dProgram.getUpper().toString()); + + return 1; + } + + @Override + public AnswerTuples evaluate(String queryText) { + return evaluate(queryText, ConjunctiveQueryHelper.getAnswerVariables(queryText)[0]); + } + + @Override + public AnswerTuples evaluate(String queryText, String[] answerVars) { + TupleIterator tupleIterator; + try { + tupleIterator = store.compileQuery(queryText.replace("_:", "?"), prefixes, parameters); + } catch (JRDFStoreException e) { + e.printStackTrace(); + return null; + } + return new RDFoxAnswerTuples(answerVars, tupleIterator); + } + + @Override + public DataStore getDataStore() { + return store; + } + + @Override + public void dispose() { + store.dispose(); + } + + protected void outputClassAssertions(String filename) { + TupleIterator allTuples = null; + boolean redirect = false; + try { + allTuples = getDataStore().compileQuery("SELECT ?X ?Z WHERE { ?X <" + Namespace.RDF_TYPE + "> ?Z }", prefixes, parameters); + redirect = Utility.redirectCurrentOut(filename); + for (long multi = allTuples.open(); multi != 0; multi = allTuples.getNext()) + System.out.println(RDFoxTripleManager.getQuotedTerm(allTuples.getResource(0)) + " " + RDFoxTripleManager.getQuotedTerm(allTuples.getResource(1))); + } catch (JRDFStoreException e) { + e.printStackTrace(); + } finally { + if (redirect) Utility.closeCurrentOut(); + if (allTuples != null) allTuples.dispose(); + } + } + + public void outputInstance4BinaryPredicate(String iri, String filename) { + Utility.redirectCurrentOut(filename); + outputInstance4BinaryPredicate(iri); + Utility.closeCurrentOut(); + } + + public void outputInstance4BinaryPredicate(String iri) { + outputAnswers("select ?x ?y where { ?x <" + iri + "> ?y . }"); + } + + public void outputInstanceNumbers(String filename) { + TupleIterator predicateTuples = null; + TupleIterator instanceTuples; + Set number = new HashSet(); + String predicate; + try { + predicateTuples = getDataStore().compileQuery("SELECT DISTINCT ?Y WHERE { ?X <" + Namespace.RDF_TYPE + "> ?Y }", prefixes, parameters); + for (long multi = predicateTuples.open(); multi != 0; multi = predicateTuples.getNext()) { + predicate = RDFoxTripleManager.getQuotedTerm(predicateTuples.getResource(0)); + instanceTuples = null; + try { + instanceTuples = getDataStore().compileQuery("SELECT ?X WHERE { ?X <" + Namespace.RDF_TYPE + "> " + predicate + " }", prefixes, parameters); + long totalCount = 0; + for (long multi1 = instanceTuples.open(); multi1 != 0; multi1 = instanceTuples.getNext()) { + totalCount += instanceTuples.getMultiplicity(); + } + number.add(predicate + " * " + totalCount); + } finally { + if (instanceTuples != null) instanceTuples.dispose(); + } + } + + predicateTuples.dispose(); + + predicateTuples = getDataStore().compileQuery("SELECT DISTINCT ?Y WHERE { ?X ?Y ?Z }", prefixes, parameters); + for (long multi = predicateTuples.open(); multi != 0; multi = predicateTuples.getNext()) { + predicate = RDFoxTripleManager.getQuotedTerm(predicateTuples.getResource(0)); + instanceTuples = null; + try { + instanceTuples = getDataStore().compileQuery("SELECT ?X ?Z WHERE { ?X " + predicate + " ?Z }", prefixes, parameters); + ; + long totalCount = 0; + for (long multi1 = instanceTuples.open(); multi1 != 0; multi1 = instanceTuples.getNext()) + totalCount += instanceTuples.getMultiplicity(); + number.add(predicate + " * " + totalCount); + } finally { + if (instanceTuples != null) instanceTuples.dispose(); + } + } + + } catch (JRDFStoreException e) { + e.printStackTrace(); + } finally { + if (predicateTuples != null) predicateTuples.dispose(); + } + + Utility.redirectCurrentOut(filename); + String[] ordered = number.toArray(new String[0]); + Arrays.sort(ordered, new DLPredicateComparator()); + for (String line: ordered) System.out.println(line); + Utility.closeCurrentOut(); + + } + + public TupleIterator internal_evaluateAgainstIDBs(String queryText) throws JRDFStoreException { + TupleIterator iter = store.compileQuery(queryText, prefixes, parameters, TripleStatus.TUPLE_STATUS_IDB.union(TripleStatus.TUPLE_STATUS_EDB), TripleStatus.TUPLE_STATUS_IDB); + iter.open(); + return iter; + } + + public TupleIterator internal_evaluate(String queryText) throws JRDFStoreException { + TupleIterator iter = store.compileQuery(queryText, prefixes, parameters); + iter.open(); + return iter; + } + + public void setExpandEquality(boolean flag) { + parameters.m_expandEquality = flag; + } + + public TupleIterator internal_evaluateNotExpanded(String queryText) throws JRDFStoreException { + parameters.m_expandEquality = false; + TupleIterator iter = store.compileQuery(queryText, prefixes, parameters); + iter.open(); + parameters.m_expandEquality = true; + return iter; + } + + + public TupleIterator internal_evaluate(String queryText, boolean incrementally) throws JRDFStoreException { + return incrementally ? internal_evaluateAgainstIDBs(queryText) : internal_evaluate(queryText); + } + + Set materialisedRules = new HashSet(); + + public String getUnusedRules(Collection clauses, boolean toUpdate) { + DLClause clause; + for (Iterator iter = clauses.iterator(); iter.hasNext(); ) { + if (materialisedRules.contains(clause = iter.next())) + iter.remove(); + else if (toUpdate) materialisedRules.add(clause); + } + + if (clauses.isEmpty()) return null; + + return Program.toString(clauses); + } + + public void outputMaterialisedRules() { + System.out.println(DLClauseHelper.toString(materialisedRules)); + } + + public void outputAnswers(String query) { + TupleIterator iter = null; + try { + iter = internal_evaluate(query); + System.out.println(query); + int arity = iter.getArity(); + for (long multi = iter.open(); multi != 0; multi = iter.getNext()) { + for (int i = 0; i < arity; ++i) + System.out.print(RDFoxTripleManager.getQuotedTerm(iter.getResource(i)) + "\t"); + System.out.println(); + } + } catch (JRDFStoreException e) { + e.printStackTrace(); + } finally { + if (iter != null) iter.dispose(); + } + } + + public void outputInstance4UnaryPredicate(String iri) { + outputAnswers("select ?x where { ?x " + + " <" + + iri + + "> .}"); + } + + public void outputSubjects(String p, String o) { + outputAnswers("select x where { ?x <" + p + "> <" + o + "> . }"); + } + + public void outputObjects(String s, String p) { + outputAnswers("select ?x where { <" + s + "> <" + p + "> ?x . }"); + } + + public void outputIDBFacts() { + TupleIterator iter = null; + try { + iter = internal_evaluateAgainstIDBs("select distict ?x ?y ?z where { ?x ?y ?z }"); + for (long multi = iter.open(); multi != 0; multi = iter.getNext()) { + for (int i = 0; i < 3; ++i) + System.out.print(RDFoxTripleManager.getQuotedTerm(iter.getResource(i)) + "\t"); + System.out.println(); + } + } catch (JRDFStoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } finally { + if (iter != null) iter.dispose(); + } + + } + + public void outputType4Individual(String iri) { + outputAnswers("select ?z where { <" + iri + "> " + Namespace.RDF_TYPE_QUOTED + " ?z }"); + } + + public int getSameAsNumber() { + TupleIterator iter = null; + int counter = 0; + try { + iter = internal_evaluate("select ?x ?y where {?x " + Namespace.EQUALITY_QUOTED + " ?y . }"); + for (long multi = iter.open(); multi != 0; multi = iter.getNext()) + if (iter.getResourceID(0) != iter.getResourceID(1)) + ++counter; + } catch (JRDFStoreException e) { + e.printStackTrace(); + } finally { + if (iter != null) iter.dispose(); + } + return counter; + } + + private UFS equalityGroups = null; + + public UFS getEqualityGroups() { + if (equalityGroups != null) return equalityGroups; + + equalityGroups = new UFS(); + + TupleIterator answers = null; + try { + Timer t = new Timer(); + answers = internal_evaluate("select ?x ?z where {?x " + Namespace.EQUALITY_QUOTED + "?z . }"); + for (long multi = answers.open(); multi != 0; multi = answers.getNext()) { + if (answers.getResourceID(0) != answers.getResourceID(1)) + equalityGroups.merge(answers.getResource(0).m_lexicalForm, answers.getResource(1).m_lexicalForm); + } + Utility.logInfo("@Time to group individuals by equality: " + t.duration()); + } catch (JRDFStoreException e) { + e.printStackTrace(); + } finally { + if (answers != null) answers.dispose(); + } + + return equalityGroups; + } + + public void clearRulesAndIDBFacts(Collection collection) { +// performDeletion(collection); + collection.clear(); + try { + store.clearRulesAndMakeFactsExplicit(); + } catch (JRDFStoreException e) { + e.printStackTrace(); + } + } + + @SuppressWarnings("unused") + private void performDeletion(Collection collection) { + Utility.logInfo("Remove all rules, idb facts and added staff..."); + Timer timer = new Timer(); + TupleIterator iter = null; + try { + UpdateType ut = UpdateType.ScheduleForDeletion; + for (int[] t: collection) + store.addTriplesByResourceIDs(t, ut); + + iter = internal_evaluateAgainstIDBs("select ?x ?y ?z where { ?x ?y ?z . }"); + for (long multi = iter.open(); multi != 0; multi = iter.getNext()) { + int[] triple = new int[3]; + for (int i = 0; i < 3; ++i) + triple[i] = iter.getResourceID(i); + store.addTriplesByResourceIDs(triple, ut); + } + store.applyReasoning(true); + } catch (JRDFStoreException e) { + e.printStackTrace(); + } finally { + if (iter != null) iter.dispose(); + } + Utility.logInfo("Time for deletion: " + timer.duration()); + } + + +} diff --git a/src/uk/ac/ox/cs/pagoda/reasoner/light/DLPredicateComparator.java b/src/uk/ac/ox/cs/pagoda/reasoner/light/DLPredicateComparator.java new file mode 100644 index 0000000..c22902c --- /dev/null +++ b/src/uk/ac/ox/cs/pagoda/reasoner/light/DLPredicateComparator.java @@ -0,0 +1,24 @@ +package uk.ac.ox.cs.pagoda.reasoner.light; + +import java.util.Comparator; + +import uk.ac.ox.cs.pagoda.multistage.Normalisation; +import uk.ac.ox.cs.pagoda.rules.OverApproxExist; + +public class DLPredicateComparator implements Comparator { + + @Override + public int compare(String arg0, String arg1) { + int ret = type(arg0) - type(arg1); + if (ret != 0) return ret; + + return arg0.compareTo(arg1); + } + + private int type(String p) { + if (p.contains(OverApproxExist.negativeSuffix)) return 1; + if (p.contains(Normalisation.auxiliaryConceptPrefix)) return 2; + else return 0; + } + +} diff --git a/src/uk/ac/ox/cs/pagoda/reasoner/light/KarmaQuery.java b/src/uk/ac/ox/cs/pagoda/reasoner/light/KarmaQuery.java new file mode 100644 index 0000000..03d2b67 --- /dev/null +++ b/src/uk/ac/ox/cs/pagoda/reasoner/light/KarmaQuery.java @@ -0,0 +1,95 @@ +package uk.ac.ox.cs.pagoda.reasoner.light; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.LinkedList; +import java.util.Map.Entry; + +import org.semanticweb.HermiT.model.DLClause; +import org.semanticweb.karma2.exception.IllegalInputQueryException; +import org.semanticweb.karma2.model.ConjunctiveQuery; +import org.semanticweb.karma2.model.cqparser.ConjunctiveQueryParser; +import uk.ac.ox.cs.pagoda.MyPrefixes; +import uk.ac.ox.cs.pagoda.hermit.DLClauseHelper; +import uk.ac.ox.cs.pagoda.hermit.RuleHelper; +import uk.ac.ox.cs.pagoda.util.Utility; + +public class KarmaQuery { + + StringBuffer queryBuffer; + + public KarmaQuery(String queryText) { + LinkedList answerVariables = new LinkedList(); + DLClause clause = DLClauseHelper.getQuery(queryText, answerVariables); + String clauseText = RuleHelper.getText(clause); +// clauseText = RuleHelper.abbreviateIRI(clauseText).replace(":-", "<-"); + clauseText = clauseText.replace(":-", "<-"); + queryBuffer = new StringBuffer(); + + clauseText = expandIRI4Arguments(clauseText); + + for (Entry entry : MyPrefixes.PAGOdAPrefixes.getPrefixIRIsByPrefixName().entrySet()) + if (clauseText.contains(entry.getKey())) { + if (queryBuffer.length() > 0) queryBuffer.append(',').append(Utility.LINE_SEPARATOR); + queryBuffer.append("prefix ").append(entry.getKey()).append(" <").append(entry.getValue()).append(">"); + } + if (queryBuffer.length() > 0) queryBuffer.append(Utility.LINE_SEPARATOR); + + queryBuffer.append("p("); + boolean first = true; + for (String var: answerVariables) { + if (first) first = false; + else queryBuffer.append(","); + + queryBuffer.append("?").append(var); + } + queryBuffer.append(")").append(clauseText.substring(0, clauseText.length() - 1)); + } + + private String expandIRI4Arguments(String clauseText) { + int leftIndex = clauseText.indexOf('('), rightIndex = clauseText.indexOf(')', leftIndex + 1); + String argsText, newArgsText; + while (leftIndex != -1) { + argsText = clauseText.substring(leftIndex + 1, rightIndex); + newArgsText = MyPrefixes.PAGOdAPrefixes.expandText(argsText); + clauseText = clauseText.replace(argsText, newArgsText); + + rightIndex += newArgsText.length() - argsText.length(); + leftIndex = clauseText.indexOf('(', rightIndex + 1); + rightIndex = clauseText.indexOf(')', leftIndex + 1); + } + + return clauseText; + } + + public ConjunctiveQuery getConjunctiveQuery() { + ConjunctiveQuery cq = null; + try { + cq = new ConjunctiveQueryParser(toString()).parse(); + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IllegalInputQueryException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (Exception e) { + Utility.logDebug("The query cannot be properly handled by KARMA."); + return null; + } + return cq; + } + + @Override + public String toString() { + return queryBuffer.toString(); + } + + static String sample = "prefix P0: , " + + "prefix rdf: , " + + "prefix owl: " + + "q(?0) <- owl:Thing(?0), P0:Person(?0)"; + +} diff --git a/src/uk/ac/ox/cs/pagoda/reasoner/light/KarmaQueryEngine.java b/src/uk/ac/ox/cs/pagoda/reasoner/light/KarmaQueryEngine.java new file mode 100644 index 0000000..f70dde9 --- /dev/null +++ b/src/uk/ac/ox/cs/pagoda/reasoner/light/KarmaQueryEngine.java @@ -0,0 +1,98 @@ +package uk.ac.ox.cs.pagoda.reasoner.light; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.*; + +import org.semanticweb.karma2.*; +import org.semanticweb.karma2.clausifier.OntologyProcesser; +import org.semanticweb.karma2.exception.IllegalInputOntologyException; +import org.semanticweb.karma2.model.ConjunctiveQuery; +import org.semanticweb.owlapi.model.OWLOntology; + +import uk.ac.ox.cs.pagoda.query.*; +import uk.ac.ox.cs.pagoda.util.ConjunctiveQueryHelper; +import uk.ac.ox.cs.pagoda.util.Utility; +import uk.ac.ox.cs.JRDFox.JRDFStoreException; +import uk.ac.ox.cs.JRDFox.store.DataStore; + +public class KarmaQueryEngine extends RDFoxQueryEngine { + + private MyKarma reasoner = null; + + String karmaDataFile = null, karmaRuleFile = null; + + public KarmaQueryEngine(String name) { + super(name); + +// int Base = 1 << 6; +// int index = (new Random().nextInt() % Base + Base) % Base; +// karmaDataFile = "karma_data" + index + ".ttl"; +// karmaRuleFile = "karma_rule" + index + ".dlog"; + karmaDataFile = Utility.TempDirectory + "karma_data.ttl"; + karmaRuleFile = Utility.TempDirectory + "karma_rule.dlog"; + + reasoner = new MyKarma(); + } + + public MyKarma getReasoner() { + return reasoner; + } + + public void processOntology(OWLOntology elhoOntology) { + try { + OntologyProcesser.transformOntology(elhoOntology, new File(karmaDataFile), new File(karmaRuleFile)); + } catch (IllegalInputOntologyException e) { + e.printStackTrace(); + } + } + + @Override + public void dispose() { + reasoner.dispose(); + } + + @Override + public AnswerTuples evaluate(String queryText) { + return evaluate(queryText, ConjunctiveQueryHelper.getAnswerVariables(queryText)[0], null); + } + + @Override + public AnswerTuples evaluate(String queryText, String[] answerVars) { + return evaluate(queryText, answerVars, null); + } + + public AnswerTuples evaluate(String queryText, AnswerTuples soundAnswerTuples) { + return evaluate(queryText, ConjunctiveQueryHelper.getAnswerVariables(queryText)[0], soundAnswerTuples); + } + + public AnswerTuples evaluate(String queryText, String[] answerVars, AnswerTuples soundAnswerTuples) { + KarmaQuery karmaQuery = new KarmaQuery(queryText.replace("_:", "?")); + reasoner.setConcurrence(false); + ConjunctiveQuery cq = karmaQuery.getConjunctiveQuery(); + if (cq == null) return null; + Set answers = reasoner.answerCQ(cq, soundAnswerTuples, !queryText.contains("_:")); + return new AnswerTuplesImp(answerVars, answers); + } + + @Override + public DataStore getDataStore() { + return reasoner.getStore(); + } + + public void initialiseKarma() { + try { + reasoner.initializeData(new File(karmaDataFile)); + reasoner.materialise(new File(karmaRuleFile)); + + File tmp; + if (karmaDataFile != null && ((tmp = new File(karmaDataFile)).exists())) tmp.delete(); + if (karmaRuleFile != null && ((tmp = new File(karmaRuleFile)).exists())) tmp.delete(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (JRDFStoreException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/uk/ac/ox/cs/pagoda/reasoner/light/RDFoxAnswerTuples.java b/src/uk/ac/ox/cs/pagoda/reasoner/light/RDFoxAnswerTuples.java new file mode 100644 index 0000000..dd71809 --- /dev/null +++ b/src/uk/ac/ox/cs/pagoda/reasoner/light/RDFoxAnswerTuples.java @@ -0,0 +1,100 @@ +package uk.ac.ox.cs.pagoda.reasoner.light; + +import org.semanticweb.HermiT.model.Constant; +import org.semanticweb.HermiT.model.Individual; +import org.semanticweb.HermiT.model.Term; + +import uk.ac.ox.cs.pagoda.query.AnswerTuple; +import uk.ac.ox.cs.pagoda.query.AnswerTuples; +import uk.ac.ox.cs.pagoda.util.Utility; +import uk.ac.ox.cs.JRDFox.JRDFStoreException; +import uk.ac.ox.cs.JRDFox.model.GroundTerm; +import uk.ac.ox.cs.JRDFox.store.TupleIterator; + +public class RDFoxAnswerTuples implements AnswerTuples { + + long multi; + TupleIterator m_iter; + String[] m_answerVars; + + public RDFoxAnswerTuples(String[] answerVars, TupleIterator iter) { + m_answerVars = answerVars; + m_iter = iter; + reset(); + } + + @Override + public boolean isValid() { + return multi != 0; + } + + @Override + public int getArity() { + try { + return m_iter.getArity(); + } catch (JRDFStoreException e) { + e.printStackTrace(); + return -1; + } + } + + @Override + public void moveNext() { + try { + multi = m_iter.getNext(); + } catch (JRDFStoreException e) { + e.printStackTrace(); + } + } + + @Override + public void dispose() { + m_iter.dispose(); + } + + protected void finalize() { + m_iter.dispose(); + } + + @Override + public AnswerTuple getTuple() { + return new AnswerTuple(m_iter, m_answerVars.length); + } + + @Override + public void reset() { + try { + multi = m_iter.open(); + } catch (JRDFStoreException e) { + e.printStackTrace(); + } + } + + @Override + public boolean contains(AnswerTuple t) { + Utility.logError("Unsupported operation in RDFoxAnswerTuples"); + return false; + } + + @Override + public void remove() { + Utility.logError("Unsupported operation in RDFoxAnswerTuples"); + } + + @Override + public String[] getAnswerVariables() { + return m_answerVars; + } + + public static Term getHermitTerm(GroundTerm t) { + if (t instanceof uk.ac.ox.cs.JRDFox.model.Individual) { + uk.ac.ox.cs.JRDFox.model.Individual individual = (uk.ac.ox.cs.JRDFox.model.Individual) t; + return Individual.create(individual.getIRI()); + } + else { + uk.ac.ox.cs.JRDFox.model.Literal literal = ((uk.ac.ox.cs.JRDFox.model.Literal) t); + return Constant.create(literal.getLexicalForm(), literal.getDatatype().getIRI()); + } + } + +} diff --git a/src/uk/ac/ox/cs/pagoda/reasoner/light/RDFoxQueryEngine.java b/src/uk/ac/ox/cs/pagoda/reasoner/light/RDFoxQueryEngine.java new file mode 100644 index 0000000..30771ab --- /dev/null +++ b/src/uk/ac/ox/cs/pagoda/reasoner/light/RDFoxQueryEngine.java @@ -0,0 +1,110 @@ +package uk.ac.ox.cs.pagoda.reasoner.light; + +import java.io.File; +import java.util.Collection; + +import uk.ac.ox.cs.pagoda.MyPrefixes; +import uk.ac.ox.cs.pagoda.query.AnswerTuples; +import uk.ac.ox.cs.pagoda.reasoner.QueryEngine; +import uk.ac.ox.cs.pagoda.reasoner.QueryReasoner; +import uk.ac.ox.cs.pagoda.tracking.AnswerTuplesWriter; +import uk.ac.ox.cs.pagoda.util.Timer; +import uk.ac.ox.cs.pagoda.util.Utility; +import uk.ac.ox.cs.JRDFox.JRDFStoreException; +import uk.ac.ox.cs.JRDFox.Prefixes; +import uk.ac.ox.cs.JRDFox.store.DataStore; +import uk.ac.ox.cs.JRDFox.store.DataStore.StoreType; + +public abstract class RDFoxQueryEngine implements QueryEngine { + + public static final int matNoOfThreads = Runtime.getRuntime().availableProcessors() * 2; + + protected String name; + protected Prefixes prefixes = MyPrefixes.PAGOdAPrefixes.getRDFoxPrefixes(); + + public RDFoxQueryEngine(String name) { + this.name = name; + } + + public abstract DataStore getDataStore(); + + public abstract void dispose(); + + public void importRDFData(String fileName, String importedFile) { + if (importedFile == null || importedFile.isEmpty()) return ; + Timer t = new Timer(); + DataStore store = getDataStore(); + try { + long oldTripleCount = store.getTriplesCount(), tripleCount; + for (String file: importedFile.split(QueryReasoner.ImportDataFileSeparator)) + store.importTurtleFile(new File(file), prefixes); + tripleCount = store.getTriplesCount(); + Utility.logDebug(name + " store after importing " + fileName + ": " + tripleCount + " (" + (tripleCount - oldTripleCount) + " new)"); + store.clearRulesAndMakeFactsExplicit(); + } catch (JRDFStoreException e) { + e.printStackTrace(); + } + Utility.logDebug(name + " store finished importing " + fileName + " in " + t.duration() + " seconds."); + } + + public void materialise(String programName, String programText) { + if (programText == null) return ; + Timer t = new Timer(); + DataStore store = getDataStore(); + try { + long oldTripleCount = store.getTriplesCount(), tripleCount; +// store.addRules(new String[] {programText}); + store.importRules(programText); + store.applyReasoning(); + tripleCount = store.getTriplesCount(); + Utility.logDebug(name + " store after materialising " + programName + ": " + tripleCount + " (" + (tripleCount - oldTripleCount) + " new)"); + store.clearRulesAndMakeFactsExplicit(); + } catch (JRDFStoreException e) { + e.printStackTrace(); + } + Utility.logDebug(name + " store finished the materialisation of " + programName + " in " + t.duration() + " seconds."); + } + + @Override + public void evaluate(Collection queryTexts, String answerFile) { + if (queryTexts == null) + return ; + + int queryID = 0; + AnswerTuplesWriter answerWriter = new AnswerTuplesWriter(answerFile); + AnswerTuples answerTuples; + Timer t = new Timer(); + try { + for (String query: queryTexts) { + t.reset(); + answerTuples = null; + try { + answerTuples = evaluate(query); + Utility.logDebug("time to answer Query " + ++queryID + ": " + t.duration()); + answerWriter.write(answerTuples.getAnswerVariables(), answerTuples); + } finally { + if (answerTuples != null) answerTuples.dispose(); + } + } + } finally { + answerWriter.close(); + } + + Utility.logDebug("done computing query answers by RDFox."); + + } + + public static DataStore createDataStore() { + DataStore instance = null; + try { +// instance = new DataStore("par-head-n"); + instance = new DataStore(StoreType.NarrowParallelHead); + instance.setNumberOfThreads(matNoOfThreads); + instance.initialize(); + } catch (JRDFStoreException e) { + e.printStackTrace(); + } + return instance; + } + +} diff --git a/src/uk/ac/ox/cs/pagoda/reasoner/light/RDFoxTripleManager.java b/src/uk/ac/ox/cs/pagoda/reasoner/light/RDFoxTripleManager.java new file mode 100644 index 0000000..2280b12 --- /dev/null +++ b/src/uk/ac/ox/cs/pagoda/reasoner/light/RDFoxTripleManager.java @@ -0,0 +1,249 @@ +package uk.ac.ox.cs.pagoda.reasoner.light; + +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Map; +import java.util.Queue; +import java.util.Set; + +import org.semanticweb.HermiT.model.AnnotatedEquality; +import org.semanticweb.HermiT.model.Atom; +import org.semanticweb.HermiT.model.AtomicConcept; +import org.semanticweb.HermiT.model.AtomicRole; +import org.semanticweb.HermiT.model.Constant; +import org.semanticweb.HermiT.model.DLPredicate; +import org.semanticweb.HermiT.model.Equality; +import org.semanticweb.HermiT.model.Individual; +import org.semanticweb.HermiT.model.Inequality; +import org.semanticweb.HermiT.model.Term; +import org.semanticweb.HermiT.model.Variable; + +import uk.ac.ox.cs.pagoda.owl.OWLHelper; +import uk.ac.ox.cs.pagoda.util.Namespace; +import uk.ac.ox.cs.JRDFox.JRDFStoreException; +import uk.ac.ox.cs.JRDFox.model.GroundTerm; +import uk.ac.ox.cs.JRDFox.store.DataStore; +import uk.ac.ox.cs.JRDFox.model.Datatype; +import uk.ac.ox.cs.JRDFox.store.Dictionary; +import uk.ac.ox.cs.JRDFox.store.DataStore.UpdateType; +import uk.ac.ox.cs.JRDFox.store.Resource; + +public class RDFoxTripleManager { + + UpdateType m_incrementally; +// boolean m_incrementally; + + DataStore m_store; + Dictionary m_dict; + Set triplesByTerm = new HashSet(); + + public RDFoxTripleManager(DataStore store, boolean incrementally) { + m_store = store; +// m_incrementally = incrementally; + if (incrementally) + m_incrementally = UpdateType.ScheduleForAddition; + else + m_incrementally = UpdateType.Add; + + try { + m_dict = store.getDictionary(); + resourceID = m_dict.resolveResources( + new String[] {Namespace.RDF_TYPE, Namespace.EQUALITY, Namespace.INEQUALITY}, + new int[] {Datatype.IRI_REFERENCE.value(), Datatype.IRI_REFERENCE.value(), Datatype.IRI_REFERENCE.value()} + ); + } catch (JRDFStoreException e) { + e.printStackTrace(); + } + } + + public boolean isRdfTypeID(int id) { + return id == resourceID[0]; + } + + public void addTripleByID(int[] tuple) { + try { + m_store.addTriplesByResourceIDs(tuple, m_incrementally); + } catch (JRDFStoreException e) { + e.printStackTrace(); + } + } + + public void addTripleByTerm(Atom atom) { + try { + m_store.addTriples(getRDFoxTriple(atom), m_incrementally); + } catch (JRDFStoreException e) { + e.printStackTrace(); + } + } + + public static GroundTerm[] getRDFoxTriple(Atom instance) { + if (instance.getArity() == 1) + return new GroundTerm[] { + uk.ac.ox.cs.JRDFox.model.Individual.create(((Individual) instance.getArgument(0)).getIRI()), + uk.ac.ox.cs.JRDFox.model.Individual.RDF_TYPE, + uk.ac.ox.cs.JRDFox.model.Individual.create(((AtomicConcept) instance.getDLPredicate()).getIRI()) }; + else if (instance.getDLPredicate() instanceof Equality || instance.getDLPredicate() instanceof AnnotatedEquality) + return new GroundTerm[] { + uk.ac.ox.cs.JRDFox.model.Individual.create(((Individual) instance.getArgument(0)).getIRI()), + uk.ac.ox.cs.JRDFox.model.Individual.SAME_AS, + uk.ac.ox.cs.JRDFox.model.Individual.create(((Individual) instance.getArgument(1)).getIRI()) }; + else if (instance.getDLPredicate() instanceof Inequality) + return new GroundTerm[] { + uk.ac.ox.cs.JRDFox.model.Individual.create(((Individual) instance.getArgument(0)).getIRI()), + uk.ac.ox.cs.JRDFox.model.Individual.DIFFERENT_FROM, + uk.ac.ox.cs.JRDFox.model.Individual.create(((Individual) instance.getArgument(1)).getIRI()) }; + else + return new GroundTerm[] { + uk.ac.ox.cs.JRDFox.model.Individual.create(((Individual) instance.getArgument(0)).getIRI()), + uk.ac.ox.cs.JRDFox.model.Individual.create(((AtomicRole) instance.getDLPredicate()).getIRI()), + uk.ac.ox.cs.JRDFox.model.Individual.create(((Individual) instance.getArgument(1)).getIRI()) }; + } + + int[] resourceID; // rdf:type, owl:sameAs, owl:differentFrom + + public int[] getInstance(Atom atom, Map assignment) { + DLPredicate p = atom.getDLPredicate(); + if (p instanceof Equality || p instanceof AnnotatedEquality) + return new int[] { + getResourceID(atom.getArgument(0), assignment), + resourceID[1], + getResourceID(atom.getArgument(1), assignment) + }; + else if (p instanceof Inequality) + return new int[] { + getResourceID(atom.getArgument(0), assignment), + resourceID[2], + getResourceID(atom.getArgument(1), assignment) + }; + else if (atom.getArity() == 1) + return new int[] { + getResourceID(atom.getArgument(0), assignment), + resourceID[0], + getResourceID(p) + }; + else + return new int[] { + getResourceID(atom.getArgument(0), assignment), + getResourceID(p), + getResourceID(atom.getArgument(1), assignment) + }; + } + + public String getRawTerm(int id) { + Resource[] res = new Resource[1]; + try { + m_dict.getResources(new int[] {id}, 0, 1, res); + } catch (JRDFStoreException e) { + e.printStackTrace(); + } + return getQuotedTerm(res[0]); + } + + Map predicateCache = new HashMap(); + + public int getResourceID(DLPredicate p) { + Integer id; + String name = p instanceof AtomicConcept ? ((AtomicConcept) p).getIRI() : ((AtomicRole) p).getIRI(); + if ((id = predicateCache.get(name)) != null) return id; + try { + predicateCache.put(name, id = resolveResource(name, Datatype.IRI_REFERENCE.value())); + + } catch (JRDFStoreException e) { + e.printStackTrace(); + } + return id; + } + + public int getResourceID(String name) { + Integer id = null; + try { + id = resolveResource(name, Datatype.IRI_REFERENCE.value()); + } catch (JRDFStoreException e) { + e.printStackTrace(); + } + return id; + } + + private int resolveResource(String name, int type) throws JRDFStoreException { + String[] lexicalForms = new String[] {name}; + int[] types = new int[] {type}; + return m_dict.resolveResources(lexicalForms, types)[0]; + } + + Map termCache = new HashMap(); + Queue termList = new LinkedList(); + int sizeLimit = 10000; + + private int getResourceID(Term arg, Map assignment) { + while (termCache.size() > sizeLimit) + termCache.remove(termList.poll()); + + if (arg instanceof Variable) return assignment.get((Variable) arg); + Integer id = null; + if ((id = termCache.get(arg)) != null) + return id; + +// if (arg instanceof Individual) { + try { + if (arg instanceof Individual) + termCache.put(arg, id = resolveResource(((Individual) arg).getIRI(), Datatype.IRI_REFERENCE.value())); + else if (arg instanceof Constant) + termCache.put(arg, id = resolveResource(((Constant) arg).getLexicalForm(), getDatatypeID(((Constant) arg).getDatatypeURI()))); + + } catch (JRDFStoreException e) { + e.printStackTrace(); + } +// } + + return id; + } + + private static int getDatatypeID(String uri) { + if (uri.equals("http://www.w3.org/2001/XMLSchema#string")) return Datatype.XSD_STRING.value(); + if (uri.equals("http://www.w3.org/1999/02/22-rdf-syntax-ns#PlainLiteral")) return Datatype.RDF_PLAIN_LITERAL.value(); + if (uri.equals("http://www.w3.org/2001/XMLSchema#integer")) return Datatype.XSD_INTEGER.value(); + if (uri.equals("http://www.w3.org/2001/XMLSchema#float")) return Datatype.XSD_FLOAT.value(); + if (uri.equals("http://www.w3.org/2001/XMLSchema#double")) return Datatype.XSD_DOUBLE.value(); + if (uri.equals("http://www.w3.org/2001/XMLSchema#boolean")) return Datatype.XSD_BOOLEAN.value(); + if (uri.equals("http://www.w3.org/2001/XMLSchema#dateTime")) return Datatype.XSD_DATE_TIME.value(); + if (uri.equals("http://www.w3.org/2001/XMLSchema#time")) return Datatype.XSD_TIME.value(); + if (uri.equals("http://www.w3.org/2001/XMLSchema#date")) return Datatype.XSD_DATE.value(); + if (uri.equals("http://www.w3.org/2001/XMLSchema#gYearMonth")) return Datatype.XSD_G_YEAR_MONTH.value(); + if (uri.equals("http://www.w3.org/2001/XMLSchema#gYear")) return Datatype.XSD_G_YEAR.value(); + if (uri.equals("http://www.w3.org/2001/XMLSchema#gMonthDay")) return Datatype.XSD_G_MONTH_DAY.value(); + if (uri.equals("http://www.w3.org/2001/XMLSchema#gDay")) return Datatype.XSD_G_DAY.value(); + if (uri.equals("http://www.w3.org/2001/XMLSchema#gMonth")) return Datatype.XSD_G_MONTH.value(); + if (uri.equals("http://www.w3.org/2001/XMLSchema#duration")) return Datatype.XSD_DURATION.value(); + + return -1; + } + + public int[] getResourceIDs(Collection individuals) { + String[] str = new String[individuals.size()]; + int[] types = new int[individuals.size()]; + int index = 0; + for (uk.ac.ox.cs.JRDFox.model.Individual individual : individuals) { + types[index] = Datatype.IRI_REFERENCE.value(); + str[index++] = individual.getIRI(); + } + + try { + return m_dict.resolveResources(str, types); + } catch (JRDFStoreException e) { + e.printStackTrace(); + return null; + } + } + + public static String getQuotedTerm(Resource r) { + if (r.m_datatype.equals(Datatype.IRI_REFERENCE)) + return OWLHelper.addAngles(r.m_lexicalForm); + if (r.m_datatype.equals(Datatype.XSD_STRING) || r.m_datatype.equals(Datatype.RDF_PLAIN_LITERAL)) + return "\"" + r.m_lexicalForm + "\""; + else + return "\"" + r.m_lexicalForm + "\"^^<" + r.m_datatype.getIRI() + ">"; + } + +} -- cgit v1.2.3