SHACL sh:rule with sh:condition in SPARQL in Topbraid Composer - sparql

The example ontology has two classes (:MyClass and :Value) and two properties (:MyObjProp and :MyDataProp).
:MyClass
a owl:Class ;
a sh:NodeShape ;
rdfs:subClassOf owl:Thing ;
.
:MyDataProp
a owl:DatatypeProperty ;
rdfs:domain :MyClass ;
rdfs:range xsd:string ;
.
:MyObjProp
a owl:ObjectProperty ;
rdfs:domain :MyClass ;
rdfs:range :Value ;
.
:Value
a owl:Class ;
rdfs:subClassOf owl:Thing ;
.
Some instances were added.
:MyClass_1
a :MyClass ;
:MyDataProp :Value_1 ;
:MyObjProp :Value_1 ;
.
:MyClass_2
a :MyClass ;
:MyObjProp :Value_2 ;
.
:Value_1
a :Value ;
.
:Value_2
a :Value ;
.
A NodeShape :NodeShapeRule with a sh:rule (:SPARQLRule_1) was created. This rule creates new triples. With the sh:condition the rule should be restricted to a subset of targets.
:NodeShapeRule
a sh:NodeShape ;
sh:rule :SPARQLRule_1 ;
sh:targetClass :MyClass ;
.
:SPARQLRule_1
a sh:SPARQLRule ;
sh:condition :NodeShapeConditionSPARQL ;
sh:construct """
PREFIX : <http://example.org/ex#>
CONSTRUCT
{
$this :MyDataProp \"New input\" .
}
WHERE
{
$this :MyObjProp ?p .
}
""" ;
.
For the restriction two equivalent NodeShapes were defined. The first constraint works with sh:property, the other uses sh:sparql.
:NodeShapeConditionProperty
a sh:NodeShape ;
sh:property [
sh:path :MyObjProp ;
sh:description "NodeShapeConditionProperty" ;
sh:hasValue :Value_1 ;
] ;
sh:targetClass :MyClass ;
.
:NodeShapeConditionSPARQL
a sh:NodeShape ;
sh:sparql [
sh:message "NodeShapeConditionSPARQL" ;
sh:prefixes <http://example.org/ex> ;
sh:select """
PREFIX : <http://example.org/ex#>
SELECT $this
WHERE
{
$this :MyObjProp ?prop .
}
""" ;
] ;
sh:targetClass :MyClass ;
.
While doing inferencing with Topbraid Composer I received different results for both solutions. Only the solution with sh:property provides the expected response. Please, can someone explain me this behavior?
:MyClass_1 :MyDataProp "New input"

The right explanation is that the SPAQRL query produces a constraint violation for each result (row) in SELECT query. So if the SPARQL query returns no result (rows) then all is fine and the rule will fire. The reason for this design is that this enables SPARQL queries to return more information about the violation, e.g. the focus node ($this) and the value node (?value).
Changing the :NodeShapeConditionSPARQL it produces violation for not existing results and then both solutions behave in the same manner.
:NodeShapeConditionSPARQL
a sh:NodeShape ;
sh:sparql [
sh:message "NodeShapeConditionSPARQL" ;
sh:prefixes <http://example.org/ex> ;
sh:select """
PREFIX : <http://example.org/ex#>
SELECT $this
WHERE
{
FILTER NOT EXISTS { $this :MyObjProp ?anyProp } .
}
""" ;
] ;
sh:targetClass :MyClass ;
.

Related

How to get the top level classes from an ontology with SPARQL and filter out classes restrictions in the query?

