21.3. 状态决策示例(转发链和冲突解析)
State 示例决策集演示了决策引擎如何使用正向链以及正在正常工作内存中的事实更改来解决按顺序规则的执行冲突。该示例着重介绍通过相同值或通过在规则中定义的日程表组解决冲突。
以下是状态示例概述:
-
名称 :
状态
-
主类 :
org.drools.examples.state.StateExampleUsingSalience
,org.drools.examples.state.StateExampleUsingAgendaGroup
(在src/main/java
中) -
模块 :
drools-examples
- 键入: Java 应用程序
-
规则文件 :
org.drools.examples.state.*.drl
(在src/main/resources
) - 目标 :通过规则认证和日程组演示转发链和冲突解决情况
forward-chaining 规则系统是一个由数据驱动的系统,它从决策引擎的工作内存从事实开始,并对事实做出响应。当对象插入到工作内存时,因为更改是由日程表计划执行而变为 true 的任何规则条件。
相反,反向链接规则系统是一个由目标驱动的系统,从结论开始,决定引擎尝试满足,通常使用递归。如果系统无法达到结论或目标,它会搜索部分当前目标的子项。系统会继续这个过程,直到初始的结论是满足或者所有子语满意。
Red Hat Process Automation Manager 中的决策引擎使用正向和向后链来评估规则。
下图显示了如何使用转发链在逻辑流中的反向链接片段评估规则:
图 21.4. 使用转发和向后链的规则评估逻辑
在 State 示例中,每个 State
类都有一个名称及其当前状态的字段(请参阅类 org.drools.examples.state.State
)。以下状态是每个对象的两个可能状态:
-
NOTRUN
-
完成
State class
public class State { public static final int NOTRUN = 0; public static final int FINISHED = 1; private final PropertyChangeSupport changes = new PropertyChangeSupport( this ); private String name; private int state; ... setters and getters go here... }
State 示例包含两个版本的同一示例,用于解决规则执行冲突:
-
一个
StateExampleUsingSalience
版本,它通过使用规则 salience 解决了冲突 -
一个
StateExampleUsingAgendaGroups
版本,它通过使用规则日程表组解决冲突
两个状态示例都涉及四个状态对象: A
、B
、C
和 D
。最初,其状态设定为
NOTRUN
,这是示例使用的构造器的默认值。
使用 salience 的州示例
State 示例的 StateExampleUsingSalience
版本使用规则中的 salience 值来解决规则执行冲突。在激活队列中排序时,具有较高优先级的规则会被赋予更高的优先级。
示例将每个 State
实例插入到 KIE 会话中,然后调用 fireAllRules()
。
Salience 状态执行示例
final State a = new State( "A" ); final State b = new State( "B" ); final State c = new State( "C" ); final State d = new State( "D" ); ksession.insert( a ); ksession.insert( b ); ksession.insert( c ); ksession.insert( d ); ksession.fireAllRules(); // Dispose KIE session if stateful (not required if stateless). ksession.dispose();
要执行该示例,请运行 org.drools.examples.state.StateExampleUsingSalience
类作为 IDE 中的 Java 应用程序。
执行后,会在 IDE 控制台窗口中显示以下输出:
IDE 控制台中的 Salience State 示例输出
A finished B finished C finished D finished
有四个规则:
首先,"Bootstrap"
规则触发,将 A
设置为状态为 FINISHED
,然后使 B
将其状态更改为 FINISHED
。对象 C
和 D
都依赖于 B
,从而导致了值解析的冲突。
为了更好地了解本例中的执行流,您可以将审计日志文件从 target/state.log
加载到 IDE 调试视图或 Audit View (例如,如果可用)。
在本例中,审计视图 显示状态中对象 A
的断言不会激活 "Bootstrap"
规则,而其他对象的断言没有立即生效。
图 21.5. Salience State 示例 Audit 视图
salience State 示例中的规则"引导"示例
rule "Bootstrap" when a : State(name == "A", state == State.NOTRUN ) then System.out.println(a.getName() + " finished" ); a.setState( State.FINISHED ); end
"Bootstrap"
规则的执行会将 A
的状态更改为 FINISHED
,后者可激活规则 "A 到 B
"。
salience State 示例中的规则"A 到 B"
rule "A to B" when State(name == "A", state == State.FINISHED ) b : State(name == "B", state == State.NOTRUN ) then System.out.println(b.getName() + " finished" ); b.setState( State.FINISHED ); end
规则 "A 到 B"
的执行将 B
的状态更改为 FINISHED
,后者可激活 "B 到 C"
和 "B 到 D"
,将其激活置于决策引擎日程表上。
salience State 示例中的规则"B 至 C"和"B to D"
rule "B to C" salience 10 when State(name == "B", state == State.FINISHED ) c : State(name == "C", state == State.NOTRUN ) then System.out.println(c.getName() + " finished" ); c.setState( State.FINISHED ); end rule "B to D" when State(name == "B", state == State.FINISHED ) d : State(name == "D", state == State.NOTRUN ) then System.out.println(d.getName() + " finished" ); d.setState( State.FINISHED ); end
此时,规则可能会触发,因此规则存在冲突。冲突解决策略使决策引擎日程表决定要触发的规则。规则 "B to C"
的值较高(10
与默认值 0
不同),因此它首先触发对象 C
,将对象 C 改为 state FINISHED
。
IDE 中的 Audit 视图显示对规则 "A 到 B"
中的 State
对象的修改,这会导致两个激活冲突。
您还可以使用 IDE 中的 Agenda View 来调查决策引擎日程表的状态。在本例中,Agen da View 显示规则 "A 到 B"
中的断点,以及带有两个冲突的规则的日程表状态。规则 "B to D"
最后触发,将对象 D
修改为状态为 FINISHED
。
图 21.6. Salience State example Agenda View
使用日程组进行状态示例
State 示例的 State 示例中的 StateExampleUsingAgendaGroups
版本使用 Rules 中的 table 组来解决规则执行冲突。日程表组使您可以对决策引擎日程表进行分区,以便对规则组提供更多执行控制。默认情况下,所有规则均位于 MAIN
日程小组。您可以使用 schedule -group
属性来指定该规则的不同日程表组。
最初,工作内存专注于 MAIN
的日程安排。仅当该组收到相关事项时,即可参与日程表组中的规则。您可以使用方法 setFocus()
或 rule 属性 auto-focus
来设置焦点。auto-focus
属性允许当规则匹配和激活时,自动为课程安排人员自动给定规则。
在本例中,auto-focus
属性可让规则 "B to C"
在 "B to D"
前触发。
会议小组示例中的规则"B to C"
rule "B to C" agenda-group "B to C" auto-focus true when State(name == "B", state == State.FINISHED ) c : State(name == "C", state == State.NOTRUN ) then System.out.println(c.getName() + " finished" ); c.setState( State.FINISHED ); kcontext.getKnowledgeRuntime().getAgenda().getAgendaGroup( "B to D" ).setFocus(); end
在 Registration group "B to C"
中的规则 "B to C"
调用 setFocus()
,使其活动规则可以触发,然后启用规则 "B to D
"。
会议小组示例中的规则"B to D"
rule "B to D" agenda-group "B to D" when State(name == "B", state == State.FINISHED ) d : State(name == "D", state == State.NOTRUN ) then System.out.println(d.getName() + " finished" ); d.setState( State.FINISHED ); end
要执行该示例,请运行 org.drools.examples.state.StateExampleUsingAgendaGroups
类作为 IDE 中的 Java 应用程序。
执行后,会在 IDE 控制台窗口中显示以下输出(与状态示例的 salience 版本相同):
IDE 控制台中查看组状态示例输出
A finished B finished C finished D finished
State 示例中的动态事实
此 State 示例中的另一个值得注意的概念是根据实施 PropertyChangeListener
对象的对象,使用动态事实。要让决策引擎查看和响应事实属性更改,应用程序必须通知发生更改的决策引擎。您可以使用 modify
语句在规则中明确配置此通信,或者通过指定事实实施 PropertyChangeSupport 接口(如 format)规范定义的 PropertyChangeSupport
接口来显式配置此通信。
本例演示了如何使用 PropertyChangeSupport
接口以避免规则中明确 修改
语句的需求。要使用此接口,请确保您的事实实施 PropertyChangeSupport
,这与类 org.drools.example.State
实施的方式相同,然后在 DRL 规则文件中使用以下代码,将决策引擎配置为侦听这些事实上的属性更改:
声明动态事实
declare type State @propertyChangeSupport end
使用 PropertyChangeListener
对象时,每个 setter 必须实施通知的额外代码。例如,以下 state
的设置者位于类 org.drools.examples
中:
带有 PropertyChangeSupport 的 setter 示例
public void setState(final int newState) { int oldState = this.state; this.state = newState; this.changes.firePropertyChange( "state", oldState, newState ); }