aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFederico Igne <federico.igne@cs.ox.ac.uk>2022-05-19 15:08:24 +0100
committerFederico Igne <federico.igne@cs.ox.ac.uk>2022-05-19 15:21:37 +0100
commit3b21b25763dffd117488e99378d466fcf97c6d52 (patch)
treeca67179d57569d8d8fd16fb732a37fae84a4be61
parent8af8f165f0a2e7ad06605daf89700073eb20c5ef (diff)
downloadRSAComb-3b21b25763dffd117488e99378d466fcf97c6d52.tar.gz
RSAComb-3b21b25763dffd117488e99378d466fcf97c6d52.zip
fix(lowerbound): cycle detection in approximation algorithm
-rw-r--r--src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Lowerbound.scala110
1 files changed, 99 insertions, 11 deletions
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 3cc8fc3..1b72699 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
@@ -3,18 +3,18 @@ package uk.ac.ox.cs.rsacomb.approximation
3import java.io.File 3import java.io.File
4 4
5import org.semanticweb.owlapi.apibinding.OWLManager 5import org.semanticweb.owlapi.apibinding.OWLManager
6import org.semanticweb.owlapi.model.{IRI => _, _} 6import org.semanticweb.owlapi.model.{IRI => OWLIRI, _}
7 7
8import tech.oxfordsemantic.jrdfox.logic.expression.{Resource, IRI} 8import tech.oxfordsemantic.jrdfox.logic.expression.{Resource, IRI, Literal}
9 9
10import scala.collection.mutable.{Set, Map} 10import scala.collection.mutable.{Set, Map}
11import scalax.collection.Graph 11import scalax.collection.Graph
12import scalax.collection.GraphPredef._, scalax.collection.GraphEdge._ 12import scalax.collection.GraphPredef._, scalax.collection.GraphEdge._
13import scalax.collection.GraphTraversal._ 13import scalax.collection.GraphTraversal._
14 14
15import uk.ac.ox.cs.rsacomb.RSAOntology 15import uk.ac.ox.cs.rsacomb.ontology.RSAOntology
16import uk.ac.ox.cs.rsacomb.ontology.Ontology 16import uk.ac.ox.cs.rsacomb.ontology.Ontology
17import uk.ac.ox.cs.rsacomb.util.DataFactory 17import uk.ac.ox.cs.rsacomb.util.{DataFactory, RDFoxUtil, RSA}
18 18
19object Lowerbound { 19object Lowerbound {
20 20
@@ -86,7 +86,7 @@ class Lowerbound(implicit fresh: DataFactory)
86 } 86 }
87 case a: OWLTransitiveObjectPropertyAxiom => false 87 case a: OWLTransitiveObjectPropertyAxiom => false
88 case a: OWLReflexiveObjectPropertyAxiom => false 88 case a: OWLReflexiveObjectPropertyAxiom => false
89 case a: OWLSubPropertyChainOfAxiom => false 89 case a: OWLSubPropertyChainOfAxiom => true /*TODO: should we leave it? */
90 case a: OWLAsymmetricObjectPropertyAxiom => false 90 case a: OWLAsymmetricObjectPropertyAxiom => false
91 case a => true 91 case a => true
92 } 92 }
@@ -172,8 +172,13 @@ class Lowerbound(implicit fresh: DataFactory)
172 * @return the approximated RSA ontology 172 * @return the approximated RSA ontology
173 */ 173 */
174 private def toRSA(ontology: Ontology): RSAOntology = { 174 private def toRSA(ontology: Ontology): RSAOntology = {
175 /* Compute the dependency graph for the ontology */ 175 val factory = Lowerbound.factory
176 val (graph, nodemap) = ontology.dependencyGraph 176 val (graph,nodemap) = ontology.dependencyGraph
177 val (server,data) = RDFoxUtil.openConnection(Ontology.DataStore)
178
179 /* G is an oriented forest.
180 * This is a custom DFS visit on the dependency graph.
181 */
177 182
178 /* Define node colors for the graph visit */ 183 /* Define node colors for the graph visit */
179 sealed trait NodeColor 184 sealed trait NodeColor
@@ -210,16 +215,99 @@ class Lowerbound(implicit fresh: DataFactory)
210 } 215 }
211 } 216 }
212 217
213 val toDelete = color.collect { case (resource: IRI, ToDelete) => 218 val delete: Set[OWLAxiom] =
214 nodemap(resource.getIRI) 219 Set.from(color.collect {
215 }.toList 220 case (resource: IRI, ToDelete) => nodemap(resource.getIRI)
221 })
222 /* Equality safety: condition 1 */
223 val answers2 = RDFoxUtil.submitQuery(data, s"""
224 SELECT ?a ?s ?b
225 WHERE {
226 graph ${Ontology.RSACheck} { ?w ${RSA.CONGRUENT} ?t } .
227 filter ( ?w != ?t ) .
228 graph ${Ontology.RSACheck} { ?t ?r [ a ${RSA.U} ] } .
229 graph ${Ontology.RBoxReasoning} {
230 ?r rdfs:subPropertyOf [ owl:inverseOf ?s ] .
231 ?x rdf:type owl:Restriction ;
232 owl:onProperty ?s ;
233 owl:maxQualifiedCardinality "1"^^xsd:nonNegativeInteger ;
234 owl:onClass ?b .
235 ?a rdfs:subClassOf ?b .
236 } .
237 }
238 """).get
239 // NOTE: there seems to be a bug that turns any [[Resource]] answer
240 // to a query into a [[Literal]] (while here we would expect them to
241 // be [[IRI]]).
242 answers2.foldLeft(delete)((d, res) => {
243 val a = res._2(0).asInstanceOf[Literal].getLexicalForm
244 val r = res._2(1).asInstanceOf[Literal].getLexicalForm
245 val b = res._2(1).asInstanceOf[Literal].getLexicalForm
246 val axiom = factory.getOWLSubClassOfAxiom(
247 factory.getOWLClass(a),
248 factory.getOWLObjectMaxCardinality(1,
249 factory.getOWLObjectProperty(r),
250 factory.getOWLClass(b)
251 )
252 )
253 d += axiom
254 })
255 /* Equality safety: condition 2 */
256 val answers3 = RDFoxUtil.submitQuery(data, s"""
257 SELECT ?r ?r1 ?s ?s1
258 WHERE {
259 graph ${Ontology.RSACheck} {
260 ?u ?s ?a ; a ${RSA.U} .
261 ?a ?r ?u ; a ${RSA.NI} .
262 } .
263 graph ${Ontology.RBoxReasoning} {
264 ?r rdfs:subPropertyOf ?r1 .
265 ?r1 ${RSA("subPropertyOfTrans")} ?t .
266 ?t owl:inverseOf ?ti .
267 ?s rdfs:subPropertyOf ?s1 .
268 ?s1 ${RSA("subPropertyOfTrans")} ?ti .
269 }
270 }
271 """).get
272 // NOTE: there seems to be a bug that turns any [[Resource]] answer
273 // to a query into a [[Literal]] (while here we would expect them to
274 // be [[IRI]]).
275 println(s"Answers 3: ${answers3.length}")
276 answers3.foldLeft(delete)((d, res) => {
277 val r1 = res._2(0).asInstanceOf[Literal].getLexicalForm
278 val r2 = res._2(1).asInstanceOf[Literal].getLexicalForm
279 val s1 = res._2(2).asInstanceOf[Literal].getLexicalForm
280 val s2 = res._2(3).asInstanceOf[Literal].getLexicalForm
281 val axiom = if (r1 == r2) {
282 factory.getOWLSubObjectPropertyOfAxiom(
283 factory.getOWLObjectProperty(s1),
284 factory.getOWLObjectProperty(s2),
285 )
286 } else {
287 factory.getOWLSubObjectPropertyOfAxiom(
288 factory.getOWLObjectProperty(r1),
289 factory.getOWLObjectProperty(r2),
290 )
291 }
292 d += axiom
293 })
294
295 println(s"To Delete (${delete.size}):")
296 delete foreach println
297
298 println(s"Before: ${ontology.axioms.length}")
299 println(s"After: ${(ontology.axioms diff delete.toList).length}")
216 300
217 /* Remove axioms from approximated ontology */ 301 /* Remove axioms from approximated ontology */
218 RSAOntology( 302 RSAOntology(
219 ontology.origin, 303 ontology.origin,
220 ontology.axioms diff toDelete, 304 ontology.axioms diff delete.toList,
221 ontology.datafiles 305 ontology.datafiles
222 ) 306 )
307
308
309
310
223 } 311 }
224 312
225 // val edges1 = Seq('A ~> 'B, 'B ~> 'C, 'C ~> 'D, 'D ~> 'H, 'H ~> 313 // val edges1 = Seq('A ~> 'B, 'B ~> 'C, 'C ~> 'D, 'D ~> 'H, 'H ~>