W3C home > Mailing lists > Public > public-data-shapes-wg@w3.org > April 2016

Re: implementation of core SHACL (using proposed syntax)

From: Holger Knublauch <holger@topquadrant.com>
Date: Wed, 13 Apr 2016 15:40:19 +1000
To: public-data-shapes-wg@w3.org
Message-ID: <570DDBC3.6090202@topquadrant.com>
On 13/04/2016 1:11, Peter F. Patel-Schneider wrote:
> Here are a few examples.   These were generated using a simple test harness
> that  calls an internal function to generate the query for a shape in a shapes
> graph, prints the query, and then runs the query against a data graph.
>
> Dimitris should be able to provide a few examples of the SPARQL code that his
> implementation produces as well.  The output may not be too different.
>
>
> ex:t1 a sh:Shape ;
>   sh:scopeClass ex:tscope1 ;
>   sh:class ex:tclass1 .
>
> PREFIX sh: <http://www.w3.org/ns/shacl#>
> # SHAPE start <http://ex.com/t1>
>    SELECT  ?this ?message ?severity
>           ?subject ?predicate ?object (<http://ex.com/t1> AS ?shape )
>    WHERE { # SHAPE body
>    { # FRAGMENT
>    SELECT  ?this ("Does not have required class ex:tclass1" AS ?message)
> (<http://www.w3.org/ns/shacl#Violation> AS ?severity) (?this AS ?object)
>    WHERE {  ?this rdf:type/rdfs:subClassOf* <http://ex.com/tscope1> .
>            FILTER ( ! EXISTS { ?this rdf:type/rdfs:subClassOf*
> <http://ex.com/tclass1> } ) } }
>          } # SHAPE end <http://ex.com/t1>
>
>
> ex:t9 a sh:Shape ;
>   sh:scopeClass ex:tscope2 ;
>   sh:equals ( ex:p1 ( ex:p2 ex:p2 ) ).
>
> PREFIX sh: <http://www.w3.org/ns/shacl#>
> # SHAPE start <http://ex.com/t9>
>    SELECT  ?this ?message ?severity
>           ?subject ?predicate ?object (<http://ex.com/t9> AS ?shape )
>    WHERE { # SHAPE body
>    { # FRAGMENT
>    SELECT  ?this ("Paths don't have equal values" AS ?message)
> (<http://www.w3.org/ns/shacl#Violation> AS ?severity) (?this AS ?object)
>    WHERE {  ?this rdf:type/rdfs:subClassOf* <http://ex.com/tscope2> .
>            { { ?this <http://ex.com/p1> ?value . MINUS { ?this
> <http://ex.com/p2>/<http://ex.com/p2> ?value . } } UNION
>           { ?this <http://ex.com/p2>/<http://ex.com/p2> ?value . MINUS { ?this
> <http://ex.com/p1> ?value.  } } } } }
>          } # SHAPE end <http://ex.com/t9>

So far so good. I am however still awaiting your clarification why 
sh:equals suddenly has a different syntax than the other property 
constraints.

>
>
> ex:unl a sh:Shape ;
>    sh:scopeClass ex:unlC ;
>    sh:propValues ( ex:propunl [ a sh:Shape ; sh:hasValue ex:snli ] ) .
>
>
> PREFIX sh: <http://www.w3.org/ns/shacl#>
> # SHAPE start <http://ex.com/unl>
>    SELECT  ?this ?message ?severity
>           ?subject ?predicate ?object (<http://ex.com/unl> AS ?shape )
>    WHERE { # SHAPE body
>    { # newContext
>    SELECT  ?this ?message ?severity ?subject ?predicate ?object
>    WHERE {
>     {SELECT (?childGrandparent AS ?parent) ?this # (?childParent AS ?this)
>             ?message ?severity ?subject ?predicate ?object
>       WHERE
>       {{ SELECT (?grandparent AS ?childGrandparent) (?parent AS ?childParent)
>                 (?message AS ?childMessage) (?severity as ?childSeverity)
>                 (?subject AS ?childSubject) (?predicate AS ?childPredicate) ?object
>          WHERE {     # SHAPE start "ub1bL296C30"
>    SELECT ?parent ?this ?message ?severity
>           ?subject ?predicate ?object ("ub1bL296C30" AS ?shape )
>    WHERE { # SHAPE body
>    { # hasValue
>    SELECT ?parent ("Missing required value ex:snli" AS ?message)
> (<http://www.w3.org/ns/shacl#Violation> AS ?severity)
>    WHERE { { SELECT (IF(BOUND(?p),?p,"UNKNOWN P") AS ?parent)
> (IF(BOUND(?gp),?gp,"UNKNOWN GP") AS ?grandparent)
> 	WHERE { { SELECT (IF(BOUND(?this),?this,"UNK T") AS ?p)
> (IF(BOUND(?parent),?parent,"UNK P") AS ?gp) WHERE { ?this
> rdf:type/rdfs:subClassOf* <http://ex.com/unlC> . } }
> 	} }
>            FILTER NOT EXISTS { { ?parent <http://ex.com/propunl> ?this . }
> FILTER sameTerm(?this,<http://ex.com/snli>) } } }
>          } # SHAPE end "ub1bL296C30"
>
>                } }
>        BIND( (IF(BOUND(?childSubject), ?childSubject, ?childParent)) AS ?subject )
>        BIND( (IF(BOUND(?childSubject), ?childPredicate, ex:propunl)) AS
> ?predicate )
>        BIND( (IF(BOUND(?childParent), ?childParent, "UNKNOWN")) AS ?this )
>        BIND( CONCAT("In path ex:propunl ",?childMessage) AS ?message )
>        BIND( <http://www.w3.org/ns/shacl#Violation> AS ?severity )
>        } }
>        ?this rdf:type/rdfs:subClassOf* <http://ex.com/unlC> . # subshape inner
>        } }
>          } # SHAPE end <http://ex.com/unl>

Gosh. This is quite a mouthful. I don't want to imagine how more complex 
patterns look like, such as sh:filterShapes.

And quite a bit of "magic" happening in the code generator. Looking at 
your source code, I see all kinds of code templates techniques with 
different handling of each core construct. All this complexity would 
have to be moved into the spec if we continue to base it on SPARQL. The 
current design and Proposal 3 are much simpler and more consistent, and 
use the same approach to evaluation each core constraint and all 
extensions. SHACL can then be defined using its own extension mechanism.

Do you have an example of a user-defined constraint component by any 
chance? How would someone formalize the kind of SPARQL generation 
without pre-binding?

This also confirms two limitations of this single-query-transformation 
approach (we had discussed this before):
- inability to generate nested validation results
- inability to handle recursion
The current design uses sh:hasShape which doesn't have these limitations.

Holger


>
>
>
>
>
>
>
>
> On 04/11/2016 09:55 PM, Holger Knublauch wrote:
>> Peter,
>>
>> in order to better understand how your algorithm works, would you be able to
>> share some examples of the SPARQL that gets generated? Also, I assume you have
>> some non-trivial test cases - these may be valuable resources for the WG in
>> general.
>>
>> (Regardless of whether the WG decided to generally recommend a
>> SPARQL-transformation approach, there certainly would be value in exploring
>> this possibility, e.g. as a WG note or in papers).
>>
>> Thanks,
>> Holger
>>
>>
>> On 23/03/2016 3:22, Peter F. Patel-Schneider wrote:
>>> I put together an implementation of core SHACL with my syntax proposal.  It is
>>> available at https://github.com/pfps/shacl
>>>
>>> There is a single python 2.7 file that can be called as
>>>     python shacl.py data shapes
>>> to validate the data graph against the shapes graph and print the validation
>>> reports.
>>>
>>> This implements my proposed syntax but there is also code that will handle
>>> most of the differences between the two syntaxes.
>>>
>>> This implementation is a pure transformation to SPARQL.  A SHACL shape is
>>> transformed into a SPARQL query and the solutions in the result set are the
>>> violations of the shape.
>>>
>>> There are a few differences between this implementation and the current spec
>>> besides the syntax differences.  There is no translation from the result set
>>> to a graph.  The subject, predicate, and object come from where the violation
>>> was detected.  Severities may be handled slightly differently.
>>>
>>>
>>> peter
>>>
>>
Received on Wednesday, 13 April 2016 05:40:55 UTC

This archive was generated by hypermail 2.4.0 : Friday, 17 January 2020 19:30:31 UTC