问题
I want to validate an ontology and throw an error if anything is incorrect.
The most validation I have to do looks like this: I have a class like this:
<owl:Class rdf:about="&schema;ExampleClass">
<rdfs:subClassOf rdf:resource="&schema;SuperClass"/>
<rdfs:subClassOf>
<owl:Restriction>
<owl:onProperty rdf:resource="&schema;myProperty"/>
<owl:onClass rdf:resource="&schema;OtherClass"/>
<owl:qualifiedCardinality rdf:datatype="&xsd;nonNegativeInteger">1</owl:qualifiedCardinality>
</owl:Restriction>
</rdfs:subClassOf>
</owl:Class>
(The interesting part is the 2nd subClassOf.)
In Protege this means ExampleClass is subClass of myProperty exactly 1 OtherClass
.
So I want to validate that there is exactly one myProperty with value: an individual of type OtherClass.
Is it possible to validate rules like this? Perfect would be if there would be a rule to do this for all classes with this modeling (and maybe with also at least 1, exactly 2, ...)
Another question is: Is there a ready closed world reasoner that is doing exactly that for me?
回答1:
Your example doesn't depend on the utilization of a closed-world principle. It depends on the introduction of a validation rule for owl:qualifiedCardinality
.
For example, let us take the sample input file that follows:
@prefix xsd: <http://www.w3.org/2001/XMLSchema#>.
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
@prefix owl: <http://www.w3.org/2002/07/owl#>.
@prefix : <urn:x-so:ex#>.
:OtherClass a owl:Class .
:SuperClass a owl:Class .
:myProperty a rdf:Property
; rdfs:range :OtherClass
.
:ExampleClass rdfs:subClassOf :SuperClass
; rdfs:subClassOf [ a owl:Restriction
; owl:onProperty :myProperty
; owl:cardinality 1
# ; owl:onClass :OtherClass
# ; owl:qualifiedCardinality 1
]
.
:o0 a :OtherClass .
:o1 a :OtherClass .
:s0 rdf:type :ExampleClass
; :myProperty :o0
; :myProperty :o1
.
Note the commented-out lines and the introduced axiom above them. This ontology is owl-1 compliant, so there are validation rules for it. In the following test there is no validation error, why? because we can infer that, for example, :o0 owl:sameAs :o1
which results in no contradiction.
final Model baseModel = ModelFactory.createDefaultModel();
try( final InputStream in = this.getClass().getResourceAsStream("/so.ttl") ){
baseModel.read(in, null, "TTL");
}
final OntModel model = ModelFactory.createOntologyModel(OntModelSpec.OWL_DL_MEM_RULE_INF, baseModel);
assertTrue(model.contains(s0, myProperty, o0));
assertTrue(model.contains(s0, myProperty, o1));
final ValidityReport report = model.validate();
assertTrue( report.isValid() );
In the next example however, we demonstrate that if we introduce :o0 owl:differentFrom :o1
, then we derive a contradiction:
final Model baseModel = ModelFactory.createDefaultModel();
try( final InputStream in = this.getClass().getResourceAsStream("/so.ttl") ){
baseModel.read(in, null, "TTL");
}
final OntModel model = ModelFactory.createOntologyModel(OntModelSpec.OWL_DL_MEM_RULE_INF, baseModel);
model.add(o1, OWL.differentFrom, o0); // NOTE!!
assertTrue(model.contains(s0, myProperty, o0));
assertTrue(model.contains(s0, myProperty, o1));
final ValidityReport report = model.validate();
assertFalse( report.isValid() );
Given the demonstrated scenario, I'd propose the following solutions (in order of ascending difficulty):
Solution 1: Open-World with OWL 1 Constraints
Express your ontology in terms of owl-1 constraints if possible, and then you can utilize the existing rule sets for validation.
Solution 2: Open-World with OWL 2 Additions
This is not going to be easy. Take a look at etc/owl-fb.rules
in jena-core
and you'll note that support of some generic owl constructs (most notably, cardinality) required the development of Jena Builtin to make the rule expression simple. I linked to another answer regarding builtins if that is the direction that you intend to go.
The following rules come from jena-core
's etc/owl-fb.rules
file to describe cardinality. They are not the complete set of cardinality rules.
[restriction5: (?C owl:onProperty ?P), (?C owl:cardinality ?X)
-> (?C owl:equivalentClass card(?P, ?X)),
(?C rdfs:subClassOf min(?P, ?X)),
(?C rdfs:subClassOf max(?P, ?X)) ]
[restriction4: (?C owl:onProperty ?P), (?C owl:maxCardinality ?X)
-> (?C owl:equivalentClass max(?P, ?X)) ]
[validationMaxN: (?v rb:validation on()), (?C rdfs:subClassOf max(?P, ?N)) greaterThan(?N, 1) (?P rdf:type owl:DatatypeProperty) ->
[max2b: (?X rb:violation error('too many values', 'Too many values on max-N property (prop, class)', ?P, ?C))
<- (?X rdf:type ?C), countLiteralValues(?X, ?P, ?M), lessThan(?N, ?M) ] ]
restriction5
simply defines cardinality in terms of min and max cardinality (min
and max
in this example are Functors). validationMaxN
is the particular rule (for N > 1) that shows how a violation can be identified. It delegates to the CountLiteralValues builtin to identify the number of bindings that exist for the property.
If you are willing to introduce a CountQualifiedValues
Builtin, then you could define a set of rules similar to the following to introduce the new axioms:
[restriction4: (?C owl:onProperty ?P), (?C owl:maxQualifiedCardinality ?X), (?C owl:onClass ?Y)
-> (?C owl:equivalentClass max(?P, ?X, ?Y)) ]
[validationMaxN: (?v rb:validation on()), (?C rdfs:subClassOf max(?P, ?N, ?Y)) greaterThan(?N, 1) (?P rdf:type owl:ObjectProperty) ->
[max2b: (?X rb:violation error('too many values', 'Too many values on max-QN property (prop, class, qclass)', ?P, ?C, ?Y))
<- (?X rdf:type ?C), countQualifiedValues(?X, ?P, ?Y, ?M), lessThan(?N, ?M) ] ]
Solution 3: Closed-World with OWL 2 Additions
This is actually not all that different from Solution 2. You will, however, be trying to define alternative semantics for OWL constructs, which is a nontrivial problem. You can introduce a few rules for validation (take a read of etc/owl-fb.rules
to get examples) that capture your particular closed-world assumptions. If you enforce that they are restricted to only operate when (?v rb:validation on())
, then you can ensure that you are only assuming a closed-world when you are performing validation.
Side Discussion
Here is an example of a cardinality restriction expressed in owl 1. It is the same as the one in the input file above. This is expressed in TURTLE
syntax and is trivial to transform to RDF/XML
or any of the other valid RDF
serializations.
:ExampleClass rdfs:subClassOf :SuperClass
; rdfs:subClassOf [ a owl:Restriction
; owl:onProperty :myProperty
; owl:cardinality 1
]
.
This pair of restrictions is not exactly semantically equivalent to owl:qualifiedCardinality
, but, if you have the ability to modify your domain model, you can often work around it.
For example, owl:qualifiedCardinality
is great to say things like :People :haveBodyPart exactly 2 :Eyes
. The OWL 1 workaround could be, for example, to create a :haveEye rdfs:subPropertyOf :haveBodyPart
and then say :People :haveEye exactly 2
(without qualified cardinality restriction)
回答2:
It sounds like you're trying to check some integrity constraints based on some OWL axioms, but it's important to note that OWL is based on the open-world assumption. That means that even if you have:
Person ⊑ ∃hasParent.Person
which says that every person has (at least) one value of the hasParent property with a value that is another Person individual, you can still have a consistent ontology that doesn't include any hasParent assertions at all! So the kind of "validation" that you're looking for is really more about a closed world and complete interpretation.
Rather than using a rules based approach, I'd probably attack this problem using some SPARQL queries to check for individuals that don't satisfy the things we expect them to satisfy. For instance, in this case, you could write a general rule that looks individuals that are instances of restrictions, and then you can check whether you can find triples in the data that "match" the restriction.
For this particular case, you can find (some) instances of (myProperty exactly 1 OtherClass) (and qualified cardinalities in general) with:
?instance a [ owl:onProperty ?property ;
owl:onClass ?class ;
owl:qualifiedCardinality ?cardinality ] .
Of course, if some individual can only be inferred to be an instance of the class, that pattern won't find it, but we're assuming that you're working with a closed-world and complete data, so something like that should work. ("Something like" could include ?instance a/rdfs:subClassOf* [ ... ]
.) Once you've got that, you can write a subquery that checks whether the data "matches":
select ?instance ?property ?class (count(?value) as ?actualCardinality) where {
?instance ?property ?value .
?value a ?class
}
group by ?instance ?property ?class
Then you can combine these to identify individuals where the ?actualCardinality doesn't match ?cardinality:
select ?instance
?property
?class
?cardinality
(count(?value) as ?actualCardinality)
where {
?instance a [ owl:onProperty ?property ;
owl:onClass ?class ;
owl:qualifiedCardinality ?cardinality ] .
?instance ?property ?value .
?value a ?class
}
group by ?instance ?property ?class ?cardinality
having ( ?cardinality != ?actualCardinality )
I haven't tested any of this yet, so there may be typos, and you haven't provided complete data, so I can't test on that either, but something in this general line should be workable.
来源:https://stackoverflow.com/questions/25422914/jena-rule-for-validation-af-a-ontology