本文介绍了RDF-将rdf:type分发到列表中的所有项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下RDF:

semapi:BaseClass     a rdfs:Class; 
                     rdfs:subClassOf rdfs:Class .

semapi:hasChainTo a rdf:Property; 
                   rdfs:domain semapi:BaseClass;
                   rdfs:range  semapi:BaseClass .                   

semapi:DerivedClass  a rdfs:Class; rdfs:subClassOf semapi:BaseClass .                  

instances:Instance1 a semapi:DerivedClass;
                    semapi:hasChainTo (
                        [
                            a semapi:DerivedClass;
                                    semapi:hasChainTo (
                                           [C1]
                                           [C2]
                                    )
                            ]
                     )

如果为semapi:hasChainTo rdfs:range semapi:BaseClass,则表示列表rdf:type semapi:BaseClass.

我真正要说的是列表中的每个 项是rdf:type(例如,[C1] rdf:type semapi:BaseClass[C2] rdf:type semapi:BaseClass,...)

我该怎么做?我需要猫头鹰(最好是不需要)吗?

解决方案

根据您要执行的操作,有几种选择.我认为您正在尝试坚持非OWL推理,因此我们将确保包括这样的解决方案,但我也想谈一谈OWL解决方案,因为在某些类似情况下,它很好用./p>

使用OWL和自定义的ObjectList

如果您要做可以选择使用OWL推理程序,那么这是一个很好的情况,您可以创建自己的列表词汇表并使用某些属性链.这个想法是您引入一个类List和一个单独的nil以及属性firstrest.您实际上只是在自己的名称空间中复制词汇表.然后假设您定义了两个属性

  • 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喜欢LikesList(A ...),那么X喜欢A.

然后,从上述所有推断的语句中,我们得到X likes AX likes BX 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的方法,我使用了两个属性pListp,但是它们可以相同,在这种情况下p将分布"在列表中.

在某处有数据存储时,您应该可以使用insert/where进行SPARQL更新:

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

Consider the following RDF:

semapi:BaseClass     a rdfs:Class; 
                     rdfs:subClassOf rdfs:Class .

semapi:hasChainTo a rdf:Property; 
                   rdfs:domain semapi:BaseClass;
                   rdfs:range  semapi:BaseClass .                   

semapi:DerivedClass  a rdfs:Class; rdfs:subClassOf semapi:BaseClass .                  

instances:Instance1 a semapi:DerivedClass;
                    semapi:hasChainTo (
                        [
                            a semapi:DerivedClass;
                                    semapi:hasChainTo (
                                           [C1]
                                           [C2]
                                    )
                            ]
                     )

If semapi:hasChainTo rdfs:range semapi:BaseClass then it implies the list is rdf:type semapi:BaseClass.

What I really mean to say is each item in the list is rdf:type (ei. [C1] rdf:type semapi:BaseClass, [C2] rdf:type semapi:BaseClass, ...)

How can I do this? Do I need Owl (preferably not)?

解决方案

Depending on how you want to do this, you have a few options. I think you're trying to stick to non-OWL reasoning, so we'll make sure to include such a solution, but I do want to touch on an OWL solution too, since for some similar situations, it works very well.

Using OWL and a custom ObjectList

If you do have the option of using an OWL reasoner, then this is a nice case in which you can create your own list vocabulary and use some property chains. The idea is that you introduce a class List with an individual nil, and properties first and rest. You're really just copying the vocabulary in your own namespace. Then lets say you define two properties

  • likes: relates an individual X to another individual Y; "X likes Y".
  • likesList: relates an individual X to a List (not an RDF list, though) of individuals that X likes.

Then you can introduce two property chain axioms

  • likesList subPropertyChain likesList o rest: if X likesList (_ ...), then X likesList (...).

This way, from X likes (A B C) we get X likes (A B C), X likes (B C), X likes (C), and X likes nil.

  • likes subPropertyChain likesList o first: if X likesList (A ...), then X likes A.

Then, from all those inferred statements above, we get X likes A, X likes B, and X likes C.

In Turtle, this looks like:

@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) .

This gets a bit inconvenient if you have to write the RDF manually, since you have to do

X :likesList [ :first A ;
               :rest [ :first B ;
                       :rest [ :first C ;
                               :rest nil ] ] ] .

and can't use the nice (...) syntax that Turtle includes. This also really doesn't help for the case that you've got, since OWL classes aren't individuals, so they can't be the object of object properties, and rdf:type isn't an object property. I just wanted to include this because it's a nice way for an object property to distribute over a (non-RDF) list of individuals, and because the approach makes the following solutions clearer.

Using SPARQL queries

Given data like:

@prefix : <urn:ex:> .

:X :pList (:A :B :C :D) .

A SPARQL query like

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
}

produces

@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 .

In imitation of the the OWL based approach above, I used two properties pList and p, but they could be the same, in which case p would be "distributed" over the list.

With a datastore somewhere, you should be able to do a SPARQL update using 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
}

to add the data to the store.

Using a Prolog like syntax

If you want to actually get this reasoning to be performed with a reasoner, you'll be in the domain of reasoner specific stuff. However, lots of reasoners support a Prolog-like query language, and you can write these rules there, too. I don't know AllegoGraph's RDFS++ syntax, but the general structure would include some definitions like:

?x p ?y :- ?x pList ?list, ?list rdf:first ?y

?x pList ?l :- ?x pList ?list, ?list rdf:rest ?l

这篇关于RDF-将rdf:type分发到列表中的所有项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-18 14:10