aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main/scala/rsacomb/CanonicalModel.scala255
-rw-r--r--src/main/scala/rsacomb/Main.scala69
-rw-r--r--src/main/scala/rsacomb/RSAOntology.scala331
3 files changed, 332 insertions, 323 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}
diff --git a/src/main/scala/rsacomb/Main.scala b/src/main/scala/rsacomb/Main.scala
index 830f1e0..64343f5 100644
--- a/src/main/scala/rsacomb/Main.scala
+++ b/src/main/scala/rsacomb/Main.scala
@@ -2,6 +2,10 @@ package rsacomb
2 2
3/* Java imports */ 3/* Java imports */
4import java.io.File 4import java.io.File
5import java.util.HashMap
6import scala.collection.JavaConverters._
7
8import tech.oxfordsemantic.jrdfox.client.UpdateType
5 9
6/* Local imports */ 10/* Local imports */
7import rsacomb.RSA._ 11import rsacomb.RSA._
@@ -46,25 +50,64 @@ object RSAComb extends App {
46 * case. 50 * case.
47 */ 51 */
48 52
49 val ontology = RSA.loadOntology(ontoPath) 53 val ontology: RSAOntology = RSA.loadOntology(ontoPath)
50 if (ontology.isRSA) { 54 if (ontology.isRSA) {
51 55
52 /* Build canonical model */
53 //val tboxCanon = rsa.canonicalModel()
54
55 // DEBUG: print program to generate canonical model
56 {
57 ontology.canonicalModel.foreach(println)
58 }
59
60 /* Load query */ 56 /* Load query */
61 val query = RDFoxUtil.parseQuery( 57 val query = RDFoxUtil.parseQuery(
62 "SELECT ?X WHERE {?X ?Y ?Z}" 58 """
59 SELECT ?uno
60 WHERE {
61 ?uno a :D ;
62 :R ?due .
63 ?due :S ?tre .
64 ?tre a :D .
65 }
66 """
63 ) 67 )
64 68
65 val filter = query map { q => ontology.filteringProgram(q) } 69 /* Compute answers to query */
66 70 query match {
67 /* ... */ 71 case Some(query) => {
72 // Open connection to RDFox
73 val (server, data) = RDFoxUtil.openConnection("AnswerComputation")
74
75 // Gather canonical model and filtering rules
76 val canon = ontology.canonicalModel
77 val filter = ontology.filteringProgram(query)
78
79 // Import relevant data
80 data.importData(UpdateType.ADDITION, RSA.Prefixes, ":a a :A .")
81 data.addRules(canon.rules.asJava)
82 data.addRules(filter.rules.asJava)
83
84 // Collect answers to query
85 for ((v, i) <- filter.variables.view.zipWithIndex) {
86 println(s"Variable $i:")
87 val query = s"SELECT ?X ?Y WHERE { ?X internal:Ans_$i ?Y }"
88 val cursor =
89 data.createCursor(
90 RSA.Prefixes,
91 query,
92 new HashMap[String, String]()
93 );
94 var mul = cursor.open()
95 while (mul > 0) {
96 printf(
97 "Ans_%d(%s,%s)",
98 i,
99 cursor.getResource(0),
100 cursor.getResource(1)
101 )
102 mul = cursor.advance()
103 }
104 }
105
106 // Close connection to RDFox
107 RDFoxUtil.closeConnection(server, data)
108 }
109 case None => {}
110 }
68 } 111 }
69} 112}
70 113
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