美文网首页大数据,机器学习,人工智能程序员
Hybrid Reasoning System(混合推理系统,D

Hybrid Reasoning System(混合推理系统,D

作者: 长风几厘米 | 来源:发表于2019-03-18 14:20 被阅读5次

1. 一点历史

  几十年前,人工智能(Artificial Intelligence)进入了著名的 "AI冬天" 时期,成为了一个非常不受欢迎的名词。有很多科学家和工程师为了获取资金而自吹自擂,却从未达到人们的期望,只留下了很多失败的项目。思维机器公司以及第五代计算机(5GP)项目或许是那个时代最好的例子。

  思维机器公司在1990年是人工智能公司的领头羊,他的销售额接近6500美元。下面的引用来自于他们的宣传册:

终有一天我们会制造出能够思考的机器。他将是真正的智能机器。是能够看,听和说的机器。是令我们骄傲的机器。

  然而,在5年后,他们根据第11章的条款申请破产保护了。网站 inc.com 上曾经发表了一篇引人入胜的文章:"The Rise and Fall of Thinking Machines" 。这篇文章报道了这个产业的发展过程,以及思维机器同DARPA之间的关系是如何使市场变的过热并最终走向奔溃的。他还解释了为什么资本会远离AI而走近更加实用的数字超级计算机。

  第5代计算机在日本是一个耗资4亿美元的项目,是为了建造下一代计算机。第一代计算机使用电子管,第二代使用晶体管,第三代使用集成电路,第四代使用微处理器。而第5代计算机试图让机器具备有效的人工智能能力。这个项目引发了英国和美国的军备竞赛,并且导致了大量的AI泡沫。第5代计算机将提供大量的多CPU并行处理硬件,能够运行强大的知识表示和推理软件,比如:Prolog(一种专家系统);到了1992年,该项目被认为失败并取消了。对于Prolog来说,这是最大和最引人注目的商业冒险,而且很多失败的原因在于,他们试图在多CPU硬件上并发的运行基于逻辑的编程语言,并期望获取有效的结果。某些人相信5GP项目的失败连累了Prolog,并且将其打回了学术界,我们可以通过 " Whatever Happened to Prolog " 来了解这段历史。
  虽然在过去的20年里,基于系统的命令式语言(例如:C、C++、Java以及C#)占据了主导的地位,这得益于语言的实用性以及运行在商业硬件上的良好性能。而随着硬件能力的提升以及人工智能研究的进展使许多人相信AI领域的文艺复兴正在进行中。2005年,Heather Havenstein 在文章 " Spring comes to AI winter " 中阐述了这种复苏的理由。NorvigRussel 撰写了数篇文章来说明人工智能产业能够克服其自身问题的原因,而且这些研究的成果也开始显现:

最近几年,人工智能发生了方法和内容上的革命。在现有理论基础上进行发展比提出全新的理论更加常见,而且,以严格的定理或硬性实验证据而不是直觉为基础,并展示了与现实世界应用相关的例子, 而不仅仅只是一个玩具。

  计算机视觉,神经网络,机器学习以及知识表示和推理(KRR)已经取得了长足的发展,具备了商业环境下的实用性。举个例子:基于视觉的系统利用强大的识别技能已经能够完全映射和导航他所在的环境。这使得自动驾驶汽车开始投入市场。基于描述逻辑的本体论研究,提供了丰富的语义来表示我们的世界。算法(比如tableaux算法)使我们能够有效地在大型复杂本体上使用这些丰富的语义。早期的KRR系统,例如5GP时代的Prolog,一直被有限的语义表达能力和内存所困扰。

2. 知识表示和推理(KRR)

  在过去的一小段历史中,AI是一个广泛的涉及知识表示和推理以及专家系统的主题,稍后我们将回到专家系统。

  KRR就是我们如何使用符号形式来表示知识,也就是我们如何描述一些事情。推理是我们如何使用知识进行思考的行为。基于面向对象语言的系统,比如C++、Java和C#,使用定义为类的数据来描述模型实体的组成部分和相关的行为。在Java中我们将这些描述模型的东西称为 instances 或者 beans 。然而这些基于类别的系统在确保计算效率方面受到了限制。过了几年,研究者开发出了日益复杂的方式来表示我们的世界。我们许多人应该已经听说过OWL(网络本体语言)。通常理论上可以使用的东西与可以实际进行计算的东西之间是有差距的,这就是为什么OWL有着从精简到完整的各种子语言。因为完全地支持OWL语言是极为困难的。尽管如此,随着算法的不断进步,这种差距被不断的缩小,并且也在不断地提高推理引擎的表现力。
  也有很多其他的方法能够使这些系统开始思考。你应该听过对响应式的,数据驱动的前进链和被动式的,查找驱动的后退链进行比较的讨论。许多其他类型的推理技术,每一个都扩大了我们宣称可以解决的问题的范围。比如:不完全推理(模糊逻辑,确定因素)、不可行逻辑,信仰体系,时间推理和相关性。你无需理解所有这些名词就可以理解并使用Drools。这些名词能够让大家对研究主题的范围有一些了解,实际上这个范围更广阔,并随着研究人员的推动,他的边界也在不断的扩展。
  KRR常被称为是人工智能的核心。即使我们使用的生物方法比如神经网络(他建立了大脑的模型,更多的用于模式识别而不是是思考),也是建立在KRR理论的基础之上。我和Drools的第一份工作是工程导向的,并没有受过针对KRR的专门的培训。学习KRR能够使我们获取广泛的理论背景,能够使我们更好的理解做什么以及如何去做的问题,因为KRR为我们的Drools R&D提供了几乎所有理论方面的支持。它确实是一个巨大而引人入胜的主题,它将为那些花时间学习的人带来红利。 我知道它确实存在并且仍然适合我。 BrachamLevesque 写了一篇开创性的作品,名为 "知识表示和推理" ,对于想要建立坚实基础的人来说,这是必读的。 我还会推荐 RusselNorvig 的书《人工智能,一种现代方法》,它也涵盖了KRR。

3. 规则引擎以及产生式规则系统(Production Rule Systems 简称 PRS)

  我们简短地介绍了人工智能发展的历史,并且了解到AI的核心是以KRR的形式来表现的。KRR是一个巨大且吸引人的主题,他是驱动Drools R&D的理论基础。
  Drools引擎是一个计算机程序,他向开发者提供KRR的功能。在应用层面有三个部分组成:

  • 本体(Ontology)
  • 规则集(Rules)
  • 数据(Data)

  在前面的章节中,我们了解到本体是我们用来表示 "东西" 的模型。我们可以使用用户记录、Java类或成熟的基于OWL的本体来表示。规则集用来执行推理,它们促进 "思考" 。规则集和基于OWL的本体之间的区别有一点模糊,因为基于OWL的本体就是基于规则的。
  规则引擎是个模棱两可的词,任何系统都在使用任意形式的规则,而规则能够应用于数据并且产生结果。这些系统包括简单的表单验证和动态表达式引擎。Malcolm Chisholm 在 《How to Build a Business Rules Engine》(2004)这本书中就展示了这种情况。虽然这本书的书名叫做如何"构建业务规则引擎",但整本书实际是在说明如何设计和修改数据库表来保留验证规则,以及如何利用这些验证规则来生成VB代码来验证输入的数据。这是一个绝佳的例子,因为我们要讨论和这些完全是两码事。
  Drools从一开始就是一种特殊类型的规则引擎,被称为产生式规则系统(Production Rule System 简称 PRS),并且是基于 Rete 算法的。Rete 算法是 Charles Forgy 在1974年开发的,他构成了产生式规则引擎的大脑,并且能够扩展到大量的规则和事实。

产生式规则的结构由如下两部分构成:

when
    <conditions>
then
    <actions>;

Drools引擎根据产生式规则(也称为生产规则或规则)来匹配事实和数据,以推断导致行动的结论。

  通过产生式规则匹配事实(可以是新的也可以是已存在的)的过程被称为模式匹配,这个过程由推理引擎来执行。行为在响应后执行,用来修改数据;我们将此称为数据驱动的推理方法。行为本身能够改变数据,而数据又可能与导致它们触发的其他规则相匹配;这被称为正向链。
  Drools5.x版本实现并且扩展了Rete算法。扩展的Rete算法被称为ReteOO,顾名思义,Drools为面向对象的系统提供了增强并优化了的Rete算法实现。其他的基于Rete的引擎也为他们经过强过的Rete算法起了名字,比如RetePlus以及Rete III等。最通用的强化Rete算法是Robert B. Doorenbos在其论文《Production Matching for Large Learning Systems》(1995)中描述的Rete/UL算法。Drools6.x版本中引入了一种新的被称为PHREAK的懒惰算法;我们将会在专门的章节中讲解该算法。
  规则集会存储在生产内存中,而推理引擎进行匹配的事实会保存在工作内存中。事实被放置于工作内存中,可以被修改和回收。一个有大量规则和事实的系统,会导致有许多的规则在一些事实的断言上都为真;这些规则发生了冲突。而议程组件(Agenda)使用冲突解决策略来管理这些冲突规则的执行顺序。

产生式规则系统

4. 混合推理系统(Hybrid Reasoning Systems 简称 HRS)

  主要的推理方式有两种:前向链(响应和数据驱动式)和后向链(被动查找式)人们一直讨论并比较这两种方式的优点,接下来我们解释这两种主要的推理方式。
  前向链是数据驱动的,因此是响应式,首先事实被放入工作内存中与规则集中的规则进行匹配测试,这会导致事实与一个或多个规则同时匹配成功,接下来就需要通过Agenda组件进行调度并执行(执行行为,即规则中的action),执行完毕后如果有新的需要匹配的事实(生成新的事实或者已有事实被修改后重新发送)被放入工作空间,那么推理工作继续进行,如果没有新的事实产生,那么本次工作结束。简单的来说,我们从一个事实开始,让事实在规则中传播,在最后在一个结论中停止。

前向链
  后向链是目标驱动的,这意味着我们从一个Drools引擎尝试满足的结论开始,如果做不到,那么他就会寻找哪些能够满足的结论。这被称为子目标,将会帮助满足现有目标的一些未知的部分。这个过程会持续到当初始的结论被证明或者已经没有其他子目标了。Prolog是一个后向链引擎的例子。而Drools也能够执行后向链,就是我们提及的派生查询。
后向链
  在过去,你将不得不在前向(比如OPS5)或者后向(比如Prolog)系统之间做出选择。但是今天,许多现代的系统同时提供了这两种推理方式。当然也有很多其他的推理技术,每一种技术都扩大了我们声明要解决的问题的范围。比如:不确定推理(模糊逻辑,确定因素),不可行逻辑,信仰体系,时间推理和相关性等。现代的系统整合了这些技术(有些技术并没有在前文中列出),创造了混合推理系统(HRS)。
  Drools一开始只是产生式推理系统,在5.x版本中引入了后向链推理,因此现在我们可以使用混合推理系统来称呼Drools。
  虽然,当前的Drools版本只能提供清晰的推理(crisp reasoning),但不确定推理( imperfect reasoning)马上就要准备好了。最初将会是使用了模糊逻辑的不确定推理;后续,我们将会添加其他类型的不确定性的支持。基于OWL的本体论推理的工作目前仍在进行中,这项功能会集成到我们的特征系统中(traits system)中。我们也会持续的改进我们的函数式编程能力。

5. 专家系统

  你应该经常听到人们使用专家系统(expert systems)这个词来指称产生式规则系统(production rule systems)或者类似Prolog的系统。但这种说法在技术上是不正确的,产生式规则系统(production rule systems)或者类Prolog系统只是构建专家系统的技术体系,而不是专家系统本身。而专家系统一般包括表示领域知识的本体模型以及一些用于知识获取或解释的工具。
  MyCin是最著名的专家系统,与70年代建造。他仍然被大量的学术文献引用和描述,比如我们推荐的书籍《Expert Systems》(作者是Peter Jackson)。

专家系统的早期历史

6. Rete 算法

  Rete算法最早出现在 Charles Forgy 博士在1978-79年间发表的一篇论文。Rete算法最简单版本发表在1982年的一篇论文中whatever-happened-to-prolog。拉丁文 "rete" 的意思是 "net" 或者 "network"。Rete算法可以分为两个部分:规则编译和运行时执行。
  编译算法描述了生产内存中的规则是如何被处理并生成有效的识别网络的。如果用非技术性的文字来描述,那么识别网络是用来过滤在网络中传播的数据的。在网络顶部的结点将会有很多匹配,随着我们在网路中进行下移,匹配会越来越少。在网络的最下层是终结点。Forgy 博士在1982年的论文中描述了4种基本的结点:root1-input2-input 以及 terminal

Rete的几种节点
  根节点(root node)是所有对象进入网络的入口。从根节点开始,他会立刻进入ObjectTypeNodeObjectTypeNode的作用就是保证Drools引擎不必去做那些没有需要的工作。举个例子:我们有两个对象:AccountOrder。如果Drools引擎试图让每一个节点都去验证传入的对象,那么将会浪费很多周期。为了提高效率,Drools只会将对象传入与他的类型相匹配的结点。最简单的实现方式就是创建一个ObjectTypeNode,然后让所有的 1-input 结点和 2-input 结点跟在他后面。通过这种方式,如果一个应用判断新传入的对象是Account,那么该对象将不会被传播到那些与Order对象类型相匹配的结点上去。当Drools在开始检查对象时,会通过该对象的Class在一个哈希表中查找可用的ObjectTypeNodes列表,如果该列表不存在,它将扫描所有ObjectTypeNodes,查找它在列表中缓存的有效匹配项。Drools匹配任何与instanceof检查匹配的Class类型。
[图片上传失败...(image-9ad90-1552890011055)]
  ObjectTypeNodes能够向AlphaNodesLeftInputAdapterNodes以及BetaNodes传播。AlphaNodes用来执行文字条件(literal conditions)。尽管1982年的文章中只介绍了相等条件,但很多RETE的实现都支持更多的操作。举个例子:Account.name == "Mr Trout"就是一个文字条件(literal conditions)。当一个规则对单个对象有多个文字条件(literal conditions)约束时,这些条件将会链接成一个单项链表。也就是说,比如应用程序断定某个对象是Account对象,那么该对象必须先满足第一个文字条件,然后才能够被传到下一个AlphaNodes。在 Forgy 博士的文章中,他将这种情况称为元素内条件。下面的图表显示了AlphaNodeCheese( name == "cheddar", strength == "strong" )结合在一起:
AlphaNodes
  Drools扩展了Rete算法,使用了哈希法(hashing)优化了ObjectTypeNodeAlphaNode的传播。每当一个AlphaNode添加到一个ObjectTypeNode中时,他的字面量就作为keyAlphaNode本身作为value被添加到哈希表中。当一个新的实例进入ObjectTypeNode,他将会通过从哈希表中检索合适的AlphaNode,而不是在每一个AlphaNode中传播,这避免了不需要的迭代检查。
  有两种 2-input 结点,JoinNodeNotNode,这两种结点都是BetaNodesBetaNodes是用来对比两个对象的,以及他们的属性。这些对象可能是不同的类型的。为了方便进行描述,我们将这两个输入的对象分别称为左和右。BetaNodes的左边输入的一般是对象的列表(在Drools中是一个元组 - Tuple),而右边输入的是单个对象,这样就可以进行exists检查。BetaNodes一般都分配了内存。左边输入的内存被叫做 Beta Memory 被用来保存输入的 元组,右边输入的内存被称为 Alpha Memory 用来保存输入的对象。Drools扩展了Rete,能够在BetaNodes上执行索引。比如:一个BetaNode正在执行字符串属性的比较,每当有事实输入时,我们就可以对这个属性的字符串值做一个哈希查找。这意味着当事实从相反的一边进入的时候,我们无需遍历所有的事实集去发现有效的连接结点,而只需通过查找就能返回潜在的有效候选结点。在任何时候,都可以发现一个有效的连接,即元组与对象连接在一起;这被称为部分匹配;然后会被传播到下一个结点。
JoinNode
  我们使用LeftInputNodeAdapter(这个组件的功能时获取对象作为输入,并且传播只有一个对象的元组)将第一个对象(图中最上面的Cheese)置入网络。
  终端节点用于指示匹配其所有条件的单个规则;在这一点上,我们说规则有完全匹配。具有 '或(or)' 条件析取连接词的规则导致为每一个可能的逻辑分支生成子规则;因此一个规则可能具有多个终端结点。
  Drools也会执行结点共享。许多规则重复使用相同的模式,结点共享允许我们折叠这些模式,这样就不会对同一个对象重复执行相同的匹配。下面的规则共享第一条模式,但不是最后一条:
rule
when
    Cheese( $cheddar : name == "cheddar" )
    $person : Person( favouriteCheese == $cheddar )
then
    System.out.println( $person.getName() + " likes cheddar" );
end
rule
when
    Cheese( $cheddar : name == "cheddar" )
    $person : Person( favouriteCheese != $cheddar )
then
    System.out.println( $person.getName() + " does not like cheddar" );
end

  正如你在下图所看到的,一个编译好的 Rete 网络共享了AlphaNode,但并为共享BetaNode,每一个BetaNode都拥有自己的终端结点。如果我们让上例中的第二条模式相同,那么这个BetaNode也会成为共享结点。

Node Sharing

7. ReteOO算法

  ReteOO 算法的开发周期贯穿3,4,5三个系列版本。ReteOO 算法在 Rete 算法的基础上应用了很多我们已经熟知的强化功能,所有这些强化都已经在相应的文献中描述过:

结点共享(Node sharing

  • alphabeta 网络都应用了结点共享。beta 网络的共享始终来自于根模式。

Alpha 索引(Alpha indexing

  • 具有许多子节点的 Alpha 节点使用哈希查找机制来避免测试每个结果。

Beta 索引(Beta indexing

  • JoinNotExist 结点使用哈希法为他们的内存建立索引。这减少了相等检查的连接尝试。最近,范围索引也已经添加到了 NotExists 中。

基于树的图(Tree based graphs

  • 连接匹配项不包含其父匹配项和子匹配项的任何引用。删除必须再次重新计算所有连接匹配,这涉及重新创建所有这些连接匹配对象,以便能够找到应删除元组的网络部分。这被称为对称传播。树图能够提供父项和子项的引用。这被称为非对称传播。这种结果更快,对GC造成更少的影响,而且更健壮,因为如没有通知Drools引擎值的变化将不会导致内存泄漏。

原地修改(Modify-in-place

  • 传统的 Rete 实现修改的方式是删除后插入。这会导致所有的连接元组被GC回收,然后作为这次插入的一部分被重新创建出来。原地修改而不是传播一次传递;每一个结点都会被检查。

属性反应(Property reactive

  • 也被称为"新的触发条件"。允许对更新进行更细粒度的反应。一个模式能够对指定属性的变化做出反应,而忽略其他属性。这缓解了递归问题,同时能够帮助改善性能。

子网络(Sub-networks

  • NotExistsAccumulate 都拥有嵌套的条件元素,这些形成了子网络。

反向链(Backward Chaining

  • 支持用于反向链的 Prolog 样式的派生树。他基于栈来实现的,因此对于大型图来说不存在递归方法的问题。

延迟真理维护(Lazy Truth Maintenance

  • 无论是否使用TMS,真理维护(Truth Maintenance)都会产生运行时开销。延迟的TMS可以让这些开销在第一次使用的时候发生;之后会进一步激活每一种对象类型,而不相关的对象类型不会造成这些运行时开销。

基于堆的议程(Heap based agenda

  • 议程使用一个2叉堆队列,通过显著性对规则进行排序,而不是任何线性搜索或维护方法。

动态规则(Dynamic Rules

  • 规则可以在运行时被添加或者移除,而Drools引擎仍然填满了数据。

8. PHREAK算法

  Drools6 引入了新的算法来解决_ Rete_ 算法的一些核心问题。这个算法并不是从头开始重写的,他吸收了所有已有的代码以及来自于 ReteOO 的增强功能。由于 PHREAKRete 算法的进化,因此他不再做为 Rete 实现的类别。某种动物一旦进化到了某个点使得关键的特征发生了改变,那么这种动物就被归类为新的物种;对于 PHREAK 来说,也是一样得道理,因此 PHREAK 算法已经不被认为是一种RETE 算法了。在不考虑优化的前提下,Rete 算法具有两个关键的特征可以用来区别其他的衍生算法:

  • Rete 算法是一种即时的,面向数据的算法
  • 所有的工作都是通过插入,删除,更新操作来完成,会即时的产生所有规则的所有部分匹配

  PHREAK 算法的特点与之形成了鲜明对比,是一个懒惰的,面向目标的算法,部分匹配会被延迟聚集起来。
  RETE 算法的这种即时性在大型系统中会带来很多麻烦,并且会浪费很多工作,这些"被浪费的工作"是指那些不会触发规则的匹配工作。
  PHREAK 从一系列算法中获取了很多灵感,包括但不限于LEAPS 算法,RETE/UL 算法,以及面向集合的匹配算法等。PHREAK 拥有所有在讲解ReteOO的章节中所列出的增强功能,并且还增加了一系列新的增强功能,将在下面的段落进行详细的说明。

  • 三层上下文内存:Node层,Segment层以及Rule内存
  • 基于规则,片段和结点的链接
  • 延迟规则评估
  • 独立的规则评估
  • 面向集合的传播
  • 基于栈的,具有暂停和恢复的评估

  当PHREAK引擎启动时,所有的规则都被认为是未链接的;而在各规则未链接之前,不会有规则评估发生。插入、更新、删除操作在进入beta网络之前会先插入队列。一种简单的启发式算法,基于最有可能导致激发的规则,会用于选择下一个用于评估的规则;这会推迟其他规则的激发和评估。只有在规则填充了所有正确的输入后,才会将规则视为链接,尽管此时还未完成任何工作。而是创建一个代表规则的目标,并放入优先级队列; 该队列通过显著性排序。每一个队列与一个议程组(AgendaGroup)相关联。激活的AgendaGroup将会检查队列,为规则弹出显著性最高的目标然后提交进行评估。因此工作从插入、更新、删除阶段进行改为了在fireAllRules阶段进行。只有作为目标的规则在创建的时候会评估,其他所有关于这些事实的潜在规则的评估都是推迟的。当评估单个规则的同时,仍然通过分段过程实现节点共享,这将在后面解释。
  RETE中每一次成功的连接操作都会产生一个元组(或者是词,或者是部分匹配),这个元组将会传播到子结点。因此,他具有面向元组算法的特征。对于元组到达的每一个子结点,都会尝试与其他结点进行连接操作;对于每一次成功的连接尝试,都会继续传播下去。这种机制创造了一种下降递归的效果,即从beta网络的入口点,上下左右传播到所有能到达的叶子结点,这会对网络造成破坏。
  PHREAK 的传播是面向集合而不是元组。对于要评估的规则,他将会访问第一个结点并且处理所有入队的插入、更新和删除。结果将会添加到集合中并且集合会传播到子结点。在子结点中,所有入队的插入、更新删除将被执行,结果会被添加到相同的集合中。一旦结束,集合将会传播到下一个子结点,这个过程会继续下去直到传播到终端结点。这种机制创造了单通道管道类型的效果,将当前评估的规则隔离。他还创造了一种批处理机制,对于特定规则的构造提供了性能的提升,比如具有累积的子网络。未来,他将开发出多种能够利用多核机器的能力。
  链接和取消链接使用基于网络分段的层级位掩码系统。构建规则网络时,将为由同一组规则共享的节点创建段。规则本身由段的路径组成,但如果没有共享将成为单个段。将位掩码偏移分配给段中的每个节点。另外一个位掩码(分层)被分配给规则路径中的每个段。当至少有一个输入(数据传播)时,节点的位设置为on。当每个节点的位设置为on时,该段的位也设置为on。相反,如果任何节点的位设置为关闭,则该段也将设置为关闭。如果规则路径中的每个段都设置为on,则表示该规则已链接,并创建目标以计划评估规则。相同的位掩码技术也用于跟踪脏节点,段和规则;这允许已经链接的规则被安排用于评估,如果它被认为是脏的,因为它是上次评估的。
  这确保了任何规则都不会评估部分匹配,如果它不可能导致规则实例,因为其中一个连接没有数据。 这在RETE中是可能的,即使最后一个连接为空,它也会快速地为所有节点产生部分匹配尝试。

  虽然增量规则评估始终从根节点开始,但脏位掩码用于允许跳过非脏的节点和段。

  使用每个节点至少一个数据项的存在是一个相当基本的启发式算法。 未来的工作将尝试进一步延迟链接,使用诸如弧一致性之类的技术来确定匹配是否会导致规则实例激活。

  RETE只有一个内存,节点内存,PHREAK有3级内存。 这允许在评估规则期间进行更多的上下文理解。

PHREAK 3 Layered memory system

  示例1显示了具有三种模式的单个规则:A,B和C.它形成单个段,节点的位为1,2和4。 单个段的位偏移量为1。

[图片上传失败...(image-212a03-1552890011055)]

示例2演示了当添加另一个共享模式A的规则时会发生什么.A放置在它自己的段中,每个规则产生两个段。这两个部分构成了各自规则的路径。第一个段由两个路径共享。当A链接时,该段将被链接。然后,它迭代段共享的每个路径,将位1设置为打开。如果稍后打开B和C,则链接路径R1的第二段;这会导致R1的位2打开。对于R1,将位1和位2设置为打开,现在链接规则并创建目标以计划规则以供稍后评估和触发。

评估规则时,它是允许共享匹配结果的段。每个段都有一个暂存内存,用于对该段的所有插入,更新和删除进行排队。如果要评估R1,它将处理A并产生一组元组。该算法检测到存在分段拆分,并将为每个插入创建对等元组,在集合中更新和删除,并将它们添加到R2的临时存储器。这些元组将与任何现有的阶段元组合并,并等待R2最终被评估。


Example 2: Two rules, with sharing

示例3添加了第三条规则,并演示了共享A和B时会发生什么。 此时仅显示段的位。 证明R4有3个段,R3有3个段,R1有2个段。 A,B由R1,R3和R4共享。 虽然D由R3和R4共享。

Example 3: Three rules, with sharing

当Not,Exists或Accumulate节点包含多个元素时,将形成子网络。 在示例4中,“B not(C)”形成子网络,注意“not(C)”是不需要子网络的单个元素,因此在Not节点内合并。

子网络有自己的段。 R1仍然有两个段的路径。 子网络形成另一条“内部”路径。 链接子网络时,它将链接到外部网段。

Example 4 : Single rule, with sub-network and no sharing

示例5示出了子网络节点可以由不具有子网络的规则共享。 这导致子网段被分成两部分。

Example 5: Two rules, one with a sub-network and sharing

Constrained Not节点和Accumulate节点具有特殊行为:这些节点永远不能取消链接段,并且始终认为它们的位已打开。

所有规则评估都是递增的,并且不会浪费重新计算已经生成的匹配项。

评估算法是基于堆栈而不是方法递归。通过使用StackEntry表示当前正在评估的节点,可以随时暂停和恢复评估。

当规则评估到达子网络时,为外部路径段和子网段创建StackEntry。首先评估子网段;当集合到达子网络路径的末尾时,它将合并到它所输入的外部节点的分段列表中。然后恢复先前的StackEntry,现在可以处理子网络的结果。这具有额外的好处,即在传播到子节点之前,批量处理所有工作;这对Accumulate节点来说效率更高。

相同的堆栈系统可用于有效的反向链接。当规则评估到达查询节点时,它再次暂停当前评估,方法是将其放在堆栈上。然后评估查询,该查询生成结果集,该结果集保存在内存位置,以便恢复的StackEntry获取并传播到子节点。如果查询本身调用其他查询,则该过程将重复,暂停当前查询并为当前查询节点设置新的评估。

关于性能的最后一点:一般来说,单个规则对PHREAK的评估速度不会比使用RETE时更快。对于使用根上下文对象启用和禁用匹配的给定规则和相同数据集,两者都尝试相同数量的匹配,生成相同数量的规则实例并占用大致相同的时间量,但用例除外with subnetworks和Accumulates。

然而,PHREAK可以被认为是更加宽容的RETE,因为规则基础写得不好,随着规则数量和复杂性的增加,性能会更优雅地降低。

RETE也将为所有连接中没有数据的规则生成部分匹配,而PHREAK将避免这种情况。

所以PHREAK并不比RETE快;它不会像你的系统增长那样慢下来:)

议程小组对RETE表现没有帮助,因为所有规则都在任何时候进行评估,无论小组如何。对于显着性也是如此,这就是为什么根上下文对象通常用于限制匹配尝试的原因。 PHREAK仅评估活动AgendaGroup的规则,并且该组内将尝试避免评估不会导致规则实例触发的规则(通过显着性)。

借助PHREAK,AgendaGroups和salience现在成为有用的性能工具。不再需要根上下文对象,并且可能会对性能产生反作用,因为它们会强制刷新和重新创建匹配规则。

相关文章

网友评论

    本文标题:Hybrid Reasoning System(混合推理系统,D

    本文链接:https://www.haomeiwen.com/subject/qvffuqtx.html