Git Product home page Git Product logo

scowl's Introduction

Scowl

status

Scowl provides a Scala DSL allowing a declarative approach to composing OWL expressions and axioms using the OWL API.

Usage

Since version 1.2.1, Scowl is available via Maven Central. Add the dependency to your build.sbt if you are using OWL API 4.x:

libraryDependencies += "org.phenoscape" %% "scowl" % "1.4.1"

For OWL API 5.x:

libraryDependencies += "org.phenoscape" %% "scowl-owlapi5" % "1.4.1"

Import org.phenoscape.scowl._, and Scowl implicit conversions will add pseudo Manchester syntax methods to native OWL API objects. Additionally, functional syntax-style constructors and extractors will be in scope.

Scowl 1.2+ is built with OWL API 4.x (and from 1.4.1, additionally OWL API 5.x). For OWL API 3.5, use Scowl 1.0.2. Scowl is cross-compiled to support Scala 2.13 and Scala 3.

Examples

The easiest way to get started is to see how the DSL can be used to implement all the examples from the OWL 2 Web Ontology Language Primer:

The examples below are also available in code.

Scowl expressions use and return native OWL API objects

import org.phenoscape.scowl._
// import org.phenoscape.scowl._

val hasParent = ObjectProperty("http://www.co-ode.org/roberts/family-tree.owl#hasParent")
// hasParent: org.semanticweb.owlapi.model.OWLObjectProperty = <http://www.co-ode.org/roberts/family-tree.owl#hasParent>

val isParentOf = ObjectProperty("http://www.co-ode.org/roberts/family-tree.owl#isParentOf")
// isParentOf: org.semanticweb.owlapi.model.OWLObjectProperty = <http://www.co-ode.org/roberts/family-tree.owl#isParentOf>

val isSiblingOf = ObjectProperty("http://www.co-ode.org/roberts/family-tree.owl#isSiblingOf")
// isSiblingOf: org.semanticweb.owlapi.model.OWLObjectProperty = <http://www.co-ode.org/roberts/family-tree.owl#isSiblingOf>

val Person = Class("http://www.co-ode.org/roberts/family-tree.owl#Person")
// Person: org.semanticweb.owlapi.model.OWLClass = <http://www.co-ode.org/roberts/family-tree.owl#Person>

val FirstCousin = Class("http://www.co-ode.org/roberts/family-tree.owl#FirstCousin")
// FirstCousin: org.semanticweb.owlapi.model.OWLClass = <http://www.co-ode.org/roberts/family-tree.owl#FirstCousin>

val axiom = FirstCousin EquivalentTo (Person and (hasParent some (Person and (isSiblingOf some (Person and (isParentOf some Person))))))
// axiom: org.semanticweb.owlapi.model.OWLEquivalentClassesAxiom = EquivalentClasses(<http://www.co-ode.org/roberts/family-tree.owl#FirstCousin> ObjectIntersectionOf(<http://www.co-ode.org/roberts/family-tree.owl#Person> ObjectSomeValuesFrom(<http://www.co-ode.org/roberts/family-tree.owl#hasParent> ObjectIntersectionOf(<http://www.co-ode.org/roberts/family-tree.owl#Person> ObjectSomeValuesFrom(<http://www.co-ode.org/roberts/family-tree.owl#isSiblingOf> ObjectIntersectionOf(<http://www.co-ode.org/roberts/family-tree.owl#Person> ObjectSomeValuesFrom(<http://www.co-ode.org/roberts/family-tree.owl#isParentOf> <http://www.co-ode.org/roberts/family-tree.owl#Person>)))))) )

Add some axioms and programmatically generated GCIs to an ontology

val manager = OWLManager.createOWLOntologyManager()
val ontology = manager.createOntology()
val PartOf = ObjectProperty("http://example.org/part_of")
val HasPart = ObjectProperty("http://example.org/has_part")
val DevelopsFrom = ObjectProperty("http://example.org/develops_from")
val Eye = Class("http://example.org/eye")
val Head = Class("http://example.org/head")
val Tail = Class("http://example.org/tail")

manager.addAxiom(ontology, Eye SubClassOf (PartOf some Head))
manager.addAxiom(ontology, Eye SubClassOf (not(PartOf some Tail)))

val gcis = for {
  term <- ontology.getClassesInSignature(true)
} yield {
  (not(HasPart some term)) SubClassOf (not(HasPart some (DevelopsFrom some term)))
}
manager.addAxioms(ontology, gcis)

Using pattern matching extractors to implement negation normal form

