Skip to content

Commit

Permalink
Merge pull request #59 from dice-group/retrieval
Browse files Browse the repository at this point in the history
Refactoring and Readme Update
  • Loading branch information
Demirrr authored Aug 22, 2024
2 parents 1f6d2aa + a1ce56d commit 427a629
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 37 deletions.
44 changes: 36 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ pytest -p no:warnings -x # Running 103 tests takes ~ 30 mins

## 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.
17 changes: 12 additions & 5 deletions owlapy/owl_ontology_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
from owlapy.owl_ontology import OWLOntology, Ontology, ToOwlready2
from owlapy.owl_property import OWLDataProperty, OWLObjectInverseOf, OWLObjectProperty, \
OWLProperty

from typing import Union

class OWLOntologyChange(metaclass=ABCMeta):
"""Represents an ontology change."""
Expand Down Expand Up @@ -849,10 +849,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 @@ -879,8 +887,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
32 changes: 9 additions & 23 deletions owlapy/owl_reasoner.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@
import operator
from abc import ABCMeta, abstractmethod
from collections import defaultdict
from enum import Enum, auto
from functools import singledispatchmethod, reduce
from itertools import chain, repeat
from types import MappingProxyType, FunctionType
from typing import DefaultDict, Iterable, Dict, Mapping, Set, Type, TypeVar, Optional, FrozenSet, List, cast
from typing import DefaultDict, Iterable, Dict, Mapping, Set, Type, TypeVar, Optional, FrozenSet
import logging

import owlready2
Expand All @@ -18,11 +17,11 @@
OWLDataAllValuesFrom
from owlapy.class_expression import OWLClass
from owlapy.iri import IRI
from owlapy.owl_axiom import OWLAxiom, OWLSubClassOfAxiom
from owlapy.owl_axiom import OWLSubClassOfAxiom
from owlapy.owl_data_ranges import OWLDataRange, OWLDataComplementOf, OWLDataUnionOf, OWLDataIntersectionOf
from owlapy.owl_datatype import OWLDatatype
from owlapy.owl_object import OWLEntity
from owlapy.owl_ontology import OWLOntology, Ontology, _parse_concept_to_owlapy, ToOwlready2
from owlapy.owl_ontology import OWLOntology, Ontology, _parse_concept_to_owlapy
from owlapy.owl_ontology_manager import OntologyManager
from owlapy.owl_property import OWLObjectPropertyExpression, OWLDataProperty, OWLObjectProperty, OWLObjectInverseOf, \
OWLPropertyExpression, OWLDataPropertyExpression
Expand All @@ -33,7 +32,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 @@ -401,20 +405,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 @@ -496,10 +486,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 @@ -1042,9 +1031,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
6 changes: 5 additions & 1 deletion owlapy/owlapi_mapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import jpype.imports

import owlapy.owl_ontology
from owlapy import owl_expression_to_manchester, manchester_to_owl_expression
from owlapy.class_expression import OWLClassExpression, OWLDataOneOf, OWLFacetRestriction, OWLDatatypeRestriction
from owlapy.iri import IRI
Expand Down Expand Up @@ -90,7 +91,10 @@ def init(the_class):

class OWLAPIMapper:

def __init__(self, ontology):
def __init__(self, ontology=None):
# TODO: CD: Please use class type of ontology
# TODO: CD: if ontology is None, then we should throw an exception with a useful information
# assert isinstance(ontology, OWLAPIMapper)
self.ontology = ontology
self.manager = ontology.getOWLOntologyManager()

Expand Down

0 comments on commit 427a629

Please sign in to comment.