89.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... }
要执行该示例,请运行 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
要在 Java 中实现此行为,示例将一个 Fibonacci 对象插入一个 Fibonacci
对象,其序列字段为 50
。然后,示例使用递归规则插入其他 49 Fibonacci
对象。
本示例使用 MVEL dialect 修改
关键字来启用块 setter 操作并通知决策引擎更改,而不是实现 PropertyChangeSupport
接口使用动态事实。
Fibonacci 示例执行
ksession.insert( new Fibonacci( 50 ) ); ksession.fireAllRules();
本例使用以下三个规则:
-
"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
为了更好地理解本例的执行流,您可以将审计日志文件从 target/fibonacci.log
加载到 IDE 调试视图或 Audit View (例如,如果可用,位于 Window
在本例中,审计 视图显示 Fibonacci
对象的原始断言,其 序列字段为
50
,它通过 Java 代码完成。在那里,审计 视图显示规则的连续递归,其中每个断言的 Fibonacci
对象会导致 "Recurse"
规则变为激活并再次触发。
图 89.7. Audit 视图中的规则"重复"
如果 Fibonacci 带有 序列字段的
对象被断言,Fib
onacci"Bootstrap"
规则会与 "Recurse"
规则一起匹配和激活。请注意,对字段
序列
的多个限制,使用 1
或 2
测试是否相等:
规则 "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
您还可以使用 IDE 中的 Agenda View 来调查决策引擎日程表的状态。"Bootstrap"
规则尚未触发,因为 "Recurse"
规则具有更高的 salience 值。
图 89.8. Agenda View 1 中的规则"Recurse"和"Bootstrap"
当断言了 序列
为 1
的 Fibonacci
对象时,会再次匹配 "Bootstrap"
规则,从而导致此规则有两个激活。"Recurse"
规则不匹配并激活,因为 not
条件元素在存在 序列
的 Fibonacci
对象时立即停止匹配规则。
图 89.9. Agenda View 2 中的规则"Recurse"和"Bootstrap"
"Bootstrap"
规则使用 序列
和 1
2
的值来设置对象。现在,有两个 Fibonacci
对象的值不等于 -1
,"Calculate"
规则可以匹配。
此时,工作内存中有近 50 Fibonacci
对象。您需要依次选择适当的三角来计算其每个值。如果您在没有字段限制的规则中使用三个 Fibonacci 模式来限制可能的跨产品,则结果将是 50x49x48 个可能的组合,从而导致大约 125,000 个可能的规则触发,其中大多数不正确。
"Calculate"
规则使用字段限制来以正确顺序评估三个 Fibonacci 模式。这种技术称为与 跨产品匹配的跨产品。
第一个模式找到任何值为 != -1
的 Fibonacci
对象,并且绑定模式和字段。第二个 Fibonacci
对象执行相同的操作,但添加了额外的字段约束,以确保其序列大于绑定到 f1
的 Fibonacci
对象。当这个规则首次触发时,您知道只有序列 1
和 2
的值为 1
,并且两个限制可确保 f1
参考序列 1
和 f2
参考序列 2
。
最终模式找到一个值等于 -1
且序列大于 f2
的 Fibonacci
对象。
此时,可以从可用的跨产品正确选择三个 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
modify
语句更新绑定到 f3
的 Fibonacci
对象的值。这意味着,您现在有一个没有等于 -1
的新 Fibonacci
对象,它允许 "Calculate"
规则重新匹配并计算下一个 Fibonacci 号。
IDE 的 debug 视图或 Audit View 显示触发最后 "Bootstrap"
规则如何修改 Fibonacci
对象,启用 "Calculate"
规则以匹配,然后修改另一个 Fibonacci
对象,以便重新匹配 "Calculate"
规则。此过程将继续,直到为所有 Fibonacci
对象设置了值。
图 89.10. Audit 视图中的规则