Skip to content

Commit

Permalink
fix validate_profiles, test import tree
Browse files Browse the repository at this point in the history
  • Loading branch information
muddymudskipper committed Aug 28, 2024
1 parent b66fbd6 commit e3517c7
Show file tree
Hide file tree
Showing 12 changed files with 128 additions and 176 deletions.
8 changes: 6 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,16 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p

- Validate: added "mode" parameter

### Fixed

- respect owl:imports in OWL2 profile validation

### Changed

- Validate: the entity output includes the reasoner option on path "reason"
- Detailed axiom generator documentation
- The axiom generator ObjectPropertyCharacteristic does not yield results possibly due to a bug in the OWL API. Currently,
this axiom generator and its (working) counterpart DataPropertyCharacteristic are removed from the Reason plugin.
- The axiom generator ObjectPropertyCharacteristic does not yield results. Currently, this axiom generator and its
- (working) counterpart DataPropertyCharacteristic are removed from the Reason plugin.

## [1.0.0beta5] 2024-08-15

Expand Down
115 changes: 0 additions & 115 deletions cmem_plugin_reason/plugin_reason.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,121 +37,6 @@

REASONER_PARAMETER.description += " Select axiom generators below [Click (?) for documentation]."

#
# SUBCLASS_DESC = """The reasoner will infer assertions about the hierarchy of classes, i.e.
# `SubClassOf:` statements.
#
# If there are classes `Person`, `Student` and `Professor`, such that `Person DisjointUnionOf:
# Student, Professor` holds, the reasoner will infer `Student SubClassOf: Person`.
# """
#
# EQUIVALENCE_DESC = """The reasoner will infer assertions about the equivalence of classes, i.e.
# `EquivalentTo:` statements.
#
# If there are classes `Person`, `Student` and `Professor`, such that `Person DisjointUnionOf:
# Student, Professor` holds, the reasoner will infer `Person EquivalentTo: Student and Professor`.
# """
#
# DISJOINT_DESC = """The reasoner will infer assertions about the disjointness of classes, i.e.
# `DisjointClasses:` statements.
#
# If there are classes `Person`, `Student` and `Professor`, such that `Person DisjointUnionOf:
# Student, Professor` holds, the reasoner will infer `DisjointClasses: Student, Professor`.
# """
#
# # DATA_PROP_CHAR_DESC = """The reasoner will infer characteristics of data properties, i.e.
# # `Characteristics:` statements. For data properties, this only pertains to functionality.
# #
# # If there are data properties `identifier` and `enrollmentNumber`, such that `enrollmentNumber
# # SubPropertyOf: identifier` and `identifier Characteristics: Functional` holds, the reasoner will
# # infer `enrollmentNumber Characteristics: Functional`.
# # """
#
# DATA_PROP_EQUIV_DESC = """The reasoner will infer axioms about the equivalence of data properties,
# i.e. `EquivalentProperties` statements.
#
# If there are data properties `identifier` and `enrollmentNumber`, such that `enrollmentNumber
# SubPropertyOf: identifier` and `identifier SubPropertyOf: enrollmentNumber` holds, the reasoner
# will infer `Student EquivalentProperties: identifier, enrollmentNumber`.
# """
#
# DATA_PROP_SUB_DESC = """The reasoner will infer axioms about the hierarchy of data properties,
# i.e. `SubPropertyOf:` statements.
#
# If there are data properties `identifier`, `studentIdentifier` and `enrollmentNumber`, such that
# `studentIdentifier SubPropertyOf: identifier` and `enrollmentNumber SubPropertyOf:
# studentIdentifier` holds, the reasoner will infer `enrollmentNumber SubPropertyOf: identifier`.
# """
#
# CLASS_ASSERT_DESC = """The reasoner will infer assertions about the classes of individuals, i.e.
# `Types:` statements.
#
# Assume, there are classes `Person`, `Student` and `University` as well as the property
# `enrolledIn`, such that `Student EquivalentTo: Person and enrolledIn some University` holds. For
# the individual `John` with the assertions `John Types: Person; Facts: enrolledIn
# LeipzigUniversity`, the reasoner will infer `John Types: Student`.
# """
#
# PROPERTY_ASSERT_DESC = """The reasoner will infer assertions about the properties of individuals,
# i.e. `Facts:` statements.
#
# Assume, there are properties `enrolledIn` and `offers`, such that `enrolled SubPropertyChain:
# enrolledIn o inverse (offers)` holds. For the individuals `John`and `LeipzigUniversity` with the
# assertions `John Facts: enrolledIn KnowledgeRepresentation` and `LeipzigUniversity Facts: offers
# KnowledgeRepresentation`, the reasoner will infer `John Facts: enrolledIn LeipzigUniversity`.
# """
#
# # OBJECT_PROP_CHAR_DESC = """The reasoner will infer characteristics of object properties, i.e.
# # `Characteristics:` statements.
# #
# # If there are object properties `enrolledIn` and `studentOf`, such that `enrolledIn
# # SubPropertyOf: studentOf` and `enrolledIn Characteristics: Functional` holds, the reasoner will
# # infer `studentOf Characteristics: Functional`. **Note: this inference does neither work in JFact
# # nor in HermiT!**
# # """
#
# OBJECT_PROP_EQUIV_DESC = """The reasoner will infer assertions about the equivalence of object
# properties, i.e. `EquivalentTo:` statements.
#
# If there are object properties `hasAlternativeLecture` and `hasSameTopicAs`, such that
# `hasAlternativeLecture Characteristics: Symmetric` and `hasSameTopicAs InverseOf:
# hasAlternativeLecture` holds, the reasoner will infer `EquivalentProperties:
# hasAlternativeLecture, hasSameTopicAs`.
# """
#
# OBJECT_PROP_SUB_DESC = """The reasoner will infer axioms about the inclusion of object properties,
# i.e. `SubPropertyOf:` statements.
#
# If there are object properties `enrolledIn`, `studentOf` and `hasStudent`, such that `enrolledIn
# SubPropertyOf: studentOf` and `enrolledIn InverseOf: hasStudent` holds, the reasoner will infer
# `hasStudent SubPropertyOf: inverse (studentOf)`.
# """
#
# OBJECT_PROP_INV_DESC = """The reasoner will infer axioms about the inversion about object
# properties, i.e. `InverseOf:` statements.
#
# If there is a object property `hasAlternativeLecture`, such that `hasAlternativeLecture
# Characteristics: Symmetric` holds, the reasoner will infer `hasAlternativeLecture InverseOf:
# hasAlternativeLecture`.
# """
#
# OBJECT_PROP_RANGE_DESC = """The reasoner will infer axioms about the ranges of object properties,
# i.e. `Range:` statements.
#
# If there are classes `Student` and `Lecture` as wells as object properties `hasStudent` and
# `enrolledIn`, such that `hasStudent Range: Student and enrolledIn some Lecture` holds, the
# reasoner will infer `hasStudent Range: Student`.
# """
#
# OBJECT_PROP_DOMAIN_DESC = """The reasoner will infer axioms about the domains of object
# properties, i.e. `Domain:` statements.
#
# If there are classes `Person`, `Student` and `Professor` as wells as the object property
# `hasRoleIn`, such that `Professor SubClassOf: Person`, `Student SubClassOf: Person` and
# `hasRoleIn Domain: Professor or Student` holds, the reasoner will infer `hasRoleIn Domain:
# Person`.
# """


