Skip to content

Commit

Permalink
Merge pull request #117 from balhoff/protege-fixes
Browse files Browse the repository at this point in the history
Improvements to Protege plugin and OWL API interface implementation
  • Loading branch information
balhoff authored Oct 27, 2020
2 parents 3a897a3 + 4572539 commit c39b714
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 25 deletions.
40 changes: 21 additions & 19 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@

lazy val owlapiVersion = "4.5.17"

lazy val commonSettings = Seq(
organization := "org.geneontology",
version := "1.0.3",
version := "1.0.4",
licenses := Seq("BSD-3-Clause" -> url("https://opensource.org/licenses/BSD-3-Clause")),
homepage := Some(url("https://github.com/balhoff/whelk")),
crossScalaVersions := Seq("2.12.11", "2.13.3"),
Expand Down Expand Up @@ -38,27 +37,28 @@ lazy val testSettings = Seq(
libraryDependencies ++= Seq("com.lihaoyi" %% "utest" % "0.7.5" % Test)
)

lazy val parentProject = project.in(file("."))
lazy val parentProject = project
.in(file("."))
.settings(commonSettings)
.settings(
name := "whelk-project",
skip in publish := true)
.settings(name := "whelk-project", skip in publish := true)
.aggregate(
core,
owlapi,
protege
)

lazy val core = project.in(file("modules/core"))
lazy val core = project
.in(file("modules/core"))
.settings(commonSettings)
.settings(testSettings)
.settings(publishSettings)
.settings(
name := "whelk",
description := "Whelk reasoner core",
description := "Whelk reasoner core"
)

lazy val owlapi = project.in(file("modules/owlapi"))
lazy val owlapi = project
.in(file("modules/owlapi"))
.dependsOn(core)
.enablePlugins(JavaAppPackaging)
.settings(commonSettings)
Expand All @@ -69,29 +69,31 @@ lazy val owlapi = project.in(file("modules/owlapi"))
description := "Whelk reasoner OWL API bindings",
mainClass in Compile := Some("org.geneontology.whelk.Main"),
libraryDependencies ++= Seq(
"net.sourceforge.owlapi" % "owlapi-distribution" % owlapiVersion,
"org.phenoscape" %% "scowl" % "1.3.4",
"org.semanticweb.elk" % "elk-owlapi" % "0.4.3" % Test,
"net.sourceforge.owlapi" % "owlapi-distribution" % owlapiVersion,
"org.phenoscape" %% "scowl" % "1.3.4",
"org.semanticweb.elk" % "elk-owlapi" % "0.4.3" % Test,
"net.sourceforge.owlapi" % "org.semanticweb.hermit" % "1.4.0.432" % Test,
"net.sourceforge.owlapi" % "jfact" % "4.0.4" % Test
"net.sourceforge.owlapi" % "jfact" % "4.0.4" % Test
)
)

def isJarToEmbed(file: java.io.File): Boolean = file.getName match {
case name if name startsWith "scala" => true
case _ => false
case name if (name startsWith "scala") || (name startsWith "scowl") => true
case _ => false
}

