From 870eb35e38f746ed73f233070dcf3bdaf4687e02 Mon Sep 17 00:00:00 2001 From: RncLsn Date: Sat, 9 May 2015 14:26:28 +0100 Subject: Adding (not completed) log of partial answers in Json. --- src/uk/ac/ox/cs/pagoda/query/AnswerTuple.java | 65 ++++++++++---- .../cs/pagoda/query/DeserializedQueryRecord.java | 9 ++ src/uk/ac/ox/cs/pagoda/query/QueryRecord.java | 98 +++++++++++++--------- .../ac/ox/cs/pagoda/reasoner/MyQueryReasoner.java | 36 ++++++-- src/uk/ac/ox/cs/pagoda/reasoner/QueryReasoner.java | 12 +-- src/uk/ac/ox/cs/pagoda/util/Utility.java | 15 +++- 6 files changed, 157 insertions(+), 78 deletions(-) create mode 100644 src/uk/ac/ox/cs/pagoda/query/DeserializedQueryRecord.java (limited to 'src/uk/ac') diff --git a/src/uk/ac/ox/cs/pagoda/query/AnswerTuple.java b/src/uk/ac/ox/cs/pagoda/query/AnswerTuple.java index 183cbe1..cd86282 100644 --- a/src/uk/ac/ox/cs/pagoda/query/AnswerTuple.java +++ b/src/uk/ac/ox/cs/pagoda/query/AnswerTuple.java @@ -15,6 +15,9 @@ import uk.ac.ox.cs.pagoda.util.Namespace; import java.lang.reflect.Type; import java.util.HashMap; import java.util.Map; +import java.util.StringTokenizer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class AnswerTuple { @@ -42,31 +45,31 @@ public class AnswerTuple { for (int i = 0; i < arity; ++i) m_tuple[i] = sup.m_tuple[i]; } - private AnswerTuple(String m_str) { - this.m_str = m_str; - } +// private AnswerTuple(String m_str) { +// this.m_str = m_str; +// } 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; +// 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; + 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()); + return false; + return true; +// return toString().equals(obj.toString()); } public String toString() { @@ -77,7 +80,7 @@ public class AnswerTuple { 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()); + sb.append(m_tuple[i].toString()); } else { Literal l = (Literal) m_tuple[i]; @@ -146,10 +149,40 @@ public class AnswerTuple { } - public class AnswerTupleDeserializer implements JsonDeserializer { + static final Pattern owlLiteralRegex = Pattern.compile("^\"(?[^@]+(@(?.+))?)\"(^^<(?.+)>)?$"); + + public static class AnswerTupleDeserializer implements JsonDeserializer { public AnswerTuple deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - return new AnswerTuple(json.getAsJsonPrimitive().getAsString()); + String tuplesString = json.getAsJsonPrimitive().getAsString(); + StringTokenizer tokenizer = new StringTokenizer(SEPARATOR); + GroundTerm[] terms = new GroundTerm[tokenizer.countTokens()]; + + // TODO test parsing + for (int i = 0; i < tokenizer.countTokens(); i++) { + String token = tokenizer.nextToken(); + if (token.charAt(0) == '<') { + terms[i] = uk.ac.ox.cs.JRDFox.model.Individual.create(token.substring(1,token.length()-1)); + } + else if (token.charAt(0) == '"') { + Matcher matcher = owlLiteralRegex.matcher(token); + if(matcher.matches()) { + String lexicalForm = matcher.group("lexicalForm"); + String dataTypeIRI = matcher.group("dataType"); + Datatype dataType; + if (dataTypeIRI.isEmpty()) dataType = Datatype.RDF_PLAIN_LITERAL; + else dataType = uk.ac.ox.cs.JRDFox.model.Datatype.value(dataTypeIRI); + terms[i] = uk.ac.ox.cs.JRDFox.model.Literal.create(lexicalForm, dataType); + } + else { + throw new IllegalArgumentException("The given json does not represent a valid AnswerTuple"); + } + } + else { + terms[i] = uk.ac.ox.cs.JRDFox.model.BlankNode.create(token); + } + } + return new AnswerTuple(terms); } } diff --git a/src/uk/ac/ox/cs/pagoda/query/DeserializedQueryRecord.java b/src/uk/ac/ox/cs/pagoda/query/DeserializedQueryRecord.java new file mode 100644 index 0000000..3d25eaf --- /dev/null +++ b/src/uk/ac/ox/cs/pagoda/query/DeserializedQueryRecord.java @@ -0,0 +1,9 @@ +package uk.ac.ox.cs.pagoda.query; + +/* +* A light version of QueryRecord, +* which can be obtained easily from the Json serialization of QueryRecord. +* */ +public class DeserializedQueryRecord { + // TODO implement +} diff --git a/src/uk/ac/ox/cs/pagoda/query/QueryRecord.java b/src/uk/ac/ox/cs/pagoda/query/QueryRecord.java index 4b55046..6c87eb5 100644 --- a/src/uk/ac/ox/cs/pagoda/query/QueryRecord.java +++ b/src/uk/ac/ox/cs/pagoda/query/QueryRecord.java @@ -19,7 +19,7 @@ public class QueryRecord { public static final String botQueryText = "SELECT ?X WHERE { ?X }"; - private Step diffculty; + private Step difficulty; private String queryText; private int queryID = -1; @@ -90,7 +90,7 @@ public class QueryRecord { } public boolean updateUpperBoundAnswers(AnswerTuples answerTuples, boolean toCheckAux) { - RDFoxAnswerTuples rdfAnswerTuples; + RDFoxAnswerTuples rdfAnswerTuples; if (answerTuples instanceof RDFoxAnswerTuples) rdfAnswerTuples = (RDFoxAnswerTuples) answerTuples; else { @@ -125,7 +125,7 @@ public class QueryRecord { if ((!toCheckAux || !tuple.hasAuxPredicate()) && !soundAnswerTuples.contains(tuple)) { if (!toCheckAux && justCheck) return false; tupleSet.add(extendedTuple); - } + } } } @@ -146,7 +146,7 @@ public class QueryRecord { } Utility.logInfo("The number of answers in the upper bound: " + (soundAnswerTuples.size() + gapAnswerTuples.size())); - + return update; } @@ -292,11 +292,11 @@ public class QueryRecord { } public void setDifficulty(Step step) { - this.diffculty = step; + this.difficulty = step; } public Step getDifficulty() { - return diffculty; + return difficulty; } OWLOntology relevantOntology = null; @@ -567,14 +567,16 @@ public class QueryRecord { return answerVariables[1].length > answerVariables[0].length; } + /** + * A Json serializer, which considers the main attributes. + */ public static class QueryRecordSerializer implements JsonSerializer { - public JsonElement serialize(QueryRecord src, Type typeOfSrc, JsonSerializationContext context) { Gson gson = new GsonBuilder().setPrettyPrinting().create(); JsonObject object = new JsonObject(); object.addProperty("queryID", src.queryID); object.addProperty("queryText", src.queryText); - object.addProperty("difficulty", src.diffculty.toString()); + object.addProperty("difficulty", src.difficulty != null ? src.difficulty.toString() : ""); object.add("answerVariables", context.serialize(src.getAnswerVariables())); object.add("answers", context.serialize(src.soundAnswerTuples)); @@ -586,8 +588,10 @@ public class QueryRecord { private QueryRecord() { } - public class QueryRecordDeserializer implements JsonDeserializer { - + /** + * A Json deserializer, compliant to the output of the serializer defined above. + */ + public static class QueryRecordDeserializer implements JsonDeserializer { public QueryRecord deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { @@ -595,6 +599,7 @@ public class QueryRecord { JsonObject object = json.getAsJsonObject(); record.queryID = object.getAsJsonPrimitive("queryID").getAsInt(); record.queryText = object.getAsJsonPrimitive("queryText").getAsString(); + record.difficulty = Step.valueOf(object.getAsJsonPrimitive("difficulty").getAsString()); JsonArray answerVariablesJson = object.getAsJsonArray("answerVariables"); record.answerVariables = new String[2][]; @@ -602,52 +607,63 @@ public class QueryRecord { for(int i = 0; i < answerVariablesJson.size(); i++) record.answerVariables[0][i] = answerVariablesJson.get(i).getAsString(); - record.soundAnswerTuples = context.deserialize(object.getAsJsonObject("answers"), - new TypeToken>() {}.getType()); + record.soundAnswerTuples = new HashSet<>(); + record.gapAnswerTuples = new HashSet<>(); + Type type = new TypeToken() { }.getType(); + for (JsonElement answer : object.getAsJsonArray("answers")) { + record.soundAnswerTuples.add(context.deserialize(answer, type)); + } + for (JsonElement answer : object.getAsJsonArray("gapAnswers")) { + record.soundAnswerTuples.add(context.deserialize(answer, type)); + } - record.gapAnswerTuples = context.deserialize(object.getAsJsonObject("gapAnswers"), - new TypeToken>() {}.getType()); - return null; + return record; } } - /* - * Two QueryRecords are equal iff - * they have the same queryText and - * their AnswerTuples have the same string representation + /** + * Two QueryRecords are equal iff + * they have the same queryText, + * soundAnswerTuples + * and gapAnswerTuples. * */ @Override public boolean equals(Object o) { if(!o.getClass().equals(getClass())) return false; QueryRecord that = (QueryRecord) o; + return this.queryText.equals(that.queryText) + && soundAnswerTuples.equals(that.soundAnswerTuples) + && gapAnswerTuples.equals(that.gapAnswerTuples); + } - if(!this.queryText.equals(that.queryText)) return false; - - if(soundAnswerTuples.size() != that.soundAnswerTuples.size()) return false; - if(gapAnswerTuples.size() != that.gapAnswerTuples.size()) return false; - - ArrayList thisSoundAnswers = new ArrayList<>(soundAnswerTuples); - Collections.sort(thisSoundAnswers, (AnswerTuple t1, AnswerTuple t2) -> t1.m_str.compareTo(t2.m_str)); + @Override + public int hashCode() { + return Objects.hash(queryText, soundAnswerTuples, gapAnswerTuples); + } - ArrayList thatSoundAnswers = new ArrayList<>(that.soundAnswerTuples); - Collections.sort(thatSoundAnswers, (AnswerTuple t1, AnswerTuple t2) -> t1.m_str.compareTo(t2.m_str)); + public static class GsonCreator { - Iterator soundIt1 = this.soundAnswerTuples.iterator(); - Iterator soundIt2 = that.soundAnswerTuples.iterator(); - while(soundIt1.hasNext() && soundIt2.hasNext()) - if(!soundIt1.next().m_str.equals(soundIt2.next().m_str)) return false; + private static Gson gson; - ArrayList thisGapAnswers = new ArrayList<>(gapAnswerTuples); - Collections.sort(thisGapAnswers, (AnswerTuple t1, AnswerTuple t2) -> t1.m_str.compareTo(t2.m_str)); + private GsonCreator() {} - ArrayList thatGapAnswers = new ArrayList<>(that.gapAnswerTuples); - Collections.sort(thatGapAnswers, (AnswerTuple t1, AnswerTuple t2) -> t1.m_str.compareTo(t2.m_str)); + public static Gson getInstance() { + if(gson == null) { + gson = new GsonBuilder() + .registerTypeAdapter(AnswerTuple.class, new AnswerTuple.AnswerTupleSerializer()) + .registerTypeAdapter(QueryRecord.class, new QueryRecord.QueryRecordSerializer()) + .registerTypeAdapter(QueryRecord.class, new QueryRecord.QueryRecordDeserializer()) + .registerTypeAdapter(AnswerTuple.class, new AnswerTuple.AnswerTupleDeserializer()) + .disableHtmlEscaping() + .setPrettyPrinting() + .create(); + } + return gson; + } - Iterator gapIt1 = this.gapAnswerTuples.iterator(); - Iterator gapIt2 = that.gapAnswerTuples.iterator(); - while(gapIt1.hasNext() && gapIt2.hasNext()) - if(!gapIt1.next().m_str.equals(gapIt2.next().m_str)) return false; +// public static void dispose() { +// gson = null; +// } - return true; } } diff --git a/src/uk/ac/ox/cs/pagoda/reasoner/MyQueryReasoner.java b/src/uk/ac/ox/cs/pagoda/reasoner/MyQueryReasoner.java index 17838ae..4465764 100644 --- a/src/uk/ac/ox/cs/pagoda/reasoner/MyQueryReasoner.java +++ b/src/uk/ac/ox/cs/pagoda/reasoner/MyQueryReasoner.java @@ -1,24 +1,29 @@ 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.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.*; +import uk.ac.ox.cs.pagoda.query.AnswerTuples; +import uk.ac.ox.cs.pagoda.query.GapByStore4ID; +import uk.ac.ox.cs.pagoda.query.QueryRecord; 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.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.Timer; import uk.ac.ox.cs.pagoda.util.Utility; +import java.util.Collection; +import java.util.HashMap; + public class MyQueryReasoner extends QueryReasoner { OWLOntology ontology; @@ -203,10 +208,17 @@ public class MyQueryReasoner extends QueryReasoner { String[] extendedQuery = queryRecord.getExtendedQueryText(); queryUpperBound(upperStore, queryRecord, queryRecord.getQueryText(), queryRecord.getAnswerVariables()); - if (!queryRecord.processed() && !queryRecord.getQueryText().equals(extendedQuery[0])) + + // TODO log correct partial answers + Utility.logDebug(toJson("upperBound1", queryRecord)); + if (!queryRecord.processed() && !queryRecord.getQueryText().equals(extendedQuery[0])) { queryUpperBound(upperStore, queryRecord, extendedQuery[0], queryRecord.getAnswerVariables()); - if (!queryRecord.processed() && queryRecord.hasNonAnsDistinguishedVariables()) + Utility.logDebug(toJson("upperBound2", queryRecord)); + } + if (!queryRecord.processed() && queryRecord.hasNonAnsDistinguishedVariables()) { queryUpperBound(upperStore, queryRecord, extendedQuery[1], queryRecord.getDistinguishedVariables()); + Utility.logDebug(toJson("upperBound3", queryRecord)); + } queryRecord.addProcessingTime(Step.UpperBound, t.duration()); if (queryRecord.processed()) { @@ -268,13 +280,19 @@ public class MyQueryReasoner extends QueryReasoner { // int counter = 0; + private String toJson(String key, Object value) { + HashMap map = new HashMap<>(); + map.put(key, value); + return QueryRecord.GsonCreator.getInstance().toJson(map); + } + 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); + queryRecord.updateUpperBoundAnswers(rlAnswer); } finally { if (rlAnswer != null) rlAnswer.dispose(); rlAnswer = null; diff --git a/src/uk/ac/ox/cs/pagoda/reasoner/QueryReasoner.java b/src/uk/ac/ox/cs/pagoda/reasoner/QueryReasoner.java index 1f08fdf..326bf7e 100644 --- a/src/uk/ac/ox/cs/pagoda/reasoner/QueryReasoner.java +++ b/src/uk/ac/ox/cs/pagoda/reasoner/QueryReasoner.java @@ -1,10 +1,8 @@ package uk.ac.ox.cs.pagoda.reasoner; import com.google.gson.Gson; -import com.google.gson.GsonBuilder; import org.semanticweb.owlapi.model.OWLOntology; import uk.ac.ox.cs.pagoda.owl.OWLHelper; -import uk.ac.ox.cs.pagoda.query.AnswerTuple; import uk.ac.ox.cs.pagoda.query.AnswerTuples; import uk.ac.ox.cs.pagoda.query.QueryManager; import uk.ac.ox.cs.pagoda.query.QueryRecord; @@ -202,11 +200,7 @@ public abstract class QueryReasoner { } Timer t = new Timer(); - Gson gson = new GsonBuilder() - .registerTypeAdapter(AnswerTuple.class, new AnswerTuple.AnswerTupleSerializer()) - .registerTypeAdapter(QueryRecord.class, new QueryRecord.QueryRecordSerializer()) - .setPrettyPrinting() - .create(); + Gson gson = QueryRecord.GsonCreator.getInstance(); for (QueryRecord record: queryRecords) { // if (Integer.parseInt(record.getQueryID()) != 218) continue; Utility.logInfo("---------- start evaluating Query " + record.getQueryID() + " ----------", @@ -226,7 +220,7 @@ public abstract class QueryReasoner { } // TODO it can handle one call only // if you call twice, you will end up with a json file with multiple roots - gson.toJson(queryRecords, answerWriter); + if(answerWriter != null) gson.toJson(queryRecords, answerWriter); queryRecords.stream().forEach(record -> record.dispose()); } @@ -251,5 +245,5 @@ public abstract class QueryReasoner { public static QueryReasoner getHermiTReasoner(boolean toCheckSatisfiability) { return new HermiTReasoner(toCheckSatisfiability); } - + } diff --git a/src/uk/ac/ox/cs/pagoda/util/Utility.java b/src/uk/ac/ox/cs/pagoda/util/Utility.java index 6d50ee0..b3a4df1 100644 --- a/src/uk/ac/ox/cs/pagoda/util/Utility.java +++ b/src/uk/ac/ox/cs/pagoda/util/Utility.java @@ -1,5 +1,6 @@ package uk.ac.ox.cs.pagoda.util; +import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.semanticweb.HermiT.model.Atom; @@ -11,7 +12,11 @@ import java.util.*; public class Utility { - private static final Logger LOGS = Logger.getLogger("PAGOdA"); + private static Logger LOGS; + static { + LOGS = Logger.getLogger("PAGOdA"); + LOGS.setLevel(Level.INFO); + } public static final String JAVA_FILE_SEPARATOR = "/"; public static final String FILE_SEPARATOR = System.getProperty("file.separator"); @@ -184,7 +189,7 @@ public class Utility { } private static StringBuilder logMessage = new StringBuilder(); - + private static String getLogMessage(Object[] messages) { if (messages.length == 1) return messages[0].toString(); else { @@ -198,7 +203,11 @@ public class Utility { } } - + + public static void setLogLevel(Level level) { + LOGS.setLevel(level); + } + public static void logInfo(Object... messages) { if (LOGS != null) LOGS.info(getLogMessage(messages)); -- cgit v1.2.3