翻译自Jena文档。
一,简介
Jena2提供的规则推理引擎支持前向链、后向链以及二者混合的推理执行模型,更准确地说,Jena有两个内部规则引擎:前向链推理RETE引擎和一个tabled datalog engine.它们可以独立运行,或者前向链作为后向链引擎的先导,来完成“查询-问答”。
不同的推理引擎配置可以通过一个单独的参数化推理机GenericRuleReasoner来进行。GenericRuleReasoner的最小需求是需要一个规则集来定义其行为。带有规则集的GenericRuleReasoner实例和其他推理机的用法类似,它和一个数据模型绑定,基于推理模型回答查询请求。
规则推理机还可以通过注册新的过程原语进行扩展,Jena现在的发布版本包括开始的一系列原语,它们对RDFS和OWL的实现来说已经足够并且是易于扩展的。
二,规则语法和结构
在基于规则的推理机中,规则被定义为一个Java的Rule对象,该对象由body terms(前提)的list,head terms(结论)list以及可选的名字和可选的方向来定义。每一个term或者ClauseEntry是一个三元模式(triple pattern),一个扩展的三元模式(extended triple pattern??)或者一个内嵌过程原语的调用。一个规则集是简单的规则列表(List)。
Jena的规则语法分析parser支持简单的基于文本的规则语法:
Rule := bare-rule .
or [bare-rule]
or [ruleName : bare-rule ]
bare-rule := term, ..., term -> hterm, ... , hterm
or term, ..., term <- term, ...., term
hterm := term
or [bare-rule ]
term := (node, node, node)
or (node, node ,functor)
or builtin(node, ..., node)
functor := functorName(node, ..., node) // 结构化的literal
node := uri-ref // 例如,http://foo.com/eg
or prefix:localname // e.g. , rdf:type
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
functor是用来创建和访问结构化文字值的。functorName是any 简单的identifier,它不与内嵌过程原语的执行相关,它只是一个数据结构。当在多个三元组之上定义一个单一的语义结构时,需要functor,以使得规则可以将这些三元组collect到一个地方。
为了保证规则的可读性,URI引用应符合qname语法。具名prefix是那些用PrintUtil对象注册的。比如rdf,rdfs,owl,daml,xsd是初始值,更多的映射还可以进一步注册。
下面是一些规则例子:
[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)
[allb: (?Y rdf:type ?D) <- (?X rdf:type ?C)]]
[max1: (?A rdf:type max(?P,1)), (?A ?P ?B), (?A, ?P, ?C) -> (?B owl:sameAs ?C) ]
规则allID阐释了functor的使用,它是用来将OWL约束的几个元素集合成为一个单一的数据结构,然后再触发其他规则。规则all2阐释了一个前向规则,它生成一个新的后向规则,并且还调用了print过程原语。规则 max1则说明了数字类型的使用。
规则文件的加载和分析是这样进行的:
List rules = Rule.rulesFromURL("file:myfile.rules");
或者
BufferedReader br = /*open reader */;
List rules = Rule.parseRules(Rule.rulesParserFromReader(br));
或者
String ruleSrc = /* lists of rules in lines */
List rules = Rule.parseRules(rulesSrc);
在前面两种情况下,规则文件被一个简单的处理器预先处理,将注释去掉,并支持一些额外的宏命令:
@prefix pre: <http://domain/url#>.
定义一个前缀pre,前缀对规则文件来说是局部的。
@include <urlToRuleFile>
包含在一个给定文件中定义的规则。不管@include出现在哪里,包含的规则都将出现在用户定义的规则前面。
注意: 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).
规则文件可以包含预定义的规则,例如RDFS和OWL等,这时urlToRuleFile被关键字RDFS, OWL, OWLMicro, OWLMini取代。
下面是包含RDFS预定义规则的一个规则文件的完整例子:
# Example rule file
@prefix pre: <http://jena.hpl.hp.com/prefix#>.
@include <RDFS>.
[rule1: (?f pre:father ?a) (?u pre:brother ?f) -> (?u pre:uncle ?a)]
前向链推理引擎
如果规则推理机被配置为以前向模式执行,那么就只能使用前向链引擎。当首次查询inference model时(或者显式调用prepare()时),模型中的所有相关数据提交到规则引擎中。任何触发创建其他三元组的规则在Jena内部的deductions graph中创建三元组,并反过来再触发其他规则。
remove原语用于删除三元组,并且能够在删除(removal mode)模式下触发规则执行。这种规则的迭代触发执行方式一致继续,直到没有规则可以触发。
一旦准备阶段完成,inference graph将作为所有在original model中的语句以及规则触发产生的放在internal deductions graph中的语句的联合来执行。这些所有的语句对所有查询都是可见的,与一般模式(normal model)下具有类似的访问速度。也可以将对原始数据和归结语句分开访问。
若推理模型(inference model)由于调用普通的API而增加、删除了部分语句,就将引发规则执行。前向规则递增式地执行,只能访问增加、删除后的结果。默认的规则引擎基于标准的RETE算法(C.L Forgy, RETE : A fast algorithm for the many pattern/many object pattern match problem, Artificial Intelligence 1982)。
当Jena以前向模式运行时,规则文件中的所有规则(包括以后向语法<-写成的规则)都被作为前向规则。
匹配的规则被触发的顺序或前提(规则体中的term)被检验的顺序还没有确保。
但一旦规则被触发,规则头中的terms将以从左到右的顺序执行。
在前向模式中,断言后向规则的规则头terms被忽略(如all1b中)。