RetePlus 算法

RetePlus 是一种基于Rete算法的规则执行模式。 它依赖于工作内存和日程安排,并支持负面模式、对象通知和逻辑对象。

RetePlus 该 Decision Server 扩展基于Rete算法。 在 RetePlus 模式下,规则执行基于工作内存和议程的环境进行。

工作记忆与任务清单

在 RetePlus 执行模式下,规则引擎通过工作内存日程表运作,当条件满足时添加规则实例以供执行。

工作内存

在 RetePlus 执行模式下,规则引擎与工作内存 Decision Server 配对使用。 工作内存包含关联 Engine 对象中的所有对象。 您可以通过在规则的操作部分添加语句或使用应用程序编程接口(API)来修改工作内存。 因此,规则引擎能够识别工作内存中的对象及其关联的任何对象。 规则引擎只能使用从工作内存中可访问的对象。

活动安排

议程是存储所有模式均匹配 Decision Server 的规则的位置。 任何进入议程的规则都称为实例化规则,它成为规则实例 ,详见规则实例

议程存储了可被执行的规则实例。 如果议程为空,执行将不产生任何效果。 列入议程的规则实例被视为有效。 通常,在议程中,多条规则是可选的。 因此,规则引擎必须具备某种机制来决定议程中应执行哪条特定规则。

在议程中,规则实例根据三个标准排序,这些标准决定了应优先执行哪条规则。 通过实现更复杂的功能,提供了额外的执行控制,详见对象通知

折射

已执行的规则实例若未发生新事实,则无法重新插入议程。具体而言,当规则匹配的对象均未被修改,或规则未匹配到新对象时,该实例将无法重新插入议程。

折射原则强制规定:对于给定的元组,仅创建一个规则实例。 由于引擎周期的数据单元是工作内存,引擎能够轻松记录所有可能的元组,并验证每个元组仅对应一条规则实例。

例如,考虑以下规则集:

class Person {
  Person(int age, boolean sick);
  boolean sick;
  int age;
}