@Plugin(
label="Reason",
Expand Down
2 changes: 1 addition & 1 deletion cmem_plugin_reason/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ def validate_profiles(plugin: WorkflowPlugin, graphs: dict) -> list:
valid_profiles = []
for profile in ("Full", "DL", "EL", "QL", "RL"):
plugin.log.info(f"Validating {profile} profile.")
cmd = f"validate-profile --profile {profile} --input {ontology_location}"
cmd = f"merge --input {ontology_location} validate-profile --profile {profile}"
response = robot(cmd, plugin.max_ram_percentage)
if response.stdout.endswith(b"[Ontology and imports closure in profile]\n\n"):
valid_profiles.append(profile)
Expand Down
24 changes: 14 additions & 10 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

48 changes: 30 additions & 18 deletions tests/test_reason.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,13 @@

UID = "e02aaed014c94e0c91bf960fed127750"
REASON_DATA_GRAPH_IRI = f"https://ns.eccenca.com/reasoning/{UID}/data/"
REASON_ONTOLOGY_GRAPH_IRI = f"https://ns.eccenca.com/reasoning/{UID}/vocab/"
REASON_ONTOLOGY_GRAPH_IRI_1 = f"https://ns.eccenca.com/reasoning/{UID}/vocab/"
REASON_ONTOLOGY_GRAPH_IRI_2 = f"https://ns.eccenca.com/reasoning/{UID}/vocab2/"
REASON_ONTOLOGY_GRAPH_IRI_3 = f"https://ns.eccenca.com/reasoning/{UID}/vocab3/"
REASON_RESULT_GRAPH_IRI = f"https://ns.eccenca.com/reasoning/{UID}/result/"
VALIDATE_ONTOLOGY_GRAPH_IRI = f"https://ns.eccenca.com/validateontology/{UID}/vocab/"
VALIDATE_ONTOLOGY_GRAPH_IRI_1 = f"https://ns.eccenca.com/validateontology/{UID}/vocab/"
VALIDATE_ONTOLOGY_GRAPH_IRI_2 = f"https://ns.eccenca.com/validateontology/{UID}/vocab2/"
VALIDATE_ONTOLOGY_GRAPH_IRI_3 = f"https://ns.eccenca.com/validateontology/{UID}/vocab3/"
OUTPUT_GRAPH_IRI = f"https://ns.eccenca.com/validateontology/{UID}/output/"
MD_FILENAME = f"{UID}.md"
PROJECT_ID = f"validate_plugin_test_project_{UID}"
Expand All @@ -37,31 +41,39 @@ def get_value_dict(entities: Entities) -> dict:
return value_dict


def import_graph(iri: str, filename: str) -> None:
"""Import graph to CMEM"""
res = post(iri, Path(__path__[0]) / filename, replace=True)
if res.status_code != 204: # noqa: PLR2004
raise ValueError(f"Response {res.status_code}: {res.url}")


@pytest.fixture()
def _setup(request: pytest.FixtureRequest) -> None:
"""Set up"""
res = post(REASON_DATA_GRAPH_IRI, Path(__path__[0]) / "dataset_owl.ttl", replace=True)
if res.status_code != 204: # noqa: PLR2004
raise ValueError(f"Response {res.status_code}: {res.url}")
res = post(REASON_ONTOLOGY_GRAPH_IRI, Path(__path__[0]) / "vocab.ttl", replace=True)
if res.status_code != 204: # noqa: PLR2004
raise ValueError(f"Response {res.status_code}: {res.url}")
import_graph(REASON_DATA_GRAPH_IRI, "dataset_owl.ttl")
import_graph(REASON_ONTOLOGY_GRAPH_IRI_1, "test_reason_ontology_1.ttl")
import_graph(REASON_ONTOLOGY_GRAPH_IRI_2, "test_reason_ontology_2.ttl")
import_graph(REASON_ONTOLOGY_GRAPH_IRI_3, "test_reason_ontology_3.ttl")

with suppress(Exception):
delete_project(PROJECT_ID)
make_new_project(PROJECT_ID)
res = post(
VALIDATE_ONTOLOGY_GRAPH_IRI, Path(__path__[0]) / "test_validate_ontology.ttl", replace=True
)
if res.status_code != 204: # noqa: PLR2004
raise ValueError(f"Response {res.status_code}: {res.url}")

import_graph(VALIDATE_ONTOLOGY_GRAPH_IRI_1, "test_validate_ontology_1.ttl")
import_graph(VALIDATE_ONTOLOGY_GRAPH_IRI_2, "test_validate_ontology_2.ttl")
import_graph(VALIDATE_ONTOLOGY_GRAPH_IRI_3, "test_validate_ontology_3.ttl")

request.addfinalizer(lambda: delete(REASON_DATA_GRAPH_IRI))
request.addfinalizer(lambda: delete(REASON_ONTOLOGY_GRAPH_IRI))
request.addfinalizer(lambda: delete(REASON_ONTOLOGY_GRAPH_IRI_1))
request.addfinalizer(lambda: delete(REASON_ONTOLOGY_GRAPH_IRI_2))
request.addfinalizer(lambda: delete(REASON_ONTOLOGY_GRAPH_IRI_3))
request.addfinalizer(lambda: delete(REASON_RESULT_GRAPH_IRI))
request.addfinalizer(lambda: delete_project(PROJECT_ID))
request.addfinalizer(lambda: delete(OUTPUT_GRAPH_IRI))
request.addfinalizer(lambda: delete(VALIDATE_ONTOLOGY_GRAPH_IRI)) # noqa: PT021
request.addfinalizer(lambda: delete(VALIDATE_ONTOLOGY_GRAPH_IRI_1))
request.addfinalizer(lambda: delete(VALIDATE_ONTOLOGY_GRAPH_IRI_2))
request.addfinalizer(lambda: delete(VALIDATE_ONTOLOGY_GRAPH_IRI_3)) # noqa: PT021


@needs_cmem
Expand All @@ -81,7 +93,7 @@ def get_remote_graph(iri: str) -> Graph:
def test_reasoner(reasoner: str, err_list: list) -> list:
ReasonPlugin(
data_graph_iri=REASON_DATA_GRAPH_IRI,
ontology_graph_iri=REASON_ONTOLOGY_GRAPH_IRI,
ontology_graph_iri=REASON_ONTOLOGY_GRAPH_IRI_1,
output_graph_iri=REASON_RESULT_GRAPH_IRI,
reasoner=reasoner,
sub_class=False,
Expand All @@ -99,7 +111,7 @@ def test_reasoner(reasoner: str, err_list: list) -> list:

def test_validate(errors: str) -> str:
result = ValidatePlugin(
ontology_graph_iri=VALIDATE_ONTOLOGY_GRAPH_IRI,
ontology_graph_iri=VALIDATE_ONTOLOGY_GRAPH_IRI_1,
output_graph_iri=OUTPUT_GRAPH_IRI,
reasoner="elk",
validate_profile=True,
Expand All @@ -116,7 +128,7 @@ def test_validate(errors: str) -> str:

if value_dict["markdown"] != md_test:
val_errors += 'EntityPath "markdown" output error. '
if value_dict["ontology_graph_iri"] != VALIDATE_ONTOLOGY_GRAPH_IRI:
if value_dict["ontology_graph_iri"] != VALIDATE_ONTOLOGY_GRAPH_IRI_1:
val_errors += 'EntityPath "ontology_graph_iri" output error. '
if value_dict["reasoner"] != "elk":
val_errors += 'EntityPath "reasoner" output error. '
Expand Down
26 changes: 2 additions & 24 deletions tests/vocab.ttl → tests/test_reason_ontology_1.ttl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
<https://ns.eccenca.com/reasoning/e02aaed014c94e0c91bf960fed127750/vocab/> rdf:type owl:Ontology ;
rdfs:comment "Vocabulary for a reasoning use case"@en ;
rdfs:label "Eccenca Reasoning Vocabulary"@en ;
rdfs:seeAlso <http://owl.man.ac.uk/2006/07/sssw/people> .
rdfs:seeAlso <http://owl.man.ac.uk/2006/07/sssw/people> ;
owl:imports <https://ns.eccenca.com/reasoning/e02aaed014c94e0c91bf960fed127750/vocab2/> .

#################################################################
# Object Properties
Expand Down Expand Up @@ -141,16 +142,6 @@ owl:Thing rdf:type owl:Class .
rdfs:label "adult"^^xsd:string .


### https://ns.eccenca.com/reasoning/e02aaed014c94e0c91bf960fed127750/vocab/animal
:animal rdf:type owl:Class ;
rdfs:subClassOf [ rdf:type owl:Restriction ;
owl:onProperty :eats ;
owl:someValuesFrom owl:Thing
] ;
rdfs:comment ""^^xsd:string ;
rdfs:isDefinedBy <https://ns.eccenca.com/reasoning/e02aaed014c94e0c91bf960fed127750/vocab/> ;
rdfs:label "animal"^^xsd:string .


### https://ns.eccenca.com/reasoning/e02aaed014c94e0c91bf960fed127750/vocab/animal_lover
:animal_lover rdf:type owl:Class ;
Expand Down Expand Up @@ -261,19 +252,6 @@ owl:Thing rdf:type owl:Class .
rdfs:label "cat liker"^^xsd:string .


### https://ns.eccenca.com/reasoning/e02aaed014c94e0c91bf960fed127750/vocab/cat_owner
:cat_owner rdf:type owl:Class ;
owl:equivalentClass [ owl:intersectionOf ( :person
[ rdf:type owl:Restriction ;
owl:onProperty :has_pet ;
owl:someValuesFrom :cat
]
) ;
rdf:type owl:Class
] ;
rdfs:comment ""^^xsd:string ;
rdfs:isDefinedBy <https://ns.eccenca.com/reasoning/e02aaed014c94e0c91bf960fed127750/vocab/> ;
rdfs:label "cat owner"^^xsd:string .


### https://ns.eccenca.com/reasoning/e02aaed014c94e0c91bf960fed127750/vocab/company
Expand Down
Loading

0 comments on commit e3517c7

Please sign in to comment.