Multiple paths and existential quantification in SHACL rules (should I use sh:oneOrMorePath perhaps?) - owl

I would like to understand how to handle multiple paths and existential quantification in SHACL rules. Let me exemplify my problem with a sample ontology.
The ontology includes the classes "Approve", "Legal", "Result", "Man", and "Machine", all disjoint. It has two properties "has-theme" and "come-from" and the following individuals:
:a rdf:type :Approve ;
:has-theme :r1,:r2 .
:r1 rdf:type :Result ;
:come-from :m1 .
:r2 rdf:type :Result ;
:come-from :m2 .
:m1 rdf:type :Man .
:m2 rdf:type :Machine .
Therefore: the Approve action ":a" has two themes: ":r1" and ":r2". The former comes from the Man ":m1", the latter comes from the Machine ":m2".
I want to write a SHACL rule stating that "Every Approve action having among its themes at least a Result that comes from a Man is Legal".
I tried this, that do NOT classify ":a" as Legal (but it should):
:testRule rdf:type sh:NodeShape;
sh:rule [rdf:type sh:TripleRule;
sh:condition :conditionTest;
sh:subject sh:this;
sh:predicate rdf:type;
sh:object ontology:Legal
];
sh:targetClass ontology:Approve.
:conditionTest
rdf:type sh:NodeShape;
sh:property
[
#IF the theme of the Approve action is a Result come from a Man
sh:path (ontology:has-theme ontology:come-from);
sh:class ontology:Man
].
The problem is that ":a" has two themes, one coming from a Man and the other from a Machine.
Then I read on the Web about sh:oneOrMorePath and I tried the following variants within sh:property:
sh:oneOrMorePath (ontology:has-theme ontology:come-from);
sh:path ([sh:oneOrMorePath ontology:has-theme] ontology:come-from);
sh:path (ontology:has-theme [sh:oneOrMorePath ontology:come-from]);
Nothing to do, these variants don't work either.
On the other hand, if I remove the triple ":r2 :come-from :m2" or the triple ":a :has-theme :r2"
it works, as there is no more in the ontology a branch leading from ":a" to a non-Man.
Could any of you be so kind to help me?
Thank you!
Livio

Your requirements states "having among its themes at least a Result that comes from a Man" which sounds like an existential constraint to me. So you cannot really use sh:class here, but you may rather want to use a qualified value constraint.
I have not tried it, but something like this may work:
:conditionTest
rdf:type sh:NodeShape ;
sh:property [
sh:path (ontology:has-theme ontology:come-from) ;
sh:qualifiedMinCount 1 ;
sh:qualifiedValueShape [
sh:class ontology:Man ;
]
] .
This should mean that at least one of the values of the path has-theme/come-from must conform to the qualified value shape, which means that it must be an instance of Man.
See https://www.w3.org/TR/shacl/#QualifiedValueShapeConstraintComponent for the specification of QVCs in SHACL.
If you can use SHACL-SPARQL and import the dash namespace, you could also simply write dash:hasValueWithClass ontology:Man, see http://datashapes.org/constraints.html#HasValueWithClassConstraintComponent

Related

How to assert inverse triples via SHACL (provided that they do not yet exist?)