I know there's some answers from Query SPARQL resulting level 1 hierarchy and SPARQL Query - get top-level classes of a dataset
But this isn't enough for what I'm trying to do. I have the class Category, subclass of owl:Thing, and the query
SELECT DISTINCT ?cls
WHERE {
?cls a owl:Class .
FILTER NOT EXISTS {
?cls rdfs:subClassOf ?sup .
FILTER(?sup != owl:Thing)
}
}
works fine for other classes without restrictions but it doesn't return Category because Category has restrictions, which this query sees them as separate classes. My Category class looks like this:
:Category rdf:type owl:Class ;
rdfs:subClassOf owl:Thing ,
[ rdf:type owl:Restriction ;
owl:onProperty :hasConfidence ;
owl:minCardinality "0"^^xsd:nonNegativeInteger
] ,
[ rdf:type owl:Restriction ;
owl:onProperty :hasIntensity ;
owl:minCardinality "0"^^xsd:nonNegativeInteger
] ,
[ rdf:type owl:Restriction ;
owl:onProperty :hasConfidence ;
owl:maxCardinality "1"^^xsd:nonNegativeInteger
] ,
[ rdf:type owl:Restriction ;
owl:onProperty :hasIntensity ;
owl:maxCardinality "1"^^xsd:nonNegativeInteger
] ;
rdfs:comment """Category refers to the classification used to annotate the emotion.
This can be further expanded to add support to new categories."""#en ;
rdfs:label "Category"#en .
How can I modify the query to add these top-level classes that are "subclasses" of some restrictions? I need a FILTER for those restrictions but I don't know how to go into this. I tried doing
SELECT DISTINCT ?cls
WHERE
{
{
?cls a owl:Class .
FILTER NOT EXISTS {
?cls rdfs:subClassOf ?sup .
FILTER(?sup != owl:Thing)
}
}
UNION
{ ?cls rdfs:subClassOf owl:Thing }
}
and it works but that implies that Category has to be EXPLICITLY subclass of owl:Thing, which isn't always the case in a lot of ontologies.
I figured it out. Here's the query for anyone who's having trouble with this like me:
SELECT DISTINCT ?cls
WHERE
{
?cls a owl:Class .
FILTER NOT EXISTS {
?cls rdfs:subClassOf ?sup .
FILTER(?sup != owl:Thing) .
FILTER NOT EXISTS {
?sup a owl:Restriction .
}
}
FILTER(?cls != owl:Thing) # We get rid of the root class from the query results
}
Basically, all I needed was a filter for the owl:Restriction class types. I also added a filter to get rid of owl:Thing from the query results. With this query I'm able to get the Category class from my ontology, which is part of the top-layer / level 1 hierarchy.

SPARQL OPTIONAL rdf:rest*/rdf:first does not return the first list

I am trying to construct a query that will return everything in an rdf list, given a specific subject.
I have a query like this:
PREFIX : <https://example.com/#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX sh: <http://www.w3.org/ns/shacl#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
select ?class ?propertyShape ?type where {
:ClassA rdfs:subClassOf ?class .
?class sh:property ?propertyShape .
OPTIONAL { ?propertyShape sh:xone/rdf:rest*/rdf:first/sh:class ?type . }
}
My data looks like this:
#prefix : <https://example.com/#> .
#prefix owl: <http://www.w3.org/2002/07/owl#> .
#prefix sh: <http://www.w3.org/ns/shacl#> .
:ClassA-shapeB
a sh:PropertyShape ;
sh:path :shapeB ;
sh:nodeKind sh:IRI ;
sh:xone (
[
sh:class :ClassB ;
]
[
sh:class :ClassC ;
]
) ;
.
:ClassA-shapeA
a sh:PropertyShape ;
sh:path :shapeA ;
sh:nodeKind sh:IRI ;
sh:xone (
[
sh:class :ClassB ;
]
[
sh:class :ClassC ;
]
) ;
.
:ClassA-shapeC
a sh:PropertyShape ;
sh:path :shapeA ;
sh:nodeKind sh:IRI ;
sh:xone (
[
sh:class :ClassB ;
]
[
sh:class :ClassC ;
]
) ;
.
:shapeA
a owl:ObjectProperty ;
.
:shapeB
a owl:ObjectProperty ;
.
:shapeC
a owl:ObjectProperty ;
.
:ClassA
a owl:Class ;
a sh:NodeShape ;
sh:property :ClassA-shapeA ;
sh:property :ClassA-shapeB ;
sh:property :ClassA-shapeC ;
rdfs:subClassOf :ClassA ;
.
:ClassC
a owl:Class ;
a sh:NodeShape ;
.
The query result looks like this:
class
propertyShape
type
:ClassA
:ClassA-shapeB
:ClassB
:ClassA
:ClassA-shapeB
:ClassC
:ClassA
:ClassA-shapeA
:ClassA
:ClassA-shapeC
:ClassB
:ClassA
:ClassA-shapeC
:ClassC
I would expect for there to also be two :ClassA-shapeA, having :ClassB and :ClassC like the other two, but it does not. The first propertyShape (alphabetically) always has it's types left out.
This query works as expected if I remove OPTIONAL, but that is needed to get the rest of the property's, (not included in this example).

