aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFederico Igne <federico.igne@cs.ox.ac.uk>2020-09-09 17:03:42 +0200
committerFederico Igne <federico.igne@cs.ox.ac.uk>2020-09-09 17:03:42 +0200
commite325a9c6282a4a98bf6799f8d04b3cbc6e56fca2 (patch)
treec069dba2a4a46a982a2753a0cca699051b6b437e /src
parent713fd36fb2bd4f71fc690a1ab3a3c1fce5b1a16f (diff)
downloadRSAComb-e325a9c6282a4a98bf6799f8d04b3cbc6e56fca2.tar.gz
RSAComb-e325a9c6282a4a98bf6799f8d04b3cbc6e56fca2.zip
Move reifing code under `FilteringProgram` class
Diffstat (limited to 'src')
-rw-r--r--src/main/scala/rsacomb/FilteringProgram.scala104
-rw-r--r--src/main/scala/rsacomb/Main.scala2
-rw-r--r--src/main/scala/rsacomb/RSAOntology.scala103
3 files changed, 96 insertions, 113 deletions
diff --git a/src/main/scala/rsacomb/FilteringProgram.scala b/src/main/scala/rsacomb/FilteringProgram.scala
index 91c98d8..afa3f1e 100644
--- a/src/main/scala/rsacomb/FilteringProgram.scala
+++ b/src/main/scala/rsacomb/FilteringProgram.scala
@@ -5,17 +5,32 @@ import scala.collection.JavaConverters._
5 5
6class FilteringProgram(query: Query, constants: List[Term]) extends RDFTriple { 6class FilteringProgram(query: Query, constants: List[Term]) extends RDFTriple {
7 7
8 /* Makes mplicit conversion OWLAPI IRI <-> RDFox IRI available */
9 import RDFoxUtil._
10
8 private val bounded: List[Term] = this.getBoundedVariables 11 private val bounded: List[Term] = this.getBoundedVariables
9 private val answer: List[Term] = query.getAnswerVariables.asScala.toList 12 private val answer: List[Term] = query.getAnswerVariables.asScala.toList
10 13
11 val facts: List[Atom] = constants.map(named) 14 val facts: List[Atom] = constants.map(named)
12 val rules: List[Rule] = this.generateFilteringProgram() 15 val rules: List[Rule] = this.generateFilteringProgram().map(reifyRule)
13 16
14 private def named(t: Term): Atom = 17 private def named(t: Term): Atom =
15 Atom.rdf(t, IRI.RDF_TYPE, RSA.internal("NAMED")) 18 Atom.rdf(t, IRI.RDF_TYPE, RSA.internal("NAMED"))
16 19
17 private def getBoundedVariables: List[Variable] = List() 20 private def getBoundedVariables: List[Variable] = List()
18 21
22 /* NOTE: we are restricting to queries that contain conjunctions of
23 * atoms for the time being. This might need to be reviewed in the
24 * future.
25 */
26 private def queryToBody(body: Formula): List[Atom] =
27 body match {
28 case a: Atom => List(a);
29 case a: Conjunction =>
30 a.getConjuncts.asScala.toList.flatMap(queryToBody);
31 case _ => List()
32 }
33
19 private def generateFilteringProgram(): List[Rule] = { 34 private def generateFilteringProgram(): List[Rule] = {
20 // Query formula as a rule body 35 // Query formula as a rule body
21 val body = queryToBody(query.getQueryFormula) 36 val body = queryToBody(query.getQueryFormula)
@@ -275,21 +290,86 @@ class FilteringProgram(query: Query, constants: List[Term]) extends RDFTriple {
275 .prepended(r1) 290 .prepended(r1)
276 } 291 }
277 292
278 /* NOTE: we are restricting to queries that contain conjunctions of 293 private sealed trait Reified;
279 * atoms for the time being. This might need to be reviewed in the 294 private case class ReifiedHead(bind: BindAtom, atoms: List[Atom])
280 * future. 295 extends Reified
281 */ 296 private case class ReifiedBody(atoms: List[Atom]) extends Reified
282 private def queryToBody(body: Formula): List[Atom] = 297 private case class Unaltered(formula: BodyFormula) extends Reified
283 body match { 298
284 case a: Atom => List(a); 299 private def getBindAtom(atom: Atom): BindAtom = {
285 case a: Conjunction => 300 val newvar = RSA.getFreshVariable()
286 a.getConjuncts.asScala.toList.flatMap(queryToBody); 301 val name =
287 case _ => List() 302 Literal.create(atom.getTupleTableName.getIRI, Datatype.XSD_STRING)
303 val args = atom
304 .getArguments()
305 .asScala
306 .toSeq
307 .prepended(name) /* Unclear requirement for SKOLEM func calls */
308 BindAtom.create(
309 BuiltinFunctionCall
310 .create("SKOLEM", args: _*),
311 newvar
312 )
313 }
314
315 private def reifyAtom(atom: Atom, variable: Variable): List[Atom] = {
316 def iri(i: Int) = atom.getTupleTableName().getIRI() ++ s"_$i"
317 atom
318 .getArguments()
319 .asScala
320 .zipWithIndex
321 .map { case (t, i) => Atom.rdf(variable, iri(i), t) }
322 .toList
323 }
324
325 private def reifyBodyFormula(
326 formula: BodyFormula,
327 head: Boolean
328 ): Reified = {
329 formula match {
330 case a: Atom => {
331 if (!a.isRdfTriple) {
332 if (head) {
333 val b = getBindAtom(a)
334 ReifiedHead(b, reifyAtom(a, b.getBoundVariable))
335 } else {
336 ReifiedBody(reifyAtom(a, RSA.getFreshVariable))
337 }
338 } else {
339 Unaltered(a)
340 }
341 }
342 case a => Unaltered(a)
343 }
344 }
345
346 private def reifyRule(rule: Rule): Rule = {
347 // Rule body
348 val body =
349 rule.getBody.asScala.map(reifyBodyFormula(_, false)).flatMap {
350 case ReifiedHead(_, _) => List(); /* handle impossible case */
351 case ReifiedBody(x) => x;
352 case Unaltered(x) => List(x)
353 }
354 // Rule head
355 val reified = rule.getHead.asScala.map(reifyBodyFormula(_, true))
356 val skols = reified.flatMap {
357 case ReifiedHead(x, _) => Some(x);
358 case ReifiedBody(_) => None; /* handle impossible case */
359 case Unaltered(_) => None
288 } 360 }
361 val head = reified.flatMap {
362 case ReifiedHead(_, x) => x;
363 case ReifiedBody(_) => List(); /* handle impossible case */
364 case Unaltered(x) =>
365 List(x.asInstanceOf[Atom]) /* Can we do better that a cast? */
366 }
367 Rule.create(head.asJava, (skols ++ body).asJava)
368 }
289 369
290} // class FilteringProgram 370} // class FilteringProgram
291 371
292object FilteringProgram { 372object FilteringProgram {
293 def apply(query: Query, constants: List[Term]): FilteringProgram = 373 def apply(query: Query, constants: List[Term]): FilteringProgram =
294 new FilteringProgram(query, constants) 374 new FilteringProgram(query, constants)
295} 375} // object FilteringProgram
diff --git a/src/main/scala/rsacomb/Main.scala b/src/main/scala/rsacomb/Main.scala
index d2bc2a8..a449db4 100644
--- a/src/main/scala/rsacomb/Main.scala
+++ b/src/main/scala/rsacomb/Main.scala
@@ -57,7 +57,7 @@ object RSAComb {
57 val query = RSA.test_query 57 val query = RSA.test_query
58 58
59 /* Compute the filtering program from the given query */ 59 /* Compute the filtering program from the given query */
60 val filter = ontology.getFilteringProgram(query) 60 val filter = ontology.filteringProgram(query)
61 61
62 /* ... */ 62 /* ... */
63 63
diff --git a/src/main/scala/rsacomb/RSAOntology.scala b/src/main/scala/rsacomb/RSAOntology.scala
index efd6e7f..2f639eb 100644
--- a/src/main/scala/rsacomb/RSAOntology.scala
+++ b/src/main/scala/rsacomb/RSAOntology.scala
@@ -28,9 +28,7 @@ trait RSAOntology {
28 /* Implements additional features to reason about RSA ontologies 28 /* Implements additional features to reason about RSA ontologies
29 * on top of `OWLOntology` from the OWLAPI. 29 * on top of `OWLOntology` from the OWLAPI.
30 */ 30 */
31 implicit class RSAOntology(ontology: OWLOntology) 31 implicit class RSAOntology(ontology: OWLOntology) extends RSAAxiom {
32 extends RSAAxiom
33 with RDFTriple {
34 32
35 /* Steps for RSA check 33 /* Steps for RSA check
36 * 1) convert ontology axioms into LP rules 34 * 1) convert ontology axioms into LP rules
@@ -165,11 +163,6 @@ trait RSAOntology {
165 if roleSuper.contains(role2) || roleSuperInv.contains(role2) 163 if roleSuper.contains(role2) || roleSuperInv.contains(role2)
166 } yield role1 164 } yield role1
167 165
168 /* TODO: We should be able to avoid this last conversion to List.
169 * Maybe we should just move everything to Sets instead of Lists,
170 * since they have a more straightforward conversion from Java
171 * collections.
172 */
173 (unsafe1 ++ unsafe2).toList 166 (unsafe1 ++ unsafe2).toList
174 } 167 }
175 168
@@ -188,98 +181,8 @@ trait RSAOntology {
188 Graph(edges: _*) 181 Graph(edges: _*)
189 } 182 }
190 183
191 def getFilteringProgram(query: Query): List[Rule] = { 184 def filteringProgram(query: Query): List[Rule] =
192 185 FilteringProgram(query, List()).rules
193 // Import implicit conversion to RDFox IRI
194 import RDFoxUtil._
195
196 sealed trait Reified;
197 case class ReifiedHead(bind: BindAtom, atoms: List[Atom]) extends Reified
198 case class ReifiedBody(atoms: List[Atom]) extends Reified
199 case class Unaltered(formula: BodyFormula) extends Reified
200
201 def getBindAtom(atom: Atom): BindAtom = {
202 // TODO: We need to implement another way to introduce fresh
203 // variables.
204 val newvar = RSA.getFreshVariable()
205 val name =
206 Literal.create(atom.getTupleTableName.getIRI, Datatype.XSD_STRING)
207 val args = atom
208 .getArguments()
209 .asScala
210 .toSeq
211 .prepended(name)
212 BindAtom.create(
213 BuiltinFunctionCall
214 .create("SKOLEM", args: _*),
215 newvar
216 )
217 }
218
219 def reifyAtom(atom: Atom, variable: Variable): List[Atom] = {
220 def iri(i: Int) = atom.getTupleTableName().getIRI() ++ s"_$i"
221 atom
222 .getArguments()
223 .asScala
224 .zipWithIndex
225 .map { case (t, i) => Atom.rdf(variable, iri(i), t) }
226 .toList
227 }
228
229 def reify(
230 formula: BodyFormula,
231 head: Boolean
232 ): Reified = {
233 def default[A <: BodyFormula](x: A) = Unaltered(x)
234 formula match {
235 case a: Atom => {
236 if (!a.isRdfTriple) {
237 if (head) {
238 val b = getBindAtom(a)
239 ReifiedHead(b, reifyAtom(a, b.getBoundVariable))
240 } else {
241 val varA = RSA.getFreshVariable()
242 ReifiedBody(reifyAtom(a, varA))
243 }
244 } else {
245 default(a)
246 }
247 }
248 case a => default(a)
249 }
250 }
251
252 def skolemizeRule(rule: Rule): Rule = {
253 // Rule body
254 val body =
255 rule.getBody.asScala.map(reify(_, false)).flatMap {
256 case ReifiedHead(_, _) => List(); /* handle impossible case */
257 case ReifiedBody(x) => x;
258 case Unaltered(x) => List(x)
259 }
260 // Rule head
261 val reified = rule.getHead.asScala.map(reify(_, true))
262 val skols = reified.flatMap {
263 case ReifiedHead(x, _) => Some(x);
264 case ReifiedBody(_) => None; /* handle impossible case */
265 case Unaltered(_) => None
266 }
267 val head = reified.flatMap {
268 case ReifiedHead(_, x) => x;
269 case ReifiedBody(_) => List(); /* handle impossible case */
270 case Unaltered(x) =>
271 List(x.asInstanceOf[Atom]) /* Can we do better that a cast? */
272 }
273 Rule.create(head.asJava, (skols ++ body).asJava)
274 }
275
276 // DEBUG
277 val rules = FilteringProgram(query, List()).rules
278 println("FILTERING PROGRAM:")
279 rules.map(skolemizeRule(_)).foreach(println(_))
280
281 List()
282 }
283 186
284 } // implicit class RSAOntology 187 } // implicit class RSAOntology
285 188