Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop' into issues-solving
Browse files Browse the repository at this point in the history
  • Loading branch information
alkidbaci committed Sep 30, 2024
2 parents 8cec437 + 172cbd0 commit efac1b3
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 35 deletions.
4 changes: 4 additions & 0 deletions owlapy/owl_ontology_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ def save_world(self):


class SyncOntologyManager(AbstractOWLOntologyManager):
"""
Create OWLManager in Python
https://owlcs.github.io/owlapi/apidocs_5/org/semanticweb/owlapi/apibinding/OWLManager.html
"""

# WARN: Do not move local imports to top of the module
def __init__(self):
Expand Down
33 changes: 10 additions & 23 deletions owlapy/owl_reasoner.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
"""OWL Reasoner"""
import operator
import logging
import threading

import owlready2

from collections import defaultdict
Expand All @@ -29,26 +27,12 @@
OWLPropertyExpression, OWLDataPropertyExpression
from owlapy.owl_individual import OWLNamedIndividual
from owlapy.owl_literal import OWLLiteral
from owlapy.utils import LRUCache
from owlapy.utils import LRUCache, run_with_timeout
from owlapy.abstracts.abstract_owl_reasoner import AbstractOWLReasoner, AbstractOWLReasonerEx

logger = logging.getLogger(__name__)

_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 @@ -1185,8 +1169,10 @@ def __init__(self, ontology: Union[SyncOntology, str], reasoner="HermiT"):
self.manager = ontology.manager
self.ontology = ontology
elif isinstance(ontology, str):
# https://owlcs.github.io/owlapi/apidocs_5/org/semanticweb/owlapi/apibinding/OWLManager.html
self.manager = SyncOntologyManager()
self.ontology = self.manager.load_ontology(ontology)
# OWLOntology
self.ontology = self.manager.load_ontology(iri=ontology)

