aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/rsacomb/RSAOntology.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/scala/rsacomb/RSAOntology.scala')
-rw-r--r--src/main/scala/rsacomb/RSAOntology.scala331
1 files changed, 276 insertions, 55 deletions
diff --git a/src/main/scala/rsacomb/RSAOntology.scala b/src/main/scala/rsacomb/RSAOntology.scala
index ef1885b..60008a2 100644
--- a/src/main/scala/rsacomb/RSAOntology.scala
+++ b/src/main/scala/rsacomb/RSAOntology.scala
@@ -4,11 +4,13 @@ package rsacomb
4import java.util.HashMap 4import java.util.HashMap
5import java.util.stream.{Collectors, Stream} 5import java.util.stream.{Collectors, Stream}
6 6
7import org.semanticweb.owlapi.model.OWLOntology 7import org.semanticweb.owlapi.model.{OWLOntology, OWLAxiom}
8import org.semanticweb.owlapi.model.{ 8import org.semanticweb.owlapi.model.{
9 OWLClass, 9 OWLClass,
10 OWLObjectProperty, 10 OWLObjectProperty,
11 OWLSubObjectPropertyOfAxiom,
11 OWLObjectPropertyExpression, 12 OWLObjectPropertyExpression,
13 OWLObjectSomeValuesFrom,
12 OWLSubClassOfAxiom 14 OWLSubClassOfAxiom
13} 15}
14import org.semanticweb.owlapi.model.parameters.Imports 16import org.semanticweb.owlapi.model.parameters.Imports
@@ -45,24 +47,37 @@ trait RSAOntology {
45 */ 47 */
46 implicit class RSAOntology(ontology: OWLOntology) extends RSAAxiom { 48 implicit class RSAOntology(ontology: OWLOntology) extends RSAAxiom {
47 49
50 // Gather TBox+RBox from original ontology
51 lazy val tbox: List[OWLAxiom] =
52 ontology
53 .tboxAxioms(Imports.INCLUDED)
54 .collect(Collectors.toList())
55 .asScala
56 .toList
57
58 lazy val rbox: List[OWLAxiom] =
59 ontology
60 .rboxAxioms(Imports.INCLUDED)
61 .collect(Collectors.toList())
62 .asScala
63 .toList
64
65 lazy val axioms: List[OWLAxiom] = tbox ++ rbox
66
48 /* Retrieve individuals in the original ontology 67 /* Retrieve individuals in the original ontology
49 */ 68 */
50 lazy val individuals: List[IRI] = { 69 lazy val individuals: List[IRI] =
51 ontology 70 ontology
52 .getIndividualsInSignature() 71 .getIndividualsInSignature()
53 .asScala 72 .asScala
54 .map(_.getIRI) 73 .map(_.getIRI)
55 .map(RDFoxUtil.owlapi2rdfox) 74 .map(RDFoxUtil.owlapi2rdfox)
56 .toList 75 .toList
57 }
58 76
59 // private val roles: Set[OWLObjectPropertyExpression] = { 77 lazy val roles: List[OWLObjectPropertyExpression] =
60 // ontology 78 axioms
61 // .rboxAxioms(Imports.INCLUDED) 79 .flatMap(_.objectPropertyExpressionsInSignature)
62 // .collect(Collectors.toSet()) 80 .distinct
63 // .asScala
64 // .flatMap(_.objectPropertyExpressionsInSignature)
65 // }
66 81
67 // OWLAPI reasoner for same easier tasks 82 // OWLAPI reasoner for same easier tasks
68 private val reasoner = 83 private val reasoner =
@@ -79,13 +94,6 @@ trait RSAOntology {
79 */ 94 */
80 lazy val isRSA: Boolean = { 95 lazy val isRSA: Boolean = {
81 96
82 val tbox = ontology.tboxAxioms(Imports.INCLUDED)
83 val rbox = ontology.rboxAxioms(Imports.INCLUDED)
84 val axioms =
85 Stream
86 .concat(tbox, rbox)
87 .collect(Collectors.toList())
88 .asScala
89 val unsafe = this.unsafeRoles 97 val unsafe = this.unsafeRoles
90 98
91 /* DEBUG: print rules in DL syntax and unsafe roles */ 99 /* DEBUG: print rules in DL syntax and unsafe roles */
@@ -154,11 +162,6 @@ trait RSAOntology {
154 162
155 lazy val unsafeRoles: List[OWLObjectPropertyExpression] = { 163 lazy val unsafeRoles: List[OWLObjectPropertyExpression] = {
156 164
157 val tbox = ontology
158 .tboxAxioms(Imports.INCLUDED)
159 .collect(Collectors.toSet())
160 .asScala
161
162 /* DEBUG: print rules in DL syntax */ 165 /* DEBUG: print rules in DL syntax */
163 //val renderer = new DLSyntaxObjectRenderer() 166 //val renderer = new DLSyntaxObjectRenderer()
164 167
@@ -210,37 +213,6 @@ trait RSAOntology {
210 (unsafe1 ++ unsafe2).toList 213 (unsafe1 ++ unsafe2).toList
211 } 214 }
212 215
213 lazy val canonicalModel: List[Rule] = {
214 // Compute program to generate canonical model
215 val tbox =
216 ontology
217 .tboxAxioms(Imports.INCLUDED)
218 .collect(Collectors.toList())
219 .asScala
220 .toList
221 val rbox =
222 ontology
223 .rboxAxioms(Imports.INCLUDED)
224 .collect(Collectors.toList())
225 .asScala
226 .toList
227 val axioms = tbox ++ rbox
228 val varX = Variable.create("X")
229 val visitor = ProgramGenerator(ontology, varX)
230 val facts = ProgramGenerator.NIs(individuals)
231 val rules1 = ProgramGenerator.generateRoleRules(
232 axioms
233 .flatMap(
234 _.objectPropertiesInSignature.collect(Collectors.toSet()).asScala
235 )
236 .toSet
237 )
238 val rules2 = axioms.flatMap(_.accept(visitor))
239
240 rules1 ++ rules2
241 // Call RDFox to generate the canonical model
242 }
243
244 private def rsaGraph( 216 private def rsaGraph(
245 data: DataStoreConnection 217 data: DataStoreConnection
246 ): Graph[Resource, UnDiEdge] = { 218 ): Graph[Resource, UnDiEdge] = {
@@ -256,8 +228,8 @@ trait RSAOntology {
256 Graph(edges: _*) 228 Graph(edges: _*)
257 } 229 }
258 230
259 def filteringProgram(query: SelectQuery): List[Rule] = 231 def filteringProgram(query: SelectQuery): FilteringProgram =
260 FilteringProgram(query, individuals).rules 232 FilteringProgram(query, individuals)
261 233
262 // TODO: the following functions needs testing 234 // TODO: the following functions needs testing
263 def confl( 235 def confl(
@@ -366,6 +338,255 @@ trait RSAOntology {
366 def unfold(axiom: OWLSubClassOfAxiom): Set[Term] = 338 def unfold(axiom: OWLSubClassOfAxiom): Set[Term] =
367 this.self(axiom) | this.cycle(axiom) 339 this.self(axiom) | this.cycle(axiom)
368 340
341 object canonicalModel {
342
343 import RDFoxUtil._
344
345 val NIs: List[Rule] =
346 individuals.map(a =>
347 Rule.create(TupleTableAtom.rdf(a, IRI.RDF_TYPE, RSA.internal("NI")))
348 )
349
350 val rolesAdditionalRules: List[Rule] = {
351 // Given a role (predicate) compute additional logic rules
352 def additional(pred: String): Seq[Rule] = {
353 val varX = Variable.create("X")
354 val varY = Variable.create("Y")
355 List(
356 Rule.create(
357 TupleTableAtom.rdf(varX, IRI.create(pred), varY),
358 TupleTableAtom
359 .rdf(
360 varX,
361 IRI.create(pred ++ RSASuffix.Forward.getSuffix),
362 varY
363 )
364 ),
365 Rule.create(
366 TupleTableAtom.rdf(varX, IRI.create(pred), varY),
367 TupleTableAtom
368 .rdf(
369 varX,
370 IRI.create(pred ++ RSASuffix.Backward.getSuffix),
371 varY
372 )
373 ),
374 Rule.create(
375 TupleTableAtom.rdf(
376 varY,
377 IRI.create(pred ++ RSASuffix.Backward.getSuffix ++ "_inv"),
378 varX
379 ),
380 TupleTableAtom
381 .rdf(
382 varX,
383 IRI.create(pred ++ RSASuffix.Forward.getSuffix),
384 varY
385 )
386 ),
387 Rule.create(
388 TupleTableAtom.rdf(
389 varY,
390 IRI.create(pred ++ RSASuffix.Forward.getSuffix ++ "_inv"),
391 varX
392 ),
393 TupleTableAtom.rdf(
394 varX,
395 IRI.create(pred ++ RSASuffix.Backward.getSuffix),
396 varY
397 )
398 )
399 )
400 }
401 // Compute additional rules per role
402 axioms
403 .flatMap(
404 _.objectPropertiesInSignature.collect(Collectors.toSet()).asScala
405 )
406 .distinct
407 .map(_.getIRI.getIRIString)
408 .flatMap(additional)
409 }
410
411 val rules: List[Rule] = {
412 // Compute rules from ontology axioms
413 val rules = axioms.flatMap(_.accept(this.ProgramGenerator))
414 // Return full set of rules
415 rules ++ rolesAdditionalRules ++ NIs
416 }
417
418 object ProgramGenerator
419 extends RDFoxAxiomConverter(
420 Variable.create("X"),
421 unsafeRoles,
422 SkolemStrategy.None,
423 RSASuffix.None
424 ) {
425
426 private def rules1(axiom: OWLSubClassOfAxiom): List[Rule] = {
427 val unfold = ontology.unfold(axiom).toList
428 // Fresh Variables
429 val v0 = IRI.create("v0_" ++ axiom.hashCode.toString)
430 val varX = Variable.create("X")
431 // Predicates
432 val atomA: TupleTableAtom = {
433 val cls = axiom.getSubClass.asInstanceOf[OWLClass].getIRI
434 TupleTableAtom.rdf(varX, IRI.RDF_TYPE, cls)
435 }
436 def notIn(t: Term): TupleTableAtom = {
437 TupleTableAtom.rdf(
438 t,
439 RSA.internal("notIn"),
440 RSA.internal(unfold.hashCode.toString)
441 )
442 }
443 val roleRf: TupleTableAtom = {
444 val visitor =
445 new RDFoxPropertyExprConverter(varX, v0, RSASuffix.Forward)
446 axiom.getSuperClass
447 .asInstanceOf[OWLObjectSomeValuesFrom]
448 .getProperty
449 .accept(visitor)
450 .head
451 }
452 val atomB: TupleTableAtom = {
453 val cls = axiom.getSuperClass
454 .asInstanceOf[OWLObjectSomeValuesFrom]
455 .getFiller
456 .asInstanceOf[OWLClass]
457 .getIRI
458 TupleTableAtom.rdf(v0, IRI.RDF_TYPE, cls)
459 }
460 // TODO: To be consistent with the specifics of the visitor we are
461 // returning facts as `Rule`s with true body. While this is correct
462 // there is an easier way to import facts into RDFox. Are we able to
463 // do that?
464 val facts = unfold.map(x => Rule.create(notIn(x)))
465 val rules = List(
466 Rule.create(roleRf, atomA, notIn(varX)),
467 Rule.create(atomB, atomA, notIn(varX))
468 )
469 facts ++ rules
470 }
471
472 private def rules2(axiom: OWLSubClassOfAxiom): List[Rule] = {
473 val roleR =
474 axiom.getSuperClass
475 .asInstanceOf[OWLObjectSomeValuesFrom]
476 .getProperty
477 if (ontology.confl(roleR) contains roleR) {
478 // Fresh Variables
479 val v0 = IRI.create("v0_" ++ axiom.hashCode.toString)
480 val v1 = IRI.create("v1_" ++ axiom.hashCode.toString)
481 val v2 = IRI.create("v2_" ++ axiom.hashCode.toString)
482 // Predicates
483 def atomA(t: Term): TupleTableAtom = {
484 val cls = axiom.getSubClass.asInstanceOf[OWLClass].getIRI
485 TupleTableAtom.rdf(t, IRI.RDF_TYPE, cls)
486 }
487 def roleRf(t1: Term, t2: Term): TupleTableAtom = {
488 val visitor =
489 new RDFoxPropertyExprConverter(t1, t2, RSASuffix.Forward)
490 roleR.accept(visitor).head
491 }
492 def atomB(t: Term): TupleTableAtom = {
493 val cls = axiom.getSuperClass
494 .asInstanceOf[OWLObjectSomeValuesFrom]
495 .getFiller
496 .asInstanceOf[OWLClass]
497 .getIRI
498 TupleTableAtom.rdf(t, IRI.RDF_TYPE, cls)
499 }
500 //Rules
501 List(
502 Rule.create(roleRf(v0, v1), atomA(v0)),
503 Rule.create(atomB(v1), atomA(v0)),
504 Rule.create(roleRf(v1, v2), atomA(v1)),
505 Rule.create(atomB(v2), atomA(v1))
506 )
507 } else {
508 List()
509 }
510 }
511
512 private def rules3(axiom: OWLSubClassOfAxiom): List[Rule] = {
513 val cycle = ontology.cycle(axiom).toList
514 val roleR =
515 axiom.getSuperClass
516 .asInstanceOf[OWLObjectSomeValuesFrom]
517 .getProperty
518 // Fresh Variables
519 val v1 = IRI.create("v1_" ++ axiom.hashCode.toString)
520 // Predicates
521 def atomA(t: Term): TupleTableAtom = {
522 val cls = axiom.getSubClass.asInstanceOf[OWLClass].getIRI
523 TupleTableAtom.rdf(t, IRI.RDF_TYPE, cls)
524 }
525 def roleRf(t: Term): TupleTableAtom = {
526 val visitor =
527 new RDFoxPropertyExprConverter(t, v1, RSASuffix.Forward)
528 roleR.accept(visitor).head
529 }
530 val atomB: TupleTableAtom = {
531 val cls = axiom.getSuperClass
532 .asInstanceOf[OWLObjectSomeValuesFrom]
533 .getFiller
534 .asInstanceOf[OWLClass]
535 .getIRI
536 TupleTableAtom.rdf(v1, IRI.RDF_TYPE, cls)
537 }
538 cycle.flatMap { x =>
539 List(
540 Rule.create(roleRf(x), atomA(x)),
541 Rule.create(atomB, atomA(x))
542 )
543 }
544 }
545
546 override def visit(axiom: OWLSubClassOfAxiom): List[Rule] = {
547 if (axiom.isT5) {
548 // TODO: get role in T5 axiom
549 // Assuming one role here
550 val role = axiom.objectPropertyExpressionsInSignature(0)
551 if (ontology.unsafeRoles.contains(role)) {
552 val visitor =
553 new RDFoxAxiomConverter(
554 Variable.create("X"),
555 ontology.unsafeRoles,
556 SkolemStrategy.Standard(axiom.toString),
557 RSASuffix.Forward
558 )
559 axiom.accept(visitor)
560 } else {
561 rules1(axiom) ++ rules2(axiom) ++ rules3(axiom)
562 }
563 } else {
564 // Fallback to standard OWL to LP translation
565 super.visit(axiom)
566 }
567 }
568
569 override def visit(axiom: OWLSubObjectPropertyOfAxiom): List[Rule] = {
570 val varX = Variable.create("X")
571 val varY = Variable.create("Y")
572 val visitorF = new RDFoxAxiomConverter(
573 Variable.create("X"),
574 ontology.unsafeRoles,
575 SkolemStrategy.None,
576 RSASuffix.Forward
577 )
578 val visitorB = new RDFoxAxiomConverter(
579 Variable.create("X"),
580 ontology.unsafeRoles,
581 SkolemStrategy.None,
582 RSASuffix.Backward
583 )
584 axiom.accept(visitorB) ++ axiom.accept(visitorF)
585 }
586
587 }
588
589 }
369 } // implicit class RSAOntology 590 } // implicit class RSAOntology
370 591
371} // trait RSAOntology 592} // trait RSAOntology