aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/example
diff options
context:
space:
mode:
authorFederico Igne <federico.igne@cs.ox.ac.uk>2020-07-15 17:44:00 +0100
committerFederico Igne <federico.igne@cs.ox.ac.uk>2020-07-15 17:44:00 +0100
commit58b8d3c11a9deebb40e21c70d0b085d01cada745 (patch)
tree2c729106e6f32cd2bdc18f8e24adff242f856663 /src/main/scala/example
parentb1e53c0b9f85783c9c6382eb69380b38cd43a566 (diff)
downloadRSAComb-58b8d3c11a9deebb40e21c70d0b085d01cada745.tar.gz
RSAComb-58b8d3c11a9deebb40e21c70d0b085d01cada745.zip
Add reworked code from previous repo
Diffstat (limited to 'src/main/scala/example')
-rw-r--r--src/main/scala/example/RDFoxAxiomConverter.scala58
-rw-r--r--src/main/scala/example/RDFoxClassExprConverter.scala119
-rw-r--r--src/main/scala/example/RDFoxPropertyExprConverter.scala23
-rw-r--r--src/main/scala/example/RDFoxRuleShards.scala6
-rw-r--r--src/main/scala/example/RSAComb.scala138
-rw-r--r--src/main/scala/example/SkolemStrategy.scala46
6 files changed, 390 insertions, 0 deletions
diff --git a/src/main/scala/example/RDFoxAxiomConverter.scala b/src/main/scala/example/RDFoxAxiomConverter.scala
new file mode 100644
index 0000000..0a6272f
--- /dev/null
+++ b/src/main/scala/example/RDFoxAxiomConverter.scala
@@ -0,0 +1,58 @@
1package rsacomb
2
3import org.semanticweb.owlapi.model.{OWLAxiom, OWLSubClassOfAxiom, OWLEquivalentClassesAxiom}
4import org.semanticweb.owlapi.model.OWLAxiomVisitorEx
5
6import tech.oxfordsemantic.jrdfox.logic.Rule
7import tech.oxfordsemantic.jrdfox.logic.{Atom, Term, Literal, Individual}
8
9import scala.collection.JavaConverters._
10
11import rsacomb.SkolemStrategy
12import rsacomb.RDFoxRuleShards
13
14object RDFoxAxiomConverter {
15
16 def apply(term : Term, skolem : SkolemStrategy) : RDFoxAxiomConverter =
17 new RDFoxAxiomConverter(term, skolem)
18
19 def apply(term : Term) : RDFoxAxiomConverter =
20 new RDFoxAxiomConverter(term, SkolemStrategy.None)
21
22} // object RDFoxAxiomConverter
23
24class RDFoxAxiomConverter(term : Term, skolem : SkolemStrategy)
25 extends OWLAxiomVisitorEx[List[Rule]]
26{
27
28 override
29 def visit(axiom : OWLSubClassOfAxiom) : List[Rule] = {
30 // Skolemization is needed only for the head of an axiom
31 val subVisitor = new RDFoxClassExprConverter(term,SkolemStrategy.None)
32 val superVisitor = new RDFoxClassExprConverter(term, skolem)
33 // Each visitor returns a `RDFoxRuleShards`, a tuple (res,ext):
34 // - the `res` List is a list of atoms resulting from the conversion
35 // of the axiom.
36 // - for some Class Expressions appearing in the head of an Axiom,
37 // the conversion might produce atoms that need to appear in the
38 // body (and not in the head) of the rule. This is what the `ext`
39 // List is for.
40 val sub = axiom.getSubClass.accept(subVisitor)
41 val sup = axiom.getSuperClass.accept(superVisitor)
42 val head = sup.res.asJava
43 val body = (sub.res ++ sup.ext).asJava
44 List(Rule.create(head,body))
45 }
46
47 override
48 def visit(axiom : OWLEquivalentClassesAxiom) : List[Rule] = {
49 for {
50 axiom1 <- axiom.asPairwiseAxioms.asScala.toList
51 axiom2 <- axiom1.asOWLSubClassOfAxioms.asScala.toList
52 rule <- axiom2.accept(this)
53 } yield rule
54 }
55
56 def doDefault(axiom : OWLAxiom) : List[Rule] = List()
57
58} // class RDFoxAxiomConverter
diff --git a/src/main/scala/example/RDFoxClassExprConverter.scala b/src/main/scala/example/RDFoxClassExprConverter.scala
new file mode 100644
index 0000000..3e60461
--- /dev/null
+++ b/src/main/scala/example/RDFoxClassExprConverter.scala
@@ -0,0 +1,119 @@
1package rsacomb
2
3import scala.collection.JavaConverters._
4import java.util.stream.{Stream,Collectors}
5
6import org.semanticweb.owlapi.model.{OWLClassExpression, OWLClass, OWLObjectSomeValuesFrom, OWLObjectIntersectionOf, OWLObjectOneOf, OWLObjectMaxCardinality}
7import org.semanticweb.owlapi.model.OWLClassExpressionVisitorEx
8import tech.oxfordsemantic.jrdfox.logic.{AtomicFormula, Bind,BuiltinFunctionCall}
9import tech.oxfordsemantic.jrdfox.logic.{Atom, Predicate, Term, Variable, Literal, Individual}
10
11import rsacomb.SkolemStrategy
12import rsacomb.RDFoxRuleShards
13
14object RDFoxClassExprConverter {
15
16 def apply(term : Term, skolem : SkolemStrategy) : RDFoxClassExprConverter =
17 new RDFoxClassExprConverter(term, skolem)
18
19 def apply(term : Term) : RDFoxClassExprConverter =
20 new RDFoxClassExprConverter(term, SkolemStrategy.None)
21
22 def merge(rules : List[RDFoxRuleShards]) : RDFoxRuleShards = {
23 rules.foldLeft(RDFoxRuleShards(List(),List())) {
24 (r1,r2) =>
25 RDFoxRuleShards(
26 r1.res ++ r2.res,
27 r1.ext ++ r2.ext
28 )
29 }
30 }
31
32} // object RDFoxClassExprConverter
33
34class RDFoxClassExprConverter(term : Term, skolem : SkolemStrategy)
35 extends OWLClassExpressionVisitorEx[RDFoxRuleShards]
36{
37
38 // OWLClass
39 override
40 def visit(expr : OWLClass) : RDFoxRuleShards = {
41 val name = expr.getIRI.getIRIString
42 val atom = List(Atom.create(Predicate.create(name), term))
43 RDFoxRuleShards(atom,List())
44 }
45
46 // OWLObjectIntersectionOf
47 override
48 def visit(expr : OWLObjectIntersectionOf) : RDFoxRuleShards = {
49 val visitor = new RDFoxClassExprConverter(term,skolem)
50 // TODO: maybe using `flatMap` instead of `merge` + `map` works as well
51 RDFoxClassExprConverter.merge (
52 expr.asConjunctSet.asScala.toList
53 .map((e : OWLClassExpression) => e.accept(visitor))
54 )
55 }
56
57 // OWLObjectOneOf
58 override
59 def visit(expr : OWLObjectOneOf) : RDFoxRuleShards = {
60 val visitor = RDFoxClassExprConverter(term,skolem)
61 // TODO: review nominal handling. Here we are taking "just" one
62 val ind = expr.individuals.collect(Collectors.toList()).asScala
63 .filter(_.isOWLNamedIndividual)
64 .head // restricts to proper "nominals"
65 .asOWLNamedIndividual.getIRI.getIRIString
66 val atom = List(Atom.create(
67 Predicate.create("owl:sameAs"), term, Individual.create(ind)
68 ))
69 RDFoxRuleShards(atom,List())
70 }
71
72 // OWLObjectSomeValuesFrom
73 override
74 def visit(expr : OWLObjectSomeValuesFrom) : RDFoxRuleShards = {
75 // TODO: variables needs to be handled at visitor level. Hardcoding
76 // the name of the varibles might lead to errors for complex cases.
77 val y = Variable.create("y")
78 val (fun,term1) = skolem match {
79 case SkolemStrategy.None => (List(),y)
80 case SkolemStrategy.Constant(c) => (List(), Individual.create(c))
81 case SkolemStrategy.Standard(f) =>
82 // At the time of writing the RDFox library does not have a
83 // particular class for the "SKOLEM" operator and it is instead
84 // a simple builtin function with a special name.
85 (List(Bind.create(BuiltinFunctionCall.create("SKOLEM",term),y)),y)
86 }
87 val classVisitor = new RDFoxClassExprConverter(term1,skolem)
88 val classResult = expr.getFiller.accept(classVisitor)
89 val propertyVisitor = new RDFoxPropertyExprConverter(term, term1, skolem)
90 val propertyResult = expr.getProperty.accept(propertyVisitor)
91 RDFoxRuleShards(
92 classResult.res ++ propertyResult,
93 fun ++ classResult.ext
94 )
95 }
96
97 // OWLObjectMaxCardinality
98 override
99 def visit(expr : OWLObjectMaxCardinality) : RDFoxRuleShards = {
100 // TODO: again, no hardcoded variables
101 val vars = List(Variable.create("y"),Variable.create("z"))
102 val classResult = RDFoxClassExprConverter.merge(
103 vars.map(new RDFoxClassExprConverter(_,skolem))
104 .map(expr.getFiller.accept(_))
105 )
106 val propertyResult =
107 vars.map(new RDFoxPropertyExprConverter(term,_,skolem))
108 .map(expr.getProperty.accept(_))
109 .flatten
110 RDFoxRuleShards(
111 List(Atom.create(Predicate.create("owl:sameAs"),vars(0),vars(1))),
112 classResult.res ++ propertyResult
113 )
114 }
115
116 def doDefault(expr : OWLClassExpression) : RDFoxRuleShards =
117 RDFoxRuleShards(List(),List())
118
119} // class RDFoxClassExprConverter
diff --git a/src/main/scala/example/RDFoxPropertyExprConverter.scala b/src/main/scala/example/RDFoxPropertyExprConverter.scala
new file mode 100644
index 0000000..2885ed9
--- /dev/null
+++ b/src/main/scala/example/RDFoxPropertyExprConverter.scala
@@ -0,0 +1,23 @@
1package rsacomb
2
3import org.semanticweb.owlapi.model.{OWLPropertyExpression, OWLObjectProperty}
4import org.semanticweb.owlapi.model.OWLPropertyExpressionVisitorEx
5
6import tech.oxfordsemantic.jrdfox.logic.{Atom, Predicate, Term, Variable, Literal}
7
8import rsacomb.SkolemStrategy
9
10class RDFoxPropertyExprConverter(term1 : Term, term2 : Term, skolem : SkolemStrategy)
11 extends OWLPropertyExpressionVisitorEx[List[Atom]]
12{
13
14 override
15 def visit(expr : OWLObjectProperty) : List[Atom] = {
16 val name = expr.getIRI.getIRIString
17 List(Atom.create(Predicate.create(name), term1, term2))
18 }
19
20 def doDefault(expr : OWLPropertyExpression) : List[Atom] = List()
21
22} // class RDFoxPropertyExprConverter
23
diff --git a/src/main/scala/example/RDFoxRuleShards.scala b/src/main/scala/example/RDFoxRuleShards.scala
new file mode 100644
index 0000000..bce31d2
--- /dev/null
+++ b/src/main/scala/example/RDFoxRuleShards.scala
@@ -0,0 +1,6 @@
1package rsacomb
2
3import tech.oxfordsemantic.jrdfox.logic.{Rule, Atom, Literal}
4
5case class RDFoxRuleShards(res : List[Atom], ext : List[Literal])
6
diff --git a/src/main/scala/example/RSAComb.scala b/src/main/scala/example/RSAComb.scala
new file mode 100644
index 0000000..bc94a8d
--- /dev/null
+++ b/src/main/scala/example/RSAComb.scala
@@ -0,0 +1,138 @@
1package rsacomb
2
3import java.io.File
4import java.util.HashMap
5import java.util.stream.{Stream,Collectors}
6
7import org.semanticweb.owlapi.apibinding.OWLManager
8import org.semanticweb.owlapi.model.{AxiomType, ClassExpressionType, OWLObjectSomeValuesFrom}
9import org.semanticweb.owlapi.model.{OWLAxiom, OWLSubClassOfAxiom, OWLEquivalentClassesAxiom}
10import org.semanticweb.owlapi.model.OWLClassExpression
11import org.semanticweb.owlapi.model.OWLOntology
12import org.semanticweb.owlapi.model.OWLOntologyManager
13import org.semanticweb.owlapi.model.parameters.Imports
14
15import tech.oxfordsemantic.jrdfox.Prefixes
16import tech.oxfordsemantic.jrdfox.client.{ConnectionFactory, ServerConnection, DataStoreConnection}
17import tech.oxfordsemantic.jrdfox.client.UpdateType
18import tech.oxfordsemantic.jrdfox.logic.{Rule, Atom, Literal, Predicate, Term, Variable}
19import tech.oxfordsemantic.jrdfox.logic.{Bind, BuiltinFunctionCall}
20
21import scala.collection.JavaConverters._
22
23import rsacomb.SkolemStrategy
24
25class RSA(ontology : OWLOntology) {
26
27 /* Alternative constructor(s) */
28 def this(file : File) = this(RSA.loadOntology(file))
29
30 def getOntology : OWLOntology = ontology
31
32} // class RSA
33
34object RSA {
35
36 def loadOntology( onto : File ) : OWLOntology = {
37 /* Retrieve ontology manager */
38 val manager : OWLOntologyManager = OWLManager.createOWLOntologyManager()
39 /* Retrieve ontology */
40 manager.loadOntologyFromOntologyDocument(onto)
41 }
42
43 def isRSA( onto : OWLOntology ) : Boolean = {
44 /* TODO: Steps for RSA check
45 * 1) convert ontology axioms into LP rules
46 * 2) call RDFox on the onto and compute materialization
47 * 3) build graph from E(x,y) facts
48 * 4) check if the graph is tree-like
49 */
50
51 /* Ontology axiom convertion into LP rules */
52 for {
53 axiom <- onto.tboxAxioms(Imports.EXCLUDED).collect(Collectors.toList()).asScala
54 visitor = new RDFoxAxiomConverter(Variable.create("x"), SkolemStrategy.Constant(axiom.toString))
55 rule <- axiom.accept(visitor)
56 } yield println(rule)
57
58 /* Return true for now... */
59 true
60 }
61
62} // object RSA
63
64object RSAComb {
65
66 val help : String = """
67 rsacomb - combined approach for CQ answering for RSA ontologies.
68
69 USAGE
70 rsacomb <path/to/ontology.owl> <path/to/query.sparql>
71
72 where
73 the ontology is expected to be an OWL file and the (single)
74 query a SPARQL query file.
75 """
76
77 def main( args : Array[String] ) : Unit = {
78
79 /* Simple arguments handling
80 *
81 * TODO: use something better later on
82 */
83
84 if (args.length < 2) {
85 println(help)
86 return ()
87 }
88
89 val ontologyPath = new File(args(0))
90 val queryPath = new File(args(1))
91
92 if (!ontologyPath.isFile || !queryPath.isFile) {
93 println("The provided arguments are not regular files.\n\n")
94 println(help)
95 return ()
96 }
97
98 /* Create RSA object from generic OWLOntology
99 *
100 * TODO: It might be required to check if the ontology in input is
101 * Horn-ALCHOIQ. At the moment we are assuming this is always the
102 * case.
103 */
104 val rsa = new RSA(ontologyPath)
105 RSA.isRSA(rsa.getOntology)
106
107 /* Build canonical model */
108 //val tboxCanon = rsa.canonicalModel()
109
110 /* Load query */
111 //val query = ...
112
113 /* Compute the filtering program from the given query */
114 //val tboxFilter = rsa.filteringProgram(query)
115
116 /* ... */
117
118 /* DEBUG ONLY */
119 println("Ok!")
120 }
121}
122
123/* Notes:
124 *
125 * To establish a connection with a local RDFox instance, do the
126 * following:
127 *
128 * ```
129 * val serverConnection : ServerConnection = ConnectionFactory.newServerConnection("rdfox:local", "", "")
130 * serverConnection.createDataStore("test","seq",new HashMap())
131 * val dataStoreConnection : DataStoreConnection = serverConnection.newDataStoreConnection("test")
132 * dataStoreConnection.importData(
133 * UpdateType.ADDITION,
134 * Prefixes.s_emptyPrefixes,
135 * new File("./path/to/file")
136 * )
137 * ```
138 */
diff --git a/src/main/scala/example/SkolemStrategy.scala b/src/main/scala/example/SkolemStrategy.scala
new file mode 100644
index 0000000..9df167f
--- /dev/null
+++ b/src/main/scala/example/SkolemStrategy.scala
@@ -0,0 +1,46 @@
1package rsacomb
2
3sealed trait SkolemStrategy
4
5object SkolemStrategy {
6 // TODO: might want to use something else other than `hashCode` as a
7 // function to generate a fresh function/constant
8
9 /* No skolemization at all.
10 *
11 * From
12 * ∃R.A ⊑ B
13 * to
14 * R(x,y), B(y) -> B(x)
15 */
16 case object None extends SkolemStrategy
17
18 /* Functional skolemization
19 *
20 * From
21 * A ⊑ ∃R.B
22 * to
23 * A(y) -> R(x,f(x)), B(f(x))
24 * for f, fresh function associated with the input axiom
25 */
26 case class Standard(func : String) extends SkolemStrategy
27 object Standard {
28 def apply(axiom : String) = new Standard(genFunctionString(axiom))
29 def genFunctionString(str : String) = "f_" ++ str.hashCode.toString
30 }
31
32 /* Functional skolemization
33 *
34 * From
35 * A ⊑ ∃R.B
36 * to
37 * A(y) -> R(x,c), B(c)
38 * for c, fresh constant associated with the input axiom
39 */
40 case class Constant(const : String) extends SkolemStrategy
41 object Constant {
42 def apply(axiom : String) = new Constant(genConstantString(axiom))
43 def genConstantString(str : String) = "internal:c_" ++ str.hashCode.toString
44 }
45}
46