self._owlapi_manager = self.manager.get_owlapi_manager()
self._owlapi_ontology = self.ontology.get_owlapi_ontology()
Expand Down Expand Up @@ -1654,11 +1640,12 @@ def infer_axioms_and_save(self, output_path: str = None, output_format: str = No
if java_object := self.inference_types_mapping.get(i, None):
generators.add(java_object)
iog = InferredOntologyGenerator(self._owlapi_reasoner, generators)
inferred_axioms_ontology = self._owlapi_manager.createOntology()
iog.fillOntology(self._owlapi_manager.getOWLDataFactory(), inferred_axioms_ontology)
inferred_ontology_file = File(output_path).getAbsoluteFile()
output_stream = FileOutputStream(inferred_ontology_file)
self._owlapi_manager.saveOntology(inferred_axioms_ontology, document_format, output_stream)
# CD: No need to create a new ontology
# inferred_axioms_ontology = self._owlapi_manager.createOntology()
iog.fillOntology(self._owlapi_manager.getOWLDataFactory(), self._owlapi_ontology)
self._owlapi_manager.saveOntology(self._owlapi_ontology,
document_format,
FileOutputStream(File(output_path).getAbsoluteFile()))

def generate_and_save_inferred_class_assertion_axioms(self, output="temp.ttl", output_format: str = None):
"""
Expand Down
8 changes: 5 additions & 3 deletions owlapy/scripts/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
"InferredSubDataPropertyAxiomGenerator",
"InferredSubObjectPropertyAxiomGenerator",
"InferredDataPropertyCharacteristicAxiomGenerator",
"InferredObjectPropertyCharacteristicAxiomGenerator"]
"InferredObjectPropertyCharacteristicAxiomGenerator"
]


def get_default_arguments(description=None):
Expand All @@ -38,12 +39,13 @@ def get_default_arguments(description=None):
def main():

args = get_default_arguments()
sync_reasoner = SyncReasoner(args.path_ontology)
sync_reasoner = SyncReasoner(ontology=args.path_ontology)
if "all" in args.inference_types:
it = inference_types
else:
it = args.inference_types
sync_reasoner.infer_axioms_and_save(output_path=args.out_ontology, output_format=args.output_type,
sync_reasoner.infer_axioms_and_save(output_path=args.out_ontology,
output_format=args.output_type,
inference_types=it)
print("Finished inferring axioms \nOutput filename: '{}'".format(args.out_ontology))

Expand Down
11 changes: 11 additions & 0 deletions owlapy/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,17 @@
from .owl_object import OWLObject
from .owl_datatype import OWLDatatype

import concurrent.futures
def run_with_timeout(func, timeout, args=(), **kwargs):
with concurrent.futures.ThreadPoolExecutor() as executor:
future = executor.submit(func, *args, **kwargs)
try:
result = future.result(timeout=timeout)
return result
except concurrent.futures.TimeoutError:
return set()


def concept_reducer(concepts:Iterable, opt:Callable):
"""
Reduces a set of concepts by applying a binary operation to each pair of concepts.
Expand Down
33 changes: 24 additions & 9 deletions tests/test_reasoner_alc_father_ontology.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from owlapy.owl_reasoner import SyncReasoner
from owlapy.class_expression import OWLClass, OWLObjectSomeValuesFrom
from owlapy.class_expression import OWLClass, OWLObjectSomeValuesFrom, OWLObjectAllValuesFrom
from owlapy.owl_individual import OWLNamedIndividual
from owlapy.iri import IRI
from owlapy.owl_property import OWLObjectProperty
Expand All @@ -13,32 +13,47 @@ def test_readme(self):

# Thing
thing = OWLClass(IRI('http://www.w3.org/2002/07/owl#', 'Thing'))
# Nothing
nothing = OWLClass(IRI('http://www.w3.org/2002/07/owl#', 'Nothing'))

# Person OWL Class
person = eval("OWLClass(IRI('http://example.com/father#', 'person'))")
# Female OWL CLass
female = eval("OWLClass(IRI('http://example.com/father#', 'female'))")
# hasChild object property
hasChild = OWLObjectProperty(IRI('http://example.com/father#', 'hasChild'))

# Things
# Sanity checking = Things
assert hermit.instances(thing) == {OWLNamedIndividual(IRI('http://example.com/father#', 'anna')), OWLNamedIndividual(IRI('http://example.com/father#', 'martin')), OWLNamedIndividual(IRI('http://example.com/father#', 'heinz')), OWLNamedIndividual(IRI('http://example.com/father#', 'stefan')), OWLNamedIndividual(IRI('http://example.com/father#', 'michelle')), OWLNamedIndividual(IRI('http://example.com/father#', 'markus'))}
# De Morgen Rules : Thing \equiv \neg Bottom
assert hermit.instances(thing) == hermit.instances(nothing.get_object_complement_of())

# hasChild a thing.
# Sanity checking = \exist hasChild Thing.
assert hermit.instances(OWLObjectSomeValuesFrom(property=hasChild, filler=thing)) == eval(
"{OWLNamedIndividual(IRI('http://example.com/father#', 'markus')), OWLNamedIndividual(IRI('http://example.com/father#', 'martin')), OWLNamedIndividual(IRI('http://example.com/father#', 'stefan')), OWLNamedIndividual(IRI('http://example.com/father#', 'anna'))}")

# hasChild a person.
# Sanity checking \exist hasChild Person.
assert hermit.instances(OWLObjectSomeValuesFrom(property=hasChild, filler=person)) == eval(
"{OWLNamedIndividual(IRI('http://example.com/father#', 'markus')), OWLNamedIndividual(IRI('http://example.com/father#', 'martin')), OWLNamedIndividual(IRI('http://example.com/father#', 'stefan')), OWLNamedIndividual(IRI('http://example.com/father#', 'anna'))}")
# \exist hasChild a person = \exist hasChild a thing
assert hermit.instances(OWLObjectSomeValuesFrom(property=hasChild, filler=thing)) == hermit.instances(
OWLObjectSomeValuesFrom(property=hasChild, filler=person))

# hasChild a female.
# Sanity checking: \exist hasChild a female.
assert hermit.instances(OWLObjectSomeValuesFrom(property=hasChild, filler=female)) == eval(
"{OWLNamedIndividual(IRI('http://example.com/father#', 'markus'))}")
# Question: hasChild something that hasChild a female.
# Answer: stefan
# (stefan haschild markus) and markus haschild anna
# Answer: stefan: (stefan haschild markus) and (markus haschild anna)
assert hermit.instances(OWLObjectSomeValuesFrom(property=hasChild,
filler=OWLObjectSomeValuesFrom(property=hasChild,
filler=female))) == eval(
"{OWLNamedIndividual(IRI('http://example.com/father#', 'stefan'))}")

# De morgen rule: \neg \exist r \neg T = \forall r T
c = thing
forall_r_c = OWLObjectAllValuesFrom(hasChild, c)
neg_exist_r_neg_c = OWLObjectSomeValuesFrom(hasChild, c.get_object_complement_of()).get_object_complement_of()
assert hermit.instances(neg_exist_r_neg_c) == hermit.instances(forall_r_c)
# De morgen rule: \neg \exist r \neg bottom = \forall r bottom
c = nothing
forall_r_c = OWLObjectAllValuesFrom(hasChild, c)
neg_exist_r_neg_c = OWLObjectSomeValuesFrom(hasChild, c.get_object_complement_of()).get_object_complement_of()
assert hermit.instances(neg_exist_r_neg_c) == hermit.instances(forall_r_c)

0 comments on commit efac1b3

Please sign in to comment.