您的示例不依赖于封闭世界原则的利用。这取决于对owl:qualifiedCardinality
.
例如,让我们采用以下示例输入文件:
@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
.
注意注释掉的行和它们上面引入的公理。这个本体是 owl-1 兼容的,所以有它的验证规则。在下面的测试中没有验证错误,为什么?因为我们可以推断,例如,:o0 owl:sameAs :o1
这不会导致矛盾。
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() );
然而,在下一个例子中,我们证明如果我们引入:o0 owl:differentFrom :o1
,那么我们会得出一个矛盾:
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() );
鉴于演示的场景,我会提出以下解决方案(按难度递增的顺序):
解决方案 1:具有 OWL 1 约束的开放世界
如果可能的话,用 owl-1 约束来表达你的本体,然后你可以利用现有的规则集进行验证。
解决方案 2:添加 OWL 2 的开放世界
这并不容易。看一下etc/owl-fb.rules
,jena-core
您会注意到对一些通用 owl 构造(最值得注意的是基数)的支持需要Jena Builtin 的开发来简化规则表达式。如果那是你打算去的方向,我链接到另一个关于内置的答案。
以下规则来自jena-core
的etc/owl-fb.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
min
简单地根据最小和最大基数定义基数(max
在这个例子中是函子)。validationMaxN
是显示如何识别违规的特定规则(对于 N > 1)。它委托给CountLiteralValues
内置函数来识别该属性存在的绑定数量。
如果您愿意引入CountQualifiedValues
Builtin,那么您可以定义一组类似于以下的规则来引入新的公理:
[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) ] ]
解决方案 3:添加 OWL 2 的封闭世界
这实际上与解决方案 2 并没有什么不同。但是,您将尝试为 OWL 构造定义替代语义,这是一个不平凡的问题。您可以引入一些验证规则(阅读etc/owl-fb.rules
以获取示例)来捕获您特定的封闭世界假设。如果您强制将它们限制为仅在 时操作(?v rb:validation on())
,那么您可以确保在执行验证时仅假设一个封闭世界。
边讨论
这是一个以 owl 1 表示的基数限制的示例。它与上面输入文件中的相同。这以TURTLE
语法表示,并且对于转换为RDF/XML
或任何其他有效的RDF
序列化是微不足道的。
:ExampleClass rdfs:subClassOf :SuperClass
; rdfs:subClassOf [ a owl:Restriction
; owl:onProperty :myProperty
; owl:cardinality 1
]
.
这对限制在语义上并不完全等同于owl:qualifiedCardinality
,但是,如果您有能力修改您的领域模型,您通常可以绕过它。
例如,说 .owl:qualifiedCardinality
之类的话很棒:People :haveBodyPart exactly 2 :Eyes
。例如,OWL 1 解决方法可以是创建一个:haveEye rdfs:subPropertyOf :haveBodyPart
然后说:People :haveEye exactly 2
(没有合格的基数限制)