BRMSで実験してみました-宣言的プログラミングのすすめ (2)-

Droolsを使って、ルールベース(BRMS)の動きを見るためにちょっと実験してみました。Droolsで、Projectをつくるとサンプルのプログラムをつくってくれますが、それをすこしばかり修正しての実験です。
(ルールベースの動きの基本は、プロダクションシステムとはとか、当ブログのルールベースプログラミングのカテゴリなどを参照ください)

まずは、ルール処理の対象となるファクトを準備します。

SampleFact.java

package com.sample;

public class SampleFact {
    private int num;
    private String name;

    public SampleFact() {
        super();
    }

    public SampleFact(int num, String name) {
        super();
        this.num = num;
        this.name = name;
    }

    /**
     * @return the num
     */
    public int getNum() {
        return num;
    }

    /**
     * @param num the num to set
     */
    public void setNum(int num) {
        this.num = num;
    }

    /**
     * @return the name
     */
    public String getName() {
        return name;
    }

    /**
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "SampleFact [num=" + num 
                   + ", name=" + name + "]";
    }

}

そして、mainプログラム

DroolsTest.java

package com.sample;

import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;

/**
 * This is a sample class to launch a rule.
 */
public class DroolsTest {
  public static final void main(String[] args) {
    try {
      // load up the knowledge base
      KieServices ks
       = KieServices.Factory.get();
      KieContainer kContainer
       = ks.getKieClasspathContainer();
      KieSession kSession
       = kContainer.newKieSession("ksession-rules");

      // go !
      SampleFact sf1 = new SampleFact(1, "A");
      SampleFact sf2 = new SampleFact(2, "B");
      SampleFact sf3 = new SampleFact(3, "C");
      SampleFact sf4 = new SampleFact(4, "D");
      SampleFact sf5 = new SampleFact(5, "E");
      kSession.insert(sf1);
      kSession.insert(sf2);
      kSession.insert(sf3);
      kSession.insert(sf4);
      kSession.insert(sf5);
      kSession.fireAllRules();
    } catch (Throwable t) {
      t.printStackTrace();
    }
}

上のように5つのファクトをワーキングメモリに追加して、以下のルール

Sample.drl

package com.sample

rule "サンプルルール1"
when
    SampleFact($num: num, $name: name)
then
    System.out.println("num=" + $num
         + ", name=" + $name);
end

を実行しました。
コンソールには、どのように表示されるでしょうか。

まあ、これはワーキングメモリに5つのファクトがあるので、単純に
条件節(when部分)のSampleFactにマッチして、5回ルールのサイクルが回ります。

num=5, name=E
num=4, name=D
num=3, name=C
num=2, name=B
num=1, name=A

つまり条件部にマッチしたファクトが
SampleFact(1, “A”);
SampleFact(2, “B”);
SampleFact(3, “C”);
SampleFact(4, “D”);
SampleFact(5, “E”);
の5つだったということ。

では、上記のサンプルルール1のかわりに次のルールがあった場合は
どうなるでしょうか

Sample.drl(改)

package com.sample

rule "サンプルルール1a"
when
    SampleFact($num: num > 3, $name: name)
then
    System.out.println("num=" + $num
         + ", name=" + $name);
end

このときは条件節に num > 3 という条件が加わったので
num=5, name=E
num=4, name=D
の2つのみが表示されます。

すなわち条件部にマッチしたファクトが
SampleFact(4, “D”);
SampleFact(5, “E”);
の2つということ。

さらに次はどうでしょう。

Sample.drl(改々)

package com.sample

rule "サンプルルール2"
when
    SampleFact($num: num, $name: name)
    SampleFact($num1: num, $name1: name)
then
    System.out.println("num=" + $num
         + ", name=" + $name
         + ", num1=" + $num1
         + ", name1=" + $name1);
end

今度は、条件節のSampleFactのパターンが2つになりました。結果は、
num=1, name=A, num1=1, name1=A
num=1, name=A, num1=2, name1=B
num=1, name=A, num1=3, name1=C
・・・(中略)・・・
num=5, name=E, num1=4, name1=D
num=5, name=E, num1=5, name1=E

以上、25行表示されました。

これは、条件節の最初のパターン
SampleFact($num: num, $name: name)
に5つのファクトがマッチして、さらに2番目のパターンにも
SampleFact($num1: num, $name1: name)
5つのファクトがマッチして結局その組合せとして5×5=25(通り)の
組合せが表示されているということを表しています。つまり

条件部にマッチしたファクトの組を
[<最初のパターンにマッチしたファクト>,<2番目のパターンにマッチしたファクト>]
の形であらわすとすると、

[SampleFact(1, “A”), SampleFact(1, “A”)]
[SampleFact(1, “A”), SampleFact(2, “B”)]
[SampleFact(1, “A”), SampleFact(3, “C”)]
・・・(中略)・・・
[SampleFact(5, “E”), SampleFact(4, “D”)]
[SampleFact(5, “E”), SampleFact(5, “E”)]

の25個のファクトの組が条件部にマッチしたことになります。

では、こんなルールであったらどうでしょうか。

Sample.drl(もひとつ改)

package com.sample

rule "サンプルルール2a"
when
    SampleFact($num: num, $name: name)
    SampleFact($num1: num > $num, $name1: name)
then
    System.out.println("num=" + $num
         + ", name=" + $name
         + ", num1=" + $num1
         + ", name1=" + $name1);
end

(この項続く)

コメント

タイトルとURLをコピーしました