aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/rsacomb/RSAOntology.scala
blob: 474d31617a7b2b583cb329d3a47f2591b13d7785 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
package rsacomb

/* Java imports */
import java.util.stream.{Collectors,Stream}

import org.semanticweb.owlapi.model.OWLOntology
import org.semanticweb.owlapi.model.OWLObjectPropertyExpression
import org.semanticweb.owlapi.model.parameters.Imports
import org.semanticweb.owlapi.reasoner.structural.StructuralReasonerFactory

import tech.oxfordsemantic.jrdfox.logic.Variable

/* Scala imports */
import scala.collection.JavaConverters._

/* Debug only */
import org.semanticweb.owlapi.dlsyntax.renderer.DLSyntaxObjectRenderer

/* Wrapper trait for the implicit class `RSAOntology`.
 */
trait RSAOntology {

  /* Implements additional features to reason about RSA ontologies
   * on top of `OWLOntology` from the OWLAPI.
   */
  implicit class RSAOntology(ontology: OWLOntology) extends RSAAxiom {

    def isRSA: Boolean = {

      /* TODO: Steps for RSA check
       * 1) convert ontology axioms into LP rules
       * 2) call RDFox on the onto and compute materialization
       * 3) build graph from E(x,y) facts
       * 4) check if the graph is tree-like
       *    ideally this annotates the graph with info about the reasons
       *    why the ontology might not be RSA. This could help a second
       *    step of approximation of an Horn-ALCHOIQ to RSA
       */

      val tbox = 
        Stream.concat(ontology.tboxAxioms(Imports.INCLUDED), ontology.rboxAxioms(Imports.INCLUDED))
              .collect(Collectors.toList()).asScala
      val unsafe = ontology.getUnsafeRoles

      /* DEBUG: print rules in DL syntax */
      val renderer = new DLSyntaxObjectRenderer()
      println("\nDL rules:")
      tbox.foreach(x => println(renderer.render(x)))

      /* Ontology convertion into LP rules */
      println("\nLP rules:")
      for {
        axiom <- tbox
        visitor = new RDFoxAxiomConverter(Variable.create("x"), SkolemStrategy.ConstantRSA(axiom.toString), unsafe)
        rule  <- axiom.accept(visitor)
      } yield println(rule)

      /* DEBUG */
      true
    }

    def getUnsafeRoles: List[OWLObjectPropertyExpression] = {
      // The reasoner is used to check unsafety condition for the ontology roles
      val factory = new StructuralReasonerFactory()
      val reasoner = factory.createReasoner(ontology)

      val tbox = ontology.tboxAxioms(Imports.INCLUDED).collect(Collectors.toSet()).asScala

      /* DEBUG: print rules in DL syntax */
      //val renderer = new DLSyntaxObjectRenderer()

      /* Checking for (1) unsafety condition:
       * 
       *    For all roles p1 appearing in an axiom of type T5, p1 is unsafe
       *    if there exists a role p2 (different from top) appearing in an axiom
       *    of type T3 and p1 is a subproperty of the inverse of p2.
       * 
       * TODO: We are not checking whether the class expression on the right in T3
       * is top. For now we can assume it is always the case.
       */
      val unsafe = for {
        ax1 <- tbox
        if ax1.isT5
        p1 <- ax1.objectPropertyExpressionsInSignature
        sup = p1.getInverseProperty +: reasoner.superObjectProperties(p1).map(_.getInverseProperty).collect(Collectors.toList()).asScala
        ax2 <- tbox
        if ax2.isT3
        p2 <- ax2.objectPropertyExpressionsInSignature 
        if sup.contains(p2)
      } yield p1

      /* Checking for (2) unsafety condition:
       *
       *    TODO
       */

      /* TODO: We should be able to avoid this last conversion to List.
       * Maybe we should just move everything to Sets instead of Lists, since
       * they have a more straightforward conversion from Java collections.
       */
      unsafe.toList
    }

  } // implicit class RSAOntology

} // trait RSAOntology