diff --git a/README.md b/README.md index b13af488..d121e51c 100644 --- a/README.md +++ b/README.md @@ -30,8 +30,9 @@ pytest -p no:warnings -x # Running 103 tests takes ~ 30 mins ## Usage -In this example we start with a simple atomic class expression and move to some more complex -ones and finally render and print the last of them in description logics syntax. + +### Creating OWL Class Expressions +
Click me! ```python from owlapy.class_expression import OWLClass, OWLObjectIntersectionOf, OWLObjectSomeValuesFrom @@ -40,17 +41,13 @@ from owlapy import owl_expression_to_sparql, owl_expression_to_dl # Create the male class male = OWLClass("http://example.com/society#male") - # Create an object property using the iri as a string for 'hasChild' property. hasChild = OWLObjectProperty("http://example.com/society#hasChild") - # Create an existential restrictions hasChild_male = OWLObjectSomeValuesFrom(hasChild, male) - # Let's make it more complex by intersecting with another class teacher = OWLClass("http://example.com/society#teacher") teacher_that_hasChild_male = OWLObjectIntersectionOf([hasChild_male, teacher]) - # You can render and print owl class expressions in description logics syntax (and vice-versa) print(owl_expression_to_dl(teacher_that_hasChild_male)) # (∃ hasChild.male) ⊓ teacher @@ -68,7 +65,35 @@ class. In the above examples we have introduced 3 types of class expressions: Like we showed in this example, you can create all kinds of class expressions using the OWL objects in [owlapy api](https://dice-group.github.io/owlapy/autoapi/owlapy/index.html). -Many axioms can automatically inferred with a selected reasoner +
+ +### Logical Inference + +
Click me! + +```python +from owlapy.owl_ontology_manager import OntologyManager +from owlapy.owlapi_adaptor import OWLAPIAdaptor + +ontology_path = "KGs/Family/family-benchmark_rich_background.owl" +# Available OWL Reasoners: 'HermiT', 'Pellet', 'JFact', 'Openllet' +owlapi_adaptor = OWLAPIAdaptor(path=ontology_path, name_reasoner="Pellet") +onto = OntologyManager().load_ontology(ontology_path) +# Iterate over defined owl Classes in the signature +for i in onto.classes_in_signature(): + # Performing type inference with Pellet + instances=owlapi_adaptor.instances(i,direct=False) + print(f"Class:{i}\t Num instances:{len(instances)}") +owlapi_adaptor.stopJVM() +``` + +
+ +### Ontology Enrichment + +
Click me! + +An Ontology can be enriched by inferring many different axioms. ```python from owlapy.owlapi_adaptor import OWLAPIAdaptor @@ -86,7 +111,10 @@ adaptor.infer_axioms_and_save(output_path="KGs/Family/inferred_family-benchmark_ adaptor.stopJVM() ``` -Check also the [examples](https://github.com/dice-group/owlapy/tree/develop/examples) folder. +
+ + +Check also the [examples](https://github.com/dice-group/owlapy/tree/develop/examples) and [tests](https://github.com/dice-group/owlapy/tree/develop/tests) folders. ## How to cite Currently, we are working on our manuscript describing our framework. diff --git a/owlapy/owl_ontology_manager.py b/owlapy/owl_ontology_manager.py index 2d5ff52e..587ddb5d 100644 --- a/owlapy/owl_ontology_manager.py +++ b/owlapy/owl_ontology_manager.py @@ -27,7 +27,7 @@ from owlapy.owl_ontology import OWLOntology, Ontology, ToOwlready2 from owlapy.owl_property import OWLDataProperty, OWLObjectInverseOf, OWLObjectProperty, \ OWLProperty - +from typing import Union class OWLOntologyChange(metaclass=ABCMeta): """Represents an ontology change.""" @@ -849,10 +849,18 @@ def __init__(self, world_store=None): else: self._world = owlready2.World(filename=world_store) - def create_ontology(self, iri: IRI) -> 'Ontology': + def create_ontology(self, iri:Union[str,IRI]=None) -> 'Ontology': + if isinstance(iri, str): + iri=IRI.create(iri) + else: + assert isinstance(iri, IRI), "iri either must be string or an instance of IRI Class" return Ontology(self, iri, load=False) - def load_ontology(self, iri: IRI) -> 'Ontology': + def load_ontology(self, iri: Union[str,IRI]=None) -> 'Ontology': + if isinstance(iri, str): + iri=IRI.create(iri) + else: + assert isinstance(iri, IRI), "iri either must be string or an instance of IRI Class" return Ontology(self, iri, load=True) def apply_change(self, change: OWLOntologyChange): @@ -879,8 +887,7 @@ def save_ontology(self, ontology: OWLOntology, document_iri: IRI): filename = document_iri.as_str()[len('file:/'):] ont_x.save(file=filename) else: - # TODO XXX - raise NotImplementedError + raise NotImplementedError("Couldn't save because the namespace of document_iri does not start with **file:/**") def save_world(self): """Saves the actual state of the quadstore in the SQLite3 file. diff --git a/owlapy/owl_reasoner.py b/owlapy/owl_reasoner.py index 04b90a92..318ad2c9 100644 --- a/owlapy/owl_reasoner.py +++ b/owlapy/owl_reasoner.py @@ -2,11 +2,10 @@ import operator from abc import ABCMeta, abstractmethod from collections import defaultdict -from enum import Enum, auto from functools import singledispatchmethod, reduce from itertools import chain, repeat from types import MappingProxyType, FunctionType -from typing import DefaultDict, Iterable, Dict, Mapping, Set, Type, TypeVar, Optional, FrozenSet, List, cast +from typing import DefaultDict, Iterable, Dict, Mapping, Set, Type, TypeVar, Optional, FrozenSet import logging import owlready2 @@ -18,11 +17,11 @@ OWLDataAllValuesFrom from owlapy.class_expression import OWLClass from owlapy.iri import IRI -from owlapy.owl_axiom import OWLAxiom, OWLSubClassOfAxiom +from owlapy.owl_axiom import OWLSubClassOfAxiom from owlapy.owl_data_ranges import OWLDataRange, OWLDataComplementOf, OWLDataUnionOf, OWLDataIntersectionOf from owlapy.owl_datatype import OWLDatatype from owlapy.owl_object import OWLEntity -from owlapy.owl_ontology import OWLOntology, Ontology, _parse_concept_to_owlapy, ToOwlready2 +from owlapy.owl_ontology import OWLOntology, Ontology, _parse_concept_to_owlapy from owlapy.owl_ontology_manager import OntologyManager from owlapy.owl_property import OWLObjectPropertyExpression, OWLDataProperty, OWLObjectProperty, OWLObjectInverseOf, \ OWLPropertyExpression, OWLDataPropertyExpression @@ -33,7 +32,12 @@ logger = logging.getLogger(__name__) +_P = TypeVar('_P', bound=OWLPropertyExpression) +# TODO:CD:The name of the classes defined with metaclass=ABCMeta should reflect that +# TODO:CD: An instance cannot be created from those classes. +# TODO:CD: We should move those Abstract Base Classes into a respective package, e.g. +# TODO:CD: owlapy/abstract_owl_reasoner/abstract_owl_reasoner.py should contain OWLReasoner and OWLReasonerEx class OWLReasoner(metaclass=ABCMeta): """An OWLReasoner reasons over a set of axioms (the set of reasoner axioms) that is based on the imports closure of a particular ontology - the "root" ontology.""" @@ -401,20 +405,6 @@ class expression with respect to the imports closure of the root ontology. If ce is equivalent to owl:Thing then nothing will be returned. """ pass - - -# Deprecated -# class BaseReasoner(Enum): -# """Enumeration class for base reasoner when calling sync_reasoner. -# -# Attributes: -# PELLET: Pellet base reasoner. -# HERMIT: HermiT base reasoner. -# """ -# PELLET = auto() -# HERMIT = auto() - - class OWLReasonerEx(OWLReasoner, metaclass=ABCMeta): """Extra convenience methods for OWL Reasoners""" @@ -496,10 +486,9 @@ def ind_object_properties(self, ind: OWLNamedIndividual, direct: bool = True) -> except StopIteration: pass - class OntologyReasoner(OWLReasonerEx): __slots__ = '_ontology', '_world' - + # TODO: CD: We will remove owlready2 from owlapy _ontology: Ontology _world: owlready2.World @@ -1042,9 +1031,6 @@ def get_root_ontology(self) -> OWLOntology: return self._ontology -_P = TypeVar('_P', bound=OWLPropertyExpression) - - class FastInstanceCheckerReasoner(OWLReasonerEx): """Tries to check instances fast (but maybe incomplete).""" __slots__ = '_ontology', '_base_reasoner', \ diff --git a/owlapy/owlapi_mapper.py b/owlapy/owlapi_mapper.py index 1b9d0be9..9e2ec046 100644 --- a/owlapy/owlapi_mapper.py +++ b/owlapy/owlapi_mapper.py @@ -3,6 +3,7 @@ import jpype.imports +import owlapy.owl_ontology from owlapy import owl_expression_to_manchester, manchester_to_owl_expression from owlapy.class_expression import OWLClassExpression, OWLDataOneOf, OWLFacetRestriction, OWLDatatypeRestriction from owlapy.iri import IRI @@ -90,7 +91,10 @@ def init(the_class): class OWLAPIMapper: - def __init__(self, ontology): + def __init__(self, ontology=None): + # TODO: CD: Please use class type of ontology + # TODO: CD: if ontology is None, then we should throw an exception with a useful information + # assert isinstance(ontology, OWLAPIMapper) self.ontology = ontology self.manager = ontology.getOWLOntologyManager()