19.10. 定制 Doom 示例决策(返回链和递归)


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中)
  • 目标 :演示后链和递归

后链规则系统是一个目标驱动的系统,从决策引擎尝试满足的目标驱动的系统开始,通常使用递归。如果系统无法访问语音或目标,它会搜索子组,这是完成当前目标的一部分。系统会继续这个过程,直到满足初始目标或满足所有子状态为止。

相反,转发链规则系统是一个数据驱动的系统,它以决策引擎的工作内存中的事实开始,并对这一事实的更改做出响应。当对象插入到工作内存中时,因更改计划执行而满足的任何规则条件。

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

下图演示了,决策引擎如何使用转发链和逻辑流中的向链段来评估规则:

图 19.27. 使用正向和后链的规则评估逻辑

Doom 示例的 House 使用各种类型的查询的规则来查找托管中的房间和项目的位置。示例类 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") );
Copy to Clipboard Toggle word wrap

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

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

图 19.28. Doom 结构的托管

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

执行后,以下输出会出现在 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
Copy to Clipboard Toggle word wrap

示例中的所有规则都触发,以检测托管中的所有项目的位置,并在输出中打印各个项目的位置。

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

在 Doom 示例中的 House 中,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
Copy to Clipboard Toggle word wrap

规则 "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
Copy to Clipboard Toggle word wrap

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

插入字符串和触发规则

ksession.insert( "go1" );
ksession.fireAllRules();
Copy to Clipboard Toggle word wrap

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

go1
Office is in the House
Copy to Clipboard Toggle word wrap

传输冲突规则

传输是父元素中包含的元素之间的关系,它在分级结构中有多个级别。

规则 "go2" 标识 DrawerHouse 的传输关系,即 Drawer 位于 House 内的 Desk 中。

rule "go2"
  when
    String( this == "go2" )
    isContainedIn("Drawer", "House"; )
  then
    System.out.println( "Drawer is in the House" );
end
Copy to Clipboard Toggle word wrap

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

插入字符串和触发规则

ksession.insert( "go2" );
ksession.fireAllRules();
Copy to Clipboard Toggle word wrap

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

go2
Drawer is in the House
Copy to Clipboard Toggle word wrap

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

  1. 查询递归搜索存放中的多个级别,以检测 DrawerHouse 之间的传输冲突。
  2. 查询使用 Location (x, y;),而是使用 (z, y;),因为 Drawer 不直接在 House 中。
  3. z 参数当前未绑定,这意味着它没有值并返回参数中的所有内容。
  4. y 参数当前绑定到 House,因此 z 返回 OfficeKitchen
  5. 如果 Drawer 位于 响应者,查询会从印度收集信息并递归检查。为这些参数调用查询行 isContainedIn (x, z;)
  6. 印度没有直接存在 Drawer 实例,因此找不到任何匹配项。
  7. 使用 z unbound 时,查询会返回响应者中的数据,并确定 z == Desk

    isContainedIn(x==drawer, z==desk)
    Copy to Clipboard Toggle word wrap
  8. isContainedIn 查询递归搜索三次,第三个时间则查询会检测 Desk 中的 Drawer 实例。

    Location(x==drawer, y==desk)
    Copy to Clipboard Toggle word wrap
  9. 在第一个位置上匹配后,查询会递归搜索结构,以确定 Drawer 是否在 Desk 中,De sk 位于印度,且响应者位于 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
Copy to Clipboard Toggle word wrap

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

插入字符串和触发规则

ksession.insert( "go3" );
ksession.fireAllRules();
Copy to Clipboard Toggle word wrap

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

go3
Copy to Clipboard Toggle word wrap

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

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

ksession.insert( new Location("Key", "Drawer") );
ksession.fireAllRules();
Copy to Clipboard Toggle word wrap

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

Key is in the Office
Copy to Clipboard Toggle word wrap

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

在规则中使用未绑定参数的查询

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

规则 "go4" 使用 unbound 参数操作来搜索绑定参数 响应中的 所有项目,而不是使用 bound 参数搜索响应者中的特定项目:

规则"go4"

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

示例将 "go4" 字符串插入到决策引擎中,并激活 "go4" 规则,以返回响应者中的所有项目:

插入字符串和触发规则

ksession.insert( "go4" );
ksession.fireAllRules();
Copy to Clipboard Toggle word wrap

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
Copy to Clipboard Toggle word wrap

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

规则 "go5"

rule "go5"
  when
    String( this == "go5" )
    isContainedIn(thing, location; )
  then
    System.out.println(thing + " is in " + location );
end
Copy to Clipboard Toggle word wrap

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

插入字符串和触发规则

ksession.insert( "go5" );
ksession.fireAllRules();
Copy to Clipboard Toggle word wrap

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
Copy to Clipboard Toggle word wrap

返回顶部
Red Hat logoGithubredditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

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

让开源更具包容性

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

關於紅帽

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

Theme

© 2025 Red Hat