From a840a197549ced185f212b2aa74abed8774c8b5c Mon Sep 17 00:00:00 2001 From: RncLsn Date: Wed, 3 Jun 2015 19:24:50 +0100 Subject: Reintroduced extended queries. Successfully tested on LightTests and GapAnswers. --- src/resources/pagoda.properties | 4 +- .../ox/cs/pagoda/endomorph/plan/OpenEndPlan.java | 6 +- src/uk/ac/ox/cs/pagoda/query/AnswerTuple.java | 2 +- src/uk/ac/ox/cs/pagoda/query/QueryRecord.java | 116 ++++++++------------- .../ac/ox/cs/pagoda/reasoner/MyQueryReasoner.java | 54 +++------- src/uk/ac/ox/cs/pagoda/util/PagodaProperties.java | 50 ++++++++- test/resources/LightTests.xml | 6 +- 7 files changed, 117 insertions(+), 121 deletions(-) diff --git a/src/resources/pagoda.properties b/src/resources/pagoda.properties index 80c6377..0b9d2ee 100644 --- a/src/resources/pagoda.properties +++ b/src/resources/pagoda.properties @@ -1 +1,3 @@ -debug=true \ No newline at end of file +debug=true +useAlwaysSimpleUpperBound=false +useSkolemUpperBound=false \ No newline at end of file diff --git a/src/uk/ac/ox/cs/pagoda/endomorph/plan/OpenEndPlan.java b/src/uk/ac/ox/cs/pagoda/endomorph/plan/OpenEndPlan.java index 4022c1d..73a27bf 100644 --- a/src/uk/ac/ox/cs/pagoda/endomorph/plan/OpenEndPlan.java +++ b/src/uk/ac/ox/cs/pagoda/endomorph/plan/OpenEndPlan.java @@ -94,14 +94,14 @@ public class OpenEndPlan implements CheckPlan { private boolean redundant(Clique clique) { for (NodeTuple nodeTuple: clique.getNodeTuples()) - if (!passedAnswers.contains(AnswerTuple.getInstance(nodeTuple.getAnswerTuple(), m_answerArity))) + if(!passedAnswers.contains(AnswerTuple.create(nodeTuple.getAnswerTuple(), m_answerArity))) return false; return true; } private void addProjections(Clique clique) { - for (NodeTuple nodeTuple: clique.getNodeTuples()) - passedAnswers.add(AnswerTuple.getInstance(nodeTuple.getAnswerTuple(), m_answerArity)); + for (NodeTuple nodeTuple: clique.getNodeTuples()) + passedAnswers.add(AnswerTuple.create(nodeTuple.getAnswerTuple(), m_answerArity)); } private void setMarkCascadelyValidated(Clique clique) { diff --git a/src/uk/ac/ox/cs/pagoda/query/AnswerTuple.java b/src/uk/ac/ox/cs/pagoda/query/AnswerTuple.java index 9a9d0de..1e5fbd4 100644 --- a/src/uk/ac/ox/cs/pagoda/query/AnswerTuple.java +++ b/src/uk/ac/ox/cs/pagoda/query/AnswerTuple.java @@ -49,7 +49,7 @@ public class AnswerTuple { /** * It returns the first argument if its arity equals length, a new AnswerTuple otherwise. */ - public static AnswerTuple getInstance(AnswerTuple extendedTuple, int length) { + public static AnswerTuple create(AnswerTuple extendedTuple, int length) { if(length == extendedTuple.getArity()) return extendedTuple; else return new AnswerTuple(extendedTuple, length); } diff --git a/src/uk/ac/ox/cs/pagoda/query/QueryRecord.java b/src/uk/ac/ox/cs/pagoda/query/QueryRecord.java index 3edb2c3..dee2966 100644 --- a/src/uk/ac/ox/cs/pagoda/query/QueryRecord.java +++ b/src/uk/ac/ox/cs/pagoda/query/QueryRecord.java @@ -9,7 +9,6 @@ import uk.ac.ox.cs.pagoda.reasoner.light.RDFoxAnswerTuples; import uk.ac.ox.cs.pagoda.rules.GeneralProgram; import uk.ac.ox.cs.pagoda.util.ConjunctiveQueryHelper; import uk.ac.ox.cs.pagoda.util.Namespace; -import uk.ac.ox.cs.pagoda.util.PagodaProperties; import uk.ac.ox.cs.pagoda.util.Utility; import uk.ac.ox.cs.pagoda.util.disposable.Disposable; import uk.ac.ox.cs.pagoda.util.disposable.DisposedException; @@ -135,18 +134,6 @@ public class QueryRecord extends Disposable { return updateUpperBoundAnswers(answerTuples, false); } - public boolean checkUpperBoundAnswers(AnswerTuples answerTuples) { - if(isDisposed()) throw new DisposedException(); - - return updateUpperBoundAnswers(answerTuples, true, false); - } - - public boolean updateUpperBoundAnswers(AnswerTuples answerTuples, boolean toCheckAux) { - if(isDisposed()) throw new DisposedException(); - - return updateUpperBoundAnswers(answerTuples, toCheckAux, true); - } - public int getNumberOfAnswers() { if(isDisposed()) throw new DisposedException(); @@ -377,7 +364,7 @@ public class QueryRecord extends Disposable { Utility.logError("The answer (" + answer + ") cannot be added, because it is not in the upper bound."); gapAnswerTuples.remove(answer); - answer = AnswerTuple.getInstance(answer, answerVariables[0].length); + answer = AnswerTuple.create(answer, answerVariables[0].length); // if (soundAnswerTuples.contains(answer)) // Utility.logError("The answer (" + answer + ") cannot be added, because it is in the lower bound."); soundAnswerTuples.add(answer); @@ -556,7 +543,6 @@ public class QueryRecord extends Disposable { return false; } - // TODO remove fully extended query public Tuple getExtendedQueryText() { if(isDisposed()) throw new DisposedException(); @@ -655,75 +641,65 @@ public class QueryRecord extends Disposable { return Objects.hash(queryText, soundAnswerTuples); } - private boolean updateUpperBoundAnswers(AnswerTuples answerTuples, boolean toCheckAux, boolean _check_containment) { - if(!(answerTuples instanceof RDFoxAnswerTuples)) { - String msg = "The upper bound must be computed by RDFox!"; - Utility.logError(msg); - throw new IllegalArgumentException(msg); + public boolean updateUpperBoundAnswers(AnswerTuples answerTuples, boolean toCheckAux) { + RDFoxAnswerTuples rdfAnswerTuples; + if(answerTuples instanceof RDFoxAnswerTuples) + rdfAnswerTuples = (RDFoxAnswerTuples) answerTuples; + else { + Utility.logError("The upper bound must be computed by RDFox!"); + return false; } - RDFoxAnswerTuples rdfoxAnswerTuples = (RDFoxAnswerTuples) answerTuples; + if(soundAnswerTuples.size() > 0) { + int number = 0; + for(; answerTuples.isValid(); answerTuples.moveNext()) { + ++number; + } + Utility.logDebug("The number of answers returned by an upper bound: " + number); + if(number <= soundAnswerTuples.size()) { + if(gapAnswerTuples != null) gapAnswerTuples.clear(); + else gapAnswerTuples = new HashSet(); - Set candidateGapAnswerTuples = new HashSet(); - AnswerTuple tuple; - for(; rdfoxAnswerTuples.isValid(); rdfoxAnswerTuples.moveNext()) { - tuple = rdfoxAnswerTuples.getTuple(); - if(isBottom() || !tuple.hasAnonymousIndividual()) - if((!toCheckAux || !tuple.hasAuxPredicate()) && !soundAnswerTuples.contains(tuple)) - candidateGapAnswerTuples.add(tuple); + Utility.logInfo("Upper bound answers updated: " + (soundAnswerTuples.size() + gapAnswerTuples.size())); + return false; + } + answerTuples.reset(); } - /*** START: debugging ***/ - if(PagodaProperties.isDebuggingMode() && _check_containment) { - if(rdfoxAnswerTuples.getArity() != getAnswerVariables().length) - throw new IllegalArgumentException( - "The arity of answers (" + rdfoxAnswerTuples.getArity() + ") " + - "is different from the number of answer variables (" + - getAnswerVariables().length + ")"); - - Set namedAnswerTuples = new HashSet<>(); - rdfoxAnswerTuples.reset(); - int numberOfAnswers = 0; - for(; rdfoxAnswerTuples.isValid(); rdfoxAnswerTuples.moveNext()) { - tuple = rdfoxAnswerTuples.getTuple(); -// if(isBottom() || !tuple.hasAnonymousIndividual()) { - namedAnswerTuples.add(tuple); -// } - numberOfAnswers++; + boolean justCheck = (answerTuples.getArity() != answerVariables[1].length); + + Set tupleSet = new HashSet(); + AnswerTuple tuple, extendedTuple; + for(; answerTuples.isValid(); answerTuples.moveNext()) { + extendedTuple = rdfAnswerTuples.getTuple(); + if(isBottom() || !extendedTuple.hasAnonymousIndividual()) { + tuple = AnswerTuple.create(extendedTuple, answerVariables[0].length); + if((!toCheckAux || !tuple.hasAuxPredicate()) && !soundAnswerTuples.contains(tuple)) { + if(!toCheckAux && justCheck) return false; + tupleSet.add(extendedTuple); + } } - Utility.logDebug("The number of answers returned by an upper bound: " + numberOfAnswers); - HashSet difference = new HashSet<>(soundAnswerTuples); - difference.removeAll(namedAnswerTuples); - if(!difference.isEmpty()) - throw new IllegalArgumentException("The upper bound does not contain the lower bound! Missing answers: " + difference - .size()); } - /*** END: debugging ***/ - boolean update; if(gapAnswerTuples == null) { - gapAnswerTuples = candidateGapAnswerTuples; - update = true; + gapAnswerTuples = tupleSet; + + Utility.logInfo("Upper bound answers updated: " + (soundAnswerTuples.size() + gapAnswerTuples.size())); + return true; } - else { - update = gapAnswerTuples.retainAll(candidateGapAnswerTuples); + + boolean update = false; + for(Iterator iter = gapAnswerTuples.iterator(); iter.hasNext(); ) { + tuple = iter.next(); + if(!tupleSet.contains(tuple)) { + iter.remove(); + update = true; + } } - if(update) - Utility.logInfo("Upper bound answers updated: " + getNumberOfAnswers()); - else - Utility.logInfo("Upper bound answers unchanged"); + Utility.logInfo("Upper bound answers updated: " + (soundAnswerTuples.size() + gapAnswerTuples.size())); return update; - -// boolean update = false; -// for(Iterator iter = gapAnswerTuples.iterator(); iter.hasNext(); ) { -// tuple = iter.next(); -// if(!candidateGapAnswerTuples.contains(tuple)) { -// iter.remove(); -// update = true; -// } -// } } public enum Step { diff --git a/src/uk/ac/ox/cs/pagoda/reasoner/MyQueryReasoner.java b/src/uk/ac/ox/cs/pagoda/reasoner/MyQueryReasoner.java index b4e2f5a..3027a73 100644 --- a/src/uk/ac/ox/cs/pagoda/reasoner/MyQueryReasoner.java +++ b/src/uk/ac/ox/cs/pagoda/reasoner/MyQueryReasoner.java @@ -19,6 +19,7 @@ import uk.ac.ox.cs.pagoda.tracking.QueryTracker; import uk.ac.ox.cs.pagoda.tracking.TrackingRuleEncoder; import uk.ac.ox.cs.pagoda.tracking.TrackingRuleEncoderDisjVar1; import uk.ac.ox.cs.pagoda.tracking.TrackingRuleEncoderWithGap; +import uk.ac.ox.cs.pagoda.util.PagodaProperties; import uk.ac.ox.cs.pagoda.util.Timer; import uk.ac.ox.cs.pagoda.util.Utility; import uk.ac.ox.cs.pagoda.util.disposable.DisposedException; @@ -44,7 +45,6 @@ class MyQueryReasoner extends QueryReasoner { private Collection predicatesWithGap = null; private ConsistencyStatus isConsistent; private ConsistencyManager consistency = new ConsistencyManager(this); - private boolean useSkolemisation = false; // now only debugging public MyQueryReasoner() { setup(true); @@ -192,7 +192,8 @@ class MyQueryReasoner extends QueryReasoner { OWLOntology relevantOntologySubset = extractRelevantOntologySubset(queryRecord); queryRecord.saveRelevantOntology("/home/alessandro/Desktop/fragment_query" + queryRecord.getQueryID() + ".owl"); - if(useSkolemisation && querySkolemisedRelevantSubset(relevantOntologySubset, queryRecord)) + if(PagodaProperties.getDefaultUseSkolemUpperBound() && + querySkolemisedRelevantSubset(relevantOntologySubset, queryRecord)) return; Timer t = new Timer(); @@ -263,10 +264,12 @@ class MyQueryReasoner extends QueryReasoner { private boolean queryUpperStore(BasicQueryEngine upperStore, QueryRecord queryRecord, Tuple extendedQuery, Step step) { t.reset(); - if(queryRecord.hasNonAnsDistinguishedVariables()) + + queryUpperBound(upperStore, queryRecord, queryRecord.getQueryText(), queryRecord.getAnswerVariables()); + if(!queryRecord.isProcessed() && !queryRecord.getQueryText().equals(extendedQuery.get(0))) queryUpperBound(upperStore, queryRecord, extendedQuery.get(0), queryRecord.getAnswerVariables()); - else - queryUpperBound(upperStore, queryRecord, queryRecord.getQueryText(), queryRecord.getAnswerVariables()); + if(!queryRecord.isProcessed() && queryRecord.hasNonAnsDistinguishedVariables()) + queryUpperBound(upperStore, queryRecord, extendedQuery.get(1), queryRecord.getDistinguishedVariables()); queryRecord.addProcessingTime(step, t.duration()); if(queryRecord.isProcessed()) { @@ -276,34 +279,6 @@ class MyQueryReasoner extends QueryReasoner { return false; } - private boolean checkGapAnswers(BasicQueryEngine relevantStore, QueryRecord queryRecord) { - t.reset(); - Tuple extendedQueries = queryRecord.getExtendedQueryText(); - if(queryRecord.hasNonAnsDistinguishedVariables()) - checkGapAnswers(relevantStore, queryRecord, extendedQueries.get(0), queryRecord.getAnswerVariables()); - else - checkGapAnswers(relevantStore, queryRecord, queryRecord.getQueryText(), queryRecord.getAnswerVariables()); - - queryRecord.addProcessingTime(Step.L_SKOLEM_UPPER_BOUND, t.duration()); - if(queryRecord.isProcessed()) { - queryRecord.setDifficulty(Step.L_SKOLEM_UPPER_BOUND); - return true; - } - return false; - } - - private void checkGapAnswers(BasicQueryEngine relevantStore, QueryRecord queryRecord, String queryText, String[] answerVariables) { - AnswerTuples rlAnswer = null; - try { - Utility.logDebug(queryText); - rlAnswer = relevantStore.evaluate(queryText, answerVariables); - Utility.logDebug(t.duration()); - queryRecord.checkUpperBoundAnswers(rlAnswer); - } finally { - if(rlAnswer != null) rlAnswer.dispose(); - } - } - /** * Returns the part of the ontology relevant for Hermit, while computing the bound answers. */ @@ -322,9 +297,11 @@ class MyQueryReasoner extends QueryReasoner { Tuple extendedQueryTexts = queryRecord.getExtendedQueryText(); - Utility.logDebug("Tracking store"); - if(queryUpperStore(trackingStore, queryRecord, extendedQueryTexts, Step.SIMPLE_UPPER_BOUND)) - return true; + if(PagodaProperties.getDefaultUseAlwaysSimpleUpperBound() || lazyUpperStore == null) { + Utility.logDebug("Tracking store"); + if(queryUpperStore(trackingStore, queryRecord, extendedQueryTexts, Step.SIMPLE_UPPER_BOUND)) + return true; + } if(!queryRecord.isBottom()) { Utility.logDebug("Lazy store"); @@ -362,7 +339,6 @@ class MyQueryReasoner extends QueryReasoner { queryRecord.addProcessingTime(Step.FRAGMENT, t.duration()); - // just statistics int numOfABoxAxioms = relevantOntologySubset.getABoxAxioms(true).size(); int numOfTBoxAxioms = relevantOntologySubset.getAxiomCount() - numOfABoxAxioms; Utility.logInfo("Relevant ontology-subset has been extracted: |ABox|=" @@ -407,7 +383,9 @@ class MyQueryReasoner extends QueryReasoner { return false; } - boolean isFullyProcessed = checkGapAnswers(relevantStore, queryRecord); + boolean isFullyProcessed = queryUpperStore(relevantStore, queryRecord, + queryRecord.getExtendedQueryText(), + Step.L_SKOLEM_UPPER_BOUND); Utility.logInfo("Semi-Skolemised relevant upper store has been evaluated"); return isFullyProcessed; } diff --git a/src/uk/ac/ox/cs/pagoda/util/PagodaProperties.java b/src/uk/ac/ox/cs/pagoda/util/PagodaProperties.java index 7b7d48d..e07d54f 100644 --- a/src/uk/ac/ox/cs/pagoda/util/PagodaProperties.java +++ b/src/uk/ac/ox/cs/pagoda/util/PagodaProperties.java @@ -10,24 +10,41 @@ import java.util.Properties; public class PagodaProperties { public static final String CONFIG_FILE = "pagoda.properties"; - public static final boolean DEFAULT_DEBUG = false; + private static final boolean DEFAULT_USE_ALWAYS_SIMPLE_UPPER_BOUND; + private static final boolean DEFAULT_USE_SKOLEM_UPPER_BOUND; + public static boolean shellModeDefault = false; private static boolean debug = DEFAULT_DEBUG; static { + boolean defaultUseAlwaysSimpleUpperBound = false; + boolean defaultUseSkolemUpperBound = true; + try(InputStream in = PagodaProperties.class.getClassLoader().getResourceAsStream(CONFIG_FILE)) { Properties config = new Properties(); config.load(in); in.close(); + Logger logger = Logger.getLogger("PagodaProperties"); if(config.containsKey("debug")) { debug = Boolean.parseBoolean(config.getProperty("debug")); - Logger.getLogger("PagodaProperties") - .info("Debugging mode is enabled (you can disable it from file \"pagoda.properties\")"); +// logger.info("Debugging mode is enabled (you can disable it from file \"pagoda.properties\")"); + logger.info("Debugging mode is enabled"); + } + if(config.containsKey("useAlwaysSimpleUpperBound")) { + defaultUseAlwaysSimpleUpperBound = + Boolean.parseBoolean(config.getProperty("useAlwaysSimpleUpperBound")); + logger.info("The simple upper bound is always used"); + } + if(config.containsKey("useSkolemUpperBound")) { + defaultUseSkolemUpperBound = Boolean.parseBoolean(config.getProperty("useSkolemUpperBound")); + logger.info("The Skolem upper bound is enabled"); } } catch(IOException e) { e.printStackTrace(); } + DEFAULT_USE_ALWAYS_SIMPLE_UPPER_BOUND = defaultUseAlwaysSimpleUpperBound; + DEFAULT_USE_SKOLEM_UPPER_BOUND = defaultUseSkolemUpperBound; } String dataPath = null; @@ -37,7 +54,8 @@ public class PagodaProperties { boolean toClassify = true; boolean toCallHermiT = true; boolean shellMode = shellModeDefault; - + private boolean useAlwaysSimpleUpperBound = DEFAULT_USE_ALWAYS_SIMPLE_UPPER_BOUND; + private boolean useSkolemUpperBound = DEFAULT_USE_SKOLEM_UPPER_BOUND; public PagodaProperties(String path) { java.util.Properties m_properties = new java.util.Properties(); InputStream inputStream = null; @@ -63,7 +81,6 @@ public class PagodaProperties { } } } - public PagodaProperties() { } @@ -71,6 +88,14 @@ public class PagodaProperties { return debug; } + public static boolean getDefaultUseAlwaysSimpleUpperBound() { + return DEFAULT_USE_ALWAYS_SIMPLE_UPPER_BOUND; + } + + public static boolean getDefaultUseSkolemUpperBound() { + return DEFAULT_USE_SKOLEM_UPPER_BOUND; + } + public String getDataPath() { return dataPath; } @@ -127,4 +152,19 @@ public class PagodaProperties { shellMode = flag; } + public boolean getUseAlwaysSimpleUpperBound() { + return useAlwaysSimpleUpperBound; + } + + public void setUseAlwaysSimpleUpperBound(boolean flag) { + useAlwaysSimpleUpperBound = flag; + } + + public boolean getUseSkolemUpperBound() { + return useSkolemUpperBound; + } + + public void setUseSkolemUpperBound(boolean flag) { + useSkolemUpperBound = flag; + } } diff --git a/test/resources/LightTests.xml b/test/resources/LightTests.xml index 92edb48..9b9eee4 100644 --- a/test/resources/LightTests.xml +++ b/test/resources/LightTests.xml @@ -10,10 +10,10 @@ - - + + - + \ No newline at end of file -- cgit v1.2.3