SPARQL: how to transfer owl:equivalentClass to rdfs:subClassOf (owl:Restriction) properties?

My question is about using SPARQL to query some owl ontology where owl:Restrictions are heavily used (in my case this is the "Cell Ontology").
Here is an example of some typical entry (in Turtle format, extracted from the above mentioned ontology):
### http://purl.obolibrary.org/obo/CL_0000792
obo:CL_0000792 rdf:type owl:Class ;
owl:equivalentClass [ owl:intersectionOf ( obo:CL_0000624
[ rdf:type owl:Restriction ;
owl:onProperty obo:RO_0002104 ;
owl:someValuesFrom obo:PR_000001380
]
[ rdf:type owl:Restriction ;
owl:onProperty obo:RO_0002215 ;
owl:someValuesFrom obo:GO_0050777
]
[ rdf:type owl:Restriction ;
owl:onProperty <http://purl.obolibrary.org/obo/cl#has_low_plasma_membrane_amount> ;
owl:someValuesFrom obo:PR_000001869
]
) ;
rdf:type owl:Class
] ;
rdfs:subClassOf obo:CL_0000624 ,
obo:CL_0000815 ,
[ rdf:type owl:Restriction ;
owl:onProperty obo:RO_0002104 ;
owl:someValuesFrom obo:PR_000001380
] ,
[ rdf:type owl:Restriction ;
owl:onProperty obo:RO_0002215 ;
owl:someValuesFrom obo:GO_0050777
] ,
[ rdf:type owl:Restriction ;
owl:onProperty <http://purl.obolibrary.org/obo/cl#has_low_plasma_membrane_amount> ;
owl:someValuesFrom obo:PR_000001869
] .
Here my ultimate goal is to transfer the owl equivalent properties to subClassOf properties:
CL_0000792 rdfs:subClassOf [
rdf:type owl:Restriction ;
owl:onProperty obo:RO_0002104 ;
owl:someValueFrom obo:PR_000001380
] ;
rdfs:subClassOf [
rdf:type owl:Restriction ;
owl:onProperty obo:cl#has_low_plasma_membrane_amount ;
owl:someValueFrom obo:PR_000001869
] .
What I do not achieve is to obtain all three properties from the rdfs:subclass part and then bind them properly to the subClassOf sorts of properties (then filtering out the obo:RO_0002215 would be easy).
EDIT: As I made some progress here a new SPARQL Query
EDIT2: following Damyan Ognyanov's answer updated the SPARQL query part which was ignoring the collection within the owl:intersectionOf part and which also more compact/elegant
Here my current SPARQL query:
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX obo: <http://purl.obolibrary.org/obo/>
PREFIX tpo: <http://www.definiens.com/ontologies/TissuePhenomicsOntology>
PREFIX cl: <http://purl.obolibrary.org/obo/cl.owl>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX efo: <http://www.ebi.ac.uk/efo/efo.owl>
CONSTRUCT {
?cell rdfs:subClassOf [ rdf:type owl:Restriction ;
owl:onProperty ?cellProp ;
owl:someValuesFrom ?cellPropValue
] .
?cellProp ?cellPropProp ?cellPropObj .
?cellPropValue ?cellPropValueProp ?cellPropValuePropValue .
?cell ?cellProp2 ?cellProp2Obj .
}
FROM named cl:
FROM named tpo:
WHERE {
# query cl to get our information
graph cl:
{
?cell (rdfs:subClassOf|(owl:equivalentClass/owl:intersectionOf/rdf:rest*/rdf:first)) ?x .
?x owl:onProperty ?cellProp ;
owl:someValuesFrom ?cellPropValue .
?cellProp ?cellPropProp ?cellPropObj .
?cellPropValue ?cellPropValueProp ?cellPropValuePropValue .
?cell ?cellProp2 ?cellProp2Obj .
}
# limit ?cell to the entries already present in TPO
graph tpo:
{
?cell rdfs:subClassOf* obo:CL_0000000 .
}
}
If you replace the CONSTRUCT part with a SELECT * then it appears that all variables are correctly assigned, the information is there.
What I am still missing though is a proper CONSTRUCT part to reconstruct the "somewhat convoluted" owl:Property restriction. As such this query mostly returns a long list of blank nodes, which won't be parsed properly by Protege for instance.
#AKSW also rightly pointed out that SPARQL may not be the tool of choice to query and construct OWL graphs. It indeed appears clearly here that one needs to know the precise data structure in order to build a working query, in this manner at least.
?cell (rdfs:subClassOf|(owl:equivalentClass/owl:intersectionOf/rdf:rest*/rdf:first)) ?x .
?x owl:onProperty ?cellProp ;
owl:someValuesFrom ?cellPropValue .
?cellProp ?cellPropProp ?cellPropObj .
?cellPropValue ?cellPropValueProp ?cellPropValuePropValue .
?cell ?cellProp2 ?cellProp2Obj .
The value of owl:intersectionOf is an RDF list and the above Turtle snippet uses the RDF list syntax to enumerate the members of the owl:intersectionOf collection (e.g., entries are enclosed between ( and )).
So, you should also include rdf:rest*/rdf:first properties in your property paths, since these are used to construct the collection.
For the query, I'll introduce an additional variable where to bind the restriction of interest and use it to fetch the values of owl:onProperty and owl:someValuesFrom, e.g., your WHERE clause may look something like:
?cell (rdfs:subClassOf|(owl:equivalentClass/owl:intersectionOf/rdf:rest*/rdf:first)) ?x .
?x owl:onProperty ?cellProp ;
owl:someValuesFrom ?cellPropValue .
?cellProp ?cellPropProp ?cellPropObj .
?cellPropValue ?cellPropValueProp ?cellPropValuePropValue .
?cell ?cellProp2 ?cellProp2Obj .

