diff options
Diffstat (limited to 'src/main/scala/uk/ac/ox/cs/rsacomb/RSAOntology.scala')
-rw-r--r-- | src/main/scala/uk/ac/ox/cs/rsacomb/RSAOntology.scala | 230 |
1 files changed, 129 insertions, 101 deletions
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 52d4905..87a2312 100644 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/RSAOntology.scala +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/RSAOntology.scala | |||
@@ -54,6 +54,7 @@ import uk.ac.ox.cs.rsacomb.converter._ | |||
54 | import uk.ac.ox.cs.rsacomb.suffix._ | 54 | import uk.ac.ox.cs.rsacomb.suffix._ |
55 | import uk.ac.ox.cs.rsacomb.sparql._ | 55 | import uk.ac.ox.cs.rsacomb.sparql._ |
56 | import uk.ac.ox.cs.rsacomb.util.{RDFoxUtil, RSA} | 56 | import uk.ac.ox.cs.rsacomb.util.{RDFoxUtil, RSA} |
57 | import uk.ac.ox.cs.rsacomb.util.Logger | ||
57 | 58 | ||
58 | object RSAOntology { | 59 | object RSAOntology { |
59 | 60 | ||
@@ -141,87 +142,91 @@ class RSAOntology(val ontology: OWLOntology) { | |||
141 | * why the ontology might not be RSA. This could help a second | 142 | * why the ontology might not be RSA. This could help a second |
142 | * step of approximation of an Horn-ALCHOIQ to RSA | 143 | * step of approximation of an Horn-ALCHOIQ to RSA |
143 | */ | 144 | */ |
144 | lazy val isRSA: Boolean = { | 145 | lazy val isRSA: Boolean = Logger.timed( |
145 | 146 | { | |
146 | val unsafe = this.unsafeRoles | 147 | val unsafe = this.unsafeRoles |
147 | 148 | ||
148 | /* DEBUG: print rules in DL syntax and unsafe roles */ | 149 | // val renderer = new DLSyntaxObjectRenderer() |
149 | //val renderer = new DLSyntaxObjectRenderer() | 150 | // println() |
150 | //println("\nDL rules:") | 151 | // println("Unsafe roles:") |
151 | //axioms.foreach(x => println(renderer.render(x))) | 152 | // println(unsafe) |
152 | //println("\nUnsafe roles:") | 153 | // println() |
153 | //println(unsafe) | 154 | // println("DL rules:") |
154 | 155 | // tbox.foreach(x => println(renderer.render(x))) | |
155 | object RSAConverter extends RDFoxConverter { | 156 | |
156 | 157 | object RSAConverter extends RDFoxConverter { | |
157 | override def convert( | 158 | |
158 | expr: OWLClassExpression, | 159 | override def convert( |
159 | term: Term, | 160 | expr: OWLClassExpression, |
160 | unsafe: List[OWLObjectPropertyExpression], | 161 | term: Term, |
161 | skolem: SkolemStrategy, | 162 | unsafe: List[OWLObjectPropertyExpression], |
162 | suffix: RSASuffix | 163 | skolem: SkolemStrategy, |
163 | ): Shards = | 164 | suffix: RSASuffix |
164 | (expr, skolem) match { | 165 | ): Shards = |
165 | 166 | (expr, skolem) match { | |
166 | case (e: OWLObjectSomeValuesFrom, c: Constant) | 167 | |
167 | if unsafe contains e.getProperty => { | 168 | case (e: OWLObjectSomeValuesFrom, c: Constant) |
168 | val (res, ext) = super.convert(e, term, unsafe, skolem, suffix) | 169 | if unsafe contains e.getProperty => { |
169 | (RSA.PE(term, c.iri) :: RSA.U(c.iri) :: res, ext) | 170 | val (res, ext) = super.convert(e, term, unsafe, skolem, suffix) |
170 | } | 171 | (RSA.PE(term, c.iri) :: RSA.U(c.iri) :: res, ext) |
171 | 172 | } | |
172 | case (e: OWLDataSomeValuesFrom, c: Constant) | 173 | |
173 | if unsafe contains e.getProperty => { | 174 | case (e: OWLDataSomeValuesFrom, c: Constant) |
174 | val (res, ext) = super.convert(e, term, unsafe, skolem, suffix) | 175 | if unsafe contains e.getProperty => { |
175 | (RSA.PE(term, c.iri) :: RSA.U(c.iri) :: res, ext) | 176 | val (res, ext) = super.convert(e, term, unsafe, skolem, suffix) |
177 | (RSA.PE(term, c.iri) :: RSA.U(c.iri) :: res, ext) | ||
178 | } | ||
179 | |||
180 | case _ => super.convert(expr, term, unsafe, skolem, suffix) | ||
176 | } | 181 | } |
177 | 182 | ||
178 | case _ => super.convert(expr, term, unsafe, skolem, suffix) | 183 | } |
179 | } | 184 | |
180 | 185 | /* Ontology convertion into LP rules */ | |
181 | } | 186 | val term = RSAOntology.genFreshVariable() |
182 | 187 | val datalog = axioms | |
183 | /* Ontology convertion into LP rules */ | 188 | .map(a => RSAConverter.convert(a, term, unsafe, new Constant(a), Empty)) |
184 | val term = RSAOntology.genFreshVariable() | 189 | .unzip |
185 | val datalog = axioms | 190 | val facts = datalog._1.flatten |
186 | .map(a => RSAConverter.convert(a, term, unsafe, new Constant(a), Empty)) | 191 | val rules = datalog._2.flatten |
187 | .unzip | 192 | |
188 | val facts = datalog._1.flatten | 193 | //println("Datalog rules:") |
189 | val rules = datalog._2.flatten | 194 | //rules foreach println |
190 | 195 | ||
191 | /* DEBUG: print datalog rules */ | 196 | // Open connection with RDFox |
192 | //println("\nDatalog rules:") | 197 | val (server, data) = RDFoxUtil.openConnection("RSACheck") |
193 | //rules.foreach(println) | 198 | |
194 | 199 | /* Add built-in rules | |
195 | // Open connection with RDFox | 200 | * TODO: substitute with RDFoxUtil.addRules |
196 | val (server, data) = RDFoxUtil.openConnection("RSACheck") | 201 | */ |
197 | 202 | data.importData( | |
198 | /* Add built-in rules | 203 | UpdateType.ADDITION, |
199 | * TODO: substitute with RDFoxUtil.addRules | 204 | RSA.Prefixes, |
200 | */ | 205 | "rsa:E[?X,?Y] :- rsa:PE[?X,?Y], rsa:U[?X], rsa:U[?Y] ." |
201 | data.importData( | 206 | ) |
202 | UpdateType.ADDITION, | ||
203 | RSA.Prefixes, | ||
204 | "rsa:E[?X,?Y] :- rsa:PE[?X,?Y], rsa:U[?X], rsa:U[?Y] ." | ||
205 | ) | ||
206 | |||
207 | /* Add ontology facts and rules */ | ||
208 | RDFoxUtil.addFacts(data, facts) | ||
209 | RDFoxUtil.addRules(data, rules) | ||
210 | |||
211 | /* Build graph */ | ||
212 | val graph = this.rsaGraph(data); | ||
213 | //println(graph) | ||
214 | |||
215 | // Close connection to RDFox | ||
216 | RDFoxUtil.closeConnection(server, data) | ||
217 | 207 | ||
218 | /* To check if the graph is tree-like we check for acyclicity in a | 208 | /* Add ontology facts and rules */ |
219 | * undirected graph. | 209 | RDFoxUtil.addFacts(data, facts) |
220 | * | 210 | RDFoxUtil.addRules(data, rules) |
221 | * TODO: Implement additional checks (taking into account equality) | 211 | |
222 | */ | 212 | /* Build graph */ |
223 | graph.isAcyclic | 213 | val graph = this.rsaGraph(data); |
224 | } | 214 | //println("Graph:") |
215 | //println(graph) | ||
216 | |||
217 | // Close connection to RDFox | ||
218 | RDFoxUtil.closeConnection(server, data) | ||
219 | |||
220 | /* To check if the graph is tree-like we check for acyclicity in a | ||
221 | * undirected graph. | ||
222 | * | ||
223 | * TODO: Implement additional checks (taking into account equality) | ||
224 | */ | ||
225 | graph.isAcyclic | ||
226 | }, | ||
227 | "RSA check", | ||
228 | Logger.DEBUG | ||
229 | ) | ||
225 | 230 | ||
226 | lazy val unsafeRoles: List[OWLObjectPropertyExpression] = { | 231 | lazy val unsafeRoles: List[OWLObjectPropertyExpression] = { |
227 | 232 | ||
@@ -288,9 +293,17 @@ class RSAOntology(val ontology: OWLOntology) { | |||
288 | } | 293 | } |
289 | 294 | ||
290 | def filteringProgram(query: ConjunctiveQuery): FilteringProgram = | 295 | def filteringProgram(query: ConjunctiveQuery): FilteringProgram = |
291 | new FilteringProgram(query, individuals) | 296 | Logger.timed( |
297 | new FilteringProgram(query, individuals), | ||
298 | "Generating filtering program", | ||
299 | Logger.DEBUG | ||
300 | ) | ||
292 | 301 | ||
293 | lazy val canonicalModel = new CanonicalModel(this) | 302 | lazy val canonicalModel = Logger.timed( |
303 | new CanonicalModel(this), | ||
304 | "Generating canonical model program", | ||
305 | Logger.DEBUG | ||
306 | ) | ||
294 | 307 | ||
295 | // TODO: the following functions needs testing | 308 | // TODO: the following functions needs testing |
296 | def confl( | 309 | def confl( |
@@ -321,27 +334,42 @@ class RSAOntology(val ontology: OWLOntology) { | |||
321 | * @param query query to execute | 334 | * @param query query to execute |
322 | * @return a collection of answers | 335 | * @return a collection of answers |
323 | */ | 336 | */ |
324 | def ask(query: ConjunctiveQuery): ConjunctiveQueryAnswers = { | 337 | def ask(query: ConjunctiveQuery): ConjunctiveQueryAnswers = Logger.timed( |
325 | import implicits.JavaCollections._ | 338 | { |
326 | val (server, data) = RDFoxUtil.openConnection(RSAOntology.DataStore) | 339 | import implicits.JavaCollections._ |
327 | val filter = this.filteringProgram(query) | 340 | val (server, data) = RDFoxUtil.openConnection(RSAOntology.DataStore) |
328 | RDFoxUtil.addRules(data, this.canonicalModel.rules) | 341 | val canon = this.canonicalModel |
329 | RDFoxUtil.addFacts(data, this.canonicalModel.facts) | 342 | val filter = this.filteringProgram(query) |
330 | RDFoxUtil.addRules(data, filter.rules) | 343 | |
331 | RDFoxUtil.addFacts(data, filter.facts) | 344 | Logger print s"Canonical model: ${canon.rules.length} rules" |
332 | val answers = RDFoxUtil | 345 | RDFoxUtil.addRules(data, this.canonicalModel.rules) |
333 | .submitQuery( | 346 | |
334 | data, | 347 | Logger print s"Canonical model: ${canon.facts.length} facts" |
335 | RDFoxUtil.buildDescriptionQuery("Ans", query.answer.size), | 348 | RDFoxUtil.addFacts(data, this.canonicalModel.facts) |
336 | RSA.Prefixes | 349 | |
337 | ) | 350 | RDFoxUtil printStatisticsFor data |
338 | .map( | 351 | |
339 | new ConjunctiveQueryAnswers(query.bcq, _) | 352 | Logger print s"Filtering program: ${filter.rules.length} rules" |
340 | ) | 353 | RDFoxUtil.addRules(data, filter.rules) |
341 | .get | 354 | |
342 | RDFoxUtil.closeConnection(server, data) | 355 | Logger print s"Filtering program: ${filter.facts.length} facts" |
343 | answers | 356 | RDFoxUtil.addFacts(data, filter.facts) |
344 | } | 357 | |
358 | RDFoxUtil printStatistics data | ||
359 | |||
360 | val answers = { | ||
361 | val ans = RDFoxUtil.buildDescriptionQuery("Ans", query.answer.size) | ||
362 | RDFoxUtil | ||
363 | .submitQuery(data, ans, RSA.Prefixes) | ||
364 | .map(new ConjunctiveQueryAnswers(query.bcq, query.variables, _)) | ||
365 | .get | ||
366 | } | ||
367 | RDFoxUtil.closeConnection(server, data) | ||
368 | answers | ||
369 | }, | ||
370 | "Answers computation", | ||
371 | Logger.DEBUG | ||
372 | ) | ||
345 | 373 | ||
346 | /** Query the RDFox data store used for query answering. | 374 | /** Query the RDFox data store used for query answering. |
347 | * | 375 | * |