From 30b199205f3a16cc92577393ddf9b5d7b36d9dc3 Mon Sep 17 00:00:00 2001 From: Federico Igne Date: Tue, 27 Jul 2021 12:52:48 +0100 Subject: Add skeleton for upperbound computation --- .../ox/cs/rsacomb/approximation/Upperbound.scala | 183 +++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Upperbound.scala (limited to 'src/main/scala/uk/ac/ox/cs/rsacomb/approximation') 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 @@ +package uk.ac.ox.cs.rsacomb.approximation + +// import java.io.File + +import org.semanticweb.owlapi.apibinding.OWLManager +import org.semanticweb.owlapi.model.{IRI => _, _} + +// import tech.oxfordsemantic.jrdfox.logic.expression.{Resource, IRI} + +// import scala.collection.mutable.{Set, Map} +// import scalax.collection.Graph +// import scalax.collection.GraphPredef._, scalax.collection.GraphEdge._ +// import scalax.collection.GraphTraversal._ + +import uk.ac.ox.cs.rsacomb.RSAOntology +// import uk.ac.ox.cs.rsacomb.RSAUtil +import uk.ac.ox.cs.rsacomb.ontology.Ontology + +object UpperBound { + + private val manager = OWLManager.createOWLOntologyManager() + private val factory = manager.getOWLDataFactory() + +} + +/** Approximation algorithm that mantains completeness for CQ answering. + * + * The input OWL 2 ontology is assumed to be normalized and the output + * ontology is guaranteed to be in RSA. + * + * The algorithm is performed in three steps: + * 1. the ontology is reduced to ALCHOIQ by discarding any axiom + * that is not in the language; + * 2. the ontology is further reduced to Horn-ALCHOIQ by shifting + * axioms with disjunction on the rhs; + * 3. the ontology is approximated to RSA by manipulating its + * dependency graph. + * + * @see [[uk.ac.ox.cs.rsacomb.converter.Normalizer]] + */ +class UpperBound extends Approximation[RSAOntology] { + + /** Simplify conversion between Java and Scala collections */ + import uk.ac.ox.cs.rsacomb.implicits.JavaCollections._ + + /** Simplify conversion between OWLAPI and RDFox concepts */ + // import uk.ac.ox.cs.rsacomb.implicits.RDFox._ + + /** Main entry point for the approximation algorithm */ + def approximate(ontology: Ontology): RSAOntology = + toRSA( + new Ontology( + ontology.axioms filter inALCHOIQ flatMap toConjuncts, + ontology.datafiles + ) + ) + + /** Discards all axioms outside ALCHOIQ */ + private def inALCHOIQ(axiom: OWLLogicalAxiom): Boolean = + axiom match { + case a: OWLSubClassOfAxiom => { + val sub = a.getSubClass.getNNF + val sup = a.getSuperClass.getNNF + (sub, sup) match { + case (sub: OWLObjectAllValuesFrom, _) => false + case (sub: OWLDataAllValuesFrom, _) => false + case (_, sup: OWLDataAllValuesFrom) => false + case (sub: OWLObjectMinCardinality, _) if sub.getCardinality >= 2 => + false + case (sub: OWLDataMinCardinality, _) if sub.getCardinality >= 2 => + false + case (_, sup: OWLObjectMinCardinality) if sup.getCardinality >= 2 => + false + case (_, sup: OWLDataMinCardinality) if sup.getCardinality >= 2 => + false + case (sub: OWLObjectMaxCardinality, _) => false + case (sub: OWLDataMaxCardinality, _) => false + case (_, sup: OWLObjectMaxCardinality) if sup.getCardinality >= 2 => + false + case (_, sup: OWLDataMaxCardinality) if sup.getCardinality >= 1 => + false + case (_, sup: OWLObjectOneOf) if sup.getIndividuals.length > 2 => + false + case (sub: OWLObjectHasSelf, _) => false + case (_, sup: OWLObjectHasSelf) => false + case _ => true + } + } + case a: OWLTransitiveObjectPropertyAxiom => false + case a: OWLReflexiveObjectPropertyAxiom => false + case a: OWLSubPropertyChainOfAxiom => false + case a: OWLAsymmetricObjectPropertyAxiom => false + case a => true + } + + /** Turn disjuncts into conjuncts + * + * This is a very naive way of getting rid of disjunction preserving + * completeness of CQ answering. + * + * @todo implement a choice function that decides which disjunct to + * keep instead of keeping all of them. Note that PAGOdA is currently + * doing something similar. + */ + private def toConjuncts(axiom: OWLLogicalAxiom): List[OWLLogicalAxiom] = + axiom match { + case a: OWLSubClassOfAxiom => { + val sub = a.getSubClass.getNNF + val sup = a.getSuperClass.getNNF + sup match { + case sup: OWLObjectUnionOf => + sup.asDisjunctSet.map( + UpperBound.factory.getOWLSubClassOfAxiom(sub, _) + ) + case _ => List(axiom) + } + } + case _ => List(axiom) + } + + // /** Approximate a Horn-ALCHOIQ ontology to RSA + // * + // * This is done by gathering those axioms that prevent the ontology + // * dependency graph from being tree-shaped, and removing them. + // * + // * @param ontology the set of axioms to approximate. + // * @return the approximated RSA ontology + // */ + // private def toRSA(ontology: Ontology): RSAOntology = { + // /* Compute the dependency graph for the ontology */ + // val (graph, nodemap) = ontology.dependencyGraph + + // /* Define node colors for the graph visit */ + // sealed trait NodeColor + // case object Unvisited extends NodeColor + // case object Visited extends NodeColor + // case object ToDelete extends NodeColor + + // /* Keep track of node colors during graph visit */ + // var color = Map.from[Resource, NodeColor]( + // graph.nodes.toOuter.map(k => (k, Unvisited)) + // ) + + // for { + // component <- graph.componentTraverser().map(_ to Graph) + // edge <- component + // .outerEdgeTraverser(component.nodes.head) + // .withKind(BreadthFirst) + // } yield { + // val source = edge._1 + // val target = edge._2 + // color(source) match { + // case Unvisited | Visited => { + // color(target) match { + // case Unvisited => + // color(source) = Visited; + // color(target) = Visited + // case Visited => + // color(source) = ToDelete + // case ToDelete => + // color(source) = Visited + // } + // } + // case ToDelete => + // } + // } + + // val toDelete = color.collect { case (resource: IRI, ToDelete) => + // nodemap(resource.getIRI) + // }.toList + + // /* Remove axioms from approximated ontology */ + // RSAOntology(ontology.axioms diff toDelete, ontology.datafiles) + // } + + // val edges1 = Seq('A ~> 'B, 'B ~> 'C, 'C ~> 'D, 'D ~> 'H, 'H ~> + // 'G, 'G ~> 'F, 'E ~> 'A, 'E ~> 'F, 'B ~> 'E, 'F ~> 'G, 'B ~> 'F, + // 'C ~> 'G, 'D ~> 'C, 'H ~> 'D) + // val edges2 = Seq('I ~> 'M, 'I ~> 'L, 'L ~> 'N, 'M ~> 'N) + // val edges3 = Seq('P ~> 'O) + // val graph = Graph.from(edges = edges1 ++ edges2 ++ edges3) + // +} -- cgit v1.2.3 From cbfa987d5c8d2f550d509c0a3d8226f302df476a Mon Sep 17 00:00:00 2001 From: Federico Igne Date: Thu, 29 Jul 2021 11:54:44 +0100 Subject: Change spelling: LowerBound to Lowerbound --- .../uk/ac/ox/cs/rsacomb/approximation/Lowerbound.scala | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src/main/scala/uk/ac/ox/cs/rsacomb/approximation') diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Lowerbound.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Lowerbound.scala index 60a88fb..290cbaf 100644 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Lowerbound.scala +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Lowerbound.scala @@ -16,7 +16,7 @@ import uk.ac.ox.cs.rsacomb.RSAOntology import uk.ac.ox.cs.rsacomb.RSAUtil import uk.ac.ox.cs.rsacomb.ontology.Ontology -object LowerBound { +object Lowerbound { private val manager = OWLManager.createOWLOntologyManager() private val factory = manager.getOWLDataFactory() @@ -38,7 +38,7 @@ object LowerBound { * * @see [[uk.ac.ox.cs.rsacomb.converter.Normalizer]] */ -class LowerBound extends Approximation[RSAOntology] { +class Lowerbound extends Approximation[RSAOntology] { /** Simplify conversion between Java and Scala collections */ import uk.ac.ox.cs.rsacomb.implicits.JavaCollections._ @@ -130,19 +130,19 @@ class LowerBound extends Approximation[RSAOntology] { ) val r1 = - LowerBound.factory.getOWLSubClassOfAxiom( - LowerBound.factory.getOWLObjectIntersectionOf( + Lowerbound.factory.getOWLSubClassOfAxiom( + Lowerbound.factory.getOWLObjectIntersectionOf( (body.map(_._1) ++ head.map(_._2)): _* ), - LowerBound.factory.getOWLNothing + Lowerbound.factory.getOWLNothing ) val r2s = for { (a, na) <- head hs = head.map(_._2).filterNot(_ equals na) - } yield LowerBound.factory.getOWLSubClassOfAxiom( - LowerBound.factory.getOWLObjectIntersectionOf( + } yield Lowerbound.factory.getOWLSubClassOfAxiom( + Lowerbound.factory.getOWLObjectIntersectionOf( (body.map(_._1) ++ hs): _* ), a @@ -152,8 +152,8 @@ class LowerBound extends Approximation[RSAOntology] { for { (a, na) <- body bs = body.map(_._1).filterNot(_ equals a) - } yield LowerBound.factory.getOWLSubClassOfAxiom( - LowerBound.factory.getOWLObjectIntersectionOf( + } yield Lowerbound.factory.getOWLSubClassOfAxiom( + Lowerbound.factory.getOWLObjectIntersectionOf( (bs ++ head.map(_._2)): _* ), na -- cgit v1.2.3 From 9256241855a2b0eb21c5af01cf5ca0e3b25524d3 Mon Sep 17 00:00:00 2001 From: Federico Igne Date: Thu, 29 Jul 2021 11:55:10 +0100 Subject: Implement fine-grained constant skolemization in upperbound --- .../ox/cs/rsacomb/approximation/Upperbound.scala | 228 ++++++++++++--------- 1 file changed, 128 insertions(+), 100 deletions(-) (limited to 'src/main/scala/uk/ac/ox/cs/rsacomb/approximation') 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 index ba26113..65cdee1 100644 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Upperbound.scala +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Upperbound.scala @@ -5,18 +5,18 @@ package uk.ac.ox.cs.rsacomb.approximation import org.semanticweb.owlapi.apibinding.OWLManager import org.semanticweb.owlapi.model.{IRI => _, _} -// import tech.oxfordsemantic.jrdfox.logic.expression.{Resource, IRI} +import tech.oxfordsemantic.jrdfox.logic.expression.{Resource, IRI} -// import scala.collection.mutable.{Set, Map} -// import scalax.collection.Graph -// import scalax.collection.GraphPredef._, scalax.collection.GraphEdge._ -// import scalax.collection.GraphTraversal._ +import scala.collection.mutable.Map +import scalax.collection.Graph +import scalax.collection.GraphPredef._, scalax.collection.GraphEdge._ +import scalax.collection.GraphTraversal._ import uk.ac.ox.cs.rsacomb.RSAOntology -// import uk.ac.ox.cs.rsacomb.RSAUtil +import uk.ac.ox.cs.rsacomb.RSAUtil import uk.ac.ox.cs.rsacomb.ontology.Ontology -object UpperBound { +object Upperbound { private val manager = OWLManager.createOWLOntologyManager() private val factory = manager.getOWLDataFactory() @@ -38,7 +38,7 @@ object UpperBound { * * @see [[uk.ac.ox.cs.rsacomb.converter.Normalizer]] */ -class UpperBound extends Approximation[RSAOntology] { +class Upperbound extends Approximation[RSAOntology] { /** Simplify conversion between Java and Scala collections */ import uk.ac.ox.cs.rsacomb.implicits.JavaCollections._ @@ -50,52 +50,52 @@ class UpperBound extends Approximation[RSAOntology] { def approximate(ontology: Ontology): RSAOntology = toRSA( new Ontology( - ontology.axioms filter inALCHOIQ flatMap toConjuncts, + ontology.axioms flatMap toConjuncts, ontology.datafiles ) ) /** Discards all axioms outside ALCHOIQ */ - private def inALCHOIQ(axiom: OWLLogicalAxiom): Boolean = - axiom match { - case a: OWLSubClassOfAxiom => { - val sub = a.getSubClass.getNNF - val sup = a.getSuperClass.getNNF - (sub, sup) match { - case (sub: OWLObjectAllValuesFrom, _) => false - case (sub: OWLDataAllValuesFrom, _) => false - case (_, sup: OWLDataAllValuesFrom) => false - case (sub: OWLObjectMinCardinality, _) if sub.getCardinality >= 2 => - false - case (sub: OWLDataMinCardinality, _) if sub.getCardinality >= 2 => - false - case (_, sup: OWLObjectMinCardinality) if sup.getCardinality >= 2 => - false - case (_, sup: OWLDataMinCardinality) if sup.getCardinality >= 2 => - false - case (sub: OWLObjectMaxCardinality, _) => false - case (sub: OWLDataMaxCardinality, _) => false - case (_, sup: OWLObjectMaxCardinality) if sup.getCardinality >= 2 => - false - case (_, sup: OWLDataMaxCardinality) if sup.getCardinality >= 1 => - false - case (_, sup: OWLObjectOneOf) if sup.getIndividuals.length > 2 => - false - case (sub: OWLObjectHasSelf, _) => false - case (_, sup: OWLObjectHasSelf) => false - case _ => true - } - } - case a: OWLTransitiveObjectPropertyAxiom => false - case a: OWLReflexiveObjectPropertyAxiom => false - case a: OWLSubPropertyChainOfAxiom => false - case a: OWLAsymmetricObjectPropertyAxiom => false - case a => true - } + // private def inALCHOIQ(axiom: OWLLogicalAxiom): Boolean = + // axiom match { + // case a: OWLSubClassOfAxiom => { + // val sub = a.getSubClass.getNNF + // val sup = a.getSuperClass.getNNF + // (sub, sup) match { + // case (sub: OWLObjectAllValuesFrom, _) => false + // case (sub: OWLDataAllValuesFrom, _) => false + // case (_, sup: OWLDataAllValuesFrom) => false + // case (sub: OWLObjectMinCardinality, _) if sub.getCardinality >= 2 => + // false + // case (sub: OWLDataMinCardinality, _) if sub.getCardinality >= 2 => + // false + // case (_, sup: OWLObjectMinCardinality) if sup.getCardinality >= 2 => + // false + // case (_, sup: OWLDataMinCardinality) if sup.getCardinality >= 2 => + // false + // case (sub: OWLObjectMaxCardinality, _) => false + // case (sub: OWLDataMaxCardinality, _) => false + // case (_, sup: OWLObjectMaxCardinality) if sup.getCardinality >= 2 => + // false + // case (_, sup: OWLDataMaxCardinality) if sup.getCardinality >= 1 => + // false + // case (_, sup: OWLObjectOneOf) if sup.getIndividuals.length > 2 => + // false + // case (sub: OWLObjectHasSelf, _) => false + // case (_, sup: OWLObjectHasSelf) => false + // case _ => true + // } + // } + // case a: OWLTransitiveObjectPropertyAxiom => false + // case a: OWLReflexiveObjectPropertyAxiom => false + // case a: OWLSubPropertyChainOfAxiom => false + // case a: OWLAsymmetricObjectPropertyAxiom => false + // case a => true + // } /** Turn disjuncts into conjuncts * - * This is a very naive way of getting rid of disjunction preserving + * This is a very naïve way of getting rid of disjunction preserving * completeness of CQ answering. * * @todo implement a choice function that decides which disjunct to @@ -110,7 +110,7 @@ class UpperBound extends Approximation[RSAOntology] { sup match { case sup: OWLObjectUnionOf => sup.asDisjunctSet.map( - UpperBound.factory.getOWLSubClassOfAxiom(sub, _) + Upperbound.factory.getOWLSubClassOfAxiom(sub, _) ) case _ => List(axiom) } @@ -118,60 +118,88 @@ class UpperBound extends Approximation[RSAOntology] { case _ => List(axiom) } - // /** Approximate a Horn-ALCHOIQ ontology to RSA - // * - // * This is done by gathering those axioms that prevent the ontology - // * dependency graph from being tree-shaped, and removing them. - // * - // * @param ontology the set of axioms to approximate. - // * @return the approximated RSA ontology - // */ - // private def toRSA(ontology: Ontology): RSAOntology = { - // /* Compute the dependency graph for the ontology */ - // val (graph, nodemap) = ontology.dependencyGraph - - // /* Define node colors for the graph visit */ - // sealed trait NodeColor - // case object Unvisited extends NodeColor - // case object Visited extends NodeColor - // case object ToDelete extends NodeColor - - // /* Keep track of node colors during graph visit */ - // var color = Map.from[Resource, NodeColor]( - // graph.nodes.toOuter.map(k => (k, Unvisited)) - // ) - - // for { - // component <- graph.componentTraverser().map(_ to Graph) - // edge <- component - // .outerEdgeTraverser(component.nodes.head) - // .withKind(BreadthFirst) - // } yield { - // val source = edge._1 - // val target = edge._2 - // color(source) match { - // case Unvisited | Visited => { - // color(target) match { - // case Unvisited => - // color(source) = Visited; - // color(target) = Visited - // case Visited => - // color(source) = ToDelete - // case ToDelete => - // color(source) = Visited - // } - // } - // case ToDelete => - // } - // } + /** Approximate a Horn-ALCHOIQ ontology to RSA + * + * This is done by gathering those existential axioms that prevent + * the ontology dependency graph from being tree-shaped and constant + * skolemize them. + * + * @param ontology the set of axioms to approximate. + * @return the approximated RSA ontology + */ + private def toRSA(ontology: Ontology): RSAOntology = { + /* Compute the dependency graph for the ontology */ + val (graph, nodemap) = ontology.dependencyGraph + + /* Define node colors for the graph visit */ + sealed trait NodeColor + case object Unvisited extends NodeColor + case object Visited extends NodeColor + case object ToSkolem extends NodeColor + + /* Keep track of node colors during graph visit */ + var color = Map.from[Resource, NodeColor]( + graph.nodes.toOuter.map(k => (k, Unvisited)) + ) + + for { + component <- graph.componentTraverser().map(_ to Graph) + edge <- component + .outerEdgeTraverser(component.nodes.head) + .withKind(BreadthFirst) + } yield { + val source = edge._1 + val target = edge._2 + color(source) match { + case Unvisited | Visited => { + color(target) match { + case Unvisited => + color(source) = Visited; + color(target) = Visited + case Visited => + color(source) = ToSkolem + case ToSkolem => + color(source) = Visited + } + } + case ToSkolem => {} + } + } - // val toDelete = color.collect { case (resource: IRI, ToDelete) => - // nodemap(resource.getIRI) - // }.toList + val toSkolem = color.collect { case (resource: IRI, ToSkolem) => + nodemap(resource.getIRI) + }.toList + + // Force constant skolemization by introducing a fresh individual + // (singleton class). + val skolemized = toSkolem flatMap { (axiom) => + import uk.ac.ox.cs.rsacomb.implicits.RSAAxiom._ + axiom.toTriple match { + case Some((subclass, role, filler)) => { + val skolem = Upperbound.factory.getOWLNamedIndividual(s"i_${axiom.toString.hashCode}") + val fresh = RSAUtil.getFreshOWLClass() + List( + Upperbound.factory.getOWLSubClassOfAxiom( + subclass, + Upperbound.factory.getOWLObjectSomeValuesFrom(role, fresh) + ), + Upperbound.factory.getOWLSubClassOfAxiom( + fresh, + Upperbound.factory.getOWLObjectOneOf(skolem) + ), + Upperbound.factory.getOWLClassAssertionAxiom(filler, skolem) + ) + } + case None => List() + } + } - // /* Remove axioms from approximated ontology */ - // RSAOntology(ontology.axioms diff toDelete, ontology.datafiles) - // } + /* Substitute selected axioms with their "skolemized" version */ + RSAOntology( + ontology.axioms diff toSkolem concat skolemized, + ontology.datafiles + ) + } // val edges1 = Seq('A ~> 'B, 'B ~> 'C, 'C ~> 'D, 'D ~> 'H, 'H ~> // 'G, 'G ~> 'F, 'E ~> 'A, 'E ~> 'F, 'B ~> 'E, 'F ~> 'G, 'B ~> 'F, @@ -179,5 +207,5 @@ class UpperBound extends Approximation[RSAOntology] { // val edges2 = Seq('I ~> 'M, 'I ~> 'L, 'L ~> 'N, 'M ~> 'N) // val edges3 = Seq('P ~> 'O) // val graph = Graph.from(edges = edges1 ++ edges2 ++ edges3) - // + } -- cgit v1.2.3 From 19c22a38ccaf1685e345a18883ffbac891f97df3 Mon Sep 17 00:00:00 2001 From: Federico Igne Date: Tue, 3 Aug 2021 12:20:34 +0100 Subject: Extend converter to RDFox rules to handle property chain axioms The converter to RDFox datalog rules shouldn't worry about which axiom is supported or not (it should be a job of the approximation algorithm or of a previous step). Now the converter tries its best to convert anything that makes sense in datalog. Also upperbound is ready for testing. --- .../ox/cs/rsacomb/approximation/Upperbound.scala | 38 ---------------------- 1 file changed, 38 deletions(-) (limited to 'src/main/scala/uk/ac/ox/cs/rsacomb/approximation') 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 index 65cdee1..ad924aa 100644 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Upperbound.scala +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Upperbound.scala @@ -55,44 +55,6 @@ class Upperbound extends Approximation[RSAOntology] { ) ) - /** Discards all axioms outside ALCHOIQ */ - // private def inALCHOIQ(axiom: OWLLogicalAxiom): Boolean = - // axiom match { - // case a: OWLSubClassOfAxiom => { - // val sub = a.getSubClass.getNNF - // val sup = a.getSuperClass.getNNF - // (sub, sup) match { - // case (sub: OWLObjectAllValuesFrom, _) => false - // case (sub: OWLDataAllValuesFrom, _) => false - // case (_, sup: OWLDataAllValuesFrom) => false - // case (sub: OWLObjectMinCardinality, _) if sub.getCardinality >= 2 => - // false - // case (sub: OWLDataMinCardinality, _) if sub.getCardinality >= 2 => - // false - // case (_, sup: OWLObjectMinCardinality) if sup.getCardinality >= 2 => - // false - // case (_, sup: OWLDataMinCardinality) if sup.getCardinality >= 2 => - // false - // case (sub: OWLObjectMaxCardinality, _) => false - // case (sub: OWLDataMaxCardinality, _) => false - // case (_, sup: OWLObjectMaxCardinality) if sup.getCardinality >= 2 => - // false - // case (_, sup: OWLDataMaxCardinality) if sup.getCardinality >= 1 => - // false - // case (_, sup: OWLObjectOneOf) if sup.getIndividuals.length > 2 => - // false - // case (sub: OWLObjectHasSelf, _) => false - // case (_, sup: OWLObjectHasSelf) => false - // case _ => true - // } - // } - // case a: OWLTransitiveObjectPropertyAxiom => false - // case a: OWLReflexiveObjectPropertyAxiom => false - // case a: OWLSubPropertyChainOfAxiom => false - // case a: OWLAsymmetricObjectPropertyAxiom => false - // case a => true - // } - /** Turn disjuncts into conjuncts * * This is a very naïve way of getting rid of disjunction preserving -- cgit v1.2.3 From 75eb39dd0fd31c295b9ed9a6d3b0fd3b25611b2a Mon Sep 17 00:00:00 2001 From: Federico Igne Date: Fri, 6 Aug 2021 13:31:54 +0100 Subject: Add new fresh data factory This will help write more significant test. --- .../uk/ac/ox/cs/rsacomb/approximation/Lowerbound.scala | 15 +++++++-------- .../uk/ac/ox/cs/rsacomb/approximation/Upperbound.scala | 17 ++++++++++------- 2 files changed, 17 insertions(+), 15 deletions(-) (limited to 'src/main/scala/uk/ac/ox/cs/rsacomb/approximation') diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Lowerbound.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Lowerbound.scala index 290cbaf..88732d5 100644 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Lowerbound.scala +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Lowerbound.scala @@ -13,8 +13,8 @@ import scalax.collection.GraphPredef._, scalax.collection.GraphEdge._ import scalax.collection.GraphTraversal._ import uk.ac.ox.cs.rsacomb.RSAOntology -import uk.ac.ox.cs.rsacomb.RSAUtil import uk.ac.ox.cs.rsacomb.ontology.Ontology +import uk.ac.ox.cs.rsacomb.util.DataFactory object Lowerbound { @@ -38,7 +38,8 @@ object Lowerbound { * * @see [[uk.ac.ox.cs.rsacomb.converter.Normalizer]] */ -class Lowerbound extends Approximation[RSAOntology] { +class Lowerbound(implicit fresh: DataFactory) + extends Approximation[RSAOntology] { /** Simplify conversion between Java and Scala collections */ import uk.ac.ox.cs.rsacomb.implicits.JavaCollections._ @@ -122,12 +123,10 @@ class Lowerbound extends Approximation[RSAOntology] { val sup = a.getSuperClass.getNNF sup match { case sup: OWLObjectUnionOf => { - val body = sub.asConjunctSet.map((atom) => - (atom, RSAUtil.getFreshOWLClass()) - ) - val head = sup.asDisjunctSet.map((atom) => - (atom, RSAUtil.getFreshOWLClass()) - ) + val body = + sub.asConjunctSet.map((atom) => (atom, fresh.getOWLClass)) + val head = + sup.asDisjunctSet.map((atom) => (atom, fresh.getOWLClass)) val r1 = Lowerbound.factory.getOWLSubClassOfAxiom( 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 index ad924aa..1ae7941 100644 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Upperbound.scala +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Upperbound.scala @@ -13,8 +13,8 @@ import scalax.collection.GraphPredef._, scalax.collection.GraphEdge._ import scalax.collection.GraphTraversal._ import uk.ac.ox.cs.rsacomb.RSAOntology -import uk.ac.ox.cs.rsacomb.RSAUtil import uk.ac.ox.cs.rsacomb.ontology.Ontology +import uk.ac.ox.cs.rsacomb.util.DataFactory object Upperbound { @@ -38,7 +38,8 @@ object Upperbound { * * @see [[uk.ac.ox.cs.rsacomb.converter.Normalizer]] */ -class Upperbound extends Approximation[RSAOntology] { +class Upperbound(implicit fresh: DataFactory) + extends Approximation[RSAOntology] { /** Simplify conversion between Java and Scala collections */ import uk.ac.ox.cs.rsacomb.implicits.JavaCollections._ @@ -138,15 +139,17 @@ class Upperbound extends Approximation[RSAOntology] { import uk.ac.ox.cs.rsacomb.implicits.RSAAxiom._ axiom.toTriple match { case Some((subclass, role, filler)) => { - val skolem = Upperbound.factory.getOWLNamedIndividual(s"i_${axiom.toString.hashCode}") - val fresh = RSAUtil.getFreshOWLClass() + val skolem = Upperbound.factory.getOWLNamedIndividual( + s"i_${axiom.toString.hashCode}" + ) + val cls = fresh.getOWLClass List( Upperbound.factory.getOWLSubClassOfAxiom( subclass, - Upperbound.factory.getOWLObjectSomeValuesFrom(role, fresh) + Upperbound.factory.getOWLObjectSomeValuesFrom(role, cls) ), Upperbound.factory.getOWLSubClassOfAxiom( - fresh, + cls, Upperbound.factory.getOWLObjectOneOf(skolem) ), Upperbound.factory.getOWLClassAssertionAxiom(filler, skolem) @@ -169,5 +172,5 @@ class Upperbound extends Approximation[RSAOntology] { // val edges2 = Seq('I ~> 'M, 'I ~> 'L, 'L ~> 'N, 'M ~> 'N) // val edges3 = Seq('P ~> 'O) // val graph = Graph.from(edges = edges1 ++ edges2 ++ edges3) - + } -- cgit v1.2.3 From c86e7d32420adcc05546efa45b21e0e31d0f6c90 Mon Sep 17 00:00:00 2001 From: Federico Igne Date: Mon, 4 Oct 2021 18:01:50 +0100 Subject: Fix issue where not all roles where considered for top axiomatisation --- src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Lowerbound.scala | 7 ++++++- src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Upperbound.scala | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'src/main/scala/uk/ac/ox/cs/rsacomb/approximation') diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Lowerbound.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Lowerbound.scala index 88732d5..e261bce 100644 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Lowerbound.scala +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Lowerbound.scala @@ -51,6 +51,7 @@ class Lowerbound(implicit fresh: DataFactory) def approximate(ontology: Ontology): RSAOntology = toRSA( new Ontology( + ontology.origin, ontology.axioms filter inALCHOIQ flatMap shift, ontology.datafiles ) @@ -218,7 +219,11 @@ class Lowerbound(implicit fresh: DataFactory) }.toList /* Remove axioms from approximated ontology */ - RSAOntology(ontology.axioms diff toDelete, ontology.datafiles) + RSAOntology( + ontology.origin, + ontology.axioms diff toDelete, + ontology.datafiles + ) } // val edges1 = Seq('A ~> 'B, 'B ~> 'C, 'C ~> 'D, 'D ~> 'H, 'H ~> 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 index 1ae7941..469d774 100644 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Upperbound.scala +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Upperbound.scala @@ -51,6 +51,7 @@ class Upperbound(implicit fresh: DataFactory) def approximate(ontology: Ontology): RSAOntology = toRSA( new Ontology( + ontology.origin, ontology.axioms flatMap toConjuncts, ontology.datafiles ) @@ -161,6 +162,7 @@ class Upperbound(implicit fresh: DataFactory) /* Substitute selected axioms with their "skolemized" version */ RSAOntology( + ontology.origin, ontology.axioms diff toSkolem concat skolemized, ontology.datafiles ) -- cgit v1.2.3