搜索

21.10. Doom 示例决策内部(反向连锁和递归)

download PDF

Doom 示例决策集的 House 展示了决策引擎如何使用向串联和递归来达到等级系统中定义的目标或子项。

以下是 Doom 示例 House 的概述:

  • 名称反向链接
  • 主类org.drools.examples.backwardchaining.HouseOfDoomMain (在 src/main/java中)
  • 模块drools-examples
  • 键入: Java 应用程序
  • 规则文件org.drools.examples.backwardchaining.BC-Example.drl ( src/main/resources)
  • 目标 :演示后向链和递归

反向链规则系统是一个目标驱动的系统,从结论开始,决定引擎尝试满足(通常使用递归)。如果系统无法达到结论或目标,它会搜索部分当前目标的子项。系统会继续这个过程,直到初始的结论是满足或者所有子语满意。

与之相反,正向链规则系统是一个数据驱动的系统,从决策引擎的工作内存中以事实开头,并对该事实的更改做出响应。当对象插入到工作内存时,因为更改是由日程表计划执行而变为 true 的任何规则条件。

Red Hat Process Automation Manager 中的决策引擎使用正向和向后链来评估规则。

下图显示了如何使用转发链在逻辑流中的反向链接片段评估规则:

图 21.27. 使用转发和向后链的规则评估逻辑

RuleEvaluation Enterprise

例如,House of Doom 示例使用包含各种查询类型的规则来查找房间和项目的位置。示例类 Location.java 包含示例中使用的 项目 和位置 元素。示例类 HouseOfDoomMain.java 在其所在位置插入项目或房间,并执行规则。

HouseOfDoomMain.java 类中的项目和位置

ksession.insert( new Location("Office", "House") );
ksession.insert( new Location("Kitchen", "House") );
ksession.insert( new Location("Knife", "Kitchen") );
ksession.insert( new Location("Cheese", "Kitchen") );
ksession.insert( new Location("Desk", "Office") );
ksession.insert( new Location("Chair", "Office") );
ksession.insert( new Location("Computer", "Desk") );
ksession.insert( new Location("Drawer", "Desk") );

示例规则依赖于向后链和递归来确定内部结构中所有项目和房间的位置。

下图展示了 Doom 的 House 的结构以及其中的项目和房间:

图 21.28. Doom 结构内部

TransitiveReasoning Enterprise

要执行示例,请运行 org.drools.examples.backwardchaining.HouseOfDoomMain 类,在 IDE 中作为 Java 应用程序。

执行后,会在 IDE 控制台窗口中显示以下输出:

IDE 控制台中的执行输出

go1
Office is in the House
---
go2
Drawer is in the House
---
go3
---
Key is in the Office
---
go4
Chair is in the Office
Desk is in the Office
Key is in the Office
Computer is in the Office
Drawer is in the Office
---
go5
Chair is in Office
Desk is in Office
Drawer is in Desk
Key is in Drawer
Kitchen is in House
Cheese is in Kitchen
Knife is in Kitchen
Computer is in Desk
Office is in House
Key is in Office
Drawer is in House
Computer is in House
Key is in House
Desk is in House
Chair is in House
Knife is in House
Cheese is in House
Computer is in Office
Drawer is in Office
Key is in Desk

示例中的所有规则均已触发,以检测内部所有项目的位置,并在输出中打印各个项目的位置。

递归查询会重复搜索数据结构的层次结构,以获得元素之间的关系。

在 Doom 示例的 House of Doom 示例中,BC-Example.drl 文件包含一个 isContainedIn 查询,示例中大多数规则的查询用于递归评估插入到决策引擎中的数据结构:

BC-Example.drl 中的递归查询

query isContainedIn( String x, String y )
  Location( x, y; )
  or
  ( Location( z, y; ) and isContainedIn( x, z; ) )
end

规则 "go" 打印插入到系统中的每个字符串,以确定如何实施项目,规则 "go1" 调用查询 为ContainedIn

规则 "go" 和 "go1"

rule "go" salience 10
  when
    $s : String()
  then
    System.out.println( $s );
end

rule "go1"
  when
    String( this == "go1" )
    isContainedIn("Office", "House"; )
  then
    System.out.println( "Office is in the House" );
end

这个示例将 "go1" 字符串插入到决策引擎中,并激活 "go1" 规则来检测该项目 办事处 位于位置 House 中:

插入字符串和触发规则

ksession.insert( "go1" );
ksession.fireAllRules();

IDE 控制台中的规则"go1"输出

go1
Office is in the House

临时防止规则

传输冲突是父元素中包含的元素之间的关系,该元素在分级结构中高于多个级别。

规则 "go2" 标识 DrawerHouse 的传输冲突:D rawerHouse 处位于办事处的 Desk

rule "go2"
  when
    String( this == "go2" )
    isContainedIn("Drawer", "House"; )
  then
    System.out.println( "Drawer is in the House" );
