I try to understand the
rector-normalization-technique for ontologies in detail.
The article recommends to have a asserted single inheritance structure and introduce multiple inheritance by inference. As example it uses classes as `Protein`, `Insulin`, and `Protein_Hormone`, `Hormone_Role`.
Asserted facts:
- `Insulin` `is_subclass_of` `Protein`
- `Insulin` `plays_role` `Hormone_Role`
- `Protein_Hormone` is equivalent to (`Protein` `and` `plays_role` `owl:someValuesFrom` `Hormone_Role`) (defined class)
After the reasoner ran, `Insulin` is correctly recognized as subclass of `Protein_Hormone` (expected result).
However, `Insulin` is still also classified as
direct subclass of protein. This relation I deem redundant because every instance of `Protein_Hormone` must be a `Protein` by definition. Also, if I apply Protegé, the inferred class structure does not contain this redundant relation, as shown here:
Is there a (canonical) way to get rid of this superfluous subclass relation?
Code for this problem (see also
this notebook for outputs):
```python
import owlready2 as owl2
# rme: rector-modularization-example
onto = owl2.get_ontology("
https://w3id.org/yet/undefined/rme#")
with onto:
class Protein(owl2.Thing):
pass
class Insulin(Protein):
pass
class Hormone_Role(owl2.Thing):
pass
class plays_role(owl2.ObjectProperty):
pass
class Protein_Hormone(owl2.Thing):
equivalent_to = [Protein & plays_role.some(Hormone_Role)]
Insulin.is_a.append(plays_role.some(Hormone_Role))
# before reasoning
print(list(Protein.subclasses()))
owl2.sync_reasoner_hermit(infer_property_values=True, debug=1)
# after reasoning
print(list(Protein.subclasses()))
```