From a5a4f5eba46c51c2a14e9915bfa34e78bff59030 Mon Sep 17 00:00:00 2001 From: Federico Igne Date: Wed, 29 Sep 2021 16:43:01 +0100 Subject: Add import of multiple queries --- src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala | 56 ++++++++++------------ .../scala/uk/ac/ox/cs/rsacomb/RSAOntology.scala | 4 +- .../scala/uk/ac/ox/cs/rsacomb/util/RDFoxUtil.scala | 50 +++++++++++++++---- 3 files changed, 70 insertions(+), 40 deletions(-) (limited to 'src/main/scala/uk') 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 { -h | -? | --help print this help message - -q | --query + -q | --queries path to a file containing a single SPARQL query. If no query is provided, only the approximation to RSA will be performed. @@ -97,11 +97,11 @@ object RSAConfig { println(help) sys.exit(0) } - case flag @ ("-q" | "--query") :: _query :: tail => { + case flag @ ("-q" | "--queries") :: _query :: tail => { val query = new File(_query) if (!query.isFile) exit(s"'$query' is not a valid filename.") - parse(tail, config ++ Map('query -> query)) + parse(tail, config ++ Map('queries -> query)) } case _ontology :: _data => { val ontology = new File(_ontology) @@ -132,36 +132,32 @@ object RSAComb extends App { config('data).get[List[File]] ).normalize(new Normalizer) + //ontology.axioms foreach println + /* Approximate the ontology to RSA */ val toRSA = new Upperbound val rsa = ontology approximate toRSA - if (config contains 'query) { - val query = - RDFoxUtil.loadQueryFromFile(config('query).get[File].getAbsoluteFile) - - ConjunctiveQuery.parse(query) match { - case Some(query) => { - // Retrieve answers - val answers = rsa ask query - Logger.print(s"$answers", Logger.VERBOSE) - Logger print s"Number of answers: ${answers.length} (${answers.lengthWithMultiplicity})" - // Retrieve unfiltered answers - // val unfiltered = rsa.queryDataStore( - // """ - // SELECT (count(?K) as ?COUNT) - // WHERE { - // ?K a rsa:QM . - // } - // """, - // RSA.Prefixes - // ) - // unfiltered.foreach((u) => - // Logger print s"Number of unfiltered answers: ${u.head._2}" - // ) - } - case None => - throw new RuntimeException("Submitted query is not conjunctive") - } + if (config contains 'queries) { + val queries = + RDFoxUtil.loadQueriesFromFile(config('queries).get[File].getAbsoluteFile) + + val answers = rsa ask queries + + // Logger.print(s"$answers", Logger.VERBOSE) + // Logger print s"Number of answers: ${answers.length} (${answers.lengthWithMultiplicity})" + // Retrieve unfiltered answers + // val unfiltered = rsa.queryDataStore( + // """ + // SELECT (count(?K) as ?COUNT) + // WHERE { + // ?K a rsa:QM . + // } + // """, + // RSA.Prefixes + // ) + // unfiltered.foreach((u) => + // Logger print s"Number of unfiltered answers: ${u.head._2}" + // ) } } 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]) def unfold(axiom: OWLSubClassOfAxiom): Set[Term] = this.self(axiom) | this.cycle(axiom) + def ask(queries: Seq[ConjunctiveQuery]): Seq[ConjunctiveQueryAnswers] = ??? + /** Returns the answers to a query * * @param query query to execute @@ -553,7 +555,7 @@ class RSAOntology(axioms: List[OWLLogicalAxiom], datafiles: List[File]) val ans = filter.answerQuery RDFoxUtil .submitQuery(data, ans, RSA.Prefixes) - .map(new ConjunctiveQueryAnswers(query.bcq, query.variables, _)) + .map(new ConjunctiveQueryAnswers(query, query.variables, _)) .get } 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.{ Term } import tech.oxfordsemantic.jrdfox.logic.sparql.statement.SelectQuery +import uk.ac.ox.cs.rsacomb.sparql.ConjunctiveQuery import uk.ac.ox.cs.rsacomb.suffix.Nth import uk.ac.ox.cs.rsacomb.util.Logger @@ -177,15 +178,6 @@ object RDFoxUtil { def materialize(data: DataStoreConnection): Unit = Logger.timed(data.updateMaterialization(), "Materialization", Logger.DEBUG) - /** Load SPARQL query from file. */ - def loadQueryFromFile(file: File): String = { - val source = io.Source.fromFile(file) - val query = source.getLines mkString "\n" - Logger print s"Loaded query:\n$query" - source.close() - query - } - /** Export data in `text/turtle`. * * @param data datastore connection from which to export data. @@ -206,6 +198,46 @@ object RDFoxUtil { ) } + /** Load SPARQL queries from file. + * + * The file can list multiple queries, each preceeded with a + * single line containing "#^[Query]" where "" is a number. + * Empty lines are ignored. + * + * @note if a query is not recognized as a [[SelectQuery]] by RDFox + * it is discarded. + * + * @param file file containing a list of conjunctive queries. + * @param prefixes additional prefixes for the query. It defaults to + * an empty set. + * + * @return a list of [[tech.oxfordsemantic.jrdfox.logic.sparql.statement.SelectQuery SelectQuery]] queries. + */ + def loadQueriesFromFile( + file: File, + prefixes: Prefixes = new Prefixes() + ): List[ConjunctiveQuery] = { + val source = io.Source.fromFile(file) + val queries = source.getLines + .map(_.trim.filter(_ >= ' ')) + .filterNot(_ == "") + .foldRight((List.empty[List[String]], List.empty[String])) { + case (line, (acc, query)) => { + if ("^#\\^\\[Query\\d+\\]$".r.matches(line)) + (query :: acc, List.empty) + else + (acc, line :: query) + } + } + ._1 + .map(_.mkString(" ")) + .map(ConjunctiveQuery.parse(_, prefixes)) + .collect { case Some(q) => q } + Logger print s"Loaded ${queries.length} queries from ${file.getAbsolutePath}" + source.close() + queries + } + /** Parse a SELECT query from a string in SPARQL format. * * @param query the string containing the SPARQL query -- cgit v1.2.3