From e932527e33b6f4c1634995224188b26d870d92b2 Mon Sep 17 00:00:00 2001 From: Federico Igne Date: Mon, 31 May 2021 15:06:47 +0100 Subject: Add scafolding for generic approximation support --- .../cs/rsacomb/approximation/approximation.scala | 16 ++ .../ox/cs/rsacomb/approximation/lowerbound.scala | 207 +++++++++++++++++++++ 2 files changed, 223 insertions(+) create mode 100644 src/main/scala/uk/ac/ox/cs/rsacomb/approximation/approximation.scala create mode 100644 src/main/scala/uk/ac/ox/cs/rsacomb/approximation/lowerbound.scala (limited to 'src/main/scala/uk/ac/ox/cs/rsacomb/approximation') diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/approximation.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/approximation.scala new file mode 100644 index 0000000..073d0d9 --- /dev/null +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/approximation.scala @@ -0,0 +1,16 @@ +package uk.ac.ox.cs.rsacomb.approximation + +import java.io.File +import org.semanticweb.owlapi.model.OWLAxiom + +/** Ontology approximation technique. */ +trait Approximation { + + /** Approximate an ontology. + * + * @param ontology input ontology + * @return a new approximated ontology + */ + def approximate(ontology: Seq[OWLAxiom], datafiles: Seq[File]): Seq[OWLAxiom] + +} 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 new file mode 100644 index 0000000..8036250 --- /dev/null +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/lowerbound.scala @@ -0,0 +1,207 @@ +package uk.ac.ox.cs.rsacomb.approximation + +/** Approximation algorithm that mantains soundness 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 LowerBound extends Approximation { + + val normalizer = new Normalizer() + + /** Main entry point for the approximation algorithm */ + def approximate( + ontology: Seq[OWLAxiom], + datafiles: Seq[File] + ): Seq[OWLAxiom] = { + /* Normalize axioms */ + val axioms1 = axioms flatMap normalizer.normalize + /* Delete any axiom outside of ALCHOIQ */ + val axioms2 = axioms1 filterNot inHornLACHOIQ + /* Shift any axiom with disjunction on the rhs */ + val axioms3 = for { + a1 <- axioms1 + a2 <- shift(a1) + a3 <- normalize(a2) + } yield a3 + /* Approximate to RSA */ + toRSA(axioms3, datafiles) + } + + /** Discards all axioms outside ALCHOIQ */ + 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 + } + + /** Shifting axioms with disjunction on the rhs. + * + * The process of shifting presenves soundness but completenes w.r.t. + * CQ answering is lost. + * + * @example + * + * A -> B1 u B2 u B3 . + * + * becomes + * + * A n nB1 n nB2 -> B3 . + * A n nB1 n nB3 -> B2 . + * A n nB2 n nB3 -> B1 . + * nB1 n nB2 n nB3 -> nA . + * + * where nA, nB1, nB2, nB3 are fresh predicates "corresponding" to + * the negation of A, B1, B2, B3 respectively. + */ + def shift(axiom: OWLLogicalAxiom): Seq[OWLLogicalAxiom] = + axiom match { + case a: OWLSubClassOfAxiom => { + val sub = a.getSubClass.getNNF + val sup = a.getSuperClass.getNNF + sup match { + case sup: OWLObjectUnionOf => { + val body = sub.asConjunctSet.map((atom) => (atom, freshOWLClass())) + val head = sup.asDisjunctSet.map((atom) => (atom, freshOWLClass())) + + val r1 = + factory.getOWLSubClassOfAxiom( + factory.getOWLObjectIntersectionOf( + (body.map(_._1) ++ head.map(_._2)): _* + ), + factory.getOWLNothing + ) + + val r2s = + for { + (a, na) <- head + hs = head.map(_._2).filterNot(_ equals na) + } yield factory.getOWLSubClassOfAxiom( + factory.getOWLObjectIntersectionOf( + (body.map(_._1) ++ hs): _* + ), + a + ) + + val r3s = + for { + (a, na) <- body + bs = body.map(_._1).filterNot(_ equals a) + } yield factory.getOWLSubClassOfAxiom( + factory.getOWLObjectIntersectionOf( + (bs ++ head.map(_._2)): _* + ), + na + ) + + Seq(r1) ++ r2s ++ r3s + } + case _ => Seq(axiom) + } + } + case _ => Seq(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 axioms the set of axioms to approximate. + * @return the approximated set of axioms. + */ + def toRSA(axioms: Seq[OWLAxiom], datafiles: Seq[File]): Seq[OWLAxiom] = { + /* Compute the dependency graph for the ontology */ + val (graph, nodemap) = RSAUtil.dependencyGraph(axioms, datafiles) + + /* 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.iterator.collect { case (resource: IRI, ToDelete) => + nodemap(resource.getIRI) + }.toSeq + + /* Remove axioms from approximated ontology */ + axioms diff toDelete + } + // 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 5f9815c3f67114645593840a8648bffb1207b8d0 Mon Sep 17 00:00:00 2001 From: Federico Igne Date: Mon, 31 May 2021 16:58:15 +0100 Subject: Multiple fixes --- .../cs/rsacomb/approximation/approximation.scala | 7 +++-- .../ox/cs/rsacomb/approximation/lowerbound.scala | 35 +++++++++++++++------- 2 files changed, 30 insertions(+), 12 deletions(-) (limited to 'src/main/scala/uk/ac/ox/cs/rsacomb/approximation') diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/approximation.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/approximation.scala index 073d0d9..1b49413 100644 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/approximation.scala +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/approximation.scala @@ -1,7 +1,7 @@ package uk.ac.ox.cs.rsacomb.approximation import java.io.File -import org.semanticweb.owlapi.model.OWLAxiom +import org.semanticweb.owlapi.model.OWLLogicalAxiom /** Ontology approximation technique. */ trait Approximation { @@ -11,6 +11,9 @@ trait Approximation { * @param ontology input ontology * @return a new approximated ontology */ - def approximate(ontology: Seq[OWLAxiom], datafiles: Seq[File]): Seq[OWLAxiom] + def approximate( + ontology: List[OWLLogicalAxiom], + datafiles: List[File] + ): List[OWLLogicalAxiom] } 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 8036250..3437bcd 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 @@ -1,5 +1,16 @@ package uk.ac.ox.cs.rsacomb.approximation +import java.io.File + +import org.semanticweb.owlapi.model._ + +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.converter.Normalizer + /** Approximation algorithm that mantains soundness for CQ answering. * * The input OWL 2 ontology is assumed to be normalized and the output @@ -21,11 +32,11 @@ class LowerBound extends Approximation { /** Main entry point for the approximation algorithm */ def approximate( - ontology: Seq[OWLAxiom], - datafiles: Seq[File] - ): Seq[OWLAxiom] = { + ontology: List[OWLLogicalAxiom], + datafiles: List[File] + ): List[OWLLogicalAxiom] = { /* Normalize axioms */ - val axioms1 = axioms flatMap normalizer.normalize + val axioms1 = axioms flatMap normalizer.normalize(_) /* Delete any axiom outside of ALCHOIQ */ val axioms2 = axioms1 filterNot inHornLACHOIQ /* Shift any axiom with disjunction on the rhs */ @@ -95,7 +106,7 @@ class LowerBound extends Approximation { * where nA, nB1, nB2, nB3 are fresh predicates "corresponding" to * the negation of A, B1, B2, B3 respectively. */ - def shift(axiom: OWLLogicalAxiom): Seq[OWLLogicalAxiom] = + def shift(axiom: OWLLogicalAxiom): List[OWLLogicalAxiom] = axiom match { case a: OWLSubClassOfAxiom => { val sub = a.getSubClass.getNNF @@ -135,12 +146,12 @@ class LowerBound extends Approximation { na ) - Seq(r1) ++ r2s ++ r3s + List(r1) ++ r2s ++ r3s } - case _ => Seq(axiom) + case _ => List(axiom) } } - case _ => Seq(axiom) + case _ => List(axiom) } /** Approximate a Horn-ALCHOIQ ontology to RSA @@ -151,7 +162,10 @@ class LowerBound extends Approximation { * @param axioms the set of axioms to approximate. * @return the approximated set of axioms. */ - def toRSA(axioms: Seq[OWLAxiom], datafiles: Seq[File]): Seq[OWLAxiom] = { + def toRSA( + axioms: List[OWLLogicalAxiom], + datafiles: List[File] + ): List[OWLLogicalAxiom] = { /* Compute the dependency graph for the ontology */ val (graph, nodemap) = RSAUtil.dependencyGraph(axioms, datafiles) @@ -192,11 +206,12 @@ class LowerBound extends Approximation { val toDelete = color.iterator.collect { case (resource: IRI, ToDelete) => nodemap(resource.getIRI) - }.toSeq + }.toList /* Remove axioms from approximated ontology */ axioms diff toDelete } + // 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) -- cgit v1.2.3 From 6b4226c41ec2a2439fb44a312ccaff01769e8212 Mon Sep 17 00:00:00 2001 From: Federico Igne Date: Tue, 1 Jun 2021 11:20:39 +0100 Subject: Fix minor compilation errors --- .../ox/cs/rsacomb/approximation/lowerbound.scala | 31 +++++++++++++++++----- 1 file changed, 25 insertions(+), 6 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 3437bcd..8a86d19 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 @@ -2,13 +2,18 @@ package uk.ac.ox.cs.rsacomb.approximation import java.io.File -import org.semanticweb.owlapi.model._ +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.converter.Normalizer /** Approximation algorithm that mantains soundness for CQ answering. @@ -28,6 +33,16 @@ import uk.ac.ox.cs.rsacomb.converter.Normalizer */ class LowerBound extends Approximation { + /** 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._ + + /** Manager instance to interface with OWLAPI */ + val manager = OWLManager.createOWLOntologyManager() + val factory = manager.getOWLDataFactory() + val normalizer = new Normalizer() /** Main entry point for the approximation algorithm */ @@ -36,14 +51,14 @@ class LowerBound extends Approximation { datafiles: List[File] ): List[OWLLogicalAxiom] = { /* Normalize axioms */ - val axioms1 = axioms flatMap normalizer.normalize(_) + val axioms1 = ontology flatMap normalizer.normalize /* Delete any axiom outside of ALCHOIQ */ - val axioms2 = axioms1 filterNot inHornLACHOIQ + val axioms2 = axioms1 filterNot inALCHOIQ /* Shift any axiom with disjunction on the rhs */ val axioms3 = for { a1 <- axioms1 a2 <- shift(a1) - a3 <- normalize(a2) + a3 <- normalizer.normalize(a2) } yield a3 /* Approximate to RSA */ toRSA(axioms3, datafiles) @@ -113,8 +128,12 @@ class LowerBound extends Approximation { val sup = a.getSuperClass.getNNF sup match { case sup: OWLObjectUnionOf => { - val body = sub.asConjunctSet.map((atom) => (atom, freshOWLClass())) - val head = sup.asDisjunctSet.map((atom) => (atom, freshOWLClass())) + val body = sub.asConjunctSet.map((atom) => + (atom, RSAOntology.getFreshOWLClass()) + ) + val head = sup.asDisjunctSet.map((atom) => + (atom, RSAOntology.getFreshOWLClass()) + ) val r1 = factory.getOWLSubClassOfAxiom( -- cgit v1.2.3 From 53646646f924887768688794aee46874ed194673 Mon Sep 17 00:00:00 2001 From: Federico Igne Date: Tue, 20 Jul 2021 15:09:20 +0100 Subject: Generalize dependency graph generation The code to generate the dependency graph has been moved in the companion object of the generic OWL 2 ontology wrapper Ontology. This signals that we could potentially build a dependency graph for any ontology (and not only RSA ontology). Moreover, a dependency graph can be build for an Ontology object or an arbitrary TBox and Abox. --- src/main/scala/uk/ac/ox/cs/rsacomb/approximation/lowerbound.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 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 8a86d19..2750cca 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 @@ -129,10 +129,10 @@ class LowerBound extends Approximation { sup match { case sup: OWLObjectUnionOf => { val body = sub.asConjunctSet.map((atom) => - (atom, RSAOntology.getFreshOWLClass()) + (atom, RSAUtil.getFreshOWLClass()) ) val head = sup.asDisjunctSet.map((atom) => - (atom, RSAOntology.getFreshOWLClass()) + (atom, RSAUtil.getFreshOWLClass()) ) val r1 = -- cgit v1.2.3 From 18ddefc7c9e9cfaca027a054495325737ae6b9e6 Mon Sep 17 00:00:00 2001 From: Federico Igne Date: Thu, 22 Jul 2021 08:29:11 +0100 Subject: Move some generic commands from RSAOntology to Ontology --- src/main/scala/uk/ac/ox/cs/rsacomb/approximation/approximation.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/main/scala/uk/ac/ox/cs/rsacomb/approximation') diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/approximation.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/approximation.scala index 1b49413..db2118f 100644 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/approximation.scala +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/approximation.scala @@ -8,8 +8,8 @@ trait Approximation { /** Approximate an ontology. * - * @param ontology input ontology - * @return a new approximated ontology + * @param ontology input ontology as a list of axioms + * @return the approximated ontology */ def approximate( ontology: List[OWLLogicalAxiom], -- cgit v1.2.3 From fb0bbb76a53d08dffea74d0ae13c03a122c379bd Mon Sep 17 00:00:00 2001 From: Federico Igne Date: Thu, 22 Jul 2021 09:20:36 +0100 Subject: Make approximation generic over returned type --- .../cs/rsacomb/approximation/approximation.scala | 9 ++-- .../ox/cs/rsacomb/approximation/lowerbound.scala | 54 +++++++++++----------- 2 files changed, 30 insertions(+), 33 deletions(-) (limited to 'src/main/scala/uk/ac/ox/cs/rsacomb/approximation') diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/approximation.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/approximation.scala index db2118f..344f0fe 100644 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/approximation.scala +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/approximation.scala @@ -3,17 +3,16 @@ package uk.ac.ox.cs.rsacomb.approximation import java.io.File import org.semanticweb.owlapi.model.OWLLogicalAxiom +import uk.ac.ox.cs.rsacomb.ontology.Ontology + /** Ontology approximation technique. */ -trait Approximation { +trait Approximation[T] { /** Approximate an ontology. * * @param ontology input ontology as a list of axioms * @return the approximated ontology */ - def approximate( - ontology: List[OWLLogicalAxiom], - datafiles: List[File] - ): List[OWLLogicalAxiom] + def approximate(ontology: Ontology): T } 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 2750cca..07f10a4 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 @@ -15,6 +15,14 @@ import scalax.collection.GraphTraversal._ import uk.ac.ox.cs.rsacomb.RSAOntology import uk.ac.ox.cs.rsacomb.RSAUtil import uk.ac.ox.cs.rsacomb.converter.Normalizer +import uk.ac.ox.cs.rsacomb.ontology.Ontology + +object LowerBound { + + private val manager = OWLManager.createOWLOntologyManager() + private val factory = manager.getOWLDataFactory() + +} /** Approximation algorithm that mantains soundness for CQ answering. * @@ -31,7 +39,7 @@ import uk.ac.ox.cs.rsacomb.converter.Normalizer * * @see [[uk.ac.ox.cs.rsacomb.converter.Normalizer]] */ -class LowerBound extends Approximation { +class LowerBound extends Approximation[RSAOntology] { /** Simplify conversion between Java and Scala collections */ import uk.ac.ox.cs.rsacomb.implicits.JavaCollections._ @@ -39,19 +47,12 @@ class LowerBound extends Approximation { /** Simplify conversion between OWLAPI and RDFox concepts */ import uk.ac.ox.cs.rsacomb.implicits.RDFox._ - /** Manager instance to interface with OWLAPI */ - val manager = OWLManager.createOWLOntologyManager() - val factory = manager.getOWLDataFactory() - - val normalizer = new Normalizer() + private val normalizer = new Normalizer() /** Main entry point for the approximation algorithm */ - def approximate( - ontology: List[OWLLogicalAxiom], - datafiles: List[File] - ): List[OWLLogicalAxiom] = { + def approximate(ontology: Ontology): RSAOntology = { /* Normalize axioms */ - val axioms1 = ontology flatMap normalizer.normalize + val axioms1 = ontology.axioms flatMap normalizer.normalize /* Delete any axiom outside of ALCHOIQ */ val axioms2 = axioms1 filterNot inALCHOIQ /* Shift any axiom with disjunction on the rhs */ @@ -61,11 +62,11 @@ class LowerBound extends Approximation { a3 <- normalizer.normalize(a2) } yield a3 /* Approximate to RSA */ - toRSA(axioms3, datafiles) + toRSA(new Ontology(axioms3, ontology.datafiles)) } /** Discards all axioms outside ALCHOIQ */ - def inALCHOIQ(axiom: OWLLogicalAxiom): Boolean = + private def inALCHOIQ(axiom: OWLLogicalAxiom): Boolean = axiom match { case a: OWLSubClassOfAxiom => { val sub = a.getSubClass.getNNF @@ -121,7 +122,7 @@ class LowerBound extends Approximation { * where nA, nB1, nB2, nB3 are fresh predicates "corresponding" to * the negation of A, B1, B2, B3 respectively. */ - def shift(axiom: OWLLogicalAxiom): List[OWLLogicalAxiom] = + private def shift(axiom: OWLLogicalAxiom): List[OWLLogicalAxiom] = axiom match { case a: OWLSubClassOfAxiom => { val sub = a.getSubClass.getNNF @@ -136,19 +137,19 @@ class LowerBound extends Approximation { ) val r1 = - factory.getOWLSubClassOfAxiom( - factory.getOWLObjectIntersectionOf( + LowerBound.factory.getOWLSubClassOfAxiom( + LowerBound.factory.getOWLObjectIntersectionOf( (body.map(_._1) ++ head.map(_._2)): _* ), - factory.getOWLNothing + LowerBound.factory.getOWLNothing ) val r2s = for { (a, na) <- head hs = head.map(_._2).filterNot(_ equals na) - } yield factory.getOWLSubClassOfAxiom( - factory.getOWLObjectIntersectionOf( + } yield LowerBound.factory.getOWLSubClassOfAxiom( + LowerBound.factory.getOWLObjectIntersectionOf( (body.map(_._1) ++ hs): _* ), a @@ -158,8 +159,8 @@ class LowerBound extends Approximation { for { (a, na) <- body bs = body.map(_._1).filterNot(_ equals a) - } yield factory.getOWLSubClassOfAxiom( - factory.getOWLObjectIntersectionOf( + } yield LowerBound.factory.getOWLSubClassOfAxiom( + LowerBound.factory.getOWLObjectIntersectionOf( (bs ++ head.map(_._2)): _* ), na @@ -179,14 +180,11 @@ class LowerBound extends Approximation { * dependency graph from being tree-shaped, and removing them. * * @param axioms the set of axioms to approximate. - * @return the approximated set of axioms. + * @return the approximated RSA ontology */ - def toRSA( - axioms: List[OWLLogicalAxiom], - datafiles: List[File] - ): List[OWLLogicalAxiom] = { + private def toRSA(ontology: Ontology): RSAOntology = { /* Compute the dependency graph for the ontology */ - val (graph, nodemap) = RSAUtil.dependencyGraph(axioms, datafiles) + val (graph, nodemap) = ontology.dependencyGraph /* Define node colors for the graph visit */ sealed trait NodeColor @@ -228,7 +226,7 @@ class LowerBound extends Approximation { }.toList /* Remove axioms from approximated ontology */ - axioms diff toDelete + RSAOntology(ontology.axioms diff toDelete, ontology.datafiles) } // val edges1 = Seq('A ~> 'B, 'B ~> 'C, 'C ~> 'D, 'D ~> 'H, 'H ~> -- cgit v1.2.3 From b8b8a69ec1d1c93d5cfcfba4dbd002d5c90dd4c6 Mon Sep 17 00:00:00 2001 From: Federico Igne Date: Thu, 22 Jul 2021 10:29:49 +0100 Subject: Remove normalization step from lowerbound computation --- .../ox/cs/rsacomb/approximation/lowerbound.scala | 27 ++++++++-------------- 1 file changed, 10 insertions(+), 17 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 07f10a4..766ea0e 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 @@ -14,7 +14,6 @@ import scalax.collection.GraphTraversal._ import uk.ac.ox.cs.rsacomb.RSAOntology import uk.ac.ox.cs.rsacomb.RSAUtil -import uk.ac.ox.cs.rsacomb.converter.Normalizer import uk.ac.ox.cs.rsacomb.ontology.Ontology object LowerBound { @@ -47,23 +46,14 @@ class LowerBound extends Approximation[RSAOntology] { /** Simplify conversion between OWLAPI and RDFox concepts */ import uk.ac.ox.cs.rsacomb.implicits.RDFox._ - private val normalizer = new Normalizer() - /** Main entry point for the approximation algorithm */ - def approximate(ontology: Ontology): RSAOntology = { - /* Normalize axioms */ - val axioms1 = ontology.axioms flatMap normalizer.normalize - /* Delete any axiom outside of ALCHOIQ */ - val axioms2 = axioms1 filterNot inALCHOIQ - /* Shift any axiom with disjunction on the rhs */ - val axioms3 = for { - a1 <- axioms1 - a2 <- shift(a1) - a3 <- normalizer.normalize(a2) - } yield a3 - /* Approximate to RSA */ - toRSA(new Ontology(axioms3, ontology.datafiles)) - } + def approximate(ontology: Ontology): RSAOntology = + toRSA( + new Ontology( + ontology.axioms filterNot inALCHOIQ flatMap shift, + ontology.datafiles + ) + ) /** Discards all axioms outside ALCHOIQ */ private def inALCHOIQ(axiom: OWLLogicalAxiom): Boolean = @@ -114,6 +104,7 @@ class LowerBound extends Approximation[RSAOntology] { * * becomes * + * A n nB1 n nB2 n nB3 -> bot . * A n nB1 n nB2 -> B3 . * A n nB1 n nB3 -> B2 . * A n nB2 n nB3 -> B1 . @@ -121,6 +112,8 @@ class LowerBound extends Approximation[RSAOntology] { * * where nA, nB1, nB2, nB3 are fresh predicates "corresponding" to * the negation of A, B1, B2, B3 respectively. + * + * @note this method maintains the normal form of the input axiom. */ private def shift(axiom: OWLLogicalAxiom): List[OWLLogicalAxiom] = axiom match { -- cgit v1.2.3 From 79ca4d0b3fe7df238bede90b96226e72707d05b7 Mon Sep 17 00:00:00 2001 From: Federico Igne Date: Thu, 22 Jul 2021 17:15:42 +0100 Subject: Fix file naming --- .../cs/rsacomb/approximation/Approximation.scala | 18 ++ .../ox/cs/rsacomb/approximation/Lowerbound.scala | 232 +++++++++++++++++++++ .../cs/rsacomb/approximation/approximation.scala | 18 -- .../ox/cs/rsacomb/approximation/lowerbound.scala | 232 --------------------- 4 files changed, 250 insertions(+), 250 deletions(-) create mode 100644 src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Approximation.scala create mode 100644 src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Lowerbound.scala delete mode 100644 src/main/scala/uk/ac/ox/cs/rsacomb/approximation/approximation.scala delete mode 100644 src/main/scala/uk/ac/ox/cs/rsacomb/approximation/lowerbound.scala (limited to 'src/main/scala/uk/ac/ox/cs/rsacomb/approximation') diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Approximation.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Approximation.scala new file mode 100644 index 0000000..344f0fe --- /dev/null +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Approximation.scala @@ -0,0 +1,18 @@ +package uk.ac.ox.cs.rsacomb.approximation + +import java.io.File +import org.semanticweb.owlapi.model.OWLLogicalAxiom + +import uk.ac.ox.cs.rsacomb.ontology.Ontology + +/** Ontology approximation technique. */ +trait Approximation[T] { + + /** Approximate an ontology. + * + * @param ontology input ontology as a list of axioms + * @return the approximated ontology + */ + def approximate(ontology: Ontology): T + +} 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 new file mode 100644 index 0000000..3fc4988 --- /dev/null +++ b/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Lowerbound.scala @@ -0,0 +1,232 @@ +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 LowerBound { + + private val manager = OWLManager.createOWLOntologyManager() + private val factory = manager.getOWLDataFactory() + +} + +/** Approximation algorithm that mantains soundness 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 LowerBound 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 filterNot inALCHOIQ flatMap shift, + 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 + } + + /** Shifting axioms with disjunction on the rhs. + * + * The process of shifting presenves soundness but completenes w.r.t. + * CQ answering is lost. + * + * @example + * + * A -> B1 u B2 u B3 . + * + * becomes + * + * A n nB1 n nB2 n nB3 -> bot . + * A n nB1 n nB2 -> B3 . + * A n nB1 n nB3 -> B2 . + * A n nB2 n nB3 -> B1 . + * nB1 n nB2 n nB3 -> nA . + * + * where nA, nB1, nB2, nB3 are fresh predicates "corresponding" to + * the negation of A, B1, B2, B3 respectively. + * + * @note this method maintains the normal form of the input axiom. + */ + private def shift(axiom: OWLLogicalAxiom): List[OWLLogicalAxiom] = + axiom match { + case a: OWLSubClassOfAxiom => { + val sub = a.getSubClass.getNNF + 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 r1 = + LowerBound.factory.getOWLSubClassOfAxiom( + LowerBound.factory.getOWLObjectIntersectionOf( + (body.map(_._1) ++ head.map(_._2)): _* + ), + LowerBound.factory.getOWLNothing + ) + + val r2s = + for { + (a, na) <- head + hs = head.map(_._2).filterNot(_ equals na) + } yield LowerBound.factory.getOWLSubClassOfAxiom( + LowerBound.factory.getOWLObjectIntersectionOf( + (body.map(_._1) ++ hs): _* + ), + a + ) + + val r3s = + for { + (a, na) <- body + bs = body.map(_._1).filterNot(_ equals a) + } yield LowerBound.factory.getOWLSubClassOfAxiom( + LowerBound.factory.getOWLObjectIntersectionOf( + (bs ++ head.map(_._2)): _* + ), + na + ) + + List(r1) ++ r2s ++ r3s + } + 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) + // +} diff --git a/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/approximation.scala b/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/approximation.scala deleted file mode 100644 index 344f0fe..0000000 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/approximation.scala +++ /dev/null @@ -1,18 +0,0 @@ -package uk.ac.ox.cs.rsacomb.approximation - -import java.io.File -import org.semanticweb.owlapi.model.OWLLogicalAxiom - -import uk.ac.ox.cs.rsacomb.ontology.Ontology - -/** Ontology approximation technique. */ -trait Approximation[T] { - - /** Approximate an ontology. - * - * @param ontology input ontology as a list of axioms - * @return the approximated ontology - */ - def approximate(ontology: Ontology): T - -} 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 deleted file mode 100644 index 766ea0e..0000000 --- a/src/main/scala/uk/ac/ox/cs/rsacomb/approximation/lowerbound.scala +++ /dev/null @@ -1,232 +0,0 @@ -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 LowerBound { - - private val manager = OWLManager.createOWLOntologyManager() - private val factory = manager.getOWLDataFactory() - -} - -/** Approximation algorithm that mantains soundness 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 LowerBound 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 filterNot inALCHOIQ flatMap shift, - 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 - } - - /** Shifting axioms with disjunction on the rhs. - * - * The process of shifting presenves soundness but completenes w.r.t. - * CQ answering is lost. - * - * @example - * - * A -> B1 u B2 u B3 . - * - * becomes - * - * A n nB1 n nB2 n nB3 -> bot . - * A n nB1 n nB2 -> B3 . - * A n nB1 n nB3 -> B2 . - * A n nB2 n nB3 -> B1 . - * nB1 n nB2 n nB3 -> nA . - * - * where nA, nB1, nB2, nB3 are fresh predicates "corresponding" to - * the negation of A, B1, B2, B3 respectively. - * - * @note this method maintains the normal form of the input axiom. - */ - private def shift(axiom: OWLLogicalAxiom): List[OWLLogicalAxiom] = - axiom match { - case a: OWLSubClassOfAxiom => { - val sub = a.getSubClass.getNNF - 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 r1 = - LowerBound.factory.getOWLSubClassOfAxiom( - LowerBound.factory.getOWLObjectIntersectionOf( - (body.map(_._1) ++ head.map(_._2)): _* - ), - LowerBound.factory.getOWLNothing - ) - - val r2s = - for { - (a, na) <- head - hs = head.map(_._2).filterNot(_ equals na) - } yield LowerBound.factory.getOWLSubClassOfAxiom( - LowerBound.factory.getOWLObjectIntersectionOf( - (body.map(_._1) ++ hs): _* - ), - a - ) - - val r3s = - for { - (a, na) <- body - bs = body.map(_._1).filterNot(_ equals a) - } yield LowerBound.factory.getOWLSubClassOfAxiom( - LowerBound.factory.getOWLObjectIntersectionOf( - (bs ++ head.map(_._2)): _* - ), - na - ) - - List(r1) ++ r2s ++ r3s - } - 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 axioms 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.iterator.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 7d619706551117a485d93d0d6847a25afa6a359d Mon Sep 17 00:00:00 2001 From: Federico Igne Date: Tue, 27 Jul 2021 10:30:07 +0100 Subject: Rework class structure to match more general workflow The major change is the introduction of a new class Ontology (superclass of RSAOntology) that contains all those operation that we would like to perform on *any* OWL 2 ontology. Approximation is also generic on the return type, allowing for example intermediate steps (or chaining of approximations). --- src/main/scala/uk/ac/ox/cs/rsacomb/approximation/Lowerbound.scala | 2 +- 1 file changed, 1 insertion(+), 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 3fc4988..60a88fb 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 @@ -50,7 +50,7 @@ class LowerBound extends Approximation[RSAOntology] { def approximate(ontology: Ontology): RSAOntology = toRSA( new Ontology( - ontology.axioms filterNot inALCHOIQ flatMap shift, + ontology.axioms filter inALCHOIQ flatMap shift, ontology.datafiles ) ) -- cgit v1.2.3