sparql and query in group of multiple predicates

I did not get the right sentence to ask the question.
I would like to explain my problem using a sample data.
let's say the triples are as below.
#prefix skos: <http://www.w3.org/2004/02/skos/core#> .
#prefix xs: <http://www.w3.org/2001/XMLSchema#> .
#prefix p0: <http://www.mlacustom.com#> .
#prefix p2: <http://www.mla.com/term/> .
_:bnode7021016689601753065 p0:lastModifiedDateTime "2018-09-14T12:55:38"^^<xsd:dateTime> ;
p0:lastModifiedUser "admin"^^xs:string .
<http://www.mla.com/name/4204078359> p0:hasClassingFacet "http://www.mla.com/facet/RA"^^xs:string ;
p0:type "Normal"^^xs:string ;
p0:classification _:bnode3452184423513029143 ,
_:bnode6827572371999795686 ;
p0:recordType "Name"^^xs:string ;
p0:recordNumber "4204078359"^^xs:string ;
p0:stdDescriptor "classification111111"^^xs:string ;
p0:establishedBy "admin"^^xs:string ;
skos:prefLabel "classification111111"^^xs:string ;
p0:createdBy "admin"^^xs:string ;
a skos:Concept ;
p0:createdDate "2018-09-14T12:55:38"^^<xsd:dateTime> ;
p0:establishedDate "2018-09-14T12:55:38"^^<xsd:dateTime> ;
p0:hasRAsubFacet "http://www.mla.com/subfacet/classing-subject-authors"^^xs:string ;
p0:lastModifiedDate "2018-09-14T12:55:38"^^<xsd:dateTime> ;
p0:lastModifiedDetails _:bnode7021016689601753065 ;
p0:isProblematic "N,N"^^xs:string ;
p0:lastModifiedBy "admin"^^xs:string ;
p0:status "established"^^xs:string .
_:bnode3452184423513029143 p0:literature p2:1513 ;
p0:timePeriod p2:1005 ;
p0:language p2:3199 .
_:bnode6827572371999795686 p0:literature p2:11307 ;
p0:timePeriod p2:1009 ;
p0:language p2:31 .
please have a look at the p0:classification it has two blank nodes and both the blank nodes has triples with p0:literature, p0:timePeriod, p0:language
Now I want to write a SPARQL query where
(
(p0:literature is p2:1513 AND p0:timePeriod is p2:1005) AND
(p0:literature is p2:11307 AND p0:timePeriod is p2:1009)
)
As per the above scenario it should return me the http://www.mla.com/name/4204078359 subject
Classification can have any number of blank nodes.
Here is one of the solutions. It is possible to find many different queries. This one is explicit.
SELECT ?s WHERE {
?s p0:classification ?o1 .
?s p0:classification ?o2 .
?o1 p0:literature p2:1513 ;
p0:timePeriod p2:1005 .
?o2 p0:literature p2:11307 ;
p0:timePeriod p2:1009 .
}

