I have defined an ontology with the following classes, properties, and individuals with object property assertions:
Class: Employee > Individuals: { EmployeeA }
Class: Skill > Individuals: { Skill1, Skill2, Skill3 }
Class: Job > Individuals: { DBA }
hasSkill > Domain (Employee) and Range (Skill)
isAskillBy > Domain (Skill) and Range (Employee) <inverse of hasSkill>
requireSkill > Domain (Job) and Range (Skill)
isAskillrequiredBy > Domain (Skill) and Range (Job) <inverse of requireSkill>
Individual: EmployeeA, object property assertion: hasSkill Skill1
hasSkill Skill2
, types : hasSkill only ({Skill1,Skill2}) <to close OWA
, Negative object property assertion: hasSkill Skill3
Individual: DBA, object property assertion: requireSkill Skill1
requireSkill Skill2
requireSkill Skill3
, types : requireSkill only ({Skill1,Skill2, Skill3}) <to close OWA
To classify whether an Employee is qualified for a job (in this case, the DBA position), I created the class Fit and made it equivalent to:
Employee and (hasSkill only (isAskillrequiredBy value DBA))
When I run a reasoner in Protege, the reasoner classifies EmployeeA under the class Fit, but with the closure axioms to address the Open World Assumption (OWA), EmployeeA should not be classified as Fit, since he does not have all three skills needed for the DBA position.
First, recall what the "universal" quantification in OWL means. The class expression
p only C
is the individuals x such that if x is related to y by property p, then y must be a C. That is, p(x,y) implies C(y). Your query is returning the correct results, but the query doesn't mean exactly what you want it to mean. The query
Employee and (hasSkill only (isAskillrequiredBy value DBA))
says that something must be an Employee, and if the employee has a skill, then the skill must be one that is required by the DBA position. EmployeeA certainly meets that definition, since the skills that EmployeeA has are Skill1 and Skill2, both of which are required for the DBA position.
The problem in this query is the only. It will manifest in two different ways: (i) if someone is qualified for DBA position (i.e., has all the necessary skills), but has additional skills, then you won't retrieve them, since they have skills that aren't required for the DBA position (but maybe you don't want overqualified people); and (ii) it retrieves people all of whose skills are required for the DBA position, but doesn't require that the people actually have all the skills needed for the DBA position.
What you actually want to ask for is individuals that have all the skills necessary for the DBA position. What you'd need to check is whether an individual lacks any skills that are required for the DBA. The skills required for the DBA position can be found with:
(inverse requiresSkill) value DBA
The skills not needed for the DBA are simply the negation of that:
not ((inverse requiresSkill) value DBA)
What you'd like to say is that any skills that an individual doesn't have must be from that class. Currently, you don't have a property that connects an individual to the skills that they don't have. If you did, then you could define your "Fit" class as
Employee and (lacksSkill only (not ((inverse requiresSkill) value DBA)))
Now, the question is whether you can define a property lacksSkill that's true exactly when an employee doesn't have a skill. I'm not sure whether you can do exactly that, but you can define
lacksSkill disjointProperty hasSkill
which will mean that if hasSkill(x,y) is true, then lacksSkill(x,y) must be false. It's not exactly the the same as a negation, because they can both be false at the same time, but they can't both be true.
That's enough to make this query work, and it removes the need for some of the closure axioms. You'll still need to close what the position requires, but you don't need to close the skills of the employees. That is, you don't need to say, e.g., that EmployeeA has only the skills Skill1, Skill2. I created an ontology in Protege that you can use to see this in action. It has an EmployeeA who has Skill1 and Skill2 (not enough to qualify for the job), and an EmployeeB who has all three skills, which is enough to qualify.
@prefix : <http://example.org/> .
@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#> .
@prefix example: <http://example.org/> .
example:Skill a owl:Class .
example:Position a owl:Class .
example:Skill3 a owl:NamedIndividual , example:Skill .
example:hasSkill a owl:ObjectProperty ;
owl:propertyDisjointWith example:lacksSkill .
example:requiresSkill
a owl:ObjectProperty .
example: a owl:Ontology .
example:DBA a owl:NamedIndividual , example:Position ;
a [ a owl:Restriction ;
owl:allValuesFrom [ a owl:Class ;
owl:oneOf ( example:Skill3 example:Skill2 example:Skill1 )
] ;
owl:onProperty example:requiresSkill
] ;
example:requiresSkill example:Skill1 , example:Skill2 , example:Skill3 .
example:Skill2 a owl:NamedIndividual , example:Skill .
example:Employee a owl:Class .
example:EmployeeA a owl:NamedIndividual , example:Employee ;
example:hasSkill example:Skill1 , example:Skill2 .
example:Skill1 a owl:NamedIndividual , example:Skill .
example:lacksSkill a owl:ObjectProperty .
example:EmployeeB a owl:NamedIndividual , example:Employee ;
example:hasSkill example:Skill1 , example:Skill2 , example:Skill3 .