diff options
| -rw-r--r-- | src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala | 56 | ||||
| -rw-r--r-- | src/main/scala/uk/ac/ox/cs/rsacomb/RSAOntology.scala | 4 | ||||
| -rw-r--r-- | src/main/scala/uk/ac/ox/cs/rsacomb/util/RDFoxUtil.scala | 50 |
3 files changed, 70 insertions, 40 deletions
diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala index a1fd20f..b1fd721 100644 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala | |||
| @@ -49,7 +49,7 @@ object RSAConfig { | |||
| 49 | -h | -? | --help | 49 | -h | -? | --help |
| 50 | print this help message | 50 | print this help message |
| 51 | 51 | ||
| 52 | -q <file> | --query <file> | 52 | -q <file> | --queries <file> |
| 53 | path to a file containing a single SPARQL query. If no query | 53 | path to a file containing a single SPARQL query. If no query |
| 54 | is provided, only the approximation to RSA will be performed. | 54 | is provided, only the approximation to RSA will be performed. |
| 55 | 55 | ||
| @@ -97,11 +97,11 @@ object RSAConfig { | |||
| 97 | println(help) | 97 | println(help) |
| 98 | sys.exit(0) | 98 | sys.exit(0) |
| 99 | } | 99 | } |
| 100 | case flag @ ("-q" | "--query") :: _query :: tail => { | 100 | case flag @ ("-q" | "--queries") :: _query :: tail => { |
| 101 | val query = new File(_query) | 101 | val query = new File(_query) |
| 102 | if (!query.isFile) | 102 | if (!query.isFile) |
| 103 | exit(s"'$query' is not a valid filename.") | 103 | exit(s"'$query' is not a valid filename.") |
| 104 | parse(tail, config ++ Map('query -> query)) | 104 | parse(tail, config ++ Map('queries -> query)) |
| 105 | } | 105 | } |
| 106 | case _ontology :: _data => { | 106 | case _ontology :: _data => { |
| 107 | val ontology = new File(_ontology) | 107 | val ontology = new File(_ontology) |
| @@ -132,36 +132,32 @@ object RSAComb extends App { | |||
| 132 | config('data).get[List[File]] | 132 | config('data).get[List[File]] |
| 133 | ).normalize(new Normalizer) | 133 | ).normalize(new Normalizer) |
| 134 | 134 | ||
| 135 | //ontology.axioms foreach println | ||
| 136 | |||
| 135 | /* Approximate the ontology to RSA */ | 137 | /* Approximate the ontology to RSA */ |
| 136 | val toRSA = new Upperbound | 138 | val toRSA = new Upperbound |
| 137 | val rsa = ontology approximate toRSA | 139 | val rsa = ontology approximate toRSA |
| 138 | 140 | ||
| 139 | if (config contains 'query) { | 141 | if (config contains 'queries) { |
| 140 | val query = | 142 | val queries = |
| 141 | RDFoxUtil.loadQueryFromFile(config('query).get[File].getAbsoluteFile) | 143 | RDFoxUtil.loadQueriesFromFile(config('queries).get[File].getAbsoluteFile) |
| 142 | 144 | ||
| 143 | ConjunctiveQuery.parse(query) match { | 145 | val answers = rsa ask queries |
| 144 | case Some(query) => { | 146 | |
| 145 | // Retrieve answers | 147 | // Logger.print(s"$answers", Logger.VERBOSE) |
| 146 | val answers = rsa ask query | 148 | // Logger print s"Number of answers: ${answers.length} (${answers.lengthWithMultiplicity})" |
| 147 | Logger.print(s"$answers", Logger.VERBOSE) | 149 | // Retrieve unfiltered answers |
| 148 | Logger print s"Number of answers: ${answers.length} (${answers.lengthWithMultiplicity})" | 150 | // val unfiltered = rsa.queryDataStore( |
| 149 | // Retrieve unfiltered answers | 151 | // """ |
| 150 | // val unfiltered = rsa.queryDataStore( | 152 | // SELECT (count(?K) as ?COUNT) |
| 151 | // """ | 153 | // WHERE { |
| 152 | // SELECT (count(?K) as ?COUNT) | 154 | // ?K a rsa:QM . |
| 153 | // WHERE { | 155 | // } |
| 154 | // ?K a rsa:QM . | 156 | // """, |
| 155 | // } | 157 | // RSA.Prefixes |
| 156 | // """, | 158 | // ) |
| 157 | // RSA.Prefixes | 159 | // unfiltered.foreach((u) => |
| 158 | // ) | 160 | // Logger print s"Number of unfiltered answers: ${u.head._2}" |
| 159 | // unfiltered.foreach((u) => | 161 | // ) |
| 160 | // Logger print s"Number of unfiltered answers: ${u.head._2}" | ||
| 161 | // ) | ||
| 162 | } | ||
| 163 | case None => | ||
| 164 | throw new RuntimeException("Submitted query is not conjunctive") | ||
| 165 | } | ||
| 166 | } | 162 | } |
| 167 | } | 163 | } |
diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/RSAOntology.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/RSAOntology.scala index 0c88f7f..8e05f3a 100644 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/RSAOntology.scala +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/RSAOntology.scala | |||
| @@ -496,6 +496,8 @@ class RSAOntology(axioms: List[OWLLogicalAxiom], datafiles: List[File]) | |||
| 496 | def unfold(axiom: OWLSubClassOfAxiom): Set[Term] = | 496 | def unfold(axiom: OWLSubClassOfAxiom): Set[Term] = |
| 497 | this.self(axiom) | this.cycle(axiom) | 497 | this.self(axiom) | this.cycle(axiom) |
| 498 | 498 | ||
| 499 | def ask(queries: Seq[ConjunctiveQuery]): Seq[ConjunctiveQueryAnswers] = ??? | ||
| 500 | |||
| 499 | /** Returns the answers to a query | 501 | /** Returns the answers to a query |
| 500 | * | 502 | * |
| 501 | * @param query query to execute | 503 | * @param query query to execute |
| @@ -553,7 +555,7 @@ class RSAOntology(axioms: List[OWLLogicalAxiom], datafiles: List[File]) | |||
| 553 | val ans = filter.answerQuery | 555 | val ans = filter.answerQuery |
| 554 | RDFoxUtil | 556 | RDFoxUtil |
| 555 | .submitQuery(data, ans, RSA.Prefixes) | 557 | .submitQuery(data, ans, RSA.Prefixes) |
| 556 | .map(new ConjunctiveQueryAnswers(query.bcq, query.variables, _)) | 558 | .map(new ConjunctiveQueryAnswers(query, query.variables, _)) |
| 557 | .get | 559 | .get |
| 558 | } | 560 | } |
| 559 | 561 | ||
diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/util/RDFoxUtil.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/util/RDFoxUtil.scala index 3d67270..620d2dd 100644 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/util/RDFoxUtil.scala +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/util/RDFoxUtil.scala | |||
| @@ -41,6 +41,7 @@ import tech.oxfordsemantic.jrdfox.logic.expression.{ | |||
| 41 | Term | 41 | Term |
| 42 | } | 42 | } |
| 43 | import tech.oxfordsemantic.jrdfox.logic.sparql.statement.SelectQuery | 43 | import tech.oxfordsemantic.jrdfox.logic.sparql.statement.SelectQuery |
| 44 | import uk.ac.ox.cs.rsacomb.sparql.ConjunctiveQuery | ||
| 44 | import uk.ac.ox.cs.rsacomb.suffix.Nth | 45 | import uk.ac.ox.cs.rsacomb.suffix.Nth |
| 45 | import uk.ac.ox.cs.rsacomb.util.Logger | 46 | import uk.ac.ox.cs.rsacomb.util.Logger |
| 46 | 47 | ||
| @@ -177,15 +178,6 @@ object RDFoxUtil { | |||
| 177 | def materialize(data: DataStoreConnection): Unit = | 178 | def materialize(data: DataStoreConnection): Unit = |
| 178 | Logger.timed(data.updateMaterialization(), "Materialization", Logger.DEBUG) | 179 | Logger.timed(data.updateMaterialization(), "Materialization", Logger.DEBUG) |
| 179 | 180 | ||
| 180 | /** Load SPARQL query from file. */ | ||
| 181 | def loadQueryFromFile(file: File): String = { | ||
| 182 | val source = io.Source.fromFile(file) | ||
| 183 | val query = source.getLines mkString "\n" | ||
| 184 | Logger print s"Loaded query:\n$query" | ||
| 185 | source.close() | ||
| 186 | query | ||
| 187 | } | ||
| 188 | |||
| 189 | /** Export data in `text/turtle`. | 181 | /** Export data in `text/turtle`. |
| 190 | * | 182 | * |
| 191 | * @param data datastore connection from which to export data. | 183 | * @param data datastore connection from which to export data. |
| @@ -206,6 +198,46 @@ object RDFoxUtil { | |||
| 206 | ) | 198 | ) |
| 207 | } | 199 | } |
| 208 | 200 | ||
| 201 | /** Load SPARQL queries from file. | ||
| 202 | * | ||
| 203 | * The file can list multiple queries, each preceeded with a | ||
| 204 | * single line containing "#^[Query<id>]" where "<id>" is a number. | ||
| 205 | * Empty lines are ignored. | ||
| 206 | * | ||
| 207 | * @note if a query is not recognized as a [[SelectQuery]] by RDFox | ||
| 208 | * it is discarded. | ||
| 209 | * | ||
| 210 | * @param file file containing a list of conjunctive queries. | ||
| 211 | * @param prefixes additional prefixes for the query. It defaults to | ||
| 212 | * an empty set. | ||
| 213 | * | ||
| 214 | * @return a list of [[tech.oxfordsemantic.jrdfox.logic.sparql.statement.SelectQuery SelectQuery]] queries. | ||
| 215 | */ | ||
| 216 | def loadQueriesFromFile( | ||
| 217 | file: File, | ||
| 218 | prefixes: Prefixes = new Prefixes() | ||
| 219 | ): List[ConjunctiveQuery] = { | ||
| 220 | val source = io.Source.fromFile(file) | ||
| 221 | val queries = source.getLines | ||
| 222 | .map(_.trim.filter(_ >= ' ')) | ||
| 223 | .filterNot(_ == "") | ||
| 224 | .foldRight((List.empty[List[String]], List.empty[String])) { | ||
| 225 | case (line, (acc, query)) => { | ||
| 226 | if ("^#\\^\\[Query\\d+\\]$".r.matches(line)) | ||
| 227 | (query :: acc, List.empty) | ||
| 228 | else | ||
| 229 | (acc, line :: query) | ||
| 230 | } | ||
| 231 | } | ||
| 232 | ._1 | ||
| 233 | .map(_.mkString(" ")) | ||
| 234 | .map(ConjunctiveQuery.parse(_, prefixes)) | ||
| 235 | .collect { case Some(q) => q } | ||
| 236 | Logger print s"Loaded ${queries.length} queries from ${file.getAbsolutePath}" | ||
| 237 | source.close() | ||
| 238 | queries | ||
| 239 | } | ||
| 240 | |||
| 209 | /** Parse a SELECT query from a string in SPARQL format. | 241 | /** Parse a SELECT query from a string in SPARQL format. |
| 210 | * | 242 | * |
| 211 | * @param query the string containing the SPARQL query | 243 | * @param query the string containing the SPARQL query |
