Skip to content

Commit

Permalink
'timeout' parameter added to instances method
Browse files Browse the repository at this point in the history
  • Loading branch information
alkidbaci committed Sep 19, 2024
1 parent c7d7513 commit 9f648b8
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 7 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
35 changes: 29 additions & 6 deletions owlapy/owl_reasoner.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
"""OWL Reasoner"""
import operator
import logging
import threading
import time

import owlready2

from collections import defaultdict
Expand Down Expand Up @@ -35,6 +38,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 +213,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 +241,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 +708,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 +1237,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 +1250,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

0 comments on commit 9f648b8

Please sign in to comment.