diff --git a/ontoScorer/ontology.py b/ontoScorer/ontology.py index 64fff47fa08783330a5122f9036f8f7a3ea0edf6..8da24eacede59b70cd1bd0755ede371f7f5a778e 100644 --- a/ontoScorer/ontology.py +++ b/ontoScorer/ontology.py @@ -14,7 +14,22 @@ from rdflib import URIRef, BNode from rdflib.namespace import split_uri from ontology_metadata import Metadata -from ontology_entity import Entity, NamedEntity, BlankEntity + +from ontoScorer.ontology_entity import (Entity, + NamedEntity, + BlankEntity) + +from ontoScorer.ontology_taxonomic_relations import (SubclassOfRelation, + SubpropertyOfRelation, + InstanceOfRelation) + +from ontoScorer.ontology_nontaxonomic_relations import (ObjectPropertyRelation, + DataPropertyRelation) + +from ontoScorer.ontology_axioms import (Axiom, + RestrictionAxiom, + SomeValuesFromRestrictionAxiom) + #============================================================================== # Class: Ontology @@ -73,6 +88,7 @@ class Ontology: annotations.add(str(o)) return annotations + #-------------------------------------------------------------------------- # Entity Extraction #-------------------------------------------------------------------------- @@ -103,20 +119,96 @@ class Ontology: return list(set(individuals)) # Ensuring uniqueness + #-------------------------------------------------------------------------- # Taxonomic Relation Extraction (Hierarchical Structure) #-------------------------------------------------------------------------- + def get_subclass_relations(self): + relations = [] + for s, _, o in self.graph.triples((None, RDFS.subClassOf, None)): + relations.append(SubclassOfRelation(s, o, self.graph)) + return relations + + def get_subproperty_relations(self): + relations = [] + for s, _, o in self.graph.triples((None, RDFS.subPropertyOf, None)): + relations.append(SubpropertyOfRelation(s, o, self.graph)) + return relations + + def get_instance_relations(self): + relations = [] + for s, _, o in self.graph.triples((None, RDF.type, None)): + # Filter out the RDF schema and ontology types to get only the actual instances + if o not in [RDF.Property, RDFS.Class, OWL.Class, OWL.ObjectProperty, OWL.DatatypeProperty]: + relations.append(InstanceOfRelation(s, o, self.graph)) + return relations + def get_taxonomic_relations(self): - return [] + return self.get_subclass_relations() + self.get_subproperty_relations() + self.get_instance_relations() + #-------------------------------------------------------------------------- # Non-Taxonomic Relation Extraction #-------------------------------------------------------------------------- + + def get_object_property_relations(self): + """Extract all object property relations which aren't taxonomically classified.""" + relations = [] + object_properties = {prop.reference for prop in self.get_object_properties()} + + for prop in object_properties: + for s, _, o in self.graph.triples((None, prop, None)): + relation = ObjectPropertyRelation(s, prop, o, self.graph) + relations.append(relation) + + return relations + + def get_data_property_relations(self): + """Extract all data property relations which aren't taxonomically classified.""" + relations = [] + data_properties = {prop.reference for prop in self.get_data_properties()} + + for prop in data_properties: + for s, _, o in self.graph.triples((None, prop, None)): + relation = DataPropertyRelation(s, prop, o, self.graph) + relations.append(relation) + + return relations + + def get_non_taxonomic_relations(self): + """Combine object and data property relations to get all non-taxonomic relations.""" + return self.get_object_property_relations() + self.get_data_property_relations() - def get_restrictions(self): - """Extract all restrictons from the ontology.""" - return self._get_elements_of_type(OWL.Restriction) + + + #-------------------------------------------------------------------------- + # Axioms Extraction + #-------------------------------------------------------------------------- + + # def get_restrictions(self): + # """Extract all restrictons from the ontology.""" + # return self._get_elements_of_type(OWL.Restriction) + + def get_some_values_from_restrictions(self): + axioms = [] + + for restriction, _, some_values_from in self.graph.triples((None, OWL.someValuesFrom, None)): + parent_classes = [s for s, p, o in self.graph.triples((None, RDFS.subClassOf, restriction))] + + on_property = self.graph.value(subject=restriction, predicate=OWL.onProperty) + if on_property: + for parent_class in parent_classes: + axiom = SomeValuesFromRestrictionAxiom(parent_class, restriction, on_property, some_values_from) + axioms.append(axiom) + + return axioms + + + def get_axioms(self): + """Extract all axioms from the ontology.""" + return self.get_some_values_from_restrictions() + #-------------------------------------------------------------------------- # Comparison Method(s) @@ -125,14 +217,7 @@ class Ontology: @staticmethod def compare_entity_names(entity1, entity2): return entity1.name() == entity2.name() - - - def compare_to(self, other_ontology) -> tuple: - """Compare classes of the current ontology with another.""" - self_classes = {c.name() for c in self.classes} - other_classes = {c.name() for c in other_ontology.classes} - - unique_to_self = self_classes - other_classes - unique_to_other = other_classes - self_classes - - return unique_to_self, unique_to_other + + @staticmethod + def compare_relations(relation1, relation2): + return relation1.compare_relation(relation2) \ No newline at end of file diff --git a/ontoScorer/ontology_axioms.py b/ontoScorer/ontology_axioms.py index f09efd25e3d7d4b54993664842dbcd3838050db3..e3019179545d67b280fb37e9de2730aaf14c56a9 100644 --- a/ontoScorer/ontology_axioms.py +++ b/ontoScorer/ontology_axioms.py @@ -19,21 +19,32 @@ class Axiom: # Restriction Axioms #-------------------------------------------------------------------------- class RestrictionAxiom(Axiom): - def __init__(self, restriction_node: (URIRef, BNode)): + def __init__(self, parent_class: (URIRef, BNode), restriction_node: (URIRef, BNode)): + self.parent_class = parent_class self.restriction_node = restriction_node def __str__(self): - return f"Restriction on: {self.restriction_node}" - + return f"Restriction on class: {self.parent_class} with node: {self.restriction_node}" + class SomeValuesFromRestrictionAxiom(RestrictionAxiom): - def __init__(self, restriction_node: (URIRef, BNode), on_property: URIRef, some_values_from: (URIRef, BNode)): - super().__init__(restriction_node) + def __init__(self, parent_class: (URIRef, BNode), restriction_node: (URIRef, BNode), on_property: URIRef, some_values_from: (URIRef, BNode)): + super().__init__(parent_class, restriction_node) self.on_property = on_property self.some_values_from = some_values_from def __str__(self): - return f"Restriction on: {self.restriction_node} via property: {self.on_property} with some values from: {self.some_values_from}" + return f"Restriction on class: {self.parent_class} with node: {self.restriction_node} via property: {self.on_property} with some values from: {self.some_values_from}" + + +# class SomeValuesFromRestrictionAxiom(RestrictionAxiom): +# def __init__(self, restriction_node: (URIRef, BNode), on_property: URIRef, some_values_from: (URIRef, BNode)): +# super().__init__(restriction_node) +# self.on_property = on_property +# self.some_values_from = some_values_from + +# def __str__(self): +# return f"Restriction on: {self.restriction_node} via property: {self.on_property} with some values from: {self.some_values_from}" # There are different kinds of restriction axioms, e.g., someValueFrom, allValuesFrom, etc. diff --git a/ontoScorer/ontology_entity.py b/ontoScorer/ontology_entity.py index 2b2ae8e1066c1d7f44ae0f884d612f5f3980d73f..c75c78970012357b619e442375131607db54899a 100644 --- a/ontoScorer/ontology_entity.py +++ b/ontoScorer/ontology_entity.py @@ -18,7 +18,10 @@ class Entity: def properties(self): """Retrieve properties associated with the entity.""" - return list(self.graph.predicate_objects(subject=self.reference)) + result_list = [] + if self.graph is not None: + result_list = list(self.graph.predicate_objects(subject=self.reference)) + return result_list def name(self): raise NotImplementedError("The method name() must be implemented by subclasses.") diff --git a/ontoScorer/ontology_nontaxonomic_relations.py b/ontoScorer/ontology_nontaxonomic_relations.py index 874ca7225478bd94954d50e04bf12ebd8dc1aae8..ea6c1a6c0d2eaeb537a276981c5c0bf4353f270b 100644 --- a/ontoScorer/ontology_nontaxonomic_relations.py +++ b/ontoScorer/ontology_nontaxonomic_relations.py @@ -14,20 +14,44 @@ from rdflib import URIRef # Base Class for Non-Taxonomic Relations #-------------------------------------------------------------------------- class NonTaxonomicRelation: - def __init__(self, source, target, graph): + def __init__(self, source, property, target, graph): """ Initialize a non-taxonomic relation between source and target entities. :param source: The starting entity (typically class or property). + :param property: The relationship property between the source and target. :param target: The target entity (typically class or datatype). :param graph: The RDF graph from which the relation is extracted. """ self.source = source + self.property = property self.target = target self.graph = graph + def compare_relation(self, other_relation): + """ + Compare this relation to another relation. + + :param other_relation: The other NonTaxonomicRelation object to compare with. + :return: True if they represent the same relation, False otherwise. + """ + return ( + self.source == other_relation.source and + self.property == other_relation.property and + self.target == other_relation.target + ) + + def __eq__(self, other): + if isinstance(other, NonTaxonomicRelation): + return self.compare_relation(other) + return False + + def __hash__(self): + return hash((self.source, self.property, self.target)) + def __str__(self): - return f"{self.source} -> {self.target}" + return f"({self.source}, {self.property}, {self.target})" + #-------------------------------------------------------------------------- # Object and Data Property Relations @@ -35,12 +59,13 @@ class NonTaxonomicRelation: class ObjectPropertyRelation(NonTaxonomicRelation): """Represents an 'object property' relation.""" def __str__(self): - return f"{self.source} has object property {self.target}" + return super().__str__() class DataPropertyRelation(NonTaxonomicRelation): """Represents a 'data property' relation.""" def __str__(self): - return f"{self.source} has data property {self.target}" + return super().__str__() + #-------------------------------------------------------------------------- # Domain and Range Relations @@ -48,11 +73,12 @@ class DataPropertyRelation(NonTaxonomicRelation): class DomainRelation(NonTaxonomicRelation): """Represents a 'domain' relation.""" def __str__(self): - return f"{self.source} has domain {self.target}" + return super().__str__() class RangeRelation(NonTaxonomicRelation): """Represents a 'range' relation.""" def __str__(self): - return f"{self.source} has range {self.target}" + return super().__str__() + # Additional relations (like subproperties, inverse properties, etc.) can be added below as needed. diff --git a/ontoScorer/ontology_taxonomic_relations.py b/ontoScorer/ontology_taxonomic_relations.py index a8177eff188cbce431802f67d206aaceca17d818..eaa35800ae259d2be6930d732e89c5f947ba3aed 100644 --- a/ontoScorer/ontology_taxonomic_relations.py +++ b/ontoScorer/ontology_taxonomic_relations.py @@ -26,16 +26,37 @@ class TaxonomicRelation: self.target = target self.graph = graph + def compare_relation(self, other_relation): + """ + Compare this relation to another relation. + + :param other_relation: The other TaxonomicRelation object to compare with. + :return: True if they represent the same relation, False otherwise. + """ + return ( + self.source == other_relation.source and + self.target == other_relation.target + ) + + def __eq__(self, other): + if isinstance(other, TaxonomicRelation): + return self.compare_relation(other) + return False + + def __hash__(self): + return hash((self.source, self.target)) + def __str__(self): return f"{self.source} -> {self.target}" + #-------------------------------------------------------------------------- # Subclass Relations #-------------------------------------------------------------------------- class SubclassOfRelation(TaxonomicRelation): """Represents a 'subclass of' relation.""" def __str__(self): - return f"{self.source} is a subclass of {self.target}" + return f"({self.source}, subClassOf, {self.target})" #-------------------------------------------------------------------------- # Subproperty Relations @@ -43,7 +64,7 @@ class SubclassOfRelation(TaxonomicRelation): class SubpropertyOfRelation(TaxonomicRelation): """Represents a 'subproperty of' relation.""" def __str__(self): - return f"{self.source} is a subproperty of {self.target}" + return f"({self.source}, subPropertyOf, {self.target})" #-------------------------------------------------------------------------- # Instance Relations @@ -51,6 +72,4 @@ class SubpropertyOfRelation(TaxonomicRelation): class InstanceOfRelation(TaxonomicRelation): """Represents an 'instance of' relation.""" def __str__(self): - return f"{self.source} is an instance of {self.target}" - -# Additional taxonomic relations can be added below as needed. + return f"({self.source}, instanceOf, {self.target})" diff --git a/ontoScorer/scorer.py b/ontoScorer/scorer.py index f1e6b8db3c4f633b42a29d72981041b33662c7ae..adccd3d5da108aa2fec0eb64f2037561373ca906 100644 --- a/ontoScorer/scorer.py +++ b/ontoScorer/scorer.py @@ -18,7 +18,6 @@ class OntoScorer: self.metrics = Metrics() def compute_metrics(self): - self.comparison_result = self.reference_ontology.compare_to(self.generated_ontology) self.metrics.compute_entity_scores(self.reference_ontology, self.generated_ontology) def generate_report(self): diff --git a/tests/dev_test_1.py b/tests/dev_test_1.py new file mode 100644 index 0000000000000000000000000000000000000000..abd52e74898a2e07115827a3040b79ccd0ebfc28 --- /dev/null +++ b/tests/dev_test_1.py @@ -0,0 +1,42 @@ +#!/usr/bin/python3.10 +# -*-coding:Utf-8 -* + +import os +from rdflib import Graph, Namespace + +# Création de l'ontologie et des namespaces nécessaires +graph = Graph() +DATA_FOLDER_PATH = f'{os.path.dirname(os.path.abspath(__file__))}/test_data' +ontology1_path = f"{DATA_FOLDER_PATH}/ontology_a.ttl" +graph.parse(ontology1_path, format="ttl") + +OWL = Namespace("http://www.w3.org/2002/07/owl#") + +def extract_some_values_from_restrictions(g: Graph): + axioms = [] + for restriction, _, some_values_from in g.triples((None, OWL.someValuesFrom, None)): + on_property = g.value(subject=restriction, predicate=OWL.onProperty) + if on_property: + axiom = (restriction, on_property, some_values_from) + axioms.append(axiom) + return axioms + +# Tester la fonction +axioms = extract_some_values_from_restrictions(graph) +n=0 +for axiom in axioms: + n += 1 + print(f'[{n}]: {axiom}\n') + +# for s, p, o in graph: +# print(s, p, o) + + + def get_some_values_from_restrictions(self): + axioms = [] + for restriction, _, some_values_from in self.graph.triples((None, OWL.someValuesFrom, None)): + on_property = self.graph.value(subject=restriction, predicate=OWL.onProperty) + if on_property: + axiom = SomeValuesFromRestrictionAxiom(restriction, on_property, some_values_from) + axioms.append(axiom) + return axioms \ No newline at end of file diff --git a/tests/test_data/ontology_c.ttl b/tests/test_data/ontology_c.ttl new file mode 100644 index 0000000000000000000000000000000000000000..eb994310df4e09b0240dc6aac1dae2d36f58bf8e --- /dev/null +++ b/tests/test_data/ontology_c.ttl @@ -0,0 +1,16 @@ +@prefix ex: <http://example.org#> . +@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . +@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . +@prefix owl: <http://www.w3.org/2002/07/owl#> . + +ex:SolarSystem a owl:NamedIndividual ; + rdfs:label "The Solar System" ; + ex:contains ex:SomeSmallerObjectInstance . + +ex:SomeSmallerObjectInstance a ex:SmallerObject . + +ex:contains a owl:ObjectProperty ; + rdfs:label "contains" . + +ex:SmallerObject a owl:Class ; + rdfs:label "Smaller Object" . diff --git a/tests/test_ontology.py b/tests/test_ontology.py index 948d4142345022751698bbeed7829aef15df53ff..170200a5e88057aa3b9a5ea3d0923f1287dc70ca 100644 --- a/tests/test_ontology.py +++ b/tests/test_ontology.py @@ -10,9 +10,16 @@ import unittest import os from context import ontoScorer + from ontoScorer.ontology import Ontology -from rdflib import URIRef +from ontoScorer.ontology_axioms import * +from ontoScorer.ontology_nontaxonomic_relations import * +from ontoScorer.ontology_taxonomic_relations import * + +#-------------------------------------------------------------------------- +# Ontology Test (Base) +#-------------------------------------------------------------------------- class TestOntology(unittest.TestCase): def setUp(self): @@ -27,6 +34,20 @@ class TestOntology(unittest.TestCase): self.assertIsNotNone(self.onto1.graph) self.assertIsNotNone(self.onto2.graph) + +#-------------------------------------------------------------------------- +# Ontology Test (Entity Extraction) +#-------------------------------------------------------------------------- +class TestOntology(unittest.TestCase): + + def setUp(self): + # Test ontology paths + DATA_FOLDER_PATH = f'{os.path.dirname(os.path.abspath(__file__))}/test_data' + self.ontology1_path = f"{DATA_FOLDER_PATH}/ontology_a.ttl" + self.ontology2_path = f"{DATA_FOLDER_PATH}/ontology_b.ttl" + self.onto1 = Ontology(self.ontology1_path) + self.onto2 = Ontology(self.ontology2_path) + def test_get_classes(self): classes1_names = {c.name() for c in self.onto1.get_classes()} classes2_names = {c.name() for c in self.onto2.get_classes()} @@ -62,30 +83,178 @@ class TestOntology(unittest.TestCase): self.assertEqual(len(data_properties_names_1), 0) self.assertEqual(len(data_properties_names_2), 0) - def test_get_restrictions(self): - restrictions = self.onto1.get_restrictions() - expected_restrictions_count = 5 - self.assertEqual(len(restrictions), expected_restrictions_count) - def test_get_individuals(self): individuals_names = {ind.name() for ind in self.onto1.get_individuals()} self.assertEqual(len(individuals_names), 1) self.assertIn("SolarSystem", individuals_names) self.assertNotIn("gravitation", individuals_names) - def test_get_annotations(self): - annotations = self.onto1.get_annotations() - self.assertIn("SolarSystem", annotations) - self.assertIn("direct", annotations) - self.assertIn("gravitation", annotations) - self.assertIn("orbit", annotations) - self.assertIn("object", annotations) - self.assertIn("sun", annotations) - self.assertIn("system", annotations) - def test_compare_to(self): - comparison_result = self.onto1.compare_to(self.onto2) - self.assertIsInstance(comparison_result, tuple) +#-------------------------------------------------------------------------- +# Ontology Test (Taxonomic Relations) +#-------------------------------------------------------------------------- +class TestOntologyTaxonomicRelations(unittest.TestCase): + + def setUp(self): + # Test ontology paths + DATA_FOLDER_PATH = f'{os.path.dirname(os.path.abspath(__file__))}/test_data' + self.ontology1_path = f"{DATA_FOLDER_PATH}/ontology_a.ttl" + self.ontology2_path = f"{DATA_FOLDER_PATH}/ontology_b.ttl" + self.onto1 = Ontology(self.ontology1_path) + self.onto2 = Ontology(self.ontology2_path) + + def test_subclass_relation_extraction_1(self): + relations = self.onto1.get_subclass_relations() + for r in relations: + self.assertIsInstance(r, SubclassOfRelation, f"Unexpected relation type: {type(r)} for relation: {r}") + + def test_subclass_relation_extraction_2(self): + relations = self.onto1.get_taxonomic_relations() + subclasses = [rel for rel in relations if isinstance(rel, SubclassOfRelation)] + self.assertTrue(any(rel.source.endswith("#gravitation-bind-system") and rel.target.endswith("#gravitation") for rel in subclasses)) + self.assertTrue(any(rel.source.endswith("#object-orbit-hasManner-direct-sun") and rel.target.endswith("#object") for rel in subclasses)) + + + def test_subproperty_relation_extraction_1(self): + relations = self.onto1.get_subproperty_relations() + for r in relations: + self.assertIsInstance(r, SubpropertyOfRelation, f"Unexpected relation type: {type(r)} for relation: {r}") + + def test_subproperty_relation_extraction_2(self): + relations = self.onto1.get_taxonomic_relations() + subproperties = [rel for rel in relations if isinstance(rel, SubpropertyOfRelation)] + self.assertTrue(any(rel.source.endswith("#direct") and rel.target.endswith("#Out_ObjectProperty") for rel in subproperties)) + self.assertTrue(any(rel.source.endswith("#orbit-hasManner-direct") and rel.target.endswith("#orbit") for rel in subproperties)) + + + def test_instance_relation_extraction_1(self): + relations = self.onto1.get_instance_relations() + for r in relations: + self.assertIsInstance(r, InstanceOfRelation, f"Unexpected relation type: {type(r)} for relation: {r}") + + def test_instance_relation_extraction_2(self): + relations = self.onto1.get_taxonomic_relations() + instances = [rel for rel in relations if isinstance(rel, InstanceOfRelation)] + self.assertTrue(any(rel.source.endswith("#SolarSystem") and rel.target.endswith("#system") for rel in instances)) + + + def test_get_taxonomic_relations(self): + relations = self.onto1.get_taxonomic_relations() + for r in relations: + self.assertIsInstance(r, (SubclassOfRelation, SubpropertyOfRelation, InstanceOfRelation), + f"Unexpected relation type: {type(r)} for relation: {r}") + + +#-------------------------------------------------------------------------- +# Ontology Test (Non-Taxonomic Relations) +#-------------------------------------------------------------------------- +class TestOntologyNonTaxonomicRelations(unittest.TestCase): + + def setUp(self): + # Test ontology paths + DATA_FOLDER_PATH = f'{os.path.dirname(os.path.abspath(__file__))}/test_data' + self.ontology1_path = f"{DATA_FOLDER_PATH}/ontology_c.ttl" + self.onto1 = Ontology(self.ontology1_path) + + def test_object_property_relations_1(self): + relations = self.onto1.get_object_property_relations() + for r in relations: + self.assertIsInstance(r, ObjectPropertyRelation, + f"Unexpected relation type: {type(r)} for relation: {r}") + + def test_object_property_relations_2(self): + relations = self.onto1.get_non_taxonomic_relations() + instances = [rel for rel in relations if isinstance(rel, ObjectPropertyRelation)] + self.assertTrue(any(rel.source.endswith("#SolarSystem") + and rel.property.endswith("#contains") + and rel.target.endswith("#SomeSmallerObjectInstance") + for rel in instances)) + + + def test_data_property_relations_1(self): + relations = self.onto1.get_data_property_relations() + for r in relations: + self.assertIsInstance(r, DataPropertyRelation, + f"Unexpected relation type: {type(r)} for relation: {r}") + + def test_get_non_taxonomic_relations(self): + relations = self.onto1.get_non_taxonomic_relations() + for r in relations: + self.assertIsInstance(r, (ObjectPropertyRelation, DataPropertyRelation, DomainRelation, RangeRelation), + f"Unexpected relation type: {type(r)} for relation: {r}") + + +#-------------------------------------------------------------------------- +# Ontology Test (Axioms) +#-------------------------------------------------------------------------- +class TestOntologyAxioms(unittest.TestCase): + + def setUp(self): + # Test ontology paths + DATA_FOLDER_PATH = f'{os.path.dirname(os.path.abspath(__file__))}/test_data' + self.ontology1_path = f"{DATA_FOLDER_PATH}/ontology_a.ttl" + self.onto1 = Ontology(self.ontology1_path) + + def test_get_some_values_from_restrictions(self): + axioms = self.onto1.get_some_values_from_restrictions() + self.assertEqual(len(axioms), 5, "Expected 5 SomeValuesFromRestrictionAxioms.") + axiom = axioms[0] + self.assertIsInstance(axiom, SomeValuesFromRestrictionAxiom) + # self.assertTrue(any(rel.on_property.endswith("#orbit-hasManner-not-direct") + # and rel.some_values_from.endswith("#sun") + # for rel in axioms)) + self.assertTrue(any(rel.on_property.endswith("#orbit-hasManner-direct") + and rel.some_values_from.endswith("#sun") + for rel in axioms)) + self.assertTrue(any(rel.on_property.endswith("#bind") + and rel.some_values_from.endswith("#system") + and rel.parent_class.endswith("gravitation-bind-system") + for rel in axioms)) + + +#-------------------------------------------------------------------------- +# Tests for Comparison Methods +#-------------------------------------------------------------------------- + +class TestOntologyComparisonMethods(unittest.TestCase): + + def setUp(self): + # Test ontology paths + DATA_FOLDER_PATH = f'{os.path.dirname(os.path.abspath(__file__))}/test_data' + self.ontology1_path = f"{DATA_FOLDER_PATH}/ontology_a.ttl" + self.ontology2_path = f"{DATA_FOLDER_PATH}/ontology_b.ttl" + self.ontology3_path = f"{DATA_FOLDER_PATH}/ontology_c.ttl" + self.onto1 = Ontology(self.ontology1_path) + self.onto2 = Ontology(self.ontology2_path) + self.onto3 = Ontology(self.ontology3_path) + + def test_compare_entity_names(self): + entity1 = self.onto1.get_classes()[0] + entity2 = self.onto2.get_classes()[0] + entity3 = self.onto2.get_classes()[1] + self.assertTrue(Ontology.compare_entity_names(entity1, entity2)) + self.assertFalse(Ontology.compare_entity_names(entity1, entity3)) + + def test_compare_relations_1(self): + relation1 = self.onto1.get_taxonomic_relations()[0] + relation2 = self.onto2.get_taxonomic_relations()[0] + relation3 = self.onto2.get_taxonomic_relations()[1] + print(relation1) + print(relation2) + self.assertTrue(Ontology.compare_relations(relation1, relation2)) + self.assertFalse(Ontology.compare_relations(relation1, relation3)) + + def test_compare_relations_2(self): + relation1 = self.onto3.get_non_taxonomic_relations()[0] + relation2 = self.onto3.get_non_taxonomic_relations()[0] + # relation3 = self.onto3.get_non_taxonomic_relations()[1] + self.assertTrue(Ontology.compare_relations(relation1, relation2)) + # self.assertFalse(Ontology.compare_relations(relation1, relation3)) + + +#-------------------------------------------------------------------------- +# Main Unit Test Run +#-------------------------------------------------------------------------- if __name__ == "__main__": unittest.main() diff --git a/tests/test_ontology_submodules.py b/tests/test_ontology_submodules.py index d18896d2727b10231fedac97bf3b3e142365f356..ad756da4b5d45b6bc0572564038c7bf680355534 100644 --- a/tests/test_ontology_submodules.py +++ b/tests/test_ontology_submodules.py @@ -16,61 +16,156 @@ from ontoScorer.ontology_axioms import * from ontoScorer.ontology_nontaxonomic_relations import * from ontoScorer.ontology_taxonomic_relations import * +from rdflib import URIRef, BNode + + #-------------------------------------------------------------------------- -# Ontology Taxonomic Relations Test +# Ontology Entities Test #-------------------------------------------------------------------------- -class TestOntologyTaxonomicRelations(unittest.TestCase): +from ontoScorer.ontology_entity import NamedEntity, BlankEntity + +class TestOntologyEntities(unittest.TestCase): def setUp(self): - # Any necessary setup can be done here... - pass + self.graph = None + + def test_named_entity_creation_and_name(self): + uri = URIRef("http://example.org#EntityName") + named_entity = NamedEntity(uri, self.graph) + self.assertEqual(named_entity.name(), "EntityName") + + def test_named_entity_properties(self): + uri = URIRef("http://example.org#EntityName") + named_entity = NamedEntity(uri, self.graph) + # Since we have a mock graph with no triples, we expect properties() to return an empty list. + self.assertEqual(named_entity.properties(), []) + + def test_blank_entity_creation_and_name(self): + bnode = BNode() + blank_entity = BlankEntity(bnode, self.graph) + self.assertEqual(blank_entity.name(), str(bnode)) + + def test_blank_entity_properties(self): + bnode = BNode() + blank_entity = BlankEntity(bnode, self.graph) + # Since we have a mock graph with no triples, we expect properties() to return an empty list. + self.assertEqual(blank_entity.properties(), []) + - def test_subclass_of_relation(self): - relation = SubclassOfRelation(URIRef("http://example.com#Subclass"), URIRef("http://example.com#Superclass"), None) - self.assertEqual(str(relation), "http://example.com#Subclass is a subclass of http://example.com#Superclass") - # Additional test methods for other taxonomic relations can be added here... - - #-------------------------------------------------------------------------- -# Ontology Non-Taxonomic Relations Test +# Ontology Taxonomic Relations Test #-------------------------------------------------------------------------- -class TestOntologyNonTaxonomicRelations(unittest.TestCase): +from ontoScorer.ontology_taxonomic_relations import (SubclassOfRelation, + SubpropertyOfRelation, + InstanceOfRelation) + +class TestOntologyTaxonomicRelations(unittest.TestCase): def setUp(self): - # Any necessary setup can be done here... - pass + self.source = URIRef("http://example.org#source") + self.target = URIRef("http://example.org#target") + self.graph = None # This can be set up with a mock RDF graph if needed + + def test_subclass_relation_str(self): + relation = SubclassOfRelation(self.source, self.target, self.graph) + self.assertEqual(str(relation), "(http://example.org#source, subClassOf, http://example.org#target)") - def test_object_property_relation(self): - relation = ObjectPropertyRelation(URIRef("http://example.com#Source"), URIRef("http://example.com#Target"), None) - self.assertEqual(str(relation), "http://example.com#Source has object property http://example.com#Target") + def test_subproperty_relation_str(self): + relation = SubpropertyOfRelation(self.source, self.target, self.graph) + self.assertEqual(str(relation), "(http://example.org#source, subPropertyOf, http://example.org#target)") + + def test_instance_relation_str(self): + relation = InstanceOfRelation(self.source, self.target, self.graph) + self.assertEqual(str(relation), "(http://example.org#source, instanceOf, http://example.org#target)") + + +class TestTaxonomicRelationComparison(unittest.TestCase): + + def setUp(self): + self.graph = None + self.source1 = URIRef("http://example.org#source1") + self.target1 = URIRef("http://example.org#target1") + self.source2 = URIRef("http://example.org#source2") + self.target2 = URIRef("http://example.org#target2") + + def test_subclass_relation_comparison_same(self): + relation1 = SubclassOfRelation(self.source1, self.target1, self.graph) + relation2 = SubclassOfRelation(self.source1, self.target1, self.graph) + self.assertTrue(relation1.compare_relation(relation2)) + + def test_subclass_relation_comparison_different(self): + relation1 = SubclassOfRelation(self.source1, self.target1, self.graph) + relation2 = SubclassOfRelation(self.source2, self.target2, self.graph) + self.assertFalse(relation1.compare_relation(relation2)) + + def test_subproperty_relation_comparison_same(self): + relation1 = SubpropertyOfRelation(self.source1, self.target1, self.graph) + relation2 = SubpropertyOfRelation(self.source1, self.target1, self.graph) + self.assertTrue(relation1.compare_relation(relation2)) + + def test_instance_relation_comparison_same(self): + relation1 = InstanceOfRelation(self.source1, self.target1, self.graph) + relation2 = InstanceOfRelation(self.source1, self.target1, self.graph) + self.assertTrue(relation1.compare_relation(relation2)) + + def test_instance_relation_comparison_different(self): + relation1 = InstanceOfRelation(self.source1, self.target1, self.graph) + relation2 = InstanceOfRelation(self.source2, self.target2, self.graph) + self.assertFalse(relation1.compare_relation(relation2)) - # Additional test methods for other non-taxonomic relations can be added here... - - #-------------------------------------------------------------------------- -# Ontology Axioms Test +# Ontology Non-Taxonomic Relations Test #-------------------------------------------------------------------------- -class TestOntologyAxioms(unittest.TestCase): +from ontoScorer.ontology_nontaxonomic_relations import (ObjectPropertyRelation, + DataPropertyRelation, + DomainRelation, + RangeRelation) + +class TestOntologyNonTaxonomicRelations(unittest.TestCase): def setUp(self): - # Any necessary setup can be done here... - pass + self.source = URIRef("http://example.org#source") + self.property = URIRef("http://example.org#property") # This was added for non-taxonomic relations + self.target = URIRef("http://example.org#target") + self.graph = None # This can be set up with a mock RDF graph if needed + + def test_object_property_relation_str(self): + relation = ObjectPropertyRelation(self.source, self.property, self.target, self.graph) + self.assertEqual(str(relation), "(http://example.org#source, http://example.org#property, http://example.org#target)") + + def test_data_property_relation_str(self): + relation = DataPropertyRelation(self.source, self.property, self.target, self.graph) + self.assertEqual(str(relation), "(http://example.org#source, http://example.org#property, http://example.org#target)") + + def test_domain_relation_str(self): + relation = DomainRelation(self.source, self.property, self.target, self.graph) + self.assertEqual(str(relation), "(http://example.org#source, http://example.org#property, http://example.org#target)") - def test_restriction_axiom(self): - axiom = RestrictionAxiom(URIRef("http://example.com#SomeClass")) - self.assertEqual(str(axiom), "Restriction on: http://example.com#SomeClass") + def test_range_relation_str(self): + relation = RangeRelation(self.source, self.property, self.target, self.graph) + self.assertEqual(str(relation), "(http://example.org#source, http://example.org#property, http://example.org#target)") - def test_some_values_from_restriction(self): - restriction_node = BNode() - on_property = URIRef("http://example.org/hasPart") - some_values_from = URIRef("http://example.org/Hand") - restriction = SomeValuesFromRestrictionAxiom(restriction_node, on_property, some_values_from) - self.assertEqual(str(restriction), "Restriction on: {} via property: http://example.org/hasPart with some values from: http://example.org/Hand".format(restriction_node)) - # Additional test methods for other axiom types can be added here... +#-------------------------------------------------------------------------- +# Ontology Axioms Test +#-------------------------------------------------------------------------- +from ontoScorer.ontology_axioms import SomeValuesFromRestrictionAxiom + +class TestAxioms(unittest.TestCase): + + def test_some_values_from_restriction_axiom(self): + parent_class = URIRef("http://example.org#ParentClass") + restriction_node = URIRef("http://example.org#RestrictionNode") + on_property = URIRef("http://example.org#hasProperty") + some_values_from = URIRef("http://example.org#SomeClass") + + axiom = SomeValuesFromRestrictionAxiom(parent_class, restriction_node, on_property, some_values_from) + expected_str = f"Restriction on class: {parent_class} with node: {restriction_node} via property: {on_property} with some values from: {some_values_from}" + + self.assertEqual(str(axiom), expected_str, "Unexpected string representation for SomeValuesFromRestrictionAxiom.")