21.4. Fibonacci 示例决策(接收和冲突解析)


Fibonacci 示例决策集演示了决策引擎如何使用递归来解析序列中的规则执行冲突。这个示例侧重于通过在规则中定义的同等值来解决冲突。

以下是 Fibonacci 示例概述:

  • 名称fibonacci
  • 主类org.drools.examples.fibonacci.FibonacciExample (在 src/main/java中)
  • 模块drools-examples
  • 键入: Java 应用程序
  • 规则文件org.drools.examples.fibonacci.Fibonacci.drl ( src/main/resources)
  • 目标 :通过规则策略检查和冲突解决

Fibonacci Numbers 形成一个以 0 和 1 开头的序列。下一个 Fibonacci 编号通过添加前两个 Fibonacci number 中获取: 0, 1, 1, 2, 3, 5, 8, 8, 13, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946 等。

Fibonacci 示例使用单一事实类 Fibonacci 和以下两个字段:

  • 序列
  • value

sequence 字段显示对象在 Fibonacci 数字序列中的位置。value 字段显示该序列位置的 Fibonacci 对象的值,其中 -1 表示仍然需要计算的值。

Fibonacci 类

public static class Fibonacci {
    private int  sequence;
    private long value;

    public Fibonacci( final int sequence ) {
        this.sequence = sequence;
        this.value = -1;
    }

    ... setters and getters go here...
}
Copy to Clipboard Toggle word wrap

要执行该示例,请运行 org.drools.examples.fibonacci.FibonacciExample 类,作为 IDE 中的 Java 应用程序。

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

IDE 控制台中的 Fibonacci 示例输出

recurse for 50
recurse for 49
recurse for 48
recurse for 47
...
recurse for 5
recurse for 4
recurse for 3
recurse for 2
1 == 1
2 == 1
3 == 2
4 == 3
5 == 5
6 == 8
...
47 == 2971215073
48 == 4807526976
49 == 7778742049
50 == 12586269025
Copy to Clipboard Toggle word wrap

要在 Java 中实现此行为,示例将一个 Fibonacci 对象插入一个 Fibonacci 对象,其序列字段为 50。然后,示例使用递归规则插入其他 49 Fibonacci 对象。

本示例使用 MVEL dialect 修改 关键字来启用块 setter 操作并通知决策引擎更改,而不是实现 PropertyChangeSupport 接口使用动态事实。

Fibonacci 示例执行

ksession.insert( new Fibonacci( 50 ) );
ksession.fireAllRules();
Copy to Clipboard Toggle word wrap

本例使用以下三个规则:

  • "recurse"
  • "bootstrap"
  • "计算"

规则 "Recurse" 匹配每个断言的 Fibonacci 对象,其值为 -1,创建并断出新的 Fibonacci 对象,其序列比当前匹配对象小。每次添加 Fibonacci 对象时,只要存在等于 1 的 sequence 字段,则规则重新匹配并再次触发。如果没有 条件元素,当您在内存中拥有 50 Fibonacci 对象后,不使用条件元素停止匹配规则。该规则也有 salience 值,因为您需要在执行 "Bootstrap" 规则前断断所有 50 Fibonacci 对象。

规则 "Recurse"

rule "Recurse"
    salience 10
  when
    f : Fibonacci ( value == -1 )
    not ( Fibonacci ( sequence == 1 ) )
  then
    insert( new Fibonacci( f.sequence - 1 ) );
    System.out.println( "recurse for " + f.sequence );
end
Copy to Clipboard Toggle word wrap

为了更好地理解本例的执行流,您可以将审计日志文件从 target/fibonacci.log 加载到 IDE 调试视图或 Audit View (例如,如果可用,位于 Window Show View in some IDE)。

在本例中,审计 视图显示 Fibonacci 对象的原始断言,其 序列字段为 50,它通过 Java 代码完成。在那里,审计 视图显示规则的连续递归,其中每个断言的 Fibonacci 对象会导致 "Recurse" 规则变为激活并再次触发。

