diff options
author | Federico Igne <federico.igne@cs.ox.ac.uk> | 2020-10-06 19:15:17 +0200 |
---|---|---|
committer | Federico Igne <federico.igne@cs.ox.ac.uk> | 2020-10-06 19:15:17 +0200 |
commit | 1d257a9287480014a4664c7808222179b6d2ae1d (patch) | |
tree | 24ec4a272cea3e7258811820fbb1346283e400c5 /src | |
parent | 4cae6afabb48cf5f77d9826881f7e41ffb57baaf (diff) | |
download | RSAComb-1d257a9287480014a4664c7808222179b6d2ae1d.tar.gz RSAComb-1d257a9287480014a4664c7808222179b6d2ae1d.zip |
Complete generation of logic program for the canonical model
Diffstat (limited to 'src')
-rw-r--r-- | src/main/scala/rsacomb/CanonicalModel.scala | 52 | ||||
-rw-r--r-- | src/main/scala/rsacomb/Main.scala | 14 | ||||
-rw-r--r-- | src/main/scala/rsacomb/RSAAxiom.scala | 8 | ||||
-rw-r--r-- | src/main/scala/rsacomb/RSAOntology.scala | 34 |
4 files changed, 75 insertions, 33 deletions
diff --git a/src/main/scala/rsacomb/CanonicalModel.scala b/src/main/scala/rsacomb/CanonicalModel.scala index c957940..95eb556 100644 --- a/src/main/scala/rsacomb/CanonicalModel.scala +++ b/src/main/scala/rsacomb/CanonicalModel.scala | |||
@@ -29,12 +29,12 @@ object ProgramGenerator { | |||
29 | new ProgramGenerator(ontology, term, unsafe) | 29 | new ProgramGenerator(ontology, term, unsafe) |
30 | 30 | ||
31 | def generateRoleRules( | 31 | def generateRoleRules( |
32 | roles: List[OWLObjectPropertyExpression] | 32 | roles: Set[OWLObjectProperty] |
33 | ): List[Rule] = { | 33 | ): List[Rule] = { |
34 | def additional(pred: String): Seq[Rule] = { | 34 | def additional(pred: String): Seq[Rule] = { |
35 | val varX = Variable.create("X") | 35 | val varX = Variable.create("X") |
36 | val varY = Variable.create("Y") | 36 | val varY = Variable.create("Y") |
37 | Seq( | 37 | List( |
38 | Rule.create( | 38 | Rule.create( |
39 | Atom.rdf(varX, IRI.create(pred), varY), | 39 | Atom.rdf(varX, IRI.create(pred), varY), |
40 | Atom.rdf(varX, IRI.create(pred ++ RSASuffix.Forward.getSuffix), varY) | 40 | Atom.rdf(varX, IRI.create(pred ++ RSASuffix.Forward.getSuffix), varY) |
@@ -62,10 +62,14 @@ object ProgramGenerator { | |||
62 | ) | 62 | ) |
63 | } | 63 | } |
64 | roles | 64 | roles |
65 | .filter(_.isInstanceOf[OWLObjectProperty]) // Can we avoid this? | 65 | .map(_.getIRI.getIRIString) |
66 | .map(_.asInstanceOf[OWLObjectProperty].getIRI.getIRIString) | ||
67 | .flatMap(additional) | 66 | .flatMap(additional) |
67 | .toList | ||
68 | } | 68 | } |
69 | |||
70 | def NIs(individuals: List[IRI]): List[Atom] = | ||
71 | individuals.map(Atom.rdf(_, IRI.RDF_TYPE, RSA.internal("NI"))) | ||
72 | |||
69 | } | 73 | } |
70 | 74 | ||
71 | class ProgramGenerator( | 75 | class ProgramGenerator( |
@@ -78,7 +82,7 @@ class ProgramGenerator( | |||
78 | 82 | ||
79 | import RDFoxUtil._ | 83 | import RDFoxUtil._ |
80 | 84 | ||
81 | def rules1(axiom: OWLSubClassOfAxiom): (List[Rule], List[Atom]) = { | 85 | def rules1(axiom: OWLSubClassOfAxiom): List[Rule] = { |
82 | val unfold = ontology.cycle(axiom).toList | 86 | val unfold = ontology.cycle(axiom).toList |
83 | // Fresh Variables | 87 | // Fresh Variables |
84 | val v0 = IRI.create("v0_" ++ axiom.hashCode.toString) | 88 | val v0 = IRI.create("v0_" ++ axiom.hashCode.toString) |
@@ -112,13 +116,16 @@ class ProgramGenerator( | |||
112 | .getIRI | 116 | .getIRI |
113 | Atom.rdf(v0, IRI.RDF_TYPE, cls) | 117 | Atom.rdf(v0, IRI.RDF_TYPE, cls) |
114 | } | 118 | } |
115 | ( | 119 | // TODO: To be consistent with the specifics of the visitor we are |
116 | List( | 120 | // returning facts as `Rule`s with true body. While this is correct |
117 | Rule.create(roleRf, atomA, notIn(varX)), | 121 | // there is an easier way to import facts into RDFox. Are we able to |
118 | Rule.create(atomB, atomA, notIn(varX)) | 122 | // do that? |
119 | ), | 123 | val facts = unfold.map(x => Rule.create(notIn(x))) |
120 | unfold map notIn | 124 | val rules = List( |
125 | Rule.create(roleRf, atomA, notIn(varX)), | ||
126 | Rule.create(atomB, atomA, notIn(varX)) | ||
121 | ) | 127 | ) |
128 | facts ++ rules | ||
122 | } | 129 | } |
123 | 130 | ||
124 | def rules2(axiom: OWLSubClassOfAxiom): List[Rule] = { | 131 | def rules2(axiom: OWLSubClassOfAxiom): List[Rule] = { |
@@ -209,10 +216,7 @@ class ProgramGenerator( | |||
209 | ) | 216 | ) |
210 | axiom.accept(visitor) | 217 | axiom.accept(visitor) |
211 | } else { | 218 | } else { |
212 | val (r1, f1) = rules1(axiom) | 219 | rules1(axiom) ++ rules2(axiom) ++ rules3(axiom) |
213 | val r2 = rules2(axiom) | ||
214 | val r3 = rules3(axiom) | ||
215 | r1 ++ r2 ++ r3 | ||
216 | } | 220 | } |
217 | } else { | 221 | } else { |
218 | // Fallback to standard OWL to LP translation | 222 | // Fallback to standard OWL to LP translation |
@@ -221,9 +225,21 @@ class ProgramGenerator( | |||
221 | } | 225 | } |
222 | 226 | ||
223 | override def visit(axiom: OWLSubObjectPropertyOfAxiom): List[Rule] = { | 227 | override def visit(axiom: OWLSubObjectPropertyOfAxiom): List[Rule] = { |
224 | // TODO: Generate additional rules for role inclusion | 228 | val varX = Variable.create("X") |
225 | val additional = List() | 229 | val varY = Variable.create("Y") |
226 | super.visit(axiom) ++ additional | 230 | val visitorF = new RDFoxAxiomConverter( |
231 | term, | ||
232 | unsafe, | ||
233 | SkolemStrategy.None, | ||
234 | RSASuffix.Forward | ||
235 | ) | ||
236 | val visitorB = new RDFoxAxiomConverter( | ||
237 | term, | ||
238 | unsafe, | ||
239 | SkolemStrategy.None, | ||
240 | RSASuffix.Backward | ||
241 | ) | ||
242 | axiom.accept(visitorB) ++ axiom.accept(visitorF) | ||
227 | } | 243 | } |
228 | 244 | ||
229 | } | 245 | } |
diff --git a/src/main/scala/rsacomb/Main.scala b/src/main/scala/rsacomb/Main.scala index 7900e19..5d92061 100644 --- a/src/main/scala/rsacomb/Main.scala +++ b/src/main/scala/rsacomb/Main.scala | |||
@@ -54,19 +54,7 @@ object RSAComb extends App { | |||
54 | 54 | ||
55 | // DEBUG: print program to generate canonical model | 55 | // DEBUG: print program to generate canonical model |
56 | { | 56 | { |
57 | import tech.oxfordsemantic.jrdfox.logic.{Variable} | 57 | ontology.canonicalModel.foreach(println) |
58 | import org.semanticweb.owlapi.model.parameters.Imports | ||
59 | import java.util.stream.{Collectors} | ||
60 | import scala.collection.JavaConverters._ | ||
61 | |||
62 | val visitor = ProgramGenerator(Variable.create("x"), ontology.unsafeRoles) | ||
63 | val axioms = | ||
64 | ontology | ||
65 | .tboxAxioms(Imports.INCLUDED) | ||
66 | .collect(Collectors.toList()) | ||
67 | .asScala | ||
68 | println("Program to generate the canonical model:") | ||
69 | axioms.flatMap(_.accept(visitor)).foreach(println) | ||
70 | } | 58 | } |
71 | 59 | ||
72 | /* Load query */ | 60 | /* Load query */ |
diff --git a/src/main/scala/rsacomb/RSAAxiom.scala b/src/main/scala/rsacomb/RSAAxiom.scala index 50dc37e..aca44b1 100644 --- a/src/main/scala/rsacomb/RSAAxiom.scala +++ b/src/main/scala/rsacomb/RSAAxiom.scala | |||
@@ -8,6 +8,7 @@ import org.semanticweb.owlapi.model.{ | |||
8 | } | 8 | } |
9 | import org.semanticweb.owlapi.model.{ | 9 | import org.semanticweb.owlapi.model.{ |
10 | OWLObjectPropertyExpression, | 10 | OWLObjectPropertyExpression, |
11 | OWLSubObjectPropertyOfAxiom, | ||
11 | OWLClass, | 12 | OWLClass, |
12 | OWLClassExpression, | 13 | OWLClassExpression, |
13 | OWLObjectSomeValuesFrom, | 14 | OWLObjectSomeValuesFrom, |
@@ -148,11 +149,16 @@ trait RSAAxiom { | |||
148 | List() | 149 | List() |
149 | } | 150 | } |
150 | 151 | ||
152 | override def visit( | ||
153 | axiom: OWLSubObjectPropertyOfAxiom | ||
154 | ): List[OWLObjectPropertyExpression] = | ||
155 | List(axiom.getSubProperty(), axiom.getSuperProperty()) | ||
156 | |||
151 | def doDefault(axiom: OWLAxiom): List[OWLObjectPropertyExpression] = List() | 157 | def doDefault(axiom: OWLAxiom): List[OWLObjectPropertyExpression] = List() |
152 | } | 158 | } |
153 | 159 | ||
154 | /* Exposed methods */ | 160 | /* Exposed methods */ |
155 | def objectPropertyExpressionsInSignature | 161 | lazy val objectPropertyExpressionsInSignature |
156 | : List[OWLObjectPropertyExpression] = { | 162 | : List[OWLObjectPropertyExpression] = { |
157 | val visitor = new RSAAxiomRoleExtractor() | 163 | val visitor = new RSAAxiomRoleExtractor() |
158 | axiom.accept(visitor) | 164 | axiom.accept(visitor) |
diff --git a/src/main/scala/rsacomb/RSAOntology.scala b/src/main/scala/rsacomb/RSAOntology.scala index 0acf2a6..e4348d8 100644 --- a/src/main/scala/rsacomb/RSAOntology.scala +++ b/src/main/scala/rsacomb/RSAOntology.scala | |||
@@ -46,12 +46,13 @@ trait RSAOntology { | |||
46 | .toList | 46 | .toList |
47 | } | 47 | } |
48 | 48 | ||
49 | private lazy val roles: Set[OWLObjectPropertyExpression] = | 49 | private val roles: Set[OWLObjectPropertyExpression] = { |
50 | ontology | 50 | ontology |
51 | .rboxAxioms(Imports.INCLUDED) | 51 | .rboxAxioms(Imports.INCLUDED) |
52 | .collect(Collectors.toSet()) | 52 | .collect(Collectors.toSet()) |
53 | .asScala | 53 | .asScala |
54 | .flatMap(_.objectPropertyExpressionsInSignature) | 54 | .flatMap(_.objectPropertyExpressionsInSignature) |
55 | } | ||
55 | 56 | ||
56 | // OWLAPI reasoner for same easier tasks | 57 | // OWLAPI reasoner for same easier tasks |
57 | private val reasoner = | 58 | private val reasoner = |
@@ -199,6 +200,37 @@ trait RSAOntology { | |||
199 | (unsafe1 ++ unsafe2).toList | 200 | (unsafe1 ++ unsafe2).toList |
200 | } | 201 | } |
201 | 202 | ||
203 | lazy val canonicalModel: List[Rule] = { | ||
204 | // Compute program to generate canonical model | ||
205 | val tbox = | ||
206 | ontology | ||
207 | .tboxAxioms(Imports.INCLUDED) | ||
208 | .collect(Collectors.toList()) | ||
209 | .asScala | ||
210 | .toList | ||
211 | val rbox = | ||
212 | ontology | ||
213 | .rboxAxioms(Imports.INCLUDED) | ||
214 | .collect(Collectors.toList()) | ||
215 | .asScala | ||
216 | .toList | ||
217 | val axioms = tbox ++ rbox | ||
218 | val varX = Variable.create("X") | ||
219 | val visitor = ProgramGenerator(ontology, varX, unsafeRoles) | ||
220 | val facts = ProgramGenerator.NIs(individuals) | ||
221 | val rules1 = ProgramGenerator.generateRoleRules( | ||
222 | axioms | ||
223 | .flatMap( | ||
224 | _.objectPropertiesInSignature.collect(Collectors.toSet()).asScala | ||
225 | ) | ||
226 | .toSet | ||
227 | ) | ||
228 | val rules2 = axioms.flatMap(_.accept(visitor)) | ||
229 | |||
230 | rules1 ++ rules2 | ||
231 | // Call RDFox to generate the canonical model | ||
232 | } | ||
233 | |||
202 | private def rsaGraph( | 234 | private def rsaGraph( |
203 | data: DataStoreConnection | 235 | data: DataStoreConnection |
204 | ): Graph[Resource, UnDiEdge] = { | 236 | ): Graph[Resource, UnDiEdge] = { |