【问题标题】:Are function symbols allowed in rule engines / Rete algorithm?规则引擎/Rete算法中是否允许使用函数符号?
【发布时间】:2021-01-03 12:51:42
【问题描述】:

AI: A Modern Approachfirst-order logic 中讨论推理时会提到Rete algorithm

然而,我发现的所有关于 Rete 算法的描述似乎都使用了没有函数符号的规则。 换句话说,规则看起来像

a(X) ∧ b(X, Y) → c(Y)

但不是

a(f(X)) ∧ b(X, Y) → c(f(Y))

(差异可能是根本性的,因为它是Prolog和Datalog之间的差异,其中只有一个是图灵完备的)

Rete 算法是否仅限于没有函数符号的规则? Drools 和 CLIPS 等现代规则引擎是否处理函数符号?

【问题讨论】:

  • 如果我正确理解了您的符号,那么是的,Drools 引擎确实允许在条件和结果内进行函数评估。不过,我不能代表其他引擎。
  • CLIPS 也一样
  • @RoddyoftheFrozenPeas "function symbols" 可能与其他地方的 "functions" 不同。这是一个试金石:当你陈述规则时,你能使用一个逻辑变量作为给那些 "functions" 的参数吗? (见Q中的第二个例子)
  • @GaryRiley 请看我对 Roddy 的回复。
  • @MaxB 我刚才提到了 Prolog,因为你提到了。如果没有简单的方法来解释函数 args 或您为什么要使用它们,那么有人很难回答您的问题。您的示例没有说明函数 args 的作用。

标签: artificial-intelligence rule-engine first-order-logic rete


【解决方案1】:

在 CLIPS 中,这就是您如何实施规则“对于每个人,只有一个父亲,如果一个人的父亲很富有,那么他/她也很富有”:

(defrule inherited-wealth
   (forall (person ?p)
           (father ?p ?f)
           (not (father ?p ~?f)))
   (person ?p)
   (father ?p ?f)
   (rich ?f)
   =>
   (assert (rich ?p)))

【讨论】:

  • 确实有两条规则。第一个(“对于每个人,只有一个父亲”)需要说明存在。我在您的代码中没有看到它。
  • 这就是 forall 语句的作用。
  • 为什么还需要forall?即使没有将它包裹在 forall 周围,这条规则也会以相同的方式执行,不是吗?
  • @Akaedintov 不,不会。 forall 是 (not (person ?p) (not (and (father ?p ?f) (not (father ?p ~?f)))) 的简写。必须保证每个人只有一个父亲.
【解决方案2】:

您的示例的问题是 Drools 对 Java 对象起作用。通过将Father 变量定义为实例而不是列表来处理条件“每个人都有一个父亲”。这将检查简化为空检查。

在 Drools 中,这是您实现这个简单英语用例的方式:

对于每个人来说,只有一个父亲,如果一个人的父亲有钱,那么他/她也有。

rule "A person has a rich father and is rich"
when
  not( Person(father == null ))

  $person: Person( $father: father,
                            isRich == true )
  Person( isRich == true ) from $father
then
  // Insert consequences here
end

这条规则的右手边(结果)将触发每个有钱的人和他的父亲有钱的人。开头的not 子句验证您工作记忆中的所有 Person 实例都有父亲的实例。每个进入工作记忆的人都会根据他们的个人优点进行评估,即使是多人进入。

基本上你会这样读:“所有人都有父亲。每个有钱人都有一个有钱的父亲。”如果您惰性化对象的设计并检查孩子,您可以断言“如果一个人很富有,那么所有孩子都是富有的”。

为了完整起见,此处建模的 Java 类如下所示:

public class Person {
  private Person father;
  private boolean isRich;
  public Person getFather() { return this.father; }
  public Person getIsRich() { return this.isRich; }
  // Setter methods omitted for brevity
}

当然,如果您尝试测试您满足此条件的情况,您当然可以反转它:

rule "A person exists without a father"
when
  exists( Person( father == null) )
then
  // Do something for situation if there's a father-less person
end

rule "A person is rich and their father is not rich"
when
  Person( $father: father != null, 
                   isRich == true )
  Person( isRich == false ) from $father
then
  // Do something for the poor father
end

...当然你可以将它们组合成一个规则,但它被认为是糟糕的规则设计。

Drools 是一种业务规则语言。它旨在用于条件和后果的组合——“如果这些条件为真,那么就这样做”。您的场景是一个简单的语句,而不是条件+结果,因此在这里建模有点困难,因为它缺乏结果。

它确实具有隐式应用于每个输入的好处,而不必指定循环或递归函数。调用上述(正面和负面情况)的方式是创建一个 Person 实例的集合并将它们一次全部传递到会话中。 Drools 将根据输入对每个 Person 实例进行评估。在评估规则是否有效时,将忽略对这些实例的任何更改而不调用特殊 Drools 的“刷新”函数之一(updateinsertmodifyretract)。例如,如果我传入一个没有父亲的 Person 实例,然后在我的一个规则中添加一个 Person,从“when”子句的角度来看,我的 Person 仍然是没有父亲的;除非我特别通知 Drools 使用上述函数,否则规则会根据完美输入进行评估。

【讨论】:

  • 规则应该声明“对于每个人,只有一个父亲......”。相反,您正在使用他的存在作为条件。在您的解释中,father 字段不应为空。 Drools 是不是不能无条件说明?
  • 在一个充满条件和后果的世界里,什么是陈述?我把它当作一种条件。由于一个陈述可以是真的也可以是假的,这似乎是一种合适的建模方式。如果陈述为真,则规则评估;如果该语句为假,则它不会(除非您反转条件。)
  • Drools 是一种业务规则语言。它不适用于对抽象逻辑结构进行建模。如果您有温度传感器并且声明“如果任何传感器连续 3 分钟报告 > 120 度,则打开火警”......我们可以用流口水来做到这一点。您的富人/穷人示例的一半翻译如果您将其视为条件-但您的规则关心您是否想知道它是否为真或是否为假,这将改变您的写作方式你的规则。
猜你喜欢
  • 1970-01-01
  • 2010-09-21
  • 1970-01-01
  • 1970-01-01
  • 2011-04-29
  • 1970-01-01
  • 2016-08-08
  • 1970-01-01
相关资源
最近更新 更多