diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index a0e107e9..a0d19860 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -25,6 +25,7 @@ jobs:
run: |
wget https://files.dice-research.org/projects/Ontolearn/KGs.zip
unzip KGs.zip
+ pip install scikit-learn
python -m pytest -p no:warnings -x
- name: Coverage report
diff --git a/.gitignore b/.gitignore
index 64e33d7f..6fc4aaf4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -148,4 +148,4 @@ cython_debug/
.vscode/
# Project related files
-/KGs/
\ No newline at end of file
+KGs/
\ No newline at end of file
diff --git a/README.md b/README.md
index 6dd942c2..5d35a36e 100644
--- a/README.md
+++ b/README.md
@@ -30,29 +30,6 @@ pytest -p no:warnings -x # Running 147 tests ~ 35 secs
## Examples
-### Sklearn to OWL Ontology
-
- Click me!
-
-```python
-from owlapy.owl_ontology_manager import SyncOntologyManager
-from owlapy.util_owl_static_funcs import csv_to_rdf_kg
-import pandas as pd
-from sklearn.datasets import load_iris
-data = load_iris()
-df = pd.DataFrame(data.data, columns=data.feature_names)
-df.to_csv("iris_dataset.csv", index=False)
-path_kg = "iris_kg.owl"
-# Construct an RDF Knowledge Graph from a CSV file
-csv_to_rdf_kg(path_csv="iris_dataset.csv", path_kg=path_kg, namespace="http://owlapy.com/iris")
-onto = SyncOntologyManager().load_ontology(path_kg)
-assert len(onto.get_abox_axioms()) == 750
-
-```
-
-
-
-
### Exploring OWL Ontology
Click me!
@@ -101,7 +78,8 @@ for axiom in onto.get_abox_axioms():
-### Creating OWL Class Expressions
+### OWL Knowledge Engineering
+
Click me!
```python
@@ -111,7 +89,7 @@ from owlapy import owl_expression_to_sparql, owl_expression_to_dl
from owlapy.owl_ontology_manager import OntologyManager
from owlapy.owl_axiom import OWLDeclarationAxiom, OWLClassAssertionAxiom
from owlapy.owl_individual import OWLNamedIndividual, IRI
-
+from owlapy.static_funcs import create_ontology
# Using owl classes to create a complex class expression
male = OWLClass("http://example.com/society#male")
hasChild = OWLObjectProperty("http://example.com/society#hasChild")
@@ -119,23 +97,19 @@ hasChild_male = OWLObjectSomeValuesFrom(hasChild, male)
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 or convert it to SPARQL for example.
+# You can render and print owl class expressions in Description Logics syntax or convert it to SPARQL for example.
print(owl_expression_to_dl(teacher_that_hasChild_male)) # (∃ hasChild.male) ⊓ teacher
print(owl_expression_to_sparql(teacher_that_hasChild_male)) # SELECT DISTINCT ?x WHERE { ?x ?s_1 . ?s_1 a . ?x a . } }
-# Create an Ontology, add the axioms and save the Ontology.
-manager = OntologyManager()
-new_iri = IRI.create("file:/example_ontology.owl")
-ontology = manager.create_ontology(new_iri)
-
+# Create an ontology via ontology manager directly
+ontology = create_ontology("file:/example_ontology.owl",with_owlapi=False)
john = OWLNamedIndividual("http://example.com/society#john")
male_declaration_axiom = OWLDeclarationAxiom(male)
hasChild_declaration_axiom = OWLDeclarationAxiom(hasChild)
john_declaration_axiom = OWLDeclarationAxiom(john)
john_a_male_assertion_axiom = OWLClassAssertionAxiom(john, male)
ontology.add_axiom([male_declaration_axiom, hasChild_declaration_axiom, john_declaration_axiom, john_a_male_assertion_axiom])
-ontology.save()
-
+ontology.save(inplace=True)
```
Every OWL object that can be used to classify individuals, is considered a class expression and
@@ -201,5 +175,29 @@ stopJVM()
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.
+
+### Sklearn to OWL Ontology
+
+ Click me!
+
+```python
+from owlapy.owl_ontology_manager import SyncOntologyManager
+from owlapy.util_owl_static_funcs import csv_to_rdf_kg
+import pandas as pd
+from sklearn.datasets import load_iris
+data = load_iris()
+df = pd.DataFrame(data.data, columns=data.feature_names)
+df.to_csv("iris_dataset.csv", index=False)
+path_kg = "iris_kg.owl"
+# Construct an RDF Knowledge Graph from a CSV file
+csv_to_rdf_kg(path_csv="iris_dataset.csv", path_kg=path_kg, namespace="http://owlapy.com/iris")
+onto = SyncOntologyManager().load_ontology(path_kg)
+assert len(onto.get_abox_axioms()) == 750
+
+```
+
+
+
+
## How to cite
Currently, we are working on our manuscript describing our framework.
diff --git a/owlapy/class_expression/restriction.py b/owlapy/class_expression/restriction.py
index 0e6658a9..827cf534 100644
--- a/owlapy/class_expression/restriction.py
+++ b/owlapy/class_expression/restriction.py
@@ -10,7 +10,7 @@
from ..owl_individual import OWLIndividual
from ..owl_datatype import OWLDatatype
from ..owl_object import OWLObject
-from ..vocab import OWLFacet
+from ..vocab import OWLFacet
from datetime import datetime, date
from pandas import Timedelta
@@ -53,7 +53,7 @@ class OWLHasValueRestriction(Generic[_T], OWLRestriction, HasFiller[_T], metacla
"""Represent a HasValue restriction in the OWL 2
Args:
- _T: The value type.
+ value: The value type _T.
"""
__slots__ = ()
@@ -143,12 +143,14 @@ def get_filler(self) -> OWLClassExpression:
return self._filler
-class OWLObjectCardinalityRestriction(OWLCardinalityRestriction[OWLClassExpression], OWLQuantifiedObjectRestriction):
+class OWLObjectCardinalityRestriction(OWLCardinalityRestriction[OWLClassExpression], OWLQuantifiedObjectRestriction,
+ metaclass=ABCMeta):
"""Represents Object Property Cardinality Restrictions in the OWL 2 specification."""
__slots__ = ()
_property: OWLObjectPropertyExpression
# @TODO: CD: property shows the in-built function
+
@abstractmethod
def __init__(self, cardinality: int, property: OWLObjectPropertyExpression, filler: OWLClassExpression):
super().__init__(cardinality, filler)
@@ -169,6 +171,7 @@ def __eq__(self, other):
and self._filler == other._filler
else:
return False
+
def __hash__(self):
return hash((self._property, self._cardinality, self._filler))
@@ -342,7 +345,6 @@ def __eq__(self, other):
else:
return False
-
def __hash__(self):
return hash(("OWLObjectHasSelf", self._property))
@@ -430,13 +432,16 @@ def as_object_union_of(self) -> OWLClassExpression:
if len(self._values) == 1:
return self
return OWLObjectUnionOf(map(lambda _: OWLObjectOneOf(_), self.individuals()))
+
def __hash__(self):
return hash(("OWLObjectOneOf", self._values))
+
def __eq__(self, other):
if type(other) is type(self):
return self._values == other._values
else:
return False
+
def __repr__(self):
return f'OWLObjectOneOf({self._values})'
@@ -466,6 +471,7 @@ def __init__(self, filler: OWLDataRange):
assert isinstance(filler, OWLDataRange), "filler must be an OWLDataRange"
self._filler = filler
# @TODO:CD: define it as @property
+
def get_filler(self) -> OWLDataRange:
# documented in parent (HasFiller)
return self._filler
@@ -479,13 +485,16 @@ class OWLDataCardinalityRestriction(OWLCardinalityRestriction[OWLDataRange],
_property: OWLDataPropertyExpression
# @TODO: CD: property shows the in-built function
+
@abstractmethod
def __init__(self, cardinality: int, property: OWLDataPropertyExpression, filler: OWLDataRange):
assert isinstance(filler, OWLDataRange), "filler must be an OWLDataRange"
super().__init__(cardinality, filler)
self._property = property
+
def __hash__(self):
return hash(("OWLDataCardinalityRestriction",self._property, self._cardinality, self._filler))
+
def __repr__(self):
return f"{type(self).__name__}(" \
f"property={repr(self.get_property())},{self.get_cardinality()},filler={repr(self.get_filler())})"
@@ -501,6 +510,7 @@ def get_property(self) -> OWLDataPropertyExpression:
# documented in parent
return self._property
+
class OWLDataMinCardinality(OWLDataCardinalityRestriction):
"""A minimum cardinality expression DataMinCardinality( n DPE DR ) consists of a nonnegative integer n, a data
property expression DPE, and a unary data range DR, and it contains all those individuals that are connected by
@@ -511,6 +521,7 @@ class OWLDataMinCardinality(OWLDataCardinalityRestriction):
type_index: Final = 3015
# @TODO: CD: property shows the in-built function
+
def __init__(self, cardinality: int, property: OWLDataPropertyExpression, filler: OWLDataRange):
"""
Args:
@@ -534,6 +545,7 @@ class OWLDataMaxCardinality(OWLDataCardinalityRestriction):
type_index: Final = 3017
# @TODO: CD: property shows the in-built function
+
def __init__(self, cardinality: int, property: OWLDataPropertyExpression, filler: OWLDataRange):
"""
Args:
@@ -557,6 +569,7 @@ class OWLDataExactCardinality(OWLDataCardinalityRestriction):
type_index: Final = 3016
# @TODO: CD: property shows the in-built function
+
def __init__(self, cardinality: int, property: OWLDataPropertyExpression, filler: OWLDataRange):
"""
Args:
@@ -593,6 +606,7 @@ class OWLDataSomeValuesFrom(OWLQuantifiedDataRestriction):
_property: OWLDataPropertyExpression
# @TODO: CD: property shows the in-built function
+
def __init__(self, property: OWLDataPropertyExpression, filler: OWLDataRange):
"""Gets an OWLDataSomeValuesFrom restriction.
@@ -614,6 +628,7 @@ def __eq__(self, other):
return self._filler == other._filler and self._property == other._property
else:
return False
+
def __hash__(self):
return hash(("OWLDataSomeValuesFrom",self._filler, self._property))
@@ -636,6 +651,7 @@ class OWLDataAllValuesFrom(OWLQuantifiedDataRestriction):
_property: OWLDataPropertyExpression
# @TODO:CD:property shows the in-built function
+
def __init__(self, property: OWLDataPropertyExpression, filler: OWLDataRange):
"""Gets an OWLDataAllValuesFrom restriction.
@@ -657,6 +673,7 @@ def __eq__(self, other):
return self._filler == other._filler and self._property == other._property
else:
return False
+
def __hash__(self):
return hash(("OWLDataAllValuesFrom",self._filler, self._property))
@@ -674,17 +691,20 @@ class OWLDataHasValue(OWLHasValueRestriction[OWLLiteral], OWLDataRestriction):
__slots__ = '_property'
# @TODO:CD:What is _v? even if it is inherited from somewhere, we should add it into docstring.
# @TODO:CD: We should also name the class attributes in a more meaningful manner.
+ # AB re: _v is indeed inherited and represents the value of this DataHasValue CE. It's name is kept general
+ # because the value can have different types depending on the implementor of the base class.
type_index: Final = 3014
_property: OWLDataPropertyExpression
# @TODO: CD: property shows the in-built function
+
def __init__(self, property: OWLDataPropertyExpression, value: OWLLiteral):
"""Gets an OWLDataHasValue restriction.
Args:
property: The data property that the restriction acts along.
- filler: The literal value.
+ value: The literal value.
Returns:
An OWLDataHasValue restriction along the specified property with the specified literal.
@@ -700,8 +720,9 @@ def __eq__(self, other):
return self._v == other._v and self._property == other._property
else:
return False
+
def __hash__(self):
- return hash(("OWLDataHasValue",self._v, self._property))
+ return hash(("OWLDataHasValue", self._v, self._property))
def as_some_values_from(self) -> OWLClassExpression:
"""A convenience method that obtains this restriction as an existential restriction with a nominal filler.
@@ -730,6 +751,7 @@ def __init__(self, values: Union[OWLLiteral, Iterable[OWLLiteral]]):
for _ in values:
assert isinstance(_, OWLLiteral)
self._values = tuple(values)
+
def __repr__(self):
return f'OWLDataOneOf({self._values})'
@@ -742,6 +764,7 @@ def __eq__(self, other):
else:
return False
# TODO:CD: define it as @property as the name of the class method does not correspond to an action
+
def values(self) -> Iterable[OWLLiteral]:
"""Gets the values that are in the oneOf.
@@ -770,7 +793,7 @@ class OWLDatatypeRestriction(OWLDataRange):
_facet_restrictions: Sequence['OWLFacetRestriction']
def __init__(self, type_: OWLDatatype, facet_restrictions: Union['OWLFacetRestriction',
- Iterable['OWLFacetRestriction']]):
+ Iterable['OWLFacetRestriction']]):
self._type = type_
if isinstance(facet_restrictions, OWLFacetRestriction):
facet_restrictions = facet_restrictions,
@@ -788,6 +811,7 @@ def __eq__(self, other):
and self._facet_restrictions == other._facet_restrictions
else:
return False
+
def __hash__(self):
return hash(("OWLDatatypeRestriction", self._type, self._facet_restrictions))
@@ -825,7 +849,7 @@ def __eq__(self, other):
return False
def __hash__(self):
- return hash(("OWLFacetRestriction",self._facet, self._literal))
+ return hash(("OWLFacetRestriction", self._facet, self._literal))
def __repr__(self):
return f'OWLFacetRestriction({self._facet}, {repr(self._literal)})'
diff --git a/owlapy/owl_axiom.py b/owlapy/owl_axiom.py
index eace5b2b..caa84eea 100644
--- a/owlapy/owl_axiom.py
+++ b/owlapy/owl_axiom.py
@@ -281,6 +281,9 @@ def __init__(self, class_expressions: List[OWLClassExpression],
annotations: Optional[Iterable['OWLAnnotation']] = None):
super().__init__(class_expressions=class_expressions, annotations=annotations)
+ def __iter__(self):
+ yield from self._class_expressions
+
def contains_named_equivalent_class(self) -> bool:
return any(isinstance(ce, OWLClass) for ce in self._class_expressions)
@@ -1259,6 +1262,14 @@ def __init__(self, property_: _P, range_: _R, annotations: Optional[Iterable[OWL
self._range = range_
super().__init__(property_=property_, annotations=annotations)
+ @property
+ def prop(self):
+ return self._property
+
+ @property
+ def range(self):
+ return self._range
+
def get_range(self) -> _R:
return self._range
@@ -1290,6 +1301,10 @@ def __init__(self, property_: OWLObjectPropertyExpression, domain: OWLClassExpre
annotations: Optional[Iterable[OWLAnnotation]] = None):
super().__init__(property_=property_, domain=domain, annotations=annotations)
+ @property
+ def prop(self):
+ return self._property
+
class OWLDataPropertyDomainAxiom(OWLPropertyDomainAxiom[OWLDataPropertyExpression]):
""" A data property domain axiom DataPropertyDomain( DPE CE ) states that the domain of the
diff --git a/owlapy/owl_ontology.py b/owlapy/owl_ontology.py
index 6be14694..930360d0 100644
--- a/owlapy/owl_ontology.py
+++ b/owlapy/owl_ontology.py
@@ -996,7 +996,7 @@ def __init__(self, manager: _SM, path: Union[IRI, str], new: bool = False):
raise NotImplementedError("Cant initialize a new ontology using path. Use IRI instead")
else: # means we are loading an existing ontology
self.owlapi_ontology = self.manager.get_owlapi_manager().loadOntologyFromOntologyDocument(File(file_path))
- self.mapper = OWLAPIMapper(self)
+ self.mapper = OWLAPIMapper()
def __eq__(self, other):
if isinstance(other, SyncOntology):
@@ -1063,6 +1063,7 @@ def get_signature(self, include_imports_closure: bool = True):
Entities in signature.
"""
# @TODO: CD: Is this class method redundant given that we have the individuals_in_signature ?
+ # AB re: This method does not return only individuals.
return self.mapper.map_(self.owlapi_ontology.getSignature(self._get_imports_enum(include_imports_closure)))
def get_abox_axioms(self, include_imports_closure: bool = True) -> Iterable[OWLAxiom]:
diff --git a/owlapy/owlapi_mapper.py b/owlapy/owlapi_mapper.py
index b72c940b..67ac16f8 100644
--- a/owlapy/owlapi_mapper.py
+++ b/owlapy/owlapi_mapper.py
@@ -2,8 +2,11 @@
from typing import Iterable, TypeVar
import jpype.imports
-from owlapy import owl_expression_to_manchester, manchester_to_owl_expression
-from owlapy.class_expression import OWLClassExpression, OWLDataOneOf, OWLFacetRestriction, OWLDatatypeRestriction
+from owlapy.class_expression import OWLDataOneOf, OWLFacetRestriction, OWLDatatypeRestriction, \
+ OWLClass, OWLObjectComplementOf, OWLObjectUnionOf, OWLObjectIntersectionOf, \
+ OWLObjectHasSelf, OWLObjectHasValue, OWLObjectSomeValuesFrom, OWLObjectAllValuesFrom, OWLObjectMinCardinality, \
+ OWLObjectMaxCardinality, OWLObjectExactCardinality, OWLDataSomeValuesFrom, OWLDataAllValuesFrom, OWLDataHasValue, \
+ OWLDataMinCardinality, OWLDataMaxCardinality, OWLDataExactCardinality, OWLObjectOneOf
from owlapy.iri import IRI
from owlapy.owl_axiom import OWLDeclarationAxiom, OWLAnnotation, OWLAnnotationProperty, OWLClassAssertionAxiom, \
OWLDataPropertyAssertionAxiom, OWLDataPropertyDomainAxiom, OWLDataPropertyRangeAxiom, OWLObjectPropertyDomainAxiom, \
@@ -30,26 +33,18 @@
startJVM()
from org.semanticweb.owlapi.model import IRI as owlapi_IRI, OWLOntologyID as owlapi_OWLOntologyID
from org.semanticweb.owlapi.vocab import OWLFacet as owlapi_OWLFacet
-from org.semanticweb.owlapi.manchestersyntax.parser import ManchesterOWLSyntaxClassExpressionParser
-from org.semanticweb.owlapi.manchestersyntax.renderer import ManchesterOWLSyntaxOWLObjectRendererImpl
-from org.semanticweb.owlapi.util import BidirectionalShortFormProviderAdapter, SimpleShortFormProvider
-from org.semanticweb.owlapi.expression import ShortFormEntityChecker
-from java.util import HashSet, ArrayList, List, Set, LinkedHashSet, Optional
+from java.util import ArrayList, List, Set, LinkedHashSet, Optional
from java.util.stream import Stream
-from uk.ac.manchester.cs.owl.owlapi import (OWLAnonymousClassExpressionImpl, OWLCardinalityRestrictionImpl,
- OWLClassExpressionImpl, OWLClassImpl, OWLDataAllValuesFromImpl,
- OWLDataCardinalityRestrictionImpl, OWLDataExactCardinalityImpl,
- OWLDataHasValueImpl, OWLDataMaxCardinalityImpl, OWLDataUnionOfImpl,
+from uk.ac.manchester.cs.owl.owlapi import (OWLClassImpl, OWLDataAllValuesFromImpl, OWL2DatatypeImpl,
+ OWLDataExactCardinalityImpl,OWLDataHasValueImpl,
+ OWLDataMaxCardinalityImpl, OWLDataUnionOfImpl,
OWLDataMinCardinalityImpl, OWLDataSomeValuesFromImpl,
- OWLNaryBooleanClassExpressionImpl, OWLObjectAllValuesFromImpl,
- OWLObjectCardinalityRestrictionImpl, OWLObjectComplementOfImpl,
+ OWLObjectAllValuesFromImpl, OWLObjectComplementOfImpl,
OWLObjectExactCardinalityImpl, OWLObjectHasSelfImpl,
OWLObjectHasValueImpl, OWLObjectIntersectionOfImpl,
OWLObjectMaxCardinalityImpl, OWLObjectMinCardinalityImpl,
OWLObjectOneOfImpl, OWLObjectSomeValuesFromImpl, OWLNaryDataRangeImpl,
- OWLObjectUnionOfImpl, OWLQuantifiedDataRestrictionImpl,
- OWLQuantifiedObjectRestrictionImpl, OWLQuantifiedRestrictionImpl,
- OWLValueRestrictionImpl, OWLLiteralImplBoolean, OWLLiteralImplString,
+ OWLObjectUnionOfImpl,OWLLiteralImplBoolean, OWLLiteralImplString,
OWLLiteralImplDouble, OWLLiteralImplFloat, OWLLiteralImplInteger,
OWLDisjointClassesAxiomImpl, OWLDeclarationAxiomImpl, OWLAnnotationImpl,
OWLAnnotationPropertyImpl, OWLClassAssertionAxiomImpl,
@@ -80,6 +75,9 @@
def init(the_class):
+ """Since classes names in owlapi and owlapy are pretty much similar with the small difference that in owlapi they
+ usually have the 'Impl' part then we can create the mapping class name dynamically reducing the amount of code
+ significantly. That's what this method does."""
cls_name = the_class.__class__.__name__
if "Impl" in cls_name:
return globals().get(cls_name.split(".")[-1].replace("Impl", ""))
@@ -91,29 +89,7 @@ def init(the_class):
class OWLAPIMapper:
-
- def __init__(self, ontology: _SO):
- self.manager = ontology.manager.get_owlapi_manager()
- self.ontology = ontology.get_owlapi_ontology()
-
- # () Get the name space. (used for rendering class expressions)
- self.namespace = self.ontology.getOntologyID().getOntologyIRI().orElse(None)
- if self.namespace is not None:
- self.namespace = str(self.namespace)
- if self.namespace[-1] not in ["/", "#", ":"]:
- self.namespace += "#"
- else:
- self.namespace = "http://www.anonymous.org/anonymous#"
-
- # () Create a manchester parser and a renderer using the given ontology.
- ontology_set = HashSet()
- 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())
- bidi_provider.add(self.manager.getOWLDataFactory().getOWLThing())
- self.parser = ManchesterOWLSyntaxClassExpressionParser(self.manager.getOWLDataFactory(), entity_checker)
- self.renderer = ManchesterOWLSyntaxOWLObjectRendererImpl()
+ """A bridge between owlapy and owlapi owl-related classes."""
@singledispatchmethod
def map_(self, e):
@@ -140,6 +116,7 @@ def _(self, e: owlapi_IRI):
@map_.register(OWLObjectProperty)
@map_.register(OWLDatatype)
@map_.register(OWLAnnotationProperty)
+ @map_.register(OWLClass)
def _(self, e):
return init(e)(self.map_(e.iri))
@@ -148,45 +125,65 @@ def _(self, e):
@map_.register(OWLObjectPropertyImpl)
@map_.register(OWLDatatypeImpl)
@map_.register(OWLAnnotationPropertyImpl)
+ @map_.register(OWLClassImpl)
def _(self, e):
return init(e)(self.map_(e.getIRI()))
+ @map_.register(OWL2DatatypeImpl)
+ def _(self, e):
+ return OWLDatatype(self.map_(e.getIRI()))
+
@map_.register
- def _(self, e: OWLClassExpression):
- return self.parser.parse(owl_expression_to_manchester(e))
+ def _(self, e: OWLObjectComplementOf):
+ return init(e)(self.map_(e.get_operand()))
- @map_.register(OWLAnonymousClassExpressionImpl)
- @map_.register(OWLCardinalityRestrictionImpl)
- @map_.register(OWLClassExpressionImpl)
- @map_.register(OWLClassImpl)
- @map_.register(OWLDataAllValuesFromImpl)
- @map_.register(OWLDataCardinalityRestrictionImpl)
- @map_.register(OWLDataExactCardinalityImpl)
- @map_.register(OWLDataHasValueImpl)
- @map_.register(OWLDataMaxCardinalityImpl)
- @map_.register(OWLDataMinCardinalityImpl)
- @map_.register(OWLDataSomeValuesFromImpl)
- @map_.register(OWLNaryBooleanClassExpressionImpl)
- @map_.register(OWLObjectAllValuesFromImpl)
- @map_.register(OWLObjectCardinalityRestrictionImpl)
- @map_.register(OWLObjectComplementOfImpl)
+ @map_.register
+ def _(self, e: OWLObjectComplementOfImpl):
+ return init(e)(self.map_(e.getOperand()))
+
+ @map_.register(OWLObjectMinCardinality)
+ @map_.register(OWLObjectMaxCardinality)
+ @map_.register(OWLObjectExactCardinality)
+ @map_.register(OWLDataMinCardinality)
+ @map_.register(OWLDataMaxCardinality)
+ @map_.register(OWLDataExactCardinality)
+ def _(self, e):
+ return init(e)(self.map_(e.get_property()), e.get_cardinality(), self.map_(e.get_filler()))
+
+ @map_.register(OWLObjectMinCardinalityImpl)
+ @map_.register(OWLObjectMaxCardinalityImpl)
@map_.register(OWLObjectExactCardinalityImpl)
+ @map_.register(OWLDataMinCardinalityImpl)
+ @map_.register(OWLDataMaxCardinalityImpl)
+ @map_.register(OWLDataExactCardinalityImpl)
+ def _(self, e):
+ return init(e)(e.getCardinality(), self.map_(e.getProperty()), self.map_(e.getFiller()))
+
+ @map_.register(OWLObjectHasSelf)
+ def _(self, e):
+ return init(e)(self.map_(e.get_property()))
+
@map_.register(OWLObjectHasSelfImpl)
+ def _(self, e):
+ return init(e)(self.map_(e.getProperty()))
+
+ @map_.register(OWLObjectHasValue)
+ @map_.register(OWLObjectSomeValuesFrom)
+ @map_.register(OWLObjectAllValuesFrom)
+ @map_.register(OWLDataSomeValuesFrom)
+ @map_.register(OWLDataAllValuesFrom)
+ @map_.register(OWLDataHasValue)
+ def _(self, e):
+ return init(e)(self.map_(e.get_property()), self.map_(e.get_filler()))
+
@map_.register(OWLObjectHasValueImpl)
- @map_.register(OWLObjectIntersectionOfImpl)
- @map_.register(OWLObjectMaxCardinalityImpl)
- @map_.register(OWLObjectMinCardinalityImpl)
- @map_.register(OWLObjectOneOfImpl)
@map_.register(OWLObjectSomeValuesFromImpl)
- @map_.register(OWLObjectUnionOfImpl)
- @map_.register(OWLQuantifiedDataRestrictionImpl)
- @map_.register(OWLQuantifiedObjectRestrictionImpl)
- @map_.register(OWLQuantifiedRestrictionImpl)
- @map_.register(OWLValueRestrictionImpl)
+ @map_.register(OWLObjectAllValuesFromImpl)
+ @map_.register(OWLDataSomeValuesFromImpl)
+ @map_.register(OWLDataAllValuesFromImpl)
+ @map_.register(OWLDataHasValueImpl)
def _(self, e):
- # Cant recognize the classes as implementation of org.semanticweb.owlapi.model.OWLClassExpression, so we
- # have to register all possible implementations
- return manchester_to_owl_expression(str(self.renderer.render(e)), self.namespace)
+ return init(e)(self.map_(e.getProperty()), self.map_(e.getFiller()))
@map_.register
def _(self, e: OWLLiteral):
@@ -225,6 +222,8 @@ def _(self, e: OWLLiteralImplInteger):
@map_.register(OWLDataOneOf)
@map_.register(OWLDataUnionOf)
@map_.register(OWLNaryDataRange)
+ @map_.register(OWLObjectIntersectionOf)
+ @map_.register(OWLObjectUnionOf)
def _(self, e):
return init(e)(self.map_(e.operands()))
@@ -232,9 +231,16 @@ def _(self, e):
@map_.register(OWLDataOneOfImpl)
@map_.register(OWLDataUnionOfImpl)
@map_.register(OWLNaryDataRangeImpl)
+ @map_.register(OWLObjectIntersectionOfImpl)
+ @map_.register(OWLObjectUnionOfImpl)
+ @map_.register(OWLObjectOneOfImpl)
def _(self, e):
return init(e)(self.map_(e.getOperandsAsList()))
+ @map_.register(OWLObjectOneOf)
+ def _(self, e):
+ return init(e)(self.map_(e.operands()).stream())
+
@map_.register(OWLDataComplementOfImpl)
def _(self, e):
return OWLDataComplementOf(self.map_(e.getDataRange()))
@@ -502,6 +508,7 @@ def _(self, e):
@map_.register(list)
@map_.register(set)
+ @map_.register(frozenset)
def _(self, e):
java_list = ArrayList()
if e is not None and len(e) > 0:
diff --git a/owlapy/render.py b/owlapy/render.py
index 9856c5b7..f6e6543f 100644
--- a/owlapy/render.py
+++ b/owlapy/render.py
@@ -21,9 +21,12 @@
from .class_expression import OWLObjectHasValue, OWLFacetRestriction, OWLDatatypeRestriction, OWLObjectOneOf
from .owl_datatype import OWLDatatype
from .abstracts.abstract_owl_reasoner import AbstractOWLReasoner
+from .owl_axiom import (OWLEquivalentClassesAxiom, OWLSubClassOfAxiom,
+ OWLObjectPropertyRangeAxiom, OWLObjectPropertyDomainAxiom)
import requests
import warnings
import abc
+
_DL_SYNTAX = types.SimpleNamespace(
SUBCLASS="⊑",
EQUIVALENT_TO="≡",
@@ -45,8 +48,7 @@
WEDGE="⋀",
IMPLIES="←",
COMMA=",",
- SELF="Self",
-)
+ SELF="Self")
def _simple_short_form_provider(e: OWLEntity) -> str:
@@ -350,8 +352,8 @@ def _render_nested(self, c: OWLClassExpression) -> str:
COMMA=",",
SELF="Self",
VALUE="value",
-)
-
+ RANGE="Range",
+ DOMAIN="Domain")
class ManchesterOWLSyntaxOWLObjectRenderer(OWLObjectRenderer):
"""Manchester Syntax renderer for OWL Objects"""
@@ -376,7 +378,7 @@ def set_short_form_provider(self, short_form_provider: Callable[[OWLEntity], str
@singledispatchmethod
def render(self, o: OWLObject) -> str:
assert isinstance(o, OWLObject), f"Tried to render non-OWLObject {o} of {type(o)}"
- raise NotImplementedError
+ raise NotImplementedError(f"We cannot render {o}\t{type(o)}")
@render.register
def _(self, o: OWLClass) -> str:
@@ -515,6 +517,29 @@ def _(self, t: OWLDatatype):
def _(self, t: OWLLiteral) -> str:
return t.get_literal()
+ @render.register
+ def _(self, equiv: OWLEquivalentClassesAxiom) -> str:
+ # TODO:CD:Can we assume that the size of equiv will be 2 ?
+ return (" %s " % _MAN_SYNTAX.EQUIVALENT_TO).join([self.render(i) for i in equiv])
+
+ @render.register
+ def _(self, equiv: OWLSubClassOfAxiom) -> str:
+ return (" %s " % _MAN_SYNTAX.SUBCLASS).join([self.render(i) for i in [equiv.sub_class,equiv.super_class]])
+
+ @render.register
+ def _(self, axiom: OWLObjectPropertyRangeAxiom) -> str:
+ # objectPropertyFrame ObjectProperty: IRI Range: annotations description ObjectPropertyRange(T(annotations) IRI T(description))
+ return f"{self.render(axiom.prop)} {_MAN_SYNTAX.RANGE} {self.render(axiom.range)}"
+ @render.register
+ def _(self, axiom: OWLObjectPropertyDomainAxiom) -> str:
+ # objectPropertyFrame ObjectProperty: IRI Domain: annotations description ObjectPropertyDomain(T(annotations) IRI T(description))
+ return f"{self.render(axiom.prop)} {_MAN_SYNTAX.DOMAIN} {self.render(axiom.get_domain())}"
+
+ @render.register
+ def _(self, axiom: OWLObjectPropertyDomainAxiom) -> str:
+ # objectPropertyFrame ObjectProperty: IRI Domain: annotations description ObjectPropertyDomain(T(annotations) IRI T(description))
+ return f"{self.render(axiom.prop)} {_MAN_SYNTAX.DOMAIN} {self.render(axiom.get_domain())}"
+
def _render_operands(self, c: OWLNaryBooleanClassExpression) -> List[str]:
return [self._render_nested(_) for _ in c.operands()]
diff --git a/owlapy/static_funcs.py b/owlapy/static_funcs.py
index 228aa050..39d5a1f7 100644
--- a/owlapy/static_funcs.py
+++ b/owlapy/static_funcs.py
@@ -57,3 +57,12 @@ def stopJVM() -> None:
if jpype.isJVMStarted():
jpype.detachThreadFromJVM()
jpype.shutdownJVM()
+
+def create_ontology(iri,with_owlapi=False):
+ """ A convenient function"""
+ if with_owlapi:
+ from .owl_ontology_manager import SyncOntologyManager
+ return SyncOntologyManager().create_ontology(iri)
+ else:
+ from .owl_ontology_manager import OntologyManager
+ return OntologyManager().create_ontology(iri)
\ No newline at end of file
diff --git a/tests/test_owlapi_adaptor.py b/tests/test_owlapi_adaptor.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/tests/test_owlapi_mapper.py b/tests/test_owlapi_mapper.py
new file mode 100644
index 00000000..9a9796ba
--- /dev/null
+++ b/tests/test_owlapi_mapper.py
@@ -0,0 +1,159 @@
+import unittest
+
+from jpype import JDouble
+
+from owlapy.class_expression import OWLClass, OWLDataSomeValuesFrom, OWLObjectIntersectionOf, OWLObjectComplementOf, \
+ OWLObjectMinCardinality, OWLObjectMaxCardinality, OWLObjectExactCardinality, OWLDataMinCardinality, \
+ OWLDataMaxCardinality, OWLDataExactCardinality, OWLObjectHasSelf, OWLObjectHasValue, OWLObjectSomeValuesFrom, \
+ OWLObjectAllValuesFrom, OWLDataAllValuesFrom, OWLDataHasValue, OWLObjectUnionOf, OWLObjectOneOf, \
+ OWLFacetRestriction, OWLDatatypeRestriction, OWLDataOneOf
+from owlapy.iri import IRI
+from owlapy.owl_axiom import OWLAnnotationProperty, OWLAnnotation, OWLAnnotationAssertionAxiom
+from owlapy.owl_data_ranges import OWLDataIntersectionOf, OWLDataUnionOf, OWLDataComplementOf
+from owlapy.owl_datatype import OWLDatatype
+from owlapy.owl_individual import OWLNamedIndividual
+from owlapy.owl_literal import OWLLiteral, IntegerOWLDatatype, BooleanOWLDatatype, DoubleOWLDatatype
+from owlapy.owl_property import OWLDataProperty, OWLObjectProperty
+from owlapy.owlapi_mapper import OWLAPIMapper
+from owlapy.providers import owl_datatype_min_inclusive_restriction
+from owlapy.vocab import OWLFacet
+
+
+class TestOWLAPIMapper(unittest.TestCase):
+
+ mapper = OWLAPIMapper()
+ test_ns = "http://test_namespace#"
+ i = OWLNamedIndividual(test_ns + "test_i")
+ c = OWLClass(test_ns + "test_c")
+ dp = OWLDataProperty(test_ns + "test_dp")
+ op = OWLObjectProperty(test_ns + "test_op")
+ dt = OWLDatatype(IRI.create(test_ns + "test_dt"))
+ ap = OWLAnnotationProperty(IRI.create(test_ns + "test_ap"))
+
+ def test_random_complex_ce_mapping(self):
+
+ # construct the class expression in owlapy
+ ns = "http://dl-learner.org/mutagenesis#"
+ nitrogen38 = OWLClass(IRI.create(ns, "Nitrogen-38"))
+ charge = OWLDataProperty(IRI.create(ns, "charge"))
+ has_charge_more_than_0_85 = OWLDataSomeValuesFrom(charge, owl_datatype_min_inclusive_restriction(0.85))
+ ce = OWLObjectIntersectionOf([nitrogen38, has_charge_more_than_0_85])
+
+ # construct the class expression in owlapi
+ from org.semanticweb.owlapi.model import IRI as IRIowlapi
+ from org.semanticweb.owlapi.vocab import OWLFacet
+ from uk.ac.manchester.cs.owl.owlapi import OWLDataFactoryImpl
+
+ nitrogenIRI = IRIowlapi.create(ns + "Nitrogen-38")
+ charge_iri = IRIowlapi.create(ns + "charge")
+ data_factory = OWLDataFactoryImpl()
+ nitrogen_class = data_factory.getOWLClass(nitrogenIRI)
+
+ charge_property = data_factory.getOWLDataProperty(charge_iri)
+ double_datatype = data_factory.getDoubleOWLDatatype()
+ facet_restriction = data_factory.getOWLFacetRestriction(OWLFacet.MIN_INCLUSIVE, JDouble(0.85))
+ datatype_restriction = data_factory.getOWLDatatypeRestriction(double_datatype, facet_restriction)
+ some_values_from = data_factory.getOWLDataSomeValuesFrom(charge_property, datatype_restriction)
+
+ class_expression = data_factory.getOWLObjectIntersectionOf(nitrogen_class, some_values_from)
+
+ # compare them with the mapped expression
+ ce_converted = self.mapper.map_(ce)
+ self.assertEqual(class_expression, ce_converted)
+
+ # map back to owlapy and check for equality
+ ce_1 = self.mapper.map_(class_expression)
+ ce_2 = self.mapper.map_(ce_converted)
+
+ self.assertEqual(ce_1, ce_2)
+ self.assertEqual(ce_1, ce)
+ self.assertEqual(ce_2, ce)
+
+ def test_entity_mapping(self):
+
+ iri = IRI.create(self.test_ns + "test")
+
+ self.assertEqual(iri, self.mapper.map_(self.mapper.map_(iri)))
+ self.assertEqual(self.i, self.mapper.map_(self.mapper.map_(self.i)))
+ self.assertEqual(self.c, self.mapper.map_(self.mapper.map_(self.c)))
+ self.assertEqual(self.dp, self.mapper.map_(self.mapper.map_(self.dp)))
+ self.assertEqual(self.op, self.mapper.map_(self.mapper.map_(self.op)))
+ self.assertEqual(self.dt, self.mapper.map_(self.mapper.map_(self.dt)))
+ self.assertEqual(self.ap, self.mapper.map_(self.mapper.map_(self.ap)))
+
+ def test_ce_mapping(self):
+
+ lit = OWLLiteral(2)
+
+ oco = OWLObjectComplementOf(self.c)
+ ominc = OWLObjectMinCardinality(1, self.op, self.c)
+ oec = OWLObjectExactCardinality(2, self.op, self.c)
+ omaxc = OWLObjectMaxCardinality(3, self.op, self.c)
+ dminc = OWLDataMinCardinality(1, self.dp, IntegerOWLDatatype)
+ dec = OWLDataExactCardinality(2, self.dp, IntegerOWLDatatype)
+ dmaxc = OWLDataMaxCardinality(3, self.dp, IntegerOWLDatatype)
+ ohs = OWLObjectHasSelf(self.op)
+ ohv = OWLObjectHasValue(self.op, self.i)
+ osv = OWLObjectSomeValuesFrom(self.op, self.c)
+ oav = OWLObjectAllValuesFrom(self.op, self.c)
+ dsv = OWLDataSomeValuesFrom(self.dp, IntegerOWLDatatype)
+ dav = OWLDataAllValuesFrom(self.dp, IntegerOWLDatatype)
+ dhv = OWLDataHasValue(self.dp, lit)
+ ooo = OWLObjectOneOf(self.i)
+ ooo2 = OWLObjectOneOf([self.i])
+ oio = OWLObjectIntersectionOf([ohs, ohv])
+ ouo = OWLObjectUnionOf([oco, ominc])
+
+ self.assertEqual(lit, self.mapper.map_(self.mapper.map_(lit)))
+ self.assertEqual(oco, self.mapper.map_(self.mapper.map_(oco)))
+ self.assertEqual(ominc, self.mapper.map_(self.mapper.map_(ominc)))
+ self.assertEqual(oec, self.mapper.map_(self.mapper.map_(oec)))
+ self.assertEqual(omaxc, self.mapper.map_(self.mapper.map_(omaxc)))
+ self.assertEqual(dminc, self.mapper.map_(self.mapper.map_(dminc)))
+ self.assertEqual(dec, self.mapper.map_(self.mapper.map_(dec)))
+ self.assertEqual(dmaxc, self.mapper.map_(self.mapper.map_(dmaxc)))
+ self.assertEqual(ohv, self.mapper.map_(self.mapper.map_(ohv)))
+ self.assertEqual(osv, self.mapper.map_(self.mapper.map_(osv)))
+ self.assertEqual(oav, self.mapper.map_(self.mapper.map_(oav)))
+ self.assertEqual(dsv, self.mapper.map_(self.mapper.map_(dsv)))
+ self.assertEqual(dav, self.mapper.map_(self.mapper.map_(dav)))
+ self.assertEqual(dhv, self.mapper.map_(self.mapper.map_(dhv)))
+ self.assertEqual(ooo2, self.mapper.map_(self.mapper.map_(ooo)))
+ self.assertEqual(ooo2, self.mapper.map_(self.mapper.map_(ooo2)))
+ self.assertEqual(oio, self.mapper.map_(self.mapper.map_(oio)))
+ self.assertEqual(ouo, self.mapper.map_(self.mapper.map_(ouo)))
+
+ def test_datarange_mapping(self):
+
+ lit = OWLLiteral(0.1)
+ bdt = BooleanOWLDatatype
+ f = OWLFacet.MAX_EXCLUSIVE
+ fr = OWLFacetRestriction(f, lit)
+ dtr = OWLDatatypeRestriction(DoubleOWLDatatype, fr)
+ dio = OWLDataIntersectionOf([dtr, bdt])
+ doo = OWLDataOneOf([lit, OWLLiteral(True)])
+ duo = OWLDataUnionOf([dtr, DoubleOWLDatatype, IntegerOWLDatatype])
+ dco = OWLDataComplementOf(dtr)
+
+ self.assertEqual(lit, self.mapper.map_(self.mapper.map_(lit)))
+ self.assertEqual(bdt, self.mapper.map_(self.mapper.map_(bdt)))
+ self.assertEqual(f, self.mapper.map_(self.mapper.map_(f)))
+ self.assertEqual(fr, self.mapper.map_(self.mapper.map_(fr)))
+ self.assertEqual(dtr, self.mapper.map_(self.mapper.map_(dtr)))
+ self.assertCountEqual(list(dio.operands()), list(self.mapper.map_(self.mapper.map_(dio)).operands()))
+ self.assertCountEqual(list(doo.operands()), list(self.mapper.map_(self.mapper.map_(doo)).operands()))
+ self.assertCountEqual(list(duo.operands()), list(self.mapper.map_(self.mapper.map_(duo)).operands()))
+ self.assertEqual(dco, self.mapper.map_(self.mapper.map_(dco)))
+
+ def test_axiom_mapping(self):
+
+ ap = OWLAnnotationProperty(IRI.create(self.test_ns + "test_annotation"))
+ av = OWLLiteral("Value of annotation")
+ a = OWLAnnotation(ap, av)
+ aa = OWLAnnotationAssertionAxiom(IRI.create(self.test_ns + "test_annotation_subject"), a)
+
+
+ self.assertEqual(ap, self.mapper.map_(self.mapper.map_(ap)))
+ self.assertEqual(av, self.mapper.map_(self.mapper.map_(av)))
+ self.assertEqual(a, self.mapper.map_(self.mapper.map_(a)))
+ self.assertEqual(aa, self.mapper.map_(self.mapper.map_(aa)))
diff --git a/tests/test_sync_reasoner.py b/tests/test_sync_reasoner.py
index 9b157457..d3ebccbf 100644
--- a/tests/test_sync_reasoner.py
+++ b/tests/test_sync_reasoner.py
@@ -1,7 +1,6 @@
import os
import unittest
-from jpype import JDouble
from owlapy.class_expression import OWLClass, OWLDataSomeValuesFrom, OWLObjectIntersectionOf, OWLNothing, OWLThing, \
OWLClassExpression, OWLObjectSomeValuesFrom, OWLObjectOneOf
from owlapy.iri import IRI
@@ -166,39 +165,6 @@ def test_instances_retrieval(self):
self.assertIn(instance, expected)
self.assertEqual(len(list(instances)), len(expected))
- def test_conversion(self):
- # construct the class expression in owlapi
- from org.semanticweb.owlapi.model import IRI as IRIowlapi
- from org.semanticweb.owlapi.vocab import OWLFacet
-
- nitrogenIRI = IRIowlapi.create(self.ns + "Nitrogen-38")
- charge_iri = IRIowlapi.create(self.ns + "charge")
-
- data_factory = self.reasoner.manager.get_owlapi_manager().getOWLDataFactory()
- nitrogen_class = data_factory.getOWLClass(nitrogenIRI)
-
- charge_property = data_factory.getOWLDataProperty(charge_iri)
- double_datatype = data_factory.getDoubleOWLDatatype()
- facet_restriction = data_factory.getOWLFacetRestriction(OWLFacet.MIN_INCLUSIVE, JDouble(0.85))
- datatype_restriction = data_factory.getOWLDatatypeRestriction(double_datatype, facet_restriction)
- some_values_from = data_factory.getOWLDataSomeValuesFrom(charge_property, datatype_restriction)
-
- class_expression = data_factory.getOWLObjectIntersectionOf(nitrogen_class, some_values_from)
-
- # compare them with the converted expression
- ce_converted = self.reasoner.mapper.map_(self.ce)
- print(ce_converted)
- print(class_expression)
- self.assertEqual(class_expression, ce_converted)
-
- # convert back to owlapy and check for equality
- ce_1 = self.reasoner.mapper.map_(class_expression)
- ce_2 = self.reasoner.mapper.map_(ce_converted)
-
- self.assertEqual(ce_1, ce_2)
- self.assertEqual(ce_1, self.ce)
- self.assertEqual(ce_2, self.ce)
-
def test_equivalent_classes(self):
self.assertCountEqual(list(reasoner2.equivalent_classes(N)), [N, Q])