Skip to content

Commit

Permalink
Merge pull request #111 from dice-group/adding_static_funcs
Browse files Browse the repository at this point in the history
Refactoring
  • Loading branch information
Demirrr authored Nov 22, 2024
2 parents a82f76f + 4382e3c commit 9a613ab
Show file tree
Hide file tree
Showing 12 changed files with 355 additions and 150 deletions.
1 change: 1 addition & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -148,4 +148,4 @@ cython_debug/
.vscode/

# Project related files
/KGs/
KGs/
64 changes: 31 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,29 +30,6 @@ pytest -p no:warnings -x # Running 147 tests ~ 35 secs

## Examples

### Sklearn to OWL Ontology

<details><summary> Click me! </summary>

```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

```

</details>


### Exploring OWL Ontology

<details><summary> Click me! </summary>
Expand Down Expand Up @@ -101,7 +78,8 @@ for axiom in onto.get_abox_axioms():

</details>

### Creating OWL Class Expressions
### OWL Knowledge Engineering

<details><summary> Click me! </summary>

```python
Expand All @@ -111,31 +89,27 @@ 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")
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 <http://example.com/society#hasChild> ?s_1 . ?s_1 a <http://example.com/society#male> . ?x a <http://example.com/society#teacher> . } }

# 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
Expand Down Expand Up @@ -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

<details><summary> Click me! </summary>

```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

```

</details>


## How to cite
Currently, we are working on our manuscript describing our framework.
40 changes: 32 additions & 8 deletions owlapy/class_expression/restriction.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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__ = ()

Expand Down Expand Up @@ -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)
Expand All @@ -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))

Expand Down Expand Up @@ -342,7 +345,6 @@ def __eq__(self, other):
else:
return False


def __hash__(self):
return hash(("OWLObjectHasSelf", self._property))

Expand Down Expand Up @@ -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})'

Expand Down Expand Up @@ -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
Expand All @@ -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())})"
Expand All @@ -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
Expand All @@ -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:
Expand All @@ -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:
Expand All @@ -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:
Expand Down Expand Up @@ -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.
Expand All @@ -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))

Expand All @@ -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.
Expand All @@ -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))

Expand All @@ -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.
Expand All @@ -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.
Expand Down Expand Up @@ -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})'

Expand All @@ -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.
Expand Down Expand Up @@ -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,
Expand All @@ -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))

Expand Down Expand Up @@ -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)})'
Expand Down
15 changes: 15 additions & 0 deletions owlapy/owl_axiom.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down
Loading

0 comments on commit 9a613ab

Please sign in to comment.