diff options
| author | Federico Igne <federico.igne@cs.ox.ac.uk> | 2020-08-19 14:21:25 +0100 |
|---|---|---|
| committer | Federico Igne <federico.igne@cs.ox.ac.uk> | 2020-08-19 14:21:25 +0100 |
| commit | fce66bdc060fe3ec6bd07fd17eca68ea45f119fa (patch) | |
| tree | 2645225f369e90bc1059d85b3b8a955ed9c39f5a /src/main/scala | |
| parent | 50f5cd42f73b655d7d349eef70e5c269826429f9 (diff) | |
| download | RSAComb-fce66bdc060fe3ec6bd07fd17eca68ea45f119fa.tar.gz RSAComb-fce66bdc060fe3ec6bd07fd17eca68ea45f119fa.zip | |
Add check for RSA graph acyclicity
Diffstat (limited to 'src/main/scala')
| -rw-r--r-- | src/main/scala/rsacomb/RSAOntology.scala | 84 |
1 files changed, 44 insertions, 40 deletions
diff --git a/src/main/scala/rsacomb/RSAOntology.scala b/src/main/scala/rsacomb/RSAOntology.scala index 10f2fa4..3d9210e 100644 --- a/src/main/scala/rsacomb/RSAOntology.scala +++ b/src/main/scala/rsacomb/RSAOntology.scala | |||
| @@ -9,16 +9,16 @@ import org.semanticweb.owlapi.model.OWLObjectPropertyExpression | |||
| 9 | import org.semanticweb.owlapi.model.parameters.Imports | 9 | import org.semanticweb.owlapi.model.parameters.Imports |
| 10 | import org.semanticweb.owlapi.reasoner.structural.StructuralReasonerFactory | 10 | import org.semanticweb.owlapi.reasoner.structural.StructuralReasonerFactory |
| 11 | 11 | ||
| 12 | import tech.oxfordsemantic.jrdfox.logic.Variable | 12 | import tech.oxfordsemantic.jrdfox.client.{UpdateType, DataStoreConnection} |
| 13 | import tech.oxfordsemantic.jrdfox.client.UpdateType | 13 | import tech.oxfordsemantic.jrdfox.logic.{Resource, Rule, Atom, Variable, IRI} |
| 14 | import tech.oxfordsemantic.jrdfox.logic.{Rule, Atom, Variable, IRI} | ||
| 15 | 14 | ||
| 16 | /* Scala imports */ | 15 | /* Scala imports */ |
| 17 | import scala.collection.JavaConverters._ | 16 | import scala.collection.JavaConverters._ |
| 17 | import scalax.collection.immutable.Graph | ||
| 18 | import scalax.collection.GraphEdge.UnDiEdge | ||
| 18 | 19 | ||
| 19 | /* Debug only */ | 20 | /* Debug only */ |
| 20 | import org.semanticweb.owlapi.dlsyntax.renderer.DLSyntaxObjectRenderer | 21 | import org.semanticweb.owlapi.dlsyntax.renderer.DLSyntaxObjectRenderer |
| 21 | import java.io.OutputStream | ||
| 22 | 22 | ||
| 23 | /* Wrapper trait for the implicit class `RSAOntology`. | 23 | /* Wrapper trait for the implicit class `RSAOntology`. |
| 24 | */ | 24 | */ |
| @@ -29,24 +29,22 @@ trait RSAOntology { | |||
| 29 | */ | 29 | */ |
| 30 | implicit class RSAOntology(ontology: OWLOntology) extends RSAAxiom { | 30 | implicit class RSAOntology(ontology: OWLOntology) extends RSAAxiom { |
| 31 | 31 | ||
| 32 | /* Steps for RSA check | ||
| 33 | * 1) convert ontology axioms into LP rules | ||
| 34 | * 2) call RDFox on the onto and compute materialization | ||
| 35 | * 3) build graph from E(x,y) facts | ||
| 36 | * 4) check if the graph is tree-like | ||
| 37 | * ideally this annotates the graph with info about the reasons | ||
| 38 | * why the ontology might not be RSA. This could help a second | ||
| 39 | * step of approximation of an Horn-ALCHOIQ to RSA | ||
| 40 | */ | ||
| 32 | def isRSA: Boolean = { | 41 | def isRSA: Boolean = { |
| 33 | 42 | ||
| 34 | /* TODO: Steps for RSA check | 43 | val tbox = ontology.tboxAxioms(Imports.INCLUDED) |
| 35 | * 1) convert ontology axioms into LP rules | 44 | val rbox = ontology.rboxAxioms(Imports.INCLUDED) |
| 36 | * 2) call RDFox on the onto and compute materialization | 45 | val axioms = |
| 37 | * 3) build graph from E(x,y) facts | ||
| 38 | * 4) check if the graph is tree-like | ||
| 39 | * ideally this annotates the graph with info about the reasons | ||
| 40 | * why the ontology might not be RSA. This could help a second | ||
| 41 | * step of approximation of an Horn-ALCHOIQ to RSA | ||
| 42 | */ | ||
| 43 | |||
| 44 | val tbox = | ||
| 45 | Stream | 46 | Stream |
| 46 | .concat( | 47 | .concat(tbox, rbox) |
| 47 | ontology.tboxAxioms(Imports.INCLUDED), | ||
| 48 | ontology.rboxAxioms(Imports.INCLUDED) | ||
| 49 | ) | ||
| 50 | .collect(Collectors.toList()) | 48 | .collect(Collectors.toList()) |
| 51 | .asScala | 49 | .asScala |
| 52 | val unsafe = ontology.getUnsafeRoles | 50 | val unsafe = ontology.getUnsafeRoles |
| @@ -54,13 +52,13 @@ trait RSAOntology { | |||
| 54 | /* DEBUG: print rules in DL syntax and unsafe roles */ | 52 | /* DEBUG: print rules in DL syntax and unsafe roles */ |
| 55 | val renderer = new DLSyntaxObjectRenderer() | 53 | val renderer = new DLSyntaxObjectRenderer() |
| 56 | println("\nDL rules:") | 54 | println("\nDL rules:") |
| 57 | tbox.foreach(x => println(renderer.render(x))) | 55 | axioms.foreach(x => println(renderer.render(x))) |
| 58 | println("\nUnsafe roles:") | 56 | println("\nUnsafe roles:") |
| 59 | println(unsafe) | 57 | println(unsafe) |
| 60 | 58 | ||
| 61 | /* Ontology convertion into LP rules */ | 59 | /* Ontology convertion into LP rules */ |
| 62 | val datalog = for { | 60 | val datalog = for { |
| 63 | axiom <- tbox | 61 | axiom <- axioms |
| 64 | visitor = new RDFoxAxiomConverter( | 62 | visitor = new RDFoxAxiomConverter( |
| 65 | Variable.create("x"), | 63 | Variable.create("x"), |
| 66 | SkolemStrategy.ConstantRSA(axiom.toString), | 64 | SkolemStrategy.ConstantRSA(axiom.toString), |
| @@ -90,29 +88,20 @@ trait RSAOntology { | |||
| 90 | */ | 88 | */ |
| 91 | data.addRules(datalog.asJava) | 89 | data.addRules(datalog.asJava) |
| 92 | 90 | ||
| 93 | // Retrieve all instances of PE | 91 | /* Build graph |
| 94 | println("\nQueries:") | 92 | */ |
| 95 | RDFoxUtil.query( | 93 | val graph = getRSAGraph(data); |
| 96 | data, | 94 | println(graph) |
| 97 | RSA.Prefixes, | ||
| 98 | "SELECT ?X ?Y WHERE { ?X internal:PE ?Y }" | ||
| 99 | ) | ||
| 100 | RDFoxUtil.query( | ||
| 101 | data, | ||
| 102 | RSA.Prefixes, | ||
| 103 | "SELECT ?X ?Y WHERE { ?X internal:E ?Y }" | ||
| 104 | ) | ||
| 105 | RDFoxUtil.query( | ||
| 106 | data, | ||
| 107 | RSA.Prefixes, | ||
| 108 | "SELECT ?X WHERE { ?X rdf:type owl:Thing }" | ||
| 109 | ) | ||
| 110 | 95 | ||
| 111 | // Close connection to RDFox | 96 | // Close connection to RDFox |
| 112 | RDFoxUtil.closeConnection(server, data) | 97 | RDFoxUtil.closeConnection(server, data) |
| 113 | 98 | ||
| 114 | /* DEBUG */ | 99 | /* To check if the graph is tree-like we check for acyclicity in a |
| 115 | true | 100 | * undirected graph. |
| 101 | * | ||
| 102 | * TODO: Implement additional checks (taking into account equality) | ||
| 103 | */ | ||
| 104 | graph.isAcyclic | ||
| 116 | } | 105 | } |
| 117 | 106 | ||
| 118 | def getUnsafeRoles: List[OWLObjectPropertyExpression] = { | 107 | def getUnsafeRoles: List[OWLObjectPropertyExpression] = { |
| @@ -180,6 +169,21 @@ trait RSAOntology { | |||
| 180 | (unsafe1 ++ unsafe2).toList | 169 | (unsafe1 ++ unsafe2).toList |
| 181 | } | 170 | } |
| 182 | 171 | ||
| 172 | def getRSAGraph( | ||
| 173 | data: DataStoreConnection | ||
| 174 | ): Graph[Resource, UnDiEdge] = { | ||
| 175 | val query = "SELECT ?X ?Y WHERE { ?X internal:E ?Y }" | ||
| 176 | val cursor = | ||
| 177 | data.createCursor(RSA.Prefixes, query, new HashMap[String, String]()); | ||
| 178 | var mul = cursor.open() | ||
| 179 | var edges: List[UnDiEdge[Resource]] = List() | ||
| 180 | while (mul > 0) { | ||
| 181 | edges = UnDiEdge(cursor.getResource(0), cursor.getResource(1)) :: edges | ||
| 182 | mul = cursor.advance() | ||
| 183 | } | ||
| 184 | Graph(edges: _*) | ||
| 185 | } | ||
| 186 | |||
| 183 | } // implicit class RSAOntology | 187 | } // implicit class RSAOntology |
| 184 | 188 | ||
| 185 | } // trait RSAOntology | 189 | } // trait RSAOntology |
