Repository: dice-group/owlapy (language: python)

Issue:
Refactoring sync reasoner



Discussion / hints:

Fix patch:
diff --git a/.github/workflows/ruff.yml b/.github/workflows/ruff.yml
deleted file mode 100644
index b6690e05..00000000
--- a/.github/workflows/ruff.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-name: Ruff
-on: [push, pull_request]
-jobs:
-  ruff:
-    runs-on: ubuntu-latest
-    steps:
-      - uses: actions/checkout@v4
-      - uses: chartboost/ruff-action@v1
\ No newline at end of file
diff --git a/README.md b/README.md
index 9eb842a7..2cfcbc91 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
 # OWLAPY
 [![Coverage](https://img.shields.io/badge/coverage-78%25-green)](https://dice-group.github.io/owlapy/usage/further_resources.html#coverage-report)
-[![Pypi](https://img.shields.io/badge/pypi-1.3.2-blue)](https://pypi.org/project/owlapy/1.3.2/)
-[![Docs](https://img.shields.io/badge/documentation-1.3.2-yellow)](https://dice-group.github.io/owlapy/usage/main.html)
+[![Pypi](https://img.shields.io/badge/pypi-1.3.3-blue)](https://pypi.org/project/owlapy/1.3.3/)
+[![Docs](https://img.shields.io/badge/documentation-1.3.3-yellow)](https://dice-group.github.io/owlapy/usage/main.html)
 
 ![OWLAPY](docs/_static/images/owlapy_logo.png)
 
@@ -30,6 +30,54 @@ pytest -p no:warnings -x # Running  142 tests ~ 30 secs
 
 ## Examples
 
+### Exploring OWL Ontology
+
+<details><summary> Click me! </summary>
+
+```python
+from owlapy.owl_ontology_manager import SyncOntologyManager
+
+ontology_path = "KGs/Family/father.owl"
+onto = SyncOntologyManager().load_ontology(ontology_path)
+
+print({owl_class.reminder for owl_class in onto.classes_in_signature()}) 
+# {'Thing', 'female', 'male', 'person'}
+
+print({individual.reminder for individual in onto.individuals_in_signature()}) 
+# {'michelle', 'stefan', 'martin', 'anna', 'heinz', 'markus'}
+
+print({object_property.reminder for object_property in onto.object_properties_in_signature()})
+# {'hasChild'}
+
+for owl_subclass_of_axiom in onto.get_tbox_axioms():
+    print(owl_subclass_of_axiom)
+
+# OWLEquivalentClassesAxiom([OWLClass(IRI('http://example.com/father#', 'male')), OWLObjectComplementOf(OWLClass(IRI('http://example.com/father#', 'female')))],[])
+# OWLSubClassOfAxiom(sub_class=OWLClass(IRI('http://example.com/father#', 'female')),super_class=OWLClass(IRI('http://example.com/father#', 'person')),annotations=[])
+# OWLSubClassOfAxiom(sub_class=OWLClass(IRI('http://example.com/father#', 'male')),super_class=OWLClass(IRI('http://example.com/father#', 'person')),annotations=[])
+# OWLSubClassOfAxiom(sub_class=OWLClass(IRI('http://example.com/father#', 'person')),super_class=OWLClass(IRI('http://www.w3.org/2002/07/owl#', 'Thing')),annotations=[])
+# OWLObjectPropertyRangeAxiom(OWLObjectProperty(IRI('http://example.com/father#', 'hasChild')),OWLClass(IRI('http://example.com/father#', 'person')),[])
+# OWLObjectPropertyDomainAxiom(OWLObjectProperty(IRI('http://example.com/father#', 'hasChild')),OWLClass(IRI('http://example.com/father#', 'person')),[])
+
+
+for axiom in onto.get_abox_axioms():
+    print(axiom)
+    
+# OWLClassAssertionAxiom(individual=OWLNamedIndividual(IRI('http://example.com/father#', 'anna')),class_expression=OWLClass(IRI('http://example.com/father#', 'female')),annotations=[])
+# OWLClassAssertionAxiom(individual=OWLNamedIndividual(IRI('http://example.com/father#', 'michelle')),class_expression=OWLClass(IRI('http://example.com/father#', 'female')),annotations=[])
+# OWLClassAssertionAxiom(individual=OWLNamedIndividual(IRI('http://example.com/father#', 'martin')),class_expression=OWLClass(IRI('http://example.com/father#', 'male')),annotations=[])
+# OWLClassAssertionAxiom(individual=OWLNamedIndividual(IRI('http://example.com/father#', 'markus')),class_expression=OWLClass(IRI('http://example.com/father#', 'male')),annotations=[])
+# OWLClassAssertionAxiom(individual=OWLNamedIndividual(IRI('http://example.com/father#', 'heinz')),class_expression=OWLClass(IRI('http://example.com/father#', 'male')),annotations=[])
+# OWLClassAssertionAxiom(individual=OWLNamedIndividual(IRI('http://example.com/father#', 'stefan')),class_expression=OWLClass(IRI('http://example.com/father#', 'male')),annotations=[])
+# OWLObjectPropertyAssertionAxiom(subject=OWLNamedIndividual(IRI('http://example.com/father#', 'markus')),property_=OWLObjectProperty(IRI('http://example.com/father#', 'hasChild')),object_=OWLNamedIndividual(IRI('http://example.com/father#', 'anna')),annotations=[])
+# OWLObjectPropertyAssertionAxiom(subject=OWLNamedIndividual(IRI('http://example.com/father#', 'martin')),property_=OWLObjectProperty(IRI('http://example.com/father#', 'hasChild')),object_=OWLNamedIndividual(IRI('http://example.com/father#', 'heinz')),annotations=[])
+# OWLObjectPropertyAssertionAxiom(subject=OWLNamedIndividual(IRI('http://example.com/father#', 'stefan')),property_=OWLObjectProperty(IRI('http://example.com/father#', 'hasChild')),object_=OWLNamedIndividual(IRI('http://example.com/father#', 'markus')),annotations=[])
+# OWLObjectPropertyAssertionAxiom(subject=OWLNamedIndividual(IRI('http://example.com/father#', 'anna')),property_=OWLObjectProperty(IRI('http://example.com/father#', 'hasChild')),object_=OWLNamedIndividual(IRI('http://example.com/father#', 'heinz')),annotations=[])
+
+```
+
+</details>
+
 ### Creating OWL Class Expressions
 <details><summary> Click me! </summary>
 
diff --git a/docs/conf.py b/docs/conf.py
index 9e37f605..641cf1fb 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -13,7 +13,7 @@
 
 project = 'OWLAPY'
 author = 'Ontolearn Team'
-release = '1.3.2'
+release = '1.3.3'
 
 # -- General configuration ---------------------------------------------------
 # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
diff --git a/docs/usage/main.md b/docs/usage/main.md
index 36b77c2b..c646825c 100644
--- a/docs/usage/main.md
+++ b/docs/usage/main.md
@@ -1,6 +1,6 @@
 # About owlapy
 
-**Version:** owlapy 1.3.2
+**Version:** owlapy 1.3.3
 
 **GitHub repository:** [https://github.com/dice-group/owlapy](https://github.com/dice-group/owlapy)
 
diff --git a/owlapy/__init__.py b/owlapy/__init__.py
index 84aec36b..78a0a08e 100644
--- a/owlapy/__init__.py
+++ b/owlapy/__init__.py
@@ -3,7 +3,7 @@
 from .converter import owl_expression_to_sparql, owl_expression_to_sparql_with_confusion_matrix
 from .owl_ontology_manager import OntologyManager
 
-__version__ = '1.3.2'
+__version__ = '1.3.3'
 
 __all__ = [
     'owl_expression_to_dl', 'owl_expression_to_manchester',
diff --git a/owlapy/class_expression/restriction.py b/owlapy/class_expression/restriction.py
index 911a718a..0e6658a9 100644
--- a/owlapy/class_expression/restriction.py
+++ b/owlapy/class_expression/restriction.py
@@ -10,7 +10,7 @@
 from ..owl_individual import OWLIndividual
 from ..owl_datatype import OWLDatatype
 from ..owl_object import OWLObject
-from owlapy.vocab import OWLFacet
+from ..vocab import  OWLFacet
 from datetime import datetime, date
 from pandas import Timedelta
 
@@ -65,7 +65,7 @@ def __init__(self, value: _T):
     def __eq__(self, other):
         if type(other) is type(self):
             return self._v == other._v
-        return NotImplemented
+        return False
 
     def __hash__(self):
         return hash(self._v)
@@ -272,10 +272,11 @@ def __repr__(self):
     def __eq__(self, other):
         if type(other) is type(self):
             return self._filler == other._filler and self._property == other._property
-        return NotImplemented
+        else:
+            return False
 
     def __hash__(self):
-        return hash((self._filler, self._property))
+        return hash(("OWLObjectSomeValuesFrom",self._filler, self._property))
 
     def get_property(self) -> OWLObjectPropertyExpression:
         # documented in parent
@@ -303,7 +304,7 @@ def __eq__(self, other):
             return False
 
     def __hash__(self):
-        return hash((self._filler, self._property))
+        return hash(("OWLObjectAllValuesFrom",self._filler, self._property))
 
     def get_property(self) -> OWLObjectPropertyExpression:
         # documented in parent
@@ -341,8 +342,9 @@ def __eq__(self, other):
         else:
             return False
 
+
     def __hash__(self):
-        return hash(self._property)
+        return hash(("OWLObjectHasSelf", self._property))
 
     def __repr__(self):
         return f'OWLObjectHasSelf({self._property})'
@@ -403,7 +405,7 @@ def __init__(self, values: OWLIndividual | Iterable[OWLIndividual]):
         else:
             for _ in values:
                 assert isinstance(_, OWLIndividual)
-            self._values = {i for i in values}
+            self._values = frozenset(values)
 
     def individuals(self) -> Iterable[OWLIndividual]:
         """Gets the individuals that are in the oneOf. These individuals represent the exact instances (extension)
@@ -428,16 +430,13 @@ def as_object_union_of(self) -> OWLClassExpression:
         if len(self._values) == 1:
             return self
         return OWLObjectUnionOf(map(lambda _: OWLObjectOneOf(_), self.individuals()))
-
     def __hash__(self):
-        return hash(self._values)
-
+        return hash(("OWLObjectOneOf", self._values))
     def __eq__(self, other):
         if type(other) is type(self):
             return self._values == other._values
         else:
             return False
-
     def __repr__(self):
         return f'OWLObjectOneOf({self._values})'
 
@@ -485,25 +484,22 @@ def __init__(self, cardinality: int, property: OWLDataPropertyExpression, filler
         assert isinstance(filler, OWLDataRange), "filler must be an OWLDataRange"
         super().__init__(cardinality, filler)
         self._property = property
-
-    def get_property(self) -> OWLDataPropertyExpression:
-        # documented in parent
-        return self._property
-
+    def __hash__(self):
+        return hash(("OWLDataCardinalityRestriction",self._property, self._cardinality, self._filler))
     def __repr__(self):
         return f"{type(self).__name__}(" \
                f"property={repr(self.get_property())},{self.get_cardinality()},filler={repr(self.get_filler())})"
 
     def __eq__(self, other):
         if type(other) is type(self):
-            return self._property == other._property \
-                and self._cardinality == other._cardinality \
-                and self._filler == other._filler
-        return NotImplemented
-
-    def __hash__(self):
-        return hash((self._property, self._cardinality, self._filler))
+            return (self._property == other._property and self._cardinality == other._cardinality
+                    and self._filler == other._filler)
+        else:
+            return False
 
+    def get_property(self) -> OWLDataPropertyExpression:
+        # documented in parent
+        return self._property
 
 class OWLDataMinCardinality(OWLDataCardinalityRestriction):
     """A minimum cardinality expression DataMinCardinality( n DPE DR ) consists of a nonnegative integer n, a data
@@ -619,7 +615,7 @@ def __eq__(self, other):
         else:
             return False
     def __hash__(self):
-        return hash((self._filler, self._property))
+        return hash(("OWLDataSomeValuesFrom",self._filler, self._property))
 
     def get_property(self) -> OWLDataPropertyExpression:
         # documented in parent
@@ -661,9 +657,8 @@ def __eq__(self, other):
             return self._filler == other._filler and self._property == other._property
         else:
             return False
-
     def __hash__(self):
-        return hash((self._filler, self._property))
+        return hash(("OWLDataAllValuesFrom",self._filler, self._property))
 
     def get_property(self) -> OWLDataPropertyExpression:
         # documented in parent
@@ -703,10 +698,10 @@ def __repr__(self):
     def __eq__(self, other):
         if type(other) is type(self):
             return self._v == other._v and self._property == other._property
-        return NotImplemented
-
+        else:
+            return False
     def __hash__(self):
-        return hash((self._v, self._property))
+        return hash(("OWLDataHasValue",self._v, self._property))
 
     def as_some_values_from(self) -> OWLClassExpression:
         """A convenience method that obtains this restriction as an existential restriction with a nominal filler.
@@ -735,6 +730,17 @@ def __init__(self, values: Union[OWLLiteral, Iterable[OWLLiteral]]):
             for _ in values:
                 assert isinstance(_, OWLLiteral)
             self._values = tuple(values)
+    def __repr__(self):
+        return f'OWLDataOneOf({self._values})'
+
+    def __hash__(self):
+        return hash(("OWLDataOneOf",self._values))
+
+    def __eq__(self, other):
+        if type(other) is type(self):
+            return {i for i in self._values} == {j for j in other._values}
+        else:
+            return False
     # TODO:CD: define it as @property as the name of the class method does not correspond to an action
     def values(self) -> Iterable[OWLLiteral]:
         """Gets the values that are in the oneOf.
@@ -748,18 +754,6 @@ def operands(self) -> Iterable[OWLLiteral]:
         # documented in parent
         yield from self.values()
 
-    def __hash__(self):
-        return hash(self._values)
-
-    def __eq__(self, other):
-        if type(other) is type(self):
-            return {i for i in self._values} == {j for j in other._values}
-        else:
-            return False
-
-    def __repr__(self):
-        return f'OWLDataOneOf({self._values})'
-
 
 class OWLDatatypeRestriction(OWLDataRange):
     """A datatype restriction DatatypeRestriction( DT F1 lt1 ... Fn ltn ) consists of a unary datatype DT and n pairs
@@ -792,10 +786,10 @@ def __eq__(self, other):
         if type(other) is type(self):
             return self._type == other._type \
                 and self._facet_restrictions == other._facet_restrictions
-        return NotImplemented
-
+        else:
+            return False
     def __hash__(self):
-        return hash((self._type, self._facet_restrictions))
+        return hash(("OWLDatatypeRestriction", self._type, self._facet_restrictions))
 
     def __repr__(self):
         return f'OWLDatatypeRestriction({repr(self._type)}, {repr(self._facet_restrictions)})'
@@ -827,10 +821,11 @@ def get_facet_value(self) -> 'OWLLiteral':
     def __eq__(self, other):
         if type(other) is type(self):
             return self._facet == other._facet and self._literal == other._literal
-        return NotImplemented
+        else:
+            return False
 
     def __hash__(self):
-        return hash((self._facet, self._literal))
+        return hash(("OWLFacetRestriction",self._facet, self._literal))
 
     def __repr__(self):
         return f'OWLFacetRestriction({self._facet}, {repr(self._literal)})'
diff --git a/owlapy/iri.py b/owlapy/iri.py
index 66166bb4..af6a3238 100644
--- a/owlapy/iri.py
+++ b/owlapy/iri.py
@@ -45,6 +45,7 @@ def __init__(self, namespace: Union[str, Namespaces], remainder: str=""):
         else:
             assert namespace[-1] in ("/", ":", "#"), "It should be a valid IRI based on /, :, and #"
         import sys
+        # https://docs.python.org/3.2/library/sys.html?highlight=sys.intern#sys.intern
         self._namespace = sys.intern(namespace)
         self._remainder = remainder
 
@@ -94,7 +95,8 @@ def __repr__(self):
     def __eq__(self, other):
         if type(other) is type(self):
             return self._namespace is other._namespace and self._remainder == other._remainder
-        return NotImplemented
+        else:
+            raise RuntimeError(f"Invalid equality checking:{self} cannot be compared with {other}")
 
     def __hash__(self):
         return hash((self._namespace, self._remainder))
diff --git a/owlapy/owl_axiom.py b/owlapy/owl_axiom.py
index 6c10ea5d..3c0cfd96 100644
--- a/owlapy/owl_axiom.py
+++ b/owlapy/owl_axiom.py
@@ -523,6 +523,13 @@ def __init__(self, sub_class: OWLClassExpression, super_class: OWLClassExpressio
         self._super_class = super_class
         super().__init__(annotations=annotations)
 
+    @property
+    def sub_class(self) -> OWLClassExpression:
+        return self._sub_class
+    @property
+    def super_class(self) -> OWLClassExpression:
+        return self._super_class
+
     def get_sub_class(self) -> OWLClassExpression:
         return self._sub_class
 
@@ -533,7 +540,8 @@ def __eq__(self, other):
         if type(other) is type(self):
             return self._super_class == other._super_class and self._sub_class == other._sub_class \
                 and self._annotations == other._annotations
-        return NotImplemented
+        else:
+            return False
 
     def __hash__(self):
         return hash((self._super_class, self._sub_class, *self._annotations))
diff --git a/owlapy/owl_individual.py b/owlapy/owl_individual.py
index 3d98ff7b..2e0fd626 100644
--- a/owlapy/owl_individual.py
+++ b/owlapy/owl_individual.py
@@ -35,11 +35,12 @@ def __init__(self, iri: Union[IRI, str]):
             self._iri = iri
         else:
             self._iri = IRI.create(iri)
-
     @property
     def iri(self) -> IRI:
         return self._iri
-
     @property
     def str(self):
         return self._iri.as_str()
+    @property
+    def reminder(self):
+        return self._iri.reminder
\ No newline at end of file
diff --git a/owlapy/owl_object.py b/owlapy/owl_object.py
index 02894034..00032820 100644
--- a/owlapy/owl_object.py
+++ b/owlapy/owl_object.py
@@ -75,7 +75,9 @@ class OWLNamedObject(OWLObject, HasIRI, metaclass=ABCMeta):
     def __eq__(self, other):
         if type(other) is type(self):
             return self._iri == other._iri
-        return NotImplemented
+        else:
+            return False
+            # raise RuntimeError(f"Invalid equality checking:{self} cannot be compared with {other}")
 
     def __lt__(self, other):
         if type(other) is type(self):
diff --git a/owlapy/owl_ontology.py b/owlapy/owl_ontology.py
index d527383e..03a2d4af 100644
--- a/owlapy/owl_ontology.py
+++ b/owlapy/owl_ontology.py
@@ -126,7 +126,6 @@ def __eq__(self, other):
 
 def _check_expression(expr: OWLObject, ontology: AbstractOWLOntology, world: owlready2.namespace.World):
     """
-    @TODO:CD: Documentation
     Creates all entities (individuals, classes, properties) that appear in the given (complex) class expression
     and do not exist in the given ontology yet
 
@@ -1035,7 +1034,6 @@ def _get_imports_enum(self, include_imports_closure: bool):
         else:
             imports = Imports.EXCLUDED
         return imports
-
     def get_signature(self, include_imports_closure: bool = True):
         """Gets the entities that are in the signature of this ontology.
 
@@ -1045,6 +1043,7 @@ def get_signature(self, include_imports_closure: bool = True):
         Returns:
             Entities in signature.
         """
+        # @TODO: CD: Is this class method redundant given that we have the individuals_in_signature ?
         return self.mapper.map_(self.owlapi_ontology.getSignature(self._get_imports_enum(include_imports_closure)))
 
     def get_abox_axioms(self, include_imports_closure: bool = True) -> Iterable[OWLAxiom]:
@@ -1056,7 +1055,6 @@ def get_abox_axioms(self, include_imports_closure: bool = True) -> Iterable[OWLA
         Returns:
             ABox axioms.
         """
-
         return self.mapper.map_(self.owlapi_ontology.getABoxAxioms(self._get_imports_enum(include_imports_closure)))
 
     def get_tbox_axioms(self, include_imports_closure: bool = True) -> Iterable[OWLAxiom]:
@@ -1100,7 +1098,14 @@ def __hash__(self):
         return int(self.owlapi_ontology.getOntologyID().hashCode())
 
     def __repr__(self):
-        return f'SyncOntology({self.manager}, {self.path}, {self.new})'
+        return (f'SyncOntology:'
+                f'\t|Tbox|={len(self.get_tbox_axioms())}'
+                f'\t|Abox|={len(self.get_abox_axioms())}'
+                f'\t|Individuals|={len(self.individuals_in_signature())}'
+                f'\t|Classes|={len(self.classes_in_signature())}'
+                f'\t|Object Properties|={len(self.object_properties_in_signature())}'
+                f'\t|Data Properties|={len(self.data_properties_in_signature())}'
+                f'\n{self.manager}\tPath:{self.path}\tNew:{self.new}')
 
 
 OWLREADY2_FACET_KEYS = MappingProxyType({
diff --git a/owlapy/owl_ontology_manager.py b/owlapy/owl_ontology_manager.py
index 4d58d58a..2df6cdd7 100644
--- a/owlapy/owl_ontology_manager.py
+++ b/owlapy/owl_ontology_manager.py
@@ -103,8 +103,7 @@ def apply_change(self, change: AbstractOWLOntologyChange):
             ont_x.imported_ontologies.append(
                 self._world.get_ontology(change.get_import_declaration().str))
         else:
-            # TODO XXX
-            raise NotImplementedError
+            raise NotImplementedError("Change is not yet implemented.")
 
     def save_world(self):
         """Saves the actual state of the quadstore in the SQLite3 file.
@@ -139,4 +138,4 @@ def get_owlapi_manager(self):
         return self.owlapi_manager
 
     def apply_change(self, change: AbstractOWLOntologyChange):
-        raise NotImplementedError()
+        raise NotImplementedError("A change cannot be applied at the moment.")
diff --git a/owlapy/owl_property.py b/owlapy/owl_property.py
index cef05361..4f3ee257 100644
--- a/owlapy/owl_property.py
+++ b/owlapy/owl_property.py
@@ -113,6 +113,10 @@ class OWLObjectProperty(OWLObjectPropertyExpression, OWLProperty):
 
     _iri: IRI
 
+    @property
+    def reminder(self):
+        return self._iri.reminder
+
     def get_named_property(self) -> 'OWLObjectProperty':
         # documented in parent
         return self
diff --git a/owlapy/owl_reasoner.py b/owlapy/owl_reasoner.py
index 211460d9..5069338f 100644
--- a/owlapy/owl_reasoner.py
+++ b/owlapy/owl_reasoner.py
@@ -27,7 +27,7 @@
     OWLPropertyExpression, OWLDataPropertyExpression
 from owlapy.owl_individual import OWLNamedIndividual
 from owlapy.owl_literal import OWLLiteral
-from owlapy.utils import LRUCache, run_with_timeout
+from owlapy.utils import run_with_timeout
 from owlapy.abstracts.abstract_owl_reasoner import AbstractOWLReasoner
 logger = logging.getLogger(__name__)
 
@@ -36,37 +36,6 @@
 
 class StructuralReasoner(AbstractOWLReasoner):
     """Tries to check instances fast (but maybe incomplete)."""
-    __slots__ = '_ontology', '_world', \
-                '_ind_set', '_cls_to_ind', \
-                '_has_prop', 'class_cache', \
-                '_objectsomevalues_cache', '_datasomevalues_cache', '_objectcardinality_cache', \
-                '_property_cache', \
-                '_obj_prop', '_obj_prop_inv', '_data_prop', \
-                '_negation_default', '_sub_properties', \
-                '__warned'
-
-    _ontology: Ontology
-    _world: owlready2.World
-    _cls_to_ind: Dict[OWLClass, FrozenSet[OWLNamedIndividual]]  # Class => individuals
-    _has_prop: Mapping[Type[_P], LRUCache[_P, FrozenSet[OWLNamedIndividual]]]  # Type => Property => individuals
-    _ind_set: FrozenSet[OWLNamedIndividual]
-    # ObjectSomeValuesFrom => individuals
-    _objectsomevalues_cache: LRUCache[OWLClassExpression, FrozenSet[OWLNamedIndividual]]
-    # DataSomeValuesFrom => individuals
-    _datasomevalues_cache: LRUCache[OWLClassExpression, FrozenSet[OWLNamedIndividual]]
-    # ObjectCardinalityRestriction => individuals
-    _objectcardinality_cache: LRUCache[OWLClassExpression, FrozenSet[OWLNamedIndividual]]
-    # ObjectProperty => { individual => individuals }
-    _obj_prop: Dict[OWLObjectProperty, Mapping[OWLNamedIndividual, Set[OWLNamedIndividual]]]
-    # ObjectProperty => { individual => individuals }
-    _obj_prop_inv: Dict[OWLObjectProperty, Mapping[OWLNamedIndividual, Set[OWLNamedIndividual]]]
-    # DataProperty => { individual => literals }
-    _data_prop: Dict[OWLDataProperty, Mapping[OWLNamedIndividual, Set[OWLLiteral]]]
-    class_cache: bool
-    _property_cache: bool
-    _negation_default: bool
-    _sub_properties: bool
-
     def __init__(self, ontology: AbstractOWLOntology, *, class_cache: bool = True,
                  property_cache: bool = True, negation_default: bool = True, sub_properties: bool = False):
         """Fast instance checker.
@@ -80,36 +49,34 @@ def __init__(self, ontology: AbstractOWLOntology, *, class_cache: bool = True,
             """
         super().__init__(ontology)
         assert isinstance(ontology, Ontology)
-        self._world = ontology._world
-        self._ontology = ontology
-        self.class_cache = class_cache
-        self._property_cache = property_cache
-        self._negation_default = negation_default
-        self._sub_properties = sub_properties
-        self.__warned = 0
+        self._world: owlready2.World = ontology._world
+        self._ontology: Ontology = ontology
+        self.class_cache: bool = class_cache
+        self._property_cache: bool = property_cache
+        self._negation_default: bool = negation_default
+        self._sub_properties: bool = sub_properties
+        self.__warned: int = 0
         self._init()
 
-    def _init(self, cache_size=128):
-
-        individuals = self._ontology.individuals_in_signature()
-        self._ind_set = frozenset(individuals)
-        self._objectsomevalues_cache = LRUCache(maxsize=cache_size)
-        self._datasomevalues_cache = LRUCache(maxsize=cache_size)
-        self._objectcardinality_cache = LRUCache(maxsize=cache_size)
+    def _init(self):
         if self.class_cache:
-            self._cls_to_ind = dict()
+            # Class => individuals
+            self._cls_to_ind: Dict[OWLClass, FrozenSet[OWLNamedIndividual]] = {} 
 
         if self._property_cache:
-            self._obj_prop = dict()
-            self._obj_prop_inv = dict()
-            self._data_prop = dict()
+            # ObjectProperty => { individual => individuals }
+            self._obj_prop: Dict[OWLObjectProperty, Mapping[OWLNamedIndividual, Set[OWLNamedIndividual]]] = dict()
+             # ObjectProperty => { individual => individuals }
+            self._obj_prop_inv: Dict[OWLObjectProperty, Mapping[OWLNamedIndividual, Set[OWLNamedIndividual]]] = dict()
+            # DataProperty => { individual => literals }
+            self._data_prop: Dict[OWLDataProperty, Mapping[OWLNamedIndividual, Set[OWLLiteral]]] = dict() 
         else:
-            self._has_prop = MappingProxyType({
-                OWLDataProperty: LRUCache(maxsize=cache_size),
-                OWLObjectProperty: LRUCache(maxsize=cache_size),
-                OWLObjectInverseOf: LRUCache(maxsize=cache_size),
-            })
-
+            self._has_prop: Mapping[Type[_P], Dict[_P, FrozenSet[OWLNamedIndividual]]] = {
+                OWLDataProperty: {},
+                OWLObjectProperty: {},
+                OWLObjectInverseOf: {},
+            }
+           
     def reset(self):
         """The reset method shall reset any cached state."""
         self._init()
@@ -636,7 +603,8 @@ def _lazy_cache_obj_prop(self, pe: OWLObjectPropertyExpression) -> None:
                         opc[s] = set()
                     opc[s] |= {o}
         else:
-            for s in self._ind_set:
+            all_ = frozenset(self._ontology.individuals_in_signature())
+            for s in all_:
                 individuals = set(self.object_property_values(s, pe, not self._sub_properties))
                 if individuals:
                     opc[s] = individuals
@@ -676,8 +644,8 @@ def _some_values_subject_index(self, pe: OWLPropertyExpression) -> FrozenSet[OWL
                     func = self.data_property_values
                 else:
                     func = self.object_property_values
-
-                for s in self._ind_set:
+                all_ = frozenset(self._ontology.individuals_in_signature())
+                for s in all_:
                     try:
                         next(iter(func(s, pe, not self._sub_properties)))
                         subs |= {s}
@@ -782,9 +750,6 @@ def _(self, ce: OWLObjectIntersectionOf) -> FrozenSet[OWLNamedIndividual]:
 
     @_find_instances.register
     def _(self, ce: OWLObjectSomeValuesFrom) -> FrozenSet[OWLNamedIndividual]:
-        if ce in self._objectsomevalues_cache:
-            return self._objectsomevalues_cache[ce]
-
         p = ce.get_property()
         assert isinstance(p, OWLObjectPropertyExpression)
         if not self._property_cache and ce.get_filler().is_owl_thing():
@@ -794,13 +759,12 @@ def _(self, ce: OWLObjectSomeValuesFrom) -> FrozenSet[OWLNamedIndividual]:
 
         ind = self._find_some_values(p, filler_ind)
 
-        self._objectsomevalues_cache[ce] = ind
         return ind
 
     @_find_instances.register
     def _(self, ce: OWLObjectComplementOf) -> FrozenSet[OWLNamedIndividual]:
         if self._negation_default:
-            all_ = self._ind_set
+            all_ = frozenset(self._ontology.individuals_in_signature())
             complement_ind = self._find_instances(ce.get_operand())
             return all_ ^ complement_ind
         else:
@@ -836,7 +800,7 @@ def _(self, ce: OWLObjectMinCardinality) -> FrozenSet[OWLNamedIndividual]:
 
     @_find_instances.register
     def _(self, ce: OWLObjectMaxCardinality) -> FrozenSet[OWLNamedIndividual]:
-        all_ = self._ind_set
+        all_ = frozenset(self._ontology.individuals_in_signature())
         min_ind = self._find_instances(OWLObjectMinCardinality(cardinality=ce.get_cardinality() + 1,
                                                                property=ce.get_property(),
                                                                filler=ce.get_filler()))
@@ -847,9 +811,6 @@ def _(self, ce: OWLObjectExactCardinality) -> FrozenSet[OWLNamedIndividual]:
         return self._get_instances_object_card_restriction(ce)
 
     def _get_instances_object_card_restriction(self, ce: OWLObjectCardinalityRestriction):
-        if ce in self._objectcardinality_cache:
-            return self._objectcardinality_cache[ce]
-
         p = ce.get_property()
         assert isinstance(p, OWLObjectPropertyExpression)
 
@@ -871,14 +832,10 @@ def _get_instances_object_card_restriction(self, ce: OWLObjectCardinalityRestric
 
         ind = self._find_some_values(p, filler_ind, min_count=min_count, max_count=max_count)
 
-        self._objectcardinality_cache[ce] = ind
         return ind
 
     @_find_instances.register
     def _(self, ce: OWLDataSomeValuesFrom) -> FrozenSet[OWLNamedIndividual]:
-        if ce in self._datasomevalues_cache:
-            return self._datasomevalues_cache[ce]
-
         pe = ce.get_property()
         filler = ce.get_filler()
         assert isinstance(pe, OWLDataProperty)
@@ -967,7 +924,6 @@ def include(lv: OWLLiteral):
             raise ValueError
 
         r = frozenset(ind)
-        self._datasomevalues_cache[ce] = r
         return r
 
     @_find_instances.register
@@ -1057,53 +1013,9 @@ def __init__(self, ontology: Union[SyncOntology, str], reasoner="HermiT"):
 
         self._owlapi_manager = self.manager.get_owlapi_manager()
         self._owlapi_ontology = self.ontology.get_owlapi_ontology()
-        # super().__init__(self.ontology)
         self.mapper = self.ontology.mapper
-        from org.semanticweb.owlapi.util import (InferredClassAssertionAxiomGenerator, InferredSubClassAxiomGenerator,
-                                                 InferredEquivalentClassAxiomGenerator,
-                                                 InferredDisjointClassesAxiomGenerator,
-                                                 InferredEquivalentDataPropertiesAxiomGenerator,
-                                                 InferredEquivalentObjectPropertyAxiomGenerator,
-                                                 InferredInverseObjectPropertiesAxiomGenerator,
-                                                 InferredSubDataPropertyAxiomGenerator,
-                                                 InferredSubObjectPropertyAxiomGenerator,
-                                                 InferredDataPropertyCharacteristicAxiomGenerator,
-                                                 InferredObjectPropertyCharacteristicAxiomGenerator)
-
-        self.inference_types_mapping = {"InferredClassAssertionAxiomGenerator": InferredClassAssertionAxiomGenerator(),
-                                        "InferredSubClassAxiomGenerator": InferredSubClassAxiomGenerator(),
-                                        "InferredDisjointClassesAxiomGenerator": InferredDisjointClassesAxiomGenerator(),
-                                        "InferredEquivalentClassAxiomGenerator": InferredEquivalentClassAxiomGenerator(),
-                                        "InferredInverseObjectPropertiesAxiomGenerator": InferredInverseObjectPropertiesAxiomGenerator(),
-                                        "InferredEquivalentDataPropertiesAxiomGenerator": InferredEquivalentDataPropertiesAxiomGenerator(),
-                                        "InferredEquivalentObjectPropertyAxiomGenerator": InferredEquivalentObjectPropertyAxiomGenerator(),
-                                        "InferredSubDataPropertyAxiomGenerator": InferredSubDataPropertyAxiomGenerator(),
-                                        "InferredSubObjectPropertyAxiomGenerator": InferredSubObjectPropertyAxiomGenerator(),
-                                        "InferredDataPropertyCharacteristicAxiomGenerator": InferredDataPropertyCharacteristicAxiomGenerator(),
-                                        "InferredObjectPropertyCharacteristicAxiomGenerator": InferredObjectPropertyCharacteristicAxiomGenerator(),
-                                        }
-
-        # () Create a reasoner using the ontology
-        if reasoner == "HermiT":
-            from org.semanticweb.HermiT import ReasonerFactory
-            self._owlapi_reasoner = ReasonerFactory().createReasoner(self._owlapi_ontology)
-            assert self._owlapi_reasoner.getReasonerName() == "HermiT"
-        elif reasoner == "JFact":
-            from uk.ac.manchester.cs.jfact import JFactFactory
-            self._owlapi_reasoner = JFactFactory().createReasoner(self._owlapi_ontology)
-        elif reasoner == "Pellet":
-            from openllet.owlapi import PelletReasonerFactory
-            self._owlapi_reasoner = PelletReasonerFactory().createReasoner(self._owlapi_ontology)
-        elif reasoner == "Openllet":
-            from openllet.owlapi import OpenlletReasonerFactory
-            self._owlapi_reasoner = OpenlletReasonerFactory().getInstance().createReasoner(self._owlapi_ontology)
-        elif reasoner == "Structural":
-            from org.semanticweb.owlapi.reasoner.structural import StructuralReasonerFactory
-            self._owlapi_reasoner = StructuralReasonerFactory().createReasoner(self._owlapi_ontology)
-        else:
-            raise NotImplementedError("Not implemented")
-
-        self.reasoner = reasoner
+        self.inference_types_mapping = import_and_include_axioms_generators()
+        self._owlapi_reasoner = initialize_reasoner(reasoner,self._owlapi_ontology)
 
     def _instances(self, ce: OWLClassExpression, direct=False) -> Set[OWLNamedIndividual]:
         """
@@ -1422,11 +1334,11 @@ def disjoint_data_properties(self, p: OWLDataProperty):
         yield from [self.mapper.map_(pe) for pe in
                     self._owlapi_reasoner.getDisjointDataProperties(self.mapper.map_(p)).getFlattened()]
 
-    def types(self, i: OWLNamedIndividual, direct: bool = False):
+    def types(self, individual: OWLNamedIndividual, direct: bool = False):
         """Gets the named classes which are (potentially direct) types of the specified named individual.
 
         Args:
-            i: The individual whose types are to be retrieved.
+            individual: The individual whose types are to be retrieved.
             direct: Specifies if the direct types should be retrieved (True), or if all types should be retrieved
                 (False).
 
@@ -1436,7 +1348,7 @@ def types(self, i: OWLNamedIndividual, direct: bool = False):
             entails ClassAssertion(C, ind).
         """
         yield from [self.mapper.map_(ind) for ind in
-                    self._owlapi_reasoner.getTypes(self.mapper.map_(i), direct).getFlattened()]
+                    self._owlapi_reasoner.getTypes(self.mapper.map_(individual), direct).getFlattened()]
 
     def has_consistent_ontology(self) -> bool:
         """
@@ -1588,3 +1500,48 @@ def unsatisfiable_classes(self):
 
     def get_root_ontology(self) -> AbstractOWLOntology:
         return self.ontology
+
+def initialize_reasoner(reasoner:str, owlapi_ontology):
+    # () Create a reasoner using the ontology
+    if reasoner == "HermiT":
+        from org.semanticweb.HermiT import ReasonerFactory
+        owlapi_reasoner = ReasonerFactory().createReasoner(owlapi_ontology)
+        assert owlapi_reasoner.getReasonerName() == "HermiT"
+    elif reasoner == "JFact":
+        from uk.ac.manchester.cs.jfact import JFactFactory
+        owlapi_reasoner = JFactFactory().createReasoner(owlapi_ontology)
+    elif reasoner == "Pellet":
+        from openllet.owlapi import PelletReasonerFactory
+        owlapi_reasoner = PelletReasonerFactory().createReasoner(owlapi_ontology)
+    elif reasoner == "Openllet":
+        from openllet.owlapi import OpenlletReasonerFactory
+        owlapi_reasoner = OpenlletReasonerFactory().getInstance().createReasoner(owlapi_ontology)
+    elif reasoner == "Structural":
+        from org.semanticweb.owlapi.reasoner.structural import StructuralReasonerFactory
+        owlapi_reasoner = StructuralReasonerFactory().createReasoner(owlapi_ontology)
+    else:
+        raise NotImplementedError("Not implemented")
+    return owlapi_reasoner
+def import_and_include_axioms_generators():
+    from org.semanticweb.owlapi.util import (InferredClassAssertionAxiomGenerator, InferredSubClassAxiomGenerator,
+                                             InferredEquivalentClassAxiomGenerator,
+                                             InferredDisjointClassesAxiomGenerator,
+                                             InferredEquivalentDataPropertiesAxiomGenerator,
+                                             InferredEquivalentObjectPropertyAxiomGenerator,
+                                             InferredInverseObjectPropertiesAxiomGenerator,
+                                             InferredSubDataPropertyAxiomGenerator,
+                                             InferredSubObjectPropertyAxiomGenerator,
+                                             InferredDataPropertyCharacteristicAxiomGenerator,
+                                             InferredObjectPropertyCharacteristicAxiomGenerator)
+
+    return {"InferredClassAssertionAxiomGenerator": InferredClassAssertionAxiomGenerator(),
+                                    "InferredSubClassAxiomGenerator": InferredSubClassAxiomGenerator(),
+                                    "InferredDisjointClassesAxiomGenerator": InferredDisjointClassesAxiomGenerator(),
+                                    "InferredEquivalentClassAxiomGenerator": InferredEquivalentClassAxiomGenerator(),
+                                    "InferredInverseObjectPropertiesAxiomGenerator": InferredInverseObjectPropertiesAxiomGenerator(),
+                                    "InferredEquivalentDataPropertiesAxiomGenerator": InferredEquivalentDataPropertiesAxiomGenerator(),
+                                    "InferredEquivalentObjectPropertyAxiomGenerator": InferredEquivalentObjectPropertyAxiomGenerator(),
+                                    "InferredSubDataPropertyAxiomGenerator": InferredSubDataPropertyAxiomGenerator(),
+                                    "InferredSubObjectPropertyAxiomGenerator": InferredSubObjectPropertyAxiomGenerator(),
+                                    "InferredDataPropertyCharacteristicAxiomGenerator": InferredDataPropertyCharacteristicAxiomGenerator(),
+                                    "InferredObjectPropertyCharacteristicAxiomGenerator": InferredObjectPropertyCharacteristicAxiomGenerator()}
diff --git a/owlapy/util_owl_static_funcs.py b/owlapy/util_owl_static_funcs.py
new file mode 100644
index 00000000..20ee01e5
--- /dev/null
+++ b/owlapy/util_owl_static_funcs.py
@@ -0,0 +1,57 @@
+from .owl_ontology import Ontology
+from .owl_ontology_manager import OntologyManager
+from typing import List
+from .class_expression import OWLClassExpression, OWLClass
+from .iri import IRI
+from .owl_axiom import OWLEquivalentClassesAxiom
+
+def save_owl_class_expressions(expressions: OWLClassExpression | List[OWLClassExpression],
+                               path: str = 'predictions',
+                               rdf_format: str = 'rdfxml',
+                               namespace:str=None) -> None:
+    """
+    Saves a set of OWL class expressions to an ontology file in RDF/XML format.
+
+    This function takes one or more OWL class expressions, creates an ontology,
+    and saves the expressions as OWL equivalent class axioms in the specified RDF format.
+    By default, it saves the file to the specified path using the 'rdfxml' format.
+
+    Args:
+        expressions (OWLClassExpression | List[OWLClassExpression]): A single or a list of OWL class expressions
+            to be saved as equivalent class axioms.
+        path (str, optional): The file path where the ontology will be saved. Defaults to 'predictions'.
+        rdf_format (str, optional): RDF serialization format for saving the ontology. Currently only
+            supports 'rdfxml'. Defaults to 'rdfxml'.
+        namespace (str, optional): The namespace URI used for the ontology. If None, defaults to
+            'https://dice-research.org/predictions#'. Must end with '#'.
+
+    Raises:
+        AssertionError: If `expressions` is neither an OWLClassExpression nor a list of OWLClassExpression.
+        AssertionError: If `rdf_format` is not 'rdfxml'.
+        AssertionError: If `namespace` does not end with a '#'.
+
+    Example:
+        >>> from some_module import OWLClassExpression
+        >>> expr1 = OWLClassExpression("SomeExpression1")
+        >>> expr2 = OWLClassExpression("SomeExpression2")
+        >>> save_owl_class_expressions([expr1, expr2], path="my_ontology.owl", rdf_format="rdfxml")
+    """
+    assert isinstance(expressions, OWLClassExpression) or isinstance(expressions[0],
+                                                                     OWLClassExpression), "expressions must be either OWLClassExpression or a list of OWLClassExpression"
+    assert rdf_format == 'rdfxml', f'Format {rdf_format} not implemented. Please use rdfxml'
+
+    if isinstance(expressions, OWLClassExpression):
+        expressions = [expressions]
+
+    namespace= 'https://dice-research.org/predictions#' if namespace is None else namespace
+    assert "#" == namespace[-1], "namespace must end with #"
+    # ()
+    manager = OntologyManager()
+    # ()
+    ontology:Ontology = manager.create_ontology(namespace)
+    # () Iterate over concepts
+    for th, i in enumerate(expressions):
+        cls_a = OWLClass(IRI.create(namespace, str(th)))
+        equivalent_classes_axiom = OWLEquivalentClassesAxiom([cls_a, i])
+        ontology.add_axiom(equivalent_classes_axiom)
+    ontology.save(path=path, inplace=False, rdf_format=rdf_format)
\ No newline at end of file
diff --git a/setup.py b/setup.py
index bf8d39f5..e3e8e579 100644
--- a/setup.py
+++ b/setup.py
@@ -5,7 +5,7 @@
 setup(
     name="owlapy",
     description="OWLAPY is a Python Framework for creating and manipulating OWL Ontologies.",
-    version="1.3.2",
+    version="1.3.3",
     packages=find_packages(),
     include_package_data=True,
     package_data={'owlapy': ['jar_dependencies/*.jar'],},
@@ -13,6 +13,7 @@
         "pandas>=1.5.0",
         "requests>=2.32.3",
         "rdflib>=6.0.2",
+        "ruff>=0.7.2",
         "parsimonious>=0.8.1",
         "pytest>=8.1.1",
         "sortedcontainers>=2.4.0",


Test patch:
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 6bee0285..a0e107e9 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -18,7 +18,9 @@ jobs:
         run: |
           python -m pip install --upgrade pip
           pip install -e .
-
+      - name: Lint with ruff
+        run: |
+          ruff check owlapy --line-length=200
       - name: Test with pytest
         run: |
           wget https://files.dice-research.org/projects/Ontolearn/KGs.zip
diff --git a/tests/test_hashing.py b/tests/test_hashing.py
new file mode 100644
index 00000000..f30dfc72
--- /dev/null
+++ b/tests/test_hashing.py
@@ -0,0 +1,52 @@
+from owlapy.owl_property import OWLObjectProperty
+from owlapy.class_expression import OWLObjectSomeValuesFrom, OWLObjectAllValuesFrom
+from owlapy.converter import owl_expression_to_sparql
+from owlapy.render import owl_expression_to_dl
+from owlapy.iri import IRI
+from owlapy.class_expression import OWLClass, OWLObjectUnionOf, OWLObjectIntersectionOf
+
+class TestHashing:
+
+    def test_el_description_logic_hash(self):
+        """
+        EL allows complex concepts of the following form:
+        C := \top | A | C1 u C2 | \existr.C
+        where A is a concept and r a role name.
+        For more, refer to https://www.emse.fr/~zimmermann/Teaching/KRR/el.html
+        """
+        memory = dict()
+        # An OWL Class can be used as a key in a dictionary.
+        memory[OWLClass("http://example.com/father#A")] = OWLClass("http://example.com/father#A")
+        memory[OWLClass("http://example.com/father#B")] = OWLClass("http://example.com/father#B")
+        memory[OWLClass("http://example.com/father#C")] = OWLClass("http://example.com/father#C")
+
+        unions = set()
+        intersections = set()
+        for k, v in memory.items():
+            assert k == v
+            # An OWLObjectUnionOf over two OWL Classes can be added into a set.
+            unions.add(OWLObjectUnionOf((k, v)))
+            # Since the order doesn't matter in an OWLObjectUnionOf the following also holds
+            assert OWLObjectUnionOf((v, k)) in unions
+
+            # This also works for intersections.
+            intersections.add(OWLObjectIntersectionOf((k, v)))
+            # Since the order doesn't matter in an OWLObjectUnionOf the following also holds
+            assert OWLObjectIntersectionOf((v, k)) in intersections
+        # OWLObjectUnionOf and OWLObjectIntersectionOf can also be used as keys
+        for i in unions | intersections:
+            memory[i]=i
+        for k, v in memory.items():
+            assert k == v
+
+        atomic_concepts={OWLClass("http://example.com/father#A"),OWLClass("http://example.com/father#B")}
+        properties={OWLObjectProperty("http://example.com/society#hasChild")}
+        memory = dict()
+        for ac in atomic_concepts:
+            for op in properties:
+                # OWLObjectSomeValuesFrom can be used as a key.
+                memory[OWLObjectSomeValuesFrom(property=op, filler=ac)] = OWLObjectSomeValuesFrom(property=op, filler=ac)
+                memory[OWLObjectAllValuesFrom(property=op, filler=ac)] = OWLObjectAllValuesFrom(property=op, filler=ac)
+
+        for k, v in memory.items():
+            assert k == v
\ No newline at end of file
diff --git a/tests/test_save_owl_expressions.py b/tests/test_save_owl_expressions.py
new file mode 100644
index 00000000..3beda87b
--- /dev/null
+++ b/tests/test_save_owl_expressions.py
@@ -0,0 +1,25 @@
+from owlapy.util_owl_static_funcs import save_owl_class_expressions
+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
+from owlapy.owl_ontology_manager import OntologyManager
+from owlapy.owl_axiom import OWLDeclarationAxiom, OWLClassAssertionAxiom
+from owlapy.owl_individual import OWLNamedIndividual, IRI
+import rdflib
+
+class TestRunningExamples:
+    def test_readme(self):
+        # Using owl classes to create a complex class expression
+        male = OWLClass("http://example.com/society#male")
+        hasChild = OWLObjectProperty("http://example.com/society#hasChild")
+        hasChild_male = OWLObjectSomeValuesFrom(hasChild, male)
+        teacher = OWLClass("http://example.com/society#teacher")
+        teacher_that_hasChild_male = OWLObjectIntersectionOf([hasChild_male, teacher])
+
+        expressions= [male, teacher_that_hasChild_male]
+        save_owl_class_expressions(expressions=expressions,
+                                   namespace="https://ontolearn.org/predictions#",
+                                   path="owl_class_expressions.owl",
+                                   rdf_format= 'rdfxml')
+        g=rdflib.Graph().parse("owl_class_expressions.owl")
+        assert len(g)==22
\ No newline at end of file
diff --git a/tests/test_sync_ontology.py b/tests/test_sync_ontology.py
index c35d7462..f02c198e 100644
--- a/tests/test_sync_ontology.py
+++ b/tests/test_sync_ontology.py
@@ -80,6 +80,13 @@ class TestSyncReasoner(unittest.TestCase):
     manager = SyncOntologyManager()
     onto = manager.load_ontology(ontology_path)
 
+    def test_interface_father_dataset(self):
+        ontology_path = "KGs/Family/father.owl"
+        onto = SyncOntologyManager().load_ontology(ontology_path)
+        assert {owl_class.reminder for owl_class in onto.classes_in_signature()}=={'male', 'female', 'Thing', 'person'}
+        assert {individual.reminder for individual in onto.individuals_in_signature()}=={'markus', 'anna', 'martin', 'stefan', 'heinz', 'michelle'}
+        assert {object_property.reminder for object_property in onto.object_properties_in_signature()}=={'hasChild'}
+
     # NOTE AB: The name of "assertCountEqual" may be misleading,but it's essentially an order-insensitive "assertEqual".
 
     def test_classes_in_signature(self):
diff --git a/tests/test_sync_reasoner.py b/tests/test_sync_reasoner.py
index f45cb8a8..9b157457 100644
--- a/tests/test_sync_reasoner.py
+++ b/tests/test_sync_reasoner.py
@@ -3,7 +3,7 @@
 
 from jpype import JDouble
 from owlapy.class_expression import OWLClass, OWLDataSomeValuesFrom, OWLObjectIntersectionOf, OWLNothing, OWLThing, \
-    OWLClassExpression, OWLObjectSomeValuesFrom
+    OWLClassExpression, OWLObjectSomeValuesFrom, OWLObjectOneOf
 from owlapy.iri import IRI
 from owlapy.owl_axiom import OWLDisjointClassesAxiom, OWLDeclarationAxiom, OWLClassAssertionAxiom, OWLSubClassOfAxiom, \
     OWLEquivalentClassesAxiom, OWLSubDataPropertyOfAxiom, OWLSubObjectPropertyOfAxiom
@@ -15,6 +15,7 @@
 from owlapy.owl_reasoner import SyncReasoner
 from owlapy.providers import owl_datatype_min_inclusive_restriction
 
+
 NS = 'http://www.semanticweb.org/stefan/ontologies/2023/1/untitled-ontology-11#'
 
 a = OWLNamedIndividual(IRI(NS, "a"))
@@ -82,6 +83,26 @@ class TestSyncReasoner(unittest.TestCase):
     ce = OWLObjectIntersectionOf([nitrogen38, has_charge_more_than_0_85])
     reasoner = SyncReasoner(ontology_path)
 
+    def test_father_dataset(self):
+        ontology_path = "KGs/Family/father.owl"
+        # Available OWL Reasoners: 'HermiT', 'Pellet', 'JFact', 'Openllet'
+        owl_reasoners = dict()
+        owl_reasoners["HermiT"] = SyncReasoner(ontology=ontology_path, reasoner="HermiT")
+        owl_reasoners["Pellet"] = SyncReasoner(ontology=ontology_path, reasoner="Pellet")
+        owl_reasoners["JFact"] = SyncReasoner(ontology=ontology_path, reasoner="JFact")
+        owl_reasoners["Openllet"] = SyncReasoner(ontology=ontology_path, reasoner="Openllet")
+
+        for k, reasoner in owl_reasoners.items():
+            exist_haschild_female = OWLObjectSomeValuesFrom(
+                property=OWLObjectProperty('http://example.com/father#hasChild'),
+                filler=OWLClass('http://example.com/father#female'))
+
+            exist_haschild_anna = OWLObjectSomeValuesFrom(property=OWLObjectProperty('http://example.com/father#hasChild'),
+                                                          filler=OWLObjectOneOf(
+                                                              OWLNamedIndividual('http://example.com/father#anna')))
+            assert reasoner.instances(ce=exist_haschild_female) == reasoner.instances(ce=exist_haschild_anna) == {
+                OWLNamedIndividual('http://example.com/father#markus')}
+
     def test_consistency_check(self):
         self.assertEqual(self.reasoner.has_consistent_ontology(), True)