根据您想要执行此操作的方式,您有几个选择。我认为您正在尝试坚持非 OWL 推理,因此我们将确保包含这样的解决方案,但我也想谈谈 OWL 解决方案,因为对于一些类似的情况,它工作得很好。
使用 OWL 和自定义 ObjectList
如果您确实可以选择使用 OWL 推理器,那么这是一个很好的案例,您可以在其中创建自己的列表词汇并使用一些属性链。这个想法是你引入一个List
具有个人nil
和 属性的类first
和rest
。您实际上只是在自己的命名空间中复制词汇。然后假设您定义了两个属性
likes
: 将一个人 X 与另一个人 Y 联系起来;“X喜欢Y”。
likesList
: 将个人 X 与 X 喜欢的个人的列表(但不是 RDF 列表)相关联。
然后可以引入两个属性链公理
likesList subPropertyChain likesList o rest
: 如果 X likesList (_ ...),那么 X likesList (...)。
这样,X likes (A B C)
我们得到X likes (A B C)
、X likes (B C)
、X likes (C)
和X likes nil
。
likes subPropertyChain likesList o first
: 如果 X 喜欢List (A ...),那么 X 喜欢 A。
然后,从上述所有推断的陈述中,我们得到X likes A
、X likes B
和X likes C
。
在 Turtle 中,这看起来像:
@prefix : <http://www.example.org/distributing#> .
@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#> .
<http://www.example.org/distributing>
a owl:Ontology .
:List
a owl:Class .
:nil a :List , owl:NamedIndividual .
:first
a owl:ObjectProperty .
:rest
a owl:ObjectProperty .
:likes
a owl:ObjectProperty ;
owl:propertyChainAxiom
(:likesList :first) .
[] a owl:Axiom ;
rdfs:comment "If X likesList (A ...), then X likes A." ;
owl:annotatedProperty
owl:propertyChainAxiom ;
owl:annotatedSource :likes ;
owl:annotatedTarget (:likesList :first) .
:likesList
a owl:ObjectProperty ;
rdfs:comment "Relates an individual I1 to a ObjectList of individuals that I1 likes." ;
owl:propertyChainAxiom
(:likesList :rest) .
[] a owl:Axiom ;
rdfs:comment "If X likesList (A B C), then since (B C) is the rest of (A B C), X likesList (B C), too." ;
owl:annotatedProperty
owl:propertyChainAxiom ;
owl:annotatedSource :likesList ;
owl:annotatedTarget (:likesList :rest) .
如果您必须手动编写 RDF,这会有点不方便,因为您必须这样做
X :likesList [ :first A ;
:rest [ :first B ;
:rest [ :first C ;
:rest nil ] ] ] .
并且不能使用(...)
Turtle 包含的漂亮语法。这对于您遇到的情况也没有帮助,因为 OWL 类不是个体,所以它们不能是对象属性的对象,rdf:type
也不是对象属性。我只是想包含它,因为它是对象属性分布在(非 RDF)个人列表上的一种好方法,并且因为该方法使以下解决方案更清晰。
使用 SPARQL 查询
给定以下数据:
@prefix : <urn:ex:> .
:X :pList (:A :B :C :D) .
一个 SPARQL 查询,如
prefix : <http://example.org/>
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
construct {
?x :p ?y
}
where {
?x :pList/rdf:rest*/rdf:first ?y
}
生产
@prefix : <http://example.org/> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
:X :p :A ;
:p :C ;
:p :B ;
:p :D .
在模仿上面基于 OWL 的方法时,我使用了两个属性pList
和p
,但它们可能是相同的,在这种情况下p
将“分布”在列表中。
在某处使用数据存储,您应该能够使用以下命令进行 SPARQL 更新insert/where
:
prefix : <http://example.org/>
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
insert {
?x :p ?y
}
where {
?x :pList/rdf:rest*/rdf:first ?y
}
将数据添加到存储中。
使用类似 Prolog 的语法
如果您想真正使用推理器执行此推理,那么您将处于推理器特定内容的领域。但是,许多推理器支持类似 Prolog 的查询语言,您也可以在那里编写这些规则。我不知道 AllegoGraph 的 RDFS++ 语法,但一般结构将包括一些定义,例如:
?x p ?y :- ?x pList ?list, ?list rdf:first ?y
?x pList ?l :- ?x pList ?list, ?list rdf:rest ?l