w3c / data-shapes

RDF Data Shapes WG repo
87 stars 33 forks source link

Disjointness of Qualified Value Shapes #92

Closed white-gecko closed 6 years ago

white-gecko commented 6 years ago

We are having a problem in the understanding of Qualified Value Shapes. This is not the same question as in #47 .

(Sorry, but this is not a very open minded example.)

This is the shape from which we are starting.

@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix ex: <http://example.org/ns#> .

ex:FamilyShape a sh:NodeShape ;
    sh:targetClass ex:Family ;
    sh:property ex:parentShape ;
    sh:property ex:motherShape ;
    sh:property ex:fatherShape ;
    sh:property ex:adultParentsShape .

ex:parentShape sh:path ex:parent ;
    sh:maxCount 2 ; sh:minCount 2 .

ex:motherShape sh:path ex:parent ;
    sh:qualifiedValueShape ex:femaleShape ;
    sh:qualifiedValueShapesDisjoint true ;
    sh:qualifiedMinCount 1 ;
    sh:qualifiedMaxCount 1 .

ex:femaleShape sh:path ex:gender ;
    sh:hasValue ex:female .

ex:fatherShape sh:path ex:parent ;
    sh:qualifiedValueShape ex:maleShape ;
    sh:qualifiedValueShapesDisjoint true ;
    sh:qualifiedMinCount 1 ;
    sh:qualifiedMaxCount 1 .

ex:maleShape sh:path ex:gender ;
    sh:hasValue ex:male .

ex:adultParentsShape sh:path ex:parent ;
    sh:qualifiedValueShape ex:adultShape ;
    sh:qualifiedValueShapesDisjoint false ;
    sh:qualifiedMinCount 2 ;
    sh:qualifiedMaxCount 2 .

ex:adultShape sh:path ex:age ;
    sh:minInclusive 18 .

We want to validate data graphs like the following:

@prefix ex: <http://example.org/ns#> .

ex:family a ex:Family ;
ex:parent ex:mother, ex:father .
ex:mother ex:gender ex:female ; ex:age 29 .
ex:father ex:gender ex:male ; ex:age 30 .

But in the playground we get the following validation report:

[
    a sh:ValidationResult ;
    sh:resultSeverity sh:Violation ;
    sh:sourceConstraintComponent sh:QualifiedMinCountConstraintComponent ;
    sh:sourceShape ex:motherShape ;
    sh:focusNode ex:family ;
    sh:resultPath ex:parent ;
    sh:resultMessage "Less than 1 values have shape ex:femaleShape" ;
] .
[
    a sh:ValidationResult ;
    sh:resultSeverity sh:Violation ;
    sh:sourceConstraintComponent sh:QualifiedMinCountConstraintComponent ;
    sh:sourceShape ex:fatherShape ;
    sh:focusNode ex:family ;
    sh:resultPath ex:parent ;
    sh:resultMessage "Less than 1 values have shape ex:maleShape" ;
] .

So we changed all sh:qualifiedValueShapesDisjoint to false which gave us 0 validation results.

@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix ex: <http://example.org/ns#> .

ex:FamilyShape a sh:NodeShape ;
    sh:targetClass ex:Family ;
    sh:property ex:parentShape ;
    sh:property ex:motherShape ;
    sh:property ex:fatherShape ;
    sh:property ex:adultParentsShape .

ex:parentShape sh:path ex:parent ;
    sh:maxCount 2 ; sh:minCount 2 .

ex:motherShape sh:path ex:parent ;
    sh:qualifiedValueShape ex:femaleShape ;
    sh:qualifiedValueShapesDisjoint false ;
    sh:qualifiedMinCount 1 ;
    sh:qualifiedMaxCount 1 .

ex:femaleShape sh:path ex:gender ;
    sh:hasValue ex:female .

ex:fatherShape sh:path ex:parent ;
    sh:qualifiedValueShape ex:maleShape ;
    sh:qualifiedValueShapesDisjoint false ;
    sh:qualifiedMinCount 1 ;
    sh:qualifiedMaxCount 1 .

ex:maleShape sh:path ex:gender ;
    sh:hasValue ex:male .

ex:adultParentsShape sh:path ex:parent ;
    sh:qualifiedValueShape ex:adultShape ;
    sh:qualifiedValueShapesDisjoint false ;
    sh:qualifiedMinCount 2 ;
    sh:qualifiedMaxCount 2 .

ex:adultShape sh:path ex:age ;
    sh:minInclusive 18 .

But this shape would also accept data graphs as the following, which we don't want to accept in this example:

@prefix ex: <http://example.org/ns#> .

ex:family a ex:Family ;
ex:parent ex:theParent, ex:theOtherParent .
ex:theParent ex:gender ex:female , ex:male ; ex:age 29 .
ex:theOtherParent ex:age 30 .

Strangely the playground even produced no validation result for:

@prefix ex: <http://example.org/ns#> .

ex:family a ex:Family ;
ex:parent ex:theParent, ex:theOtherParent .
ex:theParent ex:gender ex:female , ex:male ; ex:age 29 .

The question is, how can we express that the ex:motherShape and ex:fatherShape are disjoint, but both are not disjoint with the ex:adultParentsShape? For the strange behavior of the last example I assume it is a bug in the implementation of the playground.

HolgerKnublauch commented 6 years ago

The sh:minInclusive should not be a string, but an xsd:integer, I guess? (The playground has incomplete handling of datatype literal comparison and may therefore tolerate this, while other engines will correctly choke on this).

