diff options
author | Federico Igne <git@federicoigne.com> | 2021-09-29 16:43:01 +0100 |
---|---|---|
committer | Federico Igne <git@federicoigne.com> | 2021-09-29 16:43:01 +0100 |
commit | a5a4f5eba46c51c2a14e9915bfa34e78bff59030 (patch) | |
tree | 2bb20ae0d2ada44d3cc0cec7fc25d719bfe06f26 | |
parent | b1799a0af7bd243fb24bff66682f6f848557c27d (diff) | |
download | RSAComb-a5a4f5eba46c51c2a14e9915bfa34e78bff59030.tar.gz RSAComb-a5a4f5eba46c51c2a14e9915bfa34e78bff59030.zip |
Add import of multiple queries
-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 |