I have an ontology in which each thematic role (e.g., has-agent) is represented via an object property. Furthermore, the inverse property is always defined (e.g., is-agent-of).
I want to assert in the ontology all inverse triples via SHACL rules PROVIDED THAT THEY DO NOT ALREADY EXIST.
Thus, I wrote the following rule:
:assertInverseTriplesOnHasAgent rdf:type sh:NodeShape;
sh:rule [rdf:type sh:TripleRule;
sh:condition
[
sh:not[
sh:property[
sh:path (TBox:has-agent TBox:is-agent-of);
sh:minCount 1;
sh:equals sh:this
]
]
];
sh:subject [sh:path TBox:has-agent];
sh:predicate TBox:is-agent-of;
sh:object sh:this
];
sh:targetSubjectsOf TBox:has-agent.
But it does not work: it asserts the inverse triples even when they already exist (and it shouldn't).
I suspect that "sh:equals sh:this" is not correct, i.e., that "sh:this" cannot be used within sh:property. On the other hand, "sh:minCount 1;" alone does not work because someone can be is-agent-of more than one action.
Can anyone help me? Thanks

Embedding a path in the parameter of sh:lessThan

Connected to this question (and its previous ones):
Using sh:maxExclusive to compare (the values of) two datatype properties
I created a small ontology with three classes: DataSubject, MemberState, and Minor. There are two datatype properties: has-age and has-minimalage. The former is from DataSubject(s) to integers, the latter is from MemberState(s) to integers. Then there is an object property has-member-state from DataSubject(s) to MemberState(s).
Now we have the following individuals:
ontology:John
rdf:type ontology:DataSubject ;
ontology:has-age "20"^^xsd:positiveInteger ;
ontology:has-member-state ontology:Spain ;
.
ontology:Spain
rdf:type ontology:MemberState ;
ontology:has-minimalage "16"^^xsd:positiveInteger ;
.
And I want to write a SHACL rule saying that each DataSubject whose age is less than the minimal age of his member state is also an individual of the class Minor.
In light of the replies I got to my other questions, I tried:
sh:rule [
rdf:type sh:TripleRule ;
sh:condition [
sh:property [
sh:path ontology:has-age ;
sh:lessThan (ontology:has-member-state ontology:has-minimalage)
] ;
] ;
sh:subject sh:this ;
sh:predicate rdf:type;
sh:object ontology:Minor ;
] ;
Which does not work: it classifies John as Minor, but 20 is not less than 16. Of course I tried many other variants, e.g., "sh:lessThan[sh:node[sh:path (ontology:has-member-state ontology:has-minimalage)];];", many of which do not probably make any sense, but none of them work.
Can someone suggest me how to embed a path in the parameter of sh:lessThan?
I am sorry if I start being annoying with all these questions :-( I am new to SHACL and SPARQL but I am really trying my best to learn them out of all what I can find on the Web.
Thanks
Livio
The official spec is (hopefully) pretty clear that the values must be IRIs, i.e. only direct properties are permitted. You can however try to revert the logic and use a path at the property shape. Otherwise, fall back to SPARQL.

Redundant axiom in Protege's Pizza ontology

Something just caught my eye in the Protege's
Pizza example ontology.
With regards to the owl:equivalentClass axiom of the class :VegetarianTopping
(amongst others.) It is defined like this (for the relevant bits):
:VegetarianTopping
rdf:type owl:Class ;
owl:equivalentClass [
owl:intersectionOf (
:PizzaTopping
[
rdf:type owl:Class ;
owl:unionOf (
:CheeseTopping
:FruitTopping
:HerbSpiceTopping
:NutTopping
:SauceTopping
:VegetableTopping
)
]
) ;
rdf:type owl:Class
] .
The rdf:comment for it is the following:
An example of a covering axiom. VegetarianTopping is equivalent to the union
of all toppings in the given axiom. VegetarianToppings can only be Cheese or
Vegetable or....etc.
All the :*Topping classes in the owl:unionOf above are defined as
sub-classes of :PizzaTopping, for instance:
:CheeseTopping
rdf:type owl:Class ;
rdfs:subClassOf :PizzaTopping .
It then looks to me that the part owl:intersectionOf ( :PizzaTopping ... ) is
redundant as all of the classes in the ... already meet that requirement. So
I would rather have given the following:
:VegetarianTopping
rdf:type owl:Class ;
owl:equivalentClass [
owl:unionOf (
:CheeseTopping
:FruitTopping
:HerbSpiceTopping
:NutTopping
:SauceTopping
:VegetableTopping
) ;
rdf:type owl:Class
] .
I guess I am missing something here? If not, is there any reason why
it has been defined like that?
The Protégé tutorial leads you step by step towards using the Protégé tool. It does not tell you how to build a practical application for your pizza business. Moreover, having redundent knowledge is not necessarily a bad thing. Avoiding redundency in knowledge representation may be difficult.
If you say "a vegetarian topping is a topping that consists of either cheese topping, fruit topping, herb spice topping, nut topping, sauce topping (sauces should be vegetarian of course), and vegetable topping", then you are redundent. You should say "a vegetarian topping is something that consits of either etc.". Saying that it is a topping, in addition to the other things, does not harm your knowledge, because it is true!
Adding true knowledge that is redundent may have cost in different ways (size of the ontology, efficiency, understandability, on so forth), but from a knowledge representation point of view, and for most reasoners, it is not a problem. Now, in the specific case of the Pizza ontology and this particular example, I don't know why they added the extra PizzaTopping class, but I suspect it is because of how the Protégé tutorial is designed, leading you gradually to more complicated concepts. There is nothing to worry about.

GraphDB can not infer class of individual

There is a class MotionPoint equivalent to (Protege syntax)
(geosparql:asWKT exactly 1 rdfs:Literal)
and (:hasSpeed exactly 1 rdfs:Literal)
and (:hasTimestamp exactly 1 rdfs:Literal)
and (:locatedInRoadElement exactly 1 otn:Road_Element)
And also there is a subclass OverspeedingMotionPoint equivalent to
:MotionPoint
and (:overspeedingByValue exactly 1 rdfs:Literal)
So, having an individual X a owl:Thing with relations from the MotionPoint definition Protege Pellet reasoner infers that X is the MotionPoint.
Adding overspeedingByValue relation to X makes Pellet infers that X is the OverspeedingMotionPoint.
Finally, I imported this ontology into GraphDB, chose OWL2-RL rules set, but can not get a conclusion that X is the OverspeedingMotionPoint, it says X is only MotionPoint.
Please, help me to understand what I am doing wrong..
I think that what you ask for is in OWL DL. GraphDB doesn't support DL, it supports RL and QL.
If (some of) your props are unique per class then you can easily infer types with RDFS reasoning, eg:
:MotionPoint a rdfs:Class;
rdfs:subClassOf geo:Geometry.
:OverspeedingMotionPoint a rdfs:Class;
rdfs:subClassOf :MotionPoint.
# geo:asWKT is subprop of geo:hasSerialization attached to geo:Geometry,
# so is inherited by :MotionPoint
:hasSpeed a owl:DatatypeProperty;
rdfs:domain :MotionPoint; rdfs:range xsd:decimal.
:overspeedingByValue a owl:DatatypeProperty;
rdfs:domain :OverspeedingMotionPoint; rdfs:range xsd:decimal.
:hasTimestamp a owl:DatatypeProperty;
rdfs:domain :MotionPoint; rdfs:range xsd:dateTimeStamp.
:locatedInRoadElement a owl:ObjectProperty;
rdfs:domain :MotionPoint; rdfs:range :RoadElement.
And if all your props are attached to multiple classes: would it be too much trouble to assert the type when you record an instance?

OWL Restrictions: Defining classes that depend on a concept hierarchy

I have a hierarchy of skos:Concepts and want to define an owl:Class consisting of those individuals that are connected to a specific concept or one of its narrower terms through some property.
I managed to create an owl:Restriction that works for one specific concept, but not for a hierarchy of concepts:
# Concept hierarchy
concepts:Dance a skos:Concept .
concepts:FolkDance a skos:Concept ;
skos:broaderTransitive concepts:Dance .
concepts:SquareDance a skos:Concept ;
skos:broaderTransitive concepts:FolkDance .
# owl axioms
ex:Dance rdfs:subClassOf ex:Movement ;
owl:equivalentClass [
a owl:Restriction ;
owl:onProperty ex:hasKindOfMovement ;
owl:hasValue concepts:Dance
] .
# Assertions
ex:SomeInstance ex:hasKindOfMovement concepts:Dance .
The above correctly makes ex:someInstance an instance of ex:Dance. But how can I make ex:anotherInstance a member of ex:Dance if I have the assertion
ex:anotherInstance ex:hasKindOfMovement concepts:SquareDance
? I. e. where the individual in owl:hasValue is a transitively narrower concept than the one specified in the restriction.
This question seems similar to OWL restrictions - defining classes that only contains properties with a specific property value but I couldn't work it out from there... Any help is much appreciated.

Resources