I want to design an object property which is always linked only between the same level of classes. For example,
I want to limit the property isCounterPartOf to be an arc of the sibling nodes which belong to the same upper class, such as
house isCounterPartOf cars
bad isCounterPartOf good
slow isCounterPartOf fast
and the property should NOT link between classes of different levels (those having different ancestors), like
cars isCounterPartOf bad
cars isCounterPartOf object
cars isCounterPartOf Entity
Is there a way to do this with defining only one property?
Assuming your objective is when :isCounterPartOf links two individuals, and one is a member of e.g. :Bad, then the other should be classified as :Good, you don't need to define domain and range of :isCounterPartOf, just that it is owl:SymmetricProperty. You only need to define your classes, :Bad to be equivalent of :isCounterPartOf some :Good and :Good to be equivalent of :isCounterPartOf some :Bad, and for all "pairs" of classes respectively.
Then if:
:A :isCounterPartOf :B
:C :isCounterPartOf :B
:A a :Slow
:C a :Bad
then :B will be classified as :Fast and :Good.
Clarification (based on the comments)
In the example above,
1. :isCouterPartOf is a symetric object property:
:isCounterPartOf rdf:type owl:ObjectProperty ,
owl:SymmetricProperty .
:Good, :Bad, :Slow and :Fast are OWL classes, for which:
(no idea why the code formatting doesn't work)
:Bad rdf:type owl:Class ;
owl:equivalentClass [ rdf:type owl:Restriction ;
owl:onProperty :isCounterPartOf ;
owl:someValuesFrom :Good
] .
:Fast rdf:type owl:Class ;
owl:equivalentClass [ rdf:type owl:Restriction ;
owl:onProperty :isCounterPartOf ;
owl:someValuesFrom :Slow
] .
:Good rdf:type owl:Class ;
owl:equivalentClass [ rdf:type owl:Restriction ;
owl:onProperty :isCounterPartOf ;
owl:someValuesFrom :Bad
] .
:Slow rdf:type owl:Class ;
owl:equivalentClass [ rdf:type owl:Restriction ;
owl:onProperty :isCounterPartOf ;
owl:someValuesFrom :Fast
] .
:A, :B, and :C are individuals, for which it is asserted that:
(again, no idea why the code formatting doesn't work)
:A rdf:type owl:NamedIndividual ,
:Slow ;
:isCounterPartOf :B .
:B rdf:type owl:NamedIndividual ,
owl:Thing .
:C rdf:type owl:NamedIndividual ,
:Bad ;
:isCounterPartOf :B .
Based on these assertions, when you run the reasoner, you'll have the following situation:
:A rdf:type owl:NamedIndividual ,
:Bad , #inferred
:Slow ;
:isCounterPartOf :B .
:B rdf:type owl:NamedIndividual ,
:Fast , #inferred
:Good , #inferred
owl:Thing ;
:isCounterPartOf :A , #inferred
:C . #inferred
:C rdf:type owl:NamedIndividual ,
:Bad ,
:Slow ; #inferred
:isCounterPartOf :B .
Related
For example 1 :
Classes : A and B.
Property : hasValue.
Axiom : hasValue some A disjointWith hasValue some B.
Individual : user1.
user1 hasValue A.
user1 hasValue B.
Protege reasoner (HermiT) throws no error.
For example 2 :
Classes : A and B.
A disjoint with B.
Property : hasValue.
Axiom : hasValue some A disjointWith hasValue some B.
Individual : user1.
user1 hasValue A.
user1 hasValue B.
Protege reasoner (HermiT) throws error.
Shouldn't "hasValue some A disjointWith hasValue some B" alone be sufficient to throw error in eg 1's case?
EDIT : example 1's reasoner result is wrong. As #Henriette Harmse showed below reasoner will throw error.
I was doing declaring Axiom a little differently than what I wrote above. I declared axiom as "hasValue some B DisjointWith hasValue some
(P and (not (B)))", where P is parent class of both A and B. (Full sample ontology below.) If you import it in protege and run, you'll not get error.
It seems :
"hasValue some B DisjointWith hasValue some A"
"hasValue some B DisjointWith hasValue some (P and (not (B)))"
are not equivalent statements.
Sample ontology :
#prefix : <http://test.org/#> .
#prefix owl: <http://www.w3.org/2002/07/owl#> .
#prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
#prefix xml: <http://www.w3.org/XML/1998/namespace> .
#prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
#prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
#base <http://test.org/> .
<http://test.org/> rdf:type owl:Ontology .
#################################################################
# Object Properties
#################################################################
### http://test.org/#hasValue
:hasValue rdf:type owl:ObjectProperty .
#################################################################
# Classes
#################################################################
### http://test.org/#A
:A rdf:type owl:Class ;
rdfs:subClassOf :P .
### http://test.org/#B
:B rdf:type owl:Class ;
rdfs:subClassOf :P .
### http://test.org/#P
:P rdf:type owl:Class .
### http://test.org/#USER
:USER rdf:type owl:Class .
#################################################################
# Individuals
#################################################################
### http://test.org/#A
:A rdf:type owl:NamedIndividual ,
:A .
### http://test.org/#B
:B rdf:type owl:NamedIndividual ,
:B .
### http://test.org/#user1
:user1 rdf:type owl:NamedIndividual ;
:hasValue :A ,
:B .
#################################################################
# General axioms
#################################################################
[ rdf:type owl:Restriction ;
owl:onProperty :hasValue ;
owl:someValuesFrom :A ;
owl:disjointWith [ rdf:type owl:Restriction ;
owl:onProperty :hasValue ;
owl:someValuesFrom [ owl:intersectionOf ( :P
[ rdf:type owl:Class ;
owl:complementOf :A
]
) ;
rdf:type owl:Class
]
]
] .
[ rdf:type owl:Restriction ;
owl:onProperty :hasValue ;
owl:someValuesFrom :B ;
owl:disjointWith [ rdf:type owl:Restriction ;
owl:onProperty :hasValue ;
owl:someValuesFrom [ owl:intersectionOf ( :P
[ rdf:type owl:Class ;
owl:complementOf :B
]
) ;
rdf:type owl:Class
]
]
] .
### Generated by the OWL API (version 4.5.9.2019-02-01T07:24:44Z) https://github.com/owlcs/owlapi
I have tried this now myself and for your first example I get an inconsistency with the following explanation:
Here is the actual ontology giving the inconsistency. I will need to see your actual ontology to understand why you are not getting an inconsistency.
<?xml version="1.0"?>
<rdf:RDF xmlns="http://www.semanticweb.org/henri/ontologies/2022/6/untitled-ontology-9#"
xml:base="http://www.semanticweb.org/henri/ontologies/2022/6/untitled-ontology-9"
xmlns:owl="http://www.w3.org/2002/07/owl#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:xml="http://www.w3.org/XML/1998/namespace"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:untitled-ontology-9="http://www.semanticweb.org/henri/ontologies/2022/6/untitled-ontology-9#">
<owl:Ontology rdf:about="http://www.semanticweb.org/henri/ontologies/2022/6/untitled-ontology-9"/>
<owl:ObjectProperty rdf:about="http://www.semanticweb.org/henri/ontologies/2022/6/untitled-ontology-9#hasValue"/>
<owl:Class rdf:about="http://www.semanticweb.org/henri/ontologies/2022/6/untitled-ontology-9#A"/>
<owl:Class rdf:about="http://www.semanticweb.org/henri/ontologies/2022/6/untitled-ontology-9#B"/>
<owl:NamedIndividual rdf:about="http://www.semanticweb.org/henri/ontologies/2022/6/untitled-ontology-9#a">
<rdf:type rdf:resource="http://www.semanticweb.org/henri/ontologies/2022/6/untitled-ontology-9#A"/>
</owl:NamedIndividual>
<owl:NamedIndividual rdf:about="http://www.semanticweb.org/henri/ontologies/2022/6/untitled-ontology-9#b">
<rdf:type rdf:resource="http://www.semanticweb.org/henri/ontologies/2022/6/untitled-ontology-9#B"/>
</owl:NamedIndividual>
<owl:NamedIndividual rdf:about="http://www.semanticweb.org/henri/ontologies/2022/6/untitled-ontology-9#user1">
<hasValue rdf:resource="http://www.semanticweb.org/henri/ontologies/2022/6/untitled-ontology-9#a"/>
<hasValue rdf:resource="http://www.semanticweb.org/henri/ontologies/2022/6/untitled-ontology-9#b"/>
</owl:NamedIndividual>
<owl:Restriction>
<owl:onProperty rdf:resource="http://www.semanticweb.org/henri/ontologies/2022/6/untitled-ontology-9#hasValue"/>
<owl:someValuesFrom rdf:resource="http://www.semanticweb.org/henri/ontologies/2022/6/untitled-ontology-9#A"/>
<owl:disjointWith>
<owl:Restriction>
<owl:onProperty rdf:resource="http://www.semanticweb.org/henri/ontologies/2022/6/untitled-ontology-9#hasValue"/>
<owl:someValuesFrom rdf:resource="http://www.semanticweb.org/henri/ontologies/2022/6/untitled-ontology-9#B"/>
</owl:Restriction>
</owl:disjointWith>
</owl:Restriction>
</rdf:RDF>
Update after reviewing ACTUAL ontology
The main problem is that you stated the GCI you used incorrectly. What you said you used are substantially different from what you actually used.
What you said used: hasValue some A disjointWith hasValue some B
What you actually used:
hasValue some A DisjointWith hasValue some (P and (not (A)))
hasValue some B DisjointWith hasValue some (P and (not (B)))
To understand why your GCIs do not have the desired effect, I have drawn an example Venn diagram:
Note that hasValue some A DisjointWith hasValue some (P and (not (A))) states that there is no individual x that belongs to both the set hasValue some A and the set hasValue some (P and (not (A))). It does however allow for the possibility that you have an individual user1 that is related via hasValue to an individual in set A and that is related via hasValue to an individual in set B. This is because nothing prohibits the sets hasValue some A (to which user1 hasValue A belongs) and hasValue some B (to which user1 hasValue B belongs)` to overlap. To prohibit this, you have to add the following GCI:
hasValue some A DisjointWith hasValue some B
How to get a inconsistency using you GCIs
To get an inconsistency using your GCIs, you have to have an individual that actually belong to the disjoint sets you defined. I.e.,
Define individual x as follows:
:x rdf:type owl:NamedIndividual ,
[ owl:intersectionOf ( :P
[ rdf:type owl:Class ;
owl:complementOf :A
]
) ;
rdf:type owl:Class
] .
and then define user2:
:user2 rdf:type owl:NamedIndividual ;
:hasValue :A ,
:x .
You will get an inconsistency with the following explanation:
Please I have two questions ;
Q1: I have implemented the ChildlessPerson class in Protege 5.5.0 and defined an individual of type person with no haschild property. I tried with Hermet, Pellet, ontop, none derives that the individual is a ChildlessPerson.
:ChildlessPerson rdf:type OWL:Class ;
rdfs:subClassOf [ rdf:type OWL:Class ; OWL:intersectionOf ( :Person
[ rdf:type OWL:Class ;
OWL:complementOf [ rdf:type OWL:Restriction ;
OWL:onProperty :hasChild ; OWL:someValuesFrom OWL:Thing]
] ) ] .
Q2 : In the ontology I have Parent subclassOf Person and Father subclassOf Parent. I defined an individual of typefather, it is inferred that it is a parent, but the fact that is a person is not inferred. I checked also with Pellet incremental. Why ?
:Father rdf:type OWL:Class ; rdfs:subClassOf :Parent; OWL:disjointWith :Mother.
:Mother rdf:type OWL:Class ; rdfs:subClassOf :Parent.
:Parent rdf:type OWL:Class ; rdfs:subClassOf :Person.
:Person: rdf:type OWL:Class ; rdfs:comment "Represents the set of all people."
Thanks in advance.
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
] .
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 an ontology with Person and City classes. People travel to cities and this travel is represented in the traveledTo object property. I'd like to add a WorldTraveler class. People are world travelers if they have traveled to 2 or more cities. How can I do this in my ontology?
#prefix : <http://www.semanticweb.org/chris/ontologies/2017/9/untitled-ontology-64#> .
#prefix owl: <http://www.w3.org/2002/07/owl#> .
#prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
#prefix xml: <http://www.w3.org/XML/1998/namespace> .
#prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
#prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
#base <http://www.semanticweb.org/chris/ontologies/2017/9/untitled-ontology-64> .
<http://www.semanticweb.org/chris/ontologies/2017/9/untitled-ontology-64> rdf:type owl:Ontology .
:traveledTo rdf:type owl:ObjectProperty ;
rdfs:domain :Person ;
rdfs:range :City .
:City rdf:type owl:Class .
:Person rdf:type owl:Class .
:Bob rdf:type owl:NamedIndividual ,
:Person ;
:traveledTo :London ,
:Ottawa ,
:Paris .
:Brussels rdf:type owl:NamedIndividual ,
:City .
:London rdf:type owl:NamedIndividual ,
:City .
:Ottawa rdf:type owl:NamedIndividual ,
:City .
:Paris rdf:type owl:NamedIndividual ,
:City .
:Ralph rdf:type owl:NamedIndividual ,
:Person ;
:traveledTo :Rome .
:Rome rdf:type owl:NamedIndividual ,
:City .
:Washington rdf:type owl:NamedIndividual ,
:City .
I tried adding the following Class but it didn't seem to work:
:WorldTraveler rdf:type owl:Class ;
owl:equivalentClass [ owl:intersectionOf ( :Person
[ rdf:type owl:Restriction ;
owl:onProperty :traveledTo ;
owl:minQualifiedCardinality "2"^^xsd:nonNegativeInteger ;
owl:onClass :City
]
) ;
rdf:type owl:Class
] .
I believe that my reasoner may not be able to infer that Ralph is not a WorldTraveler because of the open world assumption. However, it should be able to infer that Bob is a WorldTraveler because he has traveled to 3 cities.
Thanks for your help.
Chris
In addition to the open world assumption (OWA), there exists the unique name assumption (UNA). OWL does make the former (OWA) and does not make the latter (UNA).
You should explicitely make individuals different.
In the Turtle syntax, it should look like this:
:London owl:differentFrom :Paris .
or
[ rdf:type owl:AllDifferent ;
owl:distinctMembers ( :Brussels :London :Ottawa :Paris :Rome :Washington )
] .