rewrite OWL class expression as SPARQL query? - sparql

I have been familiarizing myself with AKSW's https://github.com/SmartDataAnalytics/OWL2SPARQL, which is pretty easy to use, even with Scala and sbt, but doesn't rewrite Class Expressions.
I (and at least one other person!) would find class expression -> SPARQL rewriting helpful. Maybe that's because I (at least) make punning statements? For example, I need to find all drug prescription individuals that mention any drug tablet class that (indirectly) has the chemical 'rosuvastatin' as an active ingredient
:X a 'drug prescription' .
:X mentions 'rosuvastatin Oral Tablet' .
where
'drug prescription' is http://purl.obolibrary.org/obo/PDRO_0000024
mentions is http://purl.obolibrary.org/obo/IAO_0000142
'rosuvastatin Oral Tablet' is http://purl.obolibrary.org/obo/DRON_00027869
Superclasses & Asserted Axioms for 'rosuvastatin Oral Tablet':
drug tablet
has_proper_part some (scattered molecular aggregate and
(is bearer of some active ingredient) and
(has granular part some rosuvastatin))
where rosuvastatin is http://purl.obolibrary.org/obo/DRON_00018679 (and the other IRIs can be seen in RDF/XML context at http://www.ontobee.org/ontology/rdf/DRON?iri=http://purl.obolibrary.org/obo/DRON_00027869)
Are there other tools that can rewrite an OWL Class Expression as a SPARQL query?
If not, I guess I might write a property chain shortcut... but that disregards the types of classes involved in the chain, right?
I have an example at https://github.com/turbomam/owl2sparql4turbo

AKSW added the functionality I requested and gave me some good tips about using the OWL API. My bridge from a Java stream to a Scala stream may be a little kludgy.
Clone https://github.com/turbomam/owl2sparql4turbo to see how I set up build.sbt to import dependencies.
Ontology rots.owl includes the axioms like these (in Manchester notation... RDF/XML or Turtle would be OK, too):
Class: obo:DRON_00027869
Annotations:
rdfs:label "rosuvastatin Oral Tablet"^^xsd:string,
obo:DRON_00010000 "402354"^^xsd:string
SubClassOf:
obo:DRON_00000022,
<http://www.obofoundry.org/ro/ro.owl#has_proper_part> some
(obo:OBI_0000576
and (obo:BFO_0000053 some obo:DRON_00000028)
and (obo:BFO_0000071 some obo:DRON_00018679))
Run through https://github.com/turbomam/owl2sparql4turbo/blob/master/src/main/scala/ROTS.scala...
import java.io.File
import scala.compat.java8.StreamConverters.RichStream
import org.aksw.owl2sparql.OWLClassExpressionToSPARQLSubClassQueryConverter
import org.semanticweb.owlapi.apibinding.OWLManager
import org.semanticweb.owlapi.model.IRI
import org.semanticweb.owlapi.search.EntitySearcher
object ROTS {
// SPARQL searches for Rosuvastatin Oral Tablet classes
def main(args: Array[String]): Unit = {
var manager = OWLManager.createOWLOntologyManager()
var ontology = manager.loadOntologyFromOntologyDocument(new File("rots.owl"))
// use a factory to convert stings to IRI objects
var factory = manager.getOWLDataFactory()
var termIRI = IRI.create("http://purl.obolibrary.org/obo/DRON_00081385")
var someClass = factory.getOWLClass(termIRI)
var classSupers = EntitySearcher.getSuperClasses(someClass, ontology).toScala[Stream]
var oneSuper = classSupers(0)
var scConverter = new OWLClassExpressionToSPARQLSubClassQueryConverter()
var targetVar = "?x"
var queryStr = scConverter.convert(oneSuper, targetVar)
println(queryStr)
}
}
generates the output:
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
SELECT ?x WHERE { ?x rdf:type owl:Class ;
rdfs:subClassOf [ rdf:type owl:Restriction ;
owl:onProperty <http://www.obofoundry.org/ro/ro.owl#has_proper_part> ;
owl:someValuesFrom [ owl:intersectionOf ( <http://purl.obolibrary.org/obo/OBI_0000576>
[ rdf:type owl:Restriction ;
owl:onProperty <http://purl.obolibrary.org/obo/BFO_0000053> ;
owl:someValuesFrom <http://purl.obolibrary.org/obo/DRON_00000029>
]
[ rdf:type owl:Restriction ;
owl:onProperty <http://purl.obolibrary.org/obo/BFO_0000071> ;
owl:someValuesFrom <http://purl.obolibrary.org/obo/CHEBI_30618>
]
) ;
rdf:type owl:Class
]
] .
}

Related

Join has cross-product in SPARQL query