rule incrementAge {
when {
  p: Person(!sick; age < 50);
} then {
  p.age += 1;
  update p;
}

rule cure {
when {
  p: Person(sick);
} then {
  p.sick = false;
  update p;
}

若对象 Person(18,true) 被插入工作记忆,折射原理将产生以下执行轨迹:

  1. cure
  2. incrementAge

您可以在 incrementAge 规则中添加可重复属性:

rule incrementAge {
 property com.ibm.rules.engine.repeatable=true;
when {
  p: Person(!sick; age < 50);
} then {
  p.age += 1;
}

若对象 Person(18,true) 被插入工作内存,其可重复特性将产生以下执行轨迹:

  1. cure
  2. incrementAge
  3. incrementAge
  4. incrementAge
  5. ...
  6. incrementAge

    直到该条件 age < 50 为假。

可重复规则
要打破折射原理,你可以使用布尔规则属性 com.ibm.rules.engine.repeatable。 在决策引擎中,必须使用此属性来标记您希望可重复执行的规则集。
  • 当某条规则不可重复时,折射原则将阻止该规则实例再次被提交至议程。
  • 当规则具备可重复性时,若其条件对象发生变更,该规则可作为规则实例重新插入议程。
近因

若两个规则实例具有相同优先级,则匹配最近对象(最近插入、修改或撤销的对象)的规则优先执行。

优先级和最近性用于在多个规则实例同时成为执行候选时解决冲突。 若在使用所有指定的冲突解决方法后,仍有若干规则实例作为候选项存在,则引擎将启用内部元规则;这确保在相同条件下,始终遵循相同的规则执行序列。

规则执行顺序示例

以下技术规则示例展示了规则执行的顺序:


rule init {
   when {
      angel();
   }
   then {
      insert clown();
      insert dascyllus();
   }
};
rule last {
   priority = -100;
   when {
      dascyllus();
   }
   then {
      System.out.println("last");
   }
};
rule first {
   priority = 100;
   when {
      angel();
      clown();
      dascyllus();
   }
   then {
      System.out.println("first");
   }
};
rule second {
   priority = 0;
   when {
      angel();
      dascyllus();
      clown();
   }
   then {
      System.out.println("second");
   }
};
rule third {
   priority = 0;
   when {
      angel();
      clown();
      dascyllus();
   }
   then {
      System.out.println("third");
   }
};

假设该对象 angel 已通过API从应用程序插入,因此已被插入工作内存,且我们已运行所有可执行的规则。

规则运行的顺序如下:

  1. init 规则:由于该对象是从 angel 应用程序插入的,因此该 init 规则是唯一可执行的规则。 它将对象 clown 和对象 依次 dascyllus 插入工作内存。 因此,最近的 dascyllus对象是。

  2. first 规则:此规则在 second 规则之前执行。 这两条规则匹配到的最新对象是相同的。 然而,第一个对象的优先级高于第二个对象,这决定了它们的执行顺序。

  3. second 规则:此规则在 third 规则之前执行。 第二条规则和第三条规则具有相同的优先级,但对象 dascyllus 比对象更新 clown

  4. third 规则:此规则在 last 规则之前执行。 尽管对象比更晚 dascyllus 出现 clown,但规则 third 的优先级高于规则 last

  5. last 规则。

规则实例

当工作记忆中的对象满足某条规则的条件部分时, 该规则实例会被添加到议程中。

让我们考虑以下技术规则:


rule rule1 {
   when {
      Fish(color == green; type == shark);
      Fish(type == trigger);
   }
   then {...}
};

以下规则实例将被列入议程:

规则 规则 规则 规则
rule1(A,C®) rule1(A,D) rule1(B,C) rule1(B,D)

在此示例中,您可以看到规则实例是一个动态概念:规则实例由工作内存中任何符合规则所指定模式的对象组合生成。 相比之下,规则是一个静态的概念。

消极模式

标准规则条件可被描述为存在性的,其含义在于它们可能与一个或多个实际存在的对象相匹配。 在执行 RetePlus 模式中,存在一个互补的概念,称为负面模式。 为表达工作记忆中特定对象的不存在,我们需在该对象的条件前放置关键词 not ,如下所示:


not Fish(type==eel);

这种否定模式会导致匹配成功,因为没有对象匹配对应的肯定模式:


Fish(type==eel);

相反,这种负面模式:


not Fish(type==angel);

无法成功匹配的简单原因在于存在一个对象与对应的正向模式相匹配:


Fish(type==angel);

对象通知

在 RetePlus 执行模式下,您可通过语句控制各项操作:

对象插入

insert 语句允许您创建一个新对象并将其插入工作内存。 该关键字后跟要创建的对象的类名及其属性的值。

以下 Course 是一个示例,其中创建了一个新对象,其 department 和 属性分别 number 取值为 History324


insert Course(History,324);

操作 insert 的处理方式有两种可能:

  • 该对象已存在于工作记忆中。 在此情况下,插入操作等同于更新操作。

  • 该对象不在工作记忆中。 在此情况下,对象被插入工作内存,并调用对应类及其父类(如有)的插入守护进程,同时更新日程表。

物体缩回

retract 语句允许您从工作内存中移除与规则变量绑定的对象。

在下面的示例中,该 retract 原始操作符移除了绑定到 ?c 变量的对象:


rule RemoveCourse {
   when {
      ?c: Course(department == History; number == 254);
   }
   then {
      retract ?c;
   }
};

若存在对应类的守护 retract 进程,则调用该守护进程,并相应地更新日程安排。 从工作记忆中撤回某个对象可能会导致逻辑对象失去其一个或多个存在依据。

对象更新

当Java™修改对象时,这些修改不会被 Decision Server.看到。 这意味着由 维护 Decision Server 的数据将与修改后对象的新内容不一致。

为避免不一致的情况,应对此类对象调用该 update 语句。 此语句允许根据修改后对象 Decision Server 的新内容更新其内部结构。

在以下规则中,第一个动作修改了数字属性。 随后调用该 update 原始类型,以 Decision Server 通知对象已被修改。


rule NumberingUpdate {
   when {
      ?c: Course(department == "history"; number > 300);
   }
   then {
      ?c.updateNumbering(); // This call modifies ?c 
      update ?c;
   }
};
重要说明:

若未使用 modify,则必须使用 基本操作 update 来通知 Decision Server 对象已被修改。 忘记通知 Decision Server 修改会导致状态不一致。

网络运行

该 RetePlus 网络能够最大限度地减少规则和条件的数量:

RetePlus 网络运行

网络 RetePlus 通过索引规则,在每次工作内存发生变化时,最大限度地减少需要评估的规则和条件数量。 该网络通过在规则间共享测试并增量传播变更,最大限度地减少了评估次数。 当所有测试完成后,网络将指定一条规则。

在大多数情况下,执行规则会修改工作内存。 工作记忆中由这些规则引用的对象可以被插入、移除和修改。 网络处理规则执行所推导出的变更,并生成待执行的新规则集。

当工作记忆发生变化时,根据变化的性质,可能出现两种情况:

  • 若工作记忆中存在对象插入(正向),则可执行该规则。

  • 若工作记忆中存在对象移除(负面),则该规则必须从议程中移除。 议程是维护当前待执行规则集的位置。

该过程将循环进行,直至议程中不再存在规则实例。

注:

对于简单条件,当工作内存中不存在任何可匹配该条件的对象时,该 not 条件返回真值。

网络 RetePlus 示例

为说明我们对 RetePlus 网络的描述,我们将采用一条 filter 简单的规则,该规则使用规则语言编写,涉及名为 AB和 的 C类:


rule filter {
   when {
      A (a1==3; ?x:a2);
      B (b1==2; ?y:b2; b3==?x);
      C (c1==?y);
   }
   then {
      System.out.println("filter");
   }
}

类属性如下:

  • 该类 A 有两个属性,分别命名为 a1a2

  • B类具有三个属性,分别命名为 b1、和 b3b2

  • 该类 C 拥有一个名为 的单一 c1属性。

假设工作内存包含以下对象:


A( a1=3 a2=10 )
B( b1=2 b2=4 b3=10 )
B( b1=2 b2=7 b3=10 )
C( c1=4 )

RetePlus 网络结构

网络 RetePlus 可表示为由三个区域组成的图:

歧视树

别树是一种执行测试的模式匹配过程。 这些测试在网络顶部以菱形表示。 这些测试涉及对象的类别及其属性的值。 输入到该树中的内容由表示工作内存中当前每个对象的标记组成。

当模式仅涉及一个对象及其属性时,则称为鉴别测试。 当它们组合在一起时,称为连接;这些连接出现在图的下部。

Alpha节点

对于每个通过判别树测试的代币,将在网络的下一层形成一个alpha节点。 每个节点由一个或多个令牌组成,以圆角矩形表示(图中包含三个字母节点)。 一个alpha节点包含两个B类令牌。 另外两个节点各自仅包含一个类标记——分别是A类标记和C类标记。

测试与元组

网络的第三区域匹配若干类对象的令牌。 生成的节点称为元组 ,由多个标记组成。 属性 a2 与 之间的 b3 等价性测试会生成由两对令牌组成的节点,而属性 b2c1 之间的测试则会筛选出由三个令牌组成的三元组。 在网络 RetePlus 中,我们通常将此类元组称为连接节点。

对象添加

为进一步说明这种网络 RetePlus 概念,假设在工作记忆中插入一个额外对象。 添加的对象属于C c1 类,其attribute属性的值为7。


C( c1=7 )

在当前阶段,当所有节点的测试都执行完毕时,仅第三个测试 C (c1==?y); class of object = C)被满足。 随着令牌在网络中向下传递,子节点的测试持续进行。

在此,歧视树中不存在子节点。 因此,该对象被直接存储在alpha节点中。

当令牌到达第二个连接节点 B (b1==2; ?y:b2; b3==?x)时,需对存储在连接节点内存旁的成对B对象与刚抵达该节点的令牌所含C对象进行逐对测试。 对于第二组的B对象,该测试条件成立。 因此我们可以继续操作,将第二个词对与标记中的对象组合成三元组。

通过形成这个三元组,我们实际上已经遍历了整个网络,因此可以执行该 filter 规则的新实例。

物体移除

假设我们现在移除了刚刚添加到工作记忆中的对象。

令牌在判别树中的行进过程与对象添加情况相同,但负令牌抵达α节点时,会导致该令牌所包含的对象被移除。

当令牌到达第二个连接节点时,所有包含令牌中对象的三元组都会被移除,令牌继续在网络中前进。

如同对象添加示例中那样,规则节点被触发。 满足令牌中对象所对应条件的规则 filter 实例将从议程中移除。