With disjointness switched on, it does seem to do the right thing: it complains because from the perspective of motherShape and fatherShape, the adultShape is a sibling shape (see https://www.w3.org/TR/shacl/#dfn-sibling-shapes) and the given instances are both father/mother and adults.

Once you switch the disjointness off, the second example (with theOtherParent) is OK because all individual property constraints are satisfied. But it sounds like you expected that.

On the last example, no violation result is produced because you did not state that ex:age is required, i.e. it is OK for a person to not have any age to pass the adultShape test.

To enforce what you are trying to say, it should work to group father/motherShape into a new shape, so that the adult condition is out of the way and then activate disjointness. Or add a sh:maxCount 1 to ex:gender.

HolgerKnublauch commented 6 years ago

Can this issue be closed? Thanks.

white-gecko commented 6 years ago

The sh:minInclusive should not be a string, but an xsd:integer, I guess? (The playground has incomplete handling of datatype literal comparison and may therefore tolerate this, while other engines will correctly choke on this).

I've fixed this in the above example and it doens't make a difference.

With disjointness switched on, it does seem to do the right thing: it complains because from the perspective of motherShape and fatherShape, the adultShape is a sibling shape (see https://www.w3.org/TR/shacl/#dfn-sibling-shapes) and the given instances are both father/mother and adults.

This is what we've expected.

Once you switch the disjointness off, the second example (with theOtherParent) is OK because all individual property constraints are satisfied. But it sounds like you expected that.

Yes

On the last example, no violation result is produced because you did not state that ex:age is required, i.e. it is OK for a person to not have any age to pass the adultShape test.

Ok, that explains the last example.

To enforce what you are trying to say, it should work to group father/motherShape into a new shape, so that the adult condition is out of the way and then activate disjointness. Or add a sh:maxCount 1 to ex:gender.

Ok, both possibilities are solutions for the presented problem.

If I create two sh:NodeShapes to express the disjunction of ex:motherShape and ex:fatherShape, and the ex:adultParentsShape, how could I say that these shapes “belong together”? Is there any way of grouping sh:NodeShapes?

And a more general question would be: wouldn't it be a cool idea to provide full support for conjunction and disjunction in one node shape?

simonstey commented 6 years ago

And a more general question would be: wouldn't it be a cool idea to provide full support for conjunction and disjunction in one node shape?

as in https://www.w3.org/TR/shacl/#core-components-logical ?

what about something along the lines of:

ex:FamilyShape a sh:NodeShape ;
    sh:targetClass ex:Family ;
    sh:property ex:parentShape ;
    sh:and (ex:GenderShape ex:adultParentsShape) .  #added

ex:GenderShape a sh:NodeShape ; #added
    sh:property ex:motherShape ;
    sh:property ex:fatherShape .

ex:parentShape sh:path ex:parent ;
    sh:maxCount 2 ; sh:minCount 2 .

ex:motherShape sh:path ex:parent ;
    sh:qualifiedValueShape ex:femaleShape ;
    sh:qualifiedValueShapesDisjoint true ;
    sh:qualifiedMinCount 1 ;
    sh:qualifiedMaxCount 1 .

ex:femaleShape sh:path ex:gender ;
    sh:hasValue ex:female .

ex:fatherShape sh:path ex:parent ;
    sh:qualifiedValueShape ex:maleShape ;
    sh:qualifiedValueShapesDisjoint true ;
    sh:qualifiedMinCount 1 ;
    sh:qualifiedMaxCount 1 .

ex:maleShape sh:path ex:gender ;
    sh:hasValue ex:male .

ex:adultParentsShape sh:path ex:parent ;
    sh:qualifiedValueShape ex:adultShape ;
    sh:qualifiedValueShapesDisjoint false ;
    sh:qualifiedMinCount 2 ;
    sh:qualifiedMaxCount 2 .

ex:adultShape sh:path ex:age ;
    sh:minCount 1 ; #added
    sh:maxCount 1 ; #added
    sh:minInclusive 18 .

or ->

ex:FamilyShape a sh:NodeShape ;
    sh:targetClass ex:Family ;
    sh:property ex:parentShape ;
    sh:node ex:GenderShape .

ex:GenderShape a sh:NodeShape ;
    sh:property ex:motherShape ;
    sh:property ex:fatherShape .

ex:parentShape sh:path ex:parent ;
    sh:maxCount 2 ; sh:minCount 2 ; 
    sh:node ex:adultShape .     #added

ex:motherShape sh:path ex:parent ;
    sh:qualifiedValueShape ex:femaleShape ;
    sh:qualifiedValueShapesDisjoint true ;
    sh:qualifiedMinCount 1 ;
    sh:qualifiedMaxCount 1 .

ex:femaleShape sh:path ex:gender ;
    sh:hasValue ex:female .

ex:fatherShape sh:path ex:parent ;
    sh:qualifiedValueShape ex:maleShape ;
    sh:qualifiedValueShapesDisjoint true ;
    sh:qualifiedMinCount 1 ;
    sh:qualifiedMaxCount 1 .

ex:maleShape sh:path ex:gender ;
    sh:hasValue ex:male .

ex:adultShape sh:path ex:age ;
    sh:minCount 1 ; #added
    sh:maxCount 1 ; #added
    sh:minInclusive 18 .
white-gecko commented 6 years ago

If you like you can close this with the "Commenter Timeout (assuming satisfied)" label currently I have no time to check this again :-(