diff options
author | Federico Igne <git@federicoigne.com> | 2021-10-02 09:15:43 +0100 |
---|---|---|
committer | Federico Igne <git@federicoigne.com> | 2021-10-02 09:15:43 +0100 |
commit | 424d5d6fcabb410622907c095364903577014765 (patch) | |
tree | 4025b3136572e40ce619affcf94def09ae186be7 | |
parent | 360e10e686d144b918825939f48004aebc31b7f3 (diff) | |
download | RSAComb-424d5d6fcabb410622907c095364903577014765.tar.gz RSAComb-424d5d6fcabb410622907c095364903577014765.zip |
Rework revides filtering program computation to use named graphs
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 | } |
34 | import uk.ac.ox.cs.rsacomb.sparql.ConjunctiveQuery | 34 | import uk.ac.ox.cs.rsacomb.sparql.ConjunctiveQuery |
35 | import uk.ac.ox.cs.rsacomb.suffix.{Forward, Backward, Nth} | 35 | import uk.ac.ox.cs.rsacomb.suffix.{RSASuffix, Forward, Backward, Nth} |
36 | import uk.ac.ox.cs.rsacomb.util.{DataFactory, RSA, RDFoxUtil} | 36 | import 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 | */ |
69 | class RevisedFilteringProgram(val query: ConjunctiveQuery) | 73 | class 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 @@ | |||
17 | package uk.ac.ox.cs.rsacomb.implicits | 17 | package uk.ac.ox.cs.rsacomb.implicits |
18 | 18 | ||
19 | import tech.oxfordsemantic.jrdfox.logic.Datatype | 19 | import tech.oxfordsemantic.jrdfox.logic.Datatype |
20 | import tech.oxfordsemantic.jrdfox.logic.datalog.TupleTableName | ||
20 | import tech.oxfordsemantic.jrdfox.logic.expression.{ | 21 | import 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 | |||
29 | import uk.ac.ox.cs.rsacomb.suffix.{RSASuffix, Nth} | 29 | import uk.ac.ox.cs.rsacomb.suffix.{RSASuffix, Nth} |
30 | import uk.ac.ox.cs.rsacomb.util.{DataFactory, RDFoxUtil} | 30 | import 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 | |||
47 | object RSAAtom { | 32 | object 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 | ||
17 | package uk.ac.ox.cs.rsacomb.suffix | 17 | package uk.ac.ox.cs.rsacomb.suffix |
18 | 18 | ||
19 | import 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 | ||
25 | import tech.oxfordsemantic.jrdfox.logic.expression.{IRI} | 25 | import tech.oxfordsemantic.jrdfox.logic.expression.{IRI, Term} |
26 | import tech.oxfordsemantic.jrdfox.logic.datalog.{TupleTableAtom, TupleTableName} | 26 | import tech.oxfordsemantic.jrdfox.logic.datalog.{TupleTableAtom, TupleTableName} |
27 | 27 | ||
28 | object RSASuffix { | 28 | object 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 | ||
43 | case object Empty extends RSASuffix(identity) | 53 | case 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 = |