I need to implement an OWL-ontology in Protégé, which contains a two classes: s1 and s2, both are the instances of System class. These two classes are connected by the connection class s1_s2, which contains property omega. This property has to take a value according to the following law:
omega = 1 * s1.complete
How can I implement it in Protégé in a such way, I could use it in SWRL-rule in the future?
In general, you'd start by defining the classes and the properties that you need:
At this point you could add some axioms that govern how the systems have to interact, how the properties work, etc. E.g., you might declare domains and ranges on your properties. Here's a domain and range on the hasS2 property:
You might also want to say that each InterSystem has exactly one associate S1 and S2:
To put in the mathematical constraints, you'll actually need SWRL; you won't be able to enforce the constraint using other kinds of OWL axioms. The rule you'd want is along the lines of the following. If you declare domains and ranges on your predicates, then you won't need all the type predicates that appear in this rule, since they could be inferred from the property usage.
S1(?s1) ∧ InterSystem(?i) ∧ hasS1(?i,?s1) ∧
hasComplete(?s1,?complete) multiply(?omega,1,?complete) →
hasOmega(?i,?omega)
The multiplication here actually seems redundant, since you're multiplying by 1, so omega = alpha, in which case the head of that rule could simply be hasOmega(?i,?alpha). In Protégé the rule looks like this:
(In the version of Protégé that I'm using (not the latest), I had to Window > Create New Tab to create a Rules tab, and then Window > Views > Ontology Views > Rules to add the Rules list to the interface.)
The Turtle serialization of the RDF representation of this OWL ontology (which you can save and load into Protégé) is:
#prefix : <http://stackoverflow.com/q/21499126/1281433/systems#> .
#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#> .
<urn:swrl#s1> a swrl:Variable .
:hasComplete a owl:DatatypeProperty .
[ a swrl:Imp ;
swrl:body [ a swrl:AtomList ;
rdf:first [ a swrl:ClassAtom ;
swrl:argument1 <urn:swrl#i> ;
swrl:classPredicate :InterSystem
] ;
rdf:rest [ a swrl:AtomList ;
rdf:first [ a swrl:ClassAtom ;
swrl:argument1 <urn:swrl#s1> ;
swrl:classPredicate :S1
] ;
rdf:rest [ a swrl:AtomList ;
rdf:first [ a swrl:IndividualPropertyAtom ;
swrl:argument1 <urn:swrl#i> ;
swrl:argument2 <urn:swrl#s1> ;
swrl:propertyPredicate :hasS1
] ;
rdf:rest [ a swrl:AtomList ;
rdf:first [ a swrl:DatavaluedPropertyAtom ;
swrl:argument1 <urn:swrl#s1> ;
swrl:argument2 <urn:swrl#complete> ;
swrl:propertyPredicate :hasComplete
] ;
rdf:rest [ a swrl:AtomList ;
rdf:first [ a swrl:BuiltinAtom ;
swrl:arguments [ a rdf:List ;
rdf:first <urn:swrl#omega> ;
rdf:rest [ a rdf:List ;
rdf:first 1 ;
rdf:rest ( <urn:swrl#complete> )
]
] ;
swrl:builtin swrlb:multiply
] ;
rdf:rest ()
]
]
]
]
] ;
swrl:head [ a swrl:AtomList ;
rdf:first [ a swrl:DatavaluedPropertyAtom ;
swrl:argument1 <urn:swrl#i> ;
swrl:argument2 <urn:swrl#omega> ;
swrl:propertyPredicate :hasOmega
] ;
rdf:rest ()
]
] .
:S2 a owl:Class ;
rdfs:subClassOf :System .
<urn:swrl#omega> a swrl:Variable .
:S1 a owl:Class ;
rdfs:subClassOf :System .
:InterSystem a owl:Class ;
rdfs:subClassOf [ a owl:Restriction ;
owl:onClass :S1 ;
owl:onProperty :hasS1 ;
owl:qualifiedCardinality "1"^^xsd:nonNegativeInteger
] ;
rdfs:subClassOf [ a owl:Restriction ;
owl:onClass :S2 ;
owl:onProperty :hasS2 ;
owl:qualifiedCardinality "1"^^xsd:nonNegativeInteger
] .
<urn:swrl#complete> a swrl:Variable .
<http://stackoverflow.com/q/21499126/1281433/systems>
a owl:Ontology .
:hasS2 a owl:ObjectProperty .
:hasOmega a owl:DatatypeProperty .
:System a owl:Class .
:hasS1 a owl:ObjectProperty .
<urn:swrl#i> a swrl:Variable .
That's a good start, but it's worthwhile to see how it all works. To see a place where the rules could be applied, we'll need some instance data and a reasoner. You mentioned that you can use Pellet from within Protégé, so we're all set on that count. For some instance data, let's create and InterSystem, its S1, and assign the S1's complete value.
You'll need to select the Pellet reasoner from the Reasoner menu, and then select Reasoner > Start Reasoner. At this point, you could run a DL query for “hasOmega value 42” to confirm that the individual has the desired property (make sure that you check the “Individuals” checkbox on the right):
If you navigate to the intersystem individual, you probably won't see the inferred value though. To show it, go to Reasoner > Configure… and check the Data Property Assertions option:
After that, you may need to restart the reasoner (Reasoner > None; Reasoner > Pellet; Reasoner > Start Reasoner), but afterward you'll be able to see the inferred values:
Related
I have the following small ontology, with two classes ("DataSubject" and "Minor"), one property has-age from DataSubject(s) to xsd:positiveInteger, and one individual ("John", who is a DataSubject and has-age equal to 20).
ontology:DataSubject
rdf:type owl:Class ;
rdfs:subClassOf owl:Thing ;
owl:disjointWith ontology:Minor ;
owl:disjointWith owl:NamedIndividual ;
.
ontology:John
rdf:type ontology:DataSubject ;
ontology:has-age "20"^^xsd:positiveInteger ;
.
ontology:Minor
rdf:type owl:Class ;
rdfs:subClassOf owl:Thing ;
owl:disjointWith ontology:DataSubject ;
owl:disjointWith owl:NamedIndividual ;
.
ontology:has-age
rdf:type owl:DatatypeProperty ;
rdfs:domain ontology:DataSubject ;
rdfs:range xsd:positiveInteger ;
.
The following SHACL rule SHOULD mark as Minor all DataSubject(s) whose age is lower than 16.
rules:WhenDataSubjectIsMinor
rdf:type sh:NodeShape ;
sh:rule [
rdf:type sh:TripleRule ;
#IF: "the age of the Data Subject is lower than 16"
sh:condition [
sh:property [
sh:path ontology:has-age;
sh:lessThan "16"^^xsd:positiveInteger ;
] ;
] ;
#THEN: "the Data Subject is marked as type Minor"
sh:subject sh:this ;
sh:predicate rdf:type;
sh:object ontology:Minor ;
] ;
sh:targetClass ontology:DataSubject ;
.
However, the following Java code infers John as Minor... but John is not, he is 20 years old! Of course the rule is not correct, specifically the instruction "sh:lessThan "16"^^xsd:positiveInteger ;".
How can I compare datatype properties with given constants?
Thanks in advance!
Livio
public static void main(String[] args) throws Exception
{
//Load the ontology
Model ontology = JenaUtil.createMemoryModel();
FileInputStream fisOntology = new FileInputStream("./ontology.ttl");
ontology.read(fisOntology, "urn:dummy", FileUtils.langTurtle);
//Load the rules
Model rules = JenaUtil.createMemoryModel();
FileInputStream fisRules = new FileInputStream("./rules.ttl");
rules.read(fisRules, "urn:dummy", FileUtils.langTurtle);
//Executing the rule and print
Model inferredTriples = RuleUtil.executeRules(ontology, rules, null, null);
System.out.println(ModelPrinter.get().print(inferredTriples));
}
sh:lessThan is used to establish relationships between two properties, e.g. date of birth sh:lessThan date of marriage. What you need is sh:maxExclusive.
See the SHACL spec for details, e.g. https://www.w3.org/TR/shacl/#LessThanConstraintComponent
I need to express the fact that the allowed values of an ObjectProperty in my ontology are "controlled" by Concepts from a specific SKOS ConceptScheme.
EDIT:
Here is an example:
ex:colours rdf:type skos:ConceptScheme ;
skos:hasTopConcept ex:teal ;
skos:hasTopConcept ex:green .
ex:teal rdf:type skos:Concept ;
skos:inScheme ex:colours ;
skos:topConceptOf ex:colours .
ex:green rdf:type skos:Concept ;
skos:inScheme ex:colours ;
skos:topConceptOf ex:colours .
ex:P_has_colour rdf:type owl:ObjectProperty ;
rdfs:domain ex:ColoredStuff ;
rdfs:range ??? .
I want to express the fact that the values of the ex:P_has_colour ObjectProperty must be a Concept from the ex:colours SKOS ConceptScheme. I think I can add a type to each and every SKOS Concept which denotes a colour (something like ex:teal rdf:type ex:ColourConcept ;), and set the range of my property: ex:P_has_colour rdfs:range ex:ColourConcept. Is this the right way to go?
Translated from Manchester syntax to turtle, this seems to be the answer:
ex:colours rdf:type skos:ConceptScheme ;
skos:hasTopConcept ex:teal ;
skos:hasTopConcept ex:green .
ex:teal rdf:type skos:Concept ;
skos:inScheme ex:colours ;
skos:topConceptOf ex:colours .
ex:green rdf:type skos:Concept ;
skos:inScheme ex:colours ;
skos:topConceptOf ex:colours .
ex:P_has_colour rdf:type owl:ObjectProperty ;
rdfs:domain ex:ColoredStuff ;
rdfs:range [ owl:intersectionOf ( :ConceptScheme
[ rdf:type owl:Restriction ;
owl:onProperty :inScheme ;
owl:hasValue :colours
]
) ;
rdf:type owl: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) ∧ Action(?a) → hasAction(?v,?a)
Car(?v) ∧ CarAction(?a) → hasAction(?v,?a)
Truck(?v) ∧ TruckAction(?a) → 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 ⊑ RCar • topObjectProperty • 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) ∧ topObjectProperty(?c,?a) ∧ RCarAction(?a,?a) → 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
] .
I have the following Turtle syntax file (see end of question), and I would like to be able to infer :hasSibling, but only full siblings, not half. i.e. I only want those children that share the same mother and father.
I have reviewed How to infer isBrotherOf property between two individuals, which solves half of the problem. The following SPARQL query:
PREFIX : <http://example.com/Test#>
SELECT DISTINCT *
WHERE {
?child :isSiblingOf ?sibling .
FILTER ( ?child = :jennySmith )
}
returns:
:jimJones - half-sibling, don't want
:joeSmith
:jennySmith - self, not ideal, but I can live with it
I've tried to use owl:intersectionOf and provide 2 sets, one using :hasFather in an owl:propertyChainAxiom and the other using :hasMother but that intersection is empty (it's possible -- likely -- I've got the syntax wrong, or that the 2 property chains are in fact returning different "things" -- I don't have a strong grasp of OWL yet):
:x1
a owl:Restriction ;
owl:intersectionOf (
[
owl:propertyChainAxiom(
:hasFather
:isParentOf
) ] [
owl:propertyChainAxiom(
:hasMother
:isParentOf
)
]
)
.
Another possibility is that such a thing is just not possible with OWL.
I have the repository in GraphDB set up with OWL2-RL. Please ignore that there are existing ontologies to define family trees, and that OWL might not be the best way to represent them. My goal is not to create a family tree, but to learn OWL restrictions and inferences. This was the MVCE I came up with to illustrate my problem.
#prefix owl: <http://www.w3.org/2002/07/owl#> .
#prefix owl2: <http://www.w3.org/2006/12/owl2#> .
#prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
#prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
#prefix xml: <http://www.w3.org/XML/1998/namespace> .
#prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
#prefix : <http://example.com/Test#> .
<file:test.ttl>
a owl:Ontology ;
.
:Person
a owl:Class ;
rdfs:subClassOf owl:Thing ;
.
:hasGender
a owl:ObjectProperty ;
rdfs:domain :Person ;
.
:Man
a owl:Class ;
rdfs:subClassOf :Person ;
owl:equivalentClass [
a owl:Restriction ;
owl:onProperty :hasGender ;
owl:hasValue :male ;
]
.
:Woman
a owl:Class ;
rdfs:subClassOf :Person ;
owl:equivalentClass [
a owl:Restriction ;
owl:onProperty :hasGender ;
owl:hasValue :female ;
]
.
:Parent
a owl:Restriction ;
rdfs:subClassOf :Person ;
owl:onProperty :isParentOf ;
owl:someValuesFrom :Person ;
.
:Child
a owl:Restriction ;
rdfs:subClassOf :Person ;
owl:onProperty :hasParent ;
owl:someValuesFrom :Person ;
.
:Father
a owl:Class ;
rdfs:subClassOf :Parent ;
owl:equivalentClass [
a owl:Restriction ;
owl:intersectionOf ( :Parent :Man ) ;
] ;
.
:Mother
a owl:Class ;
rdfs:subClassOf :Parent ;
owl:equivalentClass [
a owl:Restriction ;
owl:intersectionOf ( :Parent :Woman ) ;
] ;
owl2:disjointObjectProperties :Father ;
.
:hasFather
owl:inverseOf :isFatherOf ;
.
:hasMother
owl:inverseOf :isMotherOf ;
.
:hasParent
a owl:ObjectProperty ;
.
:isMotherOf
a owl:ObjectProperty ;
rdfs:domain :Woman ;
rdfs:range: :Child ;
rdfs:subPropertyOf :isParentOf ;
.
:isFatherOf
a owl:ObjectProperty ;
rdfs:domain :Man ;
rdfs:range: :Child ;
rdfs:subPropertyOf :isParentOf ;
.
:isParentOf
a owl:ObjectProperty ;
rdfs:domain :Person ;
rdfs:range :Person ;
owl:inverseOf :hasParent ;
.
:isSiblingOf
a owl:ObjectProperty ;
owl:propertyChainAxiom(
:hasParent
:isParentOf
)
.
:janeSmith
a :Person ;
:hasGender :female ;
:isMotherOf :jimJones ;
:isMotherOf :joeSmith ;
:isMotherOf :jennySmith ;
.
:johnSmith
a :Person ;
:hasGender :male ;
:isFatherOf :joeSmith ;
:isFatherOf :jennySmith ;
.
:tomJones
a :Person ;
:hasGender :male ;
:isFatherOf :jimJones ;
.
:jimJones
a :Person ;
:hasGender :male ;
.
:joeSmith
a :Person ;
:hasGender :male ;
.
:jennySmith
a :Person ;
:hasGender :female ;
:isMotherOf :harrySmith ;
.
:harrySmith
a :Person ;
:hasGender :male ;
.
You can define :isFullSiblingOf with a custom rule like this. Read about Constraints and Cut at http://graphdb.ontotext.com/documentation/enterprise/reasoning.html
id: isFullSiblingOf
x <:hasFather> f
x <:hasMother> m
y <:hasFather> f [Constraint x != y] [Cut]
y <:hasMother> m
----------------
x <:isSiblingOf> y
PS1: I assume you already have inverse reasoning. The best is to pick the axioms you need, then add your own: eg you don't have to include all RL axioms if you don't need them. See more advice: http://graphdb.ontotext.com/documentation/standard/rules-optimisations.html
PS2: You should also declare isFullSiblingOf as owl:SymmetricProperty. BTW I would use hasFullSibling since the inverse name is harder to grasp
PS3: owl2:disjointObjectProperties :Father above is a mistake, you can't use that on classes.
PS4: <file:test.ttl> uses a relative URL without base, which is not very good.
I have developed an ontology and I want to add the following SWRL in protege:
Divider_intersection(?node), is_extent_of(?node, ?s), builds(?s, ?l),Segment(?s),Lane(?l),detailed_partition(?d), builds(?l, ?d)-> is_divided_at(?d, ?node)
with this I wish to add an object property, is_divided_at, between an individual from detailed_partition (?d) and a node that is classified as a divider_intersection if it is the extent of a segment (?s) that build a lane (?l) which then build the detailed?partition (?d). As noted here, I am looking for NamedIndividuals, hence I presume the SWRL should do the job.
Further research, I found Rolification (1, 2, 3) as a possible answer however I have never used it before, but I made the following chain:
r_Divider_intersection o is_extent_of o r_Segment o builds o r_Lane o builds o r_detailed_partition
still I do not get the answer. Any idea what is wrong?
Your approach works, and without seeing your ontology (your link requires permissions, and offsite links aren't very helpful anyhow) we can't see why your particular construction of it works. One thing that jumps out from your question is that the it looks like your is_divided_at property has its arguments (?d,?node) in the opposite order from what the property chain axiom would produce. Anyhow, here's a working example.
#prefix : <urn:ex:#> .
#prefix ex: <urn:ex:#> .
#prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
#prefix owl: <http://www.w3.org/2002/07/owl#> .
#prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
#prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
ex:isDividedAt a owl:ObjectProperty ;
owl:propertyChainAxiom ( ex:_DividerIntersection ex:isExtentOf ex:_Segment ex:builds ex:_Lane ex:builds ex:_DetailedPartition ) .
ex:Segment a owl:Class ;
owl:equivalentClass [ a owl:Restriction ;
owl:hasSelf true ;
owl:onProperty ex:_Segment
] .
ex:_DetailedPartition
a owl:ObjectProperty .
ex:DividerIntersection
a owl:Class ;
owl:equivalentClass [ a owl:Restriction ;
owl:hasSelf true ;
owl:onProperty ex:_DividerIntersection
] .
ex:_Segment a owl:ObjectProperty .
ex:_Lane a owl:ObjectProperty .
ex:builds a owl:ObjectProperty .
ex:dividerIntersection0
a owl:NamedIndividual , ex:DividerIntersection ;
ex:isExtentOf ex:segment0 .
<urn:ex:> a owl:Ontology .
ex:detailedPartition0
a owl:NamedIndividual , ex:DetailedPartition .
ex:_DividerIntersection
a owl:ObjectProperty .
ex:segment0 a owl:NamedIndividual , ex:Segment ;
ex:builds ex:lane0 .
ex:DetailedPartition a owl:Class ;
owl:equivalentClass [ a owl:Restriction ;
owl:hasSelf true ;
owl:onProperty ex:_DetailedPartition
] .
ex:isExtentOf a owl:ObjectProperty .
ex:lane0 a owl:NamedIndividual , ex:Lane ;
ex:builds ex:detailedPartition0 .
ex:Lane a owl:Class ;
owl:equivalentClass [ a owl:Restriction ;
owl:hasSelf true ;
owl:onProperty ex:_Lane
] .