How to create a SHACL rule to infer rdf:type from rdfs:subClassOf

Viewed 277

In order to validate my RDF graph against my SHACL validation shapes V, I want to infer some triples to keep my shapes simple. In particular, one of the rule I need to implement is (in pseudo code):

(?s, rdf:type, :X) <-- (?s, rdfs:subClassOf, :Y)

I was trying several implementations, ending up with this triple rule (and its variants):

@prefix sh:            <http://www.w3.org/ns/shacl#> .
@prefix rdf:           <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:          <http://www.w3.org/2000/01/rdf-schema#> .
@prefix : <http://example.com/ex#> .
:s
    a              sh:NodeShape ;
    sh:targetClass rdfs:Resource ;
    sh:rule        [ 
                     a            sh:TripleRule ;
                     sh:subject   sh:this ;
                     sh:predicate rdf:type ;
                     sh:object    :X ;
                     sh:condition [ sh:property [ sh:path     rdfs:subClassOf ;
                                                  sh:hasValue :Y ] ]
                   ] .

However the rule does not infer :A rdf:type :X . for data graph

:A rdfs:subClassOf :Y .

(Executing against https://github.com/TopQuadrant/shacl). It is possible to solve this issue with a SPARQL rule, so my question is whether there is an option to do it through Triple rule as well. Thanks for hints!

2 Answers

Why don't you keep the inference rules and the validation separate, as you've noted is possible using SHACL + SPARQL, as this will keep things simpler?

You could use pySHACL and put rules into an ontology file since pySHACL can run ontology rules/inference before applying SHACL validators (see the -i and -e options).

Given the "MAY" in following quote, the advice in previous answer by @NicholasCar is solid IMO.

Purpose of answering here, is just to corroborate and expand with recent experience.

The 2017 W3C SHACL docs regarding Relationship between SHACL and RDFS inferencing:

SHACL implementations MAY, but are not required to, support entailment regimes. If a shapes graph contains any triple with the predicate sh:entailment and object E and the SHACL processor does not support E as an entailment regime for the given data graph then the processor MUST signal a failure.

(AFAICT the phrase "entailment regime" only refers to SPARQL as standard)

Looking at the section on Property Paths:

SPARQL Property path: rdf:type/rdfs:subClassOf*

SHACL Property path: (rdf:type [ sh:zeroOrMorePath rdfs:subClassOf ] )

In most of the SHACL implementations I've played with basic rdfs type entailment works (obv IFF the rdf:type/rdfs:subClassOf* path is visible to the SHACL validator), so (rdf:type [ sh:zeroOrMorePath rdfs:subClassOf ]) isn't needed explicitly.

The problem comes when you try to stuff advanced paths into the shapes - e.g. following this example to enforce graph contains at least one instance of an abstract type:

sh:path [ sh:inversePath ( rdf:type [ sh:zeroOrMorePath rdfs:subClassOf ] ) ] ;

... isn't working for me in a number of SHACL validation implementations.

Related