From 9ce65c5a963b03ee97fe9cb6c5aa65a3c04a80a8 Mon Sep 17 00:00:00 2001 From: yzhou Date: Tue, 21 Apr 2015 10:34:27 +0100 Subject: initial version --- src/uk/ac/ox/cs/pagoda/query/AnswerTuple.java | 135 +++++ src/uk/ac/ox/cs/pagoda/query/AnswerTuples.java | 23 + src/uk/ac/ox/cs/pagoda/query/AnswerTuplesImp.java | 92 ++++ src/uk/ac/ox/cs/pagoda/query/GapByStore4ID.java | 192 +++++++ src/uk/ac/ox/cs/pagoda/query/GapByTriple.java | 171 +++++++ src/uk/ac/ox/cs/pagoda/query/GapTupleIterator.java | 30 ++ src/uk/ac/ox/cs/pagoda/query/QueryManager.java | 123 +++++ src/uk/ac/ox/cs/pagoda/query/QueryRecord.java | 562 +++++++++++++++++++++ .../ac/ox/cs/pagoda/query/rollup/QueryGraph.java | 383 ++++++++++++++ .../cs/pagoda/query/rollup/VariableConstant.java | 227 +++++++++ .../cs/pagoda/query/rollup/VariableIndividual.java | 416 +++++++++++++++ 11 files changed, 2354 insertions(+) create mode 100644 src/uk/ac/ox/cs/pagoda/query/AnswerTuple.java create mode 100644 src/uk/ac/ox/cs/pagoda/query/AnswerTuples.java create mode 100644 src/uk/ac/ox/cs/pagoda/query/AnswerTuplesImp.java create mode 100644 src/uk/ac/ox/cs/pagoda/query/GapByStore4ID.java create mode 100644 src/uk/ac/ox/cs/pagoda/query/GapByTriple.java create mode 100644 src/uk/ac/ox/cs/pagoda/query/GapTupleIterator.java create mode 100644 src/uk/ac/ox/cs/pagoda/query/QueryManager.java create mode 100644 src/uk/ac/ox/cs/pagoda/query/QueryRecord.java create mode 100644 src/uk/ac/ox/cs/pagoda/query/rollup/QueryGraph.java create mode 100644 src/uk/ac/ox/cs/pagoda/query/rollup/VariableConstant.java create mode 100644 src/uk/ac/ox/cs/pagoda/query/rollup/VariableIndividual.java (limited to 'src/uk/ac/ox/cs/pagoda/query') diff --git a/src/uk/ac/ox/cs/pagoda/query/AnswerTuple.java b/src/uk/ac/ox/cs/pagoda/query/AnswerTuple.java new file mode 100644 index 0000000..8d7e0b1 --- /dev/null +++ b/src/uk/ac/ox/cs/pagoda/query/AnswerTuple.java @@ -0,0 +1,135 @@ +package uk.ac.ox.cs.pagoda.query; + +import java.util.HashMap; +import java.util.Map; + +import org.semanticweb.HermiT.model.Constant; +import org.semanticweb.HermiT.model.Individual; +import org.semanticweb.HermiT.model.Term; +import org.semanticweb.HermiT.model.Variable; + +import uk.ac.ox.cs.JRDFox.JRDFStoreException; +import uk.ac.ox.cs.JRDFox.model.Datatype; +import uk.ac.ox.cs.JRDFox.model.GroundTerm; +import uk.ac.ox.cs.JRDFox.model.Literal; +import uk.ac.ox.cs.JRDFox.store.TupleIterator; +import uk.ac.ox.cs.pagoda.util.Namespace; + +public class AnswerTuple { + + public static final String SEPARATOR = "\t"; + + String m_str = null; + GroundTerm[] m_tuple; + + public AnswerTuple(TupleIterator iter, int arity) { + m_tuple = new GroundTerm[arity]; + try { + for (int i = 0; i < arity; ++i) + m_tuple[i] = iter.getGroundTerm(i); + } catch (JRDFStoreException e) { + e.printStackTrace(); + } + } + + public AnswerTuple(GroundTerm[] terms) { + m_tuple = terms; + } + + private AnswerTuple(AnswerTuple sup, int arity) { + m_tuple = new GroundTerm[arity]; + for (int i = 0; i < arity; ++i) m_tuple[i] = sup.m_tuple[i]; + } + + public int getArity() { + return m_tuple.length; + } + + public int hashCode() { +// return toString().hashCode(); + int code = 0; + for (int i = 0; i < m_tuple.length; ++i) + code = code * 1997 + m_tuple[i].hashCode(); + return code; + } + + public boolean equals(Object obj) { + if (!(obj instanceof AnswerTuple)) return false; + AnswerTuple that = (AnswerTuple) obj; + if (m_tuple.length != that.m_tuple.length) return false; + for (int i = 0; i < m_tuple.length; ++i) + if (!m_tuple[i].equals(that.m_tuple[i])) + return false; + return true; +// return toString().equals(obj.toString()); + } + + public String toString() { + if (m_str != null) return m_str; + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < m_tuple.length; ++i) { + if (sb.length() != 0) sb.append(SEPARATOR); + if (m_tuple[i] instanceof uk.ac.ox.cs.JRDFox.model.Individual) + sb.append("<").append(((uk.ac.ox.cs.JRDFox.model.Individual) m_tuple[i]).getIRI()).append(">"); + else if (m_tuple[i] instanceof uk.ac.ox.cs.JRDFox.model.BlankNode) { + sb.append(((uk.ac.ox.cs.JRDFox.model.BlankNode) m_tuple[i]).toString()); + } + else { + Literal l = (Literal) m_tuple[i]; + sb.append('"').append(l.getLexicalForm()).append("\""); + if (!l.getDatatype().equals(Datatype.XSD_STRING) && !l.getDatatype().equals(Datatype.RDF_PLAIN_LITERAL)) + sb.append("^^<").append(l.getDatatype().getIRI()).append(">"); + } + } + return m_str = sb.toString(); + } + + public GroundTerm getGroundTerm(int i) { + return m_tuple[i]; + } + + public Map getAssignment(String[] vars) { + Map map = new HashMap(); + int index = 0; + Term t; + for (String var: vars) { + if (m_tuple[index] instanceof uk.ac.ox.cs.JRDFox.model.Individual) + t = Individual.create((((uk.ac.ox.cs.JRDFox.model.Individual) m_tuple[index]).getIRI())); + else { + uk.ac.ox.cs.JRDFox.model.Literal l = (uk.ac.ox.cs.JRDFox.model.Literal) m_tuple[index]; + t = Constant.create(l.getLexicalForm(), l.getDatatype().getIRI()); + } + map.put(Variable.create(var), t); + ++index; + } + return map; + } + + public boolean hasAuxPredicate() { + String iri; + for (int i = 0; i < m_tuple.length; ++i) + if ((m_tuple[i] instanceof uk.ac.ox.cs.JRDFox.model.Individual)) { + iri = ((uk.ac.ox.cs.JRDFox.model.Individual) m_tuple[i]).getIRI(); + if ( iri.startsWith(Namespace.PAGODA_AUX) || iri.contains("_AUX") || iri.contains("_neg") || iri.contains("internal:def")) + return true; + } + return false; + } + + public boolean hasAnonyIndividual() { + String iri; + for (int i = 0; i < m_tuple.length; ++i) + if ((m_tuple[i] instanceof uk.ac.ox.cs.JRDFox.model.Individual)) { + iri = ((uk.ac.ox.cs.JRDFox.model.Individual) m_tuple[i]).getIRI(); + if (iri.startsWith(Namespace.PAGODA_ANONY) || iri.startsWith(Namespace.KARMA_ANONY)) + return true; + } + return false; + } + + 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/AnswerTuples.java b/src/uk/ac/ox/cs/pagoda/query/AnswerTuples.java new file mode 100644 index 0000000..e1e5302 --- /dev/null +++ b/src/uk/ac/ox/cs/pagoda/query/AnswerTuples.java @@ -0,0 +1,23 @@ +package uk.ac.ox.cs.pagoda.query; + +public interface AnswerTuples { + + public void reset(); + + public boolean isValid(); + + public int getArity(); + + public String[] getAnswerVariables(); + + public void moveNext(); + + public void dispose(); + + public AnswerTuple getTuple(); + + public boolean contains(AnswerTuple t); + + public void remove(); + +} diff --git a/src/uk/ac/ox/cs/pagoda/query/AnswerTuplesImp.java b/src/uk/ac/ox/cs/pagoda/query/AnswerTuplesImp.java new file mode 100644 index 0000000..3e0f320 --- /dev/null +++ b/src/uk/ac/ox/cs/pagoda/query/AnswerTuplesImp.java @@ -0,0 +1,92 @@ +package uk.ac.ox.cs.pagoda.query; + +import java.util.Iterator; +import java.util.Set; + +public class AnswerTuplesImp implements AnswerTuples { + + int m_index; + Iterator m_iter; + Set m_answers1, m_answers2; + String[] m_answerVars; + AnswerTuple m_tuple; + + public AnswerTuplesImp(String[] answerVars, Set answers) { + m_answers1 = answers; + m_answers2 = null; + m_answerVars = answerVars; + reset(); + } + + public AnswerTuplesImp(String[] answerVars, Set answers1, Set answers2) { + m_answers1 = answers1; + m_answers2 = answers2; + m_answerVars = answerVars; + reset(); + } + + @Override + public boolean isValid() { + return m_tuple != null; + } + + @Override + public int getArity() { + return m_answerVars.length; + } + + @Override + public void moveNext() { + if (m_iter != null && m_iter.hasNext()) { + m_tuple = m_iter.next(); + return ; + } + else if (m_answers2 != null && m_index == 1){ + ++m_index; + m_iter = m_answers2.iterator(); + if (m_iter.hasNext()) { + m_tuple = m_iter.next(); + return ; + } + } + else + m_tuple = null; + } + + @Override + public void dispose() {} + + @Override + public void reset() { + if (m_answers1 == null || m_answers1.isEmpty()) { + m_index = 2; + m_iter = m_answers2 == null ? null : m_answers2.iterator(); + } + else { + m_index = 1; + m_iter = m_answers1.iterator(); + } + moveNext(); + } + + @Override + public boolean contains(AnswerTuple t) { + return m_answers1.contains(t) || (m_answers2 != null && m_answers2.contains(t)); + } + + @Override + public AnswerTuple getTuple() { + return m_tuple; + } + + @Override + public String[] getAnswerVariables() { + return m_answerVars; + } + + @Override + public void remove() { + m_iter.remove(); + } + +} diff --git a/src/uk/ac/ox/cs/pagoda/query/GapByStore4ID.java b/src/uk/ac/ox/cs/pagoda/query/GapByStore4ID.java new file mode 100644 index 0000000..1c0eb48 --- /dev/null +++ b/src/uk/ac/ox/cs/pagoda/query/GapByStore4ID.java @@ -0,0 +1,192 @@ +package uk.ac.ox.cs.pagoda.query; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; + +import uk.ac.ox.cs.pagoda.MyPrefixes; +//import uk.ac.ox.cs.pagoda.multistage.AnswerTupleID; +import uk.ac.ox.cs.pagoda.reasoner.light.BasicQueryEngine; +import uk.ac.ox.cs.pagoda.reasoner.light.RDFoxTripleManager; +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; +import uk.ac.ox.cs.JRDFox.store.TupleIterator; + +//public class GapByStore4ID extends GapTupleIterator { +public class GapByStore4ID extends GapTupleIterator { + + private MyPrefixes prefixes = MyPrefixes.PAGOdAPrefixes; + private TupleIterator iterator = null; + +// AnswerTupleID tuple; + int[] tuple; + private BasicQueryEngine m_engine; + private DataStore m_store; + private RDFoxTripleManager tripleManager; + + public GapByStore4ID(BasicQueryEngine engine) { + m_engine = engine; + m_store = engine.getDataStore(); + tripleManager = new RDFoxTripleManager(m_store, false); + } + + long multi; + + @Override + public void compile(String program) throws JRDFStoreException { + clear(); + + boolean incrementally = true; + Timer t = new Timer(); + long oldTripleCount = m_store.getTriplesCount(); + + if (program != null) { +// m_store.addRules(new String[] {program}); + m_store.importRules(program); + incrementally = false; + } + + m_store.applyReasoning(incrementally); + + long tripleCount = m_store.getTriplesCount(); + + Utility.logDebug("current store after materialising upper related rules: " + tripleCount + " (" + (tripleCount - oldTripleCount) + " new)", + "current store finished the materialisation of upper related rules in " + t.duration() + " seconds."); + + m_engine.setExpandEquality(false); + iterator = m_engine.internal_evaluateAgainstIDBs("select ?x ?y ?z where { ?x ?y ?z . }"); + m_engine.setExpandEquality(true); + + multi = iterator.open(); + Utility.logDebug("gap query evaluted ..."); + } + + @Override + public boolean hasNext() { + if (iterator == null) return false; + try { +// tuple = new AnswerTupleID(3); + tuple = new int[3]; + Integer predicate; + for (; multi != 0; multi = iterator.getNext()) { + for (int i = 0; i < 3; ++i) +// tuple.setTerm(i, (int) iterator.getResourceID(i)); + tuple[i] = (int) iterator.getResourceID(i); + + if (isRDF_TYPE()) { +// predicate = getGapPredicateID(tuple.getTerm(2)); + predicate = getGapPredicateID(tuple[2]); + if (predicate == null) continue; +// tuple.setTerm(2, predicate); + tuple[2] = predicate; + } + else { +// predicate = getGapPredicateID(tuple.getTerm(1)); + predicate = getGapPredicateID(tuple[1]); + if (predicate == null) continue; +// tuple.setTerm(1, predicate); + tuple[1] = predicate; + } + return true; + } + } catch (JRDFStoreException e) { + e.printStackTrace(); + return false; + } + return false; + } + + @Override +// public AnswerTupleID next() { + public int[] next() { + try { + multi = iterator.getNext(); + } catch (JRDFStoreException e) { + e.printStackTrace(); + } + + return tuple; + } + + Map original2gap = new HashMap(); + LinkedList predicatesWithGap = new LinkedList(); + + public LinkedList getPredicatesWithGap() { + return predicatesWithGap; + } + + private Integer getGapPredicateID(int originalID) { + Integer gapID; + if ((gapID = original2gap.get(originalID)) != null) + return gapID; + + String originalPredicate = tripleManager.getRawTerm(originalID); + if (isAuxPredicate(originalPredicate)) { +// Utility.LOGS.info(originalPredicate); + return null; + } + + predicatesWithGap.add(originalPredicate); + String gapPredicate = prefixes.expandIRI(getGapPredicate(originalPredicate)); + gapID = tripleManager.getResourceID(gapPredicate); + original2gap.put(originalID, gapID); + + return gapID; + } + + private boolean isAuxPredicate(String originalPredicate) { + return originalPredicate.contains("_AUX"); + } + + private boolean isRDF_TYPE() { +// return tripleManager.isRdfTypeID(tuple.getTerm(1)); + return tripleManager.isRdfTypeID(tuple[1]); + } + + @Override + public void remove() { + Utility.logError("Unsupported operation!"); + } + + private boolean valid = false; + + @Override + public void save(String file) { + Utility.logError("Unsupported Operation..."); + } + + @Override + public void addBackTo() throws JRDFStoreException { + int tupleCounter = 0; + Timer t = new Timer(); + long oldTripleCounter; + Utility.logDebug("current store before importing gap tuples: " + (oldTripleCounter = m_store.getTriplesCount())); + while (hasNext()) { + next(); + ++tupleCounter; + tripleManager.addTripleByID(tuple); + } + valid = true; + + long tripleCounter = m_store.getTriplesCount(); + Utility.logDebug("There are " + tupleCounter + " tuples in the gap between lower and upper bound materialisation.", + "current store after importing gap tuples: " + tripleCounter + " (" + (tripleCounter - oldTripleCounter) + ").", + "current store finished importing gap tuples: " + tripleCounter + " in " + t.duration() + "."); + } + + public void clear() { + if (iterator != null) { + iterator.dispose(); + iterator = null; + } + } + + public boolean isValid() {return valid; } + + @Override + public void addTo(DataStore store) throws JRDFStoreException { + Utility.logError("Unsupported Operation..."); + } +} diff --git a/src/uk/ac/ox/cs/pagoda/query/GapByTriple.java b/src/uk/ac/ox/cs/pagoda/query/GapByTriple.java new file mode 100644 index 0000000..1a94f07 --- /dev/null +++ b/src/uk/ac/ox/cs/pagoda/query/GapByTriple.java @@ -0,0 +1,171 @@ +package uk.ac.ox.cs.pagoda.query; + +import java.io.BufferedWriter; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.util.Collection; + +import org.semanticweb.HermiT.model.Atom; +import org.semanticweb.HermiT.model.AtomicConcept; +import org.semanticweb.HermiT.model.AtomicRole; +import org.semanticweb.HermiT.model.DLClause; +import org.semanticweb.HermiT.model.Individual; + +import uk.ac.ox.cs.pagoda.MyPrefixes; +import uk.ac.ox.cs.pagoda.owl.OWLHelper; +import uk.ac.ox.cs.pagoda.reasoner.light.BasicQueryEngine; +import uk.ac.ox.cs.pagoda.reasoner.light.RDFoxTripleManager; +import uk.ac.ox.cs.pagoda.util.Namespace; +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.Parameters; +import uk.ac.ox.cs.JRDFox.store.TupleIterator; + +public class GapByTriple extends GapTupleIterator { + + private static final String RDF_TYPE = Namespace.RDF_NS + "type"; + private static final String BRIEF_RDF_TYPE = "rdf:type"; + + static final String allTripleQuery = "SELECT ?X ?Y ?Z WHERE { ?X ?Y ?Z }"; + + DataStore lowerStore, upperStore; + long multi; + TupleIterator iterator; + String sub, obj, predicate; +// GroundTerm subTerm, objTerm; + Prefixes prefixes; + Parameters parameters; + + public GapByTriple(BasicQueryEngine lowerStore, BasicQueryEngine upperStore) { + this.lowerStore = lowerStore.getDataStore(); + this.upperStore = upperStore.getDataStore(); + prefixes = MyPrefixes.PAGOdAPrefixes.getRDFoxPrefixes(); + parameters = new Parameters(); + } + + public void compile(Collection clauses) throws JRDFStoreException { + iterator = this.upperStore.compileQuery(allTripleQuery, prefixes, parameters); + multi = iterator.open(); + } + + @Override + public boolean hasNext() { + TupleIterator iter; + boolean inGap; + StringBuffer queryBuffer = new StringBuffer(); + try { + for (; multi != 0; multi = iterator.getNext()) { +// iterator.getRawGroundTerm(0); +// iterator.getRawGroundTerm(1); +// iterator.getRawGroundTerm(2); + + sub = RDFoxTripleManager.getQuotedTerm(iterator.getResource(0)); + predicate = RDFoxTripleManager.getQuotedTerm(iterator.getResource(1)); + obj = RDFoxTripleManager.getQuotedTerm(iterator.getResource(2)); + + if (!obj.startsWith("<")) { + // This fragment of code ignores data types assertions. +// Utility.LOGS.info(sub + " " + predicate + " " + obj); + continue; + } + + queryBuffer.setLength(0); + queryBuffer.append("SELECT WHERE { ").append(sub).append(" ").append(predicate).append(" ").append(obj).append(" }"); + + iter = lowerStore.compileQuery(queryBuffer.toString(), prefixes, parameters); + inGap = iter.open() != 0; + iter.dispose(); + if (inGap) + return true; + } + } catch (JRDFStoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return false; + } + + @Override + public String next() { + try { + multi = iterator.getNext(); + } catch (JRDFStoreException e) { + e.printStackTrace(); + } + StringBuilder sb = new StringBuilder(); + if (isRDF_TYPE()) { + sb.append(sub).append(" ").append(predicate).append(" ").append(getGapPredicate(obj)).append("."); + } + else sb.append(sub).append(" ").append(getGapPredicate(predicate)).append(" ").append(obj).append("."); + return sb.toString(); + } + + private boolean isRDF_TYPE() { + return predicate.equals(RDF_TYPE) || predicate.equals(BRIEF_RDF_TYPE); + } + + @Override + public void remove() { + Utility.logError("Unsupported operation!"); + } + + public void save(String file) { + int tupleCounter = 0; + try { + BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file))); + String tuple; + while (hasNext()) { + tuple = next(); + writer.write(tuple); + writer.newLine(); + ++tupleCounter; + } + writer.close(); + } catch (IOException e) { + e.printStackTrace(); + } + + Utility.logError("There are " + tupleCounter + " tuples in the gap between lower and upper bound materialisation."); + } + + public void addTo(DataStore store) throws JRDFStoreException { + int tupleCounter = 0; + RDFoxTripleManager tripleManager = new RDFoxTripleManager(store, false); + while (hasNext()) { + multi = iterator.getNext(); + ++tupleCounter; + if (isRDF_TYPE()) { + obj = OWLHelper.removeAngles(obj); + tripleManager.addTripleByTerm( + Atom.create(AtomicConcept.create(getGapPredicate(obj)), Individual.create(sub))); + } + else { + predicate = OWLHelper.removeAngles(predicate); + tripleManager.addTripleByTerm( + Atom.create(AtomicRole.create(getGapPredicate(predicate)), Individual.create(sub), Individual.create(obj))); + } + if (tupleCounter % 10000 == 0) + Utility.logDebug(tupleCounter); + } + + Utility.logDebug("There are " + tupleCounter + " tuples in the gap between lower and upper bound materialisation."); + } + + @Override + public void addBackTo() throws JRDFStoreException { + addTo(upperStore); + } + + @Override + public boolean isValid() { + return true; + } + + @Override + public void clear() { + iterator.dispose(); + } +} diff --git a/src/uk/ac/ox/cs/pagoda/query/GapTupleIterator.java b/src/uk/ac/ox/cs/pagoda/query/GapTupleIterator.java new file mode 100644 index 0000000..58303bb --- /dev/null +++ b/src/uk/ac/ox/cs/pagoda/query/GapTupleIterator.java @@ -0,0 +1,30 @@ +package uk.ac.ox.cs.pagoda.query; + +import java.util.Iterator; + +import uk.ac.ox.cs.JRDFox.JRDFStoreException; +import uk.ac.ox.cs.JRDFox.store.DataStore; + +public abstract class GapTupleIterator implements Iterator { + + public static final String gapPredicateSuffix = "_AUXg"; + + public static final String getGapPredicate(String predicateIRI) { + if (predicateIRI.startsWith("<")) + return predicateIRI.replace(">", gapPredicateSuffix + ">"); + return predicateIRI + gapPredicateSuffix; + } + + public void compile(String programText) throws JRDFStoreException {} + + public abstract boolean isValid(); + + public abstract void save(String file); + + public abstract void addBackTo() throws JRDFStoreException; + + public abstract void addTo(DataStore store) throws JRDFStoreException; + + public abstract void clear(); + +} diff --git a/src/uk/ac/ox/cs/pagoda/query/QueryManager.java b/src/uk/ac/ox/cs/pagoda/query/QueryManager.java new file mode 100644 index 0000000..419cb97 --- /dev/null +++ b/src/uk/ac/ox/cs/pagoda/query/QueryManager.java @@ -0,0 +1,123 @@ +package uk.ac.ox.cs.pagoda.query; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; +import java.util.Scanner; + +import uk.ac.ox.cs.pagoda.util.Utility; + +public class QueryManager { + + public Collection collectQueryRecords(String queryfile) { + Collection ret = new LinkedList(); + for (String queryText: collectQueryTexts(queryfile)) + ret.add(create(queryText)); + return ret; + } + + public static Collection collectQueryTexts(String queryfile) { + Scanner scanner = null; + try { + scanner = new Scanner(new File(queryfile)); + } catch (FileNotFoundException e) { + e.printStackTrace(); + return null; + } + Collection ret = new LinkedList(); + + StringBuilder sb = new StringBuilder(); + int leftToMatch; + String text; + while (scanner.hasNextLine()) { + leftToMatch = -1; + for (String line; scanner.hasNextLine(); ) { + line = scanner.nextLine(); + if (line.length() > 6 && line.substring(0, 6).equalsIgnoreCase("SELECT")) { + String next = line.split(" ")[1]; + if (!next.equalsIgnoreCase("distinct")) + line = line.substring(0, 6) + " distinct" + line.substring(6); + } + for (int i = 0; i < line.length(); ++i) + if (line.charAt(i) == '{') + if (leftToMatch == -1) leftToMatch = 1; + else ++leftToMatch; + else if (line.charAt(i) == '}') --leftToMatch; + +// if (line.isEmpty()) break; + + if (!line.isEmpty()) + sb.append(line).append(Utility.LINE_SEPARATOR); + + if (leftToMatch == 0) break; + } + + text = preprocess(sb.toString()); + if (!text.isEmpty()) + ret.add(text); + sb.setLength(0); + } + + scanner.close(); + return ret; + } + + private static String preprocess(String text) { + int index; + text = text.trim(); + while (text.startsWith("^") || text.startsWith("#") || text.startsWith("//") || text.startsWith("@")) + if ((index = text.indexOf("\n")) != -1) + text = text.substring(index + 1); + else { + text = ""; + break; + } + return text; // text.replace(" a ", " "); + } + + private Map allRecords = new HashMap(); + private int queryCounter = 0; + + public QueryRecord create(String text, int i, int j) { +// StringBuilder queryText = new StringBuilder(); +// for (String seq : text.split("\s")) { +// if (seq.length() == 0) continue; +// if (queryText.length() != 0) queryText.append(" "); +// queryText.append(seq); +// } +// text = queryText.toString(); + text = text.replaceAll("\\s+", " ").trim(); + QueryRecord ret = allRecords.get(text); + if (ret != null) return ret; + else { + if (i == -1) { + i = ++queryCounter; + } + + ret = new QueryRecord(this, text, i, j); + allRecords.put(text, ret); + return ret; + } + } + + public QueryRecord create(String text, int i) { + return create(text, i, 0); + } + + + public void remove(String queryText) { + allRecords.remove(queryText); + } + + public void put(String text, QueryRecord queryRecord) { + allRecords.put(text, queryRecord); + } + + public QueryRecord create(String queryText) { + return create(queryText, -1, 0); + } + +} diff --git a/src/uk/ac/ox/cs/pagoda/query/QueryRecord.java b/src/uk/ac/ox/cs/pagoda/query/QueryRecord.java new file mode 100644 index 0000000..ce92a67 --- /dev/null +++ b/src/uk/ac/ox/cs/pagoda/query/QueryRecord.java @@ -0,0 +1,562 @@ +package uk.ac.ox.cs.pagoda.query; + +import java.io.BufferedWriter; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.Map; +import java.util.Set; + +import org.semanticweb.HermiT.model.Atom; +import org.semanticweb.HermiT.model.AtomicConcept; +import org.semanticweb.HermiT.model.AtomicRole; +import org.semanticweb.HermiT.model.DLClause; +import org.semanticweb.HermiT.model.DLPredicate; +import org.semanticweb.HermiT.model.Variable; +import org.semanticweb.owlapi.model.OWLAxiom; +import org.semanticweb.owlapi.model.OWLClass; +import org.semanticweb.owlapi.model.OWLClassAssertionAxiom; +import org.semanticweb.owlapi.model.OWLDataProperty; +import org.semanticweb.owlapi.model.OWLDataPropertyAssertionAxiom; +import org.semanticweb.owlapi.model.OWLIndividual; +import org.semanticweb.owlapi.model.OWLLiteral; +import org.semanticweb.owlapi.model.OWLObjectProperty; +import org.semanticweb.owlapi.model.OWLObjectPropertyAssertionAxiom; +import org.semanticweb.owlapi.model.OWLOntology; +import org.semanticweb.owlapi.model.OWLOntologyManager; +import org.semanticweb.owlapi.model.OWLOntologyStorageException; + +import uk.ac.ox.cs.pagoda.hermit.DLClauseHelper; +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.Utility; + +public class QueryRecord { + + public static final String botQueryText = "SELECT ?X WHERE { ?X }"; + + private Step diffculty; + + private String queryText; + private int queryID = -1; + private String[][] answerVariables = null; + private Set soundAnswerTuples = new HashSet(); + private Set gapAnswerTuples = null; + + private QueryManager m_manager; + + public QueryRecord(QueryManager manager, String text, int id, int subID) { + m_manager =manager; + resetInfo(text, id, subID); + resetTimer(); + } + + public void resetInfo(String text, int id, int subid) { + queryID = id; + subID = subid; + stringQueryID = id + (subID == 0 ? "" : "_" + subID); + m_manager.remove(queryText); + m_manager.put(text, this); + queryClause = null; + answerVariables = ConjunctiveQueryHelper.getAnswerVariables(text); + queryText = text; // .replace("_:", "?"); + } + + public void resetTimer() { + int length = Step.values().length; + timer = new double[length]; + for (int i = 0; i < length; ++i) timer[i] = 0; + } + + public AnswerTuples getAnswers() { + if (processed()) + return getLowerBoundAnswers(); + + return getUpperBoundAnswers(); + } + + public AnswerTuples getLowerBoundAnswers() { + return new AnswerTuplesImp(answerVariables[0], soundAnswerTuples); + } + + public AnswerTuples getUpperBoundAnswers() { + return new AnswerTuplesImp(answerVariables[0], soundAnswerTuples, gapAnswerTuples); + } + + public boolean updateLowerBoundAnswers(AnswerTuples answerTuples) { + if (answerTuples == null) return false; + boolean update = false; + for (AnswerTuple tuple; answerTuples.isValid(); answerTuples.moveNext()) { + tuple = answerTuples.getTuple(); + if (!soundAnswerTuples.contains(tuple) && (gapAnswerTuples == null || gapAnswerTuples.contains(tuple))) { + soundAnswerTuples.add(tuple); + if (gapAnswerTuples != null) + gapAnswerTuples.remove(tuple); + update = true; + } + } + Utility.logInfo("The number of answers in the lower bound: " + soundAnswerTuples.size()); + + return update; + } + + public boolean updateUpperBoundAnswers(AnswerTuples answerTuples) { + return updateUpperBoundAnswers(answerTuples, false); + } + + 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; + } + + if (soundAnswerTuples.size() > 0) { + int number = 0; + for (; answerTuples.isValid(); answerTuples.moveNext()) { + ++number; + } + Utility.logInfo("The number of answers returned by the upper bound: " + number); + if (number <= soundAnswerTuples.size()) { + if (gapAnswerTuples != null) gapAnswerTuples.clear(); + else gapAnswerTuples = new HashSet(); + + Utility.logInfo("The number of answers in the upper bound: " + (soundAnswerTuples.size() + gapAnswerTuples.size())); + return false; + } + answerTuples.reset(); + } + + 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.hasAnonyIndividual()) { + tuple = AnswerTuple.create(extendedTuple, answerVariables[0].length); + if ((!toCheckAux || !tuple.hasAuxPredicate()) && !soundAnswerTuples.contains(tuple)) { + if (!toCheckAux && justCheck) return false; + tupleSet.add(extendedTuple); + } + } + } + + if (gapAnswerTuples == null) { + gapAnswerTuples = tupleSet; + + Utility.logInfo("The number of answers in the upper bound: " + (soundAnswerTuples.size() + gapAnswerTuples.size())); + return true; + } + + boolean update = false; + for (Iterator iter = gapAnswerTuples.iterator(); iter.hasNext(); ) { + tuple = iter.next(); + if (!tupleSet.contains(tuple)) { + iter.remove(); + update = true; + } + } + + Utility.logInfo("The number of answers in the upper bound: " + (soundAnswerTuples.size() + gapAnswerTuples.size())); + + return update; + } + +// private boolean containsAuxPredicate(String str) { +// return str.contains(Namespace.PAGODA_AUX) || str.contains("_AUX") || str.contains("owl#Nothing") || +// str.contains("internal:def"); +// } + + boolean processed = false; + + public void markAsProcessed() { + processed = true; + } + + public boolean processed() { + if (gapAnswerTuples != null && gapAnswerTuples.isEmpty()) processed = true; + return processed; + } + + public String[] getDistinguishedVariables() { + return answerVariables[1]; + } + + public String[] getAnswerVariables() { + return answerVariables[0]; + } + + public String[][] getVariables() { + return answerVariables; + } + + public String getQueryText() { + return queryText; + } + + String stringQueryID = null; + + public String getQueryID() { + return stringQueryID; + } + + public AnswerTuples getGapAnswers() { + return new AnswerTuplesImp(answerVariables[0], gapAnswerTuples); + } + + public String toString() { + return queryText; + } + + public static final String SEPARATOR = "----------------------------------------"; + + public void outputAnswers(BufferedWriter writer) throws IOException { + + int answerCounter = soundAnswerTuples.size(); + if (!processed()) answerCounter += gapAnswerTuples.size(); + + Utility.logInfo("The number of answer tuples: " + answerCounter); + + if (writer != null) { + writer.write("-------------- Query " + queryID + " ---------------------"); + writer.newLine(); + writer.write(queryText); + writer.newLine(); + StringBuilder space = new StringBuilder(); + int arity = getArity(), varSpace = 0; + for (int i = 0; i < arity; ++i) + varSpace += answerVariables[0][i].length(); + for (int i = 0; i < (SEPARATOR.length() - varSpace) / (arity + 1); ++i) + space.append(" "); + for (int i = 0; i < getArity(); ++i) { + writer.write(space.toString()); + writer.write(answerVariables[0][i]); + } + writer.newLine(); + writer.write(SEPARATOR); + writer.newLine(); + for (AnswerTuple tuple: soundAnswerTuples) { + writer.write(tuple.toString()); + writer.newLine(); + } + if (!processed()) + for (AnswerTuple tuple: gapAnswerTuples) { + writer.write("*"); + writer.write(tuple.toString()); + writer.newLine(); + } +// writer.write(SEPARATOR); + writer.newLine(); + } + + } + + public void outputTimes() { + for (Step step: Step.values()) { + Utility.logDebug("time for " + step + ": " + timer[step.ordinal()]); + } + } + + public String outputSoundAnswerTuple() { + StringBuilder builder = new StringBuilder(); + for (AnswerTuple tuple: soundAnswerTuples) + builder.append(tuple.toString()).append(Utility.LINE_SEPARATOR); + return builder.toString(); + } + + public String outputGapAnswerTuple() { + StringBuilder builder = new StringBuilder(); + for (AnswerTuple tuple: gapAnswerTuples) + builder.append(tuple.toString()).append(Utility.LINE_SEPARATOR); + return builder.toString(); + } + + public void setDifficulty(Step step) { + this.diffculty = step; + } + + public Step getDifficulty() { + return diffculty; + } + + OWLOntology relevantOntology = null; + Set relevantClauses = new HashSet(); + + public void setRelevantOntology(OWLOntology knowledgebase) { + relevantOntology = knowledgebase; + } + + public OWLOntology getRelevantOntology() { + return relevantOntology; + } + + public void saveRelevantOntology(String filename) { + if (relevantOntology == null) return ; + OWLOntologyManager manager = relevantOntology.getOWLOntologyManager(); + try { + FileOutputStream outputStream = new FileOutputStream(filename); + manager.saveOntology(relevantOntology, outputStream); + outputStream.close(); + } catch (OWLOntologyStorageException e) { + e.printStackTrace(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void saveRelevantClause() { + if (relevantClauses == null) return ; + GeneralProgram p = new GeneralProgram(relevantClauses, relevantOntology); + p.save(); + } + + + public void removeUpperBoundAnswers(Collection answers) { + for (AnswerTuple answer: answers) { +// if (soundAnswerTuples.contains(answer)) +// Utility.logError("The answer (" + answer + ") cannot be removed, because it is in the lower bound."); + if (!gapAnswerTuples.contains(answer)) + Utility.logError("The answer (" + answer + ") cannot be removed, because it is not in the upper bound."); + gapAnswerTuples.remove(answer); + } + } + + + public void addLowerBoundAnswers(Collection answers) { + for (AnswerTuple answer: answers) { + if (!gapAnswerTuples.contains(answer)) + Utility.logError("The answer (" + answer + ") cannot be added, because it is not in the upper bound."); + gapAnswerTuples.remove(answer); + + 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); + } + } + + public int getNoOfSoundAnswers() { + return soundAnswerTuples.size(); + } + + public enum Step {LowerBound, UpperBound, ELLowerBound, + Fragment, FragmentRefinement, Summarisation, Dependency, FullReasoning}; + + double[] timer; + + public void addProcessingTime(Step step, double time) { + timer[step.ordinal()] += time; + } + + public int getArity() { + return answerVariables[0].length; + } + + public static Collection collectQueryTexts(Collection queryRecords) { + Collection texts = new LinkedList(); + for (QueryRecord record: queryRecords) + texts.add(record.queryText); + return texts; + } + + public void addRelevantClauses(DLClause clause) { + relevantClauses.add(clause); + } + + public Set getRelevantClauses() { + return relevantClauses; + } + + public void clearClauses() { + relevantClauses.clear(); + } + + public boolean isHorn() { + for (DLClause clause: relevantClauses) + if (clause.getHeadLength() > 1) + return false; + return true; + } + + public void saveABoxInTurtle(String filename) { + try { + BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filename))); + OWLIndividual a, b; + StringBuilder builder = new StringBuilder(); + for (OWLAxiom axiom: relevantOntology.getABoxAxioms(true)) { + if (axiom instanceof OWLClassAssertionAxiom) { + OWLClassAssertionAxiom classAssertion = (OWLClassAssertionAxiom) axiom; + OWLClass c = (OWLClass) classAssertion.getClassExpression(); + a = classAssertion.getIndividual(); + builder.append(a.toString()).append(" <").append(Namespace.RDF_TYPE).append("> ").append(c.toString()); + } + else if (axiom instanceof OWLObjectPropertyAssertionAxiom) { + OWLObjectPropertyAssertionAxiom propertyAssertion = (OWLObjectPropertyAssertionAxiom) axiom; + OWLObjectProperty p = (OWLObjectProperty) propertyAssertion.getProperty(); + a = propertyAssertion.getSubject(); + b = propertyAssertion.getObject(); + builder.append(a.toString()).append(" ").append(p.toString()).append(" ").append(b.toString()); + } + else if (axiom instanceof OWLDataPropertyAssertionAxiom) { + OWLDataPropertyAssertionAxiom propertyAssertion = (OWLDataPropertyAssertionAxiom) axiom; + OWLDataProperty p = (OWLDataProperty) propertyAssertion.getProperty(); + a = propertyAssertion.getSubject(); + OWLLiteral l = propertyAssertion.getObject(); + builder.append(a.toString()).append(" ").append(p.toString()).append(" ").append(l.toString()); + } + + writer.write(builder.toString()); + writer.write(" ."); + writer.newLine(); + builder.setLength(0); + } + writer.close(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + + } + } + + int subID; + + public void updateSubID() { + ++subID; + stringQueryID = String.valueOf(queryID) + "_" + subID; + } + + DLClause queryClause = null; + + public DLClause getClause() { + if (queryClause != null) + return queryClause; + return queryClause = DLClauseHelper.getQuery(queryText, null); + } + + public boolean isBottom() { + return queryID == 0; + } + + public int getNoOfCompleteAnswers() { + return soundAnswerTuples.size() + gapAnswerTuples.size(); + } + + public int getSubID() { + return subID; + } + + public boolean hasSameGapAnswers(QueryRecord that) { + return gapAnswerTuples.containsAll(that.gapAnswerTuples) && that.gapAnswerTuples.containsAll(gapAnswerTuples); + } + + public void dispose() { + m_manager.remove(queryText); + if (gapAnswerTuples != null) gapAnswerTuples = null; + if (soundAnswerTuples != null) soundAnswerTuples = null; + if (relevantClauses != null) relevantClauses.clear(); + if (relevantOntology != null) + relevantOntology.getOWLOntologyManager().removeOntology(relevantOntology); + answerVariables = null; + } + + public boolean canBeEncodedIntoAtom() { + // FIXME + return true; +// return false; + } + + public boolean isPredicate(AnswerTuple a, int i) { + Atom[] atoms = getClause().getBodyAtoms(); + Variable v = Variable.create(answerVariables[1][i]); + String iri; + for (Atom atom: atoms) { + DLPredicate p = atom.getDLPredicate(); + if (p instanceof AtomicConcept) { + if (((AtomicConcept) p).getIRI().equals(v.toString())) return true; + } + else if (p instanceof AtomicRole) { + iri = ((AtomicRole) p).getIRI(); + if (iri.equals(v.toString())) return true; + if (iri.startsWith("?")) + iri = a.getGroundTerm(i).toString(); + if (iri.equals(Namespace.RDF_TYPE) && atom.getArgument(1).equals(v)) return true; + } + } + return false; + } + + public String[] getExtendedQueryText() { + String[] ret = new String[2]; + int index = queryText.toUpperCase().indexOf(" WHERE"); + String extendedSelect = queryText.substring(0, index); + String extendedWhere= queryText.substring(index + 1), fullyExtendedWhere = queryText.substring(index + 1); + + String sub, obj; + Map> links = new HashMap>(); + Set list; + for (Atom atom: getClause().getBodyAtoms()) + if (atom.getDLPredicate() instanceof AtomicRole && atom.getArgument(0) instanceof Variable && atom.getArgument(1) instanceof Variable) { + sub = atom.getArgumentVariable(0).getName(); + obj = atom.getArgumentVariable(1).getName(); + if ((list = links.get(sub)) == null) + links.put(sub, list = new HashSet()); + list.add(obj); + if ((list = links.get(obj)) == null) + links.put(obj, list = new HashSet()); + list.add(sub); + } + + StringBuilder extra = new StringBuilder(), fullyExtra = new StringBuilder(); +// if (answerVariables[0] != answerVariables[1]) { + for (int i = answerVariables[0].length; i < answerVariables[1].length; ++i) { +// for (int i = 0; i < answerVariables[1].length; ++i) { + fullyExtra.append(" . ?").append(answerVariables[1][i]).append(" a <").append(Namespace.PAGODA_ORIGINAL).append(">"); + if ((list = links.get(answerVariables[1][i])) == null || list.size() < 2) ; + else { + extra.append(" . ?").append(answerVariables[1][i]).append(" a <").append(Namespace.PAGODA_ORIGINAL).append(">"); + } + } + + if (extra.length() > 0) { + extra.append(" }"); + extendedWhere = extendedWhere.replace(" }", extendedWhere.contains(". }") ? extra.substring(2) : extra.toString()); + } + + if (fullyExtra.length() > 0) { + fullyExtra.append(" }"); + fullyExtendedWhere = fullyExtendedWhere.replace(" }", fullyExtendedWhere.contains(". }") ? fullyExtra.substring(2) : fullyExtra.toString()); + } +// } + + ret[0] = extendedSelect + " " + fullyExtendedWhere; + + extra.setLength(0); + if (answerVariables[0] != answerVariables[1]) { + for (int i = answerVariables[0].length; i < answerVariables[1].length; ++i) + extra.append(" ?").append(answerVariables[1][i]); + extendedSelect = extendedSelect + extra.toString(); + } + ret[1] = extendedSelect + " " + extendedWhere; + + return ret; + } + + public boolean hasNonAnsDistinguishedVariables() { + return answerVariables[1].length > answerVariables[0].length; + } + + +} diff --git a/src/uk/ac/ox/cs/pagoda/query/rollup/QueryGraph.java b/src/uk/ac/ox/cs/pagoda/query/rollup/QueryGraph.java new file mode 100644 index 0000000..11b0c75 --- /dev/null +++ b/src/uk/ac/ox/cs/pagoda/query/rollup/QueryGraph.java @@ -0,0 +1,383 @@ +package uk.ac.ox.cs.pagoda.query.rollup; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +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.Individual; +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.OWLClass; +import org.semanticweb.owlapi.model.OWLClassExpression; +import org.semanticweb.owlapi.model.OWLClassExpressionVisitorEx; +import org.semanticweb.owlapi.model.OWLDataAllValuesFrom; +import org.semanticweb.owlapi.model.OWLDataExactCardinality; +import org.semanticweb.owlapi.model.OWLDataFactory; +import org.semanticweb.owlapi.model.OWLDataHasValue; +import org.semanticweb.owlapi.model.OWLDataMaxCardinality; +import org.semanticweb.owlapi.model.OWLDataMinCardinality; +import org.semanticweb.owlapi.model.OWLDataSomeValuesFrom; +import org.semanticweb.owlapi.model.OWLIndividual; +import org.semanticweb.owlapi.model.OWLLiteral; +import org.semanticweb.owlapi.model.OWLNamedIndividual; +import org.semanticweb.owlapi.model.OWLObjectAllValuesFrom; +import org.semanticweb.owlapi.model.OWLObjectComplementOf; +import org.semanticweb.owlapi.model.OWLObjectExactCardinality; +import org.semanticweb.owlapi.model.OWLObjectHasSelf; +import org.semanticweb.owlapi.model.OWLObjectHasValue; +import org.semanticweb.owlapi.model.OWLObjectIntersectionOf; +import org.semanticweb.owlapi.model.OWLObjectMaxCardinality; +import org.semanticweb.owlapi.model.OWLObjectMinCardinality; +import org.semanticweb.owlapi.model.OWLObjectOneOf; +import org.semanticweb.owlapi.model.OWLObjectPropertyExpression; +import org.semanticweb.owlapi.model.OWLObjectSomeValuesFrom; +import org.semanticweb.owlapi.model.OWLObjectUnionOf; +import org.semanticweb.owlapi.model.OWLOntology; + +public class QueryGraph { + + Set freeVars = new HashSet(); + Set existVars = new HashSet(); + Set constants = new HashSet(); + + MultiMap concepts = new MultiMap(); + MultiMap rollable_edges = new MultiMap(); + MultiMap edges = new MultiMap(); + OWLOntology ontology; + OWLDataFactory factory; + + public QueryGraph(Atom[] bodyAtoms, String[] distinguishedVars, OWLOntology onto) { + for (String vName: distinguishedVars) + freeVars.add(Variable.create(vName)); + + ontology = onto; + factory = onto.getOWLOntologyManager().getOWLDataFactory(); + + for (Atom atom: bodyAtoms) { + if (atom.getArity() == 1) { + updateExistentiallyVariables(atom.getArgumentVariable(0)); + IRI iri = IRI.create(((AtomicConcept) atom.getDLPredicate()).getIRI()); + if (ontology.containsClassInSignature(iri)) + concepts.add(atom.getArgument(0), factory.getOWLClass(IRI.create(((AtomicConcept) atom.getDLPredicate()).getIRI()))); + } + else if (atom.getArity() == 2) { + updateExistentiallyVariables(atom.getArgumentVariable(0)); + updateExistentiallyVariables(atom.getArgumentVariable(1)); + if (atom.getArgument(0).equals(atom.getArgument(1)) && atom.getArgument(0) instanceof Variable) { + concepts.add(atom.getArgument(0), factory.getOWLObjectHasSelf(factory.getOWLObjectProperty(IRI.create(((AtomicRole) atom.getDLPredicate()).getIRI())))); + } + else createEdges(atom.getArgument(0), (AtomicRole) atom.getDLPredicate(), atom.getArgument(1)); + } + } + + rollup(); + } + + private void updateExistentiallyVariables(Variable argumentVariable) { + if (freeVars.contains(argumentVariable)) return ; + existVars.add(argumentVariable); + } + + public void createEdges(Term u, AtomicRole r, Term v) { + if (ontology.containsDataPropertyInSignature(IRI.create(r.getIRI()))) { +// edges.add(u, new DataEdge(r, v)); + Constant c = (Constant) v; + OWLLiteral l = factory.getOWLLiteral(c.getLexicalForm(), c.getDatatypeURI()); + concepts.add(u, factory.getOWLDataHasValue(factory.getOWLDataProperty(IRI.create(r.getIRI())), l)); + } + else { + boolean rollable = existVars.contains(u) || existVars.contains(v); + + ObjectEdge edge = new ObjectEdge(r, v, false); + if (rollable) { + rollable_edges.add(u, edge); + edge = new ObjectEdge(r, u, true); + rollable_edges.add(v, edge); + } + else edges.add(u, edge); + + } + } + + private void rollup() { + for (boolean updated = true; updated; ) { + updated = false; + + Set set; + for (Variable var: existVars) { + if ((set = rollable_edges.map.get(var)) != null && set.size() == 1) { + updated = true; + ObjectEdge edge = set.iterator().next(); + rollupEdge(edge.v, edge.p.getInverseProperty().getSimplified(), var, true); + set.clear(); + } + } + if (updated) continue; + + for (Variable var: existVars) { + set = rollable_edges.map.get(var); + if (set == null) continue; + for (Iterator iter = set.iterator(); iter.hasNext(); ) { + ObjectEdge edge = iter.next(); + if (constants.contains(edge.v) || freeVars.contains(edge.v)) { + updated = true; + rollupEdge(var, edge.p, edge.v, false); + iter.remove(); + } + } + } + } + + } + + private void rollupEdge(Term u, OWLObjectPropertyExpression op, Term v, boolean inverse) { + if (existVars.contains(v)) { + concepts.add(u, factory.getOWLObjectSomeValuesFrom(op, factory.getOWLObjectIntersectionOf(concepts.get(v)))); + } + else { + OWLIndividual obj = getOWLIndividual(v); + concepts.add(u, factory.getOWLObjectHasValue(op, obj)); + } + + if (inverse) + removeRollableEdge(u, op, v); + else + removeRollableEdge(v, op.getInverseProperty().getSimplified(), u); + } + + private void removeRollableEdge(Term u, OWLObjectPropertyExpression op, Term v) { + Set set = rollable_edges.get(u); + ObjectEdge edge; + if (set != null) + for (Iterator iter = set.iterator(); iter.hasNext(); ) { + edge = iter.next(); + if (edge.p.equals(op) && edge.v.equals(v)) iter.remove(); + } + } + + OWLNamedIndividual getOWLIndividual(Term t) { + if (freeVars.contains(t)) + return new VariableIndividual((Variable) t); + else if (t instanceof Variable) + return null; + else + return factory.getOWLNamedIndividual(IRI.create(((Individual) t).getIRI())); + } + + class ObjectEdge { + OWLObjectPropertyExpression p; + Term v; + + public ObjectEdge(AtomicRole r, Term t, boolean inverse) { + p = factory.getOWLObjectProperty(IRI.create(r.getIRI())); + if (inverse) p = p.getInverseProperty(); + v = t; + + } + } + + class MultiMap { + + HashMap> map = new HashMap>(); + + void add(K key, V value) { + Set list = map.get(key); + if (list == null) + map.put(key, list = new HashSet()); + list.add(value); + } + + public Set get(K v) { + return map.get(v); + } + + public boolean isEmpty() { + for (Map.Entry> entry: map.entrySet()) + if (!entry.getValue().isEmpty()) + return false; + return true; + } + + } + + public Set getPropertyAssertions(Map assignment) { + OWLIndividual sub, obj; + Set axioms = new HashSet(); + for (Map.Entry> entry: edges.map.entrySet()) { + sub = factory.getOWLNamedIndividual(IRI.create(getIndividual(entry.getKey(), assignment).getIRI())); + for (ObjectEdge edge: entry.getValue()) { + obj = factory.getOWLNamedIndividual(IRI.create(getIndividual(edge.v, assignment).getIRI())); + axioms.add(factory.getOWLObjectPropertyAssertionAxiom(edge.p, sub, obj)); + } + } + return axioms; + } + + public Set getAssertions(Map assignment) { + if (!rollable_edges.isEmpty()) return null; + + OWLIndividual sub; + Visitor visitor = new Visitor(factory, assignment); + Set axioms = getPropertyAssertions(assignment); + for (Map.Entry> entry: concepts.map.entrySet()) { + if (existVars.contains(entry.getKey())) continue; + sub = factory.getOWLNamedIndividual(IRI.create(getIndividual(entry.getKey(), assignment).getIRI())); + for (OWLClassExpression clsExp: entry.getValue()) { + axioms.add(factory.getOWLClassAssertionAxiom(clsExp.accept(visitor), sub)); + } + } + return axioms; + } + + private Individual getIndividual(Term key, Map assignment) { + if (key instanceof Individual) + return (Individual) key; + else + return (Individual) assignment.get(key); + } +} + +class Visitor implements OWLClassExpressionVisitorEx { + + OWLDataFactory factory; + Map assignment; + + public Visitor(OWLDataFactory factory, Map assignment) { + this.factory = factory; + this.assignment = assignment; + } + + @Override + public OWLClassExpression visit(OWLClass ce) { + // TODO Auto-generated method stub + return ce; + } + + @Override + public OWLClassExpression visit(OWLObjectIntersectionOf ce) { + Set clsExps = new HashSet(); + OWLClassExpression newExp; + boolean updated = false; + for (OWLClassExpression clsExp: ce.asConjunctSet()) { + clsExps.add(newExp = clsExp.accept(this)); + if (newExp != clsExp) updated = true; + } + + if (updated) return factory.getOWLObjectIntersectionOf(clsExps); + else return ce; + } + + @Override + public OWLClassExpression visit(OWLObjectUnionOf ce) { + // TODO Auto-generated method stub + return ce; + } + + @Override + public OWLClassExpression visit(OWLObjectComplementOf ce) { + // TODO Auto-generated method stub + return ce; + } + + @Override + public OWLClassExpression visit(OWLObjectSomeValuesFrom ce) { + OWLClassExpression newFiller = ce.getFiller().accept(this); + if (newFiller == ce.getFiller()) return ce; + return factory.getOWLObjectSomeValuesFrom(ce.getProperty(), newFiller); + } + + @Override + public OWLClassExpression visit(OWLObjectAllValuesFrom ce) { + // TODO Auto-generated method stub + return ce; + } + + @Override + public OWLClassExpression visit(OWLObjectHasValue ce) { + if (ce.getFiller() instanceof VariableIndividual) { + Individual c = (Individual) assignment.get(((VariableIndividual) ce.getFiller()).var); + OWLIndividual l = factory.getOWLNamedIndividual(IRI.create(c.getIRI())); + return factory.getOWLObjectHasValue(ce.getProperty(), l); + } + return ce; + } + + @Override + public OWLClassExpression visit(OWLObjectMinCardinality ce) { + // TODO Auto-generated method stub + return ce; + } + + @Override + public OWLClassExpression visit(OWLObjectExactCardinality ce) { + // TODO Auto-generated method stub + return ce; + } + + @Override + public OWLClassExpression visit(OWLObjectMaxCardinality ce) { + // TODO Auto-generated method stub + return ce; + } + + @Override + public OWLClassExpression visit(OWLObjectHasSelf ce) { + // TODO Auto-generated method stub + return ce; + } + + @Override + public OWLClassExpression visit(OWLObjectOneOf ce) { + // TODO Auto-generated method stub + return ce; + } + + @Override + public OWLClassExpression visit(OWLDataSomeValuesFrom ce) { + // TODO Auto-generated method stub + return ce; + } + + @Override + public OWLClassExpression visit(OWLDataAllValuesFrom ce) { + // TODO Auto-generated method stub + return ce; + } + + @Override + public OWLClassExpression visit(OWLDataHasValue ce) { + if (ce.getFiller() instanceof VariableConstant) { + Constant c = (Constant) assignment.get(((VariableConstant) ce.getFiller()).var); + OWLLiteral l = factory.getOWLLiteral(c.getLexicalForm(), c.getDatatypeURI()); + return factory.getOWLDataHasValue(ce.getProperty(), l); + } + return ce; + } + + @Override + public OWLClassExpression visit(OWLDataMinCardinality ce) { + // TODO Auto-generated method stub + return ce; + } + + @Override + public OWLClassExpression visit(OWLDataExactCardinality ce) { + // TODO Auto-generated method stub + return ce; + } + + @Override + public OWLClassExpression visit(OWLDataMaxCardinality ce) { + // TODO Auto-generated method stub + return ce; + } + +} \ No newline at end of file diff --git a/src/uk/ac/ox/cs/pagoda/query/rollup/VariableConstant.java b/src/uk/ac/ox/cs/pagoda/query/rollup/VariableConstant.java new file mode 100644 index 0000000..3140fa4 --- /dev/null +++ b/src/uk/ac/ox/cs/pagoda/query/rollup/VariableConstant.java @@ -0,0 +1,227 @@ +package uk.ac.ox.cs.pagoda.query.rollup; + +import java.util.Set; + +import org.semanticweb.HermiT.model.Variable; +import org.semanticweb.owlapi.model.OWLAnnotationValueVisitor; +import org.semanticweb.owlapi.model.OWLAnnotationValueVisitorEx; +import org.semanticweb.owlapi.model.OWLAnonymousIndividual; +import org.semanticweb.owlapi.model.OWLClass; +import org.semanticweb.owlapi.model.OWLClassExpression; +import org.semanticweb.owlapi.model.OWLDataProperty; +import org.semanticweb.owlapi.model.OWLDataVisitor; +import org.semanticweb.owlapi.model.OWLDataVisitorEx; +import org.semanticweb.owlapi.model.OWLDatatype; +import org.semanticweb.owlapi.model.OWLEntity; +import org.semanticweb.owlapi.model.OWLLiteral; +import org.semanticweb.owlapi.model.OWLNamedIndividual; +import org.semanticweb.owlapi.model.OWLObject; +import org.semanticweb.owlapi.model.OWLObjectProperty; +import org.semanticweb.owlapi.model.OWLObjectVisitor; +import org.semanticweb.owlapi.model.OWLObjectVisitorEx; + +class VariableConstant implements OWLLiteral { + + /** + * + */ + private static final long serialVersionUID = 5089014375729171030L; + Variable var; + + public VariableConstant(Variable v) { + var = v; + } + + @Override + public Set getSignature() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Set getAnonymousIndividuals() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Set getClassesInSignature() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Set getDataPropertiesInSignature() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Set getObjectPropertiesInSignature() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Set getIndividualsInSignature() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Set getDatatypesInSignature() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Set getNestedClassExpressions() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void accept(OWLObjectVisitor visitor) { + // TODO Auto-generated method stub + + } + + @Override + public O accept(OWLObjectVisitorEx visitor) { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isTopEntity() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isBottomEntity() { + // TODO Auto-generated method stub + return false; + } + + @Override + public int compareTo(OWLObject arg0) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public boolean containsEntityInSignature(OWLEntity owlEntity) { + // TODO Auto-generated method stub + return false; + } + + @Override + public void accept(OWLAnnotationValueVisitor visitor) { + // TODO Auto-generated method stub + + } + + @Override + public O accept(OWLAnnotationValueVisitorEx visitor) { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isRDFPlainLiteral() { + // TODO Auto-generated method stub + return false; + } + + @Override + public String getLiteral() { + // TODO Auto-generated method stub + return null; + } + + @Override + public OWLDatatype getDatatype() { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean hasLang() { + // TODO Auto-generated method stub + return false; + } + + @Override + public String getLang() { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean hasLang(String lang) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isInteger() { + // TODO Auto-generated method stub + return false; + } + + @Override + public int parseInteger() throws NumberFormatException { + // TODO Auto-generated method stub + return 0; + } + + @Override + public boolean isBoolean() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean parseBoolean() throws NumberFormatException { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isDouble() { + // TODO Auto-generated method stub + return false; + } + + @Override + public double parseDouble() throws NumberFormatException { + // TODO Auto-generated method stub + return 0; + } + + @Override + public boolean isFloat() { + // TODO Auto-generated method stub + return false; + } + + @Override + public float parseFloat() throws NumberFormatException { + // TODO Auto-generated method stub + return 0; + } + + @Override + public void accept(OWLDataVisitor visitor) { + // TODO Auto-generated method stub + + } + + @Override + public O accept(OWLDataVisitorEx visitor) { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/src/uk/ac/ox/cs/pagoda/query/rollup/VariableIndividual.java b/src/uk/ac/ox/cs/pagoda/query/rollup/VariableIndividual.java new file mode 100644 index 0000000..53288e5 --- /dev/null +++ b/src/uk/ac/ox/cs/pagoda/query/rollup/VariableIndividual.java @@ -0,0 +1,416 @@ +package uk.ac.ox.cs.pagoda.query.rollup; + +import java.util.Map; +import java.util.Set; + +import org.semanticweb.HermiT.model.Variable; +import org.semanticweb.owlapi.model.EntityType; +import org.semanticweb.owlapi.model.IRI; +import org.semanticweb.owlapi.model.OWLAnnotation; +import org.semanticweb.owlapi.model.OWLAnnotationAssertionAxiom; +import org.semanticweb.owlapi.model.OWLAnnotationProperty; +import org.semanticweb.owlapi.model.OWLAnonymousIndividual; +import org.semanticweb.owlapi.model.OWLAxiom; +import org.semanticweb.owlapi.model.OWLClass; +import org.semanticweb.owlapi.model.OWLClassExpression; +import org.semanticweb.owlapi.model.OWLDataProperty; +import org.semanticweb.owlapi.model.OWLDataPropertyExpression; +import org.semanticweb.owlapi.model.OWLDatatype; +import org.semanticweb.owlapi.model.OWLEntity; +import org.semanticweb.owlapi.model.OWLEntityVisitor; +import org.semanticweb.owlapi.model.OWLEntityVisitorEx; +import org.semanticweb.owlapi.model.OWLIndividual; +import org.semanticweb.owlapi.model.OWLIndividualVisitor; +import org.semanticweb.owlapi.model.OWLIndividualVisitorEx; +import org.semanticweb.owlapi.model.OWLLiteral; +import org.semanticweb.owlapi.model.OWLNamedIndividual; +import org.semanticweb.owlapi.model.OWLNamedObjectVisitor; +import org.semanticweb.owlapi.model.OWLObject; +import org.semanticweb.owlapi.model.OWLObjectProperty; +import org.semanticweb.owlapi.model.OWLObjectPropertyExpression; +import org.semanticweb.owlapi.model.OWLObjectVisitor; +import org.semanticweb.owlapi.model.OWLObjectVisitorEx; +import org.semanticweb.owlapi.model.OWLOntology; + +class VariableIndividual implements OWLNamedIndividual { + + /** + * + */ + private static final long serialVersionUID = 3002966246639516395L; + Variable var; + + public VariableIndividual(Variable v) { + var = v; + } + + @Override + public boolean isNamed() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isAnonymous() { + // TODO Auto-generated method stub + return false; + } + + @Override + public OWLNamedIndividual asOWLNamedIndividual() { + // TODO Auto-generated method stub + return null; + } + + @Override + public OWLAnonymousIndividual asOWLAnonymousIndividual() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Set getTypes(OWLOntology ontology) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Set getTypes(Set ontologies) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Map> getObjectPropertyValues( + OWLOntology ontology) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Set getObjectPropertyValues( + OWLObjectPropertyExpression property, OWLOntology ontology) { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean hasObjectPropertyValue(OWLObjectPropertyExpression property, + OWLIndividual individual, OWLOntology ontology) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean hasDataPropertyValue(OWLDataPropertyExpression property, + OWLLiteral value, OWLOntology ontology) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean hasNegativeObjectPropertyValue( + OWLObjectPropertyExpression property, OWLIndividual individual, + OWLOntology ontology) { + // TODO Auto-generated method stub + return false; + } + + @Override + public Map> getNegativeObjectPropertyValues( + OWLOntology ontology) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Map> getDataPropertyValues( + OWLOntology ontology) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Set getDataPropertyValues( + OWLDataPropertyExpression property, OWLOntology ontology) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Map> getNegativeDataPropertyValues( + OWLOntology ontology) { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean hasNegativeDataPropertyValue( + OWLDataPropertyExpression property, OWLLiteral literal, + OWLOntology ontology) { + // TODO Auto-generated method stub + return false; + } + + @Override + public Set getSameIndividuals(OWLOntology ontology) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Set getDifferentIndividuals(OWLOntology ontology) { + // TODO Auto-generated method stub + return null; + } + + @Override + public String toStringID() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void accept(OWLIndividualVisitor visitor) { + // TODO Auto-generated method stub + + } + + @Override + public O accept(OWLIndividualVisitorEx visitor) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Set getSignature() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Set getAnonymousIndividuals() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Set getClassesInSignature() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Set getDataPropertiesInSignature() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Set getObjectPropertiesInSignature() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Set getIndividualsInSignature() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Set getDatatypesInSignature() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Set getNestedClassExpressions() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void accept(OWLObjectVisitor visitor) { + // TODO Auto-generated method stub + + } + + @Override + public O accept(OWLObjectVisitorEx visitor) { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isTopEntity() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isBottomEntity() { + // TODO Auto-generated method stub + return false; + } + + @Override + public int compareTo(OWLObject arg0) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public boolean containsEntityInSignature(OWLEntity owlEntity) { + // TODO Auto-generated method stub + return false; + } + + @Override + public EntityType getEntityType() { + // TODO Auto-generated method stub + return null; + } + + @Override + public E getOWLEntity(EntityType entityType) { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isType(EntityType entityType) { + // TODO Auto-generated method stub + return false; + } + + @Override + public Set getAnnotations(OWLOntology ontology) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Set getAnnotations(OWLOntology ontology, + OWLAnnotationProperty annotationProperty) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Set getAnnotationAssertionAxioms( + OWLOntology ontology) { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isBuiltIn() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isOWLClass() { + // TODO Auto-generated method stub + return false; + } + + @Override + public OWLClass asOWLClass() { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isOWLObjectProperty() { + // TODO Auto-generated method stub + return false; + } + + @Override + public OWLObjectProperty asOWLObjectProperty() { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isOWLDataProperty() { + // TODO Auto-generated method stub + return false; + } + + @Override + public OWLDataProperty asOWLDataProperty() { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isOWLNamedIndividual() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isOWLDatatype() { + // TODO Auto-generated method stub + return false; + } + + @Override + public OWLDatatype asOWLDatatype() { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isOWLAnnotationProperty() { + // TODO Auto-generated method stub + return false; + } + + @Override + public OWLAnnotationProperty asOWLAnnotationProperty() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Set getReferencingAxioms(OWLOntology ontology) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Set getReferencingAxioms(OWLOntology ontology, + boolean includeImports) { + // TODO Auto-generated method stub + return null; + } + + @Override + public void accept(OWLEntityVisitor visitor) { + // TODO Auto-generated method stub + + } + + @Override + public O accept(OWLEntityVisitorEx visitor) { + // TODO Auto-generated method stub + return null; + } + + @Override + public IRI getIRI() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void accept(OWLNamedObjectVisitor visitor) { + // TODO Auto-generated method stub + + } + +} -- cgit v1.2.3