How to relate each instance of class with each instance of another class?

The general problem
I'm working on a simple ontology, using Protégé 4.3 and trying to create a model such that every instance of a class C has some particular value v, which is an instance of a class V, for a given property p. I can get this inference using an axiom
C subClassOf (p value v)
but I think I want to be able to state this more along the lines of a
C subClassOf (p some V)
because I'd actually like each instance of C to be related to every instance of V.
A specific example
My example is automobiles and actions — I want to create a set of actions for automobiles. When I create new instances of automobiles I want each to have a set of actions. If I add new instances of actions I want all the instances of automobiles to reflect all their related actions.
To add further detail, I have defined the Auto class and two subclasses: Car and Truck. I have also defined an Action class and a subclass, TruckAction. I have defined a hasAction property with domain Auto and range Action to relate autos and actions. I have further created several individuals of different types:
Auto
Truck {F150}
Car {ChevyMalibu}
Action {Accelerate}
TruckAction {LoadCargo}
When I make Car a subclass of (hasAction value Accelerate), I can see that ChevyMalibu has the inferred object property hasAction Accelerate, but this seems akin to hard-coding the object property assertion. I would like to have all car actions inferred for the ChevyMalibu and likewise all TruckActions inferred for F150. I'm not quite sure why doing something like making Car a subclass of (hasAction some Action) won't get me there.
I think that the eloquent answer to OWL type inference with a restriction is related to my question, but I can't quite add this up.
Encoding the rules
You correctly note that if an individual x is an instance of p value y, then you'll infer the assertion p(x,y). However, simply saying that x is an instance of p some Y doesn't (without some more information) won't let you infer that p(x,yi) for any particular yi, even if yi is the only particular instance of Y that you've declared. This is because OWL makes the open world assumption; just because you haven't said something is true (or false) yet doesn't mean that it couldn't be true (or false). (Of course, you might have already said other things that would let you figure out whether something is true or false.) This is described in more detail in another question, Why is this DL-Query not returning any individuals?
If I've understood it correctly, what you're trying to do is say something like:
every Vehicle is related by hasAction to every Action
every Car is related by hasAction to every CarAction
every Truck is related by hasAction to every TruckAction
There are a couple of ways that you could do this. The easiest is to simply use some SWRL rules, and the other is called rolification.
Using SWRL Rules
You can write SWRL rule counterparts of the rules above, and the they're pretty easy to write:
Vehicle(?v) &wedge; Action(?a) &rightarrow; hasAction(?v,?a)
Car(?v) &wedge; CarAction(?a) &rightarrow; hasAction(?v,?a)
Truck(?v) &wedge; TruckAction(?a) &rightarrow; hasAction(?v,?a)
If you use all of these rules, you'll find that each of your vehicles has more actions than you want it to, because, by the first rule, each vehicle is related to each action. E.g., since each TruckAction is also an Action, and since each Car is a Vehicle, the first rule will relate each TruckAction to each Car, and you didn't really want that. Even so, using some rules may well be the easiest option here.
Using Rolification
If you don't want to use SWRL rules, then another option is rolification. I've described rolification and how to do it in answers to a few questions, so you should have a look at:
OWL 2 rolification
OWL 2 reasoning with SWRL rules
How to infer isBrotherOf property between two individuals
Equal relationship between ontology properties
Those will give you more details about rolification. The main point, though, is that we get new properties, e.g., RCar, that have a special behavior: they only relate instances of a particular class to that same instance. E.g., RCar relates each instance of Car
to itself, and doesn't do anything else. It's effectively an equivalence relation on a particular class.
How is rolification useful here? It means that we can use subproperty chain axioms to infer some hasAction properties. E.g.,
hasAction &sqsubseteq; RCar &bullet; topObjectProperty &bullet; RCarAction
That's essentially equivalent to the SWRL rule (topObjectProperty is a built in property of OWL that relates everything to everything):
RCar(?c,?c) &wedge; topObjectProperty(?c,?a) &wedge; RCarAction(?a,?a) &rightarrow; hasAction(?c,?a)
There are two advantages, though:
the subproperty chain axiom doesn't require a reasoner to have SWRL support; and
the subproperty chain axiom works on all individuals, but the SWRL rule works only on named individuals, so you get somewhat better coverage.
You'll still have the same issue that you did with the specificity of the SWRL rules, though; if you say that every Vehicle is related to every Action by hasAction, then that subproperty chain will also apply to subclasses of vehicle and subclasses of action.
There's a significant disadvantage, though: for each class that you want to use in one of these "rules," you need a new property and an equivalent class axiom, and that gets to be sort of tedious.
A different hierarchy for actions
Because both the SWRL rule approach and the subproperty chain with rolification approaches have the problem that the generic rule that relates each vehicle to each action will capture all the actions from subclasses of Action and vehicles from subclasses of Vehicles, you may need to restructure one of your hierarchies a bit. I'd suggest that rather than
Action
CarAction
TruckAction
that you use
Action
VehicleAction
CarAction
TruckAction
and not mirror the hierarchy that you have under Vehicle. This way you can write rules of the form:
every Vehicle is related to every GenericAction by hasAction
every Car is related to every CarAction by hasAction
every Truck is related to every TruckAction by hasAction
With SWRL rules
If you do this with SWRL rules, it looks like this:
(The default layout for Protégé might not include a place to edit SWRL rules though. See my answer to Ontology property definition in Protégé-OWL / SWRL for instructions on getting one. It's just a minor interface tweak; you don't need to download or install anything.) This produces results like this:
You can copy and paste this ontology:
#prefix : <https://stackoverflow.com/q/21512765/1281433/cars#> .
#prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
#prefix swrl: <http://www.w3.org/2003/11/swrl#> .
#prefix owl: <http://www.w3.org/2002/07/owl#> .
#prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
#prefix swrlb: <http://www.w3.org/2003/11/swrlb#> .
#prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
:Action a owl:Class .
<urn:swrl#a> a swrl:Variable .
:DodgeRam a owl:NamedIndividual , :Truck .
:Truck a owl:Class ;
rdfs:subClassOf :Vehicle .
:Car a owl:Class ;
rdfs:subClassOf :Vehicle .
<urn:swrl#v> a swrl:Variable .
:LoadCargo a owl:NamedIndividual , :TruckAction .
[ a swrl:Imp ;
swrl:body [ a swrl:AtomList ;
rdf:first [ a swrl:ClassAtom ;
swrl:argument1 <urn:swrl#a> ;
swrl:classPredicate :GenericAction
] ;
rdf:rest [ a swrl:AtomList ;
rdf:first [ a swrl:ClassAtom ;
swrl:argument1 <urn:swrl#v> ;
swrl:classPredicate :Vehicle
] ;
rdf:rest ()
]
] ;
swrl:head [ a swrl:AtomList ;
rdf:first [ a swrl:IndividualPropertyAtom ;
swrl:argument1 <urn:swrl#v> ;
swrl:argument2 <urn:swrl#a> ;
swrl:propertyPredicate :hasAction
] ;
rdf:rest ()
]
] .
:Accelerate a owl:NamedIndividual , :GenericAction .
:F150 a owl:NamedIndividual , :Truck .
:FordFocusZX5 a owl:NamedIndividual , :Car .
[ a swrl:Imp ;
swrl:body [ a swrl:AtomList ;
rdf:first [ a swrl:ClassAtom ;
swrl:argument1 <urn:swrl#c> ;
swrl:classPredicate :Car
] ;
rdf:rest [ a swrl:AtomList ;
rdf:first [ a swrl:ClassAtom ;
swrl:argument1 <urn:swrl#a> ;
swrl:classPredicate :CarAction
] ;
rdf:rest ()
]
] ;
swrl:head [ a swrl:AtomList ;
rdf:first [ a swrl:IndividualPropertyAtom ;
swrl:argument1 <urn:swrl#c> ;
swrl:argument2 <urn:swrl#a> ;
swrl:propertyPredicate :hasAction
] ;
rdf:rest ()
]
] .
:Brake a owl:NamedIndividual , :GenericAction .
:hasAction a owl:ObjectProperty .
:GenericAction a owl:Class ;
rdfs:subClassOf :Action .
<https://stackoverflow.com/q/21512765/1281433/cars>
a owl:Ontology .
:Vehicle a owl:Class .
<urn:swrl#c> a swrl:Variable .
:ChevyMalibu a owl:NamedIndividual , :Car .
<urn:swrl#t> a swrl:Variable .
:CarAction a owl:Class ;
rdfs:subClassOf :Action .
[ a swrl:Imp ;
swrl:body [ a swrl:AtomList ;
rdf:first [ a swrl:ClassAtom ;
swrl:argument1 <urn:swrl#t> ;
swrl:classPredicate :Truck
] ;
rdf:rest [ a swrl:AtomList ;
rdf:first [ a swrl:ClassAtom ;
swrl:argument1 <urn:swrl#a> ;
swrl:classPredicate :TruckAction
] ;
rdf:rest ()
]
] ;
swrl:head [ a swrl:AtomList ;
rdf:first [ a swrl:IndividualPropertyAtom ;
swrl:argument1 <urn:swrl#t> ;
swrl:argument2 <urn:swrl#a> ;
swrl:propertyPredicate :hasAction
] ;
rdf:rest ()
]
] .
:TruckAction a owl:Class ;
rdfs:subClassOf :Action .
With rolification
If you do this with rolification, it looks like this:
and you get the results you'd expect:
You can copy and paste this ontology:
#prefix : <https://stackoverflow.com/q/21512765/1281433/cars#> .
#prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
#prefix owl: <http://www.w3.org/2002/07/owl#> .
#prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
#prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
:GenericAction a owl:Class ;
rdfs:subClassOf :Action ;
owl:equivalentClass [ a owl:Restriction ;
owl:hasSelf true ;
owl:onProperty :R_GenericAction
] .
:Car a owl:Class ;
rdfs:subClassOf :Vehicle ;
owl:equivalentClass [ a owl:Restriction ;
owl:hasSelf true ;
owl:onProperty :R_Car
] .
:CarAction a owl:Class ;
rdfs:subClassOf :Action ;
owl:equivalentClass [ a owl:Restriction ;
owl:hasSelf true ;
owl:onProperty :R_CarAction
] .
:R_TruckAction a owl:ObjectProperty .
:R_Car a owl:ObjectProperty .
:Truck a owl:Class ;
rdfs:subClassOf :Vehicle ;
owl:equivalentClass [ a owl:Restriction ;
owl:hasSelf true ;
owl:onProperty :R_Truck
] .
:Brake a owl:NamedIndividual , :GenericAction .
:hasAction a owl:ObjectProperty ;
owl:propertyChainAxiom ( :R_Vehicle owl:topObjectProperty :R_GenericAction ) ;
owl:propertyChainAxiom ( :R_Car owl:topObjectProperty :R_CarAction ) ;
owl:propertyChainAxiom ( :R_Truck owl:topObjectProperty :R_TruckAction ) .
:R_CarAction a owl:ObjectProperty .
:R_Truck a owl:ObjectProperty .
:F150 a owl:NamedIndividual , :Truck .
:Accelerate a owl:NamedIndividual , :GenericAction .
:Action a owl:Class .
:ChevyMalibu a owl:NamedIndividual , :Car .
:R_Vehicle a owl:ObjectProperty .
:FordFocusZX5 a owl:NamedIndividual , :Car .
:R_GenericAction a owl:ObjectProperty .
:TruckAction a owl:Class ;
rdfs:subClassOf :Action ;
owl:equivalentClass [ a owl:Restriction ;
owl:hasSelf true ;
owl:onProperty :R_TruckAction
] .
:DodgeRam a owl:NamedIndividual , :Truck .
<https://stackoverflow.com/q/21512765/1281433/cars>
a owl:Ontology .
:LoadCargo a owl:NamedIndividual , :TruckAction .
:Vehicle a owl:Class ;
owl:equivalentClass [ a owl:Restriction ;
owl:hasSelf true ;
owl:onProperty :R_Vehicle
] .