diff options
| author | Federico Igne <federico.igne@cs.ox.ac.uk> | 2020-10-05 18:51:52 +0200 |
|---|---|---|
| committer | Federico Igne <federico.igne@cs.ox.ac.uk> | 2020-10-05 18:51:52 +0200 |
| commit | 4cae6afabb48cf5f77d9826881f7e41ffb57baaf (patch) | |
| tree | 28a916c97513a3ebc833e32591289d6d1042c40c | |
| parent | 78966faa10b2ca4f93724e062ba6984a4a4ba956 (diff) | |
| download | RSAComb-4cae6afabb48cf5f77d9826881f7e41ffb57baaf.tar.gz RSAComb-4cae6afabb48cf5f77d9826881f7e41ffb57baaf.zip | |
Add generation of rules for safe T5 axioms
| -rw-r--r-- | src/main/scala/rsacomb/CanonicalModel.scala | 143 |
1 files changed, 139 insertions, 4 deletions
diff --git a/src/main/scala/rsacomb/CanonicalModel.scala b/src/main/scala/rsacomb/CanonicalModel.scala index 162bea1..c957940 100644 --- a/src/main/scala/rsacomb/CanonicalModel.scala +++ b/src/main/scala/rsacomb/CanonicalModel.scala | |||
| @@ -1,20 +1,32 @@ | |||
| 1 | package rsacomb | 1 | package rsacomb |
| 2 | 2 | ||
| 3 | import org.semanticweb.owlapi.model.{ | 3 | import org.semanticweb.owlapi.model.{ |
| 4 | OWLOntology, | ||
| 5 | OWLClass, | ||
| 4 | OWLSubObjectPropertyOfAxiom, | 6 | OWLSubObjectPropertyOfAxiom, |
| 5 | OWLSubClassOfAxiom, | 7 | OWLSubClassOfAxiom, |
| 6 | OWLObjectProperty, | 8 | OWLObjectProperty, |
| 7 | OWLObjectPropertyExpression | 9 | OWLObjectPropertyExpression, |
| 10 | OWLObjectSomeValuesFrom | ||
| 8 | } | 11 | } |
| 9 | import tech.oxfordsemantic.jrdfox.logic.{IRI, Atom, Rule, Term, Variable} | 12 | import tech.oxfordsemantic.jrdfox.logic.{ |
| 13 | IRI, | ||
| 14 | BodyFormula, | ||
| 15 | Atom, | ||
| 16 | Rule, | ||
| 17 | Term, | ||
| 18 | Variable | ||
| 19 | } | ||
| 20 | import scala.collection.JavaConverters._ | ||
| 10 | 21 | ||
| 11 | object ProgramGenerator { | 22 | object ProgramGenerator { |
| 12 | 23 | ||
| 13 | def apply( | 24 | def apply( |
| 25 | ontology: OWLOntology, | ||
| 14 | term: Term, | 26 | term: Term, |
| 15 | unsafe: List[OWLObjectPropertyExpression] = List() | 27 | unsafe: List[OWLObjectPropertyExpression] = List() |
| 16 | ): RDFoxAxiomConverter = | 28 | ): RDFoxAxiomConverter = |
| 17 | new ProgramGenerator(term, unsafe) | 29 | new ProgramGenerator(ontology, term, unsafe) |
| 18 | 30 | ||
| 19 | def generateRoleRules( | 31 | def generateRoleRules( |
| 20 | roles: List[OWLObjectPropertyExpression] | 32 | roles: List[OWLObjectPropertyExpression] |
| @@ -57,11 +69,131 @@ object ProgramGenerator { | |||
| 57 | } | 69 | } |
| 58 | 70 | ||
| 59 | class ProgramGenerator( | 71 | class ProgramGenerator( |
| 72 | ontology: OWLOntology, | ||
| 60 | term: Term, | 73 | term: Term, |
| 61 | unsafe: List[OWLObjectPropertyExpression] | 74 | unsafe: List[OWLObjectPropertyExpression] |
| 62 | ) extends RDFoxAxiomConverter(term, unsafe, SkolemStrategy.None, RSASuffix.None) | 75 | ) extends RDFoxAxiomConverter(term, unsafe, SkolemStrategy.None, RSASuffix.None) |
| 76 | with RSAOntology | ||
| 63 | with RSAAxiom { | 77 | with RSAAxiom { |
| 64 | 78 | ||
| 79 | import RDFoxUtil._ | ||
| 80 | |||
| 81 | def rules1(axiom: OWLSubClassOfAxiom): (List[Rule], List[Atom]) = { | ||
| 82 | val unfold = ontology.cycle(axiom).toList | ||
| 83 | // Fresh Variables | ||
| 84 | val v0 = IRI.create("v0_" ++ axiom.hashCode.toString) | ||
| 85 | val varX = Variable.create("x") | ||
| 86 | // Predicates | ||
| 87 | val atomA: Atom = { | ||
| 88 | val cls = axiom.getSubClass.asInstanceOf[OWLClass].getIRI | ||
| 89 | Atom.rdf(varX, IRI.RDF_TYPE, cls) | ||
| 90 | } | ||
| 91 | def notIn(t: Term): Atom = { | ||
| 92 | Atom.rdf( | ||
| 93 | t, | ||
| 94 | RSA.internal("notIn"), | ||
| 95 | RSA.internal(unfold.hashCode.toString) | ||
| 96 | ) | ||
| 97 | } | ||
| 98 | val roleRf: Atom = { | ||
| 99 | val visitor = | ||
| 100 | new RDFoxPropertyExprConverter(varX, v0, RSASuffix.Forward) | ||
| 101 | axiom.getSuperClass | ||
| 102 | .asInstanceOf[OWLObjectSomeValuesFrom] | ||
| 103 | .getProperty | ||
| 104 | .accept(visitor) | ||
| 105 | .head | ||
| 106 | } | ||
| 107 | val atomB: Atom = { | ||
| 108 | val cls = axiom.getSuperClass | ||
| 109 | .asInstanceOf[OWLObjectSomeValuesFrom] | ||
| 110 | .getFiller | ||
| 111 | .asInstanceOf[OWLClass] | ||
| 112 | .getIRI | ||
| 113 | Atom.rdf(v0, IRI.RDF_TYPE, cls) | ||
| 114 | } | ||
| 115 | ( | ||
| 116 | List( | ||
| 117 | Rule.create(roleRf, atomA, notIn(varX)), | ||
| 118 | Rule.create(atomB, atomA, notIn(varX)) | ||
| 119 | ), | ||
| 120 | unfold map notIn | ||
| 121 | ) | ||
| 122 | } | ||
| 123 | |||
| 124 | def rules2(axiom: OWLSubClassOfAxiom): List[Rule] = { | ||
| 125 | val roleR = | ||
| 126 | axiom.getSuperClass | ||
| 127 | .asInstanceOf[OWLObjectSomeValuesFrom] | ||
| 128 | .getProperty | ||
| 129 | if (ontology.confl(roleR) contains roleR) { | ||
| 130 | // Fresh Variables | ||
| 131 | val v0 = IRI.create("v0_" ++ axiom.hashCode.toString) | ||
| 132 | val v1 = IRI.create("v1_" ++ axiom.hashCode.toString) | ||
| 133 | val v2 = IRI.create("v2_" ++ axiom.hashCode.toString) | ||
| 134 | // Predicates | ||
| 135 | def atomA(t: Term): Atom = { | ||
| 136 | val cls = axiom.getSubClass.asInstanceOf[OWLClass].getIRI | ||
| 137 | Atom.rdf(t, IRI.RDF_TYPE, cls) | ||
| 138 | } | ||
| 139 | def roleRf(t1: Term, t2: Term): Atom = { | ||
| 140 | val visitor = new RDFoxPropertyExprConverter(t1, t2, RSASuffix.Forward) | ||
| 141 | roleR.accept(visitor).head | ||
| 142 | } | ||
| 143 | def atomB(t: Term): Atom = { | ||
| 144 | val cls = axiom.getSuperClass | ||
| 145 | .asInstanceOf[OWLObjectSomeValuesFrom] | ||
| 146 | .getFiller | ||
| 147 | .asInstanceOf[OWLClass] | ||
| 148 | .getIRI | ||
| 149 | Atom.rdf(t, IRI.RDF_TYPE, cls) | ||
| 150 | } | ||
| 151 | //Rules | ||
| 152 | List( | ||
| 153 | Rule.create(roleRf(v0, v1), atomA(v0)), | ||
| 154 | Rule.create(atomB(v1), atomA(v0)), | ||
| 155 | Rule.create(roleRf(v1, v2), atomA(v1)), | ||
| 156 | Rule.create(atomB(v2), atomA(v1)) | ||
| 157 | ) | ||
| 158 | } else { | ||
| 159 | List() | ||
| 160 | } | ||
| 161 | } | ||
| 162 | |||
| 163 | def rules3(axiom: OWLSubClassOfAxiom): List[Rule] = { | ||
| 164 | val cycle = ontology.cycle(axiom).toList | ||
| 165 | val roleR = | ||
| 166 | axiom.getSuperClass | ||
| 167 | .asInstanceOf[OWLObjectSomeValuesFrom] | ||
| 168 | .getProperty | ||
| 169 | // Fresh Variables | ||
| 170 | val v1 = IRI.create("v1_" ++ axiom.hashCode.toString) | ||
| 171 | // Predicates | ||
| 172 | def atomA(t: Term): Atom = { | ||
| 173 | val cls = axiom.getSubClass.asInstanceOf[OWLClass].getIRI | ||
| 174 | Atom.rdf(t, IRI.RDF_TYPE, cls) | ||
| 175 | } | ||
| 176 | def roleRf(t: Term): Atom = { | ||
| 177 | val visitor = | ||
| 178 | new RDFoxPropertyExprConverter(t, v1, RSASuffix.Forward) | ||
| 179 | roleR.accept(visitor).head | ||
| 180 | } | ||
| 181 | val atomB: Atom = { | ||
| 182 | val cls = axiom.getSuperClass | ||
| 183 | .asInstanceOf[OWLObjectSomeValuesFrom] | ||
| 184 | .getFiller | ||
| 185 | .asInstanceOf[OWLClass] | ||
| 186 | .getIRI | ||
| 187 | Atom.rdf(v1, IRI.RDF_TYPE, cls) | ||
| 188 | } | ||
| 189 | cycle.flatMap { x => | ||
| 190 | List( | ||
| 191 | Rule.create(roleRf(x), atomA(x)), | ||
| 192 | Rule.create(atomB, atomA(x)) | ||
| 193 | ) | ||
| 194 | } | ||
| 195 | } | ||
| 196 | |||
| 65 | override def visit(axiom: OWLSubClassOfAxiom): List[Rule] = { | 197 | override def visit(axiom: OWLSubClassOfAxiom): List[Rule] = { |
| 66 | if (axiom.isT5) { | 198 | if (axiom.isT5) { |
| 67 | // TODO: get role in T5 axiom | 199 | // TODO: get role in T5 axiom |
| @@ -77,7 +209,10 @@ class ProgramGenerator( | |||
| 77 | ) | 209 | ) |
| 78 | axiom.accept(visitor) | 210 | axiom.accept(visitor) |
| 79 | } else { | 211 | } else { |
| 80 | List() | 212 | val (r1, f1) = rules1(axiom) |
| 213 | val r2 = rules2(axiom) | ||
| 214 | val r3 = rules3(axiom) | ||
| 215 | r1 ++ r2 ++ r3 | ||
| 81 | } | 216 | } |
| 82 | } else { | 217 | } else { |
| 83 | // Fallback to standard OWL to LP translation | 218 | // Fallback to standard OWL to LP translation |
