aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/rsacomb
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/scala/rsacomb')
-rw-r--r--src/main/scala/rsacomb/CanonicalModel.scala62
-rw-r--r--src/main/scala/rsacomb/FilteringProgram.scala284
-rw-r--r--src/main/scala/rsacomb/Main.scala232
-rw-r--r--src/main/scala/rsacomb/RDFoxAxiomConverter.scala2
-rw-r--r--src/main/scala/rsacomb/RDFoxClassExprConverter.scala19
-rw-r--r--src/main/scala/rsacomb/RDFoxPropertyExprConverter.scala2
-rw-r--r--src/main/scala/rsacomb/RDFoxUtil.scala113
-rw-r--r--src/main/scala/rsacomb/RSA.scala105
-rw-r--r--src/main/scala/rsacomb/RSAAtom.scala6
-rw-r--r--src/main/scala/rsacomb/RSAAxiom.scala13
-rw-r--r--src/main/scala/rsacomb/RSAOntology.scala31
-rw-r--r--src/main/scala/rsacomb/implicits/JavaCollections.scala13
-rw-r--r--src/main/scala/rsacomb/implicits/RDFox.scala20
-rw-r--r--src/main/scala/rsacomb/util/RDFoxHelpers.scala100
14 files changed, 502 insertions, 500 deletions
diff --git a/src/main/scala/rsacomb/CanonicalModel.scala b/src/main/scala/rsacomb/CanonicalModel.scala
index f7a45a7..5f781d1 100644
--- a/src/main/scala/rsacomb/CanonicalModel.scala
+++ b/src/main/scala/rsacomb/CanonicalModel.scala
@@ -24,16 +24,15 @@ import tech.oxfordsemantic.jrdfox.logic.expression.{
24} 24}
25 25
26import suffix.{Empty, Forward, Backward, Inverse} 26import suffix.{Empty, Forward, Backward, Inverse}
27import util.RSA
27 28
28class CanonicalModel(val ontology: RSAOntology) extends RSAAxiom { 29class CanonicalModel(val ontology: RSAOntology) extends RSAAxiom {
29 30
30 // Makes working with IRIs less painful 31 import implicits.RDFox._
31 import RDFoxUtil._ 32 import implicits.JavaCollections._
32 33
33 val named: List[Rule] = 34 val named: List[Rule] =
34 ontology.individuals.map(a => 35 ontology.individuals.map(a => Rule.create(RSA.Named(a)))
35 Rule.create(TupleTableAtom.rdf(a, IRI.RDF_TYPE, RSA.Named))
36 )
37 36
38 val rolesAdditionalRules: List[Rule] = { 37 val rolesAdditionalRules: List[Rule] = {
39 // Given a role (predicate) compute additional logic rules 38 // Given a role (predicate) compute additional logic rules
@@ -69,7 +68,7 @@ class CanonicalModel(val ontology: RSAOntology) extends RSAAxiom {
69 val varY = Variable.create("Y") 68 val varY = Variable.create("Y")
70 val concepts = ontology.concepts.map(c => { 69 val concepts = ontology.concepts.map(c => {
71 Rule.create( 70 Rule.create(
72 TupleTableAtom.rdf(varX, IRI.RDF_TYPE, IRI.THING), 71 RSA.Thing(varX),
73 TupleTableAtom.rdf(varX, IRI.RDF_TYPE, c.getIRI) 72 TupleTableAtom.rdf(varX, IRI.RDF_TYPE, c.getIRI)
74 ) 73 )
75 }) 74 })
@@ -80,10 +79,7 @@ class CanonicalModel(val ontology: RSAOntology) extends RSAAxiom {
80 x.getInverse.getNamedProperty.getIRI.getIRIString :: Inverse 79 x.getInverse.getNamedProperty.getIRI.getIRIString :: Inverse
81 } 80 }
82 Rule.create( 81 Rule.create(
83 List( 82 List(RSA.Thing(varX), RSA.Thing(varY)),
84 TupleTableAtom.rdf(varX, IRI.RDF_TYPE, IRI.THING),
85 TupleTableAtom.rdf(varY, IRI.RDF_TYPE, IRI.THING)
86 ),
87 List(TupleTableAtom.rdf(varX, name, varY)) 83 List(TupleTableAtom.rdf(varX, name, varY))
88 ) 84 )
89 }) 85 })
@@ -95,18 +91,15 @@ class CanonicalModel(val ontology: RSAOntology) extends RSAAxiom {
95 val varY = Variable.create("Y") 91 val varY = Variable.create("Y")
96 val varZ = Variable.create("Z") 92 val varZ = Variable.create("Z")
97 List( 93 List(
94 // Reflexivity
95 Rule.create(RSA.EquivTo(varX, varX), RSA.Thing(varX)),
96 // Simmetry
97 Rule.create(RSA.EquivTo(varY, varX), RSA.EquivTo(varX, varY)),
98 // Transitivity
98 Rule.create( 99 Rule.create(
99 TupleTableAtom.rdf(varX, RSA.EquivTo, varX), 100 RSA.EquivTo(varX, varZ),
100 TupleTableAtom.rdf(varX, IRI.RDF_TYPE, IRI.THING) 101 RSA.EquivTo(varX, varY),
101 ), 102 RSA.EquivTo(varY, varZ)
102 Rule.create(
103 TupleTableAtom.rdf(varY, RSA.EquivTo, varX),
104 TupleTableAtom.rdf(varX, RSA.EquivTo, varY)
105 ),
106 Rule.create(
107 TupleTableAtom.rdf(varX, RSA.EquivTo, varZ),
108 TupleTableAtom.rdf(varX, RSA.EquivTo, varY),
109 TupleTableAtom.rdf(varY, RSA.EquivTo, varZ)
110 ) 103 )
111 ) 104 )
112 } 105 }
@@ -129,21 +122,14 @@ class CanonicalModel(val ontology: RSAOntology) extends RSAAxiom {
129 private def rules1(axiom: OWLSubClassOfAxiom): List[Rule] = { 122 private def rules1(axiom: OWLSubClassOfAxiom): List[Rule] = {
130 val unfold = ontology.unfold(axiom).toList 123 val unfold = ontology.unfold(axiom).toList
131 // Fresh Variables 124 // Fresh Variables
132 val v0 = RSA.rsa("v0_" ++ RSA.hashed(axiom)) 125 val v0 = RSA("v0_" ++ axiom.hashed)
133 val varX = Variable.create("X") 126 val varX = Variable.create("X")
134 // Predicates 127 implicit val unfoldTerm = RSA(unfold.hashCode.toString)
128 // TODO: use axiom.toTriple instead
135 val atomA: TupleTableAtom = { 129 val atomA: TupleTableAtom = {
136 val cls = axiom.getSubClass.asInstanceOf[OWLClass].getIRI 130 val cls = axiom.getSubClass.asInstanceOf[OWLClass].getIRI
137 TupleTableAtom.rdf(varX, IRI.RDF_TYPE, cls) 131 TupleTableAtom.rdf(varX, IRI.RDF_TYPE, cls)
138 } 132 }
139 def predIN(t: Term): TupleTableAtom = {
140 TupleTableAtom.rdf(
141 t,
142 RSA.rsa("IN"),
143 RSA.rsa(unfold.hashCode.toString)
144 )
145 }
146 def notIn(t: Term): Negation = Negation.create(predIN(t))
147 val roleRf: TupleTableAtom = { 133 val roleRf: TupleTableAtom = {
148 val visitor = 134 val visitor =
149 new RDFoxPropertyExprConverter(varX, v0, Forward) 135 new RDFoxPropertyExprConverter(varX, v0, Forward)
@@ -165,10 +151,10 @@ class CanonicalModel(val ontology: RSAOntology) extends RSAAxiom {
165 // returning facts as `Rule`s with true body. While this is correct 151 // returning facts as `Rule`s with true body. While this is correct
166 // there is an easier way to import facts into RDFox. Are we able to 152 // there is an easier way to import facts into RDFox. Are we able to
167 // do that? 153 // do that?
168 val facts = unfold.map(x => Rule.create(predIN(x))) 154 val facts = unfold.map(x => Rule.create(RSA.In(x)))
169 val rules = List( 155 val rules = List(
170 Rule.create(roleRf, atomA, notIn(varX)), 156 Rule.create(roleRf, atomA, RSA.notIn(varX)),
171 Rule.create(atomB, atomA, notIn(varX)) 157 Rule.create(atomB, atomA, RSA.notIn(varX))
172 ) 158 )
173 facts ++ rules 159 facts ++ rules
174 } 160 }
@@ -180,9 +166,9 @@ class CanonicalModel(val ontology: RSAOntology) extends RSAAxiom {
180 .getProperty 166 .getProperty
181 if (ontology.confl(roleR) contains roleR) { 167 if (ontology.confl(roleR) contains roleR) {
182 // Fresh Variables 168 // Fresh Variables
183 val v0 = RSA.rsa("v0_" ++ RSA.hashed(axiom)) 169 val v0 = RSA("v0_" ++ axiom.hashed)
184 val v1 = RSA.rsa("v1_" ++ RSA.hashed(axiom)) 170 val v1 = RSA("v1_" ++ axiom.hashed)
185 val v2 = RSA.rsa("v2_" ++ RSA.hashed(axiom)) 171 val v2 = RSA("v2_" ++ axiom.hashed)
186 // Predicates 172 // Predicates
187 def atomA(t: Term): TupleTableAtom = { 173 def atomA(t: Term): TupleTableAtom = {
188 val cls = axiom.getSubClass.asInstanceOf[OWLClass].getIRI 174 val cls = axiom.getSubClass.asInstanceOf[OWLClass].getIRI
@@ -220,7 +206,7 @@ class CanonicalModel(val ontology: RSAOntology) extends RSAAxiom {
220 .asInstanceOf[OWLObjectSomeValuesFrom] 206 .asInstanceOf[OWLObjectSomeValuesFrom]
221 .getProperty 207 .getProperty
222 // Fresh Variables 208 // Fresh Variables
223 val v1 = RSA.rsa("v1_" ++ RSA.hashed(axiom)) 209 val v1 = RSA("v1_" ++ axiom.hashed)
224 // Predicates 210 // Predicates
225 def atomA(t: Term): TupleTableAtom = { 211 def atomA(t: Term): TupleTableAtom = {
226 val cls = axiom.getSubClass.asInstanceOf[OWLClass].getIRI 212 val cls = axiom.getSubClass.asInstanceOf[OWLClass].getIRI
diff --git a/src/main/scala/rsacomb/FilteringProgram.scala b/src/main/scala/rsacomb/FilteringProgram.scala
index af07ac3..5aaf5b0 100644
--- a/src/main/scala/rsacomb/FilteringProgram.scala
+++ b/src/main/scala/rsacomb/FilteringProgram.scala
@@ -29,44 +29,43 @@ import scala.collection.JavaConverters._
29 29
30import implicits.RSAAtom 30import implicits.RSAAtom
31import suffix.{RSASuffix, Forward, Backward} 31import suffix.{RSASuffix, Forward, Backward}
32import util.RSA
32 33
33class FilteringProgram(query: SelectQuery, constants: List[Term]) 34class FilteringProgram(query: SelectQuery, constants: List[Term])
34 extends RSAAtom { 35 extends RSAAtom {
35 36
36 /* Makes mplicit conversion OWLAPI IRI <-> RDFox IRI available */ 37 /* Makes mplicit conversion OWLAPI IRI <-> RDFox IRI available */
37 import RDFoxUtil._ 38 // import implicits.RDFox._
38 39
39 lazy val variables = { 40 implicit val variables: (List[Term], List[Term]) = {
40 query.getQueryBody.getWherePattern match { 41 val all: Set[Variable] = query.getQueryBody.getWherePattern match {
41 case b: ConjunctionPattern => { 42 case b: ConjunctionPattern => {
42 b.getConjuncts.asScala.toSet.flatMap { conj: QueryPattern => 43 b.getConjuncts.asScala.toSet.flatMap { conj: QueryPattern =>
43 conj match { 44 conj match {
44 case c: TriplePattern => 45 case c: TriplePattern =>
45 Set(c.getSubject, c.getPredicate, c.getObject) 46 Set(c.getSubject, c.getPredicate, c.getObject).collect {
46 .filter(_.isInstanceOf[Variable]) 47 case v: Variable => v
48 }
47 case _ => Set() 49 case _ => Set()
48 } 50 }
49 } 51 }
50 } 52 }
51 case _ => Set() 53 case _ => Set()
52 } 54 }
53 }.toList
54
55 val answer: List[Term] =
56 if (query.getAllPossibleVariables) { 55 if (query.getAllPossibleVariables) {
57 variables 56 (all.toList, List())
58 } else { 57 } else {
59 query.getSelection.asScala.map(_.getVariable).toList 58 val answer = query.getSelection.asScala.map(_.getVariable).toSet
59 (answer.toList, (all &~ answer).toList)
60 } 60 }
61 val bounded: List[Term] = this.variables.filterNot(answer.contains(_)) 61 }
62
63 val (answer, bounded) = variables
62 64
63 val facts: List[Rule] = constants.map(c => Rule.create(predNI(c))) 65 val facts: List[Rule] = constants.map(c => Rule.create(RSA.NI(c)))
64 val rules: List[Rule] = 66 val rules: List[Rule] =
65 this.generateFilteringProgram().map(reifyRule) ++ facts 67 this.generateFilteringProgram().map(reifyRule) ++ facts
66 68
67 private def predNI(t: Term): TupleTableAtom =
68 TupleTableAtom.rdf(t, IRI.RDF_TYPE, RSA.rsa("NI"))
69
70 /* NOTE: we are restricting to queries that contain conjunctions of 69 /* NOTE: we are restricting to queries that contain conjunctions of
71 * atoms for the time being. This might need to be reviewed in the 70 * atoms for the time being. This might need to be reviewed in the
72 * future. 71 * future.
@@ -97,64 +96,54 @@ class FilteringProgram(query: SelectQuery, constants: List[Term])
97 val body = queryToBody(query.getQueryBody.getWherePattern) 96 val body = queryToBody(query.getQueryBody.getWherePattern)
98 // Auxiliar predicates/helpers 97 // Auxiliar predicates/helpers
99 def not(atom: TupleTableAtom): BodyFormula = Negation.create(atom) 98 def not(atom: TupleTableAtom): BodyFormula = Negation.create(atom)
100 val predQM = 99 // val predQM =
101 TupleTableAtom.create( 100 // TupleTableAtom.create(
102 TupleTableName.create(RSA.rsa("QM").getIRI), 101 // TupleTableName.create(RSA.Qm.getIRI),
103 (answer ++ bounded): _* 102 // (answer ++ bounded): _*
104 ) 103 // )
105 def predID(t1: Term, t2: Term) = 104 // def predID(t1: Term, t2: Term) =
106 TupleTableAtom.create( 105 // TupleTableAtom.create(
107 TupleTableName.create(RSA.rsa("ID").getIRI), 106 // TupleTableName.create(RSA.rsa("ID").getIRI),
108 (answer ++ bounded).appended(t1).appended(t2): _* 107 // (answer ++ bounded).appended(t1).appended(t2): _*
109 ) 108 // )
110 def predNAMED(t1: Term): TupleTableAtom = 109 // def predNAMED(t1: Term): TupleTableAtom =
111 TupleTableAtom.rdf(t1, IRI.RDF_TYPE, RSA.rsa("NAMED")) 110 // TupleTableAtom.rdf(t1, IRI.RDF_TYPE, RSA.rsa("NAMED"))
112 def predTQ(t1: Term, t2: Term, sx: RSASuffix) = 111 // def predTQ(t1: Term, t2: Term, sx: RSASuffix) =
113 TupleTableAtom.create( 112 // TupleTableAtom.create(
114 TupleTableName.create(RSA.rsa("TQ" :: sx).getIRI), 113 // TupleTableName.create(RSA.rsa("TQ" :: sx).getIRI),
115 (answer ++ bounded).appended(t1).appended(t2): _* 114 // (answer ++ bounded).appended(t1).appended(t2): _*
116 ) 115 // )
117 def predAQ(t1: Term, t2: Term, sx: RSASuffix) = 116 // def predAQ(t1: Term, t2: Term, sx: RSASuffix) =
118 TupleTableAtom.create( 117 // TupleTableAtom.create(
119 TupleTableName.create(RSA.rsa("AQ" :: sx).getIRI), 118 // TupleTableName.create(RSA.rsa("AQ" :: sx).getIRI),
120 (answer ++ bounded).appended(t1).appended(t2): _* 119 // (answer ++ bounded).appended(t1).appended(t2): _*
121 ) 120 // )
122 val predFK = 121 // val predFK =
123 TupleTableAtom.create( 122 // TupleTableAtom.create(
124 TupleTableName.create(RSA.rsa("FK").getIRI), 123 // TupleTableName.create(RSA.rsa("FK").getIRI),
125 (answer ++ bounded): _* 124 // (answer ++ bounded): _*
126 ) 125 // )
127 val predSP = 126 // val predSP =
128 TupleTableAtom.create( 127 // TupleTableAtom.create(
129 TupleTableName.create(RSA.rsa("SP").getIRI), 128 // TupleTableName.create(RSA.rsa("SP").getIRI),
130 (answer ++ bounded): _* 129 // (answer ++ bounded): _*
131 ) 130 // )
132 val predANS = 131 // val predANS =
133 TupleTableAtom.create( 132 // TupleTableAtom.create(
134 TupleTableName.create(RSA.rsa("ANS").getIRI), 133 // TupleTableName.create(RSA.rsa("ANS").getIRI),
135 answer: _* 134 // answer: _*
136 ) 135 // )
137 136
138 /* Rule 1 */ 137 /* Rule 1 */
139 val r1 = Rule.create(predQM, body: _*) 138 val r1 = Rule.create(RSA.QM, body: _*)
140 139
141 /* Rules 3x */ 140 /* Rules 3x */
142 val r3a = 141 val r3a =
143 for ((v, i) <- bounded.zipWithIndex) 142 for ((v, i) <- bounded.zipWithIndex)
144 yield Rule.create( 143 yield Rule.create(RSA.ID(RSA(i), RSA(i)), RSA.QM, not(RSA.NI(v)))
145 predID(RSA.rsa(i), RSA.rsa(i)), 144 val r3b = Rule.create(RSA.ID(varV, varU), RSA.ID(varU, varV))
146 predQM, 145 val r3c =
147 not(predNI(v)) 146 Rule.create(RSA.ID(varU, varW), RSA.ID(varU, varV), RSA.ID(varV, varW))
148 )
149 val r3b = Rule.create(
150 predID(varV, varU),
151 predID(varU, varV)
152 )
153 val r3c = Rule.create(
154 predID(varU, varW),
155 predID(varU, varV),
156 predID(varV, varW)
157 )
158 147
159 /* Rules 4x */ 148 /* Rules 4x */
160 val r4a = for { 149 val r4a = for {
@@ -163,20 +152,14 @@ class FilteringProgram(query: SelectQuery, constants: List[Term])
163 role2 <- body.filter(_.isRoleAssertion) 152 role2 <- body.filter(_.isRoleAssertion)
164 if bounded contains (role2.getArguments.get(2)) 153 if bounded contains (role2.getArguments.get(2))
165 } yield Rule.create( 154 } yield Rule.create(
166 predFK, 155 RSA.FK,
167 role1 << Forward, 156 role1 << Forward,
168 role2 << Forward, 157 role2 << Forward,
169 predID( 158 RSA.ID(
170 RSA.rsa(bounded.indexOf(role1.getArguments.get(2))), 159 RSA(bounded.indexOf(role1.getArguments.get(2))),
171 RSA.rsa(bounded.indexOf(role2.getArguments.get(2))) 160 RSA(bounded.indexOf(role2.getArguments.get(2)))
172 ), 161 ),
173 not( 162 not(RSA.EquivTo(role1.getArguments.get(0), role2.getArguments.get(0)))
174 TupleTableAtom.rdf(
175 role1.getArguments.get(0),
176 RSA.EquivTo,
177 role2.getArguments.get(0)
178 )
179 )
180 ) 163 )
181 val r4b = for { 164 val r4b = for {
182 role1 <- body.filter(_.isRoleAssertion) 165 role1 <- body.filter(_.isRoleAssertion)
@@ -184,20 +167,14 @@ class FilteringProgram(query: SelectQuery, constants: List[Term])
184 role2 <- body.filter(_.isRoleAssertion) 167 role2 <- body.filter(_.isRoleAssertion)
185 if bounded contains (role2.getArguments.get(0)) 168 if bounded contains (role2.getArguments.get(0))
186 } yield Rule.create( 169 } yield Rule.create(
187 predFK, 170 RSA.FK,
188 role1 << Forward, 171 role1 << Forward,
189 role2 << Backward, 172 role2 << Backward,
190 predID( 173 RSA.ID(
191 RSA.rsa(bounded.indexOf(role1.getArguments.get(2))), 174 RSA(bounded.indexOf(role1.getArguments.get(2))),
192 RSA.rsa(bounded.indexOf(role2.getArguments.get(0))) 175 RSA(bounded.indexOf(role2.getArguments.get(0)))
193 ), 176 ),
194 not( 177 not(RSA.EquivTo(role1.getArguments.get(0), role2.getArguments.get(2)))
195 TupleTableAtom.rdf(
196 role1.getArguments.get(0),
197 RSA.EquivTo,
198 role2.getArguments.get(2)
199 )
200 )
201 ) 178 )
202 val r4c = for { 179 val r4c = for {
203 role1 <- body.filter(_.isRoleAssertion) 180 role1 <- body.filter(_.isRoleAssertion)
@@ -205,20 +182,14 @@ class FilteringProgram(query: SelectQuery, constants: List[Term])
205 role2 <- body.filter(_.isRoleAssertion) 182 role2 <- body.filter(_.isRoleAssertion)
206 if bounded contains (role2.getArguments.get(0)) 183 if bounded contains (role2.getArguments.get(0))
207 } yield Rule.create( 184 } yield Rule.create(
208 predFK, 185 RSA.FK,
209 role1 << Backward, 186 role1 << Backward,
210 role2 << Backward, 187 role2 << Backward,
211 predID( 188 RSA.ID(
212 RSA.rsa(bounded.indexOf(role1.getArguments.get(0))), 189 RSA(bounded.indexOf(role1.getArguments.get(0))),
213 RSA.rsa(bounded.indexOf(role2.getArguments.get(0))) 190 RSA(bounded.indexOf(role2.getArguments.get(0)))
214 ), 191 ),
215 not( 192 not(RSA.EquivTo(role1.getArguments.get(2), role2.getArguments.get(2)))
216 TupleTableAtom.rdf(
217 role1.getArguments.get(2),
218 RSA.EquivTo,
219 role2.getArguments.get(2)
220 )
221 )
222 ) 193 )
223 194
224 /* Rules 5x */ 195 /* Rules 5x */
@@ -234,18 +205,18 @@ class FilteringProgram(query: SelectQuery, constants: List[Term])
234 if bounded contains role2arg0 205 if bounded contains role2arg0
235 if bounded contains role2arg2 206 if bounded contains role2arg2
236 } yield Rule.create( 207 } yield Rule.create(
237 predID( 208 RSA.ID(
238 RSA.rsa(bounded indexOf role1arg0), 209 RSA(bounded indexOf role1arg0),
239 RSA.rsa(bounded indexOf role2arg0) 210 RSA(bounded indexOf role2arg0)
240 ), 211 ),
241 role1 << Forward, 212 role1 << Forward,
242 role2 << Forward, 213 role2 << Forward,
243 predID( 214 RSA.ID(
244 RSA.rsa(bounded indexOf role1arg2), 215 RSA(bounded indexOf role1arg2),
245 RSA.rsa(bounded indexOf role2arg2) 216 RSA(bounded indexOf role2arg2)
246 ), 217 ),
247 TupleTableAtom.rdf(role1arg0, RSA.EquivTo, role2arg0), 218 RSA.EquivTo(role1arg0, role2arg0),
248 not(predNI(role1arg0)) 219 not(RSA.NI(role1arg0))
249 ) 220 )
250 val r5b = for { 221 val r5b = for {
251 role1 <- body.filter(_.isRoleAssertion) 222 role1 <- body.filter(_.isRoleAssertion)
@@ -259,18 +230,18 @@ class FilteringProgram(query: SelectQuery, constants: List[Term])
259 if bounded contains role2arg0 230 if bounded contains role2arg0
260 if bounded contains role2arg2 231 if bounded contains role2arg2
261 } yield Rule.create( 232 } yield Rule.create(
262 predID( 233 RSA.ID(
263 RSA.rsa(bounded indexOf role1arg0), 234 RSA(bounded indexOf role1arg0),
264 RSA.rsa(bounded indexOf role2arg2) 235 RSA(bounded indexOf role2arg2)
265 ), 236 ),
266 role1 << Forward, 237 role1 << Forward,
267 role2 << Backward, 238 role2 << Backward,
268 predID( 239 RSA.ID(
269 RSA.rsa(bounded indexOf role1arg2), 240 RSA(bounded indexOf role1arg2),
270 RSA.rsa(bounded indexOf role2arg0) 241 RSA(bounded indexOf role2arg0)
271 ), 242 ),
272 TupleTableAtom.rdf(role1arg0, RSA.EquivTo, role2arg2), 243 RSA.EquivTo(role1arg0, role2arg2),
273 not(predNI(role1arg0)) 244 not(RSA.NI(role1arg0))
274 ) 245 )
275 val r5c = for { 246 val r5c = for {
276 role1 <- body.filter(_.isRoleAssertion) 247 role1 <- body.filter(_.isRoleAssertion)
@@ -284,18 +255,18 @@ class FilteringProgram(query: SelectQuery, constants: List[Term])
284 if bounded contains role2arg0 255 if bounded contains role2arg0
285 if bounded contains role2arg2 256 if bounded contains role2arg2
286 } yield Rule.create( 257 } yield Rule.create(
287 predID( 258 RSA.ID(
288 RSA.rsa(bounded indexOf role1arg2), 259 RSA(bounded indexOf role1arg2),
289 RSA.rsa(bounded indexOf role2arg2) 260 RSA(bounded indexOf role2arg2)
290 ), 261 ),
291 role1 << Backward, 262 role1 << Backward,
292 role2 << Backward, 263 role2 << Backward,
293 predID( 264 RSA.ID(
294 RSA.rsa(bounded indexOf role1arg0), 265 RSA(bounded indexOf role1arg0),
295 RSA.rsa(bounded indexOf role2arg0) 266 RSA(bounded indexOf role2arg0)
296 ), 267 ),
297 TupleTableAtom.rdf(role1arg2, RSA.EquivTo, role2arg2), 268 RSA.EquivTo(role1arg2, role2arg2),
298 not(predNI(role1arg2)) 269 not(RSA.NI(role1arg2))
299 ) 270 )
300 271
301 /* Rules 6 */ 272 /* Rules 6 */
@@ -308,10 +279,10 @@ class FilteringProgram(query: SelectQuery, constants: List[Term])
308 if bounded contains arg2 279 if bounded contains arg2
309 suffix <- Seq(Forward, Backward) 280 suffix <- Seq(Forward, Backward)
310 } yield Rule.create( 281 } yield Rule.create(
311 predAQ(varV, varW, suffix), 282 RSA.AQ(varV, varW, suffix),
312 role << suffix, 283 role << suffix,
313 predID(RSA.rsa(bounded indexOf arg0), varV), 284 RSA.ID(RSA(bounded indexOf arg0), varV),
314 predID(RSA.rsa(bounded indexOf arg2), varW) 285 RSA.ID(RSA(bounded indexOf arg2), varW)
315 ) 286 )
316 } 287 }
317 288
@@ -319,52 +290,33 @@ class FilteringProgram(query: SelectQuery, constants: List[Term])
319 val r7a = { 290 val r7a = {
320 for (suffix <- List(Forward, Backward)) 291 for (suffix <- List(Forward, Backward))
321 yield Rule.create( 292 yield Rule.create(
322 predTQ(varU, varV, suffix), 293 RSA.TQ(varU, varV, suffix),
323 predAQ(varU, varV, suffix) 294 RSA.AQ(varU, varV, suffix)
324 ) 295 )
325 } 296 }
326 val r7b = { 297 val r7b = {
327 for (suffix <- List(Forward, Backward)) 298 for (suffix <- List(Forward, Backward))
328 yield Rule.create( 299 yield Rule.create(
329 predTQ(varU, varW, suffix), 300 RSA.TQ(varU, varW, suffix),
330 predAQ(varU, varV, suffix), 301 RSA.AQ(varU, varV, suffix),
331 predTQ(varV, varW, suffix) 302 RSA.TQ(varV, varW, suffix)
332 ) 303 )
333 } 304 }
334 305
335 /* Rules 8x */ 306 /* Rules 8x */
336 val r8a = 307 val r8a =
337 for (v <- answer) yield Rule.create(predSP, predQM, not(predNAMED(v))) 308 for (v <- answer) yield Rule.create(RSA.SP, RSA.QM, not(RSA.Named(v)))
338 val r8b = 309 val r8b =
339 Rule.create(predSP, predFK) 310 Rule.create(RSA.SP, RSA.FK)
340 val r8c = 311 val r8c =
341 for (suffix <- List(Forward, Backward)) 312 for (suffix <- List(Forward, Backward))
342 yield Rule.create( 313 yield Rule.create(
343 predSP, 314 RSA.SP,
344 predTQ(varV, varV, suffix) 315 RSA.TQ(varV, varV, suffix)
345 ) 316 )
346 317
347 /* Rule 9 */ 318 /* Rule 9 */
348 val r9 = Rule.create(predANS, predQM, not(predSP)) 319 val r9 = Rule.create(RSA.Ans, RSA.QM, not(RSA.SP))
349
350 // List.empty
351 // .prepended(r9)
352 // .prependedAll(r8c)
353 // .prepended(r8b)
354 // .prependedAll(r8a)
355 // .prependedAll(r7b)
356 // .prependedAll(r7a)
357 // .prependedAll(r6)
358 // .prependedAll(r5c)
359 // .prependedAll(r5b)
360 // .prependedAll(r5a)
361 // .prependedAll(r4c)
362 // .prependedAll(r4b)
363 // .prependedAll(r4a)
364 // .prepended(r3c)
365 // .prepended(r3b)
366 // .prependedAll(r3a)
367 // .prepended(r1)
368 320
369 r1 :: 321 r1 ::
370 r3a ::: r3b :: r3c :: 322 r3a ::: r3b :: r3c ::
@@ -377,26 +329,6 @@ class FilteringProgram(query: SelectQuery, constants: List[Term])
377 List() 329 List()
378 } 330 }
379 331
380 // private def reifyTupleTableAtom(
381 // atom: TupleTableAtom
382 // ): (Option[BindAtom], List[TupleTableAtom]) = {
383 // if (!atom.isRDF) {
384 // // Compute binding atom
385 // val bvar = RSA.getFreshVariable()
386 // val name =
387 // Literal.create(atom.getTupleTableName.toString(), Datatype.XSD_STRING)
388 // val args = atom.getArguments.asScala.toList.prepended(name)
389 // val bind = BindAtom.create(FunctionCall.create("SKOLEM", args: _*), bvar)
390 // // Compute reified atom
391 // def reifiedIRI(i: Int) = atom.getTupleTableName.getName ++ s"_$i"
392 // val atoms = atom.getArguments.asScala.toList.zipWithIndex
393 // .map { case (t, i) => TupleTableAtom.rdf(bvar, reifiedIRI(i), t) }
394 // (Some(bind), atoms)
395 // } else {
396 // (None, List(atom))
397 // }
398 // }
399
400 private def reifyAtom(atom: Atom): (Option[BindAtom], List[Atom]) = { 332 private def reifyAtom(atom: Atom): (Option[BindAtom], List[Atom]) = {
401 atom match { 333 atom match {
402 case atom: TupleTableAtom => atom.reified 334 case atom: TupleTableAtom => atom.reified
diff --git a/src/main/scala/rsacomb/Main.scala b/src/main/scala/rsacomb/Main.scala
index 8270205..31dd5a0 100644
--- a/src/main/scala/rsacomb/Main.scala
+++ b/src/main/scala/rsacomb/Main.scala
@@ -10,7 +10,7 @@ import tech.oxfordsemantic.jrdfox.logic.sparql.statement.SelectQuery
10import tech.oxfordsemantic.jrdfox.logic.expression.{IRI, Term} 10import tech.oxfordsemantic.jrdfox.logic.expression.{IRI, Term}
11 11
12/* Local imports */ 12/* Local imports */
13import rsacomb.RSA._ 13import util.{RDFoxHelpers, RSA}
14 14
15object RSAComb extends App { 15object RSAComb extends App {
16 16
@@ -56,8 +56,10 @@ object RSAComb extends App {
56 if (ontology.isRSA) { 56 if (ontology.isRSA) {
57 57
58 /* Load query */ 58 /* Load query */
59 val query = RDFoxUtil.parseQuery( 59 val query = RDFoxHelpers.parseSelectQuery(
60 """ 60 """
61 PREFIX : <http://example.com/rsa_example.owl#>
62
61 SELECT ?X 63 SELECT ?X
62 WHERE { 64 WHERE {
63 ?X a :D ; 65 ?X a :D ;
@@ -71,8 +73,11 @@ object RSAComb extends App {
71 /* Compute answers to query */ 73 /* Compute answers to query */
72 query match { 74 query match {
73 case Some(query) => { 75 case Some(query) => {
76
77 import implicits.JavaCollections._
78
74 // Open connection to RDFox 79 // Open connection to RDFox
75 val (server, data) = RDFoxUtil.openConnection("AnswerComputation") 80 val (server, data) = RDFoxHelpers.openConnection("AnswerComputation")
76 81
77 { 82 {
78 println("\nQuery") 83 println("\nQuery")
@@ -81,7 +86,7 @@ object RSAComb extends App {
81 86
82 // Step 1. Computing the canonical model 87 // Step 1. Computing the canonical model
83 val canon = ontology.canonicalModel 88 val canon = ontology.canonicalModel
84 data.addRules(canon.rules.asJava) 89 data.addRules(canon.rules)
85 90
86 { 91 {
87 println("\nCanonical Model rules:") 92 println("\nCanonical Model rules:")
@@ -90,129 +95,136 @@ object RSAComb extends App {
90 95
91 // Step 2. Computing the canonical model 96 // Step 2. Computing the canonical model
92 val nis = { 97 val nis = {
93 val query = 98 val query = "SELECT ?Y WHERE { ?X rsa:EquivTo ?Y ; a rsa:Named . }"
94 "SELECT ?Y WHERE { ?X rsa:EquivTo ?Y ; a rsa:NAMED . }" 99 RDFoxHelpers.submitSelectQuery(data, query, RSA.Prefixes).flatten
95 val cursor =
96 data.createCursor(
97 RSA.Prefixes,
98 query,
99 new HashMap[String, String]()
100 );
101 var mul = cursor.open()
102 var iris: List[IRI] = List()
103 while (mul > 0) {
104 println(cursor.getResource(0))
105 iris = cursor.getResource(0) match {
106 case iri: IRI => iri :: iris
107 case _ => iris
108 }
109 mul = cursor.advance()
110 }
111 iris
112 } 100 }
113 val filter = ontology.filteringProgram(query, nis) 101 val filter = ontology.filteringProgram(query, nis)
114 data.addRules(filter.rules.asJava) 102 data.addRules(filter.rules)
115 103
116 { 104 {
117 println("\nFiltering rules") 105 println("\nFiltering rules")
118 filter.rules.foreach(println) 106 filter.rules.foreach(println)
119 } 107 }
120 108
121 def retrieveInstances(pred: String, arity: Int): Unit = {
122 // Build query
123 var query = "SELECT"
124 for (i <- 0 until arity) {
125 query ++= s" ?X$i"
126 }
127 query ++= " WHERE {"
128 for (i <- 0 until arity) {
129 query ++= s" ?S rsa:${pred}_$i ?X$i ."
130 }
131 query ++= " }"
132 // Collect answers
133 RDFoxUtil.submitQuery(
134 data,
135 RSA.Prefixes,
136 query,
137 arity
138 )
139 }
140
141 // Retrieve answers 109 // Retrieve answers
142 println("\nAnswers:") 110 println("\nAnswers:")
143 retrieveInstances("ANS", filter.answer.length) 111 val ans =
112 RDFoxHelpers.queryInternalPredicate(data, "Ans", filter.answer.length)
113 println(ans)
144 114
145 /* DEBUG: adding additional checks 115 /* DEBUG: adding additional checks
146 */ 116 */
147 println("\nIndividuals:")
148 ontology.individuals.foreach(println)
149
150 println("\nThings:")
151 RDFoxUtil.submitQuery(
152 data,
153 RSA.Prefixes,
154 "SELECT ?X { ?X a owl:Thing }",
155 1
156 )
157
158 println("\nNAMEDs:")
159 RDFoxUtil.submitQuery(
160 data,
161 RSA.Prefixes,
162 "SELECT ?X { ?X a rsa:NAMED }",
163 1
164 )
165
166 println("\nNIs:")
167 RDFoxUtil.submitQuery(
168 data,
169 RSA.Prefixes,
170 "SELECT ?X { ?X a rsa:NI }",
171 1
172 )
173
174 // ID instances
175 println("\nID instances:")
176 retrieveInstances("ID", filter.variables.length + 2)
177
178 println("\nSameAs instances:")
179 RDFoxUtil.submitQuery(
180 data,
181 RSA.Prefixes,
182 "SELECT ?X ?Y { ?X rsa:EquivTo ?Y }",
183 2
184 )
185
186 // Unfiltered answers
187 println("\nPossible answers:")
188 retrieveInstances("QM", filter.variables.length)
189
190 // Cycle detected
191 println("\nCycle detection:")
192 retrieveInstances("AQ_f", filter.variables.length + 2)
193 retrieveInstances("AQ_b", filter.variables.length + 2)
194
195 // Forks detected
196 println("\nForks:")
197 retrieveInstances("FK", filter.variables.length)
198
199 // Spurious answers
200 println("\nSpurious answers")
201 retrieveInstances("SP", filter.variables.length)
202
203 { 117 {
204 val cursor = data.createCursor( 118 import suffix.{Forward, Backward}
205 RSA.Prefixes, 119
206 "ASK { :a a :D }", 120 val arity = filter.answer.length + filter.bounded.length
207 new HashMap[String, String]() 121
208 ); 122 println("\nIndividuals:")
209 var mul = cursor.open() 123 ontology.individuals.foreach(println)
210 println(s"Answer: ${mul > 0}") 124
211 cursor.close(); 125 println("\nThings:")
126 val things = RDFoxHelpers.submitSelectQuery(
127 data,
128 """
129 PREFIX owl: <http://www.w3.org/2002/07/owl#>
130
131 SELECT ?X {
132 ?X a owl:Thing
133 }
134 """
135 )
136 println(things)
137
138 println("\nNAMEDs:")
139 val named = RDFoxHelpers.submitSelectQuery(
140 data,
141 """
142 SELECT ?X {
143 ?X a rsa:Named
144 }
145 """,
146 RSA.Prefixes
147 )
148 println(named)
149
150 println("\nNIs:")
151 val nis = RDFoxHelpers.submitSelectQuery(
152 data,
153 """
154 SELECT ?X {
155 ?X a rsa:NI
156 }
157 """,
158 RSA.Prefixes
159 )
160 println(nis)
161
162 // ID instances
163 println("\nIDs:")
164 val ids = RDFoxHelpers.queryInternalPredicate(
165 data,
166 "ID",
167 arity + 2
168 )
169 println(ids)
170
171 println("\nEquivTo:")
172 val equivs = RDFoxHelpers.submitSelectQuery(
173 data,
174 """
175 SELECT ?X ?Y {
176 ?X rsa:EquivTo ?Y
177 }
178 """,
179 RSA.Prefixes
180 )
181 println(equivs)
182
183 // Unfiltered answers
184 println("\nPossible answers:")
185 val qms = RDFoxHelpers.queryInternalPredicate(
186 data,
187 "QM",
188 arity
189 )
190 println(qms)
191
192 // Cycle detected
193 println("\nCycle detection:")
194 val aqf = RDFoxHelpers.queryInternalPredicate(
195 data,
196 "AQ" :: Forward,
197 arity + 2
198 )
199 val aqb = RDFoxHelpers.queryInternalPredicate(
200 data,
201 "AQ" :: Backward,
202 arity + 2
203 )
204 println(aqf)
205 println(aqb)
206
207 // Forks detected
208 println("\nForks:")
209 val fk = RDFoxHelpers.queryInternalPredicate(
210 data,
211 "FK",
212 arity
213 )
214 println(fk)
215
216 // Spurious answers
217 println("\nSpurious answers")
218 val sp = RDFoxHelpers.queryInternalPredicate(
219 data,
220 "SP",
221 arity
222 )
223 println(sp)
212 } 224 }
213 225
214 // Close connection to RDFox 226 // Close connection to RDFox
215 RDFoxUtil.closeConnection(server, data) 227 RDFoxHelpers.closeConnection(server, data)
216 } 228 }
217 case None => {} 229 case None => {}
218 } 230 }
diff --git a/src/main/scala/rsacomb/RDFoxAxiomConverter.scala b/src/main/scala/rsacomb/RDFoxAxiomConverter.scala
index 0368b7c..9b78e8e 100644
--- a/src/main/scala/rsacomb/RDFoxAxiomConverter.scala
+++ b/src/main/scala/rsacomb/RDFoxAxiomConverter.scala
@@ -78,7 +78,7 @@ class RDFoxAxiomConverter(
78 } 78 }
79 79
80 override def visit(axiom: OWLSubObjectPropertyOfAxiom): List[Rule] = { 80 override def visit(axiom: OWLSubObjectPropertyOfAxiom): List[Rule] = {
81 val term1 = RSA.getFreshVariable() 81 val term1 = RSAOntology.genFreshVariable()
82 val subVisitor = 82 val subVisitor =
83 new RDFoxPropertyExprConverter(term, term1, suffix) 83 new RDFoxPropertyExprConverter(term, term1, suffix)
84 val superVisitor = new RDFoxPropertyExprConverter(term, term1, suffix) 84 val superVisitor = new RDFoxPropertyExprConverter(term, term1, suffix)
diff --git a/src/main/scala/rsacomb/RDFoxClassExprConverter.scala b/src/main/scala/rsacomb/RDFoxClassExprConverter.scala
index f3a0dfc..f4187ed 100644
--- a/src/main/scala/rsacomb/RDFoxClassExprConverter.scala
+++ b/src/main/scala/rsacomb/RDFoxClassExprConverter.scala
@@ -26,12 +26,11 @@ import tech.oxfordsemantic.jrdfox.logic.expression.{
26 IRI 26 IRI
27} 27}
28 28
29import rsacomb.SkolemStrategy
30import rsacomb.RDFoxRuleShards
31import org.semanticweb.owlapi.model.OWLObjectPropertyExpression 29import org.semanticweb.owlapi.model.OWLObjectPropertyExpression
32import org.semanticweb.owlapi.model.OWLObjectProperty 30import org.semanticweb.owlapi.model.OWLObjectProperty
33 31
34import suffix.{RSASuffix, Empty} 32import suffix.{RSASuffix, Empty}
33import util.RSA
35 34
36object RDFoxClassExprConverter { 35object RDFoxClassExprConverter {
37 36
@@ -61,7 +60,7 @@ class RDFoxClassExprConverter(
61 suffix: RSASuffix 60 suffix: RSASuffix
62) extends OWLClassExpressionVisitorEx[RDFoxRuleShards] { 61) extends OWLClassExpressionVisitorEx[RDFoxRuleShards] {
63 62
64 import RDFoxUtil.owlapi2rdfox; 63 import implicits.RDFox._
65 64
66 // OWLClass 65 // OWLClass
67 override def visit(expr: OWLClass): RDFoxRuleShards = { 66 override def visit(expr: OWLClass): RDFoxRuleShards = {
@@ -99,7 +98,7 @@ class RDFoxClassExprConverter(
99 98
100 // OWLObjectSomeValuesFrom 99 // OWLObjectSomeValuesFrom
101 override def visit(expr: OWLObjectSomeValuesFrom): RDFoxRuleShards = { 100 override def visit(expr: OWLObjectSomeValuesFrom): RDFoxRuleShards = {
102 val y = RSA.getFreshVariable() 101 val y = RSAOntology.genFreshVariable()
103 // Here we are assuming a role name 102 // Here we are assuming a role name
104 val prop = expr.getProperty() 103 val prop = expr.getProperty()
105 // Computes the result of rule skolemization. Depending on the used 104 // Computes the result of rule skolemization. Depending on the used
@@ -110,14 +109,7 @@ class RDFoxClassExprConverter(
110 case SkolemStrategy.Constant(c) => (List(), List(), c) 109 case SkolemStrategy.Constant(c) => (List(), List(), c)
111 case SkolemStrategy.ConstantRSA(c) => { 110 case SkolemStrategy.ConstantRSA(c) => {
112 if (unsafe.contains(prop)) 111 if (unsafe.contains(prop))
113 ( 112 (List(RSA.PE(term, c), RSA.U(c)), List(), c)
114 List(
115 TupleTableAtom.rdf(term, RSA.rsa("PE"), c),
116 TupleTableAtom.rdf(c, IRI.RDF_TYPE, RSA.rsa("U"))
117 ),
118 List(),
119 c
120 )
121 else 113 else
122 (List(), List(), c) 114 (List(), List(), c)
123 } 115 }
@@ -143,7 +135,8 @@ class RDFoxClassExprConverter(
143 // OWLObjectMaxCardinality 135 // OWLObjectMaxCardinality
144 override def visit(expr: OWLObjectMaxCardinality): RDFoxRuleShards = { 136 override def visit(expr: OWLObjectMaxCardinality): RDFoxRuleShards = {
145 // TODO: again, no hardcoded variables 137 // TODO: again, no hardcoded variables
146 val vars = List(RSA.getFreshVariable(), RSA.getFreshVariable()) 138 val vars =
139 List(RSAOntology.genFreshVariable(), RSAOntology.genFreshVariable())
147 val classResult = RDFoxClassExprConverter.merge( 140 val classResult = RDFoxClassExprConverter.merge(
148 vars 141 vars
149 .map(new RDFoxClassExprConverter(_, unsafe, skolem, suffix)) 142 .map(new RDFoxClassExprConverter(_, unsafe, skolem, suffix))
diff --git a/src/main/scala/rsacomb/RDFoxPropertyExprConverter.scala b/src/main/scala/rsacomb/RDFoxPropertyExprConverter.scala
index 525ec62..826e965 100644
--- a/src/main/scala/rsacomb/RDFoxPropertyExprConverter.scala
+++ b/src/main/scala/rsacomb/RDFoxPropertyExprConverter.scala
@@ -17,7 +17,7 @@ class RDFoxPropertyExprConverter(
17) extends OWLPropertyExpressionVisitorEx[List[TupleTableAtom]] { 17) extends OWLPropertyExpressionVisitorEx[List[TupleTableAtom]] {
18 18
19 // Automatically converts OWLAPI types into RDFox equivalent types. 19 // Automatically converts OWLAPI types into RDFox equivalent types.
20 import RDFoxUtil.owlapi2rdfox; 20 import implicits.RDFox._
21 21
22 override def visit(expr: OWLObjectProperty): List[TupleTableAtom] = { 22 override def visit(expr: OWLObjectProperty): List[TupleTableAtom] = {
23 val base = expr.getIRI.getIRIString 23 val base = expr.getIRI.getIRIString
diff --git a/src/main/scala/rsacomb/RDFoxUtil.scala b/src/main/scala/rsacomb/RDFoxUtil.scala
deleted file mode 100644
index 653c51f..0000000
--- a/src/main/scala/rsacomb/RDFoxUtil.scala
+++ /dev/null
@@ -1,113 +0,0 @@
1package rsacomb
2
3/* Java imports */
4import java.util.HashMap
5import java.io.StringReader
6import tech.oxfordsemantic.jrdfox.Prefixes
7import tech.oxfordsemantic.jrdfox.logic.sparql.statement.{Query, SelectQuery}
8import tech.oxfordsemantic.jrdfox.client.{
9 ConnectionFactory,
10 ServerConnection,
11 DataStoreConnection
12}
13import tech.oxfordsemantic.jrdfox.formats.SPARQLParser
14
15import tech.oxfordsemantic.jrdfox.logic.expression.{IRI => RDFox_IRI}
16import org.semanticweb.owlapi.model.{IRI => OWL_IRI}
17
18import scala.collection.JavaConverters._
19
20object RDFoxUtil {
21
22 implicit def rdfox2owlapi(iri: RDFox_IRI): OWL_IRI = {
23 OWL_IRI.create(iri.getIRI)
24 }
25
26 implicit def owlapi2rdfox(iri: OWL_IRI): RDFox_IRI = {
27 RDFox_IRI.create(iri.getIRIString())
28 }
29
30 implicit def stringToRDFoxIRI(iri: String): RDFox_IRI = {
31 RDFox_IRI.create(iri)
32 }
33
34 implicit def javaToScalaList[A](list: java.util.List[A]): List[A] = {
35 list.asScala.toList
36 }
37
38 implicit def scalaToJavaList[A](list: List[A]): java.util.List[A] = {
39 list.asJava
40 }
41
42 def openConnection(
43 dataStore: String
44 ): (ServerConnection, DataStoreConnection) = {
45 /* Create local server connection
46 */
47 val serverUrl = "rdfox:local"
48 val role = ""
49 val password = ""
50 val server =
51 ConnectionFactory.newServerConnection(serverUrl, role, password)
52
53 /* Create datastore connection
54 */
55 val parameters = new HashMap[String, String]()
56 parameters.put("owl-in-rdf-support", "relaxed")
57 //parameters.put("equality", "noUNA")
58 server.createDataStore(dataStore, "par-complex-nn", parameters)
59 val data = server.newDataStoreConnection(dataStore)
60
61 (server, data)
62 }
63
64 def parseQuery(
65 query: String,
66 prefixes: Prefixes = RSA.Prefixes
67 ): Option[SelectQuery] = {
68 val parser = new SPARQLParser(
69 prefixes,
70 new StringReader(query)
71 )
72 // NOTE: return only conjunctive queries for now (SelectQuery)
73 parser.parseSingleQuery() match {
74 case q: SelectQuery => Some(q)
75 case _ => None
76 }
77 }
78
79 def submitQuery(
80 data: DataStoreConnection,
81 prefixes: Prefixes,
82 query: String,
83 answers: Int
84 ): Unit = {
85 println(s"\nQUERY {\n$query\n}")
86 val cursor = data.createCursor(
87 prefixes,
88 query,
89 new HashMap[String, String]()
90 );
91 var mul = cursor.open()
92 while (mul > 0) {
93 print("Answer: ")
94 for (i <- 0 until answers) {
95 val res = cursor.getResource(i)
96 print(s"$res ")
97 }
98 println()
99 mul = cursor.advance()
100 }
101 cursor.close();
102 println(s"QUERY END")
103 }
104
105 def closeConnection(
106 server: ServerConnection,
107 data: DataStoreConnection
108 ): Unit = {
109 server.close();
110 data.close();
111 }
112
113} // object RDFoxUtil
diff --git a/src/main/scala/rsacomb/RSA.scala b/src/main/scala/rsacomb/RSA.scala
index b0e140b..1b2aa9c 100644
--- a/src/main/scala/rsacomb/RSA.scala
+++ b/src/main/scala/rsacomb/RSA.scala
@@ -1,11 +1,16 @@
1package rsacomb 1package rsacomb.util
2 2
3/* Java imports */ 3/* Java imports */
4import java.util.Map 4import java.util.Map
5 5
6import tech.oxfordsemantic.jrdfox.formats.SPARQLParser 6import tech.oxfordsemantic.jrdfox.formats.SPARQLParser
7import tech.oxfordsemantic.jrdfox.Prefixes 7import tech.oxfordsemantic.jrdfox.Prefixes
8import tech.oxfordsemantic.jrdfox.logic.expression.{Variable, IRI} 8import tech.oxfordsemantic.jrdfox.logic.datalog.{
9 TupleTableAtom,
10 TupleTableName,
11 Negation
12}
13import tech.oxfordsemantic.jrdfox.logic.expression.{Term, Variable, IRI}
9import org.semanticweb.owlapi.model.OWLOntology 14import org.semanticweb.owlapi.model.OWLOntology
10import org.semanticweb.owlapi.model.{ 15import org.semanticweb.owlapi.model.{
11 OWLAxiom, 16 OWLAxiom,
@@ -13,51 +18,83 @@ import org.semanticweb.owlapi.model.{
13 OWLObjectPropertyExpression 18 OWLObjectPropertyExpression
14} 19}
15 20
21import rsacomb.suffix.RSASuffix
22
16// Debug only 23// Debug only
17import scala.collection.JavaConverters._ 24import scala.collection.JavaConverters._
18 25
19object RSA extends RSAAxiom { 26object RSA {
20 27
21 val Prefixes: Prefixes = new Prefixes() 28 val Prefixes: Prefixes = new Prefixes()
22 Prefixes.declarePrefix(":", "http://example.com/rsa_example.owl#")
23 Prefixes.declarePrefix("rsa:", "http://127.0.0.1/") 29 Prefixes.declarePrefix("rsa:", "http://127.0.0.1/")
24 Prefixes.declarePrefix("rdf:", "http://www.w3.org/1999/02/22-rdf-syntax-ns#")
25 Prefixes.declarePrefix("rdfs:", "http://www.w3.org/2000/01/rdf-schema#")
26 Prefixes.declarePrefix("owl:", "http://www.w3.org/2002/07/owl#")
27 30
28 val EquivTo: IRI = this.rsa("EquivTo") 31 private def atom(name: IRI, vars: List[Term]) =
29 val Named: IRI = this.rsa("NAMED") 32 TupleTableAtom.create(TupleTableName.create(name.getIRI), vars: _*)
33
34 def PE(t1: Term, t2: Term) =
35 TupleTableAtom.rdf(t1, RSA("PE"), t2)
36
37 def U(t: Term) =
38 TupleTableAtom.rdf(t, IRI.RDF_TYPE, RSA("U"))
39
40 def In(t: Term)(implicit set: Term) =
41 TupleTableAtom.rdf(t, RSA("In"), set)
42
43 def notIn(t: Term)(implicit set: Term) = Negation.create(In(t)(set))
30 44
31 // Counter used to implement a simple fresh variable generator 45 def EquivTo(t1: Term, t2: Term) =
32 private var counter = -1; 46 TupleTableAtom.rdf(t1, RSA("EquivTo"), t2)
33 47
34 def getFreshVariable(): Variable = { 48 def QM(implicit variables: (List[Term], List[Term])) = {
35 counter += 1 49 val (answer, bounded) = variables
36 Variable.create(f"I$counter%03d") 50 atom(RSA("QM"), answer ::: bounded)
37 } 51 }
38 52
39 def base(name: Any): IRI = 53 def ID(t1: Term, t2: Term)(implicit variables: (List[Term], List[Term])) = {
40 IRI.create( 54 val (answer, bounded) = variables
41 Prefixes.getPrefixIRIsByPrefixName.get(":").getIRI 55 atom(RSA("ID"), (answer ::: bounded) :+ t1 :+ t2)
42 + name.toString 56 }
43 )
44 57
45 def rsa(name: Any): IRI = 58 def Named(t: Term) =
46 IRI.create( 59 TupleTableAtom.rdf(t, IRI.RDF_TYPE, RSA("Named"))
47 Prefixes.getPrefixIRIsByPrefixName.get("rsa:").getIRI 60
48 + name.toString 61 def Thing(t: Term) =
49 ) 62 TupleTableAtom.rdf(t, IRI.RDF_TYPE, IRI.THING)
50 63
51 def hashed( 64 def NI(t: Term) =
52 cls1: OWLClass, 65 TupleTableAtom.rdf(t, IRI.RDF_TYPE, RSA("NI"))
53 prop: OWLObjectPropertyExpression,
54 cls2: OWLClass
55 ): String =
56 (cls1, prop, cls2).hashCode.toString
57 66
58 def hashed(axiom: OWLAxiom): String = { 67 def TQ(t1: Term, t2: Term, sx: RSASuffix)(implicit
59 val (cls1, prop, cls2) = axiom.toTriple.get 68 variables: (List[Term], List[Term])
60 this.hashed(cls1, prop, cls2) 69 ) = {
70 val (answer, bounded) = variables
71 atom(RSA("TQ" :: sx), (answer ::: bounded) :+ t1 :+ t2)
61 } 72 }
62 73
63} // object RSA 74 def AQ(t1: Term, t2: Term, sx: RSASuffix)(implicit
75 variables: (List[Term], List[Term])
76 ) = {
77 val (answer, bounded) = variables
78 atom(RSA("AQ" :: sx), (answer ::: bounded) :+ t1 :+ t2)
79 }
80
81 def FK(implicit variables: (List[Term], List[Term])) = {
82 val (answer, bounded) = variables
83 atom(RSA("FK"), answer ::: bounded)
84 }
85
86 def SP(implicit variables: (List[Term], List[Term])) = {
87 val (answer, bounded) = variables
88 atom(RSA("SP"), answer ::: bounded)
89 }
90
91 def Ans(implicit variables: (List[Term], List[Term])) = {
92 val (answer, _) = variables
93 atom(RSA("Ans"), answer)
94 }
95
96 def apply(name: Any): IRI =
97 IRI.create(
98 Prefixes.getPrefixIRIsByPrefixName.get("rsa:").getIRI + name.toString
99 )
100}
diff --git a/src/main/scala/rsacomb/RSAAtom.scala b/src/main/scala/rsacomb/RSAAtom.scala
index a65c168..8832226 100644
--- a/src/main/scala/rsacomb/RSAAtom.scala
+++ b/src/main/scala/rsacomb/RSAAtom.scala
@@ -11,7 +11,7 @@ import tech.oxfordsemantic.jrdfox.logic.expression.{IRI}
11import scala.collection.JavaConverters._ 11import scala.collection.JavaConverters._
12 12
13import rsacomb.suffix.{RSASuffix, Nth} 13import rsacomb.suffix.{RSASuffix, Nth}
14import rsacomb.RSA 14import rsacomb.RSAOntology
15 15
16/* Is this the best way to determine if an atom is an RDF triple? 16/* Is this the best way to determine if an atom is an RDF triple?
17 * Note that we can't use `getNumberOfArguments()` because is not 17 * Note that we can't use `getNumberOfArguments()` because is not
@@ -32,7 +32,7 @@ trait RSAAtom {
32 32
33 implicit class RSAAtom(val atom: TupleTableAtom) { 33 implicit class RSAAtom(val atom: TupleTableAtom) {
34 34
35 import rsacomb.RDFoxUtil.stringToRDFoxIRI 35 import RDFox._
36 36
37 val name: String = atom.getTupleTableName.getName 37 val name: String = atom.getTupleTableName.getName
38 38
@@ -74,7 +74,7 @@ trait RSAAtom {
74 if (isRDF) { 74 if (isRDF) {
75 (None, List(atom)) 75 (None, List(atom))
76 } else { 76 } else {
77 val bvar = RSA.getFreshVariable() 77 val bvar = RSAOntology.genFreshVariable()
78 val str = Literal.create(name, Datatype.XSD_STRING) 78 val str = Literal.create(name, Datatype.XSD_STRING)
79 val args = atom.getArguments.asScala.toList 79 val args = atom.getArguments.asScala.toList
80 val skolem = FunctionCall.create("SKOLEM", str :: args: _*) 80 val skolem = FunctionCall.create("SKOLEM", str :: args: _*)
diff --git a/src/main/scala/rsacomb/RSAAxiom.scala b/src/main/scala/rsacomb/RSAAxiom.scala
index 3cd9a9d..08de5b7 100644
--- a/src/main/scala/rsacomb/RSAAxiom.scala
+++ b/src/main/scala/rsacomb/RSAAxiom.scala
@@ -38,6 +38,17 @@ trait RSAAxiom {
38 case object T5 extends RSAAxiomType // A ⊑ ∃R.B 38 case object T5 extends RSAAxiomType // A ⊑ ∃R.B
39 } 39 }
40 40
41 object RSAAxiom {
42
43 def hashed(
44 cls1: OWLClass,
45 prop: OWLObjectPropertyExpression,
46 cls2: OWLClass
47 ): String =
48 (cls1, prop, cls2).hashCode.toString
49
50 }
51
41 /* Implements additional features on top of `OWLAxiom` from 52 /* Implements additional features on top of `OWLAxiom` from
42 * the OWLAPI. 53 * the OWLAPI.
43 */ 54 */
@@ -137,6 +148,8 @@ trait RSAAxiom {
137 } 148 }
138 cls2 <- Some(someValues.getFiller) collect { case a: OWLClass => a } 149 cls2 <- Some(someValues.getFiller) collect { case a: OWLClass => a }
139 } yield (cls1, prop, cls2) 150 } yield (cls1, prop, cls2)
151
152 lazy val hashed: String = (RSAAxiom.hashed _) tupled toTriple.get
140 } 153 }
141 154
142} // trait RSAAxiom 155} // trait RSAAxiom
diff --git a/src/main/scala/rsacomb/RSAOntology.scala b/src/main/scala/rsacomb/RSAOntology.scala
index 52bff37..1a5e4ca 100644
--- a/src/main/scala/rsacomb/RSAOntology.scala
+++ b/src/main/scala/rsacomb/RSAOntology.scala
@@ -47,14 +47,23 @@ import tech.oxfordsemantic.jrdfox.logic._
47import org.semanticweb.owlapi.model.OWLObjectInverseOf 47import org.semanticweb.owlapi.model.OWLObjectInverseOf
48 48
49import suffix.{Empty, Forward, Backward, Inverse} 49import suffix.{Empty, Forward, Backward, Inverse}
50import util.{RDFoxHelpers, RSA}
50 51
51object RSAOntology { 52object RSAOntology {
52 53
54 // Counter used to implement a simple fresh variable generator
55 private var counter = -1;
56
53 def apply(ontology: OWLOntology): RSAOntology = new RSAOntology(ontology) 57 def apply(ontology: OWLOntology): RSAOntology = new RSAOntology(ontology)
54 58
55 def apply(ontology: File): RSAOntology = 59 def apply(ontology: File): RSAOntology =
56 new RSAOntology(loadOntology(ontology)) 60 new RSAOntology(loadOntology(ontology))
57 61
62 def genFreshVariable(): Variable = {
63 counter += 1
64 Variable.create(f"I$counter%03d")
65 }
66
58 private def loadOntology(onto: File): OWLOntology = { 67 private def loadOntology(onto: File): OWLOntology = {
59 val manager = OWLManager.createOWLOntologyManager() 68 val manager = OWLManager.createOWLOntologyManager()
60 manager.loadOntologyFromOntologyDocument(onto) 69 manager.loadOntologyFromOntologyDocument(onto)
@@ -94,7 +103,7 @@ class RSAOntology(val ontology: OWLOntology) extends RSAAxiom {
94 .getIndividualsInSignature() 103 .getIndividualsInSignature()
95 .asScala 104 .asScala
96 .map(_.getIRI) 105 .map(_.getIRI)
97 .map(RDFoxUtil.owlapi2rdfox) 106 .map(implicits.RDFox.owlapiToRdfoxIri)
98 .toList 107 .toList
99 108
100 val concepts: List[OWLClass] = 109 val concepts: List[OWLClass] =
@@ -133,7 +142,7 @@ class RSAOntology(val ontology: OWLOntology) extends RSAAxiom {
133 val datalog = for { 142 val datalog = for {
134 axiom <- axioms 143 axiom <- axioms
135 visitor = new RDFoxAxiomConverter( 144 visitor = new RDFoxAxiomConverter(
136 RSA.getFreshVariable(), 145 RSAOntology.genFreshVariable(),
137 unsafe, 146 unsafe,
138 SkolemStrategy.ConstantRSA(axiom.toString), 147 SkolemStrategy.ConstantRSA(axiom.toString),
139 Empty 148 Empty
@@ -146,9 +155,9 @@ class RSAOntology(val ontology: OWLOntology) extends RSAAxiom {
146 //datalog.foreach(println) 155 //datalog.foreach(println)
147 156
148 // Open connection with RDFox 157 // Open connection with RDFox
149 val (server, data) = RDFoxUtil.openConnection("RSACheck") 158 val (server, data) = RDFoxHelpers.openConnection("RSACheck")
150 // Add Data (hardcoded for now) 159 // Add Data (hardcoded for now)
151 data.importData(UpdateType.ADDITION, RSA.Prefixes, ":a a :A .") 160 //data.importData(UpdateType.ADDITION, RSA.Prefixes, ":a a :A .")
152 161
153 /* Add built-in rules 162 /* Add built-in rules
154 */ 163 */
@@ -176,7 +185,7 @@ class RSAOntology(val ontology: OWLOntology) extends RSAAxiom {
176 //println(graph) 185 //println(graph)
177 186
178 // Close connection to RDFox 187 // Close connection to RDFox
179 RDFoxUtil.closeConnection(server, data) 188 RDFoxHelpers.closeConnection(server, data)
180 189
181 /* To check if the graph is tree-like we check for acyclicity in a 190 /* To check if the graph is tree-like we check for acyclicity in a
182 * undirected graph. 191 * undirected graph.
@@ -291,8 +300,8 @@ class RSAOntology(val ontology: OWLOntology) extends RSAAxiom {
291 val role = axiom.objectPropertyExpressionsInSignature(0) 300 val role = axiom.objectPropertyExpressionsInSignature(0)
292 if (this.confl(role).contains(role)) { 301 if (this.confl(role).contains(role)) {
293 Set( 302 Set(
294 RSA.rsa("v0_" ++ RSA.hashed(axiom)), 303 RSA("v0_" ++ axiom.hashed),
295 RSA.rsa("v1_" ++ RSA.hashed(axiom)) 304 RSA("v1_" ++ axiom.hashed)
296 ) 305 )
297 } else { 306 } else {
298 Set() 307 Set()
@@ -354,15 +363,15 @@ class RSAOntology(val ontology: OWLOntology) extends RSAAxiom {
354 classC <- classes 363 classC <- classes
355 // Keeping this check for now 364 // Keeping this check for now
356 if !unsafeRoles.contains(roleS) 365 if !unsafeRoles.contains(roleS)
357 tripleARB = RSA.hashed(classA, roleR, classB) 366 tripleARB = RSAAxiom.hashed(classA, roleR, classB)
358 tripleDSC = RSA.hashed(classD, roleS, classC) 367 tripleDSC = RSAAxiom.hashed(classD, roleS, classC)
359 individual = 368 individual =
360 if (tripleARB > tripleDSC) { 369 if (tripleARB > tripleDSC) {
361 RSA.rsa("v1_" ++ tripleDSC) 370 RSA("v1_" ++ tripleDSC)
362 } else { 371 } else {
363 // Note that this is also the case for 372 // Note that this is also the case for
364 // `tripleARB == tripleDSC` 373 // `tripleARB == tripleDSC`
365 RSA.rsa("v0_" ++ tripleDSC) 374 RSA("v0_" ++ tripleDSC)
366 } 375 }
367 } yield individual 376 } yield individual
368 } 377 }
diff --git a/src/main/scala/rsacomb/implicits/JavaCollections.scala b/src/main/scala/rsacomb/implicits/JavaCollections.scala
new file mode 100644
index 0000000..69e825b
--- /dev/null
+++ b/src/main/scala/rsacomb/implicits/JavaCollections.scala
@@ -0,0 +1,13 @@
1package rsacomb.implicits
2
3import scala.collection.JavaConverters._
4
5object JavaCollections {
6
7 implicit def javaToScalaList[A](list: java.util.List[A]): List[A] =
8 list.asScala.toList
9
10 implicit def scalaToJavaList[A](list: List[A]): java.util.List[A] =
11 list.asJava
12
13}
diff --git a/src/main/scala/rsacomb/implicits/RDFox.scala b/src/main/scala/rsacomb/implicits/RDFox.scala
new file mode 100644
index 0000000..44b7c01
--- /dev/null
+++ b/src/main/scala/rsacomb/implicits/RDFox.scala
@@ -0,0 +1,20 @@
1package rsacomb.implicits
2
3import tech.oxfordsemantic.jrdfox.logic.expression.{IRI => RDFoxIRI}
4import org.semanticweb.owlapi.model.{IRI => OWLIRI}
5
6object RDFox {
7
8 implicit def rdfoxToOwlapiIri(iri: RDFoxIRI): OWLIRI = {
9 OWLIRI.create(iri.getIRI)
10 }
11
12 implicit def owlapiToRdfoxIri(iri: OWLIRI): RDFoxIRI = {
13 RDFoxIRI.create(iri.getIRIString())
14 }
15
16 implicit def stringToRdfoxIri(iri: String): RDFoxIRI = {
17 RDFoxIRI.create(iri)
18 }
19
20}
diff --git a/src/main/scala/rsacomb/util/RDFoxHelpers.scala b/src/main/scala/rsacomb/util/RDFoxHelpers.scala
new file mode 100644
index 0000000..9856e27
--- /dev/null
+++ b/src/main/scala/rsacomb/util/RDFoxHelpers.scala
@@ -0,0 +1,100 @@
1package rsacomb.util
2
3import java.util.{Map => JMap, HashMap => JHashMap}
4import java.io.StringReader
5import tech.oxfordsemantic.jrdfox.Prefixes
6import tech.oxfordsemantic.jrdfox.client.{
7 ConnectionFactory,
8 ServerConnection,
9 DataStoreConnection
10}
11import tech.oxfordsemantic.jrdfox.formats.SPARQLParser
12import tech.oxfordsemantic.jrdfox.logic.expression.Resource
13import tech.oxfordsemantic.jrdfox.logic.sparql.statement.SelectQuery
14
15import rsacomb.suffix.Nth
16
17object RDFoxHelpers {
18
19 def openConnection(
20 dataStore: String,
21 opts: JMap[String, String] = new JHashMap[String, String]()
22 ): (ServerConnection, DataStoreConnection) = {
23 /* Create local server connection
24 */
25 val serverUrl = "rdfox:local"
26 val role = ""
27 val password = ""
28 val server =
29 ConnectionFactory.newServerConnection(serverUrl, role, password)
30
31 /* Create datastore connection
32 */
33 // parameters.put("owl-in-rdf-support", "relaxed")
34 // parameters.put("equality", "noUNA")
35 server.createDataStore(dataStore, "par-complex-nn", opts)
36 val data = server.newDataStoreConnection(dataStore)
37
38 (server, data)
39 }
40
41 def parseSelectQuery(
42 query: String,
43 prefixes: Prefixes = new Prefixes()
44 ): Option[SelectQuery] = {
45 val parser = new SPARQLParser(
46 prefixes,
47 new StringReader(query)
48 )
49 parser.parseSingleQuery() match {
50 case q: SelectQuery => Some(q)
51 case _ => None
52 }
53 }
54
55 def submitSelectQuery(
56 data: DataStoreConnection,
57 query: String,
58 prefixes: Prefixes = new Prefixes(),
59 opts: JMap[String, String] = new JHashMap[String, String]()
60 ): List[List[Resource]] = {
61 val cursor = data.createCursor(prefixes, query, opts)
62 var answers: List[List[Resource]] = List()
63 var mul = cursor.open()
64 while (mul > 0) {
65 val answer =
66 (0 until cursor.getArity).map(cursor.getResource(_)).toList
67 answers = answer :: answers
68 mul = cursor.advance()
69 }
70 cursor.close();
71 answers
72 }
73
74 def queryInternalPredicate(
75 data: DataStoreConnection,
76 pred: String,
77 arity: Int,
78 opts: JMap[String, String] = new JHashMap[String, String]()
79 ): List[List[Resource]] = {
80 var query = "SELECT"
81 for (i <- 0 until arity) {
82 query ++= s" ?X$i"
83 }
84 query ++= " WHERE {"
85 for (i <- 0 until arity) {
86 query ++= s" ?S rsa:${pred :: Nth(i)} ?X$i ."
87 }
88 query ++= " }"
89 submitSelectQuery(data, query, RSA.Prefixes, opts)
90 }
91
92 def closeConnection(
93 server: ServerConnection,
94 data: DataStoreConnection
95 ): Unit = {
96 server.close();
97 data.close();
98 }
99
100}