Skip to content

Commit

Permalink
Merge branch 'develop' into ruff-integration
Browse files Browse the repository at this point in the history
# Conflicts:
#	owlapy/__init__.py
#	owlapy/owl_ontology_manager.py
#	owlapy/owl_reasoner.py
#	owlapy/owlapi_mapper.py
  • Loading branch information
alkidbaci committed Aug 27, 2024
2 parents 94f6e71 + e83232b commit f5fdc1a
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 34 deletions.
46 changes: 37 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,14 @@ pip3 install owlapy
```shell
# To download RDF knowledge graphs
wget https://files.dice-research.org/projects/Ontolearn/KGs.zip -O ./KGs.zip && unzip KGs.zip
pytest -p no:warnings -x # Running 103 tests takes ~ 30 mins
pytest -p no:warnings -x # Running 102 tests takes ~ 1 min
```

## Usage

In this example we start with a simple atomic class expression and move to some more complex
ones and finally render and print the last of them in description logics syntax.

### Creating OWL Class Expressions
<details><summary> Click me! </summary>

```python
from owlapy.class_expression import OWLClass, OWLObjectIntersectionOf, OWLObjectSomeValuesFrom
Expand All @@ -40,17 +41,13 @@ 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
hasChild_male = OWLObjectSomeValuesFrom(hasChild, male)

# Let's make it more complex by intersecting with another class
teacher = OWLClass("http://example.com/society#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(teacher_that_hasChild_male))
# (∃ hasChild.male) ⊓ teacher
Expand All @@ -68,7 +65,35 @@ class. In the above examples we have introduced 3 types of class expressions:
Like we showed in this example, you can create all kinds of class expressions using the
OWL objects in [owlapy api](https://dice-group.github.io/owlapy/autoapi/owlapy/index.html).

Many axioms can automatically inferred with a selected reasoner
</details>

### Logical Inference

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

```python
from owlapy.owl_ontology_manager import OntologyManager
from owlapy.owlapi_adaptor import OWLAPIAdaptor

ontology_path = "KGs/Family/family-benchmark_rich_background.owl"
# Available OWL Reasoners: 'HermiT', 'Pellet', 'JFact', 'Openllet'
owlapi_adaptor = OWLAPIAdaptor(path=ontology_path, name_reasoner="Pellet")
onto = OntologyManager().load_ontology(ontology_path)
# Iterate over defined owl Classes in the signature
for i in onto.classes_in_signature():
# Performing type inference with Pellet
instances=owlapi_adaptor.instances(i,direct=False)
print(f"Class:{i}\t Num instances:{len(instances)}")
owlapi_adaptor.stopJVM()
```

</details>

### Ontology Enrichment

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

An Ontology can be enriched by inferring many different axioms.
```python
from owlapy.owlapi_adaptor import OWLAPIAdaptor

Expand All @@ -86,7 +111,10 @@ adaptor.infer_axioms_and_save(output_path="KGs/Family/inferred_family-benchmark_
adaptor.stopJVM()
```

Check also the [examples](https://github.com/dice-group/owlapy/tree/develop/examples) folder.
</details>


Check also the [examples](https://github.com/dice-group/owlapy/tree/develop/examples) and [tests](https://github.com/dice-group/owlapy/tree/develop/tests) folders.

## How to cite
Currently, we are working on our manuscript describing our framework.
2 changes: 1 addition & 1 deletion owlapy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
from .parser import (dl_to_owl_expression as dl_to_owl_expression,
manchester_to_owl_expression as manchester_to_owl_expression)
from .converter import owl_expression_to_sparql as owl_expression_to_sparql
__version__ = '1.2.0'
__version__ = '1.2.1'
15 changes: 11 additions & 4 deletions owlapy/owl_ontology_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -851,10 +851,18 @@ def __init__(self, world_store=None):
else:
self._world = owlready2.World(filename=world_store)

def create_ontology(self, iri: IRI) -> 'Ontology':
def create_ontology(self, iri:Union[str,IRI]=None) -> 'Ontology':
if isinstance(iri, str):
iri=IRI.create(iri)
else:
assert isinstance(iri, IRI), "iri either must be string or an instance of IRI Class"
return Ontology(self, iri, load=False)

def load_ontology(self, iri: IRI) -> 'Ontology':
def load_ontology(self, iri: Union[str,IRI]=None) -> 'Ontology':
if isinstance(iri, str):
iri=IRI.create(iri)
else:
assert isinstance(iri, IRI), "iri either must be string or an instance of IRI Class"
return Ontology(self, iri, load=True)

def apply_change(self, change: OWLOntologyChange):
Expand All @@ -881,8 +889,7 @@ def save_ontology(self, ontology: OWLOntology, document_iri: IRI):
filename = document_iri.as_str()[len('file:/'):]
ont_x.save(file=filename)
else:
# TODO XXX
raise NotImplementedError
raise NotImplementedError("Couldn't save because the namespace of document_iri does not start with **file:/**")

def save_world(self):
"""Saves the actual state of the quadstore in the SQLite3 file.
Expand Down
25 changes: 6 additions & 19 deletions owlapy/owl_reasoner.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,12 @@

logger = logging.getLogger(__name__)

_P = TypeVar('_P', bound=OWLPropertyExpression)

# TODO:CD:The name of the classes defined with metaclass=ABCMeta should reflect that
# TODO:CD: An instance cannot be created from those classes.
# TODO:CD: We should move those Abstract Base Classes into a respective package, e.g.
# TODO:CD: owlapy/abstract_owl_reasoner/abstract_owl_reasoner.py should contain OWLReasoner and OWLReasonerEx
class OWLReasoner(metaclass=ABCMeta):
"""An OWLReasoner reasons over a set of axioms (the set of reasoner axioms) that is based on the imports closure of
a particular ontology - the "root" ontology."""
Expand Down Expand Up @@ -399,20 +404,6 @@ class expression with respect to the imports closure of the root ontology.
If ce is equivalent to owl:Thing then nothing will be returned.
"""
pass


# Deprecated
# class BaseReasoner(Enum):
# """Enumeration class for base reasoner when calling sync_reasoner.
#
# Attributes:
# PELLET: Pellet base reasoner.
# HERMIT: HermiT base reasoner.
# """
# PELLET = auto()
# HERMIT = auto()


class OWLReasonerEx(OWLReasoner, metaclass=ABCMeta):
"""Extra convenience methods for OWL Reasoners"""

Expand Down Expand Up @@ -494,10 +485,9 @@ def ind_object_properties(self, ind: OWLNamedIndividual, direct: bool = True) ->
except StopIteration:
pass


class OntologyReasoner(OWLReasonerEx):
__slots__ = '_ontology', '_world'

# TODO: CD: We will remove owlready2 from owlapy
_ontology: Ontology
_world: owlready2.World

Expand Down Expand Up @@ -1040,9 +1030,6 @@ def get_root_ontology(self) -> OWLOntology:
return self._ontology


_P = TypeVar('_P', bound=OWLPropertyExpression)


class FastInstanceCheckerReasoner(OWLReasonerEx):
"""Tries to check instances fast (but maybe incomplete)."""
__slots__ = '_ontology', '_base_reasoner', \
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
setup(
name="owlapy",
description="OWLAPY is a Python Framework for creating and manipulating OWL Ontologies.",
version="1.2.0",
version="1.2.1",
packages=find_packages(),
include_package_data=True,
package_data={
Expand Down

0 comments on commit f5fdc1a

Please sign in to comment.