diff --git a/README.md b/README.md index c228967..072804b 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,6 @@ 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 import owl_expression_to_sparql, owl_expression_to_dl @@ -33,16 +32,16 @@ male = OWLClass("http://example.com/society#male") 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 ?s_1 . ?s_1 a . ?x a . } } ``` For more, you can check the [API documentation](https://dice-group.github.io/owlapy/autoapi/owlapy/index.html). diff --git a/docs/index.rst b/docs/index.rst index 3e4858f..29abab7 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -11,4 +11,5 @@ Welcome to OWLAPY! :caption: Contents: usage/main + usage/examples autoapi/owlapy/index \ No newline at end of file diff --git a/docs/usage/main.md b/docs/usage/main.md index 54b6f2f..b45e981 100644 --- a/docs/usage/main.md +++ b/docs/usage/main.md @@ -1,3 +1,58 @@ # OWLAPY -placeholder \ No newline at end of file +**Version:** ontolearn 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 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. + + +## Installation + +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 +``` \ No newline at end of file diff --git a/docs/usage/usage_examples.md b/docs/usage/usage_examples.md new file mode 100644 index 0000000..531b249 --- /dev/null +++ b/docs/usage/usage_examples.md @@ -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 . { SELECT ?x WHERE { ?x ?s_1 . ?s_1 a . } 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. \ No newline at end of file diff --git a/owlapy/parser.py b/owlapy/parser.py index ee8081c..fa047fa 100644 --- a/owlapy/parser.py +++ b/owlapy/parser.py @@ -775,9 +775,11 @@ def generic_visit(self, node, children): ManchesterParser = ManchesterOWLSyntaxParser() -def dl_to_owl_expression(dl_expression: str): +def dl_to_owl_expression(dl_expression: str, namespace: str): + DLparser.ns = namespace return DLparser.parse_expression(dl_expression) -def manchester_to_owl_expression(manchester_expression: str): +def manchester_to_owl_expression(manchester_expression: str, namespace: str): + ManchesterParser.ns = namespace return ManchesterParser.parse_expression(manchester_expression)