图 21.7. Audit 视图中的规则"重复"

如果 Fibonacci 带有 序列字段的 Fib onacci 对象被断言,"Bootstrap" 规则会与 "Recurse" 规则一起匹配和激活。请注意,对字段 序列 的多个限制,使用 12 测试是否相等:

规则 "Bootstrap"

rule "Bootstrap"
  when
    f : Fibonacci( sequence == 1 || == 2, value == -1 ) // multi-restriction
  then
    modify ( f ){ value = 1 };
    System.out.println( f.sequence + " == " + f.value );
end
Copy to Clipboard Toggle word wrap

您还可以使用 IDE 中的 Agenda View 来调查决策引擎日程表的状态。"Bootstrap" 规则尚未触发,因为 "Recurse" 规则具有更高的 salience 值。

图 21.8. Agenda View 1 中的规则"Recurse"和"Bootstrap"

当断言了 序列1Fibonacci 对象时,会再次匹配 "Bootstrap" 规则,从而导致此规则有两个激活。"Recurse" 规则不匹配并激活,因为 not 条件元素在存在 序列Fibonacci 对象时立即停止匹配规则。

图 21.9. Agenda View 2 中的规则"Recurse"和"Bootstrap"

"Bootstrap" 规则使用 序列 1 2 的值来设置对象。现在,有两个 Fibonacci 对象的值不等于 -1"Calculate" 规则可以匹配。

此时,工作内存中有近 50 Fibonacci 对象。您需要依次选择适当的三角来计算其每个值。如果您在没有字段限制的规则中使用三个 Fibonacci 模式来限制可能的跨产品,则结果将是 50x49x48 个可能的组合,从而导致大约 125,000 个可能的规则触发,其中大多数不正确。

"Calculate" 规则使用字段限制来以正确顺序评估三个 Fibonacci 模式。这种技术称为与 跨产品匹配的跨产品

第一个模式找到任何值为 != -1Fibonacci 对象,并且绑定模式和字段。第二个 Fibonacci 对象执行相同的操作,但添加了额外的字段约束,以确保其序列大于绑定到 f1Fibonacci 对象。当这个规则首次触发时,您知道只有序列 12 的值为 1,并且两个限制可确保 f1 参考序列 1f2 参考序列 2

最终模式找到一个值等于 -1 且序列大于 f2Fibonacci 对象。

此时,可以从可用的跨产品正确选择三个 Fibonacci 对象,您可以计算绑定到 f3 的第三个 Fibonacci 对象的值。

规则"计算"

rule "Calculate"
  when
    // Bind f1 and s1.
    f1 : Fibonacci( s1 : sequence, value != -1 )
    // Bind f2 and v2, refer to bound variable s1.
    f2 : Fibonacci( sequence == (s1 + 1), v2 : value != -1 )
    // Bind f3 and s3, alternative reference of f2.sequence.
    f3 : Fibonacci( s3 : sequence == (f2.sequence + 1 ), value == -1 )
  then
    // Note the various referencing techniques.
    modify ( f3 ) { value = f1.value + v2 };
    System.out.println( s3 + " == " + f3.value );
end
Copy to Clipboard Toggle word wrap

modify 语句更新绑定到 f3Fibonacci 对象的值。这意味着,您现在有一个没有等于 -1 的新 Fibonacci 对象,它允许 "Calculate" 规则重新匹配并计算下一个 Fibonacci 号。

IDE 的 debug 视图或 Audit View 显示触发最后 "Bootstrap" 规则如何修改 Fibonacci 对象,启用 "Calculate" 规则以匹配,然后修改另一个 Fibonacci 对象,以便重新匹配 "Calculate" 规则。此过程将继续,直到为所有 Fibonacci 对象设置了值。

图 21.10. Audit 视图中的规则

返回顶部
Red Hat logoGithubredditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

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

让开源更具包容性

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

關於紅帽

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

Theme

© 2025 Red Hat