def nnf(expression: OWLClassExpression): OWLClassExpression = expression match {
  case Class(_)                                                          => expression
  case ObjectComplementOf(Class(_))                                      => expression
  case ObjectComplementOf(ObjectComplementOf(expression))                => nnf(expression)
  case ObjectUnionOf(operands)                                           => ObjectUnionOf(operands.map(nnf))
  case ObjectIntersectionOf(operands)                                    => ObjectIntersectionOf(operands.map(nnf))
  case ObjectComplementOf(ObjectUnionOf(operands))                       => ObjectIntersectionOf(operands.map(c => nnf(ObjectComplementOf(c))))
  case ObjectComplementOf(ObjectIntersectionOf(operands))                => ObjectUnionOf(operands.map(c => nnf(ObjectComplementOf(c))))
  case ObjectAllValuesFrom(property, filler)                             => ObjectAllValuesFrom(property, nnf(filler))
  case ObjectSomeValuesFrom(property, filler)                            => ObjectSomeValuesFrom(property, nnf(filler))
  case ObjectMinCardinality(num, property, filler)                       => ObjectMinCardinality(num, property, nnf(filler))
  case ObjectMaxCardinality(num, property, filler)                       => ObjectMaxCardinality(num, property, nnf(filler))
  case ObjectExactCardinality(num, property, filler)                     => ObjectExactCardinality(num, property, nnf(filler))
  case ObjectComplementOf(ObjectAllValuesFrom(property, filler))         => ObjectSomeValuesFrom(property, nnf(ObjectComplementOf(filler)))
  case ObjectComplementOf(ObjectSomeValuesFrom(property, filler))        => ObjectAllValuesFrom(property, nnf(ObjectComplementOf(filler)))
  case ObjectComplementOf(ObjectMinCardinality(num, property, filler))   => ObjectMaxCardinality(math.max(num - 1, 0), property, nnf(filler))
  case ObjectComplementOf(ObjectMaxCardinality(num, property, filler))   => ObjectMinCardinality(num + 1, property, nnf(filler))
  case ObjectComplementOf(ObjectExactCardinality(num, property, filler)) => ObjectUnionOf(ObjectMinCardinality(num + 1, property, nnf(filler)), ObjectMaxCardinality(math.max(num - 1, 0), property, nnf(filler)))
  case _                                                                 => ???
}

Using pattern matching extractors in for comprehensions

// Print all properties and fillers used in existential restrictions in subclass axioms
for {
  SubClassOf(_, subclass, ObjectSomeValuesFrom(property, filler)) <- ontology.getAxioms
} yield {
  println(s"$property $filler")
}

// Make an index of language tags to label values
val langValuePairs = for {
  AnnotationAssertion(_, RDFSLabel, _, value @@ Some(lang)) <- ontology.getAxioms(Imports.INCLUDED)
} yield {
  lang -> value
}
val langToValues: Map[String, Set[String]] = langValuePairs.foldLeft(Map.empty[String, Set[String]]) {
  case (langIndex, (lang, value)) =>
    langIndex.updated(lang, langIndex.getOrElse(value, Set.empty) ++ Set(value))
}

Question or problem?

If you have questions about how to use Scowl, feel free to send an email to [email protected], or open an issue on the tracker. Contributions are welcome.

Funding

Development of Scowl has been supported by National Science Foundation grant DBI-1062404 to the University of North Carolina.

License

Scowl is open source under the MIT License. See LICENSE for more information.

scowl's People

Contributors

balhoff avatar francesco-kriegel avatar scala-steward avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

scowl's Issues

Using an individual as the object of an annotation axiom

It is not possible to use an individual as the object of an annotation axiom specified using scowl annotation or annotations.

I believe this is legal (if slightly odd) OWL. Protege handles it fine, e.g.:

image

Would it be too much of a stretch to extend SCOWL to handle this?

Don't create nested intersections

A chain of "and" methods creates nested intersections:

A and B and C produces ObjectIntersectionOf(A, ObjectIntersectionOf(B, C))

instead of

ObjectIntersectionOf(A, B, C)

Infix conjuctions are not commutative

Conjuction is commutative in OWL, but not in Scowl. Consider:

scala> import org.phenoscape.scowl._

import org.phenoscape.scowl._

scala>
scala> val a = Class("a")
a: org.semanticweb.owlapi.model.OWLClass = <a>

scala> val b = Class("b")
b: org.semanticweb.owlapi.model.OWLClass = <b>

scala> val c = Class("c")
c: org.semanticweb.owlapi.model.OWLClass = <c>

scala> a and b and c
res0: org.semanticweb.owlapi.model.OWLObjectIntersectionOf = ObjectIntersectionOf(<a> <b> <c>)

scala> a and (b and c)
res1: org.semanticweb.owlapi.model.OWLObjectIntersectionOf = ObjectIntersectionOf(<a> ObjectIntersectionOf(<b> <c>))

scala> (b and c) and a
res2: org.semanticweb.owlapi.model.OWLObjectIntersectionOf = ObjectIntersectionOf(<a> <b> <c>)

All of these results make sense except for the last which should return
ObjectIntersectionOf(<a> ObjectIntersectionOf(<b> <c>)) I think.

I think this is caused bc2d369 which addresses #3 unfortunately.

Just playing with Scowl and Scala. Very nice piece of work (Scowl that is,
Scala I will reserve judgement on for the moment)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.