Skip to content

Commit

Permalink
Merge pull request #73 from dice-group/issues-solving
Browse files Browse the repository at this point in the history
fixing issue with OWLNothing + new parameter for `OWLReasoner.instances`
  • Loading branch information
Demirrr authored Sep 20, 2024
2 parents 499caf8 + bdbe811 commit 4251f78
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 11 deletions.
3 changes: 2 additions & 1 deletion owlapy/abstracts/abstract_owl_reasoner.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,13 +201,14 @@ def object_property_values(self, ind: OWLNamedIndividual, pe: OWLObjectPropertyE
pass

@abstractmethod
def instances(self, ce: OWLClassExpression, direct: bool = False) -> Iterable[OWLNamedIndividual]:
def instances(self, ce: OWLClassExpression, direct: bool = False, timeout: int = 1000) -> Iterable[OWLNamedIndividual]:
"""Gets the individuals which are instances of the specified class expression.
Args:
ce: The class expression whose instances are to be retrieved.
direct: Specifies if the direct instances should be retrieved (True), or if all instances should be
retrieved (False).
timeout: Time limit in seconds until results must be returned, else empty set is returned.
Returns:
If direct is True, each named individual j where the set of reasoner axioms entails
Expand Down
34 changes: 28 additions & 6 deletions owlapy/owl_reasoner.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
"""OWL Reasoner"""
import operator
import logging
import threading

import owlready2

from collections import defaultdict
Expand Down Expand Up @@ -35,6 +37,18 @@
_P = TypeVar('_P', bound=OWLPropertyExpression)


def run_with_timeout(func, timeout, args=(), kwargs={}):
result = [None]
thread = threading.Thread(target=lambda: result.append(func(*args, **kwargs)))
thread.start()
thread.join(timeout)
if thread.is_alive():
print(f"{func.__self__.__class__.__name__}.instances timed out! Timeout limit is currently set to {timeout} "
f"seconds\nReturning empty results...")
return []
return result[-1]


class OntologyReasoner(AbstractOWLReasonerEx):
__slots__ = '_ontology', '_world'
# TODO: CD: We will remove owlready2 from owlapy
Expand Down Expand Up @@ -198,7 +212,7 @@ def object_property_values(self, ind: OWLNamedIndividual, pe: OWLObjectPropertyE
else:
raise NotImplementedError(pe)

def instances(self, ce: OWLClassExpression, direct: bool = False) -> Iterable[OWLNamedIndividual]:
def _instances(self, ce: OWLClassExpression, direct: bool = False) -> Iterable[OWLNamedIndividual]:
if direct:
if isinstance(ce, OWLClass):
c_x: owlready2.ThingClass = self._world[ce.str]
Expand Down Expand Up @@ -226,6 +240,9 @@ def instances(self, ce: OWLClassExpression, direct: bool = False) -> Iterable[OW
else:
raise NotImplementedError("instances for complex class expressions not implemented", ce)

def instances(self, ce: OWLClassExpression, direct: bool = False, timeout: int = 1000):
return run_with_timeout(self._instances, timeout, (ce, direct))

def _sub_classes_recursive(self, ce: OWLClassExpression, seen_set: Set, only_named: bool = True) \
-> Iterable[OWLClassExpression]:

Expand Down Expand Up @@ -690,14 +707,17 @@ def object_property_values(self, ind: OWLNamedIndividual, pe: OWLObjectPropertyE
-> Iterable[OWLNamedIndividual]:
yield from self._base_reasoner.object_property_values(ind, pe, direct)

def instances(self, ce: OWLClassExpression, direct: bool = False) -> Iterable[OWLNamedIndividual]:
def _instances(self, ce: OWLClassExpression, direct: bool = False) -> Iterable[OWLNamedIndividual]:
if direct:
if not self.__warned & 2:
logger.warning("direct not implemented")
self.__warned |= 2
temp = self._find_instances(ce)
yield from temp

def instances(self, ce: OWLClassExpression, direct: bool = False, timeout: int = 1000):
return run_with_timeout(self._instances, timeout, (ce, direct))

def sub_classes(self, ce: OWLClassExpression, direct: bool = False, only_named: bool = True) \
-> Iterable[OWLClassExpression]:
yield from self._base_reasoner.sub_classes(ce, direct=direct, only_named=only_named)
Expand Down Expand Up @@ -1216,10 +1236,9 @@ def __init__(self, ontology: Union[SyncOntology, str], reasoner="HermiT"):
else:
raise NotImplementedError("Not implemented")

self.reasoner = reasoner

self.reasoner=reasoner

def instances(self, ce: OWLClassExpression, direct=False) -> Set[OWLNamedIndividual]:
def _instances(self, ce: OWLClassExpression, direct=False) -> Set[OWLNamedIndividual]:
"""
Get the instances for a given class expression using HermiT.
Expand All @@ -1230,12 +1249,15 @@ def instances(self, ce: OWLClassExpression, direct=False) -> Set[OWLNamedIndivid
Returns:
set: A set of individuals classified by the given class expression.
"""
mapped_ce=self.mapper.map_(ce)
mapped_ce = self.mapper.map_(ce)
instances = self._owlapi_reasoner.getInstances(mapped_ce, direct)
flattended_instances = instances.getFlattened()
assert str(type(flattended_instances)) == "<java class 'java.util.LinkedHashSet'>"
return {self.mapper.map_(ind) for ind in flattended_instances}

def instances(self, ce: OWLClassExpression, direct: bool = False, timeout: int = 1000):
return run_with_timeout(self._instances, timeout, (ce, direct))

def equivalent_classes(self, ce: OWLClassExpression) -> List[OWLClassExpression]:
"""
Gets the set of named classes that are equivalent to the specified class expression with
Expand Down
6 changes: 2 additions & 4 deletions owlapy/owlapi_mapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
import jpype.imports

from owlapy import owl_expression_to_manchester, manchester_to_owl_expression
from owlapy.class_expression import OWLClassExpression, OWLDataOneOf, OWLFacetRestriction, OWLDatatypeRestriction, \
OWLNothing, OWLClass
from owlapy.class_expression import OWLClassExpression, OWLDataOneOf, OWLFacetRestriction, OWLDatatypeRestriction
from owlapy.iri import IRI
from owlapy.owl_axiom import OWLDeclarationAxiom, OWLAnnotation, OWLAnnotationProperty, OWLClassAssertionAxiom, \
OWLDataPropertyAssertionAxiom, OWLDataPropertyDomainAxiom, OWLDataPropertyRangeAxiom, OWLObjectPropertyDomainAxiom, \
Expand Down Expand Up @@ -111,6 +110,7 @@ def __init__(self, ontology: _SO):
ontology_set.add(self.ontology)
bidi_provider = BidirectionalShortFormProviderAdapter(self.manager, ontology_set, SimpleShortFormProvider())
entity_checker = ShortFormEntityChecker(bidi_provider)
bidi_provider.add(self.manager.getOWLDataFactory().getOWLNothing())
self.parser = ManchesterOWLSyntaxClassExpressionParser(self.manager.getOWLDataFactory(), entity_checker)
self.renderer = ManchesterOWLSyntaxOWLObjectRendererImpl()

Expand Down Expand Up @@ -152,8 +152,6 @@ def _(self, e):

@map_.register
def _(self, e: OWLClassExpression):
if isinstance(e, OWLClass) and e.str == OWLNothing.str:
return OWLClassImpl(self.map_(e.iri))
return self.parser.parse(owl_expression_to_manchester(e))

@map_.register(OWLAnonymousClassExpressionImpl)
Expand Down

0 comments on commit 4251f78

Please sign in to comment.