I am trying to come up with a trivial minimal functional example of a federated query not using any web interface or something, but a local query engine (in my case AG free tier).
Now this at least doesn't throw any errors and returns stuff, but I'm getting a warning that the query contains a cross-product. Now I guess the problem is that there is nothing that actually relates the results from the two endpoints.
join has cross-product. Unique LHS variables: ?actor_1_1, ?birthDate, ?spouseURI_1_2, ?spouseName; Unique RHS variables ?actor_2_1, ?gender
But how do I relate them then? In a generic manner, since I guess this information needs to be passed to the query-resolver, and eventually I'll query other databases.
PREFIX dbpo: <http://dbpedia.org/ontology/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX wdt: <http://www.wikidata.org/prop/direct/>
SELECT ?birthDate ?spouseName ?gender {
{ SERVICE <https://dbpedia.org/sparql>
{ SELECT ?birthDate ?spouseName WHERE {
?actor rdfs:label "Arnold Schwarzenegger"#en ;
dbpo:birthDate ?birthDate ;
dbpo:spouse ?spouseURI .
?spouseURI rdfs:label ?spouseName .
FILTER ( lang(?spouseName) = "en" )
}
}
}
{ SERVICE <https://query.wikidata.org/sparql>
{ SELECT ?gender WHERE {
?actor wdt:P1559 "Arnold Alois Schwarzenegger"#de .
?actor wdt:P21 ?gender .
}
}
}
}
I'd appreciate any help here, I haven't had as hard a time getting into a subject since forever.

SPARQLRule not constructing

I have a Nodeshape with a sh:SPARQLTarget and a sh:SPARQLRule. I tried to run both Target and Rule as Queries and both deliver results, but when I'm executing the Shapes with the Apache Jena SHACL Processor, it won't construct any triples. Did I do something wrong? I'm out of ideas.
Here is my Nodeshape:
iep:hasKG331
a rdf:Property, sh:NodeShape ;
sh:Target [
a sh:SPARQLTarget ;
sh:select """
PREFIX express: <https://w3id.org/express#>
PREFIX ifcowl: <http://standards.buildingsmart.org/IFC/DEV/IFC4/ADD1/OWL#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX iep: <https://www.inf.bi.rub.de/semweb/ns/ifc-enrichment-procedure/iep#>
SELECT ?this
WHERE {
?this rdf:type ifcowl:IfcWallStandardCase .
?relDefinesByProperties ifcowl:relatedObjects_IfcRelDefines ?this .
?relDefinesByProperties ifcowl:relatingPropertyDefinition_IfcRelDefinesByProperties ?pset .
}
""" ;
] ;
sh:rule [
a sh:SPARQLRule ;
sh:construct """
PREFIX express: <https://w3id.org/express#>
PREFIX ifcowl: <http://standards.buildingsmart.org/IFC/DEV/IFC4/ADD1/OWL#>
PREFIX iep: <xxx/ifc-enrichment-procedure/iep#>
CONSTRUCT {
$this iep:hasKG iep:hasKG331 .
}
WHERE {
?relDBP ifcowl:relatedObjects_IfcRelDefines $this .
?relDBP ifcowl:relatingPropertyDefinition_IfcRelDefinesByProperties ?propSet .
?propSet ifcowl:hasProperties_IfcPropertySet ?psv1 .
?propSet ifcowl:hasProperties_IfcPropertySet ?psv2 .
?psv1 iep:isExternal true .
?psv2 iep:isLoadBearing true .
}
""" ;
] .
As I mentioned, when I execute the Target or the Rule as single queries, I do get results and the Focus Nodes from the Target do come up as $this in the Rule. The IRIs iep:isExternal and iep:isLoadBearing got inferenced in a step before. Am I missing something?
Without looking at details, the sh:Target needs to be sh:target with lower-case t. All property names are typically lower-case.

How to list root classes of an ontology in SPARQL?

I am trying to list root classes of the NIF ontology which is an ontology created of several other ontologies as its modules.
I use this code from an online resource:
SELECT ?directSub ?super
WHERE { ?directSub rdfs:subClassOf ?super .
FILTER NOT EXISTS {
?directSub rdfs:subClassOf ?otherSub .
FILTER (?otherSub != ?directSub)
}
}
The logic of the code seems fine but it does not return any answers (even when I test it on other ontologies)! Why is that?
The #UninformedUser's answer works fine. However, there is an exception that does not work with that solution, which is a root class without any child. The solution assumes that all roots have subclasses, which is not always true.
The following piece of code can find these classes:
SELECT DISTINCT ?exClass
WHERE {
?exClass rdf:type owl:Class
FILTER NOT EXISTS { ?subClass rdfs:subClassOf ?exClass }
FILTER NOT EXISTS { ?exClass rdfs:subClassOf ?supClass }}
Hence, the full SPARQL query for finding all root nodes is:
SELECT DISTINCT ?rootClass
WHERE {{
?rootClass rdf:type owl:Class .
?subClass rdf:type owl:Class .
?subClass rdfs:subClassOf ?rootClass
FILTER NOT EXISTS {
?rootClass rdfs:subClassOf ?otherSup
FILTER (?otherSup != owl:Thing)}
} UNION {
?rootClass rdf:type owl:Class
FILTER NOT EXISTS { ?subClass rdfs:subClassOf ?rootClass }
FILTER NOT EXISTS { ?rootClass rdfs:subClassOf ?supClass }}}
I am sure that the above pieces of code can be improved, however, I am just a beginner. I really would appreciate it if someone can provide tips on how to improve it.

