aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFederico Igne <git@federicoigne.com>2021-10-02 09:15:43 +0100
committerFederico Igne <git@federicoigne.com>2021-10-02 09:15:43 +0100
commit424d5d6fcabb410622907c095364903577014765 (patch)
tree4025b3136572e40ce619affcf94def09ae186be7
parent360e10e686d144b918825939f48004aebc31b7f3 (diff)
downloadRSAComb-424d5d6fcabb410622907c095364903577014765.tar.gz
RSAComb-424d5d6fcabb410622907c095364903577014765.zip
Rework revides filtering program computation to use named graphs
-rw-r--r--src/main/scala/uk/ac/ox/cs/rsacomb/RSAOntology.scala7
-rw-r--r--src/main/scala/uk/ac/ox/cs/rsacomb/filtering/NaiveFilteringProgram.scala143
-rw-r--r--src/main/scala/uk/ac/ox/cs/rsacomb/filtering/RevisedFilteringProgram.scala215
-rw-r--r--src/main/scala/uk/ac/ox/cs/rsacomb/implicits/RDFox.scala4
-rw-r--r--src/main/scala/uk/ac/ox/cs/rsacomb/implicits/RSAAtom.scala53
-rw-r--r--src/main/scala/uk/ac/ox/cs/rsacomb/suffix/RSASuffix.scala24
-rw-r--r--src/main/scala/uk/ac/ox/cs/rsacomb/util/RSA.scala70
7 files changed, 254 insertions, 262 deletions
diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/RSAOntology.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/RSAOntology.scala
index 6a3dca2..993e9df 100644
--- a/src/main/scala/uk/ac/ox/cs/rsacomb/RSAOntology.scala
+++ b/src/main/scala/uk/ac/ox/cs/rsacomb/RSAOntology.scala
@@ -545,7 +545,7 @@ class RSAOntology(axioms: List[OWLLogicalAxiom], datafiles: List[File])
545 RDFoxUtil.addFacts( 545 RDFoxUtil.addFacts(
546 data, 546 data,
547 RSAOntology.CanonGraph, 547 RSAOntology.CanonGraph,
548 (individuals ++ literals) map RSA.Named 548 (individuals ++ literals) map RSA.Named(RSAOntology.CanonGraph)
549 ) 549 )
550 data.evaluateUpdate( 550 data.evaluateUpdate(
551 null, // the base IRI for the query (if null, a default is used) 551 null, // the base IRI for the query (if null, a default is used)
@@ -569,13 +569,12 @@ class RSAOntology(axioms: List[OWLLogicalAxiom], datafiles: List[File])
569 569
570 queries map { query => 570 queries map { query =>
571 { 571 {
572 //val graph = RSAOntology.FilterGraph(query)
573 val filter = RSAOntology.filteringProgram(query) 572 val filter = RSAOntology.filteringProgram(query)
573
574 /* Add filtering program */ 574 /* Add filtering program */
575 Logger print s"Filtering program rules: ${filter.rules.length}" 575 Logger print s"Filtering program rules: ${filter.rules.length}"
576 RDFoxUtil.addRules(data, filter.rules) 576 RDFoxUtil.addRules(data, filter.rules)
577 577 // TODO: We remove the rules, should we drop the tuple table as well?
578 // We remove the rules, should we drop the tuple table as well?
579 data.clearRulesAxiomsExplicateFacts() 578 data.clearRulesAxiomsExplicateFacts()
580 579
581 /* Gather answers to the query */ 580 /* Gather answers to the query */
diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/filtering/NaiveFilteringProgram.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/filtering/NaiveFilteringProgram.scala
index 1777713..6174c9d 100644
--- a/src/main/scala/uk/ac/ox/cs/rsacomb/filtering/NaiveFilteringProgram.scala
+++ b/src/main/scala/uk/ac/ox/cs/rsacomb/filtering/NaiveFilteringProgram.scala
@@ -32,7 +32,7 @@ import tech.oxfordsemantic.jrdfox.logic.expression.{
32 Variable 32 Variable
33} 33}
34import uk.ac.ox.cs.rsacomb.sparql.ConjunctiveQuery 34import uk.ac.ox.cs.rsacomb.sparql.ConjunctiveQuery
35import uk.ac.ox.cs.rsacomb.suffix.{Forward, Backward, Nth} 35import uk.ac.ox.cs.rsacomb.suffix.{RSASuffix, Forward, Backward, Nth}
36import uk.ac.ox.cs.rsacomb.util.{DataFactory, RSA, RDFoxUtil} 36import uk.ac.ox.cs.rsacomb.util.{DataFactory, RSA, RDFoxUtil}
37 37
38/** Factory for [[uk.ac.ox.cs.rsacomb.FilteringProgram FilteringProgram]] */ 38/** Factory for [[uk.ac.ox.cs.rsacomb.FilteringProgram FilteringProgram]] */
@@ -95,10 +95,41 @@ class NaiveFilteringProgram(
95 95
96 /** `TupleTableName`s for the source/targer named graphs */ 96 /** `TupleTableName`s for the source/targer named graphs */
97 val tts: TupleTableName = TupleTableName.create(source.getIRI) 97 val tts: TupleTableName = TupleTableName.create(source.getIRI)
98 implicit val ttt: TupleTableName = TupleTableName.create(target.getIRI) 98 val ttt: TupleTableName = TupleTableName.create(target.getIRI)
99 99
100 /** Set of atoms in the body of the query */ 100 /** Set of atoms in the body of the query */
101 val queryBody: List[TupleTableAtom] = query.atoms(tts) 101 private val queryBody: List[TupleTableAtom] = query.atoms(tts)
102
103 /** Helpers */
104 private def not(atom: TupleTableAtom): BodyFormula = Negation.create(atom)
105
106 private val QM: TupleTableAtom =
107 TupleTableAtom.create(ttt, RSA.QM :: query.answer ::: query.bounded)
108 private def ID(t1: Term, t2: Term) =
109 TupleTableAtom.create(
110 ttt,
111 RSA.ID +: (query.answer ::: query.bounded) :+ t1 :+ t2
112 )
113 private def NI(term: Term) =
114 TupleTableAtom.create(ttt, term, IRI.RDF_TYPE, RSA.NI)
115 private def TQ(sx: RSASuffix, t1: Term, t2: Term) =
116 TupleTableAtom.create(
117 ttt,
118 (RSA.TQ :: sx) +: (query.answer ::: query.bounded) :+ t1 :+ t2
119 )
120 private def AQ(sx: RSASuffix, t1: Term, t2: Term) =
121 TupleTableAtom.create(
122 ttt,
123 (RSA.AQ :: sx) +: (query.answer ::: query.bounded) :+ t1 :+ t2
124 )
125 private val FK: TupleTableAtom =
126 TupleTableAtom.create(ttt, RSA.FK :: query.answer ::: query.bounded)
127 private val SP: TupleTableAtom =
128 TupleTableAtom.create(ttt, RSA.SP :: query.answer ::: query.bounded)
129 private def Ans = if (query.bcq)
130 TupleTableAtom.create(ttt, RSA("blank"), IRI.RDF_TYPE, RSA.ANS)
131 else
132 TupleTableAtom.create(ttt, RSA.ANS :: query.answer)
102 133
103 /** Rule generating the instances of the predicate `rsa:NI`. 134 /** Rule generating the instances of the predicate `rsa:NI`.
104 * 135 *
@@ -117,23 +148,20 @@ class NaiveFilteringProgram(
117 */ 148 */
118 val nis: Rule = 149 val nis: Rule =
119 Rule.create( 150 Rule.create(
120 RSA.NI(varX), 151 NI(varX),
121 RSA.Congruent(varX, varY)(tts), 152 RSA.Congruent(tts)(varX, varY),
122 RSA.Named(varY)(tts) 153 RSA.Named(tts)(varY)
123 ) 154 )
124 155
125 /** Collection of filtering program rules. */ 156 /** Collection of filtering program rules. */
126 val rules: List[Rule] = 157 val rules: List[Rule] =
127 nis :: { 158 nis :: {
128 159
129 /** Negates a [[tech.oxfordsemantic.jrdfox.logic.datalog.TupleTableAtom TupleTableAtom]] */
130 def not(atom: TupleTableAtom): BodyFormula = Negation.create(atom)
131
132 /** Generates all possible, unfiltered answers. 160 /** Generates all possible, unfiltered answers.
133 * 161 *
134 * @note corresponds to rule 1 in Table 3 in the paper. 162 * @note corresponds to rule 1 in Table 3 in the paper.
135 */ 163 */
136 val r1 = Rule.create(RSA.QM, queryBody: _*) 164 val r1 = Rule.create(QM, queryBody: _*)
137 165
138 /** Initializes instances of `rsa:ID`. 166 /** Initializes instances of `rsa:ID`.
139 * 167 *
@@ -145,10 +173,10 @@ class NaiveFilteringProgram(
145 */ 173 */
146 val r3a = 174 val r3a =
147 for ((v, i) <- query.bounded.zipWithIndex) 175 for ((v, i) <- query.bounded.zipWithIndex)
148 yield Rule.create(RSA.ID(RSA(i), RSA(i)), RSA.QM, not(RSA.NI(v))) 176 yield Rule.create(ID(RSA(i), RSA(i)), QM, not(NI(v)))
149 val r3b = Rule.create(RSA.ID(varV, varU), RSA.ID(varU, varV)) 177 val r3b = Rule.create(ID(varV, varU), ID(varU, varV))
150 val r3c = 178 val r3c =
151 Rule.create(RSA.ID(varU, varW), RSA.ID(varU, varV), RSA.ID(varV, varW)) 179 Rule.create(ID(varU, varW), ID(varU, varV), ID(varV, varW))
152 180
153 /** Detects forks in the canonical model. 181 /** Detects forks in the canonical model.
154 * 182 *
@@ -162,10 +190,10 @@ class NaiveFilteringProgram(
162 index2 = query.bounded indexOf (role2.getArguments get 2) 190 index2 = query.bounded indexOf (role2.getArguments get 2)
163 if index2 >= 0 191 if index2 >= 0
164 } yield Rule.create( 192 } yield Rule.create(
165 RSA.FK, 193 FK,
166 RSA.ID(RSA(index1), RSA(index2)), 194 ID(RSA(index1), RSA(index2)),
167 role1 << Forward, 195 role1 :: Forward,
168 role2 << Forward, 196 role2 :: Forward,
169 not( 197 not(
170 TupleTableAtom.create( 198 TupleTableAtom.create(
171 tts, 199 tts,
@@ -183,10 +211,10 @@ class NaiveFilteringProgram(
183 index2 = query.bounded indexOf (role2.getArguments get 0) 211 index2 = query.bounded indexOf (role2.getArguments get 0)
184 if index2 >= 0 212 if index2 >= 0
185 } yield Rule.create( 213 } yield Rule.create(
186 RSA.FK, 214 FK,
187 RSA.ID(RSA(index1), RSA(index2)), 215 ID(RSA(index1), RSA(index2)),
188 role1 << Forward, 216 role1 :: Forward,
189 role2 << Backward, 217 role2 :: Backward,
190 not( 218 not(
191 TupleTableAtom.create( 219 TupleTableAtom.create(
192 tts, 220 tts,
@@ -204,10 +232,10 @@ class NaiveFilteringProgram(
204 index2 = query.bounded indexOf (role2.getArguments get 0) 232 index2 = query.bounded indexOf (role2.getArguments get 0)
205 if index2 >= 0 233 if index2 >= 0
206 } yield Rule.create( 234 } yield Rule.create(
207 RSA.FK, 235 FK,
208 RSA.ID(RSA(index1), RSA(index2)), 236 ID(RSA(index1), RSA(index2)),
209 role1 << Backward, 237 role1 :: Backward,
210 role2 << Backward, 238 role2 :: Backward,
211 not( 239 not(
212 TupleTableAtom.create( 240 TupleTableAtom.create(
213 tts, 241 tts,
@@ -234,18 +262,18 @@ class NaiveFilteringProgram(
234 r2arg2 = role2.getArguments get 2 262 r2arg2 = role2.getArguments get 2
235 if query.bounded contains r2arg2 263 if query.bounded contains r2arg2
236 } yield Rule.create( 264 } yield Rule.create(
237 RSA.ID( 265 ID(
238 RSA(query.bounded indexOf r1arg0), 266 RSA(query.bounded indexOf r1arg0),
239 RSA(query.bounded indexOf r2arg0) 267 RSA(query.bounded indexOf r2arg0)
240 ), 268 ),
241 RSA.ID( 269 ID(
242 RSA(query.bounded indexOf r1arg2), 270 RSA(query.bounded indexOf r1arg2),
243 RSA(query.bounded indexOf r2arg2) 271 RSA(query.bounded indexOf r2arg2)
244 ), 272 ),
245 TupleTableAtom.create(tts, r1arg0, RSA.CONGRUENT, r2arg0), 273 TupleTableAtom.create(tts, r1arg0, RSA.CONGRUENT, r2arg0),
246 role1 << Forward, 274 role1 :: Forward,
247 role2 << Forward, 275 role2 :: Forward,
248 not(RSA.NI(r1arg0)) 276 not(NI(r1arg0))
249 ) 277 )
250 val r5b = for { 278 val r5b = for {
251 role1 <- queryBody filter (_.isRoleAssertion) 279 role1 <- queryBody filter (_.isRoleAssertion)
@@ -259,18 +287,18 @@ class NaiveFilteringProgram(
259 r2arg2 = role2.getArguments get 2 287 r2arg2 = role2.getArguments get 2
260 if query.bounded contains r2arg2 288 if query.bounded contains r2arg2
261 } yield Rule.create( 289 } yield Rule.create(
262 RSA.ID( 290 ID(
263 RSA(query.bounded indexOf r1arg0), 291 RSA(query.bounded indexOf r1arg0),
264 RSA(query.bounded indexOf r2arg2) 292 RSA(query.bounded indexOf r2arg2)
265 ), 293 ),
266 RSA.ID( 294 ID(
267 RSA(query.bounded indexOf r1arg2), 295 RSA(query.bounded indexOf r1arg2),
268 RSA(query.bounded indexOf r2arg0) 296 RSA(query.bounded indexOf r2arg0)
269 ), 297 ),
270 TupleTableAtom.create(tts, r1arg0, RSA.CONGRUENT, r2arg2), 298 TupleTableAtom.create(tts, r1arg0, RSA.CONGRUENT, r2arg2),
271 role1 << Forward, 299 role1 :: Forward,
272 role2 << Backward, 300 role2 :: Backward,
273 not(RSA.NI(r1arg0)) 301 not(NI(r1arg0))
274 ) 302 )
275 val r5c = for { 303 val r5c = for {
276 role1 <- queryBody filter (_.isRoleAssertion) 304 role1 <- queryBody filter (_.isRoleAssertion)
@@ -284,18 +312,18 @@ class NaiveFilteringProgram(
284 r2arg2 = role2.getArguments get 2 312 r2arg2 = role2.getArguments get 2
285 if query.bounded contains r2arg2 313 if query.bounded contains r2arg2
286 } yield Rule.create( 314 } yield Rule.create(
287 RSA.ID( 315 ID(
288 RSA(query.bounded indexOf r1arg2), 316 RSA(query.bounded indexOf r1arg2),
289 RSA(query.bounded indexOf r2arg2) 317 RSA(query.bounded indexOf r2arg2)
290 ), 318 ),
291 RSA.ID( 319 ID(
292 RSA(query.bounded indexOf r1arg0), 320 RSA(query.bounded indexOf r1arg0),
293 RSA(query.bounded indexOf r2arg0) 321 RSA(query.bounded indexOf r2arg0)
294 ), 322 ),
295 TupleTableAtom.create(tts, r1arg2, RSA.CONGRUENT, r2arg2), 323 TupleTableAtom.create(tts, r1arg2, RSA.CONGRUENT, r2arg2),
296 role1 << Backward, 324 role1 :: Backward,
297 role2 << Backward, 325 role2 :: Backward,
298 not(RSA.NI(r1arg2)) 326 not(NI(r1arg2))
299 ) 327 )
300 328
301 /** Detect cycles in the canonical model. 329 /** Detect cycles in the canonical model.
@@ -314,23 +342,23 @@ class NaiveFilteringProgram(
314 if index2 >= 0 342 if index2 >= 0
315 suffix <- Seq(Forward, Backward) 343 suffix <- Seq(Forward, Backward)
316 } yield Rule.create( 344 } yield Rule.create(
317 RSA.AQ(suffix, varV, varW), 345 AQ(suffix, varV, varW),
318 role << suffix, 346 role :: suffix,
319 RSA.ID(RSA(index0), varV), 347 ID(RSA(index0), varV),
320 RSA.ID(RSA(index2), varW) 348 ID(RSA(index2), varW)
321 ) 349 )
322 val r7a = 350 val r7a =
323 for (suffix <- List(Forward, Backward)) 351 for (suffix <- List(Forward, Backward))
324 yield Rule.create( 352 yield Rule.create(
325 RSA.TQ(suffix, varU, varV), 353 TQ(suffix, varU, varV),
326 RSA.AQ(suffix, varU, varV) 354 AQ(suffix, varU, varV)
327 ) 355 )
328 val r7b = 356 val r7b =
329 for (suffix <- List(Forward, Backward)) 357 for (suffix <- List(Forward, Backward))
330 yield Rule.create( 358 yield Rule.create(
331 RSA.TQ(suffix, varU, varW), 359 TQ(suffix, varU, varW),
332 RSA.AQ(suffix, varU, varV), 360 AQ(suffix, varU, varV),
333 RSA.TQ(suffix, varV, varW) 361 TQ(suffix, varV, varW)
334 ) 362 )
335 363
336 /** Flag spurious answers. 364 /** Flag spurious answers.
@@ -340,19 +368,14 @@ class NaiveFilteringProgram(
340 val r8a = 368 val r8a =
341 for (v <- query.answer) 369 for (v <- query.answer)
342 yield Rule.create( 370 yield Rule.create(
343 RSA.SP, 371 SP,
344 RSA.QM, 372 QM,
345 not( 373 not(TupleTableAtom.create(tts, v, IRI.RDF_TYPE, RSA.NAMED))
346 TupleTableAtom.create(tts, v, IRI.RDF_TYPE, RSA.NAMED)
347 )
348 ) 374 )
349 val r8b = Rule.create(RSA.SP, RSA.FK) 375 val r8b = Rule.create(SP, FK)
350 val r8c = 376 val r8c =
351 for (suffix <- List(Forward, Backward)) 377 for (suffix <- List(Forward, Backward))
352 yield Rule.create( 378 yield Rule.create(SP, TQ(suffix, varV, varV))
353 RSA.SP,
354 RSA.TQ(suffix, varV, varV)
355 )
356 379
357 /** Determine answers to the query 380 /** Determine answers to the query
358 * 381 *
@@ -369,7 +392,7 @@ class NaiveFilteringProgram(
369 * 392 *
370 * @note corresponds to rule 9 in Table 3. 393 * @note corresponds to rule 9 in Table 3.
371 */ 394 */
372 val r9 = Rule.create(RSA.Ans, RSA.QM, not(RSA.SP)) 395 val r9 = Rule.create(Ans, QM, not(SP))
373 396
374 (r1 :: 397 (r1 ::
375 r3a ::: r3b :: r3c :: 398 r3a ::: r3b :: r3c ::
diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/filtering/RevisedFilteringProgram.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/filtering/RevisedFilteringProgram.scala
index 5d11369..f059bcd 100644
--- a/src/main/scala/uk/ac/ox/cs/rsacomb/filtering/RevisedFilteringProgram.scala
+++ b/src/main/scala/uk/ac/ox/cs/rsacomb/filtering/RevisedFilteringProgram.scala
@@ -54,8 +54,12 @@ object RevisedFilteringProgram {
54 * 54 *
55 * @param query CQ to be converted into logic rules. 55 * @param query CQ to be converted into logic rules.
56 */ 56 */
57 def apply(query: ConjunctiveQuery): RevisedFilteringProgram = 57 def apply(
58 new RevisedFilteringProgram(query) 58 source: IRI,
59 target: IRI,
60 query: ConjunctiveQuery
61 ): RevisedFilteringProgram =
62 new RevisedFilteringProgram(source, target, query)
59 63
60} 64}
61 65
@@ -66,8 +70,11 @@ object RevisedFilteringProgram {
66 * 70 *
67 * Instances can be created using the companion object. 71 * Instances can be created using the companion object.
68 */ 72 */
69class RevisedFilteringProgram(val query: ConjunctiveQuery) 73class RevisedFilteringProgram(
70 extends FilteringProgram { 74 val source: IRI,
75 val target: IRI,
76 val query: ConjunctiveQuery
77) extends FilteringProgram {
71 78
72 import RDFoxDSL._ 79 import RDFoxDSL._
73 80
@@ -76,45 +83,47 @@ class RevisedFilteringProgram(val query: ConjunctiveQuery)
76 */ 83 */
77 import uk.ac.ox.cs.rsacomb.implicits.RSAAtom._ 84 import uk.ac.ox.cs.rsacomb.implicits.RSAAtom._
78 85
86 /** Simplify conversion between Java and Scala `List`s */
87 import uk.ac.ox.cs.rsacomb.implicits.JavaCollections._
88
79 /** Implicit parameter used in RSA internal predicates. 89 /** Implicit parameter used in RSA internal predicates.
80 * 90 *
81 * @see [[uk.ac.ox.cs.rsacomb.util.RSA]] for more information. 91 * @see [[uk.ac.ox.cs.rsacomb.util.RSA]] for more information.
82 */ 92 */
83 implicit private[this] val _query = query 93 implicit private[this] val _query = query
84 94
85 /** Helpers */ 95 /** `TupleTableName`s for the source/targer named graphs */
96 val tts: TupleTableName = TupleTableName.create(source.getIRI)
97 val ttt: TupleTableName = TupleTableName.create(target.getIRI)
98
99 /** Set of atoms in the body of the query */
100 private val queryBody: List[TupleTableAtom] = query.atoms(tts)
86 101
87 //private def v(name: String): Term = Variable.create(s"${name}i") 102 /** Helpers */
88 private def not(atom: TupleTableAtom): BodyFormula = Negation.create(atom) 103 private def not(atom: TupleTableAtom): BodyFormula = Negation.create(atom)
89 104
90 private def named(x: Term): TupleTableAtom =
91 TupleTableAtom.rdf(x, IRI.RDF_TYPE, RSA.NAMED)
92 private def congruent(x: Term, y: Term): TupleTableAtom =
93 TupleTableAtom.rdf(x, RSA.CONGRUENT, y)
94 private def skolem(skolem: Term, terms: List[Term]): TupleTableAtom =
95 TupleTableAtom.create(TupleTableName.SKOLEM, (terms :+ skolem): _*)
96 private def QM(x: Term): TupleTableAtom = 105 private def QM(x: Term): TupleTableAtom =
97 TupleTableAtom.rdf(x, IRI.RDF_TYPE, RSA("QM")) 106 TupleTableAtom.create(ttt, x, IRI.RDF_TYPE, RSA.QM)
98 private def FK(x: Term): TupleTableAtom = 107 private def FK(x: Term): TupleTableAtom =
99 TupleTableAtom.rdf(x, IRI.RDF_TYPE, RSA("FK")) 108 TupleTableAtom.create(ttt, x, IRI.RDF_TYPE, RSA.FK)
100 private def SP(x: Term): TupleTableAtom = 109 private def SP(x: Term): TupleTableAtom =
101 TupleTableAtom.rdf(x, IRI.RDF_TYPE, RSA("SP")) 110 TupleTableAtom.create(ttt, x, IRI.RDF_TYPE, RSA.SP)
102 private def NI(x: Term): TupleTableAtom = 111 private def NI(x: Term): TupleTableAtom =
103 TupleTableAtom.rdf(x, IRI.RDF_TYPE, RSA("NI")) 112 TupleTableAtom.create(ttt, x, IRI.RDF_TYPE, RSA.NI)
104 private def Ans(x: Term): TupleTableAtom = 113 private def Ans(x: Term): TupleTableAtom =
105 TupleTableAtom.rdf(x, IRI.RDF_TYPE, RSA("Ans")) 114 TupleTableAtom.create(ttt, x, IRI.RDF_TYPE, RSA.ANS)
106 private def ID(x: Term, y: Term): TupleTableAtom = 115 private def ID(x: Term, y: Term): TupleTableAtom =
107 TupleTableAtom.rdf(x, RSA("ID"), y) 116 TupleTableAtom.create(ttt, x, RSA.ID, y)
108 private def AQ(suffix: RSASuffix, x: Term, y: Term): TupleTableAtom = 117 private def AQ(suffix: RSASuffix)(x: Term, y: Term): TupleTableAtom =
109 TupleTableAtom.rdf(x, RSA("AQ"), y) << suffix 118 TupleTableAtom.create(ttt, x, RSA.AQ :: suffix, y)
110 private def TQ(suffix: RSASuffix, x: Term, y: Term): TupleTableAtom = 119 private def TQ(suffix: RSASuffix)(x: Term, y: Term): TupleTableAtom =
111 TupleTableAtom.rdf(x, RSA("TQ"), y) << suffix 120 TupleTableAtom.create(ttt, x, RSA.TQ :: suffix, y)
112 121
113 /** Rule generating the instances of the predicate `rsa:NI`. 122 /** Rule generating the instances of the predicate `rsa:NI`.
114 * 123 *
115 * According to the original paper, the set of `rsa:NI` is defined as 124 * According to the original paper, the set of `rsa:NI` is defined as
116 * the set of constants that are equal (w.r.t. the congruence 125 * the set of constants that are equal (w.r.t. the congruence
117 * relation represented by `rsa:Congruent`) to a constant in the 126 * relation represented by `rsacomb:Congruent`) to a constant in the
118 * original ontology. 127 * original ontology.
119 * 128 *
120 * @note that the set of `rsa:Named` constants is always a subset of 129 * @note that the set of `rsa:Named` constants is always a subset of
@@ -125,7 +134,8 @@ class RevisedFilteringProgram(val query: ConjunctiveQuery)
125 * predicate, this is not feasible, and the instances are instead 134 * predicate, this is not feasible, and the instances are instead
126 * generate in the filtering program using a logic rule. 135 * generate in the filtering program using a logic rule.
127 */ 136 */
128 val nis: Rule = Rule.create(NI(v"X"), named(v"Y"), congruent(v"X", v"Y")) 137 val nis: Rule =
138 Rule.create(NI(v"X"), RSA.Named(tts)(v"Y"), RSA.Congruent(tts)(v"X", v"Y"))
129 139
130 /** Collection of filtering program rules. */ 140 /** Collection of filtering program rules. */
131 val rules: List[Rule] = 141 val rules: List[Rule] =
@@ -138,7 +148,7 @@ class RevisedFilteringProgram(val query: ConjunctiveQuery)
138 * @note corresponds to rule 1 in Table 3 in the paper. 148 * @note corresponds to rule 1 in Table 3 in the paper.
139 */ 149 */
140 val r1 = 150 val r1 =
141 Rule.create(QM(v"K"), (query.atoms :+ skolem(v"K", variables)): _*) 151 Rule.create(QM(v"K"), queryBody :+ RSA.Skolem(v"K", variables))
142 152
143 /** Initializes instances of `rsa:ID`. 153 /** Initializes instances of `rsa:ID`.
144 * 154 *
@@ -153,26 +163,26 @@ class RevisedFilteringProgram(val query: ConjunctiveQuery)
153 yield Rule.create( 163 yield Rule.create(
154 ID(v"K", v"S"), 164 ID(v"K", v"S"),
155 QM(v"K"), 165 QM(v"K"),
156 skolem(v"K", variables), 166 RSA.Skolem(v"K", variables),
157 not(NI(v)), 167 not(NI(v)),
158 skolem(v"S", variables :+ RSA(i) :+ RSA(i)) 168 RSA.Skolem(v"S", variables :+ RSA(i) :+ RSA(i))
159 ) 169 )
160 val r3b = Rule.create( 170 val r3b = Rule.create(
161 ID(v"K", v"T"), 171 ID(v"K", v"T"),
162 ID(v"K", v"S"), 172 ID(v"K", v"S"),
163 skolem(v"S", variables :+ v"U" :+ v"V"), 173 RSA.Skolem(v"S", variables :+ v"U" :+ v"V"),
164 skolem(v"T", variables :+ v"V" :+ v"U") 174 RSA.Skolem(v"T", variables :+ v"V" :+ v"U")
165 ) 175 )
166 val r3c = Rule.create( 176 val r3c = Rule.create(
167 ID(v"K1", v"Q"), 177 ID(v"K1", v"Q"),
168 QM(v"K1"), 178 QM(v"K1"),
169 ID(v"K2", v"S"), 179 ID(v"K2", v"S"),
170 FilterAtom.create(FunctionCall.equal(v"K1", v"K2")), 180 FilterAtom.create(FunctionCall.equal(v"K1", v"K2")),
171 skolem(v"S", variables :+ v"U" :+ v"V"), 181 RSA.Skolem(v"S", variables :+ v"U" :+ v"V"),
172 ID(v"K3", v"T"), 182 ID(v"K3", v"T"),
173 FilterAtom.create(FunctionCall.equal(v"K1", v"K3")), 183 FilterAtom.create(FunctionCall.equal(v"K1", v"K3")),
174 skolem(v"T", variables :+ v"V" :+ v"W"), 184 RSA.Skolem(v"T", variables :+ v"V" :+ v"W"),
175 skolem(v"Q", variables :+ v"U" :+ v"W") 185 RSA.Skolem(v"Q", variables :+ v"U" :+ v"W")
176 ) 186 )
177 187
178 /** Detects forks in the canonical model. 188 /** Detects forks in the canonical model.
@@ -180,49 +190,55 @@ class RevisedFilteringProgram(val query: ConjunctiveQuery)
180 * @note corresponds to rules 4x in Table 3. 190 * @note corresponds to rules 4x in Table 3.
181 */ 191 */
182 val r4a = for { 192 val r4a = for {
183 role1 <- query.atoms filter (_.isRoleAssertion) 193 role1 <- queryBody filter (_.isRoleAssertion)
184 index1 = query.bounded indexOf (role1.getArguments get 2) 194 index1 = query.bounded indexOf (role1.getArguments get 2)
185 if index1 >= 0 195 if index1 >= 0
186 role2 <- query.atoms filter (_.isRoleAssertion) 196 role2 <- queryBody filter (_.isRoleAssertion)
187 index2 = query.bounded indexOf (role2.getArguments get 2) 197 index2 = query.bounded indexOf (role2.getArguments get 2)
188 if index2 >= 0 198 if index2 >= 0
189 } yield Rule.create( 199 } yield Rule.create(
190 FK(v"K"), 200 FK(v"K"),
191 ID(v"K", v"S"), 201 ID(v"K", v"S"),
192 skolem(v"S", variables :+ RSA(index1) :+ RSA(index2)), 202 RSA.Skolem(v"S", variables :+ RSA(index1) :+ RSA(index2)),
193 role1 << Forward, 203 role1 :: Forward,
194 role2 << Forward, 204 role2 :: Forward,
195 not(RSA.Congruent(role1.getArguments get 0, role2.getArguments get 0)) 205 not(
206 RSA.Congruent(tts)(role1.getArguments get 0, role2.getArguments get 0)
207 )
196 ) 208 )
197 val r4b = for { 209 val r4b = for {
198 role1 <- query.atoms filter (_.isRoleAssertion) 210 role1 <- queryBody filter (_.isRoleAssertion)
199 index1 = query.bounded indexOf (role1.getArguments get 2) 211 index1 = query.bounded indexOf (role1.getArguments get 2)
200 if index1 >= 0 212 if index1 >= 0
201 role2 <- query.atoms filter (_.isRoleAssertion) 213 role2 <- queryBody filter (_.isRoleAssertion)
202 index2 = query.bounded indexOf (role2.getArguments get 0) 214 index2 = query.bounded indexOf (role2.getArguments get 0)
203 if index2 >= 0 215 if index2 >= 0
204 } yield Rule.create( 216 } yield Rule.create(
205 FK(v"K"), 217 FK(v"K"),
206 ID(v"K", v"S"), 218 ID(v"K", v"S"),
207 skolem(v"S", variables :+ RSA(index1) :+ RSA(index2)), 219 RSA.Skolem(v"S", variables :+ RSA(index1) :+ RSA(index2)),
208 role1 << Forward, 220 role1 :: Forward,
209 role2 << Backward, 221 role2 :: Backward,
210 not(RSA.Congruent(role1.getArguments get 0, role2.getArguments get 2)) 222 not(
223 RSA.Congruent(tts)(role1.getArguments get 0, role2.getArguments get 2)
224 )
211 ) 225 )
212 val r4c = for { 226 val r4c = for {
213 role1 <- query.atoms filter (_.isRoleAssertion) 227 role1 <- queryBody filter (_.isRoleAssertion)
214 index1 = query.bounded indexOf (role1.getArguments get 0) 228 index1 = query.bounded indexOf (role1.getArguments get 0)
215 if index1 >= 0 229 if index1 >= 0
216 role2 <- query.atoms filter (_.isRoleAssertion) 230 role2 <- queryBody filter (_.isRoleAssertion)
217 index2 = query.bounded indexOf (role2.getArguments get 0) 231 index2 = query.bounded indexOf (role2.getArguments get 0)
218 if index2 >= 0 232 if index2 >= 0
219 } yield Rule.create( 233 } yield Rule.create(
220 FK(v"K"), 234 FK(v"K"),
221 ID(v"K", v"S"), 235 ID(v"K", v"S"),
222 skolem(v"S", variables :+ RSA(index1) :+ RSA(index2)), 236 RSA.Skolem(v"S", variables :+ RSA(index1) :+ RSA(index2)),
223 role1 << Backward, 237 role1 :: Backward,
224 role2 << Backward, 238 role2 :: Backward,
225 not(RSA.Congruent(role1.getArguments get 2, role2.getArguments get 2)) 239 not(
240 RSA.Congruent(tts)(role1.getArguments get 2, role2.getArguments get 2)
241 )
226 ) 242 )
227 243
228 /** Recursively propagates `rsa:ID` predicate. 244 /** Recursively propagates `rsa:ID` predicate.
@@ -230,12 +246,12 @@ class RevisedFilteringProgram(val query: ConjunctiveQuery)
230 * @note corresponds to rules 5x in Table 3. 246 * @note corresponds to rules 5x in Table 3.
231 */ 247 */
232 val r5a = for { 248 val r5a = for {
233 role1 <- query.atoms filter (_.isRoleAssertion) 249 role1 <- queryBody filter (_.isRoleAssertion)
234 r1arg0 = role1.getArguments get 0 250 r1arg0 = role1.getArguments get 0
235 if query.bounded contains r1arg0 251 if query.bounded contains r1arg0
236 r1arg2 = role1.getArguments get 2 252 r1arg2 = role1.getArguments get 2
237 if query.bounded contains r1arg2 253 if query.bounded contains r1arg2
238 role2 <- query.atoms filter (_.isRoleAssertion) 254 role2 <- queryBody filter (_.isRoleAssertion)
239 r2arg0 = role2.getArguments get 0 255 r2arg0 = role2.getArguments get 0
240 if query.bounded contains r2arg0 256 if query.bounded contains r2arg0
241 r2arg2 = role2.getArguments get 2 257 r2arg2 = role2.getArguments get 2
@@ -243,17 +259,17 @@ class RevisedFilteringProgram(val query: ConjunctiveQuery)
243 } yield Rule.create( 259 } yield Rule.create(
244 ID(v"K", v"T"), 260 ID(v"K", v"T"),
245 ID(v"K", v"S"), 261 ID(v"K", v"S"),
246 skolem( 262 RSA.Skolem(
247 v"S", 263 v"S",
248 variables :+ 264 variables :+
249 RSA(query.bounded indexOf r1arg2) :+ 265 RSA(query.bounded indexOf r1arg2) :+
250 RSA(query.bounded indexOf r2arg2) 266 RSA(query.bounded indexOf r2arg2)
251 ), 267 ),
252 RSA.Congruent(r1arg0, r2arg0), 268 RSA.Congruent(tts)(r1arg0, r2arg0),
253 role1 << Forward, 269 role1 :: Forward,
254 role2 << Forward, 270 role2 :: Forward,
255 not(NI(r1arg0)), 271 not(NI(r1arg0)),
256 skolem( 272 RSA.Skolem(
257 v"T", 273 v"T",
258 variables :+ 274 variables :+
259 RSA(query.bounded indexOf r1arg0) :+ 275 RSA(query.bounded indexOf r1arg0) :+
@@ -261,12 +277,12 @@ class RevisedFilteringProgram(val query: ConjunctiveQuery)
261 ) 277 )
262 ) 278 )
263 val r5b = for { 279 val r5b = for {
264 role1 <- query.atoms filter (_.isRoleAssertion) 280 role1 <- queryBody filter (_.isRoleAssertion)
265 r1arg0 = role1.getArguments get 0 281 r1arg0 = role1.getArguments get 0
266 if query.bounded contains r1arg0 282 if query.bounded contains r1arg0
267 r1arg2 = role1.getArguments get 2 283 r1arg2 = role1.getArguments get 2
268 if query.bounded contains r1arg2 284 if query.bounded contains r1arg2
269 role2 <- query.atoms filter (_.isRoleAssertion) 285 role2 <- queryBody filter (_.isRoleAssertion)
270 r2arg0 = role2.getArguments get 0 286 r2arg0 = role2.getArguments get 0
271 if query.bounded contains r2arg0 287 if query.bounded contains r2arg0
272 r2arg2 = role2.getArguments get 2 288 r2arg2 = role2.getArguments get 2
@@ -274,17 +290,17 @@ class RevisedFilteringProgram(val query: ConjunctiveQuery)
274 } yield Rule.create( 290 } yield Rule.create(
275 ID(v"K", v"T"), 291 ID(v"K", v"T"),
276 ID(v"K", v"S"), 292 ID(v"K", v"S"),
277 skolem( 293 RSA.Skolem(
278 v"S", 294 v"S",
279 variables :+ 295 variables :+
280 RSA(query.bounded indexOf r1arg2) :+ 296 RSA(query.bounded indexOf r1arg2) :+
281 RSA(query.bounded indexOf r2arg0) 297 RSA(query.bounded indexOf r2arg0)
282 ), 298 ),
283 RSA.Congruent(r1arg0, r2arg2), 299 RSA.Congruent(tts)(r1arg0, r2arg2),
284 role1 << Forward, 300 role1 :: Forward,
285 role2 << Backward, 301 role2 :: Backward,
286 not(RSA.NI(r1arg0)), 302 not(NI(r1arg0)),
287 skolem( 303 RSA.Skolem(
288 v"T", 304 v"T",
289 variables :+ 305 variables :+
290 RSA(query.bounded indexOf r1arg0) :+ 306 RSA(query.bounded indexOf r1arg0) :+
@@ -292,12 +308,12 @@ class RevisedFilteringProgram(val query: ConjunctiveQuery)
292 ) 308 )
293 ) 309 )
294 val r5c = for { 310 val r5c = for {
295 role1 <- query.atoms filter (_.isRoleAssertion) 311 role1 <- queryBody filter (_.isRoleAssertion)
296 r1arg0 = role1.getArguments get 0 312 r1arg0 = role1.getArguments get 0
297 if query.bounded contains r1arg0 313 if query.bounded contains r1arg0
298 r1arg2 = role1.getArguments get 2 314 r1arg2 = role1.getArguments get 2
299 if query.bounded contains r1arg2 315 if query.bounded contains r1arg2
300 role2 <- query.atoms filter (_.isRoleAssertion) 316 role2 <- queryBody filter (_.isRoleAssertion)
301 r2arg0 = role2.getArguments get 0 317 r2arg0 = role2.getArguments get 0
302 if query.bounded contains r2arg0 318 if query.bounded contains r2arg0
303 r2arg2 = role2.getArguments get 2 319 r2arg2 = role2.getArguments get 2
@@ -305,17 +321,17 @@ class RevisedFilteringProgram(val query: ConjunctiveQuery)
305 } yield Rule.create( 321 } yield Rule.create(
306 ID(v"K", v"T"), 322 ID(v"K", v"T"),
307 ID(v"K", v"S"), 323 ID(v"K", v"S"),
308 skolem( 324 RSA.Skolem(
309 v"S", 325 v"S",
310 variables :+ 326 variables :+
311 RSA(query.bounded indexOf r1arg0) :+ 327 RSA(query.bounded indexOf r1arg0) :+
312 RSA(query.bounded indexOf r2arg0) 328 RSA(query.bounded indexOf r2arg0)
313 ), 329 ),
314 RSA.Congruent(r1arg2, r2arg2), 330 RSA.Congruent(tts)(r1arg2, r2arg2),
315 role1 << Backward, 331 role1 :: Backward,
316 role2 << Backward, 332 role2 :: Backward,
317 not(RSA.NI(r1arg2)), 333 not(NI(r1arg2)),
318 skolem( 334 RSA.Skolem(
319 v"T", 335 v"T",
320 variables :+ 336 variables :+
321 RSA(query.bounded indexOf r1arg2) :+ 337 RSA(query.bounded indexOf r1arg2) :+
@@ -332,38 +348,38 @@ class RevisedFilteringProgram(val query: ConjunctiveQuery)
332 * @note corresponds to rules 6,7x in Table 3. 348 * @note corresponds to rules 6,7x in Table 3.
333 */ 349 */
334 val r6 = for { 350 val r6 = for {
335 role <- query.atoms filter (_.isRoleAssertion) 351 role <- queryBody filter (_.isRoleAssertion)
336 index0 = query.bounded indexOf (role.getArguments get 0) 352 index0 = query.bounded indexOf (role.getArguments get 0)
337 if index0 >= 0 353 if index0 >= 0
338 index2 = query.bounded indexOf (role.getArguments get 2) 354 index2 = query.bounded indexOf (role.getArguments get 2)
339 if index2 >= 0 355 if index2 >= 0
340 suffix <- Seq(Forward, Backward) 356 suffix <- Seq(Forward, Backward)
341 } yield Rule.create( 357 } yield Rule.create(
342 AQ(suffix, v"K1", v"Q"), 358 AQ(suffix)(v"K1", v"Q"),
343 ID(v"K1", v"S"), 359 ID(v"K1", v"S"),
344 skolem(v"S", variables :+ RSA(index0) :+ v"V"), 360 RSA.Skolem(v"S", variables :+ RSA(index0) :+ v"V"),
345 ID(v"K2", v"T"), 361 ID(v"K2", v"T"),
346 FilterAtom.create(FunctionCall.equal(v"K1", v"K2")), 362 FilterAtom.create(FunctionCall.equal(v"K1", v"K2")),
347 skolem(v"T", variables :+ RSA(index2) :+ v"W"), 363 RSA.Skolem(v"T", variables :+ RSA(index2) :+ v"W"),
348 role << suffix, 364 role :: suffix,
349 skolem(v"Q", variables :+ v"V" :+ v"W") 365 RSA.Skolem(v"Q", variables :+ v"V" :+ v"W")
350 ) 366 )
351 val r7a = 367 val r7a =
352 for (suffix <- List(Forward, Backward)) 368 for (suffix <- List(Forward, Backward))
353 yield Rule.create( 369 yield Rule.create(
354 TQ(suffix, v"K", v"S"), 370 TQ(suffix)(v"K", v"S"),
355 AQ(suffix, v"K", v"S") 371 AQ(suffix)(v"K", v"S")
356 ) 372 )
357 val r7b = 373 val r7b =
358 for (suffix <- List(Forward, Backward)) 374 for (suffix <- List(Forward, Backward))
359 yield Rule.create( 375 yield Rule.create(
360 TQ(suffix, v"K1", v"Q"), 376 TQ(suffix)(v"K1", v"Q"),
361 AQ(suffix, v"K1", v"S"), 377 AQ(suffix)(v"K1", v"S"),
362 skolem(v"S", variables :+ v"U" :+ v"V"), 378 RSA.Skolem(v"S", variables :+ v"U" :+ v"V"),
363 TQ(suffix, v"K2", v"T"), 379 TQ(suffix)(v"K2", v"T"),
364 FilterAtom.create(FunctionCall.equal(v"K1", v"K2")), 380 FilterAtom.create(FunctionCall.equal(v"K1", v"K2")),
365 skolem(v"T", variables :+ v"V" :+ v"W"), 381 RSA.Skolem(v"T", variables :+ v"V" :+ v"W"),
366 skolem(v"Q", variables :+ v"U" :+ v"W") 382 RSA.Skolem(v"Q", variables :+ v"U" :+ v"W")
367 ) 383 )
368 384
369 /** Flag spurious answers. 385 /** Flag spurious answers.
@@ -375,19 +391,16 @@ class RevisedFilteringProgram(val query: ConjunctiveQuery)
375 yield Rule.create( 391 yield Rule.create(
376 SP(v"K"), 392 SP(v"K"),
377 QM(v"K"), 393 QM(v"K"),
378 skolem(v"K", variables), 394 RSA.Skolem(v"K", variables),
379 not(RSA.Named(v)) 395 not(RSA.Named(tts)(v))
380 ) 396 )
381 val r8b = Rule.create( 397 val r8b = Rule.create(SP(v"K"), FK(v"K"))
382 SP(v"K"),
383 FK(v"K")
384 )
385 val r8c = 398 val r8c =
386 for (suffix <- List(Forward, Backward)) 399 for (suffix <- List(Forward, Backward))
387 yield Rule.create( 400 yield Rule.create(
388 SP(v"K"), 401 SP(v"K"),
389 TQ(suffix, v"K", v"S"), 402 TQ(suffix)(v"K", v"S"),
390 skolem(v"S", variables :+ v"V" :+ v"V") 403 RSA.Skolem(v"S", variables :+ v"V" :+ v"V")
391 ) 404 )
392 405
393 /** Determine answers to the query 406 /** Determine answers to the query
@@ -405,11 +418,7 @@ class RevisedFilteringProgram(val query: ConjunctiveQuery)
405 * 418 *
406 * @note corresponds to rule 9 in Table 3. 419 * @note corresponds to rule 9 in Table 3.
407 */ 420 */
408 val r9 = Rule.create( 421 val r9 = Rule.create(Ans(v"K"), QM(v"K"), not(SP(v"K")))
409 Ans(v"K"),
410 QM(v"K"),
411 not(SP(v"K"))
412 )
413 422
414 (r1 :: r3a ::: r3b :: r3c :: r4a ::: r4b ::: r4c ::: r5a ::: r5b ::: r5c ::: r6 ::: r7b ::: r7a ::: r8a ::: r8b :: r8c ::: r9 :: List()) 423 (r1 :: r3a ::: r3b :: r3c :: r4a ::: r4b ::: r4c ::: r5a ::: r5b ::: r5c ::: r6 ::: r7b ::: r7a ::: r8a ::: r8b :: r8c ::: r9 :: List())
415 } 424 }
@@ -422,12 +431,12 @@ class RevisedFilteringProgram(val query: ConjunctiveQuery)
422 s""" 431 s"""
423 SELECT $answer 432 SELECT $answer
424 WHERE { 433 WHERE {
425 GRAPH <$graph> { ?K a rsa:Ans } . 434 GRAPH $target { ?K a ${RSA.ANS} } .
426 TT <http://oxfordsemantic.tech/RDFox#SKOLEM> { $answer $bounded ?K } . 435 TT ${TupleTableName.SKOLEM} { $answer $bounded ?K } .
427 } 436 }
428 """ 437 """
429 } else { 438 } else {
430 s"ASK { GRAPH <$graph> { ?X a rsa:Ans } }" 439 s"ASK { GRAPH $target { ?X a ${RSA.ANS} } }"
431 } 440 }
432 } 441 }
433 442
diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/implicits/RDFox.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/implicits/RDFox.scala
index d4b7876..ca77409 100644
--- a/src/main/scala/uk/ac/ox/cs/rsacomb/implicits/RDFox.scala
+++ b/src/main/scala/uk/ac/ox/cs/rsacomb/implicits/RDFox.scala
@@ -17,6 +17,7 @@
17package uk.ac.ox.cs.rsacomb.implicits 17package uk.ac.ox.cs.rsacomb.implicits
18 18
19import tech.oxfordsemantic.jrdfox.logic.Datatype 19import tech.oxfordsemantic.jrdfox.logic.Datatype
20import tech.oxfordsemantic.jrdfox.logic.datalog.TupleTableName
20import tech.oxfordsemantic.jrdfox.logic.expression.{ 21import tech.oxfordsemantic.jrdfox.logic.expression.{
21 BlankNode, 22 BlankNode,
22 IRI => RDFoxIRI, 23 IRI => RDFoxIRI,
@@ -47,6 +48,9 @@ object RDFox {
47 implicit def stringToRdfoxIri(iri: String): RDFoxIRI = 48 implicit def stringToRdfoxIri(iri: String): RDFoxIRI =
48 RDFoxIRI.create(iri) 49 RDFoxIRI.create(iri)
49 50
51 implicit def iriToTupleTableName(iri: RDFoxIRI): TupleTableName =
52 TupleTableName.create(iri.getIRI)
53
50 /** Converst an OWLAPI datatype into an RDFox datatype. 54 /** Converst an OWLAPI datatype into an RDFox datatype.
51 * 55 *
52 * The builtin datatypes defined by the two systems do not match 56 * The builtin datatypes defined by the two systems do not match
diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/implicits/RSAAtom.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/implicits/RSAAtom.scala
index 37c70df..89777c4 100644
--- a/src/main/scala/uk/ac/ox/cs/rsacomb/implicits/RSAAtom.scala
+++ b/src/main/scala/uk/ac/ox/cs/rsacomb/implicits/RSAAtom.scala
@@ -29,21 +29,6 @@ import uk.ac.ox.cs.rsacomb.RSAOntology
29import uk.ac.ox.cs.rsacomb.suffix.{RSASuffix, Nth} 29import uk.ac.ox.cs.rsacomb.suffix.{RSASuffix, Nth}
30import uk.ac.ox.cs.rsacomb.util.{DataFactory, RDFoxUtil} 30import uk.ac.ox.cs.rsacomb.util.{DataFactory, RDFoxUtil}
31 31
32/* Is this the best way to determine if an atom is an RDF triple?
33 * Note that we can't use `getNumberOfArguments()` because is not
34 * "consistent":
35 * - for an atom created with `rdf(<term1>, <term2>, <term3>)`,
36 * `getNumberOfArguments` returns 3
37 * - for an atom created with `Atom.create(<tupletablename>, <term1>,
38 * <term2>, <term3>)`, `getNumberOfArguments()` returns 3
39 *
40 * This is probably because `Atom.rdf(...) is implemented as:
41 * ```scala
42 * def rdf(term1: Term, term2: Term, term3: Term): Atom =
43 * Atom.create(TupleTableName.create("rdfox:DefaultTriples"), term1, term2, term3)
44 * ```
45 */
46
47object RSAAtom { 32object RSAAtom {
48 33
49 implicit class RSAAtom(val atom: TupleTableAtom) { 34 implicit class RSAAtom(val atom: TupleTableAtom) {
@@ -62,25 +47,25 @@ object RSAAtom {
62 47
63 val isRoleAssertion: Boolean = isRDF && !isClassAssertion 48 val isRoleAssertion: Boolean = isRDF && !isClassAssertion
64 49
65 def <<(suffix: RSASuffix): TupleTableAtom = 50 // def <<(suffix: RSASuffix): TupleTableAtom =
66 if (isRDF) { 51 // if (isRDF) {
67 val subj = atom.getArguments.get(0) 52 // val subj = atom.getArguments.get(0)
68 val pred = atom.getArguments.get(1) 53 // val pred = atom.getArguments.get(1)
69 val obj = atom.getArguments.get(2) 54 // val obj = atom.getArguments.get(2)
70 if (isClassAssertion) { 55 // if (isClassAssertion) {
71 val obj1 = obj match { 56 // val obj1 = obj match {
72 case iri: IRI => IRI.create(iri.getIRI :: suffix) 57 // case iri: IRI => IRI.create(iri.getIRI :: suffix)
73 case other => other 58 // case other => other
74 } 59 // }
75 TupleTableAtom.create(tt, subj, pred, obj1) 60 // TupleTableAtom.create(tt, subj, pred, obj1)
76 } else { 61 // } else {
77 val pred1 = pred match { 62 // val pred1 = pred match {
78 case iri: IRI => IRI.create(iri.getIRI :: suffix) 63 // case iri: IRI => IRI.create(iri.getIRI :: suffix)
79 case other => other 64 // case other => other
80 } 65 // }
81 TupleTableAtom.create(tt, subj, pred1, obj) 66 // TupleTableAtom.create(tt, subj, pred1, obj)
82 } 67 // }
83 } else atom 68 // } else atom
84 69
85 // def reified(implicit 70 // def reified(implicit
86 // fresh: DataFactory 71 // fresh: DataFactory
diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/suffix/RSASuffix.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/suffix/RSASuffix.scala
index 424f2a0..282aa0b 100644
--- a/src/main/scala/uk/ac/ox/cs/rsacomb/suffix/RSASuffix.scala
+++ b/src/main/scala/uk/ac/ox/cs/rsacomb/suffix/RSASuffix.scala
@@ -16,13 +16,13 @@
16 16
17package uk.ac.ox.cs.rsacomb.suffix 17package uk.ac.ox.cs.rsacomb.suffix
18 18
19import org.semanticweb.owlapi.model.{ 19// import org.semanticweb.owlapi.model.{
20 OWLPropertyExpression, 20// OWLPropertyExpression,
21 OWLObjectInverseOf, 21// OWLObjectInverseOf,
22 OWLObjectProperty 22// OWLObjectProperty
23} 23// }
24 24
25import tech.oxfordsemantic.jrdfox.logic.expression.{IRI} 25import tech.oxfordsemantic.jrdfox.logic.expression.{IRI, Term}
26import tech.oxfordsemantic.jrdfox.logic.datalog.{TupleTableAtom, TupleTableName} 26import tech.oxfordsemantic.jrdfox.logic.datalog.{TupleTableAtom, TupleTableName}
27 27
28object RSASuffix { 28object RSASuffix {
@@ -37,7 +37,17 @@ class RSASuffix(val suffix: String => String) {
37 new RSASuffix(this.suffix andThen that.suffix) 37 new RSASuffix(this.suffix andThen that.suffix)
38 38
39 def ::(str: String): String = this suffix str 39 def ::(str: String): String = this suffix str
40 40 def ::(iri: IRI): IRI = IRI.create(this suffix iri.getIRI)
41 def ::(tta: TupleTableAtom): TupleTableAtom = {
42 val ttn: TupleTableName = tta.getTupleTableName
43 tta.getArguments match {
44 case List(subj: Term, IRI.RDF_TYPE, obj: IRI) =>
45 TupleTableAtom.create(ttn, subj, IRI.RDF_TYPE, obj :: this)
46 case List(subj: Term, pred: IRI, obj: Term) =>
47 TupleTableAtom.create(ttn, subj, pred :: this, obj)
48 case _ => tta
49 }
50 }
41} 51}
42 52
43case object Empty extends RSASuffix(identity) 53case object Empty extends RSASuffix(identity)
diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/util/RSA.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/util/RSA.scala
index 40c5ced..5abb83c 100644
--- a/src/main/scala/uk/ac/ox/cs/rsacomb/util/RSA.scala
+++ b/src/main/scala/uk/ac/ox/cs/rsacomb/util/RSA.scala
@@ -54,73 +54,35 @@ object RSA {
54 /** Creates a `rsacomb:<name>` IRI */ 54 /** Creates a `rsacomb:<name>` IRI */
55 def apply(name: Any): IRI = 55 def apply(name: Any): IRI =
56 IRI.create( 56 IRI.create(
57 //Prefixes.decodeIRI("rsacomb:") + name.toString
57 Prefixes.getPrefixIRIsByPrefixName.get("rsacomb:").getIRI + name.toString 58 Prefixes.getPrefixIRIsByPrefixName.get("rsacomb:").getIRI + name.toString
58 ) 59 )
59 60
61 /** Helper IRIs */
60 val ANS = RSA("Ans") 62 val ANS = RSA("Ans")
63 val AQ = RSA("AQ")
61 val CONGRUENT = RSA("congruent") 64 val CONGRUENT = RSA("congruent")
65 val FK = RSA("FK")
66 val ID = RSA("ID")
62 val IN = RSA("In") 67 val IN = RSA("In")
63 val NAMED = RSA("Named") 68 val NAMED = RSA("Named")
69 val NI = RSA("NI")
70 val QM = RSA("QM")
71 val SP = RSA("SP")
72 val TQ = RSA("TQ")
73
74 def Named(tt: TupleTableName)(x: Term): TupleTableAtom =
75 TupleTableAtom.create(tt, x, IRI.RDF_TYPE, RSA.NAMED)
76 def Congruent(tt: TupleTableName)(x: Term, y: Term): TupleTableAtom =
77 TupleTableAtom.create(tt, x, RSA.CONGRUENT, y)
78 def Skolem(skolem: Term, terms: List[Term]): TupleTableAtom =
79 TupleTableAtom.create(TupleTableName.SKOLEM, terms :+ skolem)
64 80
65 // def In(t: Term)(implicit set: Term) = 81 // def In(t: Term)(implicit set: Term) =
66 // TupleTableAtom.rdf(t, RSA("In"), set) 82 // TupleTableAtom.rdf(t, RSA("In"), set)
67 83
68 // def NotIn(t: Term)(implicit set: Term) = Negation.create(In(t)(set)) 84 // def NotIn(t: Term)(implicit set: Term) = Negation.create(In(t)(set))
69 85
70 def Congruent(t1: Term, t2: Term)(implicit graph: TupleTableName) =
71 TupleTableAtom.create(graph, t1, RSA.CONGRUENT, t2)
72
73 def Named(term: Term)(implicit graph: TupleTableName) =
74 TupleTableAtom.create(graph, term, IRI.RDF_TYPE, RSA.NAMED)
75
76 def QM(implicit query: ConjunctiveQuery, graph: TupleTableName) =
77 TupleTableAtom.create(graph, RSA("QM") :: query.answer ::: query.bounded)
78
79 def ID(t1: Term, t2: Term)(implicit
80 query: ConjunctiveQuery,
81 graph: TupleTableName
82 ) =
83 TupleTableAtom.create(
84 graph,
85 RSA("ID") +: (query.answer ::: query.bounded) :+ t1 :+ t2
86 )
87
88 // def Thing(t: Term) =
89 // TupleTableAtom.rdf(t, IRI.RDF_TYPE, IRI.THING)
90
91 def NI(term: Term)(implicit graph: TupleTableName) =
92 TupleTableAtom.create(graph, term, IRI.RDF_TYPE, RSA("NI"))
93
94 def TQ(sx: RSASuffix, t1: Term, t2: Term)(implicit
95 query: ConjunctiveQuery,
96 graph: TupleTableName
97 ) =
98 TupleTableAtom.create(
99 graph,
100 RSA("TQ" :: sx) +: (query.answer ::: query.bounded) :+ t1 :+ t2
101 )
102
103 def AQ(sx: RSASuffix, t1: Term, t2: Term)(implicit
104 query: ConjunctiveQuery,
105 graph: TupleTableName
106 ) =
107 TupleTableAtom.create(
108 graph,
109 RSA("AQ" :: sx) +: (query.answer ::: query.bounded) :+ t1 :+ t2
110 )
111
112 def FK(implicit query: ConjunctiveQuery, graph: TupleTableName) =
113 TupleTableAtom.create(graph, RSA("FK") :: query.answer ::: query.bounded)
114
115 def SP(implicit q: ConjunctiveQuery, graph: TupleTableName) =
116 TupleTableAtom.create(graph, RSA("SP") :: q.answer ::: q.bounded)
117
118 def Ans(implicit q: ConjunctiveQuery, graph: TupleTableName) =
119 if (q.bcq)
120 TupleTableAtom.create(graph, RSA("blank"), IRI.RDF_TYPE, RSA.ANS)
121 else
122 TupleTableAtom.create(graph, RSA.ANS :: q.answer)
123
124 /* TODO: review after reworking the dependency graph construction */ 86 /* TODO: review after reworking the dependency graph construction */
125 87
126 // private def atom(name: IRI, vars: List[Term]): TupleTableAtom = 88 // private def atom(name: IRI, vars: List[Term]): TupleTableAtom =