aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/rsacomb/CanonicalModel.scala
diff options
context:
space:
mode:
authorFederico Igne <federico.igne@cs.ox.ac.uk>2020-11-06 17:18:07 +0000
committerFederico Igne <federico.igne@cs.ox.ac.uk>2020-11-06 17:18:07 +0000
commitb721703c349cebd3ffe888d9644f2b85d5a8eeb7 (patch)
treea3845fbf44827ff66fc956c90fe20c1d4be73115 /src/main/scala/rsacomb/CanonicalModel.scala
parentc6babfd508f65e8b7596a96659214cb43881dadd (diff)
downloadRSAComb-b721703c349cebd3ffe888d9644f2b85d5a8eeb7.tar.gz
RSAComb-b721703c349cebd3ffe888d9644f2b85d5a8eeb7.zip
Rework canonical model computation
This is a first attempt to avoid a bug triggered by the nature of the class RSAOntology and CanonicalModel. An OWLOntology is converted implicitly to an RSAOntology object whenever it is needed. From within the RSAOntology class we used to create a CanonicalModel object (and pass the underling OWLOntology object as a parameter). Inside CanonicalModel we require RSAOntology functionalities from the OWLOntology, triggering a new conversion into RSAOntology (that would compute a new CanonicalModel and so on in a loop). While declaring the CanonicalModel as lazy in RSAOntology could solve the problem, it does not fix the underlying issue of having a class strictly related to RSAOntology as a top level class. As a first attempt we moved CanonicalModel as an object inside RSAOntology.
Diffstat (limited to 'src/main/scala/rsacomb/CanonicalModel.scala')
-rw-r--r--src/main/scala/rsacomb/CanonicalModel.scala255
1 files changed, 0 insertions, 255 deletions
diff --git a/src/main/scala/rsacomb/CanonicalModel.scala b/src/main/scala/rsacomb/CanonicalModel.scala
deleted file mode 100644
index fcc404a..0000000
--- a/src/main/scala/rsacomb/CanonicalModel.scala
+++ /dev/null
@@ -1,255 +0,0 @@
1package rsacomb
2
3import org.semanticweb.owlapi.model.{
4 OWLOntology,
5 OWLClass,
6 OWLSubObjectPropertyOfAxiom,
7 OWLSubClassOfAxiom,
8 OWLObjectProperty,
9 OWLObjectPropertyExpression,
10 OWLObjectSomeValuesFrom
11}
12import tech.oxfordsemantic.jrdfox.logic.Datatype
13import tech.oxfordsemantic.jrdfox.logic.expression.{IRI, Term, Variable}
14import tech.oxfordsemantic.jrdfox.logic.datalog.{
15 BodyFormula,
16 TupleTableAtom,
17 Rule
18}
19
20import scala.collection.JavaConverters._
21import rsacomb.RSA._
22
23object ProgramGenerator {
24
25 def apply(
26 ontology: OWLOntology,
27 term: Term = Variable.create("X")
28 ): RDFoxAxiomConverter =
29 new ProgramGenerator(ontology, term)
30
31 def generateRoleRules(
32 roles: Set[OWLObjectProperty]
33 ): List[Rule] = {
34 def additional(pred: String): Seq[Rule] = {
35 val varX = Variable.create("X")
36 val varY = Variable.create("Y")
37 List(
38 Rule.create(
39 TupleTableAtom.rdf(varX, IRI.create(pred), varY),
40 TupleTableAtom
41 .rdf(varX, IRI.create(pred ++ RSASuffix.Forward.getSuffix), varY)
42 ),
43 Rule.create(
44 TupleTableAtom.rdf(varX, IRI.create(pred), varY),
45 TupleTableAtom
46 .rdf(varX, IRI.create(pred ++ RSASuffix.Backward.getSuffix), varY)
47 ),
48 Rule.create(
49 TupleTableAtom.rdf(
50 varY,
51 IRI.create(pred ++ RSASuffix.Backward.getSuffix ++ "_inv"),
52 varX
53 ),
54 TupleTableAtom
55 .rdf(varX, IRI.create(pred ++ RSASuffix.Forward.getSuffix), varY)
56 ),
57 Rule.create(
58 TupleTableAtom.rdf(
59 varY,
60 IRI.create(pred ++ RSASuffix.Forward.getSuffix ++ "_inv"),
61 varX
62 ),
63 TupleTableAtom.rdf(
64 varX,
65 IRI.create(pred ++ RSASuffix.Backward.getSuffix),
66 varY
67 )
68 )
69 )
70 }
71 roles
72 .map(_.getIRI.getIRIString)
73 .flatMap(additional)
74 .toList
75 }
76
77 def NIs(individuals: List[IRI]): List[TupleTableAtom] =
78 individuals.map(TupleTableAtom.rdf(_, IRI.RDF_TYPE, RSA.internal("NI")))
79
80}
81
82class ProgramGenerator(
83 ontology: OWLOntology,
84 term: Term
85) extends RDFoxAxiomConverter(
86 term,
87 ontology.unsafeRoles,
88 SkolemStrategy.None,
89 RSASuffix.None
90 )
91 with RSAAxiom {
92
93 import RDFoxUtil._
94
95 def rules1(axiom: OWLSubClassOfAxiom): List[Rule] = {
96 val unfold = ontology.unfold(axiom).toList
97 // Fresh Variables
98 val v0 = IRI.create("v0_" ++ axiom.hashCode.toString)
99 val varX = Variable.create("X")
100 // Predicates
101 val atomA: TupleTableAtom = {
102 val cls = axiom.getSubClass.asInstanceOf[OWLClass].getIRI
103 TupleTableAtom.rdf(varX, IRI.RDF_TYPE, cls)
104 }
105 def notIn(t: Term): TupleTableAtom = {
106 TupleTableAtom.rdf(
107 t,
108 RSA.internal("notIn"),
109 RSA.internal(unfold.hashCode.toString)
110 )
111 }
112 val roleRf: TupleTableAtom = {
113 val visitor =
114 new RDFoxPropertyExprConverter(varX, v0, RSASuffix.Forward)
115 axiom.getSuperClass
116 .asInstanceOf[OWLObjectSomeValuesFrom]
117 .getProperty
118 .accept(visitor)
119 .head
120 }
121 val atomB: TupleTableAtom = {
122 val cls = axiom.getSuperClass
123 .asInstanceOf[OWLObjectSomeValuesFrom]
124 .getFiller
125 .asInstanceOf[OWLClass]
126 .getIRI
127 TupleTableAtom.rdf(v0, IRI.RDF_TYPE, cls)
128 }
129 // TODO: To be consistent with the specifics of the visitor we are
130 // returning facts as `Rule`s with true body. While this is correct
131 // there is an easier way to import facts into RDFox. Are we able to
132 // do that?
133 val facts = unfold.map(x => Rule.create(notIn(x)))
134 val rules = List(
135 Rule.create(roleRf, atomA, notIn(varX)),
136 Rule.create(atomB, atomA, notIn(varX))
137 )
138 facts ++ rules
139 }
140
141 def rules2(axiom: OWLSubClassOfAxiom): List[Rule] = {
142 val roleR =
143 axiom.getSuperClass
144 .asInstanceOf[OWLObjectSomeValuesFrom]
145 .getProperty
146 if (ontology.confl(roleR) contains roleR) {
147 // Fresh Variables
148 val v0 = IRI.create("v0_" ++ axiom.hashCode.toString)
149 val v1 = IRI.create("v1_" ++ axiom.hashCode.toString)
150 val v2 = IRI.create("v2_" ++ axiom.hashCode.toString)
151 // Predicates
152 def atomA(t: Term): TupleTableAtom = {
153 val cls = axiom.getSubClass.asInstanceOf[OWLClass].getIRI
154 TupleTableAtom.rdf(t, IRI.RDF_TYPE, cls)
155 }
156 def roleRf(t1: Term, t2: Term): TupleTableAtom = {
157 val visitor = new RDFoxPropertyExprConverter(t1, t2, RSASuffix.Forward)
158 roleR.accept(visitor).head
159 }
160 def atomB(t: Term): TupleTableAtom = {
161 val cls = axiom.getSuperClass
162 .asInstanceOf[OWLObjectSomeValuesFrom]
163 .getFiller
164 .asInstanceOf[OWLClass]
165 .getIRI
166 TupleTableAtom.rdf(t, IRI.RDF_TYPE, cls)
167 }
168 //Rules
169 List(
170 Rule.create(roleRf(v0, v1), atomA(v0)),
171 Rule.create(atomB(v1), atomA(v0)),
172 Rule.create(roleRf(v1, v2), atomA(v1)),
173 Rule.create(atomB(v2), atomA(v1))
174 )
175 } else {
176 List()
177 }
178 }
179
180 def rules3(axiom: OWLSubClassOfAxiom): List[Rule] = {
181 val cycle = ontology.cycle(axiom).toList
182 val roleR =
183 axiom.getSuperClass
184 .asInstanceOf[OWLObjectSomeValuesFrom]
185 .getProperty
186 // Fresh Variables
187 val v1 = IRI.create("v1_" ++ axiom.hashCode.toString)
188 // Predicates
189 def atomA(t: Term): TupleTableAtom = {
190 val cls = axiom.getSubClass.asInstanceOf[OWLClass].getIRI
191 TupleTableAtom.rdf(t, IRI.RDF_TYPE, cls)
192 }
193 def roleRf(t: Term): TupleTableAtom = {
194 val visitor =
195 new RDFoxPropertyExprConverter(t, v1, RSASuffix.Forward)
196 roleR.accept(visitor).head
197 }
198 val atomB: TupleTableAtom = {
199 val cls = axiom.getSuperClass
200 .asInstanceOf[OWLObjectSomeValuesFrom]
201 .getFiller
202 .asInstanceOf[OWLClass]
203 .getIRI
204 TupleTableAtom.rdf(v1, IRI.RDF_TYPE, cls)
205 }
206 cycle.flatMap { x =>
207 List(
208 Rule.create(roleRf(x), atomA(x)),
209 Rule.create(atomB, atomA(x))
210 )
211 }
212 }
213
214 override def visit(axiom: OWLSubClassOfAxiom): List[Rule] = {
215 if (axiom.isT5) {
216 // TODO: get role in T5 axiom
217 // Assuming one role here
218 val role = axiom.objectPropertyExpressionsInSignature(0)
219 if (ontology.unsafeRoles.contains(role)) {
220 val visitor =
221 new RDFoxAxiomConverter(
222 term,
223 ontology.unsafeRoles,
224 SkolemStrategy.Standard(axiom.toString),
225 RSASuffix.Forward
226 )
227 axiom.accept(visitor)
228 } else {
229 rules1(axiom) ++ rules2(axiom) ++ rules3(axiom)
230 }
231 } else {
232 // Fallback to standard OWL to LP translation
233 super.visit(axiom)
234 }
235 }
236
237 override def visit(axiom: OWLSubObjectPropertyOfAxiom): List[Rule] = {
238 val varX = Variable.create("X")
239 val varY = Variable.create("Y")
240 val visitorF = new RDFoxAxiomConverter(
241 term,
242 ontology.unsafeRoles,
243 SkolemStrategy.None,
244 RSASuffix.Forward
245 )
246 val visitorB = new RDFoxAxiomConverter(
247 term,
248 ontology.unsafeRoles,
249 SkolemStrategy.None,
250 RSASuffix.Backward
251 )
252 axiom.accept(visitorB) ++ axiom.accept(visitorF)
253 }
254
255}