end

这个示例将 "go2" 字符串插入到决策引擎中,并激活 "go2" 规则,以检测项目 Drawer 最终在位置 House 中:

插入字符串和触发规则

ksession.insert( "go2" );
ksession.fireAllRules();

IDE 控制台中的规则"go2"输出

go2
Drawer is in the House

决策引擎根据以下逻辑决定这一结果:

  1. 查询会以递归方式搜索内部的几个级别,以检测 DrawerHouse 之间传输冲突。
  2. 查询该选项使用 (z, y;) 而不是使用 Location(x, y;),因为 Drawer 不在 House 中。
  3. z 参数目前未绑定,这意味着它没有值并返回参数中的所有内容。
  4. y 参数目前绑定到 House,因此 z 返回 office 和 Kitchen
  5. 该查询从 办公室 收集信息并递归检查该办事处是否位于 办事处对于这些参数,调用查询行 isContainedIn(x, z;)
  6. 办事处 没有直接存在 Drawer 实例,因此无法找到任何匹配项。
  7. 通过 z unbound,查询会返回 办事处 中的数据,并确定 z == Desk

    isContainedIn(x==drawer, z==desk)
  8. isContainedIn 查询会以递归方式搜索三次,而且在第三个时间,查询检测到 Desk 中的 Drawer 实例。

    Location(x==drawer, y==desk)
  9. 在第一个位置上的此匹配项后,查询会以递归方式搜索结构,以确定 Drawer 位于 Desk 中,Desk 位于 办事处,且该 办事处 位于 House 中。因此,Drawer 位于 House 中,该规则会满足。

被动查询规则

被动查询会搜索数据结构的层次结构,以获得元素之间的关系,并在修改结构中的元素时动态更新。

规则 "go3" 函数作为被动查询,通过传输冲突检测到在 办公室中 是否出现新的项目 密钥办公室的 Drawer 中的密钥

规则"go3"

rule "go3"
  when
    String( this == "go3" )
    isContainedIn("Key", "Office"; )
  then
    System.out.println( "Key is in the Office" );
end

这个示例将 "go3" 字符串插入到决策引擎中,并激活 "go3" 规则。最初,此规则不满意,因为内部结构中没有项目 密钥,因此该规则不会产生任何输出。

插入字符串和触发规则

ksession.insert( "go3" );
ksession.fireAllRules();

IDE 控制台中的规则"go3"输出(不满意)

go3

然后,示例在位置 Drawer 中插入一个新项目 密钥,它位于 办事处。这个更改满足在 "go3" 规则中传输冲突,输出会被相应地填充。

插入新项目位置和触发规则

ksession.insert( new Location("Key", "Drawer") );
ksession.fireAllRules();

IDE 控制台中的规则"go3"输出(satisfied)

Key is in the Office

此更改也会在查询后续递归搜索中包含的结构中添加另一个级别。

在规则中带有 unbound 参数的查询

带有一个或多个未绑定参数的查询会返回查询定义的(绑定)参数内所有未定义(绑定)项。如果查询中的所有参数都未绑定,则查询会返回查询范围内的所有项目。

规则 "go4" 使用 unbound 参数项搜索绑定参数 办事处 的所有项目,而不是使用 bound 参数搜索 office 中的特定项目:

规则"go4"

rule "go4"
  when
    String( this == "go4" )
    isContainedIn(thing, "Office"; )
  then
    System.out.println( thing + "is in the Office" );
end

这个示例将 "go4" 字符串插入到决策引擎中,并激活 "go4" 规则,以返回办公室中的所有项目:

插入字符串和触发规则

ksession.insert( "go4" );
ksession.fireAllRules();

IDE 控制台中的规则"go4"输出

go4
Chair is in the Office
Desk is in the Office
Key is in the Office
Computer is in the Office
Drawer is in the Office

规则 "go5" 使用 unbound 参数项 和位置 来搜索整个 House 数据结构中的所有项目及其位置:

规则"go5"

rule "go5"
  when
    String( this == "go5" )
    isContainedIn(thing, location; )
  then
    System.out.println(thing + " is in " + location );
end

这个示例将 "go5" 字符串插入到决策引擎中,并激活 "go5" 规则,以返回 House 数据结构中的所有项目及其位置:

插入字符串和触发规则

ksession.insert( "go5" );
ksession.fireAllRules();

IDE 控制台中的规则"go5"输出

go5
Chair is in Office
Desk is in Office
Drawer is in Desk
Key is in Drawer
Kitchen is in House
Cheese is in Kitchen
Knife is in Kitchen
Computer is in Desk
Office is in House
Key is in Office
Drawer is in House
Computer is in House
Key is in House
Desk is in House
Chair is in House
Knife is in House
Cheese is in House
Computer is in Office
Drawer is in Office
Key is in Desk

Red Hat logoGithubRedditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

© 2024 Red Hat, Inc.