Closed ajnelson-nist closed 7 months ago
As an aside, I am able to implement this C-not-A, C-not-B disjointedness in two other ways.
Using a union ...
@prefix ex: <http://example.org/ontology/> .
@prefix sh-ex: <http://example.org/shapes/> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
sh-ex:ClassC-shape
a sh:NodeShape ;
sh:not [
a sh:NodeShape ;
sh:or (
[
a sh:NodeShape ;
sh:class ex:ClassA ;
]
[
a sh:NodeShape ;
sh:class ex:ClassB ;
]
) ;
] ;
sh:targetClass ex:ClassC ;
.
... flags the individuals I expect:
pyshacl \
--metashacl \
--shacl try-shapes-or.ttl \
--ont-graph try-ontology.ttl \
try-data.ttl
Validation Report
Conforms: False
Results (2):
Constraint Violation in NotConstraintComponent (http://www.w3.org/ns/shacl#NotConstraintComponent):
Severity: sh:Violation
Source Shape: sh-ex:ClassC-shape
Focus Node: kb:Thing-2
Value Node: kb:Thing-2
Message: Node kb:Thing-2 conforms to shape [ rdf:type sh:NodeShape ; sh:or ( [ rdf:type sh:NodeShape ; sh:class ex:ClassA ] [ rdf:type sh:NodeShape ; sh:class ex:ClassB ] ) ]
Constraint Violation in NotConstraintComponent (http://www.w3.org/ns/shacl#NotConstraintComponent):
Severity: sh:Violation
Source Shape: sh-ex:ClassC-shape
Focus Node: kb:Thing-3
Value Node: kb:Thing-3
Message: Node kb:Thing-3 conforms to shape [ rdf:type sh:NodeShape ; sh:or ( [ rdf:type sh:NodeShape ; sh:class ex:ClassA ] [ rdf:type sh:NodeShape ; sh:class ex:ClassB ] ) ]
Using indirect node shapes ...
@prefix ex: <http://example.org/ontology/> .
@prefix sh-ex: <http://example.org/shapes/> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
sh-ex:ClassC-shape
a sh:NodeShape ;
sh:node
[
a sh:NodeShape ;
sh:not [
a sh:NodeShape ;
sh:class ex:ClassA ;
] ;
] ,
[
a sh:NodeShape ;
sh:not [
a sh:NodeShape ;
sh:class ex:ClassB ;
] ;
]
;
sh:targetClass ex:ClassC ;
.
... flags the individuals I expect:
pyshacl \
--metashacl \
--shacl try-shapes-indirect.ttl \
--ont-graph try-ontology.ttl \
try-data.ttl
Validation Report
Conforms: False
Results (2):
Constraint Violation in NodeConstraintComponent (http://www.w3.org/ns/shacl#NodeConstraintComponent):
Severity: sh:Violation
Source Shape: sh-ex:ClassC-shape
Focus Node: kb:Thing-2
Value Node: kb:Thing-2
Message: Value does not conform to every Shape in ('[ rdf:type sh:NodeShape ; sh:not [ rdf:type sh:NodeShape ; sh:class ex:ClassA ] ]', '[ rdf:type sh:NodeShape ; sh:not [ rdf:type sh:NodeShape ; sh:class ex:ClassB ] ]'). See details for more information.
Details:
Constraint Violation in NotConstraintComponent (http://www.w3.org/ns/shacl#NotConstraintComponent):
Severity: sh:Violation
Source Shape: [ rdf:type sh:NodeShape ; sh:not [ rdf:type sh:NodeShape ; sh:class ex:ClassA ] ]
Focus Node: kb:Thing-2
Value Node: kb:Thing-2
Message: Node kb:Thing-2 conforms to shape [ rdf:type sh:NodeShape ; sh:class ex:ClassA ]
Constraint Violation in NodeConstraintComponent (http://www.w3.org/ns/shacl#NodeConstraintComponent):
Severity: sh:Violation
Source Shape: sh-ex:ClassC-shape
Focus Node: kb:Thing-3
Value Node: kb:Thing-3
Message: Value does not conform to every Shape in ('[ rdf:type sh:NodeShape ; sh:not [ rdf:type sh:NodeShape ; sh:class ex:ClassA ] ]', '[ rdf:type sh:NodeShape ; sh:not [ rdf:type sh:NodeShape ; sh:class ex:ClassB ] ]'). See details for more information.
Details:
Constraint Violation in NotConstraintComponent (http://www.w3.org/ns/shacl#NotConstraintComponent):
Severity: sh:Violation
Source Shape: [ rdf:type sh:NodeShape ; sh:not [ rdf:type sh:NodeShape ; sh:class ex:ClassB ] ]
Focus Node: kb:Thing-3
Value Node: kb:Thing-3
Message: Node kb:Thing-3 conforms to shape [ rdf:type sh:NodeShape ; sh:class ex:ClassB ]
Hi @ajnelson-nist
Thanks for filing this issue.
I've just re-read the whole section on sh:not
in the Spec, and I agree it is not clear.
The description:
sh:not
specifies the condition that each value node cannot conform to a given shape. This is comparable to negation and the logical "not" operator.
and the Textual Definition:
For each value node
v:
A failure MUST be reported if the conformance checking ofv
against the shape$not
produces a failure. Otherwise, ifv
conforms to the shape$not
, there is validation result withv
assh:value
.
both mention just a single shape for sh:not
on the constraint, but do not say it cannot have more than one.
However, the "parameters" section contains:
| Property | Summary and Syntax Rules | | sh:not | The shape to negate. The values of
sh:not
in a shape must be well-formed shapes.|
That mentions values plural. So to me that indeed shows multiple values are allowed.
So this is a bug. Even though you've shown it is relatively easy to work around, it will still be fixed to allow multiple values for sh:not
. This was not picked up earlier because there are no tests in the W3C SHACL Test Suite (SHT) nor the Datashapes SHACL Test Suite (DASH) that contain a case with multiple values for sh:not
, and as you pointed out, there are no examples in the Spec doc showing it.
Thank you for the review! I look forward to the fix.
@ajnelson-nist two releases today (v0.24.1 for users of Python 3.7 + RDFLib 6.2, and v0.25.0 for users of Python 3.8+ & RDFlib 7.0.0) - both contain this fix.
Many thanks!
I've encountered something
pyshacl
is telling me is not allowed, but I'm having a hard time finding this in the spec and SHACL-SHACL.Given this ontology graph:
And given this data graph:
I would like to write a SHACL shapes graph that implements the OWL disjointedness checks. If I didn't have class B and just had one disjointedness to concern myself with, I would try this graph:
And this gives me the validation report I expect -
kb:Thing-2
alone is flagged:But, if I try one naïve maneuver and tie another anonymous node shape via
sh:not
...... I get an interesting message from
pyshacl
, which seems to be sourced from here (in today's code-state):I have other ways to satisfy my disjointedness-review goal (and I'll note those in a follow-on comment), but I'm interested in seeing the source of this constraint on
sh:not
usage.The referenced specification section (4.6.1) neither demonstrates a second
sh:not
, nor makes any statement on the predicate's cardinality.From the SHACL-SHACL graph (linked in Section C), all of the occurrences of
sh:not
in that file fit at once on my computer screen, and nothing among the occurrences appears to assign an upper bound on how many times it can be used. (And I concluded likewise when I ran the graph through a Turtle syntax normalizer, in case the line breaks and bracket wrapping were throwing me.)Is this max-cardinality-1 constraint on
sh:not
a bit more than is in the spec?