存档

‘语义网基础’ 分类的存档

用jena api来理解RDFS——subClassOf subPropertyOf range domain

2010年1月9日

这四个词汇与推理密切相关,查看JENA的RDFSRuleReasonerFactory可以看到里面有这么一段代码:

  1. Resource base = capabilities.createResource(getURI());
  2. base.addProperty(ReasonerVocabulary.nameP, "RDFS FB-TGC Rule Reasoner")
  3. .addProperty(ReasonerVocabulary.descriptionP, "Complete RDFS implementation supporting metalevel statements.\nCan separate tbox and abox data if desired to reuse tbox caching or mix them.")
  4. .addProperty(ReasonerVocabulary.supportsP, RDFS.subClassOf)
  5. .addProperty(ReasonerVocabulary.supportsP, RDFS.subPropertyOf)
  6. .addProperty(ReasonerVocabulary.supportsP, RDFS.member)
  7. .addProperty(ReasonerVocabulary.supportsP, RDFS.range)
  8. .addProperty(ReasonerVocabulary.supportsP, RDFS.domain)
  9. .addProperty(ReasonerVocabulary.versionP, "0.1");

说明jena对其提供了支持。

subPropertyOf
如果张三养了一只狗,那么一定可以推理出张三养了一只宠物,因此养狗和有宠物是subPropertyOf关系。

  1. String ns = "htpp://www.crabone.com#";
  2.  
  3. Model model = ModelFactory.createDefaultModel();
  4.  
  5. // 养狗subPropertyOf有宠物
  6. Property hasPet = model.createProperty(ns, "有宠物");
  7. Property hasDog = model.createProperty(ns, "养狗");
  8. model.add(hasDog, RDFS.subPropertyOf, hasPet);
  9.  
  10. // 张三养了一只狗叫汪汪
  11. model.createResource(ns+"张三").addProperty(hasDog, "汪汪");
  12.  
  13. // 得到JENA内置的RDFS推理机
  14. Reasoner reasoner = ReasonerRegistry.getRDFSReasoner();
  15.  
  16. // 用原来的图和推理机构造出新的推理图
  17. InfModel infModel = ModelFactory.createInfModel(reasoner, model);
  18.  
  19. System.out.println(infModel.getResource(ns+"张三").getProperty(hasPet));

