diff --git a/examples/comparing_adaptor_reasoners.py b/examples/comparing_adaptor_reasoners.py deleted file mode 100644 index 25222601..00000000 --- a/examples/comparing_adaptor_reasoners.py +++ /dev/null @@ -1,45 +0,0 @@ -from owlapy.owl_property import OWLObjectProperty -from owlapy.owl_reasoner import SyncReasoner -from owlapy.iri import IRI -from owlapy.class_expression import OWLClass, OWLObjectAllValuesFrom, OWLObjectComplementOf -import time -ontology_location = "../KGs/Carcinogenesis/carcinogenesis.owl" - -i1 = set() -i2 = set() -i3 = set() -i4 = set() - -for rsn in ["HermiT", "Pellet", "JFact", "Openllet"]: - reasoner = SyncReasoner(ontology_location, rsn) - # TODO AB: needs a more complex class expression to show the specific differences of the reasoners - ce = OWLObjectAllValuesFrom(property=OWLObjectProperty(IRI('http://dl-learner.org/carcinogenesis#', 'hasAtom')), - filler=OWLObjectComplementOf(OWLClass(IRI('http://dl-learner.org/carcinogenesis#', - 'Sulfur-75')))) - - if rsn == "HermiT": - i1 = set(reasoner.instances(ce)) - elif rsn == "Pellet": - i2 = set(reasoner.instances(ce)) - elif rsn == "JFact": - i3 = set(reasoner.instances(ce)) - elif rsn == "Openllet": - i4 = set(reasoner.instances(ce)) - -print("Hermit-Pellet:") -[print(_) for _ in i1-i2] -time.sleep(10) -print("Hermit-JFact:") -[print(_) for _ in i1-i3] -time.sleep(10) -print("Hermit-Openllet:") -[print(_) for _ in i1-i4] -time.sleep(10) -print("Pellet-JFact:") -[print(_) for _ in i2-i3] -time.sleep(10) -print("Pellet-Openllet:") -[print(_) for _ in i2-i4] -time.sleep(10) -print("JFact-Openllet:") -[print(_) for _ in i3-i4] \ No newline at end of file diff --git a/examples/ontology_modification.py b/examples/ontology_engineering.py similarity index 100% rename from examples/ontology_modification.py rename to examples/ontology_engineering.py diff --git a/examples/ontology_reasoning_retrieval.py b/examples/ontology_reasoning_retrieval.py new file mode 100644 index 00000000..414de2b0 --- /dev/null +++ b/examples/ontology_reasoning_retrieval.py @@ -0,0 +1,39 @@ +""" + +KB = { (A subclass B), (B subclass C), (x type A) } + +KB = { (A subclass B), (B subclass C), (x type A), (x type B), (x type C) } + +Missing types are inferred due to subclass hierarchy. +""" +from owlapy.class_expression import OWLClass +from owlapy.owl_axiom import OWLDeclarationAxiom, OWLClassAssertionAxiom, OWLSubClassOfAxiom +from owlapy.owl_ontology_manager import OntologyManager +from owlapy.owl_individual import OWLNamedIndividual +from owlapy.iri import IRI +from owlapy.owl_reasoner import SyncReasoner +# () Define a base IRI. +base_iri = IRI(namespace="https://github.com/dice-group/owlapy#") +# () Create an empty ontology. +onto = OntologyManager().create_ontology(iri=base_iri) +# () Define classes and individuals. +A = OWLClass(iri=base_iri.get_namespace() + "A") +B = OWLClass(iri=base_iri.get_namespace() + "B") +C = OWLClass(iri=base_iri.get_namespace() + "C") +x = OWLNamedIndividual(iri=base_iri.get_namespace() + "x") +# () Add axioms. +onto.add_axiom([OWLDeclarationAxiom(A), + OWLDeclarationAxiom(B), + OWLDeclarationAxiom(C), + OWLDeclarationAxiom(x), + OWLSubClassOfAxiom(A,B), + OWLSubClassOfAxiom(B,C), + OWLClassAssertionAxiom(x,A)]) +# () Save axioms [ (A subclass B), (B subclass C), (x type A) ]. +onto.save("new_ontology.owl") +# () Initialize reasoner. +reasoner = SyncReasoner(ontology="new_ontology.owl", reasoner="Pellet") +# () Infer instances. +for i in reasoner.ontology.classes_in_signature(): + print(f"Retrieve {i}:",end=" ") + print(" ".join( [_.str for _ in reasoner.instances(i)])) \ No newline at end of file diff --git a/examples/ontology_reasoning_retrieval_agreements.py b/examples/ontology_reasoning_retrieval_agreements.py new file mode 100644 index 00000000..ca66d1e3 --- /dev/null +++ b/examples/ontology_reasoning_retrieval_agreements.py @@ -0,0 +1,33 @@ +from owlapy.owl_reasoner import SyncReasoner +from owlapy import OntologyManager +from owlapy.class_expression import OWLClassExpression +from typing import Dict +ontology_path = "../KGs/Family/family-benchmark_rich_background.owl" +# () Load ontology +onto = OntologyManager().load_ontology(ontology_path) + +# () Initialize Reasoners +reasoners = dict() +reasoners["HermiT"] = SyncReasoner(ontology=ontology_path, reasoner="HermiT") +reasoners["Pellet"] = SyncReasoner(ontology=ontology_path, reasoner="Pellet") +reasoners["JFact"] = SyncReasoner(ontology=ontology_path, reasoner="JFact") +reasoners["Openllet"] = SyncReasoner(ontology=ontology_path, reasoner="Openllet") + +def compute_agreements(owl_reasoners:Dict[str,SyncReasoner], expression: OWLClassExpression, verbose=False): + if verbose: + print(f"Computing agreements between Reasoners on {expression}...",end="\t") + retrieval_result = None + flag = False + for __, reasoner in owl_reasoners.items(): + if retrieval_result: + flag = retrieval_result == {_.str for _ in reasoner.instances(expression)} + else: + retrieval_result = {_.str for _ in reasoner.instances(expression)} + if verbose: + print(f"Successful:{flag}") + return flag + +# () Iterate over named classes +for c in onto.classes_in_signature(): + # reasoners must agree + assert compute_agreements(reasoners, c, True) \ No newline at end of file diff --git a/examples/owl_reasoners.py b/examples/ontology_reasoning_retrieval_agreements_and_runtimes.py similarity index 95% rename from examples/owl_reasoners.py rename to examples/ontology_reasoning_retrieval_agreements_and_runtimes.py index 90584e24..4c449184 100644 --- a/examples/owl_reasoners.py +++ b/examples/ontology_reasoning_retrieval_agreements_and_runtimes.py @@ -9,6 +9,7 @@ import matplotlib.pyplot as plt import seaborn as sns import numpy as np +from tqdm import tqdm ontology_path = "../KGs/Family/family-benchmark_rich_background.owl" @@ -45,10 +46,9 @@ def eval_reasoners(iter_owl_exp, mapping): - print("Number of expressions:", len(iter_owl_exp)) results = dict() runtime_results = dict() - for c in iter_owl_exp: + for c in tqdm(iter_owl_exp): for name_i, reasoner_i in mapping.items(): start_time_i = time.time() result_reasoner_i = {i.str for i in reasoner_i.instances(c)} @@ -110,15 +110,19 @@ def plot_similarity_btw_reasoners(results): # EVAL Named Concepts +print("Evaluation over named concepts...") similarity_results, average_runtime_owl_reasoners = eval_reasoners(nc, owl_reasoners) plot_similarity_btw_reasoners(similarity_results) plot_runtimes(average_runtime_owl_reasoners, title="Avg Runtime of Reasoners on Named Concepts") + # EVAL Negated Concepts +print("Evaluation over negated named concepts...") similarity_results, average_runtime_owl_reasoners = eval_reasoners(nnc, owl_reasoners) plot_similarity_btw_reasoners(similarity_results) plot_runtimes(average_runtime_owl_reasoners, title="Avg Runtime of Reasoners on Negated Named Concepts") # EVAL Exist R. NC +print("Evaluation over existential object property restrictions... takes some time") similarity_results, average_runtime_owl_reasoners = eval_reasoners(exist_nc, owl_reasoners) plot_similarity_btw_reasoners(similarity_results) plot_runtimes(average_runtime_owl_reasoners, title="Avg Runtime of Reasoners on OWLObjectSomeValuesFrom") diff --git a/owlapy/__init__.py b/owlapy/__init__.py index 4f6b6692..6c8bd5cf 100644 --- a/owlapy/__init__.py +++ b/owlapy/__init__.py @@ -3,4 +3,6 @@ from .parser import (dl_to_owl_expression as dl_to_owl_expression, manchester_to_owl_expression as manchester_to_owl_expression) from .converter import owl_expression_to_sparql as owl_expression_to_sparql -__version__ = '1.3.0' +from .owl_ontology_manager import OntologyManager as OntologyManager + +__version__ = '1.3.1' diff --git a/owlapy/class_expression/owl_class.py b/owlapy/class_expression/owl_class.py index fd821f45..0f218a75 100644 --- a/owlapy/class_expression/owl_class.py +++ b/owlapy/class_expression/owl_class.py @@ -62,4 +62,10 @@ def get_nnf(self) -> 'OWLClass': # documented in parent return self + def __str__(self): + return f"OWLClass({self.reminder})" + + def __repr__(self): + return f"OWLClass({self._iri})" + diff --git a/owlapy/iri.py b/owlapy/iri.py index c7234414..66166bb4 100644 --- a/owlapy/iri.py +++ b/owlapy/iri.py @@ -39,7 +39,7 @@ class IRI(OWLAnnotationSubject, OWLAnnotationValue, metaclass=_meta_IRI): _namespace: str _remainder: str - def __init__(self, namespace: Union[str, Namespaces], remainder: str): + def __init__(self, namespace: Union[str, Namespaces], remainder: str=""): if isinstance(namespace, Namespaces): namespace = namespace.ns else: @@ -89,7 +89,7 @@ def create(string, remainder=None) -> 'IRI': return IRI(string[0:index], string[index:]) def __repr__(self): - return f"IRI({repr(self._namespace)},{repr(self._remainder)})" + return f"IRI({repr(self._namespace)}, {repr(self._remainder)})" def __eq__(self, other): if type(other) is type(self): diff --git a/owlapy/owl_object.py b/owlapy/owl_object.py index b90e9888..02894034 100644 --- a/owlapy/owl_object.py +++ b/owlapy/owl_object.py @@ -88,8 +88,6 @@ def __hash__(self): def __repr__(self): return f"{type(self).__name__}({repr(self._iri)})" - pass - class OWLEntity(OWLNamedObject, metaclass=ABCMeta): """Represents Entities in the OWL 2 Specification.""" diff --git a/owlapy/owl_ontology.py b/owlapy/owl_ontology.py index 44b064a7..0e72b3c3 100644 --- a/owlapy/owl_ontology.py +++ b/owlapy/owl_ontology.py @@ -38,6 +38,7 @@ OWLDifferentIndividualsAxiom, OWLDisjointClassesAxiom, OWLSameIndividualAxiom, OWLClassAxiom, OWLDataPropertyDomainAxiom, OWLDataPropertyRangeAxiom, OWLObjectPropertyDomainAxiom) from owlapy.vocab import OWLFacet +import os logger = logging.getLogger(__name__) @@ -800,6 +801,9 @@ def __init__(self, manager: _OM, ontology_iri: IRI, load: bool): onto = onto.load() self._onto = onto + def __len__(self) -> int: + return len([t for t in self._onto.get_triples()]) + def classes_in_signature(self) -> Iterable[OWLClass]: for c in self._onto.classes(): yield OWLClass(IRI.create(c.iri)) @@ -928,13 +932,27 @@ def remove_axiom(self, axiom: Union[OWLAxiom, Iterable[OWLAxiom]]): for ax in axiom: _remove_axiom(ax, self, self._world) - def save(self, path: Union[str,IRI] = None, rdf_format = "rdfxml"): + def save(self, path: Union[str,IRI] = None, inplace:bool=False, rdf_format = "rdfxml"): + # convert it into str. if isinstance(path, IRI): - path=path.as_str() + path = path.as_str() + # Sanity checking + if inplace is False: + assert isinstance(path,str), f"path must be string if inplace is set to False. Current path is {type(path)}" + # Get the current ontology defined in the world. ont_x:owlready2.namespace.Ontology - assert isinstance(path,str), f"path must be string. Currently it is {type(path)}" ont_x = self._world.get_ontology(self.get_ontology_id().get_ontology_iri().as_str()) - ont_x.save(file=path,format=rdf_format) + + if inplace: + if os.path.exists(self._iri.as_str()): + print(f"Saving {self} inplace...") + ont_x.save(file=self._iri.as_str(), format=rdf_format) + else: + print(f"Saving {self} inplace with name of demo.owl...") + self._world.get_ontology(self.get_ontology_id().get_ontology_iri().as_str()).save(file="demo.owl") + else: + print(f"Saving {path}..") + ont_x.save(file=path,format=rdf_format) def get_original_iri(self): """Get the IRI argument that was used to create this ontology.""" @@ -949,7 +967,7 @@ def __hash__(self): return hash(self._onto.base_iri) def __repr__(self): - return f'Ontology({IRI.create(self._onto.base_iri)}, {self._onto.loaded})' + return f'Ontology({self._onto.base_iri}, loaded:{self._onto.loaded})' class SyncOntology(OWLOntology): diff --git a/owlapy/owl_reasoner.py b/owlapy/owl_reasoner.py index 45d02bca..f909e15e 100644 --- a/owlapy/owl_reasoner.py +++ b/owlapy/owl_reasoner.py @@ -1228,6 +1228,7 @@ def instances(self, ce: OWLClassExpression, direct=False) -> List[OWLNamedIndivi list: A list of individuals classified by the given class expression. """ inds = self._owlapi_reasoner.getInstances(self.mapper.map_(ce), direct).getFlattened() + assert str(type(inds)) == "" return [self.mapper.map_(ind) for ind in inds] def equivalent_classes(self, ce: OWLClassExpression) -> List[OWLClassExpression]: diff --git a/setup.py b/setup.py index b24a367e..b5e96717 100644 --- a/setup.py +++ b/setup.py @@ -8,9 +8,7 @@ version="1.3.0", packages=find_packages(), include_package_data=True, - package_data={ - 'owlapy': ['jar_dependencies/*.jar'], - }, + package_data={'owlapy': ['jar_dependencies/*.jar'],}, install_requires=[ "pandas>=1.5.0", "requests>=2.32.3", @@ -19,7 +17,8 @@ "pytest>=8.1.1", "sortedcontainers>=2.4.0", "owlready2>=0.40", - "JPype1>=1.5.0"], + "JPype1>=1.5.0", + "tqdm>=4.66.5"], author='Caglar Demir', author_email='caglardemir8@gmail.com', url='https://github.com/dice-group/owlapy',