How to stack SpinSail on top of GraphDB remote repository

I am using GraphDB to store my triples and need to stack SpinSail component upon the GraphDB to support Spin Rules along with all the rest of the features that GraphDB supports by default.
So far I have managed to create a SailRepository on the remote server supporting Spin Rules (more details below) but it seems that it only supports Spin and none of the other features that GraphDB supports (e.g. reviewing the Graph, adding triples through files, searching etc.)
The configuration file, once the repository is created, looks like below:
#prefix ms: <http://www.openrdf.org/config/sail/memory#> .
#prefix rep: <http://www.openrdf.org/config/repository#> .
#prefix sail: <http://www.openrdf.org/config/sail#> .
#prefix sr: <http://www.openrdf.org/config/repository/sail#> .
#prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
<#Test1> a rep:Repository;
rep:repositoryID "Test1";
rep:repositoryImpl [
rep:repositoryType "openrdf:SailRepository";
sr:sailImpl [
sail:delegate [
sail:sailType "openrdf:MemoryStore";
ms:persist true
];
sail:sailType "openrdf:SpinSail"
]
] .
Although a normal configuration file (i.e. if someone would create a repository through the workbench) would look like the one below:
#prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
#prefix rep: <http://www.openrdf.org/config/repository#> .
#prefix sail: <http://www.openrdf.org/config/sail#> .
#prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
<#Test> a rep:Repository;
rep:repositoryID "Test";
rep:repositoryImpl [
rep:repositoryType "graphdb:FreeSailRepository";
<http://www.openrdf.org/config/repository/sail#sailImpl> [
<http://www.ontotext.com/trree/owlim#base-URL> "http://example.org/owlim#";
<http://www.ontotext.com/trree/owlim#check-for-inconsistencies> "false";
<http://www.ontotext.com/trree/owlim#defaultNS> "";
<http://www.ontotext.com/trree/owlim#disable-sameAs> "false";
<http://www.ontotext.com/trree/owlim#enable-context-index> "false";
<http://www.ontotext.com/trree/owlim#enable-literal-index> "true";
<http://www.ontotext.com/trree/owlim#enablePredicateList> "true";
<http://www.ontotext.com/trree/owlim#entity-id-size> "32";
<http://www.ontotext.com/trree/owlim#entity-index-size> "10000000";
<http://www.ontotext.com/trree/owlim#imports> "";
<http://www.ontotext.com/trree/owlim#in-memory-literal-properties> "true";
<http://www.ontotext.com/trree/owlim#query-limit-results> "0";
<http://www.ontotext.com/trree/owlim#query-timeout> "0";
<http://www.ontotext.com/trree/owlim#read-only> "false";
<http://www.ontotext.com/trree/owlim#repository-type> "file-repository";
<http://www.ontotext.com/trree/owlim#ruleset> "owl2-rl-optimized";
<http://www.ontotext.com/trree/owlim#storage-folder> "storage";
<http://www.ontotext.com/trree/owlim#throw-QueryEvaluationException-on-timeout> "false";
sail:sailType "graphdb:FreeSail"
]
];
rdfs:label "Test" .
The following code was used to create the repository.
RemoteRepositoryManager manager = new RemoteRepositoryManager("http://localhost:7200");
manager.init();
String repositoryId = "Test1";
// create a configuration for the SAIL stack
boolean persist = true;
// create a configuration for the SAIL stack
SailImplConfig spinSailConfig = new MemoryStoreConfig(persist);
spinSailConfig = new SpinSailConfig(spinSailConfig);
RepositoryImplConfig repositoryTypeSpec = new SailRepositoryConfig(spinSailConfig);
// create a configuration for the repository implementation
// RepositoryImplConfig repositoryTypeSpec = new SailRepositoryConfig(backendConfig);
RepositoryConfig repConfig = new RepositoryConfig(repositoryId, repositoryTypeSpec);
manager.addRepositoryConfig(repConfig);
Once I created this repository I was able to insert the following rule into it through the SPARQL section (by using INSERT DATA):
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX sp: <http://spinrdf.org/sp#>
PREFIX spin: <http://spinrdf.org/spin#>
PREFIX ex: <http://example.org/>
INSERT DATA {
ex:Person a rdfs:Class ;
spin:rule [
a sp:Construct ;
sp:text """PREFIX ex: <http://example.org/>
CONSTRUCT { ?this ex:childOf ?parent . }
WHERE { ?parent ex:parentOf ?this . }"""
] . }
and then similarly add the following statements:
PREFIX ex: <http://example.org/>
INSERT DATA {
ex:John a ex:Father ;
ex:parentOf ex:Lucy .
ex:Lucy a ex:Person .
}
After that by running the following query:
PREFIX ex: <http://example.org/>
SELECT ?child WHERE { ?child ex:childOf ?parent }
I was able to confirm that the Spin rule was executed successfully.
So my question is:
Is there a way to create a remote repository supporting all the features of GraphDB and then stack upon it the SpinSail component?
As of the moment GraphDB (version 8.10.0) does not support SpinSail. Such option is under consideration for one of the next GraphDB releases.

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
] .