diff options
| author | Federico Igne <git@federicoigne.com> | 2021-08-06 13:31:54 +0100 |
|---|---|---|
| committer | Federico Igne <git@federicoigne.com> | 2021-08-06 13:31:54 +0100 |
| commit | 75eb39dd0fd31c295b9ed9a6d3b0fd3b25611b2a (patch) | |
| tree | 885cb3a76a5bdcbb685ac697e297ea8d91eb2ed8 | |
| parent | 19c22a38ccaf1685e345a18883ffbac891f97df3 (diff) | |
| download | RSAComb-75eb39dd0fd31c295b9ed9a6d3b0fd3b25611b2a.tar.gz RSAComb-75eb39dd0fd31c295b9ed9a6d3b0fd3b25611b2a.zip | |
Add new fresh data factory
This will help write more significant test.
14 files changed, 455 insertions, 376 deletions
diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/CanonicalModel.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/CanonicalModel.scala index ca54054..3467d3c 100644 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/CanonicalModel.scala +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/CanonicalModel.scala | |||
| @@ -39,7 +39,7 @@ import implicits.JavaCollections._ | |||
| 39 | 39 | ||
| 40 | import uk.ac.ox.cs.rsacomb.converter._ | 40 | import uk.ac.ox.cs.rsacomb.converter._ |
| 41 | import uk.ac.ox.cs.rsacomb.suffix._ | 41 | import uk.ac.ox.cs.rsacomb.suffix._ |
| 42 | import uk.ac.ox.cs.rsacomb.util.RSA | 42 | import uk.ac.ox.cs.rsacomb.util.{DataFactory, RSA} |
| 43 | 43 | ||
| 44 | /** Canonical model generator | 44 | /** Canonical model generator |
| 45 | * | 45 | * |
| @@ -92,7 +92,7 @@ class CanonicalModel(val ontology: RSAOntology) { | |||
| 92 | val (facts, rules): (List[TupleTableAtom], List[Rule]) = { | 92 | val (facts, rules): (List[TupleTableAtom], List[Rule]) = { |
| 93 | // Compute rules from ontology axioms | 93 | // Compute rules from ontology axioms |
| 94 | val (facts, rules) = { | 94 | val (facts, rules) = { |
| 95 | val term = RSAUtil.genFreshVariable() | 95 | val term = Variable.create("X") |
| 96 | val unsafe = ontology.unsafe | 96 | val unsafe = ontology.unsafe |
| 97 | ontology.axioms | 97 | ontology.axioms |
| 98 | .map(a => | 98 | .map(a => |
| @@ -216,13 +216,13 @@ class CanonicalModel(val ontology: RSAOntology) { | |||
| 216 | unsafe: List[OWLObjectPropertyExpression], | 216 | unsafe: List[OWLObjectPropertyExpression], |
| 217 | skolem: SkolemStrategy, | 217 | skolem: SkolemStrategy, |
| 218 | suffix: RSASuffix | 218 | suffix: RSASuffix |
| 219 | ): Result = | 219 | )(implicit fresh: DataFactory): Result = |
| 220 | axiom match { | 220 | axiom match { |
| 221 | 221 | ||
| 222 | case a: OWLSubClassOfAxiom if a.isT5 => { | 222 | case a: OWLSubClassOfAxiom if a.isT5 => { |
| 223 | val role = axiom.objectPropertyExpressionsInSignature(0) | 223 | val role = axiom.objectPropertyExpressionsInSignature(0) |
| 224 | if (unsafe contains role) | 224 | if (unsafe contains role) |
| 225 | super.convert(a, term, unsafe, new Standard(a), Forward) | 225 | super.convert(a, term, unsafe, new Standard(a), Forward)(fresh) |
| 226 | else { | 226 | else { |
| 227 | val (f1, r1) = rules1(a) | 227 | val (f1, r1) = rules1(a) |
| 228 | (f1, r1 ::: rules2(a) ::: rules3(a)) | 228 | (f1, r1 ::: rules2(a) ::: rules3(a)) |
| @@ -231,12 +231,12 @@ class CanonicalModel(val ontology: RSAOntology) { | |||
| 231 | 231 | ||
| 232 | case a: OWLSubObjectPropertyOfAxiom => { | 232 | case a: OWLSubObjectPropertyOfAxiom => { |
| 233 | val (facts, rules) = List(Empty, Forward, Backward) | 233 | val (facts, rules) = List(Empty, Forward, Backward) |
| 234 | .map(super.convert(a, term, unsafe, NoSkolem, _)) | 234 | .map(super.convert(a, term, unsafe, NoSkolem, _)(fresh)) |
| 235 | .unzip | 235 | .unzip |
| 236 | (facts.flatten, rules.flatten) | 236 | (facts.flatten, rules.flatten) |
| 237 | } | 237 | } |
| 238 | 238 | ||
| 239 | case a => super.convert(a, term, unsafe, skolem, suffix) | 239 | case a => super.convert(a, term, unsafe, skolem, suffix)(fresh) |
| 240 | 240 | ||
| 241 | } | 241 | } |
| 242 | } | 242 | } |
diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala index 4c63e17..a1fd20f 100644 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/Main.scala | |||
| @@ -28,7 +28,7 @@ import sparql.ConjunctiveQuery | |||
| 28 | 28 | ||
| 29 | import uk.ac.ox.cs.rsacomb.ontology.Ontology | 29 | import uk.ac.ox.cs.rsacomb.ontology.Ontology |
| 30 | import uk.ac.ox.cs.rsacomb.converter.Normalizer | 30 | import uk.ac.ox.cs.rsacomb.converter.Normalizer |
| 31 | import uk.ac.ox.cs.rsacomb.approximation.Lowerbound | 31 | import uk.ac.ox.cs.rsacomb.approximation.{Upperbound, Lowerbound} |
| 32 | 32 | ||
| 33 | case class RSAOption[+T](opt: T) { | 33 | case class RSAOption[+T](opt: T) { |
| 34 | def get[T]: T = opt.asInstanceOf[T] | 34 | def get[T]: T = opt.asInstanceOf[T] |
| @@ -133,7 +133,7 @@ object RSAComb extends App { | |||
| 133 | ).normalize(new Normalizer) | 133 | ).normalize(new Normalizer) |
| 134 | 134 | ||
| 135 | /* Approximate the ontology to RSA */ | 135 | /* Approximate the ontology to RSA */ |
| 136 | val toRSA = new Lowerbound | 136 | val toRSA = new Upperbound |
| 137 | val rsa = ontology approximate toRSA | 137 | val rsa = ontology approximate toRSA |
| 138 | 138 | ||
| 139 | if (config contains 'query) { | 139 | if (config contains 'query) { |
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 30e1305..869dd88 100644 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/RSAOntology.scala +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/RSAOntology.scala | |||
| @@ -81,30 +81,6 @@ import uk.ac.ox.cs.rsacomb.util.{RDFoxUtil, RSA} | |||
| 81 | import uk.ac.ox.cs.rsacomb.util.Logger | 81 | import uk.ac.ox.cs.rsacomb.util.Logger |
| 82 | import uk.ac.ox.cs.rsacomb.ontology.Ontology | 82 | import uk.ac.ox.cs.rsacomb.ontology.Ontology |
| 83 | 83 | ||
| 84 | object RSAUtil { | ||
| 85 | |||
| 86 | // implicit def axiomsToOntology(axioms: Seq[OWLAxiom]) = { | ||
| 87 | // val manager = OWLManager.createOWLOntologyManager() | ||
| 88 | // manager.createOntology(axioms.asJava) | ||
| 89 | // } | ||
| 90 | |||
| 91 | /** Manager instance to interface with OWLAPI */ | ||
| 92 | val manager = OWLManager.createOWLOntologyManager() | ||
| 93 | val factory = manager.getOWLDataFactory() | ||
| 94 | |||
| 95 | /** Simple fresh variable/class generator */ | ||
| 96 | private var counter = -1; | ||
| 97 | def genFreshVariable(): Variable = { | ||
| 98 | counter += 1 | ||
| 99 | Variable.create(f"I$counter%05d") | ||
| 100 | } | ||
| 101 | def getFreshOWLClass(): OWLClass = { | ||
| 102 | counter += 1 | ||
| 103 | factory.getOWLClass(s"X$counter") | ||
| 104 | } | ||
| 105 | |||
| 106 | } | ||
| 107 | |||
| 108 | object RSAOntology { | 84 | object RSAOntology { |
| 109 | 85 | ||
| 110 | import uk.ac.ox.cs.rsacomb.implicits.JavaCollections._ | 86 | import uk.ac.ox.cs.rsacomb.implicits.JavaCollections._ |
diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Lowerbound.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Lowerbound.scala index 290cbaf..88732d5 100644 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Lowerbound.scala +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Lowerbound.scala | |||
| @@ -13,8 +13,8 @@ import scalax.collection.GraphPredef._, scalax.collection.GraphEdge._ | |||
| 13 | import scalax.collection.GraphTraversal._ | 13 | import scalax.collection.GraphTraversal._ |
| 14 | 14 | ||
| 15 | import uk.ac.ox.cs.rsacomb.RSAOntology | 15 | import uk.ac.ox.cs.rsacomb.RSAOntology |
| 16 | import uk.ac.ox.cs.rsacomb.RSAUtil | ||
| 17 | import uk.ac.ox.cs.rsacomb.ontology.Ontology | 16 | import uk.ac.ox.cs.rsacomb.ontology.Ontology |
| 17 | import uk.ac.ox.cs.rsacomb.util.DataFactory | ||
| 18 | 18 | ||
| 19 | object Lowerbound { | 19 | object Lowerbound { |
| 20 | 20 | ||
| @@ -38,7 +38,8 @@ object Lowerbound { | |||
| 38 | * | 38 | * |
| 39 | * @see [[uk.ac.ox.cs.rsacomb.converter.Normalizer]] | 39 | * @see [[uk.ac.ox.cs.rsacomb.converter.Normalizer]] |
| 40 | */ | 40 | */ |
| 41 | class Lowerbound extends Approximation[RSAOntology] { | 41 | class Lowerbound(implicit fresh: DataFactory) |
| 42 | extends Approximation[RSAOntology] { | ||
| 42 | 43 | ||
| 43 | /** Simplify conversion between Java and Scala collections */ | 44 | /** Simplify conversion between Java and Scala collections */ |
| 44 | import uk.ac.ox.cs.rsacomb.implicits.JavaCollections._ | 45 | import uk.ac.ox.cs.rsacomb.implicits.JavaCollections._ |
| @@ -122,12 +123,10 @@ class Lowerbound extends Approximation[RSAOntology] { | |||
| 122 | val sup = a.getSuperClass.getNNF | 123 | val sup = a.getSuperClass.getNNF |
| 123 | sup match { | 124 | sup match { |
| 124 | case sup: OWLObjectUnionOf => { | 125 | case sup: OWLObjectUnionOf => { |
| 125 | val body = sub.asConjunctSet.map((atom) => | 126 | val body = |
| 126 | (atom, RSAUtil.getFreshOWLClass()) | 127 | sub.asConjunctSet.map((atom) => (atom, fresh.getOWLClass)) |
| 127 | ) | 128 | val head = |
| 128 | val head = sup.asDisjunctSet.map((atom) => | 129 | sup.asDisjunctSet.map((atom) => (atom, fresh.getOWLClass)) |
| 129 | (atom, RSAUtil.getFreshOWLClass()) | ||
| 130 | ) | ||
| 131 | 130 | ||
| 132 | val r1 = | 131 | val r1 = |
| 133 | Lowerbound.factory.getOWLSubClassOfAxiom( | 132 | Lowerbound.factory.getOWLSubClassOfAxiom( |
diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Upperbound.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Upperbound.scala index ad924aa..1ae7941 100644 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Upperbound.scala +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Upperbound.scala | |||
| @@ -13,8 +13,8 @@ import scalax.collection.GraphPredef._, scalax.collection.GraphEdge._ | |||
| 13 | import scalax.collection.GraphTraversal._ | 13 | import scalax.collection.GraphTraversal._ |
| 14 | 14 | ||
| 15 | import uk.ac.ox.cs.rsacomb.RSAOntology | 15 | import uk.ac.ox.cs.rsacomb.RSAOntology |
| 16 | import uk.ac.ox.cs.rsacomb.RSAUtil | ||
| 17 | import uk.ac.ox.cs.rsacomb.ontology.Ontology | 16 | import uk.ac.ox.cs.rsacomb.ontology.Ontology |
| 17 | import uk.ac.ox.cs.rsacomb.util.DataFactory | ||
| 18 | 18 | ||
| 19 | object Upperbound { | 19 | object Upperbound { |
| 20 | 20 | ||
| @@ -38,7 +38,8 @@ object Upperbound { | |||
| 38 | * | 38 | * |
| 39 | * @see [[uk.ac.ox.cs.rsacomb.converter.Normalizer]] | 39 | * @see [[uk.ac.ox.cs.rsacomb.converter.Normalizer]] |
| 40 | */ | 40 | */ |
| 41 | class Upperbound extends Approximation[RSAOntology] { | 41 | class Upperbound(implicit fresh: DataFactory) |
| 42 | extends Approximation[RSAOntology] { | ||
| 42 | 43 | ||
| 43 | /** Simplify conversion between Java and Scala collections */ | 44 | /** Simplify conversion between Java and Scala collections */ |
| 44 | import uk.ac.ox.cs.rsacomb.implicits.JavaCollections._ | 45 | import uk.ac.ox.cs.rsacomb.implicits.JavaCollections._ |
| @@ -138,15 +139,17 @@ class Upperbound extends Approximation[RSAOntology] { | |||
| 138 | import uk.ac.ox.cs.rsacomb.implicits.RSAAxiom._ | 139 | import uk.ac.ox.cs.rsacomb.implicits.RSAAxiom._ |
| 139 | axiom.toTriple match { | 140 | axiom.toTriple match { |
| 140 | case Some((subclass, role, filler)) => { | 141 | case Some((subclass, role, filler)) => { |
| 141 | val skolem = Upperbound.factory.getOWLNamedIndividual(s"i_${axiom.toString.hashCode}") | 142 | val skolem = Upperbound.factory.getOWLNamedIndividual( |
| 142 | val fresh = RSAUtil.getFreshOWLClass() | 143 | s"i_${axiom.toString.hashCode}" |
| 144 | ) | ||
| 145 | val cls = fresh.getOWLClass | ||
| 143 | List( | 146 | List( |
| 144 | Upperbound.factory.getOWLSubClassOfAxiom( | 147 | Upperbound.factory.getOWLSubClassOfAxiom( |
| 145 | subclass, | 148 | subclass, |
| 146 | Upperbound.factory.getOWLObjectSomeValuesFrom(role, fresh) | 149 | Upperbound.factory.getOWLObjectSomeValuesFrom(role, cls) |
| 147 | ), | 150 | ), |
| 148 | Upperbound.factory.getOWLSubClassOfAxiom( | 151 | Upperbound.factory.getOWLSubClassOfAxiom( |
| 149 | fresh, | 152 | cls, |
| 150 | Upperbound.factory.getOWLObjectOneOf(skolem) | 153 | Upperbound.factory.getOWLObjectOneOf(skolem) |
| 151 | ), | 154 | ), |
| 152 | Upperbound.factory.getOWLClassAssertionAxiom(filler, skolem) | 155 | Upperbound.factory.getOWLClassAssertionAxiom(filler, skolem) |
| @@ -169,5 +172,5 @@ class Upperbound extends Approximation[RSAOntology] { | |||
| 169 | // val edges2 = Seq('I ~> 'M, 'I ~> 'L, 'L ~> 'N, 'M ~> 'N) | 172 | // val edges2 = Seq('I ~> 'M, 'I ~> 'L, 'L ~> 'N, 'M ~> 'N) |
| 170 | // val edges3 = Seq('P ~> 'O) | 173 | // val edges3 = Seq('P ~> 'O) |
| 171 | // val graph = Graph.from(edges = edges1 ++ edges2 ++ edges3) | 174 | // val graph = Graph.from(edges = edges1 ++ edges2 ++ edges3) |
| 172 | 175 | ||
| 173 | } | 176 | } |
diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/converter/Normalizer.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/converter/Normalizer.scala index b5da3cc..c24f99d 100644 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/converter/Normalizer.scala +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/converter/Normalizer.scala | |||
| @@ -19,9 +19,8 @@ package uk.ac.ox.cs.rsacomb.converter | |||
| 19 | import org.semanticweb.owlapi.apibinding.OWLManager | 19 | import org.semanticweb.owlapi.apibinding.OWLManager |
| 20 | import org.semanticweb.owlapi.model._ | 20 | import org.semanticweb.owlapi.model._ |
| 21 | 21 | ||
| 22 | import uk.ac.ox.cs.rsacomb.util.Logger | 22 | import uk.ac.ox.cs.rsacomb.util.{Logger, DataFactory} |
| 23 | import uk.ac.ox.cs.rsacomb.RSAOntology | 23 | import uk.ac.ox.cs.rsacomb.RSAOntology |
| 24 | import uk.ac.ox.cs.rsacomb.RSAUtil | ||
| 25 | 24 | ||
| 26 | object Normalizer { | 25 | object Normalizer { |
| 27 | 26 | ||
| @@ -45,7 +44,9 @@ class Normalizer() { | |||
| 45 | 44 | ||
| 46 | /** Normalizes a [[OWLLogicalAxiom]] | 45 | /** Normalizes a [[OWLLogicalAxiom]] |
| 47 | */ | 46 | */ |
| 48 | def normalize(axiom: OWLLogicalAxiom): Seq[OWLLogicalAxiom] = | 47 | def normalize( |
| 48 | axiom: OWLLogicalAxiom | ||
| 49 | )(implicit fresh: DataFactory): Seq[OWLLogicalAxiom] = | ||
| 49 | axiom match { | 50 | axiom match { |
| 50 | case a: OWLSubClassOfAxiom => { | 51 | case a: OWLSubClassOfAxiom => { |
| 51 | val sub = a.getSubClass.getNNF | 52 | val sub = a.getSubClass.getNNF |
| @@ -56,11 +57,11 @@ class Normalizer() { | |||
| 56 | * C c D -> { C c X, X c D } | 57 | * C c D -> { C c X, X c D } |
| 57 | */ | 58 | */ |
| 58 | case _ if !sub.isOWLClass && !sup.isOWLClass => { | 59 | case _ if !sub.isOWLClass && !sup.isOWLClass => { |
| 59 | val cls = RSAUtil.getFreshOWLClass() | 60 | val cls = fresh.getOWLClass |
| 60 | Seq( | 61 | Seq( |
| 61 | factory.getOWLSubClassOfAxiom(sub, cls), | 62 | factory.getOWLSubClassOfAxiom(sub, cls), |
| 62 | factory.getOWLSubClassOfAxiom(cls, sup) | 63 | factory.getOWLSubClassOfAxiom(cls, sup) |
| 63 | ).flatMap(normalize) | 64 | ).flatMap(normalize(_)(fresh)) |
| 64 | } | 65 | } |
| 65 | /** Conjunction on the lhs | 66 | /** Conjunction on the lhs |
| 66 | * | 67 | * |
| @@ -77,7 +78,7 @@ class Normalizer() { | |||
| 77 | if (conj.isOWLClass) | 78 | if (conj.isOWLClass) |
| 78 | (acc1 :+ conj, acc2) | 79 | (acc1 :+ conj, acc2) |
| 79 | else { | 80 | else { |
| 80 | val cls = RSAUtil.getFreshOWLClass() | 81 | val cls = fresh.getOWLClass |
| 81 | ( | 82 | ( |
| 82 | acc1 :+ cls, | 83 | acc1 :+ cls, |
| 83 | acc2 :+ factory.getOWLSubClassOfAxiom(conj, cls) | 84 | acc2 :+ factory.getOWLSubClassOfAxiom(conj, cls) |
| @@ -89,9 +90,11 @@ class Normalizer() { | |||
| 89 | factory.getOWLObjectIntersectionOf(acc1: _*), | 90 | factory.getOWLObjectIntersectionOf(acc1: _*), |
| 90 | sup | 91 | sup |
| 91 | )) | 92 | )) |
| 92 | .flatMap(normalize) | 93 | .flatMap(normalize(_)(fresh)) |
| 93 | } else { | 94 | } else { |
| 94 | normalize(factory.getOWLSubClassOfAxiom(factory.getOWLThing, sup)) | 95 | normalize( |
| 96 | factory.getOWLSubClassOfAxiom(factory.getOWLThing, sup) | ||
| 97 | )(fresh) | ||
| 95 | } | 98 | } |
| 96 | } | 99 | } |
| 97 | /** Conjunction on the rhs | 100 | /** Conjunction on the rhs |
| @@ -103,9 +106,11 @@ class Normalizer() { | |||
| 103 | if (conjuncts.length > 0) { | 106 | if (conjuncts.length > 0) { |
| 104 | conjuncts | 107 | conjuncts |
| 105 | .map(cls => factory.getOWLSubClassOfAxiom(sub, cls)) | 108 | .map(cls => factory.getOWLSubClassOfAxiom(sub, cls)) |
| 106 | .flatMap(normalize) | 109 | .flatMap(normalize(_)(fresh)) |
| 107 | } else { | 110 | } else { |
| 108 | normalize(factory.getOWLSubClassOfAxiom(sub, factory.getOWLThing)) | 111 | normalize( |
| 112 | factory.getOWLSubClassOfAxiom(sub, factory.getOWLThing) | ||
| 113 | )(fresh) | ||
| 109 | } | 114 | } |
| 110 | } | 115 | } |
| 111 | /** Disjunction on the lhs | 116 | /** Disjunction on the lhs |
| @@ -117,11 +122,11 @@ class Normalizer() { | |||
| 117 | if (disjuncts.length > 0) { | 122 | if (disjuncts.length > 0) { |
| 118 | disjuncts | 123 | disjuncts |
| 119 | .map(cls => factory.getOWLSubClassOfAxiom(cls, sup)) | 124 | .map(cls => factory.getOWLSubClassOfAxiom(cls, sup)) |
| 120 | .flatMap(normalize) | 125 | .flatMap(normalize(_)(fresh)) |
| 121 | } else { | 126 | } else { |
| 122 | normalize( | 127 | normalize( |
| 123 | factory.getOWLSubClassOfAxiom(factory.getOWLNothing, sup) | 128 | factory.getOWLSubClassOfAxiom(factory.getOWLNothing, sup) |
| 124 | ) | 129 | )(fresh) |
| 125 | } | 130 | } |
| 126 | } | 131 | } |
| 127 | /** Disjunction on the rhs | 132 | /** Disjunction on the rhs |
| @@ -137,9 +142,10 @@ class Normalizer() { | |||
| 137 | if (disjuncts.length > 0) { | 142 | if (disjuncts.length > 0) { |
| 138 | val acc = (Seq[OWLClassExpression](), Seq[OWLLogicalAxiom]()) | 143 | val acc = (Seq[OWLClassExpression](), Seq[OWLLogicalAxiom]()) |
| 139 | val (acc1, acc2) = disjuncts.foldLeft(acc)( | 144 | val (acc1, acc2) = disjuncts.foldLeft(acc)( |
| 140 | { case ((acc1, acc2), disj: OWLClass) => (acc1 :+ disj, acc2) | 145 | { |
| 146 | case ((acc1, acc2), disj: OWLClass) => (acc1 :+ disj, acc2) | ||
| 141 | case ((acc1, acc2), disj) => { | 147 | case ((acc1, acc2), disj) => { |
| 142 | val cls = RSAUtil.getFreshOWLClass() | 148 | val cls = fresh.getOWLClass |
| 143 | ( | 149 | ( |
| 144 | acc1 :+ cls, | 150 | acc1 :+ cls, |
| 145 | acc2 :+ factory.getOWLSubClassOfAxiom(cls, disj) | 151 | acc2 :+ factory.getOWLSubClassOfAxiom(cls, disj) |
| @@ -150,9 +156,11 @@ class Normalizer() { | |||
| 150 | (acc2 :+ factory.getOWLSubClassOfAxiom( | 156 | (acc2 :+ factory.getOWLSubClassOfAxiom( |
| 151 | sub, | 157 | sub, |
| 152 | factory.getOWLObjectUnionOf(acc1: _*) | 158 | factory.getOWLObjectUnionOf(acc1: _*) |
| 153 | )).flatMap(normalize) | 159 | )).flatMap(normalize(_)(fresh)) |
| 154 | } else { | 160 | } else { |
| 155 | normalize(factory.getOWLSubClassOfAxiom(sub, factory.getOWLNothing)) | 161 | normalize( |
| 162 | factory.getOWLSubClassOfAxiom(sub, factory.getOWLNothing) | ||
| 163 | )(fresh) | ||
| 156 | } | 164 | } |
| 157 | } | 165 | } |
| 158 | /** Complex class expression on existential restriction on the lhs | 166 | /** Complex class expression on existential restriction on the lhs |
| @@ -161,14 +169,14 @@ class Normalizer() { | |||
| 161 | */ | 169 | */ |
| 162 | case (sub: OWLObjectSomeValuesFrom, _) | 170 | case (sub: OWLObjectSomeValuesFrom, _) |
| 163 | if !sub.getFiller.isOWLClass => { | 171 | if !sub.getFiller.isOWLClass => { |
| 164 | val cls = RSAUtil.getFreshOWLClass() | 172 | val cls = fresh.getOWLClass |
| 165 | Seq( | 173 | Seq( |
| 166 | factory.getOWLSubClassOfAxiom(sub.getFiller, cls), | 174 | factory.getOWLSubClassOfAxiom(sub.getFiller, cls), |
| 167 | factory.getOWLSubClassOfAxiom( | 175 | factory.getOWLSubClassOfAxiom( |
| 168 | factory.getOWLObjectSomeValuesFrom(sub.getProperty, cls), | 176 | factory.getOWLObjectSomeValuesFrom(sub.getProperty, cls), |
| 169 | sup | 177 | sup |
| 170 | ) | 178 | ) |
| 171 | ).flatMap(normalize) | 179 | ).flatMap(normalize(_)(fresh)) |
| 172 | } | 180 | } |
| 173 | /** Complex class expression on existential restriction on the rhs | 181 | /** Complex class expression on existential restriction on the rhs |
| 174 | * | 182 | * |
| @@ -176,14 +184,14 @@ class Normalizer() { | |||
| 176 | */ | 184 | */ |
| 177 | case (_, sup: OWLObjectSomeValuesFrom) | 185 | case (_, sup: OWLObjectSomeValuesFrom) |
| 178 | if !sup.getFiller.isOWLClass => { | 186 | if !sup.getFiller.isOWLClass => { |
| 179 | val cls = RSAUtil.getFreshOWLClass() | 187 | val cls = fresh.getOWLClass |
| 180 | Seq( | 188 | Seq( |
| 181 | factory.getOWLSubClassOfAxiom(cls, sup.getFiller), | 189 | factory.getOWLSubClassOfAxiom(cls, sup.getFiller), |
| 182 | factory.getOWLSubClassOfAxiom( | 190 | factory.getOWLSubClassOfAxiom( |
| 183 | sub, | 191 | sub, |
| 184 | factory.getOWLObjectSomeValuesFrom(sup.getProperty, cls) | 192 | factory.getOWLObjectSomeValuesFrom(sup.getProperty, cls) |
| 185 | ) | 193 | ) |
| 186 | ).flatMap(normalize) | 194 | ).flatMap(normalize(_)(fresh)) |
| 187 | } | 195 | } |
| 188 | /** Object universal quantification on the lhs | 196 | /** Object universal quantification on the lhs |
| 189 | * | 197 | * |
| @@ -197,7 +205,7 @@ class Normalizer() { | |||
| 197 | case (sub: OWLObjectAllValuesFrom, _) => { | 205 | case (sub: OWLObjectAllValuesFrom, _) => { |
| 198 | val role = sub.getProperty | 206 | val role = sub.getProperty |
| 199 | val filler = sub.getFiller | 207 | val filler = sub.getFiller |
| 200 | val (c, d) = (RSAUtil.getFreshOWLClass, RSAUtil.getFreshOWLClass) | 208 | val (c, d) = (fresh.getOWLClass, fresh.getOWLClass) |
| 201 | Seq( | 209 | Seq( |
| 202 | factory.getOWLSubClassOfAxiom( | 210 | factory.getOWLSubClassOfAxiom( |
| 203 | factory.getOWLThing, | 211 | factory.getOWLThing, |
| @@ -208,12 +216,13 @@ class Normalizer() { | |||
| 208 | factory.getOWLNothing | 216 | factory.getOWLNothing |
| 209 | ), | 217 | ), |
| 210 | factory.getOWLSubClassOfAxiom( | 218 | factory.getOWLSubClassOfAxiom( |
| 211 | c, factory.getOWLObjectSomeValuesFrom(role, d) | 219 | c, |
| 220 | factory.getOWLObjectSomeValuesFrom(role, d) | ||
| 212 | ) | 221 | ) |
| 213 | ) | 222 | ) |
| 214 | } | 223 | } |
| 215 | /** Object/Data universal quantification on the lhs */ | 224 | /** Object/Data universal quantification on the lhs */ |
| 216 | case (sub: OWLDataAllValuesFrom, _) => notSupported(a) | 225 | case (sub: OWLDataAllValuesFrom, _) => notSupported(a) |
| 217 | /** Object universal quantification on the rhs | 226 | /** Object universal quantification on the rhs |
| 218 | * | 227 | * |
| 219 | * C c forall R . D -> exists R- . C c D | 228 | * C c forall R . D -> exists R- . C c D |
| @@ -228,7 +237,7 @@ class Normalizer() { | |||
| 228 | ), | 237 | ), |
| 229 | sup.getFiller | 238 | sup.getFiller |
| 230 | ) | 239 | ) |
| 231 | ) | 240 | )(fresh) |
| 232 | /** Object universal quantification on the rhs not supported */ | 241 | /** Object universal quantification on the rhs not supported */ |
| 233 | case (_, sup: OWLDataAllValuesFrom) => notSupported(a) | 242 | case (_, sup: OWLDataAllValuesFrom) => notSupported(a) |
| 234 | /** Exact object/data cardinality restriction on the lhs/rhs | 243 | /** Exact object/data cardinality restriction on the lhs/rhs |
| @@ -238,19 +247,19 @@ class Normalizer() { | |||
| 238 | case (sub: OWLObjectExactCardinality, _) => | 247 | case (sub: OWLObjectExactCardinality, _) => |
| 239 | normalize( | 248 | normalize( |
| 240 | factory.getOWLSubClassOfAxiom(sub.asIntersectionOfMinMax, sup) | 249 | factory.getOWLSubClassOfAxiom(sub.asIntersectionOfMinMax, sup) |
| 241 | ) | 250 | )(fresh) |
| 242 | case (sub: OWLDataExactCardinality, _) => | 251 | case (sub: OWLDataExactCardinality, _) => |
| 243 | normalize( | 252 | normalize( |
| 244 | factory.getOWLSubClassOfAxiom(sub.asIntersectionOfMinMax, sup) | 253 | factory.getOWLSubClassOfAxiom(sub.asIntersectionOfMinMax, sup) |
| 245 | ) | 254 | )(fresh) |
| 246 | case (_, sup: OWLObjectExactCardinality) => | 255 | case (_, sup: OWLObjectExactCardinality) => |
| 247 | normalize( | 256 | normalize( |
| 248 | factory.getOWLSubClassOfAxiom(sub, sup.asIntersectionOfMinMax) | 257 | factory.getOWLSubClassOfAxiom(sub, sup.asIntersectionOfMinMax) |
| 249 | ) | 258 | )(fresh) |
| 250 | case (_, sup: OWLDataExactCardinality) => | 259 | case (_, sup: OWLDataExactCardinality) => |
| 251 | normalize( | 260 | normalize( |
| 252 | factory.getOWLSubClassOfAxiom(sub, sup.asIntersectionOfMinMax) | 261 | factory.getOWLSubClassOfAxiom(sub, sup.asIntersectionOfMinMax) |
| 253 | ) | 262 | )(fresh) |
| 254 | /** Min object/data cardinality restriction on the lhs/rhs | 263 | /** Min object/data cardinality restriction on the lhs/rhs |
| 255 | * | 264 | * |
| 256 | * >= 0 R . C -> top | 265 | * >= 0 R . C -> top |
| @@ -263,7 +272,7 @@ class Normalizer() { | |||
| 263 | case 0 => | 272 | case 0 => |
| 264 | normalize( | 273 | normalize( |
| 265 | factory.getOWLSubClassOfAxiom(factory.getOWLThing, sup) | 274 | factory.getOWLSubClassOfAxiom(factory.getOWLThing, sup) |
| 266 | ) | 275 | )(fresh) |
| 267 | case 1 => | 276 | case 1 => |
| 268 | normalize( | 277 | normalize( |
| 269 | factory.getOWLSubClassOfAxiom( | 278 | factory.getOWLSubClassOfAxiom( |
| @@ -273,7 +282,7 @@ class Normalizer() { | |||
| 273 | ), | 282 | ), |
| 274 | sup | 283 | sup |
| 275 | ) | 284 | ) |
| 276 | ) | 285 | )(fresh) |
| 277 | case _ => notSupported(a) | 286 | case _ => notSupported(a) |
| 278 | } | 287 | } |
| 279 | case (sub: OWLDataMinCardinality, _) => | 288 | case (sub: OWLDataMinCardinality, _) => |
| @@ -281,7 +290,7 @@ class Normalizer() { | |||
| 281 | case 0 => | 290 | case 0 => |
| 282 | normalize( | 291 | normalize( |
| 283 | factory.getOWLSubClassOfAxiom(factory.getOWLThing, sup) | 292 | factory.getOWLSubClassOfAxiom(factory.getOWLThing, sup) |
| 284 | ) | 293 | )(fresh) |
| 285 | case 1 => | 294 | case 1 => |
| 286 | normalize( | 295 | normalize( |
| 287 | factory.getOWLSubClassOfAxiom( | 296 | factory.getOWLSubClassOfAxiom( |
| @@ -291,7 +300,7 @@ class Normalizer() { | |||
| 291 | ), | 300 | ), |
| 292 | sup | 301 | sup |
| 293 | ) | 302 | ) |
| 294 | ) | 303 | )(fresh) |
| 295 | case _ => notSupported(a) | 304 | case _ => notSupported(a) |
| 296 | } | 305 | } |
| 297 | case (_, sup: OWLObjectMinCardinality) => | 306 | case (_, sup: OWLObjectMinCardinality) => |
| @@ -306,7 +315,7 @@ class Normalizer() { | |||
| 306 | sup.getFiller | 315 | sup.getFiller |
| 307 | ) | 316 | ) |
| 308 | ) | 317 | ) |
| 309 | ) | 318 | )(fresh) |
| 310 | case _ => notSupported(a) | 319 | case _ => notSupported(a) |
| 311 | } | 320 | } |
| 312 | case (_, sup: OWLDataMinCardinality) => | 321 | case (_, sup: OWLDataMinCardinality) => |
| @@ -321,7 +330,7 @@ class Normalizer() { | |||
| 321 | sup.getFiller | 330 | sup.getFiller |
| 322 | ) | 331 | ) |
| 323 | ) | 332 | ) |
| 324 | ) | 333 | )(fresh) |
| 325 | case _ => notSupported(a) | 334 | case _ => notSupported(a) |
| 326 | } | 335 | } |
| 327 | /** Max object/data cardinality restriction on the lhs not supported */ | 336 | /** Max object/data cardinality restriction on the lhs not supported */ |
| @@ -344,17 +353,17 @@ class Normalizer() { | |||
| 344 | ), | 353 | ), |
| 345 | factory.getOWLNothing | 354 | factory.getOWLNothing |
| 346 | ) | 355 | ) |
| 347 | ) | 356 | )(fresh) |
| 348 | case (_, sup: OWLObjectMaxCardinality) | 357 | case (_, sup: OWLObjectMaxCardinality) |
| 349 | if sup.getCardinality == 1 && !sup.getFiller.isOWLClass => { | 358 | if sup.getCardinality == 1 && !sup.getFiller.isOWLClass => { |
| 350 | val cls = RSAUtil.getFreshOWLClass() | 359 | val cls = fresh.getOWLClass |
| 351 | Seq( | 360 | Seq( |
| 352 | factory.getOWLSubClassOfAxiom(cls, sup.getFiller), | 361 | factory.getOWLSubClassOfAxiom(cls, sup.getFiller), |
| 353 | factory.getOWLSubClassOfAxiom( | 362 | factory.getOWLSubClassOfAxiom( |
| 354 | sub, | 363 | sub, |
| 355 | factory.getOWLObjectMaxCardinality(1, sup.getProperty, cls) | 364 | factory.getOWLObjectMaxCardinality(1, sup.getProperty, cls) |
| 356 | ) | 365 | ) |
| 357 | ).flatMap(normalize) | 366 | ).flatMap(normalize(_)(fresh)) |
| 358 | } | 367 | } |
| 359 | case (_, sup: OWLObjectMaxCardinality) if sup.getCardinality >= 2 => | 368 | case (_, sup: OWLObjectMaxCardinality) if sup.getCardinality >= 2 => |
| 360 | notSupported(a) | 369 | notSupported(a) |
| @@ -368,7 +377,7 @@ class Normalizer() { | |||
| 368 | ), | 377 | ), |
| 369 | factory.getOWLNothing | 378 | factory.getOWLNothing |
| 370 | ) | 379 | ) |
| 371 | ) | 380 | )(fresh) |
| 372 | case (_, sup: OWLDataMaxCardinality) if sup.getCardinality >= 1 => | 381 | case (_, sup: OWLDataMaxCardinality) if sup.getCardinality >= 1 => |
| 373 | notSupported(a) | 382 | notSupported(a) |
| 374 | /** HasValue expression on the lhs/rhs | 383 | /** HasValue expression on the lhs/rhs |
| @@ -384,7 +393,7 @@ class Normalizer() { | |||
| 384 | ), | 393 | ), |
| 385 | sup | 394 | sup |
| 386 | ) | 395 | ) |
| 387 | ) | 396 | )(fresh) |
| 388 | case (sub: OWLDataHasValue, _) => | 397 | case (sub: OWLDataHasValue, _) => |
| 389 | normalize( | 398 | normalize( |
| 390 | factory.getOWLSubClassOfAxiom( | 399 | factory.getOWLSubClassOfAxiom( |
| @@ -394,7 +403,7 @@ class Normalizer() { | |||
| 394 | ), | 403 | ), |
| 395 | sup | 404 | sup |
| 396 | ) | 405 | ) |
| 397 | ) | 406 | )(fresh) |
| 398 | case (_, sup: OWLObjectHasValue) => | 407 | case (_, sup: OWLObjectHasValue) => |
| 399 | normalize( | 408 | normalize( |
| 400 | factory.getOWLSubClassOfAxiom( | 409 | factory.getOWLSubClassOfAxiom( |
| @@ -404,7 +413,7 @@ class Normalizer() { | |||
| 404 | factory.getOWLObjectOneOf(sup.getFiller) | 413 | factory.getOWLObjectOneOf(sup.getFiller) |
| 405 | ) | 414 | ) |
| 406 | ) | 415 | ) |
| 407 | ) | 416 | )(fresh) |
| 408 | case (_, sup: OWLDataHasValue) => | 417 | case (_, sup: OWLDataHasValue) => |
| 409 | normalize( | 418 | normalize( |
| 410 | factory.getOWLSubClassOfAxiom( | 419 | factory.getOWLSubClassOfAxiom( |
| @@ -414,7 +423,7 @@ class Normalizer() { | |||
| 414 | factory.getOWLDataOneOf(sup.getFiller) | 423 | factory.getOWLDataOneOf(sup.getFiller) |
| 415 | ) | 424 | ) |
| 416 | ) | 425 | ) |
| 417 | ) | 426 | )(fresh) |
| 418 | /** Enumeration of individuals on the lhs | 427 | /** Enumeration of individuals on the lhs |
| 419 | * | 428 | * |
| 420 | * {a1, ... ,an} c D -> { D(a1), ..., D(an) } | 429 | * {a1, ... ,an} c D -> { D(a1), ..., D(an) } |
| @@ -433,7 +442,7 @@ class Normalizer() { | |||
| 433 | sup.getIndividuals.map(factory.getOWLObjectOneOf(_)) | 442 | sup.getIndividuals.map(factory.getOWLObjectOneOf(_)) |
| 434 | ) | 443 | ) |
| 435 | ) | 444 | ) |
| 436 | ) | 445 | )(fresh) |
| 437 | /** Class complement on the lhs | 446 | /** Class complement on the lhs |
| 438 | * | 447 | * |
| 439 | * ~C c D -> top c C u D | 448 | * ~C c D -> top c C u D |
| @@ -444,7 +453,7 @@ class Normalizer() { | |||
| 444 | factory.getOWLThing, | 453 | factory.getOWLThing, |
| 445 | factory.getOWLObjectUnionOf(sub.getComplementNNF, sup) | 454 | factory.getOWLObjectUnionOf(sub.getComplementNNF, sup) |
| 446 | ) | 455 | ) |
| 447 | ) | 456 | )(fresh) |
| 448 | /** Class complement on the rhs | 457 | /** Class complement on the rhs |
| 449 | * | 458 | * |
| 450 | * C c ~D -> C n D c bot | 459 | * C c ~D -> C n D c bot |
| @@ -455,7 +464,7 @@ class Normalizer() { | |||
| 455 | factory.getOWLObjectIntersectionOf(sup.getComplementNNF, sub), | 464 | factory.getOWLObjectIntersectionOf(sup.getComplementNNF, sub), |
| 456 | factory.getOWLNothing | 465 | factory.getOWLNothing |
| 457 | ) | 466 | ) |
| 458 | ) | 467 | )(fresh) |
| 459 | /** Self-restriction over an object property */ | 468 | /** Self-restriction over an object property */ |
| 460 | case (sub: OWLObjectHasSelf, _) => notSupported(a) | 469 | case (sub: OWLObjectHasSelf, _) => notSupported(a) |
| 461 | case (_, sup: OWLObjectHasSelf) => notSupported(a) | 470 | case (_, sup: OWLObjectHasSelf) => notSupported(a) |
| @@ -466,32 +475,34 @@ class Normalizer() { | |||
| 466 | } | 475 | } |
| 467 | 476 | ||
| 468 | case a: OWLEquivalentClassesAxiom => { | 477 | case a: OWLEquivalentClassesAxiom => { |
| 469 | a.getAxiomWithoutAnnotations.asOWLSubClassOfAxioms.flatMap(normalize) | 478 | a.getAxiomWithoutAnnotations.asOWLSubClassOfAxioms.flatMap( |
| 479 | normalize(_)(fresh) | ||
| 480 | ) | ||
| 470 | } | 481 | } |
| 471 | 482 | ||
| 472 | case a: OWLEquivalentObjectPropertiesAxiom => { | 483 | case a: OWLEquivalentObjectPropertiesAxiom => { |
| 473 | a.getAxiomWithoutAnnotations.asSubObjectPropertyOfAxioms.flatMap( | 484 | a.getAxiomWithoutAnnotations.asSubObjectPropertyOfAxioms.flatMap( |
| 474 | normalize | 485 | normalize(_)(fresh) |
| 475 | ) | 486 | ) |
| 476 | } | 487 | } |
| 477 | 488 | ||
| 478 | case a: OWLEquivalentDataPropertiesAxiom => { | 489 | case a: OWLEquivalentDataPropertiesAxiom => { |
| 479 | a.getAxiomWithoutAnnotations.asSubDataPropertyOfAxioms.flatMap( | 490 | a.getAxiomWithoutAnnotations.asSubDataPropertyOfAxioms.flatMap( |
| 480 | normalize | 491 | normalize(_)(fresh) |
| 481 | ) | 492 | ) |
| 482 | } | 493 | } |
| 483 | 494 | ||
| 484 | case a: OWLObjectPropertyDomainAxiom => | 495 | case a: OWLObjectPropertyDomainAxiom => |
| 485 | normalize(a.getAxiomWithoutAnnotations.asOWLSubClassOfAxiom) | 496 | normalize(a.getAxiomWithoutAnnotations.asOWLSubClassOfAxiom)(fresh) |
| 486 | 497 | ||
| 487 | case a: OWLObjectPropertyRangeAxiom => | 498 | case a: OWLObjectPropertyRangeAxiom => |
| 488 | normalize(a.getAxiomWithoutAnnotations.asOWLSubClassOfAxiom) | 499 | normalize(a.getAxiomWithoutAnnotations.asOWLSubClassOfAxiom)(fresh) |
| 489 | 500 | ||
| 490 | case a: OWLDataPropertyDomainAxiom => | 501 | case a: OWLDataPropertyDomainAxiom => |
| 491 | normalize(a.getAxiomWithoutAnnotations.asOWLSubClassOfAxiom) | 502 | normalize(a.getAxiomWithoutAnnotations.asOWLSubClassOfAxiom)(fresh) |
| 492 | 503 | ||
| 493 | case a: OWLDataPropertyRangeAxiom => | 504 | case a: OWLDataPropertyRangeAxiom => |
| 494 | normalize(a.getAxiomWithoutAnnotations.asOWLSubClassOfAxiom) | 505 | normalize(a.getAxiomWithoutAnnotations.asOWLSubClassOfAxiom)(fresh) |
| 495 | 506 | ||
| 496 | case a: OWLDisjointClassesAxiom => | 507 | case a: OWLDisjointClassesAxiom => |
| 497 | a.asPairwiseAxioms.map((a) => { | 508 | a.asPairwiseAxioms.map((a) => { |
| @@ -504,20 +515,22 @@ class Normalizer() { | |||
| 504 | 515 | ||
| 505 | case a: OWLInverseObjectPropertiesAxiom => | 516 | case a: OWLInverseObjectPropertiesAxiom => |
| 506 | a.getAxiomWithoutAnnotations.asSubObjectPropertyOfAxioms.flatMap( | 517 | a.getAxiomWithoutAnnotations.asSubObjectPropertyOfAxioms.flatMap( |
| 507 | normalize | 518 | normalize(_)(fresh) |
| 508 | ) | 519 | ) |
| 509 | 520 | ||
| 510 | case a: OWLFunctionalObjectPropertyAxiom => | 521 | case a: OWLFunctionalObjectPropertyAxiom => |
| 511 | normalize(a.getAxiomWithoutAnnotations.asOWLSubClassOfAxiom) | 522 | normalize(a.getAxiomWithoutAnnotations.asOWLSubClassOfAxiom)(fresh) |
| 512 | 523 | ||
| 513 | case a: OWLFunctionalDataPropertyAxiom => | 524 | case a: OWLFunctionalDataPropertyAxiom => |
| 514 | normalize(a.getAxiomWithoutAnnotations.asOWLSubClassOfAxiom) | 525 | normalize(a.getAxiomWithoutAnnotations.asOWLSubClassOfAxiom)(fresh) |
| 515 | 526 | ||
| 516 | case a: OWLInverseFunctionalObjectPropertyAxiom => | 527 | case a: OWLInverseFunctionalObjectPropertyAxiom => |
| 517 | normalize(a.getAxiomWithoutAnnotations.asOWLSubClassOfAxiom) | 528 | normalize(a.getAxiomWithoutAnnotations.asOWLSubClassOfAxiom)(fresh) |
| 518 | 529 | ||
| 519 | case a: OWLSymmetricObjectPropertyAxiom => | 530 | case a: OWLSymmetricObjectPropertyAxiom => |
| 520 | a.getAxiomWithoutAnnotations.asSubPropertyAxioms.flatMap(normalize) | 531 | a.getAxiomWithoutAnnotations.asSubPropertyAxioms.flatMap( |
| 532 | normalize(_)(fresh) | ||
| 533 | ) | ||
| 521 | 534 | ||
| 522 | case a: OWLDifferentIndividualsAxiom => | 535 | case a: OWLDifferentIndividualsAxiom => |
| 523 | a.asPairwiseAxioms.map((a) => { | 536 | a.asPairwiseAxioms.map((a) => { |
| @@ -529,42 +542,44 @@ class Normalizer() { | |||
| 529 | }) | 542 | }) |
| 530 | 543 | ||
| 531 | case a: OWLIrreflexiveObjectPropertyAxiom => | 544 | case a: OWLIrreflexiveObjectPropertyAxiom => |
| 532 | normalize(a.getAxiomWithoutAnnotations.asOWLSubClassOfAxiom) | 545 | normalize(a.getAxiomWithoutAnnotations.asOWLSubClassOfAxiom)(fresh) |
| 533 | 546 | ||
| 534 | case a: OWLSameIndividualAxiom => | 547 | case a: OWLSameIndividualAxiom => |
| 535 | a.getAxiomWithoutAnnotations.asOWLSubClassOfAxioms.flatMap(normalize) | 548 | a.getAxiomWithoutAnnotations.asOWLSubClassOfAxioms.flatMap( |
| 549 | normalize(_)(fresh) | ||
| 550 | ) | ||
| 536 | 551 | ||
| 537 | case a: OWLDisjointUnionAxiom => | 552 | case a: OWLDisjointUnionAxiom => |
| 538 | Seq(a.getOWLDisjointClassesAxiom, a.getOWLEquivalentClassesAxiom) | 553 | Seq(a.getOWLDisjointClassesAxiom, a.getOWLEquivalentClassesAxiom) |
| 539 | .flatMap(normalize) | 554 | .flatMap(normalize(_)(fresh)) |
| 540 | 555 | ||
| 541 | /** Complex class assertion | 556 | /** Complex class assertion |
| 542 | * | 557 | * |
| 543 | * C(a) -> { X(a), X c C } | 558 | * C(a) -> { X(a), X c C } |
| 544 | */ | 559 | */ |
| 545 | case a: OWLClassAssertionAxiom if !a.getClassExpression.isOWLClass => { | 560 | case a: OWLClassAssertionAxiom if !a.getClassExpression.isOWLClass => { |
| 546 | val cls = RSAUtil.getFreshOWLClass() | 561 | val cls = fresh.getOWLClass |
| 547 | Seq( | 562 | Seq( |
| 548 | factory.getOWLClassAssertionAxiom(cls, a.getIndividual), | 563 | factory.getOWLClassAssertionAxiom(cls, a.getIndividual), |
| 549 | factory.getOWLSubClassOfAxiom(cls, a.getClassExpression) | 564 | factory.getOWLSubClassOfAxiom(cls, a.getClassExpression) |
| 550 | ).flatMap(normalize) | 565 | ).flatMap(normalize(_)(fresh)) |
| 551 | } | 566 | } |
| 552 | 567 | ||
| 553 | case a: OWLNegativeObjectPropertyAssertionAxiom => | 568 | case a: OWLNegativeObjectPropertyAssertionAxiom => |
| 554 | normalize(a.getAxiomWithoutAnnotations.asOWLSubClassOfAxiom) | 569 | normalize(a.getAxiomWithoutAnnotations.asOWLSubClassOfAxiom)(fresh) |
| 555 | 570 | ||
| 556 | case a: OWLNegativeDataPropertyAssertionAxiom => | 571 | case a: OWLNegativeDataPropertyAssertionAxiom => |
| 557 | normalize(a.getAxiomWithoutAnnotations.asOWLSubClassOfAxiom) | 572 | normalize(a.getAxiomWithoutAnnotations.asOWLSubClassOfAxiom)(fresh) |
| 558 | 573 | ||
| 559 | case a: OWLTransitiveObjectPropertyAxiom => { | 574 | case a: OWLTransitiveObjectPropertyAxiom => { |
| 560 | val role = a.getProperty | 575 | val role = a.getProperty |
| 561 | normalize( | 576 | normalize( |
| 562 | factory.getOWLSubPropertyChainOfAxiom( List(role, role), role) | 577 | factory.getOWLSubPropertyChainOfAxiom(List(role, role), role) |
| 563 | ) | 578 | )(fresh) |
| 564 | } | 579 | } |
| 565 | 580 | ||
| 566 | case a: OWLReflexiveObjectPropertyAxiom => | 581 | case a: OWLReflexiveObjectPropertyAxiom => |
| 567 | normalize(a.getAxiomWithoutAnnotations.asOWLSubClassOfAxiom) | 582 | normalize(a.getAxiomWithoutAnnotations.asOWLSubClassOfAxiom)(fresh) |
| 568 | 583 | ||
| 569 | case a: OWLAsymmetricObjectPropertyAxiom => notSupported(a) | 584 | case a: OWLAsymmetricObjectPropertyAxiom => notSupported(a) |
| 570 | 585 | ||
diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/converter/RDFoxConverter.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/converter/RDFoxConverter.scala index 03c1246..266c158 100644 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/converter/RDFoxConverter.scala +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/converter/RDFoxConverter.scala | |||
| @@ -27,10 +27,9 @@ import tech.oxfordsemantic.jrdfox.logic.datalog.{ | |||
| 27 | TupleTableAtom | 27 | TupleTableAtom |
| 28 | } | 28 | } |
| 29 | import tech.oxfordsemantic.jrdfox.logic.expression.{Term, IRI, FunctionCall} | 29 | import tech.oxfordsemantic.jrdfox.logic.expression.{Term, IRI, FunctionCall} |
| 30 | import uk.ac.ox.cs.rsacomb.RSAUtil | ||
| 31 | import uk.ac.ox.cs.rsacomb.RSAOntology | 30 | import uk.ac.ox.cs.rsacomb.RSAOntology |
| 32 | import uk.ac.ox.cs.rsacomb.suffix.{Empty, Inverse, RSASuffix} | 31 | import uk.ac.ox.cs.rsacomb.suffix.{Empty, Inverse, RSASuffix} |
| 33 | import uk.ac.ox.cs.rsacomb.util.{RSA, RDFoxUtil} | 32 | import uk.ac.ox.cs.rsacomb.util.{DataFactory, RSA, RDFoxUtil} |
| 34 | 33 | ||
| 35 | /** Horn-ALCHOIQ to RDFox axiom converter. | 34 | /** Horn-ALCHOIQ to RDFox axiom converter. |
| 36 | * | 35 | * |
| @@ -129,16 +128,16 @@ trait RDFoxConverter { | |||
| 129 | unsafe: List[OWLObjectPropertyExpression], | 128 | unsafe: List[OWLObjectPropertyExpression], |
| 130 | skolem: SkolemStrategy, | 129 | skolem: SkolemStrategy, |
| 131 | suffix: RSASuffix | 130 | suffix: RSASuffix |
| 132 | ): Result = | 131 | )(implicit fresh: DataFactory): Result = |
| 133 | axiom match { | 132 | axiom match { |
| 134 | 133 | ||
| 135 | case a: OWLSubClassOfAxiom => { | 134 | case a: OWLSubClassOfAxiom => { |
| 136 | val subcls = a.getSubClass | 135 | val subcls = a.getSubClass |
| 137 | val supcls = a.getSuperClass | 136 | val supcls = a.getSuperClass |
| 138 | val (sub, _) = | 137 | val (sub, _) = |
| 139 | convert(subcls, term, unsafe, NoSkolem, suffix) | 138 | convert(subcls, term, unsafe, NoSkolem, suffix)(fresh) |
| 140 | val (sup, ext) = | 139 | val (sup, ext) = |
| 141 | convert(supcls, term, unsafe, skolem, suffix) | 140 | convert(supcls, term, unsafe, skolem, suffix)(fresh) |
| 142 | val rule = Rule.create(sup, ext ::: sub) | 141 | val rule = Rule.create(sup, ext ::: sub) |
| 143 | ResultR(List(rule)) | 142 | ResultR(List(rule)) |
| 144 | } | 143 | } |
| @@ -148,7 +147,7 @@ trait RDFoxConverter { | |||
| 148 | case a: OWLEquivalentClassesAxiom => { | 147 | case a: OWLEquivalentClassesAxiom => { |
| 149 | val (atoms, rules) = a.asPairwiseAxioms | 148 | val (atoms, rules) = a.asPairwiseAxioms |
| 150 | .flatMap(_.asOWLSubClassOfAxioms) | 149 | .flatMap(_.asOWLSubClassOfAxioms) |
| 151 | .map(a => convert(a, term, unsafe, skolem dup a, suffix)) | 150 | .map(a => convert(a, term, unsafe, skolem dup a, suffix)(fresh)) |
| 152 | .unzip | 151 | .unzip |
| 153 | (atoms.flatten, rules.flatten) | 152 | (atoms.flatten, rules.flatten) |
| 154 | } | 153 | } |
| @@ -156,61 +155,64 @@ trait RDFoxConverter { | |||
| 156 | case a: OWLEquivalentObjectPropertiesAxiom => { | 155 | case a: OWLEquivalentObjectPropertiesAxiom => { |
| 157 | val (atoms, rules) = a.asPairwiseAxioms | 156 | val (atoms, rules) = a.asPairwiseAxioms |
| 158 | .flatMap(_.asSubObjectPropertyOfAxioms) | 157 | .flatMap(_.asSubObjectPropertyOfAxioms) |
| 159 | .map(a => convert(a, term, unsafe, skolem dup a, suffix)) | 158 | .map(a => convert(a, term, unsafe, skolem dup a, suffix)(fresh)) |
| 160 | .unzip | 159 | .unzip |
| 161 | (atoms.flatten, rules.flatten) | 160 | (atoms.flatten, rules.flatten) |
| 162 | } | 161 | } |
| 163 | 162 | ||
| 164 | case a: OWLSubObjectPropertyOfAxiom => { | 163 | case a: OWLSubObjectPropertyOfAxiom => { |
| 165 | val term1 = RSAUtil.genFreshVariable() | 164 | val term1 = fresh.getVariable |
| 166 | val body = convert(a.getSubProperty, term, term1, suffix) | 165 | val body = convert(a.getSubProperty, term, term1, suffix)(fresh) |
| 167 | val head = convert(a.getSuperProperty, term, term1, suffix) | 166 | val head = convert(a.getSuperProperty, term, term1, suffix)(fresh) |
| 168 | ResultR(List(Rule.create(head, body))) | 167 | ResultR(List(Rule.create(head, body))) |
| 169 | } | 168 | } |
| 170 | 169 | ||
| 171 | case a: OWLSubDataPropertyOfAxiom => { | 170 | case a: OWLSubDataPropertyOfAxiom => { |
| 172 | val term1 = RSAUtil.genFreshVariable() | 171 | val term1 = fresh.getVariable |
| 173 | val body = convert(a.getSubProperty, term, term1, suffix) | 172 | val body = convert(a.getSubProperty, term, term1, suffix)(fresh) |
| 174 | val head = convert(a.getSuperProperty, term, term1, suffix) | 173 | val head = convert(a.getSuperProperty, term, term1, suffix)(fresh) |
| 175 | ResultR(List(Rule.create(head, body))) | 174 | ResultR(List(Rule.create(head, body))) |
| 176 | } | 175 | } |
| 177 | 176 | ||
| 178 | case a: OWLObjectPropertyDomainAxiom => | 177 | case a: OWLObjectPropertyDomainAxiom => |
| 179 | convert(a.asOWLSubClassOfAxiom, term, unsafe, skolem, suffix) | 178 | convert(a.asOWLSubClassOfAxiom, term, unsafe, skolem, suffix)(fresh) |
| 180 | 179 | ||
| 181 | case a: OWLObjectPropertyRangeAxiom => { | 180 | case a: OWLObjectPropertyRangeAxiom => { |
| 182 | val term1 = RSAUtil.genFreshVariable() | 181 | val term1 = fresh.getVariable |
| 183 | val (res, ext) = convert(a.getRange, term, unsafe, skolem, suffix) | 182 | val (res, ext) = |
| 184 | val prop = convert(a.getProperty, term1, term, suffix) | 183 | convert(a.getRange, term, unsafe, skolem, suffix)(fresh) |
| 184 | val prop = convert(a.getProperty, term1, term, suffix)(fresh) | ||
| 185 | ResultR(List(Rule.create(res, prop :: ext))) | 185 | ResultR(List(Rule.create(res, prop :: ext))) |
| 186 | } | 186 | } |
| 187 | 187 | ||
| 188 | case a: OWLDataPropertyDomainAxiom => | 188 | case a: OWLDataPropertyDomainAxiom => |
| 189 | convert(a.asOWLSubClassOfAxiom, term, unsafe, skolem, suffix) | 189 | convert(a.asOWLSubClassOfAxiom, term, unsafe, skolem, suffix)(fresh) |
| 190 | 190 | ||
| 191 | case a: OWLDisjointClassesAxiom => { | 191 | case a: OWLDisjointClassesAxiom => { |
| 192 | val body = a.getOperandsAsList.asScala.toSeq | 192 | val body = a.getOperandsAsList.asScala.toSeq |
| 193 | .flatMap((cls) => convert(cls, term, unsafe, NoSkolem, suffix)._1) | 193 | .flatMap((cls) => |
| 194 | convert(cls, term, unsafe, NoSkolem, suffix)(fresh)._1 | ||
| 195 | ) | ||
| 194 | val bottom = TupleTableAtom.rdf(term, IRI.RDF_TYPE, IRI.NOTHING) | 196 | val bottom = TupleTableAtom.rdf(term, IRI.RDF_TYPE, IRI.NOTHING) |
| 195 | ResultR(List(Rule.create(bottom, body: _*))) | 197 | ResultR(List(Rule.create(bottom, body: _*))) |
| 196 | } | 198 | } |
| 197 | 199 | ||
| 198 | case a: OWLInverseObjectPropertiesAxiom => { | 200 | case a: OWLInverseObjectPropertiesAxiom => { |
| 199 | val (atoms, rules) = a.asSubObjectPropertyOfAxioms | 201 | val (atoms, rules) = a.asSubObjectPropertyOfAxioms |
| 200 | .map(a => convert(a, term, unsafe, skolem dup a, suffix)) | 202 | .map(a => convert(a, term, unsafe, skolem dup a, suffix)(fresh)) |
| 201 | .unzip | 203 | .unzip |
| 202 | (atoms.flatten, rules.flatten) | 204 | (atoms.flatten, rules.flatten) |
| 203 | } | 205 | } |
| 204 | 206 | ||
| 205 | case a: OWLFunctionalObjectPropertyAxiom => | 207 | case a: OWLFunctionalObjectPropertyAxiom => |
| 206 | convert(a.asOWLSubClassOfAxiom, term, unsafe, skolem, suffix) | 208 | convert(a.asOWLSubClassOfAxiom, term, unsafe, skolem, suffix)(fresh) |
| 207 | 209 | ||
| 208 | case a: OWLInverseFunctionalObjectPropertyAxiom => | 210 | case a: OWLInverseFunctionalObjectPropertyAxiom => |
| 209 | convert(a.asOWLSubClassOfAxiom, term, unsafe, skolem, suffix) | 211 | convert(a.asOWLSubClassOfAxiom, term, unsafe, skolem, suffix)(fresh) |
| 210 | 212 | ||
| 211 | case a: OWLSymmetricObjectPropertyAxiom => { | 213 | case a: OWLSymmetricObjectPropertyAxiom => { |
| 212 | val (atoms, rules) = a.asSubPropertyAxioms | 214 | val (atoms, rules) = a.asSubPropertyAxioms |
| 213 | .map(a => convert(a, term, unsafe, skolem dup a, suffix)) | 215 | .map(a => convert(a, term, unsafe, skolem dup a, suffix)(fresh)) |
| 214 | .unzip | 216 | .unzip |
| 215 | (atoms.flatten, rules.flatten) | 217 | (atoms.flatten, rules.flatten) |
| 216 | } | 218 | } |
| @@ -221,7 +223,7 @@ trait RDFoxConverter { | |||
| 221 | case i: OWLNamedIndividual => { | 223 | case i: OWLNamedIndividual => { |
| 222 | val cls = a.getClassExpression | 224 | val cls = a.getClassExpression |
| 223 | val (res, _) = | 225 | val (res, _) = |
| 224 | convert(cls, i.getIRI, unsafe, NoSkolem, suffix) | 226 | convert(cls, i.getIRI, unsafe, NoSkolem, suffix)(fresh) |
| 225 | ResultF(res) | 227 | ResultF(res) |
| 226 | } | 228 | } |
| 227 | case _ => Result() | 229 | case _ => Result() |
| @@ -234,7 +236,7 @@ trait RDFoxConverter { | |||
| 234 | else { | 236 | else { |
| 235 | val subj = a.getSubject.asOWLNamedIndividual.getIRI | 237 | val subj = a.getSubject.asOWLNamedIndividual.getIRI |
| 236 | val obj = a.getObject.asOWLNamedIndividual.getIRI | 238 | val obj = a.getObject.asOWLNamedIndividual.getIRI |
| 237 | val prop = convert(a.getProperty, subj, obj, suffix) | 239 | val prop = convert(a.getProperty, subj, obj, suffix)(fresh) |
| 238 | ResultF(List(prop)) | 240 | ResultF(List(prop)) |
| 239 | } | 241 | } |
| 240 | 242 | ||
| @@ -248,29 +250,29 @@ trait RDFoxConverter { | |||
| 248 | else { | 250 | else { |
| 249 | val subj = a.getSubject.asOWLNamedIndividual.getIRI | 251 | val subj = a.getSubject.asOWLNamedIndividual.getIRI |
| 250 | val obj = a.getObject | 252 | val obj = a.getObject |
| 251 | val prop = convert(a.getProperty, subj, obj, suffix) | 253 | val prop = convert(a.getProperty, subj, obj, suffix)(fresh) |
| 252 | ResultF(List(prop)) | 254 | ResultF(List(prop)) |
| 253 | } | 255 | } |
| 254 | 256 | ||
| 255 | case a: OWLSubPropertyChainOfAxiom => { | 257 | case a: OWLSubPropertyChainOfAxiom => { |
| 256 | val (term1, body) = a.getPropertyChain.foldLeft((term, List[TupleTableAtom]())){ | 258 | val (term1, body) = |
| 257 | case ((term, atoms), prop) => { | 259 | a.getPropertyChain.foldLeft((term, List[TupleTableAtom]())) { |
| 258 | val term1 = RSAUtil.genFreshVariable() | 260 | case ((term, atoms), prop) => { |
| 259 | val atom = convert(prop, term, term1, suffix) | 261 | val term1 = fresh.getVariable |
| 260 | (term1, atoms :+ atom) | 262 | val atom = convert(prop, term, term1, suffix)(fresh) |
| 263 | (term1, atoms :+ atom) | ||
| 264 | } | ||
| 261 | } | 265 | } |
| 262 | } | 266 | val head = convert(a.getSuperProperty, term, term1, suffix)(fresh) |
| 263 | val head = convert(a.getSuperProperty, term, term1, suffix) | 267 | val rule = Rule.create(head, body) |
| 264 | ResultR(List(Rule.create(head, body))) | 268 | println(rule) |
| 269 | ResultR(List(rule)) | ||
| 265 | } | 270 | } |
| 266 | 271 | ||
| 267 | /** Catch-all case for all unhandled axiom types. */ | 272 | /** Catch-all case for all unhandled axiom types. */ |
| 268 | case a => unsupported(axiom) | 273 | case a => unsupported(axiom) |
| 269 | } | 274 | } |
| 270 | 275 | ||
| 271 | protected def toBeNormalised(axiom: OWLLogicalAxiom): Result = | ||
| 272 | throw new RuntimeException(s"Axiom '$axiom' should be normalised!") | ||
| 273 | |||
| 274 | protected def unsupported(axiom: OWLLogicalAxiom): Result = | 276 | protected def unsupported(axiom: OWLLogicalAxiom): Result = |
| 275 | throw new RuntimeException(s"Axiom '$axiom' is not supported (yet?)") | 277 | throw new RuntimeException(s"Axiom '$axiom' is not supported (yet?)") |
| 276 | 278 | ||
| @@ -299,7 +301,7 @@ trait RDFoxConverter { | |||
| 299 | unsafe: List[OWLObjectPropertyExpression], | 301 | unsafe: List[OWLObjectPropertyExpression], |
| 300 | skolem: SkolemStrategy, | 302 | skolem: SkolemStrategy, |
| 301 | suffix: RSASuffix | 303 | suffix: RSASuffix |
| 302 | ): Shards = | 304 | )(implicit fresh: DataFactory): Shards = |
| 303 | expr match { | 305 | expr match { |
| 304 | 306 | ||
| 305 | /** Simple class name. | 307 | /** Simple class name. |
| @@ -318,7 +320,7 @@ trait RDFoxConverter { | |||
| 318 | */ | 320 | */ |
| 319 | case e: OWLObjectIntersectionOf => { | 321 | case e: OWLObjectIntersectionOf => { |
| 320 | val (res, ext) = e.asConjunctSet | 322 | val (res, ext) = e.asConjunctSet |
| 321 | .map(convert(_, term, unsafe, skolem, suffix)) | 323 | .map(convert(_, term, unsafe, skolem, suffix)(fresh)) |
| 322 | .unzip | 324 | .unzip |
| 323 | (res.flatten, ext.flatten) | 325 | (res.flatten, ext.flatten) |
| 324 | } | 326 | } |
| @@ -352,14 +354,14 @@ trait RDFoxConverter { | |||
| 352 | case e: OWLObjectSomeValuesFrom => { | 354 | case e: OWLObjectSomeValuesFrom => { |
| 353 | val cls = e.getFiller() | 355 | val cls = e.getFiller() |
| 354 | val role = e.getProperty() | 356 | val role = e.getProperty() |
| 355 | val varX = RSAUtil.genFreshVariable | 357 | val varX = fresh.getVariable |
| 356 | val (bind, term1) = skolem match { | 358 | val (bind, term1) = skolem match { |
| 357 | case NoSkolem => (None, varX) | 359 | case NoSkolem => (None, varX) |
| 358 | case c: Constant => (None, c.iri) | 360 | case c: Constant => (None, c.iri) |
| 359 | case s: Standard => (Some(RDFoxUtil.skolem(s.name, term, varX)), varX) | 361 | case s: Standard => (Some(RDFoxUtil.skolem(s.name, term, varX)), varX) |
| 360 | } | 362 | } |
| 361 | val (res, ext) = convert(cls, term1, unsafe, skolem, suffix) | 363 | val (res, ext) = convert(cls, term1, unsafe, skolem, suffix)(fresh) |
| 362 | val prop = convert(role, term, term1, suffix) | 364 | val prop = convert(role, term, term1, suffix)(fresh) |
| 363 | (prop :: res, ext ++ bind) | 365 | (prop :: res, ext ++ bind) |
| 364 | } | 366 | } |
| 365 | 367 | ||
| @@ -379,13 +381,13 @@ trait RDFoxConverter { | |||
| 379 | // Computes the result of rule skolemization. Depending on the used | 381 | // Computes the result of rule skolemization. Depending on the used |
| 380 | // technique it might involve the introduction of additional atoms, | 382 | // technique it might involve the introduction of additional atoms, |
| 381 | // and/or fresh constants and variables. | 383 | // and/or fresh constants and variables. |
| 382 | val varX = RSAUtil.genFreshVariable | 384 | val varX = fresh.getVariable |
| 383 | val (bind, term1) = skolem match { | 385 | val (bind, term1) = skolem match { |
| 384 | case NoSkolem => (None, varX) | 386 | case NoSkolem => (None, varX) |
| 385 | case c: Constant => (None, c.iri) | 387 | case c: Constant => (None, c.iri) |
| 386 | case s: Standard => (Some(RDFoxUtil.skolem(s.name, term, varX)), varX) | 388 | case s: Standard => (Some(RDFoxUtil.skolem(s.name, term, varX)), varX) |
| 387 | } | 389 | } |
| 388 | val prop = convert(role, term, term1, suffix) | 390 | val prop = convert(role, term, term1, suffix)(fresh) |
| 389 | (List(prop), bind.toList) | 391 | (List(prop), bind.toList) |
| 390 | } | 392 | } |
| 391 | 393 | ||
| @@ -404,11 +406,12 @@ trait RDFoxConverter { | |||
| 404 | s"Class expression '$e' has cardinality restriction != 1." | 406 | s"Class expression '$e' has cardinality restriction != 1." |
| 405 | ) | 407 | ) |
| 406 | val vars @ (y :: z :: _) = | 408 | val vars @ (y :: z :: _) = |
| 407 | Seq(RSAUtil.genFreshVariable(), RSAUtil.genFreshVariable()) | 409 | Seq(fresh.getVariable, fresh.getVariable) |
| 408 | val cls = e.getFiller | 410 | val cls = e.getFiller |
| 409 | val role = e.getProperty | 411 | val role = e.getProperty |
| 410 | val (res, ext) = vars.map(convert(cls, _, unsafe, skolem, suffix)).unzip | 412 | val (res, ext) = |
| 411 | val props = vars.map(convert(role, term, _, suffix)) | 413 | vars.map(convert(cls, _, unsafe, skolem, suffix)(fresh)).unzip |
| 414 | val props = vars.map(convert(role, term, _, suffix)(fresh)) | ||
| 412 | val eq = TupleTableAtom.rdf(y, IRI.SAME_AS, z) | 415 | val eq = TupleTableAtom.rdf(y, IRI.SAME_AS, z) |
| 413 | (List(eq), res.flatten ++ props) | 416 | (List(eq), res.flatten ++ props) |
| 414 | } | 417 | } |
| @@ -431,7 +434,7 @@ trait RDFoxConverter { | |||
| 431 | val filler = e.getFiller | 434 | val filler = e.getFiller |
| 432 | val property = e.getProperty | 435 | val property = e.getProperty |
| 433 | val expr = factory.getOWLObjectSomeValuesFrom(property, filler) | 436 | val expr = factory.getOWLObjectSomeValuesFrom(property, filler) |
| 434 | convert(expr, term, unsafe, skolem, suffix) | 437 | convert(expr, term, unsafe, skolem, suffix)(fresh) |
| 435 | } | 438 | } |
| 436 | 439 | ||
| 437 | /** Minimum cardinality restriction class | 440 | /** Minimum cardinality restriction class |
| @@ -452,7 +455,7 @@ trait RDFoxConverter { | |||
| 452 | val filler = e.getFiller | 455 | val filler = e.getFiller |
| 453 | val property = e.getProperty | 456 | val property = e.getProperty |
| 454 | val expr = factory.getOWLDataSomeValuesFrom(property, filler) | 457 | val expr = factory.getOWLDataSomeValuesFrom(property, filler) |
| 455 | convert(expr, term, unsafe, skolem, suffix) | 458 | convert(expr, term, unsafe, skolem, suffix)(fresh) |
| 456 | } | 459 | } |
| 457 | 460 | ||
| 458 | //case (_, sup: OWLObjectExactCardinality) => { | 461 | //case (_, sup: OWLObjectExactCardinality) => { |
| @@ -475,7 +478,7 @@ trait RDFoxConverter { | |||
| 475 | case i: OWLNamedIndividual => i.getIRI | 478 | case i: OWLNamedIndividual => i.getIRI |
| 476 | case i: OWLAnonymousIndividual => i.getID | 479 | case i: OWLAnonymousIndividual => i.getID |
| 477 | } | 480 | } |
| 478 | (List(convert(e.getProperty, term, term1, suffix)), List()) | 481 | (List(convert(e.getProperty, term, term1, suffix)(fresh)), List()) |
| 479 | } | 482 | } |
| 480 | 483 | ||
| 481 | /** Existential quantification with singleton literal filler | 484 | /** Existential quantification with singleton literal filler |
| @@ -484,7 +487,7 @@ trait RDFoxConverter { | |||
| 484 | * [[http://www.w3.org/TR/owl2-syntax/#Literal_Value_Restriction]] | 487 | * [[http://www.w3.org/TR/owl2-syntax/#Literal_Value_Restriction]] |
| 485 | */ | 488 | */ |
| 486 | case e: OWLDataHasValue => | 489 | case e: OWLDataHasValue => |
| 487 | (List(convert(e.getProperty, term, e.getFiller, suffix)), List()) | 490 | (List(convert(e.getProperty, term, e.getFiller, suffix)(fresh)), List()) |
| 488 | 491 | ||
| 489 | case e: OWLObjectUnionOf => { | 492 | case e: OWLObjectUnionOf => { |
| 490 | (List(), List()) | 493 | (List(), List()) |
| @@ -503,7 +506,7 @@ trait RDFoxConverter { | |||
| 503 | term1: Term, | 506 | term1: Term, |
| 504 | term2: Term, | 507 | term2: Term, |
| 505 | suffix: RSASuffix | 508 | suffix: RSASuffix |
| 506 | ): TupleTableAtom = | 509 | )(implicit fresh: DataFactory): TupleTableAtom = |
| 507 | expr match { | 510 | expr match { |
| 508 | 511 | ||
| 509 | /** Simple named role/object property. | 512 | /** Simple named role/object property. |
| @@ -524,7 +527,7 @@ trait RDFoxConverter { | |||
| 524 | */ | 527 | */ |
| 525 | case e: OWLObjectInverseOf => | 528 | case e: OWLObjectInverseOf => |
| 526 | //convert(e.getInverse, term1, term2, suffix + Inverse) | 529 | //convert(e.getInverse, term1, term2, suffix + Inverse) |
| 527 | convert(e.getInverse, term2, term1, suffix) | 530 | convert(e.getInverse, term2, term1, suffix)(fresh) |
| 528 | 531 | ||
| 529 | /** The infamous impossible case. | 532 | /** The infamous impossible case. |
| 530 | * | 533 | * |
| @@ -543,7 +546,7 @@ trait RDFoxConverter { | |||
| 543 | term1: Term, | 546 | term1: Term, |
| 544 | term2: Term, | 547 | term2: Term, |
| 545 | suffix: RSASuffix | 548 | suffix: RSASuffix |
| 546 | ): TupleTableAtom = | 549 | )(implicit fresh: DataFactory): TupleTableAtom = |
| 547 | expr match { | 550 | expr match { |
| 548 | 551 | ||
| 549 | /** Simple named role/data property | 552 | /** Simple named role/data property |
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 09bfa1e..795e039 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 | |||
| @@ -25,10 +25,9 @@ import tech.oxfordsemantic.jrdfox.logic.datalog.{ | |||
| 25 | } | 25 | } |
| 26 | import tech.oxfordsemantic.jrdfox.logic.expression.{IRI} | 26 | import tech.oxfordsemantic.jrdfox.logic.expression.{IRI} |
| 27 | 27 | ||
| 28 | import uk.ac.ox.cs.rsacomb.RSAUtil | ||
| 29 | import uk.ac.ox.cs.rsacomb.RSAOntology | 28 | import uk.ac.ox.cs.rsacomb.RSAOntology |
| 30 | import uk.ac.ox.cs.rsacomb.suffix.{RSASuffix, Nth} | 29 | import uk.ac.ox.cs.rsacomb.suffix.{RSASuffix, Nth} |
| 31 | import uk.ac.ox.cs.rsacomb.util.RDFoxUtil | 30 | import uk.ac.ox.cs.rsacomb.util.{DataFactory, RDFoxUtil} |
| 32 | 31 | ||
| 33 | /* Is this the best way to determine if an atom is an RDF triple? | 32 | /* Is this the best way to determine if an atom is an RDF triple? |
| 34 | * Note that we can't use `getNumberOfArguments()` because is not | 33 | * Note that we can't use `getNumberOfArguments()` because is not |
| @@ -91,11 +90,13 @@ object RSAAtom { | |||
| 91 | TupleTableAtom.create(ttname, atom.getArguments()) | 90 | TupleTableAtom.create(ttname, atom.getArguments()) |
| 92 | } | 91 | } |
| 93 | 92 | ||
| 94 | lazy val reified: (Option[TupleTableAtom], List[TupleTableAtom]) = | 93 | def reified(implicit |
| 94 | fresh: DataFactory | ||
| 95 | ): (Option[TupleTableAtom], List[TupleTableAtom]) = | ||
| 95 | if (isRDF) { | 96 | if (isRDF) { |
| 96 | (None, List(atom)) | 97 | (None, List(atom)) |
| 97 | } else { | 98 | } else { |
| 98 | val varS = RSAUtil.genFreshVariable() | 99 | val varS = fresh.getVariable |
| 99 | val skolem = RDFoxUtil.skolem(name, (args :+ varS): _*) | 100 | val skolem = RDFoxUtil.skolem(name, (args :+ varS): _*) |
| 100 | val atom = TupleTableAtom.rdf(varS, IRI.RDF_TYPE, name) | 101 | val atom = TupleTableAtom.rdf(varS, IRI.RDF_TYPE, name) |
| 101 | val atoms = args.zipWithIndex | 102 | val atoms = args.zipWithIndex |
diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/ontology/Ontology.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/ontology/Ontology.scala index ba44605..1f44ce1 100644 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/ontology/Ontology.scala +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/ontology/Ontology.scala | |||
| @@ -35,9 +35,7 @@ import tech.oxfordsemantic.jrdfox.logic.expression.{Resource, Term, Variable} | |||
| 35 | import uk.ac.ox.cs.rsacomb.approximation.Approximation | 35 | import uk.ac.ox.cs.rsacomb.approximation.Approximation |
| 36 | import uk.ac.ox.cs.rsacomb.converter._ | 36 | import uk.ac.ox.cs.rsacomb.converter._ |
| 37 | import uk.ac.ox.cs.rsacomb.suffix._ | 37 | import uk.ac.ox.cs.rsacomb.suffix._ |
| 38 | import uk.ac.ox.cs.rsacomb.util.{RDFoxUtil, RSA} | 38 | import uk.ac.ox.cs.rsacomb.util.{DataFactory, RDFoxUtil, RSA} |
| 39 | |||
| 40 | import uk.ac.ox.cs.rsacomb.RSAUtil | ||
| 41 | 39 | ||
| 42 | object Ontology { | 40 | object Ontology { |
| 43 | 41 | ||
| @@ -95,12 +93,13 @@ object Ontology { | |||
| 95 | unsafe: List[OWLObjectPropertyExpression], | 93 | unsafe: List[OWLObjectPropertyExpression], |
| 96 | skolem: SkolemStrategy, | 94 | skolem: SkolemStrategy, |
| 97 | suffix: RSASuffix | 95 | suffix: RSASuffix |
| 98 | ): Shards = | 96 | )(implicit fresh: DataFactory): Shards = |
| 99 | (expr, skolem) match { | 97 | (expr, skolem) match { |
| 100 | 98 | ||
| 101 | case (e: OWLObjectSomeValuesFrom, c: Constant) => { | 99 | case (e: OWLObjectSomeValuesFrom, c: Constant) => { |
| 102 | nodemap.update(c.iri.getIRI, c.axiom) | 100 | nodemap.update(c.iri.getIRI, c.axiom) |
| 103 | val (res, ext) = super.convert(e, term, unsafe, skolem, suffix) | 101 | val (res, ext) = |
| 102 | super.convert(e, term, unsafe, skolem, suffix)(fresh) | ||
| 104 | if (unsafe contains e.getProperty) | 103 | if (unsafe contains e.getProperty) |
| 105 | (RSA.PE(term, c.iri) :: RSA.U(c.iri) :: res, ext) | 104 | (RSA.PE(term, c.iri) :: RSA.U(c.iri) :: res, ext) |
| 106 | else | 105 | else |
| @@ -109,19 +108,20 @@ object Ontology { | |||
| 109 | 108 | ||
| 110 | case (e: OWLDataSomeValuesFrom, c: Constant) => { | 109 | case (e: OWLDataSomeValuesFrom, c: Constant) => { |
| 111 | nodemap.update(c.iri.getIRI, c.axiom) | 110 | nodemap.update(c.iri.getIRI, c.axiom) |
| 112 | val (res, ext) = super.convert(e, term, unsafe, skolem, suffix) | 111 | val (res, ext) = |
| 112 | super.convert(e, term, unsafe, skolem, suffix)(fresh) | ||
| 113 | if (unsafe contains e.getProperty) | 113 | if (unsafe contains e.getProperty) |
| 114 | (RSA.PE(term, c.iri) :: RSA.U(c.iri) :: res, ext) | 114 | (RSA.PE(term, c.iri) :: RSA.U(c.iri) :: res, ext) |
| 115 | else | 115 | else |
| 116 | (RSA.PE(term, c.iri) :: res, ext) | 116 | (RSA.PE(term, c.iri) :: res, ext) |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | case _ => super.convert(expr, term, unsafe, skolem, suffix) | 119 | case _ => super.convert(expr, term, unsafe, skolem, suffix)(fresh) |
| 120 | } | 120 | } |
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | /* Ontology convertion into LP rules */ | 123 | /* Ontology convertion into LP rules */ |
| 124 | val term = RSAUtil.genFreshVariable() | 124 | val term = Variable.create("X") |
| 125 | val result = axioms.map(a => | 125 | val result = axioms.map(a => |
| 126 | RSAConverter.convert(a, term, unsafe, new Constant(a), Empty) | 126 | RSAConverter.convert(a, term, unsafe, new Constant(a), Empty) |
| 127 | ) | 127 | ) |
| @@ -216,8 +216,6 @@ class Ontology(val axioms: List[OWLLogicalAxiom], val datafiles: List[File]) { | |||
| 216 | /** Simplify conversion between Java and Scala collections */ | 216 | /** Simplify conversion between Java and Scala collections */ |
| 217 | import uk.ac.ox.cs.rsacomb.implicits.JavaCollections._ | 217 | import uk.ac.ox.cs.rsacomb.implicits.JavaCollections._ |
| 218 | 218 | ||
| 219 | println(s"Axioms: ${axioms.length}") | ||
| 220 | |||
| 221 | /** OWLOntology based on input axioms | 219 | /** OWLOntology based on input axioms |
| 222 | * | 220 | * |
| 223 | * This is mainly used to instantiate a new reasoner to be used in | 221 | * This is mainly used to instantiate a new reasoner to be used in |
diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/package.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/package.scala new file mode 100644 index 0000000..53fa095 --- /dev/null +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/package.scala | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2020, 2021 KRR Oxford | ||
| 3 | * | ||
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | * you may not use this file except in compliance with the License. | ||
| 6 | * You may obtain a copy of the License at | ||
| 7 | * | ||
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | * | ||
| 10 | * Unless required by applicable law or agreed to in writing, software | ||
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | * See the License for the specific language governing permissions and | ||
| 14 | * limitations under the License. | ||
| 15 | */ | ||
| 16 | |||
| 17 | package uk.ac.ox.cs | ||
| 18 | package object rsacomb { | ||
| 19 | |||
| 20 | implicit val seed: util.DataFactory = util.DataFactory(0) | ||
| 21 | } | ||
diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/util/DataFactory.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/util/DataFactory.scala new file mode 100644 index 0000000..848c6b5 --- /dev/null +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/util/DataFactory.scala | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | package uk.ac.ox.cs.rsacomb.util | ||
| 2 | |||
| 3 | import org.semanticweb.owlapi.apibinding.OWLManager | ||
| 4 | import org.semanticweb.owlapi.model.OWLClass | ||
| 5 | import tech.oxfordsemantic.jrdfox.logic.expression.Variable | ||
| 6 | |||
| 7 | /** Simple fresh variable/class generator */ | ||
| 8 | object DataFactory { | ||
| 9 | |||
| 10 | /** Manager instance to interface with OWLAPI */ | ||
| 11 | private val manager = OWLManager.createOWLOntologyManager() | ||
| 12 | private val factory = manager.getOWLDataFactory() | ||
| 13 | |||
| 14 | def apply(counter: Integer = -1): DataFactory = new DataFactory(counter) | ||
| 15 | } | ||
| 16 | |||
| 17 | class DataFactory(private var counter: Integer) { | ||
| 18 | |||
| 19 | private def getNext(): Integer = { | ||
| 20 | counter += 1 | ||
| 21 | counter | ||
| 22 | } | ||
| 23 | |||
| 24 | def getVariable(): Variable = | ||
| 25 | Variable.create(f"I${this.getNext()}%05d") | ||
| 26 | |||
| 27 | def getOWLClass(): OWLClass = | ||
| 28 | DataFactory.factory.getOWLClass(s"X${this.getNext()}") | ||
| 29 | } | ||
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 abfe1ee..8d363e9 100644 --- a/src/test/scala/uk/ac/ox/cs/rsacomb/CanonicalModelSpec.scala +++ b/src/test/scala/uk/ac/ox/cs/rsacomb/CanonicalModelSpec.scala | |||
| @@ -31,6 +31,8 @@ import tech.oxfordsemantic.jrdfox.logic.expression.Variable | |||
| 31 | import scala.collection.JavaConverters._ | 31 | import scala.collection.JavaConverters._ |
| 32 | 32 | ||
| 33 | import uk.ac.ox.cs.rsacomb.RSAOntology | 33 | import uk.ac.ox.cs.rsacomb.RSAOntology |
| 34 | import uk.ac.ox.cs.rsacomb.approximation.Lowerbound | ||
| 35 | import uk.ac.ox.cs.rsacomb.ontology.Ontology | ||
| 34 | import uk.ac.ox.cs.rsacomb.converter.{SkolemStrategy, NoSkolem} | 36 | import uk.ac.ox.cs.rsacomb.converter.{SkolemStrategy, NoSkolem} |
| 35 | import uk.ac.ox.cs.rsacomb.suffix.Empty | 37 | import uk.ac.ox.cs.rsacomb.suffix.Empty |
| 36 | import uk.ac.ox.cs.rsacomb.util.{RDFoxUtil, RSA} | 38 | import uk.ac.ox.cs.rsacomb.util.{RDFoxUtil, RSA} |
| @@ -44,7 +46,7 @@ object Ontology1_CanonicalModelSpec { | |||
| 44 | IRI.create("http://example.com/rsa_example.owl#" + str) | 46 | IRI.create("http://example.com/rsa_example.owl#" + str) |
| 45 | 47 | ||
| 46 | val ontology_path: File = new File("examples/example1.ttl") | 48 | val ontology_path: File = new File("examples/example1.ttl") |
| 47 | val ontology = RSAOntology(ontology_path) | 49 | val ontology = Ontology(ontology_path, List()).approximate(new Lowerbound) |
| 48 | val program = ontology.canonicalModel | 50 | val program = ontology.canonicalModel |
| 49 | val converter = program.CanonicalModelConverter | 51 | val converter = program.CanonicalModelConverter |
| 50 | 52 | ||
| @@ -109,7 +111,7 @@ class Ontology1_CanonicalModelSpec | |||
| 109 | 111 | ||
| 110 | renderer.render(AsubClassOfD) should "be converted into a single Rule" in { | 112 | renderer.render(AsubClassOfD) should "be converted into a single Rule" in { |
| 111 | val term = Variable.create("X") | 113 | val term = Variable.create("X") |
| 112 | val unsafe = ontology.unsafeRoles | 114 | val unsafe = ontology.unsafe |
| 113 | val (facts, rules) = | 115 | val (facts, rules) = |
| 114 | converter.convert(AsubClassOfD, term, unsafe, NoSkolem, Empty) | 116 | converter.convert(AsubClassOfD, term, unsafe, NoSkolem, Empty) |
| 115 | facts shouldBe empty | 117 | facts shouldBe empty |
| @@ -119,7 +121,7 @@ class Ontology1_CanonicalModelSpec | |||
| 119 | // Role R // | 121 | // Role R // |
| 120 | 122 | ||
| 121 | renderer.render(roleR) should "be safe" in { | 123 | renderer.render(roleR) should "be safe" in { |
| 122 | ontology.unsafeRoles should not contain roleR | 124 | ontology.unsafe should not contain roleR |
| 123 | } | 125 | } |
| 124 | 126 | ||
| 125 | it should "have 3 elements in its conflict set" in { | 127 | it should "have 3 elements in its conflict set" in { |
| @@ -143,7 +145,7 @@ class Ontology1_CanonicalModelSpec | |||
| 143 | // Role S // | 145 | // Role S // |
| 144 | 146 | ||
| 145 | renderer.render(roleS) should "be safe" in { | 147 | renderer.render(roleS) should "be safe" in { |
| 146 | ontology.unsafeRoles should not contain roleS | 148 | ontology.unsafe should not contain roleS |
| 147 | } | 149 | } |
| 148 | 150 | ||
| 149 | it should "have 3 elements in its conflict set" in { | 151 | it should "have 3 elements in its conflict set" in { |
| @@ -169,14 +171,14 @@ class Ontology1_CanonicalModelSpec | |||
| 169 | // S⁻ | 171 | // S⁻ |
| 170 | 172 | ||
| 171 | renderer.render(roleS_inv) should "be unsafe" in { | 173 | renderer.render(roleS_inv) should "be unsafe" in { |
| 172 | ontology.unsafeRoles should contain(roleS_inv) | 174 | ontology.unsafe should contain(roleS_inv) |
| 173 | } | 175 | } |
| 174 | 176 | ||
| 175 | renderer.render( | 177 | renderer.render( |
| 176 | AsomeValuesFromSiC | 178 | AsomeValuesFromSiC |
| 177 | ) should "produce 1 rule" ignore { | 179 | ) should "produce 1 rule" ignore { |
| 178 | val term = Variable.create("X") | 180 | val term = Variable.create("X") |
| 179 | val unsafe = ontology.unsafeRoles | 181 | val unsafe = ontology.unsafe |
| 180 | val (facts, rules) = | 182 | val (facts, rules) = |
| 181 | converter.convert(AsomeValuesFromSiC, term, unsafe, NoSkolem, Empty) | 183 | converter.convert(AsomeValuesFromSiC, term, unsafe, NoSkolem, Empty) |
| 182 | facts shouldBe empty | 184 | facts shouldBe empty |
| @@ -200,7 +202,7 @@ class Ontology1_CanonicalModelSpec | |||
| 200 | // Rule 2 provides 0 rules | 202 | // Rule 2 provides 0 rules |
| 201 | // Rule 3 provides 48 rule (split in 2) | 203 | // Rule 3 provides 48 rule (split in 2) |
| 202 | val term = Variable.create("X") | 204 | val term = Variable.create("X") |
| 203 | val unsafe = ontology.unsafeRoles | 205 | val unsafe = ontology.unsafe |
| 204 | val (facts, rules) = | 206 | val (facts, rules) = |
| 205 | converter.convert(DsomeValuesFromRB, term, unsafe, NoSkolem, Empty) | 207 | converter.convert(DsomeValuesFromRB, term, unsafe, NoSkolem, Empty) |
| 206 | facts should have length 48 | 208 | facts should have length 48 |
| @@ -225,7 +227,7 @@ class Ontology1_CanonicalModelSpec | |||
| 225 | // Rule 3 provides 32 rule (split in 2) | 227 | // Rule 3 provides 32 rule (split in 2) |
| 226 | // Then (1*2 + 32) + (0) + (32*2) = 98 | 228 | // Then (1*2 + 32) + (0) + (32*2) = 98 |
| 227 | val term = Variable.create("X") | 229 | val term = Variable.create("X") |
| 228 | val unsafe = ontology.unsafeRoles | 230 | val unsafe = ontology.unsafe |
| 229 | val (facts, rules) = | 231 | val (facts, rules) = |
| 230 | converter.convert(BsomeValuesFromSD, term, unsafe, NoSkolem, Empty) | 232 | converter.convert(BsomeValuesFromSD, term, unsafe, NoSkolem, Empty) |
| 231 | facts should have length 32 | 233 | facts should have length 32 |
| @@ -236,7 +238,7 @@ class Ontology1_CanonicalModelSpec | |||
| 236 | SsubPropertyOfT | 238 | SsubPropertyOfT |
| 237 | ) should "produce 3 rules" in { | 239 | ) should "produce 3 rules" in { |
| 238 | val term = Variable.create("X") | 240 | val term = Variable.create("X") |
| 239 | val unsafe = ontology.unsafeRoles | 241 | val unsafe = ontology.unsafe |
| 240 | val (facts, rules) = | 242 | val (facts, rules) = |
| 241 | converter.convert(SsubPropertyOfT, term, unsafe, NoSkolem, Empty) | 243 | converter.convert(SsubPropertyOfT, term, unsafe, NoSkolem, Empty) |
| 242 | facts shouldBe empty | 244 | facts shouldBe empty |
| @@ -245,167 +247,167 @@ class Ontology1_CanonicalModelSpec | |||
| 245 | 247 | ||
| 246 | } | 248 | } |
| 247 | 249 | ||
| 248 | object Ontology2_CanonicalModelSpec { | 250 | // object Ontology2_CanonicalModelSpec { |
| 249 | 251 | ||
| 250 | /* Renderer to display OWL Axioms with DL syntax*/ | 252 | // /* Renderer to display OWL Axioms with DL syntax*/ |
| 251 | val renderer = new DLSyntaxObjectRenderer() | 253 | // val renderer = new DLSyntaxObjectRenderer() |
| 252 | 254 | ||
| 253 | def base(str: String): IRI = | 255 | // def base(str: String): IRI = |
| 254 | IRI.create("http://example.com/rsa_example.owl#" + str) | 256 | // IRI.create("http://example.com/rsa_example.owl#" + str) |
| 255 | 257 | ||
| 256 | val ontology_path: File = new File("examples/example2.owl") | 258 | // val ontology_path: File = new File("examples/example2.owl") |
| 257 | val ontology = RSAOntology(ontology_path) | 259 | // val ontology = Ontology(ontology_path, List()).approximate(new Lowerbound) |
| 258 | val program = ontology.canonicalModel | 260 | // val program = ontology.canonicalModel |
| 259 | val converter = program.CanonicalModelConverter | 261 | // val converter = program.CanonicalModelConverter |
| 260 | 262 | ||
| 261 | val roleR = new OWLObjectPropertyImpl(base("R")) | 263 | // val roleR = new OWLObjectPropertyImpl(base("R")) |
| 262 | val roleS = new OWLObjectPropertyImpl(base("S")) | 264 | // val roleS = new OWLObjectPropertyImpl(base("S")) |
| 263 | val roleT = new OWLObjectPropertyImpl(base("T")) | 265 | // val roleT = new OWLObjectPropertyImpl(base("T")) |
| 264 | val roleP = new OWLObjectPropertyImpl(base("P")) | 266 | // val roleP = new OWLObjectPropertyImpl(base("P")) |
| 265 | val roleR_inv = roleR.getInverseProperty() | 267 | // val roleR_inv = roleR.getInverseProperty() |
| 266 | val roleS_inv = roleS.getInverseProperty() | 268 | // val roleS_inv = roleS.getInverseProperty() |
| 267 | val roleT_inv = roleT.getInverseProperty() | 269 | // val roleT_inv = roleT.getInverseProperty() |
| 268 | val roleP_inv = roleP.getInverseProperty() | 270 | // val roleP_inv = roleP.getInverseProperty() |
| 269 | 271 | ||
| 270 | val AsomeValuesFromRB = new OWLSubClassOfAxiomImpl( | 272 | // val AsomeValuesFromRB = new OWLSubClassOfAxiomImpl( |
| 271 | new OWLClassImpl(base("A")), | 273 | // new OWLClassImpl(base("A")), |
| 272 | new OWLObjectSomeValuesFromImpl( | 274 | // new OWLObjectSomeValuesFromImpl( |
| 273 | roleR, | 275 | // roleR, |
| 274 | new OWLClassImpl(base("B")) | 276 | // new OWLClassImpl(base("B")) |
| 275 | ), | 277 | // ), |
| 276 | Seq().asJava | 278 | // Seq().asJava |
| 277 | ) | 279 | // ) |
| 278 | 280 | ||
| 279 | val BsomeValuesFromSC = new OWLSubClassOfAxiomImpl( | 281 | // val BsomeValuesFromSC = new OWLSubClassOfAxiomImpl( |
| 280 | new OWLClassImpl(base("B")), | 282 | // new OWLClassImpl(base("B")), |
| 281 | new OWLObjectSomeValuesFromImpl( | 283 | // new OWLObjectSomeValuesFromImpl( |
| 282 | roleS, | 284 | // roleS, |
| 283 | new OWLClassImpl(base("C")) | 285 | // new OWLClassImpl(base("C")) |
| 284 | ), | 286 | // ), |
| 285 | Seq().asJava | 287 | // Seq().asJava |
| 286 | ) | 288 | // ) |
| 287 | 289 | ||
| 288 | val CsomeValuesFromTD = new OWLSubClassOfAxiomImpl( | 290 | // val CsomeValuesFromTD = new OWLSubClassOfAxiomImpl( |
| 289 | new OWLClassImpl(base("C")), | 291 | // new OWLClassImpl(base("C")), |
| 290 | new OWLObjectSomeValuesFromImpl( | 292 | // new OWLObjectSomeValuesFromImpl( |
| 291 | roleT, | 293 | // roleT, |
| 292 | new OWLClassImpl(base("D")) | 294 | // new OWLClassImpl(base("D")) |
| 293 | ), | 295 | // ), |
| 294 | Seq().asJava | 296 | // Seq().asJava |
| 295 | ) | 297 | // ) |
| 296 | 298 | ||
| 297 | val DsomeValuesFromPA = new OWLSubClassOfAxiomImpl( | 299 | // val DsomeValuesFromPA = new OWLSubClassOfAxiomImpl( |
| 298 | new OWLClassImpl(base("D")), | 300 | // new OWLClassImpl(base("D")), |
| 299 | new OWLObjectSomeValuesFromImpl( | 301 | // new OWLObjectSomeValuesFromImpl( |
| 300 | roleP, | 302 | // roleP, |
| 301 | new OWLClassImpl(base("A")) | 303 | // new OWLClassImpl(base("A")) |
| 302 | ), | 304 | // ), |
| 303 | Seq().asJava | 305 | // Seq().asJava |
| 304 | ) | 306 | // ) |
| 305 | 307 | ||
| 306 | } | 308 | // } |
| 307 | 309 | ||
| 308 | class Ontology2_CanonicalModelSpec | 310 | // class Ontology2_CanonicalModelSpec |
| 309 | extends AnyFlatSpec | 311 | // extends AnyFlatSpec |
| 310 | with Matchers | 312 | // with Matchers |
| 311 | with LoneElement { | 313 | // with LoneElement { |
| 312 | 314 | ||
| 313 | import Ontology2_CanonicalModelSpec._ | 315 | // import Ontology2_CanonicalModelSpec._ |
| 314 | 316 | ||
| 315 | "The program generated from Example #1" should "not be empty" in { | 317 | // "The program generated from Example #1" should "not be empty" in { |
| 316 | program.rules should not be empty | 318 | // program.rules should not be empty |
| 317 | } | 319 | // } |
| 318 | 320 | ||
| 319 | // Role R // | 321 | // // Role R // |
| 320 | 322 | ||
| 321 | renderer.render(roleR) should "be unsafe" in { | 323 | // renderer.render(roleR) should "be unsafe" in { |
| 322 | ontology.unsafeRoles should contain(roleR) | 324 | // ontology.unsafe should contain(roleR) |
| 323 | } | 325 | // } |
| 324 | 326 | ||
| 325 | it should "have only its inverse in its conflict set" in { | 327 | // it should "have only its inverse in its conflict set" in { |
| 326 | ontology.confl(roleR).loneElement shouldBe roleR_inv | 328 | // ontology.confl(roleR).loneElement shouldBe roleR_inv |
| 327 | } | 329 | // } |
| 328 | 330 | ||
| 329 | // Role S // | 331 | // // Role S // |
| 330 | 332 | ||
| 331 | renderer.render(roleS) should "be unsafe" in { | 333 | // renderer.render(roleS) should "be unsafe" in { |
| 332 | ontology.unsafeRoles should contain(roleS) | 334 | // ontology.unsafe should contain(roleS) |
| 333 | } | 335 | // } |
| 334 | 336 | ||
| 335 | it should "have only its inverse in its conflict set" in { | 337 | // it should "have only its inverse in its conflict set" in { |
| 336 | ontology.confl(roleS).loneElement shouldBe roleS_inv | 338 | // ontology.confl(roleS).loneElement shouldBe roleS_inv |
| 337 | } | 339 | // } |
| 338 | 340 | ||
| 339 | // Role T // | 341 | // // Role T // |
| 340 | 342 | ||
| 341 | renderer.render(roleT) should "be unsafe" in { | 343 | // renderer.render(roleT) should "be unsafe" in { |
| 342 | ontology.unsafeRoles should contain(roleT) | 344 | // ontology.unsafe should contain(roleT) |
| 343 | } | 345 | // } |
| 344 | 346 | ||
| 345 | it should "have only its inverse in its conflict set" in { | 347 | // it should "have only its inverse in its conflict set" in { |
| 346 | ontology.confl(roleT).loneElement shouldBe roleT_inv | 348 | // ontology.confl(roleT).loneElement shouldBe roleT_inv |
| 347 | } | 349 | // } |
| 348 | 350 | ||
| 349 | // Role P // | 351 | // // Role P // |
| 350 | 352 | ||
| 351 | renderer.render(roleP) should "be unsafe" in { | 353 | // renderer.render(roleP) should "be unsafe" in { |
| 352 | ontology.unsafeRoles should contain(roleP) | 354 | // ontology.unsafe should contain(roleP) |
| 353 | } | 355 | // } |
| 354 | 356 | ||
| 355 | it should "have only its inverse in its conflict set" in { | 357 | // it should "have only its inverse in its conflict set" in { |
| 356 | ontology.confl(roleP).loneElement shouldBe roleP_inv | 358 | // ontology.confl(roleP).loneElement shouldBe roleP_inv |
| 357 | } | 359 | // } |
| 358 | 360 | ||
| 359 | // A ⊑ ∃ R.B | 361 | // // A ⊑ ∃ R.B |
| 360 | 362 | ||
| 361 | renderer.render( | 363 | // renderer.render( |
| 362 | AsomeValuesFromRB | 364 | // AsomeValuesFromRB |
| 363 | ) should "produce 1 rule" in { | 365 | // ) should "produce 1 rule" in { |
| 364 | val term = Variable.create("X") | 366 | // val term = Variable.create("X") |
| 365 | val unsafe = ontology.unsafeRoles | 367 | // val unsafe = ontology.unsafe |
| 366 | val (facts, rules) = | 368 | // val (facts, rules) = |
| 367 | converter.convert(AsomeValuesFromRB, term, unsafe, NoSkolem, Empty) | 369 | // converter.convert(AsomeValuesFromRB, term, unsafe, NoSkolem, Empty) |
| 368 | facts shouldBe empty | 370 | // facts shouldBe empty |
| 369 | rules should have length 1 | 371 | // rules should have length 1 |
| 370 | } | 372 | // } |
| 371 | 373 | ||
| 372 | // B ⊑ ∃ S.C | 374 | // // B ⊑ ∃ S.C |
| 373 | 375 | ||
| 374 | renderer.render( | 376 | // renderer.render( |
| 375 | BsomeValuesFromSC | 377 | // BsomeValuesFromSC |
| 376 | ) should "produce 1 rule" in { | 378 | // ) should "produce 1 rule" in { |
| 377 | val term = Variable.create("X") | 379 | // val term = Variable.create("X") |
| 378 | val unsafe = ontology.unsafeRoles | 380 | // val unsafe = ontology.unsafe |
| 379 | val (facts, rules) = | 381 | // val (facts, rules) = |
| 380 | converter.convert(BsomeValuesFromSC, term, unsafe, NoSkolem, Empty) | 382 | // converter.convert(BsomeValuesFromSC, term, unsafe, NoSkolem, Empty) |
| 381 | facts shouldBe empty | 383 | // facts shouldBe empty |
| 382 | rules should have length 1 | 384 | // rules should have length 1 |
| 383 | } | 385 | // } |
| 384 | 386 | ||
| 385 | // C ⊑ ∃ T.D | 387 | // // C ⊑ ∃ T.D |
| 386 | 388 | ||
| 387 | renderer.render( | 389 | // renderer.render( |
| 388 | CsomeValuesFromTD | 390 | // CsomeValuesFromTD |
| 389 | ) should "produce 1 rule" in { | 391 | // ) should "produce 1 rule" in { |
| 390 | val term = Variable.create("X") | 392 | // val term = Variable.create("X") |
| 391 | val unsafe = ontology.unsafeRoles | 393 | // val unsafe = ontology.unsafe |
| 392 | val (facts, rules) = | 394 | // val (facts, rules) = |
| 393 | converter.convert(CsomeValuesFromTD, term, unsafe, NoSkolem, Empty) | 395 | // converter.convert(CsomeValuesFromTD, term, unsafe, NoSkolem, Empty) |
| 394 | facts shouldBe empty | 396 | // facts shouldBe empty |
| 395 | rules should have length 1 | 397 | // rules should have length 1 |
| 396 | } | 398 | // } |
| 397 | 399 | ||
| 398 | // D ⊑ ∃ P.A | 400 | // // D ⊑ ∃ P.A |
| 399 | 401 | ||
| 400 | renderer.render( | 402 | // renderer.render( |
| 401 | DsomeValuesFromPA | 403 | // DsomeValuesFromPA |
| 402 | ) should "produce 1 rule" in { | 404 | // ) should "produce 1 rule" in { |
| 403 | val term = Variable.create("X") | 405 | // val term = Variable.create("X") |
| 404 | val unsafe = ontology.unsafeRoles | 406 | // val unsafe = ontology.unsafe |
| 405 | val (facts, rules) = | 407 | // val (facts, rules) = |
| 406 | converter.convert(DsomeValuesFromPA, term, unsafe, NoSkolem, Empty) | 408 | // converter.convert(DsomeValuesFromPA, term, unsafe, NoSkolem, Empty) |
| 407 | facts shouldBe empty | 409 | // facts shouldBe empty |
| 408 | rules should have length 1 | 410 | // rules should have length 1 |
| 409 | } | 411 | // } |
| 410 | 412 | ||
| 411 | } | 413 | // } |
diff --git a/src/test/scala/uk/ac/ox/cs/rsacomb/SuiteAll.scala b/src/test/scala/uk/ac/ox/cs/rsacomb/SuiteAll.scala index 1df0757..9653546 100644 --- a/src/test/scala/uk/ac/ox/cs/rsacomb/SuiteAll.scala +++ b/src/test/scala/uk/ac/ox/cs/rsacomb/SuiteAll.scala | |||
| @@ -32,7 +32,7 @@ import uk.ac.ox.cs.rsacomb.sparql.{ | |||
| 32 | class SuiteAll | 32 | class SuiteAll |
| 33 | extends Suites( | 33 | extends Suites( |
| 34 | new Ontology1_CanonicalModelSpec, | 34 | new Ontology1_CanonicalModelSpec, |
| 35 | new Ontology2_CanonicalModelSpec, | 35 | //new Ontology2_CanonicalModelSpec, |
| 36 | new NaiveFilteringProgramSpec, | 36 | new NaiveFilteringProgramSpec, |
| 37 | new OWLAxiomSpec, | 37 | new OWLAxiomSpec, |
| 38 | new OWLClassSpec, | 38 | new OWLClassSpec, |
diff --git a/src/test/scala/uk/ac/ox/cs/rsacomb/converter/NormalizerSpec.scala b/src/test/scala/uk/ac/ox/cs/rsacomb/converter/NormalizerSpec.scala index 7285df2..5047e12 100644 --- a/src/test/scala/uk/ac/ox/cs/rsacomb/converter/NormalizerSpec.scala +++ b/src/test/scala/uk/ac/ox/cs/rsacomb/converter/NormalizerSpec.scala | |||
| @@ -27,6 +27,7 @@ import tech.oxfordsemantic.jrdfox.logic.expression.{Variable, IRI} | |||
| 27 | import uk.ac.ox.cs.rsacomb.converter.RDFoxConverter | 27 | import uk.ac.ox.cs.rsacomb.converter.RDFoxConverter |
| 28 | import uk.ac.ox.cs.rsacomb.suffix.{Empty, Forward, Backward, Inverse} | 28 | import uk.ac.ox.cs.rsacomb.suffix.{Empty, Forward, Backward, Inverse} |
| 29 | import uk.ac.ox.cs.rsacomb.converter.{Normalizer, SkolemStrategy, NoSkolem} | 29 | import uk.ac.ox.cs.rsacomb.converter.{Normalizer, SkolemStrategy, NoSkolem} |
| 30 | import uk.ac.ox.cs.rsacomb.util.DataFactory | ||
| 30 | 31 | ||
| 31 | object NormalizerSpec { | 32 | object NormalizerSpec { |
| 32 | val manager = OWLManager.createOWLOntologyManager() | 33 | val manager = OWLManager.createOWLOntologyManager() |
| @@ -89,27 +90,58 @@ class NormalizerSpec extends AnyFlatSpec with Matchers with LoneElement { | |||
| 89 | ).flatMap(normalizer.normalize) | 90 | ).flatMap(normalizer.normalize) |
| 90 | } | 91 | } |
| 91 | 92 | ||
| 92 | "Disjunction on the rhs" should "be shifted" in { | 93 | "A c \\exists R . D" should "be normalised to { A c \\exists R . C, C c D } if D is not a concept name" in { |
| 93 | def cls(n: Int) = factory.getOWLClass(s"_:class$n") | 94 | val seed = 42 |
| 94 | val axiom1 = | 95 | val test = normalizer.normalize( |
| 95 | factory.getOWLSubClassOfAxiom( | 96 | factory |
| 96 | factory.getOWLObjectIntersectionOf(cls(1), cls(2), cls(3)), | 97 | .getOWLSubClassOfAxiom( |
| 97 | factory.getOWLObjectUnionOf(cls(4), cls(5)) | 98 | factory.getOWLClass("A"), |
| 98 | ) | 99 | factory.getOWLObjectSomeValuesFrom( |
| 99 | val axiom2 = | 100 | factory.getOWLObjectProperty("R"), |
| 100 | factory.getOWLSubClassOfAxiom( | 101 | factory.getOWLObjectIntersectionOf( |
| 101 | cls(1), | 102 | factory.getOWLClass("D1"), |
| 102 | factory.getOWLObjectUnionOf(cls(2), cls(3), cls(4)) | 103 | factory.getOWLClass("D2") |
| 103 | ) | 104 | ) |
| 104 | val axiom3 = | 105 | ) |
| 105 | factory.getOWLSubClassOfAxiom( | 106 | ) |
| 106 | factory.getOWLObjectIntersectionOf(cls(1), cls(2), cls(3)), | 107 | )(DataFactory(seed)) |
| 107 | factory.getOWLObjectUnionOf(cls(4)) | 108 | val cls = DataFactory(seed).getOWLClass |
| 108 | ) | 109 | val result = List( |
| 109 | normalizer.normalize(axiom1) should have length 5 | 110 | factory |
| 110 | normalizer.normalize(axiom2) should have length 5 | 111 | .getOWLSubClassOfAxiom( |
| 111 | normalizer.normalize(axiom3) should have length 4 | 112 | factory.getOWLClass("A"), |
| 113 | factory.getOWLObjectSomeValuesFrom( | ||
| 114 | factory.getOWLObjectProperty("R"), | ||
| 115 | cls | ||
| 116 | ) | ||
| 117 | ), | ||
| 118 | factory.getOWLSubClassOfAxiom(cls, factory.getOWLClass("D1")), | ||
| 119 | factory.getOWLSubClassOfAxiom(cls, factory.getOWLClass("D2")) | ||
| 120 | ) | ||
| 121 | test should contain theSameElementsAs result | ||
| 112 | } | 122 | } |
| 123 | |||
| 124 | // "Disjunction on the rhs" should "be shifted" in { | ||
| 125 | // def cls(n: Int) = factory.getOWLClass(s"_:class$n") | ||
| 126 | // val axiom1 = | ||
| 127 | // factory.getOWLSubClassOfAxiom( | ||
| 128 | // factory.getOWLObjectIntersectionOf(cls(1), cls(2), cls(3)), | ||
| 129 | // factory.getOWLObjectUnionOf(cls(4), cls(5)) | ||
| 130 | // ) | ||
| 131 | // val axiom2 = | ||
| 132 | // factory.getOWLSubClassOfAxiom( | ||
| 133 | // cls(1), | ||
| 134 | // factory.getOWLObjectUnionOf(cls(2), cls(3), cls(4)) | ||
| 135 | // ) | ||
| 136 | // val axiom3 = | ||
| 137 | // factory.getOWLSubClassOfAxiom( | ||
| 138 | // factory.getOWLObjectIntersectionOf(cls(1), cls(2), cls(3)), | ||
| 139 | // factory.getOWLObjectUnionOf(cls(4)) | ||
| 140 | // ) | ||
| 141 | // normalizer.normalize(axiom1) should have length 5 | ||
| 142 | // normalizer.normalize(axiom2) should have length 5 | ||
| 143 | // normalizer.normalize(axiom3) should have length 4 | ||
| 144 | // } | ||
| 113 | //"A class name" should "be converted into a single atom" in { | 145 | //"A class name" should "be converted into a single atom" in { |
| 114 | // val cls = factory.getOWLClass(iriString0) | 146 | // val cls = factory.getOWLClass(iriString0) |
| 115 | // val atom = TupleTableAtom.rdf(term0, IRI.RDF_TYPE, IRI.create(iriString0)) | 147 | // val atom = TupleTableAtom.rdf(term0, IRI.RDF_TYPE, IRI.create(iriString0)) |
