Skip to content

Commit

Permalink
Merge pull request #27 from dice-group/develop
Browse files Browse the repository at this point in the history
New Release
  • Loading branch information
Demirrr committed Apr 19, 2024
2 parents 8ee155b + c48e40d commit ea48dc9
Show file tree
Hide file tree
Showing 42 changed files with 1,620 additions and 1,038 deletions.
30 changes: 16 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# OWLAPY

OWLAPY is a Python Framework that serves as a base structure for creating and manipulating
OWL Ontologies.

Have a look at the [Documentation](https://dice-group.github.io/owlapy/).

## Installation
<details><summary> Click me! </summary>

Expand All @@ -21,42 +26,39 @@ In this example we start with a simple atomic class expression and move to some
ones and finally render and print the last of them in description logics syntax.

```python
from owlapy.iri import IRI
from owlapy.class_expression import OWLClass, OWLObjectIntersectionOf, OWLObjectSomeValuesFrom
from owlapy.owl_property import OWLObjectProperty
from owlapy.owl2sparql.converter import owl_expression_to_sparql
from owlapy.render import owl_expression_to_dl
from owlapy import owl_expression_to_sparql, owl_expression_to_dl

# Create the male class
male = OWLClass("http://example.com/society#male")

# Create an object property using the iri as a string for 'hasChild' property.
hasChild = OWLObjectProperty("http://example.com/society#hasChild")

# Create an existential restrictions
males_with_children = OWLObjectSomeValuesFrom(hasChild, male)
hasChild_male = OWLObjectSomeValuesFrom(hasChild, male)

# Let's make it more complex by intersecting with another class
teacher = OWLClass("http://example.com/society#teacher")
male_teachers_with_children = OWLObjectIntersectionOf([males_with_children, teacher])
teacher_that_hasChild_male = OWLObjectIntersectionOf([hasChild_male, teacher])

# You can render and print owl class expressions in description logics syntax (and vice-versa)
print(owl_expression_to_dl(male_teachers_with_children))
print(owl_expression_to_dl(teacher_that_hasChild_male))
# (∃ hasChild.male) ⊓ teacher
print(owl_expression_to_sparql("?x", male_teachers_with_children))
print(owl_expression_to_sparql("?x", teacher_that_hasChild_male))
# SELECT DISTINCT ?x WHERE { ?x <http://example.com/society#hasChild> ?s_1 . ?s_1 a <http://example.com/society#male> . ?x a <http://example.com/society#teacher> . } }
```
For more, you can check the [API documentation](https://ontolearn-docs-dice-group.netlify.app/autoapi/owlapy/#module-owlapy).


Every OWL object that can be used to classify individuals, is considered a class expression and
inherits from [OWLClassExpression](https://ontolearn-docs-dice-group.netlify.app/autoapi/owlapy/model/#owlapy.model.OWLClassExpression)
inherits from [OWLClassExpression](https://dice-group.github.io/owlapy/autoapi/owlapy/class_expression/class_expression/index.html#owlapy.class_expression.class_expression.OWLClassExpression)
class. In the above examples we have introduced 3 types of class expressions:
- [OWLClass](https://ontolearn-docs-dice-group.netlify.app/autoapi/owlapy/model/#owlapy.model.OWLClass),
- [OWLObjectSomeValuesFrom](https://ontolearn-docs-dice-group.netlify.app/autoapi/owlapy/model/#owlapy.model.OWLObjectSomeValuesFrom)
- [OWLObjectIntersectionOf](https://ontolearn-docs-dice-group.netlify.app/autoapi/owlapy/model/#owlapy.model.OWLObjectIntersectionOf).
- [OWLClass](https://dice-group.github.io/owlapy/autoapi/owlapy/class_expression/owl_class/index.html#owlapy.class_expression.owl_class.OWLClass),
- [OWLObjectSomeValuesFrom](https://dice-group.github.io/owlapy/autoapi/owlapy/class_expression/restriction/index.html#owlapy.class_expression.restriction.OWLObjectSomeValuesFrom)
- [OWLObjectIntersectionOf](https://dice-group.github.io/owlapy/autoapi/owlapy/class_expression/nary_boolean_expression/index.html#owlapy.class_expression.nary_boolean_expression.OWLObjectIntersectionOf).

Like we showed in this example, you can create all kinds of class expressions using the
OWL objects in [owlapy model](https://ontolearn-docs-dice-group.netlify.app/autoapi/owlapy/model/#module-owlapy.model).
OWL objects in [owlapy api](https://dice-group.github.io/owlapy/autoapi/owlapy/index.html).
</details>

## How to cite
Expand Down
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ Welcome to OWLAPY!
:caption: Contents:

usage/main
usage/usage_examples
autoapi/owlapy/index
59 changes: 57 additions & 2 deletions docs/usage/main.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,58 @@
# OWLAPY
# About owlapy

placeholder
**Version:** owlapy 1.0.0

**GitHub repository:** [https://github.com/dice-group/owlapy](https://github.com/dice-group/owlapy)

**Publisher and maintainer:** [DICE](https://dice-research.org/) - data science research group of [Paderborn University](https://www.uni-paderborn.de/en/university).

**Contact**: [onto-learn@lists.uni-paderborn.de](mailto:onto-learn@lists.uni-paderborn.de)

**License:** GNU Affero General Public License v3 or later (AGPLv3+)

--------------------------------------------------------------------------------------------
## What is owlapy?
Owlapy is an open-source software library in python that is used to represent entities
in OWL 2 Web Ontology Language.

We identified the gap of having a library that will serve as a base structure
for representing OWL entities in python and like that, owlapy was created. Owlapy
is loosely based on its java-counterpart, _owlapi_. Owlapy is currently utilized
by powerful libraries such as [Ontolearn](https://github.com/dice-group/Ontolearn)
and [OntoSample](https://github.com/alkidbaci/OntoSample).

Owlapy is the perfect choice for machine learning projects that are built in python and
focus on knowledge graphs and class expression learnings.

---------------------------------------

## What does owlapy have to offer?

- Represent every notation in
[OWL 2 Structural Specification and Functional-Style Syntax](https://www.w3.org/TR/owl2-syntax/)
including:
- Entities, Literals, and Anonymous Individuals
- Property Expressions
- Data Ranges
- Class Expressions
- Axioms
- Annotations
- Construct complex class expressions.
- Provide interfaces for OWL Ontology, Ontology manager and Reasoner.
- Convert owl expression to SPARQL queries.
- Render owl expression to Description Logics or Manchester syntax.
- Parse Description Logics or Manchester expression to owl expression.


## How to install?

Installation from source:
``` bash
git clone https://github.com/dice-group/owlapy
conda create -n temp_owlapy python=3.10.13 --no-default-packages && conda activate temp_owlapy && pip3 install -e .
```

or using PyPI:
```bash
pip3 install owlapy
```
126 changes: 126 additions & 0 deletions docs/usage/usage_examples.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# Usage

The main usage for owlapy is to use it for class expression construction. Class
expression learning algorithms require such basic structure to work upon. Let's walk
through an example of constructing some class expressions.

In this example we will be using the _family_ ontology,
a simple ontology with namespace: `http://example.com/family#`.
Here is a hierarchical diagram that shows the classes and their relationship:

Thing
|
person
/ |
male female

It contains only one object property which is `hasChild` and in total there
are six persons (individuals), of which four are males and two are females.

## Atomic Classes

To represent the classes `male`, `female`, and `person` we can simply use the
class [OWLClass](https://dice-group.github.io/owlapy/autoapi/owlapy/class_expression/owl_class/index.html#owlapy.class_expression.owl_class.OWLClass):

```python
from owlapy.class_expression import OWLClass
from owlapy.iri import IRI

namespace = "http://example.com/family#"

male = OWLClass(IRI(namespace, "male"))
female = OWLClass(IRI(namespace, "female"))
person = OWLClass(IRI(namespace, "person"))

```

Notice that we created an `IRI` object for every class. [IRI](https://dice-group.github.io/owlapy/autoapi/owlapy/iri/index.html#owlapy.iri.IRI)
is used to represent an _IRI_. Every named entity requires an IRI, whereas Anonymous entities does not.
However, in owlapy you can create an _OWLClass_ by passing the _IRI_ directly as a string, like so:

```python
male = OWLClass("http://example.com/family#male")
```

## Object Property

To represent the object property `hasChild` we can use the class
[OWLObjectProperty](https://dice-group.github.io/owlapy/autoapi/owlapy/owl_property/index.html#owlapy.owl_property.OWLObjectProperty):

```python
from owlapy.owl_property import OWLObjectProperty

hasChild = OWLObjectProperty("http://example.com/family#hasChild")
```

> **Tip:** In owlapy the naming of the classes is made in accordance with the notations from
> OWL 2 specification but with the word _"OWL"_ in the beginning. Example: _"OWLObjectProperty"_
> represents the notation _"ObjectProperty"_.
## Complex class expressions

Now that we have these atomic entities, we can construct more complex class
expressions. Let's say we want to represent all individuals which are `male`
and have at least 1 child.

We already have the concept of `male`. We need to find the appropriate class
for the second part: _"have at least 1 child"_. In OWL 2 specification that would be
[ObjectMinCardinality](https://www.w3.org/TR/owl2-syntax/#Minimum_Cardinality). In owlapy,
as we said, we simply add the word _"OWL"_ upfront to find the correct class:

```python
from owlapy.class_expression import OWLObjectMinCardinality

has_at_least_one_child = OWLObjectMinCardinality(
cardinality = 1,
property = hasChild,
filler = person
)
```
As you can see, to create an object of class [OWLObjectMinCardinality](https://dice-group.github.io/owlapy/autoapi/owlapy/class_expression/restriction/index.html#owlapy.class_expression.restriction.OWLObjectMinCardinality)
is as easy as that. You specify the cardinality which in this case is `1`, the object property where we apply this
cardinality restriction and the filler class in case you want to restrict the domain of the class expression. In this
case we used `person`.

Now let's merge both class expressions together using [OWLObjectIntersectionOf](https://dice-group.github.io/owlapy/autoapi/owlapy/class_expression/nary_boolean_expression/index.html#owlapy.class_expression.nary_boolean_expression.OWLObjectIntersectionOf):

```python
from owlapy.class_expression import OWLObjectIntersectionOf

ce = OWLObjectIntersectionOf([male, has_at_least_one_child])
```

## Convert to SPARQL, DL or Manchester syntax

Owlapy is not just a library to represent OWL entities, you can also
use it to convert owl expressions into other formats:

```python
from owlapy import owl_expression_to_sparql, owl_expression_to_dl, owl_expression_to_manchester

print(owl_expression_to_dl(ce))
# Result: male ⊓ (≥ 1 hasChild.person)

print(owl_expression_to_sparql(expression=ce))
# Result: SELECT DISTINCT ?x WHERE { ?x a <http://example.com/family#male> . { SELECT ?x WHERE { ?x <http://example.com/family#hasChild> ?s_1 . ?s_1 a <http://example.com/family#person> . } GROUP BY ?x HAVING ( COUNT ( ?s_1 ) >= 1 ) } }

print(owl_expression_to_manchester(ce))
# Result: male and (hasChild min 1 person)
```

To parse a DL or Manchester expression to owl expression you can use the
following convenient methods:

```python
from owlapy import dl_to_owl_expression, manchester_to_owl_expression

print(dl_to_owl_expression("∃ hasChild.male", namespace))
# Result: OWLObjectSomeValuesFrom(property=OWLObjectProperty(IRI('http://example.com/family#','hasChild')),filler=OWLClass(IRI('http://example.com/family#','male')))

print(manchester_to_owl_expression("female and (hasChild max 2 person)", namespace))
# Result: OWLObjectIntersectionOf((OWLClass(IRI('http://example.com/family#','female')), OWLObjectMaxCardinality(property=OWLObjectProperty(IRI('http://example.com/family#','hasChild')),2,filler=OWLClass(IRI('http://example.com/family#','person')))))

```

In these examples we showed a fraction of **owlapy**. You can explore the
[api documentation](owlapy) to learn more about all classes in owlapy.
5 changes: 4 additions & 1 deletion owlapy/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
__version__ = '0.1.3'
from .render import owl_expression_to_dl, owl_expression_to_manchester
from .parser import dl_to_owl_expression, manchester_to_owl_expression
from .converter import owl_expression_to_sparql
__version__ = '1.0.0'
14 changes: 0 additions & 14 deletions owlapy/_utils.py

This file was deleted.

7 changes: 4 additions & 3 deletions owlapy/class_expression/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""https://www.w3.org/TR/owl2-syntax/#Class_Expressions
""" OWL Class Expressions
https://www.w3.org/TR/owl2-syntax/#Class_Expressions
ClassExpression :=
owl_class.py:
Class
Expand Down Expand Up @@ -36,5 +37,5 @@
from typing import Final
from ..vocab import OWLRDFVocabulary

OWLThing: Final = OWLClass(OWLRDFVocabulary.OWL_THING.get_iri()) #: : :The OWL Class corresponding to owl:Thing
OWLNothing: Final = OWLClass(OWLRDFVocabulary.OWL_NOTHING.get_iri()) #: : :The OWL Class corresponding to owl:Nothing
OWLThing: Final = OWLClass(OWLRDFVocabulary.OWL_THING.iri) #: : :The OWL Class corresponding to owl:Thing
OWLNothing: Final = OWLClass(OWLRDFVocabulary.OWL_NOTHING.iri) #: : :The OWL Class corresponding to owl:Nothing
11 changes: 9 additions & 2 deletions owlapy/class_expression/class_expression.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
"""OWL Base Classes Expressions"""
from abc import abstractmethod, ABCMeta
from ..data_ranges import OWLPropertyRange, OWLDataRange
from ..owl_data_ranges import OWLPropertyRange
from ..meta_classes import HasOperands

from typing import Final, Iterable


class OWLClassExpression(OWLPropertyRange):
"""An OWL 2 Class Expression (https://www.w3.org/TR/owl2-syntax/#Class_Expressions) """
"""OWL Class expressions represent sets of individuals by formally specifying conditions on the individuals' properties;
individuals satisfying these conditions are said to be instances of the respective class expressions.
In the structural specification of OWL 2, class expressions are represented by ClassExpression.
(https://www.w3.org/TR/owl2-syntax/#Class_Expressions)
"""
__slots__ = ()

@abstractmethod
Expand Down
15 changes: 11 additions & 4 deletions owlapy/class_expression/nary_boolean_expression.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
"""OWL nary boolean expressions"""
from .class_expression import OWLClassExpression, OWLBooleanClassExpression
from ..meta_classes import HasOperands
from typing import Final, Sequence, Iterable


class OWLNaryBooleanClassExpression(OWLBooleanClassExpression, HasOperands[OWLClassExpression]):
"""OWLNaryBooleanClassExpression."""
__slots__ = ()
Expand Down Expand Up @@ -30,18 +33,22 @@ def __hash__(self):
return hash(self._operands)




class OWLObjectUnionOf(OWLNaryBooleanClassExpression):
"""Represents an ObjectUnionOf class expression in the OWL 2 Specification."""
"""A union class expression ObjectUnionOf( CE1 ... CEn ) contains all individuals that are instances
of at least one class expression CEi for 1 ≤ i ≤ n.
(https://www.w3.org/TR/owl2-syntax/#Union_of_Class_Expressions)
"""
__slots__ = '_operands'
type_index: Final = 3002

_operands: Sequence[OWLClassExpression]


class OWLObjectIntersectionOf(OWLNaryBooleanClassExpression):
"""Represents an OWLObjectIntersectionOf class expression in the OWL 2 Specification."""
"""An intersection class expression ObjectIntersectionOf( CE1 ... CEn ) contains all individuals that are instances
of all class expressions CEi for 1 ≤ i ≤ n.
(https://www.w3.org/TR/owl2-syntax/#Intersection_of_Class_Expressions)
"""
__slots__ = '_operands'
type_index: Final = 3001

Expand Down
Loading

0 comments on commit ea48dc9

Please sign in to comment.