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 | |
parent | 50f5cd42f73b655d7d349eef70e5c269826429f9 (diff) | |
download | RSAComb-fce66bdc060fe3ec6bd07fd17eca68ea45f119fa.tar.gz RSAComb-fce66bdc060fe3ec6bd07fd17eca68ea45f119fa.zip |
Add check for RSA graph acyclicity
-rw-r--r-- | build.sbt | 9 | ||||
-rw-r--r-- | src/main/scala/rsacomb/RSAOntology.scala | 84 |
2 files changed, 49 insertions, 44 deletions
@@ -1,7 +1,7 @@ | |||
1 | //import Dependencies._ | 1 | //import Dependencies._ |
2 | 2 | ||
3 | ThisBuild / scalaVersion := "2.13.1" | 3 | ThisBuild / scalaVersion := "2.13.1" |
4 | ThisBuild / version := "0.1.0" | 4 | ThisBuild / 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 | |||
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 |