lazy val protege = project.in(file("modules/protege"))
lazy val protege = project
.in(file("modules/protege"))
.dependsOn(owlapi)
.enablePlugins(SbtOsgi)
.settings(commonSettings)
.settings(
skip in publish := true,
name := "whelk-protege",
name := "Whelk reasoner Protege plugin",
description := "Whelk reasoner Protégé plugin",
// Bundle-Version is set to the version by default.
OsgiKeys.bundleSymbolicName := "org.geneontology.whelk;singleton:=true",
OsgiKeys.bundleActivator := Some("org.protege.editor.owl.ProtegeOWL"),
// Include the packages specified by privatePackage in the bundle.
OsgiKeys.privatePackage := Seq("org.geneontology.*"),
OsgiKeys.exportPackage := Seq("!*"),
Expand All @@ -105,7 +107,7 @@ lazy val protege = project.in(file("modules/protege"))
),
libraryDependencies ++= Seq(
"net.sourceforge.owlapi" % "owlapi-distribution" % owlapiVersion % Provided,
"edu.stanford.protege" % "protege-editor-core" % "5.2.0" % Provided,
"edu.stanford.protege" % "protege-editor-owl" % "5.2.0" % Provided
"edu.stanford.protege" % "protege-editor-core" % "5.2.0" % Provided,
"edu.stanford.protege" % "protege-editor-owl" % "5.2.0" % Provided
)
)
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ final case class ReasonerState(
// Using the regular algorithm for Bottom takes too long
val directSuperClassesOfBottom = closureSubsBySuperclass.collect { case (superclass: AtomicConcept, subclasses) if (subclasses - Bottom - superclass).forall(_.isAnonymous) => superclass }.toSet
val equivalentsToBottom = closureSubsBySuperclass(Bottom).collect { case subclass: AtomicConcept => subclass }
closureSubsBySubclass.collect {
(closureSubsBySubclass - Bottom).collect {
case (c: AtomicConcept, subsumers) => c -> directSubsumers(c, subsumers + Top)
} + (Bottom -> (equivalentsToBottom, directSuperClassesOfBottom))
}
Expand Down Expand Up @@ -179,16 +179,20 @@ object Reasoner {
private[this] def processConcept(concept: Concept, reasoner: ReasonerState): ReasonerState = {
if (reasoner.inits(concept)) reasoner
else {
val newState = `R⊤`(concept, R0(concept, reasoner.copy(inits = reasoner.inits + concept)))
val superClassesOfBottom = reasoner.closureSubsBySubclass.getOrElse(Bottom, Set.empty)
val updatedClosureSubsBySubclass = reasoner.closureSubsBySubclass.updated(Bottom, superClassesOfBottom + concept)
val newState = `R⊤`(concept, R0(concept, reasoner.copy(inits = reasoner.inits + concept, closureSubsBySubclass = updatedClosureSubsBySubclass)))
newState.queueDelegates.keysIterator.foldLeft(newState) { (state, delegateKey) =>
state.queueDelegates(delegateKey).processConcept(concept, state)
}
}
}

private[this] val emptySubClassSet: Set[Concept] = Set(Bottom)

private[this] def processConceptInclusion(ci: ConceptInclusion, reasoner: ReasonerState): ReasonerState = {
val ConceptInclusion(subclass, superclass) = ci
val subs = reasoner.closureSubsBySuperclass.getOrElse(superclass, Set.empty)
val subs = reasoner.closureSubsBySuperclass.getOrElse(superclass, emptySubClassSet)
if (subs(subclass)) reasoner else {
val closureSubsBySuperclass = reasoner.closureSubsBySuperclass.updated(superclass, subs + subclass)
val supers = reasoner.closureSubsBySubclass.getOrElse(subclass, Set.empty)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
Prefix(:=<http://example.org/>)
Prefix(owl:=<http://www.w3.org/2002/07/owl#>)
Prefix(rdf:=<http://www.w3.org/1999/02/22-rdf-syntax-ns#>)
Prefix(xml:=<http://www.w3.org/XML/1998/namespace>)
Prefix(xsd:=<http://www.w3.org/2001/XMLSchema#>)
Prefix(rdfs:=<http://www.w3.org/2000/01/rdf-schema#>)


Ontology(<http://example.org/>

Declaration(Class(:A))
Declaration(Class(:B))
Declaration(Class(:BY))
Declaration(Class(:C))
Declaration(Class(:X))
Declaration(Class(:Y))
Declaration(Class(:Z))
############################
# Classes
############################

# Class: :A (:A)

DisjointClasses(:A :X)

# Class: :B (:B)

SubClassOf(:B :A)

# Class: :BY (:BY)

EquivalentClasses(:BY ObjectIntersectionOf(:B :Y))

# Class: :C (:C)

SubClassOf(:C :B)

# Class: :Y (:Y)

SubClassOf(:Y :X)

# Class: :Z (:Z)

SubClassOf(:Z :Y)


)
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,18 @@ object TestOWLReasoner extends TestSuite {
reasoner.getInstances(Class("http://example.org/blah"), true)
}

"Unsatisfiable classes should be equivalent to owl:Nothing" - {
val manager = OWLManager.createOWLOntologyManager()
val ontology = manager.loadOntologyFromOntologyDocument(this.getClass.getResourceAsStream("owl-reasoner-nothing-equiv.ofn"))
val reasoner = new WhelkOWLReasonerFactory().createReasoner(ontology)
assert(reasoner.getSubClasses(Class("http://example.org/C") and Class("http://example.org/Z"), false).isEmpty)
assert(reasoner.getEquivalentClasses(Class("http://example.org/C") and Class("http://example.org/Z")).getEntities.asScala.toSet == Set(OWLNothing))
assert(reasoner.getSubClasses(Class("http://example.org/BY"), false).isEmpty)
assert(reasoner.getEquivalentClasses(Class("http://example.org/BY")).getEntities.asScala.toSet == Set(OWLNothing))
assert(reasoner.getSubClasses(OWLNothing, false).getFlattened.isEmpty)
assert(reasoner.getEquivalentClasses(OWLNothing).getEntities.asScala.toSet == Set(Class("http://example.org/BY")))
}

}

}
5 changes: 2 additions & 3 deletions modules/protege/update.properties
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
id=org.geneontology.whelk
version=1.0
#FIXME
download=https://github.com/balhoff/whelk-protege/releases/download/v0.1.0.1/whelk-protege-0.1.0.1.jar
version=1.0.4
download=https://github.com/balhoff/whelk-protege/releases/download/v1.0.4/whelk-reasoner-protege-plugin-1.0.4.jar
name=Whelk plug-in for Protégé
readme=https://raw.githubusercontent.com/balhoff/whelk/master/README.md
license=https://opensource.org/licenses/BSD-3-Clause
Expand Down

0 comments on commit c39b714

Please sign in to comment.