dice-group / owlapy

OWLAPY is a Python Framework for creating and manipulating OWL Ontologies.
MIT License
16 stars 1 forks source link

OWLObjectOneOf and Enumeration of Individuals #13

Closed Demirrr closed 6 months ago

Demirrr commented 6 months ago
from owlapy.render import DLSyntaxObjectRenderer
from owlapy.model import OWLObjectSomeValuesFrom, OWLObjectProperty, OWLNamedIndividual, OWLObjectOneOf
from owlapy.owl2sparql.converter import owl_expression_to_sparql

a = OWLNamedIndividual(iri='http://example.com/society#a')
b = OWLNamedIndividual(iri='http://example.com/society#b')
hasChild = OWLObjectProperty('http://example.com/society#hasChild')

ce=OWLObjectSomeValuesFrom(property=hasChild,filler=OWLObjectOneOf(values=[a,b]))

DL representation of the class expression has the union at the filler

print(DLSyntaxObjectRenderer().render(ce))
∃ hasChild.{a ⊔ b}

SPARQL query of the class expression

print(owl_expression_to_sparql(expression=ce))
SELECT
 DISTINCT ?x WHERE { 
?x <http://example.com/society#hasChild> ?s_1 . 
 FILTER ( ?s_1 IN ( 
<http://example.com/society#a>
,
<http://example.com/society#b>
 ) )
 }

An enumeration of individuals ObjectOneOf( a1 ... an ) contains exactly the individuals ai with 1 ≤ i ≤ n see source for more details as well as an example.

Therefore, I would suggest to ∃ hasChild.{a, b}. The SPARQL mapping is incorrect. Filter must be also changed to indicate that ?x haschild #a and #b

Demirrr commented 6 months ago

To give a concrete example

from ontolearn.triple_store import TripleStore
from owlapy.model import OWLNamedIndividual, IRI, OWLObjectSomeValuesFrom, OWLObjectOneOf, OWLObjectProperty
from owlapy.render import DLSyntaxObjectRenderer
from owlapy.owl2sparql.converter import owl_expression_to_sparql
path = "KGs/father.owl"
kb = TripleStore(path=path)
x=OWLObjectSomeValuesFrom(OWLObjectProperty(IRI('http://example.com/father#','hasChild')),filler=OWLObjectOneOf(values=(OWLNamedIndividual(IRI.create('http://example.com/father#heinz')),OWLNamedIndividual(IRI.create("http://example.com/father#anna")))))
print(DLSyntaxObjectRenderer().render(x)) 
sparql=owl_expression_to_sparql(root_variable="?x", ce=x)
∃ hasChild.{heinz ⊔ anna}

SELECT
 DISTINCT ?x WHERE { 
?x <http://example.com/father#hasChild> ?s_1 . 
 FILTER ( ?s_1 IN ( 
<http://example.com/father#heinz>
,
<http://example.com/father#anna>
 ) )
 }

Result

print(list(kb.query(sparql)))
[(rdflib.term.URIRef('http://example.com/father#anna'),), (rdflib.term.URIRef('http://example.com/father#martin'),), (rdflib.term.URIRef('http://example.com/father#markus'),)]

Results are incorrect as hasChild(martin,heinz), hasChild(anna,heinz) , and hasChild(markus,anna).

    <owl:NamedIndividual rdf:about="http://example.com/father#martin">
        <rdf:type rdf:resource="http://example.com/father#male"/>
        <hasChild rdf:resource="http://example.com/father#heinz"/>
    </owl:NamedIndividual>

    <owl:NamedIndividual rdf:about="http://example.com/father#anna">
        <rdf:type rdf:resource="http://example.com/father#female"/>
        <hasChild rdf:resource="http://example.com/father#heinz"/>
    </owl:NamedIndividual>

    <owl:NamedIndividual rdf:about="http://example.com/father#markus">
        <rdf:type rdf:resource="http://example.com/father#male"/>
        <hasChild rdf:resource="http://example.com/father#anna"/>
    </owl:NamedIndividual>

Results must be as empty set. As, there is no NamedIndividual that hasChild heinz and anna

Demirrr commented 6 months ago

Please work on this issue in the refactoring_sparql_mapping branch

alkidbaci commented 6 months ago

For the up-mention class expression x, I would suggest that the following SPARQL query should be constructed:

SELECT
 DISTINCT ?x WHERE { 
    ?x <http://example.com/father#hasChild> <http://example.com/father#heinz> . 
    ?x <http://example.com/father#hasChild> <http://example.com/father#anna> . 
 }

Do you agree?

Demirrr commented 6 months ago

Yes, this SPARQL query would work for ∃ hasChild.{heinz, anna} and a like

Demirrr commented 6 months ago

@alkidbaci This issue is solved. It was not a bug. Thank you @nkaralis for the clarification

nkaralis commented 6 months ago

Example

Assume a concept C that is equivalent to the concept ObjectOneOf (a, b, c, d). This means that the individuals belonging to C are exactly {a, b, c, d}.

The individuals belonging to the class expression ∃ knows.C are those that have at least one knows-successor that is an instance of C. Since C and ObjectOneOf (a, b, c, d) are equivalent, ∃ knows.ObjectOneOf (a, b, c, d) (written as ∃ knows.{a, b, c, d}) should return the same results, i.e., all those individuals that have a knows-successor that is in the set {a, b, c, d}.