Search code examples
shacl

Simple way to model "inverse cardinality" in SHACL?


We want to transform a UML diagram of an ontology with cardinalities into a SHACL shape to validate if the cardinalities in our data are correct.

Let's say we have Author 1 ---first author ---> 1.n Book, the right part is quite easy to model as:

:AuthorShape a sh:NodeShape;
    sh:targetClass :Author;
    sh:property [sh:path :firstAuthor; sh:minCount 1].

However now I also want to model the "other end", i.e. that a book cannot have more than 1 first authors:

:FirstAuthorCardinalityOtherEndShape a sh:NodeShape;
    sh:targetObjectsOf :firstAuthor;
    sh:property [
            sh:path [ sh:inversePath :firstAuthor ];
            sh:minCount 1;
            sh:maxCount 1
    ];                              
    sh:nodeKind sh:IRI.

However that looks quite convoluted (8 lines instead of 3) and error prone (:firstAuthor is mentioned twice). Is there a simpler way to model this?

For example, this could be like this, but sh:inverseMinCount doesn't exist:

:AuthorShape a sh:NodeShape;
    sh:targetClass :Author;
    sh:property [sh:path :firstAuthor; sh:minCount 1; sh:inverseMinCount 1; sh:inverseMaxCount 1].

Solution

  • The issue that :firstAuthor is mentioned twice can be avoided by attaching the property to Book, e.g.

    :BookShape a sh:NodeShape ;
        sh:targetClass :Book ;
        sh:property [
            sh:path [ sh:inversePath :firstAuthor ] ;
            sh:maxCount 1 ;
        ] .
    

    (You already have AuthorShape, so having BookShape would be a perfectly natural thing to do).

    In any case you wouldn't need the sh:minCount 1 because the sh:targetObjectsOf already implies this, although I can see why you would want this from an UML point of view.

    And I don't think the design above is much more complex than the forward direction, assuming you're OK with the sh:inversePath overhead, which is unavoidable.