diff options
author | Federico Igne <federico.igne@cs.ox.ac.uk> | 2020-12-02 18:52:39 +0000 |
---|---|---|
committer | Federico Igne <federico.igne@cs.ox.ac.uk> | 2020-12-02 18:52:39 +0000 |
commit | d7fa665c289923c362c17ce16cda03588911a817 (patch) | |
tree | 6b027414dba598859c5f27740e7a30799308b38e /src/test/scala/uk/ac | |
parent | 6462d8566cc10b47473803e3e9e9547cec6524be (diff) | |
parent | 91de03f187f298004d90708c5815e86134b10eae (diff) | |
download | RSAComb-d7fa665c289923c362c17ce16cda03588911a817.tar.gz RSAComb-d7fa665c289923c362c17ce16cda03588911a817.zip |
Merge branch 'rdfox-converter' into master
Diffstat (limited to 'src/test/scala/uk/ac')
3 files changed, 192 insertions, 33 deletions
diff --git a/src/test/scala/uk/ac/ox/cs/rsacomb/CanonicalModelSpec.scala b/src/test/scala/uk/ac/ox/cs/rsacomb/CanonicalModelSpec.scala index 3070ce3..0d07923 100644 --- a/src/test/scala/uk/ac/ox/cs/rsacomb/CanonicalModelSpec.scala +++ b/src/test/scala/uk/ac/ox/cs/rsacomb/CanonicalModelSpec.scala | |||
@@ -15,6 +15,8 @@ import tech.oxfordsemantic.jrdfox.logic.expression.Variable | |||
15 | import scala.collection.JavaConverters._ | 15 | import scala.collection.JavaConverters._ |
16 | 16 | ||
17 | import uk.ac.ox.cs.rsacomb.RSAOntology | 17 | import uk.ac.ox.cs.rsacomb.RSAOntology |
18 | import uk.ac.ox.cs.rsacomb.converter.SkolemStrategy | ||
19 | import uk.ac.ox.cs.rsacomb.suffix.Empty | ||
18 | import uk.ac.ox.cs.rsacomb.util.{RDFoxUtil, RSA} | 20 | import uk.ac.ox.cs.rsacomb.util.{RDFoxUtil, RSA} |
19 | 21 | ||
20 | object Ontology1_CanonicalModelSpec { | 22 | object Ontology1_CanonicalModelSpec { |
@@ -28,6 +30,7 @@ object Ontology1_CanonicalModelSpec { | |||
28 | val ontology_path: File = new File("examples/example1.ttl") | 30 | val ontology_path: File = new File("examples/example1.ttl") |
29 | val ontology = RSAOntology(ontology_path) | 31 | val ontology = RSAOntology(ontology_path) |
30 | val program = ontology.canonicalModel | 32 | val program = ontology.canonicalModel |
33 | val converter = program.CanonicalModelConverter | ||
31 | 34 | ||
32 | val roleR = new OWLObjectPropertyImpl(base("R")) | 35 | val roleR = new OWLObjectPropertyImpl(base("R")) |
33 | val roleS = new OWLObjectPropertyImpl(base("S")) | 36 | val roleS = new OWLObjectPropertyImpl(base("S")) |
@@ -89,9 +92,13 @@ class Ontology1_CanonicalModelSpec | |||
89 | } | 92 | } |
90 | 93 | ||
91 | renderer.render(AsubClassOfD) should "be converted into a single Rule" in { | 94 | renderer.render(AsubClassOfD) should "be converted into a single Rule" in { |
92 | val varX = Variable.create("X") | 95 | val term = Variable.create("X") |
93 | val visitor = program.RuleGenerator | 96 | val unsafe = ontology.unsafeRoles |
94 | val rules = AsubClassOfD.accept(visitor) | 97 | val skolem = SkolemStrategy.None |
98 | val suffix = Empty | ||
99 | val (facts, rules) = | ||
100 | converter.convert(AsubClassOfD, term, unsafe, skolem, suffix) | ||
101 | facts shouldBe empty | ||
95 | rules.loneElement shouldBe a[Rule] | 102 | rules.loneElement shouldBe a[Rule] |
96 | } | 103 | } |
97 | 104 | ||
@@ -154,10 +161,14 @@ class Ontology1_CanonicalModelSpec | |||
154 | renderer.render( | 161 | renderer.render( |
155 | AsomeValuesFromSiC | 162 | AsomeValuesFromSiC |
156 | ) should "produce 1 rule" in { | 163 | ) should "produce 1 rule" in { |
157 | val varX = Variable.create("X") | 164 | val term = Variable.create("X") |
158 | val visitor = program.RuleGenerator | 165 | val unsafe = ontology.unsafeRoles |
159 | val rules = AsomeValuesFromSiC.accept(visitor) | 166 | val skolem = SkolemStrategy.None |
160 | rules should have length 1 | 167 | val suffix = Empty |
168 | val (facts, rules) = | ||
169 | converter.convert(AsomeValuesFromSiC, term, unsafe, skolem, suffix) | ||
170 | facts shouldBe empty | ||
171 | rules.loneElement shouldBe a[Rule] | ||
161 | } | 172 | } |
162 | 173 | ||
163 | renderer.render( | 174 | renderer.render( |
@@ -172,15 +183,18 @@ class Ontology1_CanonicalModelSpec | |||
172 | ontology.cycle(DsomeValuesFromRB) should have size 48 | 183 | ontology.cycle(DsomeValuesFromRB) should have size 48 |
173 | } | 184 | } |
174 | 185 | ||
175 | it should "produce 5 rules" in { | 186 | it should "produce 48 facts and 98 rules" in { |
176 | // Rule 1 provides 1 rule (split in 2) + 48 fact | 187 | // Rule 1 provides 1 rule (split in 2) + 48 fact |
177 | // Rule 2 provides 0 rules | 188 | // Rule 2 provides 0 rules |
178 | // Rule 3 provides 48 rule (split in 2) | 189 | // Rule 3 provides 48 rule (split in 2) |
179 | // Then (1*2 + 48) + (0) + (48*2) = 146 | 190 | val term = Variable.create("X") |
180 | val varX = Variable.create("X") | 191 | val unsafe = ontology.unsafeRoles |
181 | val visitor = program.RuleGenerator | 192 | val skolem = SkolemStrategy.None |
182 | val rules = DsomeValuesFromRB.accept(visitor) | 193 | val suffix = Empty |
183 | rules should have length 146 | 194 | val (facts, rules) = |
195 | converter.convert(DsomeValuesFromRB, term, unsafe, skolem, suffix) | ||
196 | facts should have length 48 | ||
197 | rules should have length 98 | ||
184 | } | 198 | } |
185 | 199 | ||
186 | renderer.render( | 200 | renderer.render( |
@@ -200,18 +214,26 @@ class Ontology1_CanonicalModelSpec | |||
200 | // Rule 2 provides 0 rules | 214 | // Rule 2 provides 0 rules |
201 | // Rule 3 provides 32 rule (split in 2) | 215 | // Rule 3 provides 32 rule (split in 2) |
202 | // Then (1*2 + 32) + (0) + (32*2) = 98 | 216 | // Then (1*2 + 32) + (0) + (32*2) = 98 |
203 | val varX = Variable.create("X") | 217 | val term = Variable.create("X") |
204 | val visitor = program.RuleGenerator | 218 | val unsafe = ontology.unsafeRoles |
205 | val rules = DsomeValuesFromRB.accept(visitor) | 219 | val skolem = SkolemStrategy.None |
206 | rules should have length 146 | 220 | val suffix = Empty |
221 | val (facts, rules) = | ||
222 | converter.convert(BsomeValuesFromSD, term, unsafe, skolem, suffix) | ||
223 | facts should have length 32 | ||
224 | rules should have length 66 | ||
207 | } | 225 | } |
208 | 226 | ||
209 | renderer.render( | 227 | renderer.render( |
210 | SsubPropertyOfT | 228 | SsubPropertyOfT |
211 | ) should "produce 2 rules" in { | 229 | ) should "produce 2 rules" in { |
212 | val varX = Variable.create("X") | 230 | val term = Variable.create("X") |
213 | val visitor = program.RuleGenerator | 231 | val unsafe = ontology.unsafeRoles |
214 | val rules = SsubPropertyOfT.accept(visitor) | 232 | val skolem = SkolemStrategy.None |
233 | val suffix = Empty | ||
234 | val (facts, rules) = | ||
235 | converter.convert(SsubPropertyOfT, term, unsafe, skolem, suffix) | ||
236 | facts shouldBe empty | ||
215 | rules should have length 2 | 237 | rules should have length 2 |
216 | } | 238 | } |
217 | 239 | ||
@@ -228,6 +250,7 @@ object Ontology2_CanonicalModelSpec { | |||
228 | val ontology_path: File = new File("examples/example2.owl") | 250 | val ontology_path: File = new File("examples/example2.owl") |
229 | val ontology = RSAOntology(ontology_path) | 251 | val ontology = RSAOntology(ontology_path) |
230 | val program = ontology.canonicalModel | 252 | val program = ontology.canonicalModel |
253 | val converter = program.CanonicalModelConverter | ||
231 | 254 | ||
232 | val roleR = new OWLObjectPropertyImpl(base("R")) | 255 | val roleR = new OWLObjectPropertyImpl(base("R")) |
233 | val roleS = new OWLObjectPropertyImpl(base("S")) | 256 | val roleS = new OWLObjectPropertyImpl(base("S")) |
@@ -332,8 +355,13 @@ class Ontology2_CanonicalModelSpec | |||
332 | renderer.render( | 355 | renderer.render( |
333 | AsomeValuesFromRB | 356 | AsomeValuesFromRB |
334 | ) should "produce 1 rule" in { | 357 | ) should "produce 1 rule" in { |
335 | val visitor = program.RuleGenerator | 358 | val term = Variable.create("X") |
336 | val rules = AsomeValuesFromRB.accept(visitor) | 359 | val unsafe = ontology.unsafeRoles |
360 | val skolem = SkolemStrategy.None | ||
361 | val suffix = Empty | ||
362 | val (facts, rules) = | ||
363 | converter.convert(AsomeValuesFromRB, term, unsafe, skolem, suffix) | ||
364 | facts shouldBe empty | ||
337 | rules should have length 1 | 365 | rules should have length 1 |
338 | } | 366 | } |
339 | 367 | ||
@@ -342,8 +370,13 @@ class Ontology2_CanonicalModelSpec | |||
342 | renderer.render( | 370 | renderer.render( |
343 | BsomeValuesFromSC | 371 | BsomeValuesFromSC |
344 | ) should "produce 1 rule" in { | 372 | ) should "produce 1 rule" in { |
345 | val visitor = program.RuleGenerator | 373 | val term = Variable.create("X") |
346 | val rules = BsomeValuesFromSC.accept(visitor) | 374 | val unsafe = ontology.unsafeRoles |
375 | val skolem = SkolemStrategy.None | ||
376 | val suffix = Empty | ||
377 | val (facts, rules) = | ||
378 | converter.convert(BsomeValuesFromSC, term, unsafe, skolem, suffix) | ||
379 | facts shouldBe empty | ||
347 | rules should have length 1 | 380 | rules should have length 1 |
348 | } | 381 | } |
349 | 382 | ||
@@ -352,8 +385,13 @@ class Ontology2_CanonicalModelSpec | |||
352 | renderer.render( | 385 | renderer.render( |
353 | CsomeValuesFromTD | 386 | CsomeValuesFromTD |
354 | ) should "produce 1 rule" in { | 387 | ) should "produce 1 rule" in { |
355 | val visitor = program.RuleGenerator | 388 | val term = Variable.create("X") |
356 | val rules = CsomeValuesFromTD.accept(visitor) | 389 | val unsafe = ontology.unsafeRoles |
390 | val skolem = SkolemStrategy.None | ||
391 | val suffix = Empty | ||
392 | val (facts, rules) = | ||
393 | converter.convert(CsomeValuesFromTD, term, unsafe, skolem, suffix) | ||
394 | facts shouldBe empty | ||
357 | rules should have length 1 | 395 | rules should have length 1 |
358 | } | 396 | } |
359 | 397 | ||
@@ -362,8 +400,13 @@ class Ontology2_CanonicalModelSpec | |||
362 | renderer.render( | 400 | renderer.render( |
363 | DsomeValuesFromPA | 401 | DsomeValuesFromPA |
364 | ) should "produce 1 rule" in { | 402 | ) should "produce 1 rule" in { |
365 | val visitor = program.RuleGenerator | 403 | val term = Variable.create("X") |
366 | val rules = DsomeValuesFromPA.accept(visitor) | 404 | val unsafe = ontology.unsafeRoles |
405 | val skolem = SkolemStrategy.None | ||
406 | val suffix = Empty | ||
407 | val (facts, rules) = | ||
408 | converter.convert(DsomeValuesFromPA, term, unsafe, skolem, suffix) | ||
409 | facts shouldBe empty | ||
367 | rules should have length 1 | 410 | rules should have length 1 |
368 | } | 411 | } |
369 | 412 | ||
diff --git a/src/test/scala/uk/ac/ox/cs/rsacomb/FilteringProgramSpecs.scala b/src/test/scala/uk/ac/ox/cs/rsacomb/FilteringProgramSpecs.scala index 71c9a99..86e0253 100644 --- a/src/test/scala/uk/ac/ox/cs/rsacomb/FilteringProgramSpecs.scala +++ b/src/test/scala/uk/ac/ox/cs/rsacomb/FilteringProgramSpecs.scala | |||
@@ -65,24 +65,32 @@ class FilteringProgramSpec extends AnyFlatSpec with Matchers { | |||
65 | 65 | ||
66 | import FilteringProgramSpec._ | 66 | import FilteringProgramSpec._ |
67 | 67 | ||
68 | "CQ 0" should "generate 30 rules" in { | 68 | "CQ 0" should "generate 27 rules and 3 facts" in { |
69 | val cq = ConjunctiveQuery(cq0).get | 69 | val cq = ConjunctiveQuery(cq0).get |
70 | FilteringProgram(cq, constants).rules should have length 30 | 70 | val filter = FilteringProgram(cq, constants) |
71 | filter.facts should have length 3 | ||
72 | filter.rules should have length 27 | ||
71 | } | 73 | } |
72 | 74 | ||
73 | "CQ 1" should "generate 15 rules" in { | 75 | "CQ 1" should "generate 15 rules" in { |
74 | val cq = ConjunctiveQuery(cq1).get | 76 | val cq = ConjunctiveQuery(cq1).get |
75 | FilteringProgram(cq, List()).rules should have length 15 | 77 | val filter = FilteringProgram(cq, List()) |
78 | filter.facts shouldBe empty | ||
79 | filter.rules should have length 15 | ||
76 | } | 80 | } |
77 | 81 | ||
78 | "CQ 2" should "generate 51 rules" in { | 82 | "CQ 2" should "generate 51 rules" in { |
79 | val cq = ConjunctiveQuery(cq2).get | 83 | val cq = ConjunctiveQuery(cq2).get |
80 | FilteringProgram(cq, List()).rules should have length 51 | 84 | val filter = FilteringProgram(cq, List()) |
85 | filter.facts shouldBe empty | ||
86 | filter.rules should have length 51 | ||
81 | } | 87 | } |
82 | 88 | ||
83 | "BCQ 0" should "generate 46 rules" in { | 89 | "BCQ 0" should "generate 46 rules" in { |
84 | val cq = ConjunctiveQuery(bcq0).get | 90 | val cq = ConjunctiveQuery(bcq0).get |
85 | FilteringProgram(cq, constants).rules should have length 46 | 91 | val filter = FilteringProgram(cq, constants) |
92 | filter.facts should have length 3 | ||
93 | filter.rules should have length 43 | ||
86 | } | 94 | } |
87 | 95 | ||
88 | } | 96 | } |
diff --git a/src/test/scala/uk/ac/ox/cs/rsacomb/RDFoxConverterSpec.scala b/src/test/scala/uk/ac/ox/cs/rsacomb/RDFoxConverterSpec.scala new file mode 100644 index 0000000..e2da6e4 --- /dev/null +++ b/src/test/scala/uk/ac/ox/cs/rsacomb/RDFoxConverterSpec.scala | |||
@@ -0,0 +1,108 @@ | |||
1 | package rsacomb | ||
2 | |||
3 | import org.scalatest.LoneElement | ||
4 | import org.scalatest.flatspec.AnyFlatSpec | ||
5 | import org.scalatest.matchers.should.Matchers | ||
6 | import org.semanticweb.owlapi.apibinding.OWLManager | ||
7 | import org.semanticweb.owlapi.model.OWLOntologyManager | ||
8 | |||
9 | import tech.oxfordsemantic.jrdfox.logic.datalog.TupleTableAtom | ||
10 | import tech.oxfordsemantic.jrdfox.logic.expression.{Variable, IRI} | ||
11 | import uk.ac.ox.cs.rsacomb.converter.RDFoxConverter | ||
12 | import uk.ac.ox.cs.rsacomb.suffix.{Empty, Forward, Backward, Inverse} | ||
13 | import uk.ac.ox.cs.rsacomb.converter.SkolemStrategy | ||
14 | |||
15 | object RDFoxConverterSpec { | ||
16 | |||
17 | val manager = OWLManager.createOWLOntologyManager() | ||
18 | val factory = manager.getOWLDataFactory | ||
19 | |||
20 | val term0 = Variable.create("X") | ||
21 | val term1 = Variable.create("Y") | ||
22 | val iriString0 = "http://example.com/rsacomb/iri0" | ||
23 | val iriString1 = "http://example.com/rsacomb/iri1" | ||
24 | val iriString2 = "http://example.com/rsacomb/iri2" | ||
25 | val suffixes = Seq( | ||
26 | Empty, | ||
27 | Forward, | ||
28 | Backward, | ||
29 | Inverse, | ||
30 | Forward + Inverse, | ||
31 | Backward + Inverse | ||
32 | ) | ||
33 | } | ||
34 | |||
35 | class RDFoxConverterSpec | ||
36 | extends AnyFlatSpec | ||
37 | with Matchers | ||
38 | with LoneElement | ||
39 | with RDFoxConverter { | ||
40 | |||
41 | import RDFoxConverterSpec._ | ||
42 | |||
43 | "A class name" should "be converted into a single atom" in { | ||
44 | val cls = factory.getOWLClass(iriString0) | ||
45 | val atom = TupleTableAtom.rdf(term0, IRI.RDF_TYPE, IRI.create(iriString0)) | ||
46 | val (res, ext) = | ||
47 | convert(cls, term0, List(), SkolemStrategy.None, Empty) | ||
48 | res.loneElement shouldEqual atom | ||
49 | ext shouldBe empty | ||
50 | } | ||
51 | |||
52 | "A intersection of classes" should "be converted into the union of the conversion of the classes" in { | ||
53 | val cls0 = factory.getOWLClass(iriString0) | ||
54 | val cls1 = factory.getOWLClass(iriString1) | ||
55 | val cls2 = factory.getOWLClass(iriString2) | ||
56 | val conj = factory.getOWLObjectIntersectionOf(cls0, cls1, cls2) | ||
57 | val (res0, ext0) = | ||
58 | convert(cls0, term0, List(), SkolemStrategy.None, Empty) | ||
59 | val (res1, ext1) = | ||
60 | convert(cls1, term0, List(), SkolemStrategy.None, Empty) | ||
61 | val (res2, ext2) = | ||
62 | convert(cls2, term0, List(), SkolemStrategy.None, Empty) | ||
63 | val (res, ext) = | ||
64 | convert(conj, term0, List(), SkolemStrategy.None, Empty) | ||
65 | res should contain theSameElementsAs (res0 ::: res1 ::: res2) | ||
66 | ext should contain theSameElementsAs (ext0 ::: ext1 ::: ext2) | ||
67 | } | ||
68 | |||
69 | "A singleton intersection" should "correspond to the conversion of the internal class" in { | ||
70 | val cls0 = factory.getOWLClass(iriString0) | ||
71 | val conj = factory.getOWLObjectIntersectionOf(cls0) | ||
72 | val (res0, ext0) = | ||
73 | convert(cls0, term0, List(), SkolemStrategy.None, Empty) | ||
74 | val (res, ext) = | ||
75 | convert(conj, term0, List(), SkolemStrategy.None, Empty) | ||
76 | res should contain theSameElementsAs res0 | ||
77 | ext should contain theSameElementsAs ext0 | ||
78 | } | ||
79 | |||
80 | "An object property" should "be converted into an atom with matching predicate" in { | ||
81 | val prop = factory.getOWLObjectProperty(iriString0) | ||
82 | for (sx <- suffixes) { | ||
83 | val atom = | ||
84 | TupleTableAtom.rdf(term0, IRI.create(iriString0 :: sx), term1) | ||
85 | convert(prop, term0, term1, sx) shouldEqual atom | ||
86 | } | ||
87 | } | ||
88 | |||
89 | "The inverse of an object property" should "be converted into an atom with matching negated predicate" in { | ||
90 | val prop = factory.getOWLObjectProperty(iriString0) | ||
91 | val inv = factory.getOWLObjectInverseOf(prop) | ||
92 | for (sx <- Seq(Empty, Forward, Backward)) { | ||
93 | val atom = | ||
94 | TupleTableAtom.rdf(term0, IRI.create(iriString0 :: sx + Inverse), term1) | ||
95 | convert(inv, term0, term1, sx) shouldEqual atom | ||
96 | } | ||
97 | } | ||
98 | |||
99 | "A data property" should "be converted into an atom with matching predicate" in { | ||
100 | val prop = factory.getOWLDataProperty(iriString0) | ||
101 | for (suffix <- suffixes) { | ||
102 | val atom = | ||
103 | TupleTableAtom.rdf(term0, IRI.create(iriString0 :: suffix), term1) | ||
104 | convert(prop, term0, term1, suffix) shouldEqual atom | ||
105 | } | ||
106 | } | ||
107 | |||
108 | } | ||