Jena Inference API 学习总结

更新时间:2024-04-07 13:19:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

Jena Inference API 学习总结

By Christophe

JenaReasoner测试代码说明和相应截图 1、

Jena RDF API实践测试

(1)使用ModelFactory.createDefaultModel()方法创建RDF模型,model.createResource()创建资源,addProperty()添加属性。RDF的有向图如图所示,

owner www.cit.gu.edu.au/_db David Billington phone 3875507 owner Andrew Rock www.cit.gu.edu.au/arock 实例

//jena/reasoner/test/RDFTest.java 运行后截图

(2) 然后使用modle.write(System.out,”RDF/XML-ABBREV”)方法输出到屏

幕,接着用PrintWriter写入文件test.rdf中,最后用StmtIterator遍历RDF三元组并输出。

//test.rdf如下所示,

2、 Jena的RDFSRuleReasoner的多种创建方法和有效性检测

ValidityReport

首先创建一个RDF模型,包含属性p是属性q的子属性。资源a有属性p且其值为”foo”。然后我们创建一个推理模型,它能对数据执行RDFS推理。 有多种方法创建InfModel,rdfs是已经创建好的模型,如下所示

(1) 简单方法:InfModel inf = ModelFactory.createRDFSModel(rdfs);

(2) 如果我们想要用不同的reasoner或者想要配置一个reasoner,则用手工的

方法创建:

Reasoner reasoner = ReasonerRegistry.getRDFSReasoner(); InfModel inf = ModelFactory.createInfModel(reasoner, rdfs); (3) 还可以用

Reasoner reasoner = RDFSRuleReasonerFactory.theInstance().create(null); InfModel inf = ModelFactory.createInfModel(reasoner, rdfs); (4) 可以设置配置参数来建立reasoner,可以通过创建一个新的Reasoner配置

的描述来设置processing level参数。