输出:[htpp://www.crabone.com#张三, htpp://www.crabone.com#有宠物, "汪汪"]
从代码来看,jena的推理是基于图的相关算法来实现的。subClassOf和其道理一样,这里就不啰嗦了。

domain、range

个人感觉这是推理性非常强的一种机制!在protege入门里面就有相关的解释。domain和range是用来描述一个property的,比如:拿养狗这个property来说,一般,只有人才会养狗,水瓶是不会养狗的,电插座也是不会养狗的,所以养狗这个property的domain是(一种class),同样养狗这个property的range是(一种class)。当推理机知道这些道理后,告诉它,张三养了一只汪汪,那么,这个推理机能推理出,张三是人,汪汪是狗。

  1. String ns = "htpp://www.crabone.com#";
  2.  
  3. Model model = ModelFactory.createDefaultModel();
  4.  
  5. // 构造人这个类
  6. Resource personClass = model.createResource(ns+"");
  7. model.add(personClass, RDF.type, RDFS.Class);
  8.  
  9. // 构造狗这个类
  10. Resource dogClass = model.createResource(ns+"");
  11. model.add(dogClass, RDF.type, RDFS.Class);
  12.  
  13. // 构造养狗这个属性,并设置domain是人,range是狗
  14. Property hasDog = model.createProperty(ns, "养狗");
  15. model.add(hasDog, RDFS.domain, personClass);
  16. model.add(hasDog, RDFS.range, dogClass);
  17.  
  18. // 添加张三养了一条狗汪汪这个事实
  19. Resource zhangsan = model.createResource(ns+"张三");
  20. Resource wangwang = model.createResource(ns+"汪汪");
  21. zhangsan.addProperty(hasDog, wangwang);
  22.  
  23. // 构造RDFS推理机
  24. Reasoner reasoner = ReasonerRegistry.getRDFSReasoner();
  25.  
  26. // 生成推理图
  27. InfModel infModel = ModelFactory.createInfModel(reasoner, model);
  28.  
  29. System.out.println(infModel.getResource(ns+"张三").getProperty(RDF.type));
  30. System.out.println(infModel.getResource(ns+"汪汪").getProperty(RDF.type));

输出:
[htpp://www.crabone.com#张三, http://www.w3.org/1999/02/22-rdf-syntax-ns#type, htpp://www.crabone.com#人]
[htpp://www.crabone.com#汪汪, http://www.w3.org/1999/02/22-rdf-syntax-ns#type, htpp://www.crabone.com#狗]
总结:domain和rang其实也是一种property;domain这个property用来连接property和class,range这个property用来连接property和class,这是w3的标准,其实在JENA里面比较宽松,domain这个property用来连接property和节点即可,range也是如此。

JENA, 语义网基础

OWL 2 词汇全貌

2010年1月6日

首先介绍4个OWL 2词汇需要用到的预定义命名空间

  • rdf: http://www.w3.org/1999/02/22-rdf-syntax-ns#
  • rdfs: http://www.w3.org/2000/01/rdf-schema#
  • owl: http://www.w3.org/2002/07/owl#
  • xsd: http://www.w3.org/2001/XMLSchema#

定义类,有以下几种方式:
1.直接取名字,这是用的最多的方法
用RDF/XML-ABBREV语法表达如下:
<owl:Class rdf:about=”#crab”/>

2.集合类,通过几种类组合创造出一个新的类
比如:有一个类,它是“女人”和“有孩子的”这2个类取交集,所得到的类(这个类可以等价于“母亲”)
用RDF/XML-ABBREV语法表达如下:
<owl:Class rdf:about=”#母亲”>
 <owl:equivalentClass>
  <owl:Class>
  <owl:intersectionOf rdf:parseType=”Collection”>
   <rdf:Description rdf:about=”#女人” />
   <owl:Restriction>
   <owl:onProperty rdf:resource=”#有孩子” />
   <owl:someValuesFrom rdf:resource=”#人” />
   </owl:Restriction>
  </owl:intersectionOf>
  </owl:Class>
 </owl:equivalentClass>
</owl:Class>

上面介绍的是owl:intersectionOf,它代表交集,所有的集合表达方式如下:
_:x owl:intersectionOf ( C1 … Cn ). 交集 protege中使用“and”
_:x owl:unionOf ( C1 … Cn ). 并集 protege中使用“or”
_:x owl:complementOf C. 补集 并集 protege中使用“not”

3.枚举类,通过一系列的个体(individual)所描绘的一种类
比如:“文一美食店”这个类,是由很多在文一路的美食店所组成的一个类
  <owl:Class rdf:about=”#饭店”/>
  <owl:Class rdf:about=”#文一美食店”>
    <owl:oneOf rdf:parseType=”Collection”>
      <j.0:饭店 rdf:about=”#半亩地”/>
      <j.0:饭店 rdf:about=”#一席地”/>
      <j.0:饭店 rdf:about=”#老山东牛杂”/>
    </owl:oneOf>
  </owl:Class>
需要注意的是,该类并非由其他类所构成,而是由一系列的个体(individual)构成,语法如下:
_:x owl:oneOf ( a1 … an ). protege中使用 {}

4.限制类,这个翻译来源于Object(Datatype) Property Restrictions,这种定义类的方式听起来很别扭,但在现实生活中确实需要如此去表达,比如:很富有的人、有2个孩子的父亲,这些都是可以表达成类的。看一个用RDF/XML-ABBREV语法表达的例子:
  <owl:Class rdf:about=”#奶茶店”>
    <owl:equivalentClass>
      <owl:Restriction>
        <owl:someValuesFrom>
          <owl:Class rdf:about=”#奶茶”/>
        </owl:someValuesFrom>
        <owl:onProperty rdf:resource=”#出售”/>
      </owl:Restriction>
    </owl:equivalentClass>
  </owl:Class>

上面需要表达的意思:奶茶店等价于这样的一个类,这个类叫“出售一些奶茶的”。对于现实中的例子就是,奶茶店是卖奶茶的。在这里,我们发现,“出售一些奶茶的”这本身就是一种类,这种类就是所谓的限制类。限制类的定义方法有很多,在JENA中,我们会发现OntClass有一个子接口Restriction,而Restriction接口下面又衍生出

  1. SomeValuesFromRestriction
  2. AllValuesFromRestriction
  3. HasValueRestriction
  4. MaxCardinalityQRestriction
  5. MinCardinalityQRestriction
  6. CardinalityQRestriction
  7. MaxCardinalityRestriction
  8. MinCardinalityRestriction
  9. CardinalityRestriction

我们逐一解释:
1、已经介绍了
2、这家奶茶店只卖奶茶,出售这个属性所跟的所有个体全部属于奶茶(AllValuesFrom)
关于SomeValuesFrom和AllValuesFrom有很多话题可以聊,具体看其他文章
3、这个和前面2者不同,前面2者属性后面需要跟,而这个属性后面必须跟个体,出售拿破仑戒指的古董店,拿破仑戒指是戒指一个个体,不是一个类,这里把有出售拿破仑戒指的这些古董店合起来称为一个类
4、最多出售一种品牌的店叫专卖店
5、最少有两家分店的店可以叫做连锁店
6、精确的定义到数字
7、8、9和4、5、6非常类似,区别在于,属性后面可以不跟,4、5、6是OWL 2新增的内容

另外,OWL 2又多了一种限制类,叫做ObjectHasSelf,具有自反性质,比如:爱自己的人可以称为自恋的人,这个在protege和jena里面都还没有实现。上面9个方式可以基于Object Property来描述的,同样也可以基于Data Property来描述。不过OWL-API分的跟细致,将Object Property Restrictions和Data Property Restrictions分开实现了,有新兴趣的朋友可以去比较比较。

语义网基础

用jena api来理解RDF——三元组

2010年1月1日

JENA中有一个最底层的接口:RDFNode,它代表RDF这张巨大图中的节点,这个节点可以是一个资源,可以是一个字符窜或者数字。因此它对应与2个子接口:
interface Literal extends RDFNode
interface Resource extends RDFNode
Literal接口代表了一些原始类型节点,比如:32位整型、布尔型等等。
Resource接口还可以继续衍生出2个重要的接口:
interface Container extends Resource
interface Property extends Resource
Container接口就对应了RDF的容器表达能力,里面有bag,seq,alt
Property接口就是所谓的资源属性了

在RDF的世界中,其实描述资源只有一种方式,那就是三元组,包括:主体(subject),谓词(predicate),客体(object)。主体和客体就是图中的2个节点,谓词就是一条边。这三元组在JENA中用Statement接口来描述,该接口中有下面3个方法:
public Resource getSubject();
public Property getPredicate();
public RDFNode getObject();

我们可以发现,主体一定是一种资源,不可能是一个Literal原始类型,因此主体必定属于Resource接口实现,但是客体可以是原始类型,比如:人有2条腿。为主体;为谓词;2为客体。

用一个例子来巩固下:

  1. <?xml version="1.0"?>
  2.  <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  3.           xmlns:s="http://example.org/students/vocab#">
  4.  
  5.     <rdf:Description rdf:about="http://example.org/courses/6.001">
  6.        <s:students>
  7.           <rdf:Bag>
  8.              <rdf:li rdf:resource="http://example.org/students/Amy"/>
  9.              <rdf:li rdf:resource="http://example.org/students/Mohamed"/>
  10.              <rdf:li rdf:resource="http://example.org/students/Johann"/>
  11.              <rdf:li rdf:resource="http://example.org/students/Maria"/>
  12.              <rdf:li rdf:resource="http://example.org/students/Phuong"/>
  13.           </rdf:Bag>
  14.        </s:students>
  15.     </rdf:Description>
  16.  </rdf:RDF>

如果要一下子看出这个RDF中有几个三元组,一定不是很方便吧?如果用图来表示:
201001011021
是不是非常清晰呢?图中有一个主体http://example.org/courses/6.001,它有一条边http://example.org/students/vocab#students,对应的客体就是那个空节点。同理还有这个空节点所对应的那些三元组。用JENA来解析这个例子:

  1. Model model = ModelFactory.createDefaultModel();
  2.  
  3. model.read(new FileInputStream("student.rdf"), null);
  4.  
  5. StmtIterator  it = model.listStatements();
  6.  
  7. while(it.hasNext())
  8. {
  9.     System.out.println(it.next());
  10. }

打印的结果如下:
[http://example.org/courses/6.001, http://example.org/students/vocab#students, -23ba78ea:125e9da42c8:-8000]
[-23ba78ea:125e9da42c8:-8000, http://www.w3.org/1999/02/22-rdf-syntax-ns#_5, http://example.org/students/Phuong]
[-23ba78ea:125e9da42c8:-8000, http://www.w3.org/1999/02/22-rdf-syntax-ns#_4, http://example.org/students/Maria]
[-23ba78ea:125e9da42c8:-8000, http://www.w3.org/1999/02/22-rdf-syntax-ns#_3, http://example.org/students/Johann]
[-23ba78ea:125e9da42c8:-8000, http://www.w3.org/1999/02/22-rdf-syntax-ns#_2, http://example.org/students/Mohamed]
[-23ba78ea:125e9da42c8:-8000, http://www.w3.org/1999/02/22-rdf-syntax-ns#_1, http://example.org/students/Amy]
[-23ba78ea:125e9da42c8:-8000, http://www.w3.org/1999/02/22-rdf-syntax-ns#type, http://www.w3.org/1999/02/22-rdf-syntax-ns#Bag]

JENA, 语义网基础 ,

用jena api来理解RDF——空节点

2009年12月26日

在RDF入门的例子中,有这样一幅图:
200912262132
最中间的那个节点起一个过渡作用,这时,虽然它也是一个资源,但这个资源没有必要标上资源描述符,因为它可能只在应用程序局部使用,作为推理机的一个桥梁等等作用,换句说,这个资源别人没有必要去引用。这样的节点,我们称之为空节点:

  1. Model model = ModelFactory.createDefaultModel();
  2.  
  3.   Resource blankNode = model.createResource(new AnonId("tempNode"));
  4.   Property city = model.createProperty("http://www.crabobe.com/city");
  5.   Property street = model.createProperty("http://www.crabobe.com/street");
  6.   blankNode.addProperty(city, "深圳");
  7.   blankNode.addProperty(street, "龙岗");
  8.  
  9.   Resource crab = model.createResource("http://www.crabobe.com/crab");
  10.   Property address = model.createProperty("http://www.crabobe.com/address");
  11.   crab.addProperty(address, blankNode);
  12.  
  13.   model.write(System.out);

注意,包含中文的源码文件必须是UTF-8的,运行结果如下:

  1. <rdf:RDF
  2.     xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  3.     xmlns:j.0="http://www.crabobe.com/" > 
  4.   <rdf:Description rdf:about="http://www.crabobe.com/crab">
  5.     <j.0:address rdf:nodeID="A0"/>
  6.   </rdf:Description>
  7.   <rdf:Description rdf:nodeID="A0">
  8.     <j.0:street>龙岗</j.0:street>
  9.     <j.0:city>深圳</j.0:city>
  10.   </rdf:Description>
  11. </rdf:RDF>

JENA, 语义网基础 , , ,

用jena api来理解RDF——资源概念

2009年12月26日

RDF作为资源描述框架,有2件事情是它的本职工作,第一,描述资源的唯一性,只有统一了,各种应用才能达成共识,好比秦始皇那会儿一样。第二,要把资源表述得有条有理。下面,拿出代码来解释。

  1. Model model = ModelFactory.createDefaultModel();
  2.  
  3. Resource crab = model.createResource("http://www.crabobe.com/crab");
  4.      
  5. model.write(System.out);

上面,我们用jena建立了crab这样一个资源,当然,crab只是java内存中的一个变量名而已,它真是的标识符号是http://www.crabobe.com/crab,也即,在这个世界上,这个资源是唯一存在的。

我们继续添加一个资源

  1. Model model = ModelFactory.createDefaultModel();
  2.  
  3. Resource crab = model.createResource("http://www.crabobe.com/crab");
  4. Property numerOfLeg = model.createProperty("http://www.crabobe.com/crab#numerOfLeg");
  5.      
  6. model.write(System.out);

这里我们添加了一个资源numerOfLeg,有人问,它是一个属性(Property)吧?没错,但在RDF中,属性也是一种资源,在JENA中,Property是Resource的子接口。既然它是一种资源,那必定得有唯一的标识符,这个标识符就是http://www.crabobe.com/crab#numerOfLeg

接着我们用numerOfLeg这个属性来描述crab

  1. Model model = ModelFactory.createDefaultModel();
  2.  
  3. Resource crab = model.createResource("http://www.crabobe.com/crab");
  4. Property numerOfLeg = model.createProperty("http://www.crabobe.com/crab#numerOfLeg");
  5. crab.addProperty(numerOfLeg, "8");
  6.      
  7. model.write(System.out);

运行的结果:

  1. <rdf:RDF
  2.     xmlns:j.0="http://www.crabobe.com/crab#"
  3.     xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" > 
  4.   <rdf:Description rdf:about="http://www.crabobe.com/crab">
  5.     <j.0:numerOfLeg>8</j.0:numerOfLeg>
  6.   </rdf:Description>
  7. </rdf:RDF>

关于这个结果,虽然很简单,但是里面有个细节需要我们去关注!!同样是资源描述符,资源的描述符和属性的描述符是不一样的。区别就体现在,资源的描述符仅仅是作为rdf:Description标签的一个属性,而属性的描述符却要被用来作为XML标签。在这点上来看,属性的资源描述符一定要带有相对路径,假如我们这样写:
model.createProperty(”http://www.crabobe.com”);
那么这个属性标签的命名空间就没有了,如果命名空间标示为http://www.crabobe.com,那它自己的名称呢?所以,jena会报错。
所以,我们的写法可以是这样:
http://www.crabobe.com/crab
那么http://www.crabobe.com/就是命名空间,crab就是标签名称
也可以像例子都那样写:
http://www.crabobe.com/crab#numerOfLeg
那么命名空间就是http://www.crabobe.com/crab#,被jena简写成j.0,名称就是numerOfLeg。

现在,我们来验证资源的唯一性:

  1. Model model = ModelFactory.createDefaultModel();
  2.  
  3. Resource crab = model.createResource("http://www.crabobe.com");
  4. Resource crab1 = model.createResource("http://www.crabobe.com");
  5. Property numerOfLeg = model.createProperty("http://www.crabobe.com/crab#numerOfLeg");
  6. Property numerOfLeg1 = model.createProperty("http://www.crabobe.com/crab#numerOfLeg");
  7. crab.addProperty(numerOfLeg, "8");
  8. crab1.addProperty(numerOfLeg1, "8");
  9.      
  10. model.write(System.out);

这里,我们人为写出2个对象,但是资源描述符写成一样,这2个对象分别有各自属性,按照唯一性,那么内存中即使对象再是多,在RDF规范中,只会认资源描述符,只要资源描述符是一样的,那么就视为一个资源。运行的结果,符合我们的推理。

如果我们改一改:

  1. Model model = ModelFactory.createDefaultModel();
  2.  
  3. Resource crab = model.createResource("http://www.crabobe.com");
  4. Resource crab1 = model.createResource("http://www.crabobe.com");
  5. Property numerOfLeg = model.createProperty("http://www.crabobe.com/crab#numerOfLeg");
  6. Property numerOfLeg1 = model.createProperty("http://www.crabobe.com/crab#numerOfLeg");
  7. crab.addProperty(numerOfLeg, "8");
  8. crab1.addProperty(numerOfLeg1, "10");
  9.      
  10. model.write(System.out);

运行结果是什么?可以思考下,再运行结果,留待大家思考吧~

JENA, 语义网基础 ,