aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFederico Igne <git@federicoigne.com>2021-07-27 12:52:48 +0100
committerFederico Igne <git@federicoigne.com>2021-07-27 12:52:48 +0100
commit30b199205f3a16cc92577393ddf9b5d7b36d9dc3 (patch)
tree3cb94f148a2bfb206c9481e723141a28cfcc310a
parentd017662e2d65ec72e7decde3b76591c198da9819 (diff)
downloadRSAComb-30b199205f3a16cc92577393ddf9b5d7b36d9dc3.tar.gz
RSAComb-30b199205f3a16cc92577393ddf9b5d7b36d9dc3.zip
Add skeleton for upperbound computation
-rw-r--r--src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Upperbound.scala183
1 files changed, 183 insertions, 0 deletions
diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Upperbound.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Upperbound.scala
new file mode 100644
index 0000000..ba26113
--- /dev/null
+++ b/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Upperbound.scala
@@ -0,0 +1,183 @@
1package uk.ac.ox.cs.rsacomb.approximation
2
3// import java.io.File
4
5import org.semanticweb.owlapi.apibinding.OWLManager
6import org.semanticweb.owlapi.model.{IRI => _, _}
7
8// import tech.oxfordsemantic.jrdfox.logic.expression.{Resource, IRI}
9
10// import scala.collection.mutable.{Set, Map}
11// import scalax.collection.Graph
12// import scalax.collection.GraphPredef._, scalax.collection.GraphEdge._
13// import scalax.collection.GraphTraversal._
14
15import uk.ac.ox.cs.rsacomb.RSAOntology
16// import uk.ac.ox.cs.rsacomb.RSAUtil
17import uk.ac.ox.cs.rsacomb.ontology.Ontology
18
19object UpperBound {
20
21 private val manager = OWLManager.createOWLOntologyManager()
22 private val factory = manager.getOWLDataFactory()
23
24}
25
26/** Approximation algorithm that mantains completeness for CQ answering.
27 *
28 * The input OWL 2 ontology is assumed to be normalized and the output
29 * ontology is guaranteed to be in RSA.
30 *
31 * The algorithm is performed in three steps:
32 * 1. the ontology is reduced to ALCHOIQ by discarding any axiom
33 * that is not in the language;
34 * 2. the ontology is further reduced to Horn-ALCHOIQ by shifting
35 * axioms with disjunction on the rhs;
36 * 3. the ontology is approximated to RSA by manipulating its
37 * dependency graph.
38 *
39 * @see [[uk.ac.ox.cs.rsacomb.converter.Normalizer]]
40 */
41class UpperBound extends Approximation[RSAOntology] {
42
43 /** Simplify conversion between Java and Scala collections */
44 import uk.ac.ox.cs.rsacomb.implicits.JavaCollections._
45
46 /** Simplify conversion between OWLAPI and RDFox concepts */
47 // import uk.ac.ox.cs.rsacomb.implicits.RDFox._
48
49 /** Main entry point for the approximation algorithm */
50 def approximate(ontology: Ontology): RSAOntology =
51 toRSA(
52 new Ontology(
53 ontology.axioms filter inALCHOIQ flatMap toConjuncts,
54 ontology.datafiles
55 )
56 )
57
58 /** Discards all axioms outside ALCHOIQ */
59 private def inALCHOIQ(axiom: OWLLogicalAxiom): Boolean =
60 axiom match {
61 case a: OWLSubClassOfAxiom => {
62 val sub = a.getSubClass.getNNF
63 val sup = a.getSuperClass.getNNF
64 (sub, sup) match {
65 case (sub: OWLObjectAllValuesFrom, _) => false
66 case (sub: OWLDataAllValuesFrom, _) => false
67 case (_, sup: OWLDataAllValuesFrom) => false
68 case (sub: OWLObjectMinCardinality, _) if sub.getCardinality >= 2 =>
69 false
70 case (sub: OWLDataMinCardinality, _) if sub.getCardinality >= 2 =>
71 false
72 case (_, sup: OWLObjectMinCardinality) if sup.getCardinality >= 2 =>
73 false
74 case (_, sup: OWLDataMinCardinality) if sup.getCardinality >= 2 =>
75 false
76 case (sub: OWLObjectMaxCardinality, _) => false
77 case (sub: OWLDataMaxCardinality, _) => false
78 case (_, sup: OWLObjectMaxCardinality) if sup.getCardinality >= 2 =>
79 false
80 case (_, sup: OWLDataMaxCardinality) if sup.getCardinality >= 1 =>
81 false
82 case (_, sup: OWLObjectOneOf) if sup.getIndividuals.length > 2 =>
83 false
84 case (sub: OWLObjectHasSelf, _) => false
85 case (_, sup: OWLObjectHasSelf) => false
86 case _ => true
87 }
88 }
89 case a: OWLTransitiveObjectPropertyAxiom => false
90 case a: OWLReflexiveObjectPropertyAxiom => false
91 case a: OWLSubPropertyChainOfAxiom => false
92 case a: OWLAsymmetricObjectPropertyAxiom => false
93 case a => true
94 }
95
96 /** Turn disjuncts into conjuncts
97 *
98 * This is a very naive way of getting rid of disjunction preserving
99 * completeness of CQ answering.
100 *
101 * @todo implement a choice function that decides which disjunct to
102 * keep instead of keeping all of them. Note that PAGOdA is currently
103 * doing something similar.
104 */
105 private def toConjuncts(axiom: OWLLogicalAxiom): List[OWLLogicalAxiom] =
106 axiom match {
107 case a: OWLSubClassOfAxiom => {
108 val sub = a.getSubClass.getNNF
109 val sup = a.getSuperClass.getNNF
110 sup match {
111 case sup: OWLObjectUnionOf =>
112 sup.asDisjunctSet.map(
113 UpperBound.factory.getOWLSubClassOfAxiom(sub, _)
114 )
115 case _ => List(axiom)
116 }
117 }
118 case _ => List(axiom)
119 }
120
121 // /** Approximate a Horn-ALCHOIQ ontology to RSA
122 // *
123 // * This is done by gathering those axioms that prevent the ontology
124 // * dependency graph from being tree-shaped, and removing them.
125 // *
126 // * @param ontology the set of axioms to approximate.
127 // * @return the approximated RSA ontology
128 // */
129 // private def toRSA(ontology: Ontology): RSAOntology = {
130 // /* Compute the dependency graph for the ontology */
131 // val (graph, nodemap) = ontology.dependencyGraph
132
133 // /* Define node colors for the graph visit */
134 // sealed trait NodeColor
135 // case object Unvisited extends NodeColor
136 // case object Visited extends NodeColor
137 // case object ToDelete extends NodeColor
138
139 // /* Keep track of node colors during graph visit */
140 // var color = Map.from[Resource, NodeColor](
141 // graph.nodes.toOuter.map(k => (k, Unvisited))
142 // )
143
144 // for {
145 // component <- graph.componentTraverser().map(_ to Graph)
146 // edge <- component
147 // .outerEdgeTraverser(component.nodes.head)
148 // .withKind(BreadthFirst)
149 // } yield {
150 // val source = edge._1
151 // val target = edge._2
152 // color(source) match {
153 // case Unvisited | Visited => {
154 // color(target) match {
155 // case Unvisited =>
156 // color(source) = Visited;
157 // color(target) = Visited
158 // case Visited =>
159 // color(source) = ToDelete
160 // case ToDelete =>
161 // color(source) = Visited
162 // }
163 // }
164 // case ToDelete =>
165 // }
166 // }
167
168 // val toDelete = color.collect { case (resource: IRI, ToDelete) =>
169 // nodemap(resource.getIRI)
170 // }.toList
171
172 // /* Remove axioms from approximated ontology */
173 // RSAOntology(ontology.axioms diff toDelete, ontology.datafiles)
174 // }
175
176 // val edges1 = Seq('A ~> 'B, 'B ~> 'C, 'C ~> 'D, 'D ~> 'H, 'H ~>
177 // 'G, 'G ~> 'F, 'E ~> 'A, 'E ~> 'F, 'B ~> 'E, 'F ~> 'G, 'B ~> 'F,
178 // 'C ~> 'G, 'D ~> 'C, 'H ~> 'D)
179 // val edges2 = Seq('I ~> 'M, 'I ~> 'L, 'L ~> 'N, 'M ~> 'N)
180 // val edges3 = Seq('P ~> 'O)
181 // val graph = Graph.from(edges = edges1 ++ edges2 ++ edges3)
182 //
183}