Resource config = ModelFactory.createDefaultModel() .createResource() .addProperty(ReasonerVocabulary.PROPsetRDFSLevel, \

Reasoner reasoner = RDFSRuleReasonerFactory.theInstance().create(config); InfModel inf = ModelFactory.createInfModel(reasoner, rdfs); (5) 还可以用下面更简单的方法。

Reasoner reasoner = RDFSRuleReasonerFactory.theInstance().create(null); reasoner.setParameter(ReasonerVocabulary.PROPsetRDFSLevel,

ReasonerVocabulary.RDFS_SIMPLE); InfModel inf = ModelFactory.createInfModel(reasoner, rdfs);

(6) 假设你有更复杂的RDF schema,它定义在schema的模型中,你想要把

这个schema应用到几个实例数据中而不用重做许多相同的中间推理。可用以下方法:

Reasoner boundReasoner = reasoner.bindSchema(schema);

InfModel inf = ModelFactory.createInfModel(boundReasoner,data);

实例

//jena/reasoner/test/ManualTest1.java

其中test1()方法使用第一种方法,test2()方法使用第四种或第五种方法,我们可以得到模型显示a也有属性q且其值为”foo”由于子属性的描述。运行如下:

为了用reasoner去测试一个数据集的不一致性,我们使用InfModel.validate()接口,它可以检查schema和实例数据的不一致。结果返回一个ValidityReport的对象,用ValidityReport.isValid()判断是否一致。

实例:

//jena/reasoner/test/ManualTest1.java

Test3()方法是检查一个数据集和列举任何有效性问题。

The file ddtest2.nt declares a property bar with range xsd:integer and attaches a bar value to some resource with the value \ 运行结果如下

输出结果:Testing file:Data/dttest2.nt Conflicts

- Error (dtRange): Property http://www.hpl.hp.com/semweb/2003/eg#bar

has a typed range Datatype[http://www.w3.org/2001/XMLSchema#integer -> class

java.math.BigInteger]that

is

not

compatible

with

\

如果The file ddtest3.nt use the value “25” ^^xsd:decimal instead. 这是有效的整数所以通过有效性检查。运行结果如下:

3、 Jena的GenericRuleReasoner的创建和Derivations的测试

(1)Jena的GenericRuleReasoner的创建方法如下所示, String rules = \

Reasoner reasoner = new GenericRuleReasoner(Rule.parseRules(rules));

(2)有时追踪一个被推理出的陈述从哪里产生是有用的。获得trace可以通过使用InfModel.getDerivation(Statement)方法,它返回一个对Derivation集合的iterator。默认情况下是没有记录Derivation信息。只有在对推理Model查询之前使用reasoner.setDerivationLogging(true)方法才能够启动记录。

实例:

//jena/reasoner/test/GenericRulesTest.java

我们建立一个规则,\,是对关系p的传递性闭包,然后测试是否通过传递性eg:A有属性eg:p且值为eg:D,然后列举derivation路径。 运行结果如下,

4、 RDFSRuleReasoner的配置和推理实例

RDFSRuleReasoner可以通过配置工作在三种不同的应用层次

(1) Full :实现了所有RDFS公理和闭包规则,除了bNode限定和数据类型

(rdfD 1)。

(2) Default :省略了昂贵的对容器成员属性的检查,和”everything is a

resource”和”everything used as a property is one”规则(rdf1,rdfs4a,rdfs4b)。 (3) Simple :只实现了subPropertyOf和subClassOf关系的传递闭包,还有

domain和range的限定和subPropertyOf和subClassOf的隐含含义。它忽略了所有公理。

可以通过调用setParameter()方法设置层次,

reasoner.setParameter(ReasonerVocabulary.PROPsetRDFSLevel,

ReasonerVocabulary.RDFS_SIMPLE);

或者创建一个RDF配置描述,然后把它传给RDFSRuleReasonerFactory。 Resource config = ModelFactory.createDefaultModel() .createResource() .addProperty(ReasonerVocabulary.PROPsetRDFSLevel, \

Reasoner reasoner = RDFSRuleReasonerFactory.theInstance().create(config);

实例:

//jena/reasoner/test/RDFSReasonerTest.java 我们创建了一个简单的RDFS schema,一些实例数据,然后使用RDFS reasoner的一个实例去查询这两个。

我们在rdfsDemoSchema.rdf文件中定义了一个属性parent,它的定义域是Person和值域是Person。parent的一个子属性mum和一个值域为整型值的属性age。

我们使用实例文件rdfsDemoData.rdf如下所示

It defines a Teenager called colin who has a mum rosy and an age of 13.

然后我们从键盘输入模式的文件名和数据的文件名,读取包含上面定义的文件,创建一个推理Model,接着查询关于colin的rdf:type属性,rosy的rdf:type属性和Person的rdf:type属性。

运行结果:

分析结果:colin是一个Teenager(直接定义),一个Person(因为他有mum推出他有parent而parent的定义域是Person,一个rdfs:Resource。rosy是一个Person(即使没有直接定义,因为mum的值域是Person),一个rdfs:Resource。Person是一个rdf:Class,即使没有直接定义,因为它是range和domain的对象。

我们还可以对InfModle进行有效性检测,通过调用InfModle.validate()方法获得

ValidityReport。我们在RDFSReasonerTest类中调用ValidityCheck(infmodle)方法进行检查。

运行结果:Conflicts

- Error (dtRange): Property urn:x-hp:eg/age has a typed range Datatype[http://www.w3.org/2001/XMLSchema#integer java.math.BigInteger]that is not compatible with \

->

class

因为在age属性中没有显示的表明值为xsd;integer型。改为

5、 GenericRuleReasoner的Rule格式与创建方法和推理实例

(1) 概述

Jena2提供了一个基于规则的推理机用来实现RDFS和OWL推理机,它也可以作为一般使用。推理机提供了对RDF图基于规则的推理,还提供了三种模式,分别为forward chaining,backward chaining和hybrid。实际上有两个内部的规则引擎一个是forward chaining RETE engine,一个是tabled datatlog engine。

通过GenericRuleReasoner可以设置不同的配置。它至少需要一个规则集合来定于它的行为。规则推理机也可以通过注册新的过程化原语进行扩展。 (2) Rule语法结构和创建方法

一个Rule是由Jena的Rule对象定义,包含前提,结论,一个可选的名字和一个可选的方向。一个规则集合就是一个Rules的List。

一个简单的parser被包含在Rule里,它允许rules在文本源文件中以紧凑的方式指定。我们也可以创建自己的rule parser。

一个非正式的简化的文本rule语法的描述如下所示: Rule := bare-rule . or [ bare-rule ]

or [ ruleName : bare-rule ]

bare-rule := term, ... term -> hterm, ... hterm // forward rule or term, ... term <- term, ... term // backward rule hterm := term or [ bare-rule ] term := (node, node, node) // triple pattern or (node, node, functor) // extended triple pattern

or builtin(node, ... node) // invoke procedural primitive

functor := functorName(node, ... node) // structured literal

node := uri-ref // e.g. http://foo.com/eg

or prefix:localname // e.g. rdf:type or // e.g. or ?varname // variable

or 'a literal' // a plain string literal

or 'lex'^^typeURI // a typed literal, xsd:* type names supported

or number // e.g. 42 or 25.5 forward和backward rule语法的区别只和hybrid执行策略相关。

扩展的三元组functor用来创建和取得结构化的文本值。functor的名字可以是任何简单的标识符。

已知的前缀集合是用PrintUtil对象注册的。可以通过PrintUtil.registerPrefix方法注册自己定义的前缀。还可以在rule文件中定义自己的前缀。

这些是一些例子:

[allID: (?C rdf:type owl:Restriction), (?C owl:onProperty ?P), (?C owl:allValuesFrom ?D) -> (?C owl:equivalentClass all(?P, ?D)) ]

[all2: (?C rdfs:subClassOf all(?P, ?D)) -> print('Rule for ', ?C) [all1b: (?Y rdf:type ?D) <- (?X ?P ?Y), (?X rdf:type ?C) ] ]

[max1: (?A rdf:type max(?P, 1)), (?A ?P ?B), (?A ?P ?C) -> (?B owl:sameAs ?C) ]

Rule文件可以被装载和分析通过如下方式:

List rules = Rule.rulesFromURL(\

or

BufferedReader br = /* open reader */ ;

List rules = Rule.parseRules( Rule.rulesParserFromReader(br) );

or

String ruleSrc = /* list of rules in line */ List rules = Rule.parseRules( rulesSrc );

Rule文件还可以包括以下宏命令:

# ...

A comment line.

// ...

A comment line.

@prefix pre: .

Defines a prefix pre which can be used in the rules. The prefix is local to the rule file.

@include .

Includes the rules defined in the given file in this file. A set of special cases is supported to allow a rule file to include the predefined rules for RDFS and OWL - in place of a real URL for a rule file use one of the keywords RDFS OWL OWLMicro OWLMini (case insensitive).

(3) forward chaining engine

在forward模式下只会使用forward chaining engine。在进行查询之前engine会先根据规则进行推理。一旦准备阶段完成,推理图会扮演得就像它是在原始的model里的所有陈述加上从规则推理出来的内部推理图的所有陈述的集合。

默认的rule engine是根据标准的RETE算法。(Charles Forgy, \Fast Algorithm for the Many Pattern/Many Object Pattern Match Problem\Artificial Intelligence, 1982 )

RETE算法介绍

http://encyclopedia.thefreedictionary.com/Rete algorithm (4) Backward chaining engine

如果推理机是在backward chaining模式下,它使用和Prolog engines执行策略类似的logic programming(LP)引擎。但查询提交给推理模型时,查询被翻译为一个目标,推理机尝试满足这个目标通过和已经存储的三元组匹配,和通过backward chaining rules进行推理。 (5) Tabling

LP引擎支持tabling。当一个目标被tabled时所有匹配那个目标的计算过的陈述都会被记录,在满足相似目标时使用。你可以要求所有目标都被tabled通过调用tableALL()原语或者包含一个属性P的所有目标被tabled通过调用table(P)。比如:

-> table(rdfs:subClassOf).

[r1: (?A rdfs:subClassOf ?C) <- (?A rdfs:subClassOf ?B) (?B rdfs:subClassOf ?C)]

会成功地计算subClassof关系的所有传递闭环。如果没有第一行这个rule会是无限循环。

(6) Hybrid rule engine

当运行hybrid模式时数据流动如下所示:

forward engine如上面所示运行和保持推理出的陈述的集合。通过使用

backward chaining LP engine回答查询。把已提供的和推理出的规则应用到backward engine。比如一个简单实现subPropertyOF的后向规则:

(?a ?q ?b) <- (?p rdfs:subPropertyOf ?q), (?a ?p ?b) . 而混合规则如下:

(?p rdfs:subPropertyOf ?q), notEqual(?p,?q) -> [ (?a ?q ?b) <- (?a ?p ?b) ] 它会预编译所有声称subPropertyOf关系到简单的chain rules,这些规则只有在查询目标指向有子属性的属性时才会运行。 (7) GenericRuleReasoner的配置

Reasoner的参数设置可以通过调用Reasoner.setParameter()方法或者把一个RDF Model传给Reasoner Factory。 GenericRuleReasoner的创建方法如下所示:

String ruleSrc = \(?a eg:p ?b) (?b eg:p ?c) -> (?a eg:p ?c)]\List rules = Rule.parseRules(ruleSrc); ...

Reasoner reasoner = new GenericRuleReasoner(rules); 主要参数总结:

Parameter PROPruleMode

Values \\\

PROPruleSet

filename-string The name of a rule text file

which can be found on the classpath

or

from

the

current directory.

PROPtraceOn

Boolean

If

true,

switches

on

Description

Sets the rule direction Default is \

\mode as discussed above.

exhaustive tracing of rule executions to the log4j info appender.

PROPderivationLogging

Boolean

If true, causes derivation routes to be recorded

internally so that future getDerivation

calls

can

return useful information.

实例:

//jena/reasoner/test/ GenericRulesTest.java

我们声称一个属性作为其他两个属性的相关联的事物,然后创建一个rule reasoner去实现它。

我们定义两个属性eg:concatFirst, eg:concatSecond,声称了在链接中的第一个和第二个属性。有如下三元组:

eg:r eg:concatFirst eg:p . eg:r eg:concatSecond eg:q . 意味着属性r=p o q。

我们有一个Jena Model rawModel,它包含了以上断言和下列陈述: eg:A eg:p eg:B . eg:B eg:q eg:C .

然后我们可以下结论A与C相关通过组合关系r。我们使用以下的rule: [r1: (?c eg:concatFirst ?p), (?c eg:concatSecond ?q) -> [r1b: (?x ?c ?y) <- (?x ?p ?z) (?z ?q ?y)] ]

我们还使用reasoner.setDerivationLogging(true)和inf.getDerivation(s)方法获得推理过程的记录。 运行结果如下:

第二个例子,我们定义了一个实现自反性和传递性的属性。我们把rules放在一个分开的文件中,为了简化编辑它们。我们会使用RDF Model来配置一个reasoner和PrintUtil.registerPrefix()方法来定义前缀。而且可以选择不同的Rule文件来进行配置reasoner。

文件demo.rules定义了属性demo:p,使用了forward rules来实现自反性和传递性:

[transitiveRule: (?A demo:p ?B), (?B demo:p ?C) -> (?A > demo:p ?C) ]

[symmetricRule: (?Y demo:p ?X) -> (?X demo:p ?Y) ] 在demoData.rdf文件中定义了以下陈述:

(demo:a demo:p demo:b) (demo:c demo:p demo:a) (demo:b demo:p demo:d)

使用demo1.rules的运行结果如下:

如果我们定义指示自反性和传递性的属性的一个新的类和使demo:p是那个类的一个成员,那么会更好。在demo2.rules定义了如下规则:

[transitiveRule: (?P rdf:type demo:TransProp)(?A ?P ?B), (?B ?P ?C) -> (?A ?P ?C) ]

[symmetricRule: (?P rdf:type demo:TransProp)(?Y ?P ?X) -> (?X ?P ?Y) ] 运行结果:

假设我们有很多p值但是只想要查询它们中的一些,则使用backward rules计算要求的闭包会更好。hybrid规则系统允许我们使用forward rules来识别任何demo:TransProp声明一次和产生合适的backward rules。在demo3.rules定义了如下规则:

-> tableAll().

[rule1: (?P rdf:type demo:TransProp) -> [ (?X ?P ?Y) <- (?Y ?P ?X) ] [ (?A ?P ?C) <- (?A ?P ?B), (?B ?P ?C) ] ] 运行结果:

思考:根据课程自主设计一个优秀的规则集,然后进行测量。测量方法是根据设计出的不同rules进行推理,统计推理的时间,然后作比较。rules的设计包括forward,backward和hybrid。

(8) 结合RDFS/OWL和rules

有两种方法实现这样的结合:第一,可以级联(cascade)推理机通过使用另一个InfModel作为基础数据来构建一个InfModel;第二,可以创建一个

GenericRuleReasoner,它的rules结合了RDFS或者OWL规则和自定义规则。 两种方法都存在层次性的极限。一个典型的配置如下所示:

Model data = FileManager.get().loadModel(\

List rules = Rule.rulesFromURL(\

GenericRuleReasoner reasoner = new GenericRuleReasoner(rules); reasoner.setOWLTranslation(true); // not needed in RDFS case

reasoner.setTransitiveClosureCaching(true);

InfModel inf = ModelFactory.createInfModel(reasoner, data); 在myrules.rules文件中会使用@include去包含RDFS或者OWL规则集。 在简单情况下,可以人工地包含一个纯粹的规则集对于你想要的RDFS/OWL,这样的话就没有层次的问题。

一个简单的例子,RDFS的一些规则可以获得通过设置TransitiveClosureCaching和包含下面的核心规则:

[rdfs2: (?x ?p ?y), (?p rdfs:domain ?c) -> (?x rdf:type ?c)] [rdfs3: (?x ?p ?y), (?p rdfs:range ?c) -> (?y rdf:type ?c)] [rdfs6: (?a ?p ?b), (?p rdfs:subPropertyOf ?q) -> (?a ?q ?b)] [rdfs9: (?x rdfs:subClassOf ?y), (?a rdf:type ?x) -> (?a rdf:type ?y)]

本文来源:https://www.bwwdw.com/article/h08r.html

Top