aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFederico Igne <federico.igne@cs.ox.ac.uk>2020-08-19 14:21:25 +0100
committerFederico Igne <federico.igne@cs.ox.ac.uk>2020-08-19 14:21:25 +0100
commitfce66bdc060fe3ec6bd07fd17eca68ea45f119fa (patch)
tree2645225f369e90bc1059d85b3b8a955ed9c39f5a
parent50f5cd42f73b655d7d349eef70e5c269826429f9 (diff)
downloadRSAComb-fce66bdc060fe3ec6bd07fd17eca68ea45f119fa.tar.gz
RSAComb-fce66bdc060fe3ec6bd07fd17eca68ea45f119fa.zip
Add check for RSA graph acyclicity
-rw-r--r--build.sbt9
-rw-r--r--src/main/scala/rsacomb/RSAOntology.scala84
2 files changed, 49 insertions, 44 deletions
diff --git a/build.sbt b/build.sbt
index 2e1c384..34e5232 100644
--- a/build.sbt
+++ b/build.sbt
@@ -1,7 +1,7 @@
1//import Dependencies._ 1//import Dependencies._
2 2
3ThisBuild / scalaVersion := "2.13.1" 3ThisBuild / scalaVersion := "2.13.1"
4ThisBuild / version := "0.1.0" 4ThisBuild / version := "0.1.0"
5//ThisBuild / organization := "com.example" 5//ThisBuild / organization := "com.example"
6//ThisBuild / organizationName := "example" 6//ThisBuild / organizationName := "example"
7 7
@@ -9,7 +9,8 @@ lazy val root = (project in file("."))
9 .settings( 9 .settings(
10 name := "RSAComb", 10 name := "RSAComb",
11 libraryDependencies ++= Seq( 11 libraryDependencies ++= Seq(
12 "org.scalatest" %% "scalatest" % "3.1.0" % "test", 12 "org.scalatest" %% "scalatest" % "3.1.0" % "test",
13 "net.sourceforge.owlapi" % "owlapi-apibinding" % "5.1.13" 13 "net.sourceforge.owlapi" % "owlapi-apibinding" % "5.1.13",
14 "org.scala-graph" %% "graph-core" % "1.13.2"
14 ) 15 )
15 ) 16 )
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
9import org.semanticweb.owlapi.model.parameters.Imports 9import org.semanticweb.owlapi.model.parameters.Imports
10import org.semanticweb.owlapi.reasoner.structural.StructuralReasonerFactory 10import org.semanticweb.owlapi.reasoner.structural.StructuralReasonerFactory
11 11
12import tech.oxfordsemantic.jrdfox.logic.Variable 12import tech.oxfordsemantic.jrdfox.client.{UpdateType, DataStoreConnection}
13import tech.oxfordsemantic.jrdfox.client.UpdateType 13import tech.oxfordsemantic.jrdfox.logic.{Resource, Rule, Atom, Variable, IRI}
14import tech.oxfordsemantic.jrdfox.logic.{Rule, Atom, Variable, IRI}
15 14
16/* Scala imports */ 15/* Scala imports */
17import scala.collection.JavaConverters._ 16import scala.collection.JavaConverters._
17import scalax.collection.immutable.Graph
18import scalax.collection.GraphEdge.UnDiEdge
18 19
19/* Debug only */ 20/* Debug only */
20import org.semanticweb.owlapi.dlsyntax.renderer.DLSyntaxObjectRenderer 21import org.semanticweb.owlapi.dlsyntax.renderer.DLSyntaxObjectRenderer
21import 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