第3章 デシジョンエンジンにおける推論と真理維持
デシジョンエンジンの基本的な機能は、データをビジネスルールに一致させ、ルールを実行するかどうか、そしてどのように実行するかを決定することです。関連データが適切なルールに確実に適用されるように、デシジョンエンジンは既存の知識に基づいて 推論 を作成し、推論された情報に基づいてアクションを実行します。
たとえば、以下の DRL ルールは、バスの乗車パスに関する方針など、大人の年齢要件を決定します。
年齢要件を定義するためのルール
rule "Infer Adult" when $p : Person(age >= 18) then insert(new IsAdult($p)) end
rule "Infer Adult"
when
$p : Person(age >= 18)
then
insert(new IsAdult($p))
end
このルールに基づいて、デシジョンエンジンはバス利用者が大人か子供かを推論し、指定されたアクション (then
の結果) を実行します。18 歳以上のすべての人には、ワーキングメモリーに IsAdult
のインスタンスが挿入されています。続いて、年齢とバスの乗車パスの推論されたこの関係は、以下のようなルールセグメントなどのルールで呼び出すことができます。
$p : Person() IsAdult(person == $p)
$p : Person()
IsAdult(person == $p)
多くの場合、ルールシステムの新しいデータは他のルール実行の結果であり、この新しいデータは他のルール実行に影響を与える可能性があります。デシジョンエンジンがルール実行の結果としてデータをアサートする場合、デシジョンエンジンは真理維持を使用してアサーションを正当化し、推論された情報を他のルールに適用する時に真理を強制します。真理維持は、不一致の特定と矛盾の処理にも役立ちます。たとえば、2 つのルールが実行され、矛盾したアクションが発生した場合、デシジョンエンジンは以前に計算された結論からの仮定に基づいてアクションを選択します。
デシジョンエンジンは、記述挿入または論理挿入のいずれかを使用してファクトを挿入します。
-
記述挿入:
insert()
で定義されます。記述挿入の後、通常はファクトが明示的に取り消されます。(挿入 という用語が一般的に使用される場合は 記述挿入 を指します。) -
論理挿入:
insertLogical()
で定義されます。論理挿入の後、挿入されたファクトは、ファクトを挿入したルールの条件が true でなくなると自動的に取り消されます。論理挿入をサポートする条件がない場合、ファクトは取り消されます。論理的に挿入されたファクトは、デシジョンエンジンによって 正当化される と見なされます。
たとえば、以下の DRL ルールのサンプルでは、ファクトの記述挿入を使用して、子供用または大人用のバスの乗車パスを発行するための年齢要件を決定します。
バスの乗車パスを発行するためのルール (記述挿入)
rule "Issue Child Bus Pass" when $p : Person(age < 18) then insert(new ChildBusPass($p)); end rule "Issue Adult Bus Pass" when $p : Person(age >= 18) then insert(new AdultBusPass($p)); end
rule "Issue Child Bus Pass"
when
$p : Person(age < 18)
then
insert(new ChildBusPass($p));
end
rule "Issue Adult Bus Pass"
when
$p : Person(age >= 18)
then
insert(new AdultBusPass($p));
end
バス利用者の年齢が上がると、子供用から大人用の乗車パスへと移行するため、デシジョンエンジンでこれらのルールを維持することは簡単ではありません。別の方法としては、ファクトの論理挿入を使用して、これらのルールをバス利用者の年齢のルールと乗車パスの種類のルールに分けることができます。ファクトを論理的に挿入することで、ファクトは when
節の真理に依存することになります。
以下の DRL ルールは、論理挿入を使用して子供と大人の年齢要件を決定します。
子供および大人の年齢要件 (論理挿入)
rule "Infer Child" when $p : Person(age < 18) then insertLogical(new IsChild($p)) end rule "Infer Adult" when $p : Person(age >= 18) then insertLogical(new IsAdult($p)) end
rule "Infer Child"
when
$p : Person(age < 18)
then
insertLogical(new IsChild($p))
end
rule "Infer Adult"
when
$p : Person(age >= 18)
then
insertLogical(new IsAdult($p))
end
論理挿入の場合、ファクトオブジェクトは、Java 標準に従って java.lang.Object
オブジェクトの equals
メソッドおよび hashCode
メソッドをオーバーライドする必要があります。2 つのオブジェクトが等しくなるのは、双方の equals
メソッドが互いに true
を返し、双方の hashCode
メソッドが同じ値を返す場合です。詳細については、お使いの Java バージョンの Java API ドキュメントを参照してください。
ルールの条件が false の場合、ファクトは自動的に取り消されます。2 つのルールは相互に排他的であるため、この例ではこの動作が役立ちます。この例では、バス利用者が 18 歳未満の場合、ルールは IsChild
ファクトを論理的に挿入します。利用者が 18 歳以上になると、IsChild
ファクトが自動的に取り消され、IsAdult
ファクトが挿入されます。
続いて、以下の DRL ルールが、子供用または大人用のバスの乗車パスを発行するかどうかを決定し、ChildBusPass
ファクトおよび AdultBusPass
ファクトを論理的に挿入します。このルールの設定が可能なのは、デシジョンエンジンの真理維持システムが、取り消しセットのカスケードに対する論理的挿入の連鎖をサポートしているためです。
バスの乗車パスを発行するためのルール (論理挿入)
rule "Issue Child Bus Pass" when $p : Person() IsChild(person == $p) then insertLogical(new ChildBusPass($p)); end rule "Issue Adult Bus Pass" when $p : Person() IsAdult(person =$p) then insertLogical(new AdultBusPass($p)); end
rule "Issue Child Bus Pass"
when
$p : Person()
IsChild(person == $p)
then
insertLogical(new ChildBusPass($p));
end
rule "Issue Adult Bus Pass"
when
$p : Person()
IsAdult(person =$p)
then
insertLogical(new AdultBusPass($p));
end
バス利用者が 18 歳になると、IsChild
ファクトとその利用者の ChildBusPass
ファクトが取り消されます。これらの条件のセットに、18 歳になると子供用の乗車パスを返却する必要があることを示す別のルールを関連付けることができます。デシジョンエンジンが ChildBusPass
オブジェクトを自動的に取り消すと、以下のルールが実行され、利用者にリクエストが送信されます。
バスの乗車パス利用者に新しいパスを通知するルール
rule "Return ChildBusPass Request" when $p : Person() not(ChildBusPass(person == $p)) then requestChildBusPass($p); end
rule "Return ChildBusPass Request"
when
$p : Person()
not(ChildBusPass(person == $p))
then
requestChildBusPass($p);
end
以下のフローチャートは、記述挿入と論理挿入のライフサイクルを示しています。
図3.1 記述挿入

図3.2 論理挿入

ルールの実行中にデシジョンエンジンが論理的にオブジェクトを挿入すると、デシジョンエンジンはルールを実行してオブジェクトを 正当化 します。論理挿入ごとに、等しいオブジェクトは 1 つしか存在できず、後続の等しい論理挿入はそれぞれ、その論理挿入の正当化カウンターを増やします。ルールの条件が true でなくなると、正当化は削除されます。正当化がすべてなくなると、論理オブジェクトは自動的に取り消されます。
3.1. デシジョンエンジンのファクト等価モード
デシジョンエンジンは、挿入されたファクトをデシジョンエンジンが保存および比較する方法を決める以下のファクト等価モードをサポートします。
-
identity
: (デフォルト) デシジョンエンジンはIdentityHashMap
を使用して、すべての挿入されたファクトを保存します。新しいファクトの挿入ごとに、デシジョンエンジンは、新しいFactHandle
オブジェクトを返します。ファクトが再度挿入されると、デシジョンエンジンはオリジナルのFactHandle
オブジェクトを返し、同じファクトに対して繰り返される挿入を無視します。このモードでは、2 つのファクトが同じアイデンティティーを持つまったく同じオブジェクトである場合に限り、デシジョンエンジンにとってこの 2 つのファクトは同じものになります。 -
equality
: デシジョンエンジンはHashMap
を使用して、すべての挿入されたファクトを保存します。デシジョンエンジンは、挿入されたファクトのequals()
メソッドに従って、挿入されたファクトが既存のファクトと等しくない場合に限り、新しいFactHandle
オブジェクトを返します。このモードでは、アイデンティティーに関係なく、2 つのファクトが同じ方法で設定される場合、デシジョンエンジンにとってこの 2 つのファクトは同じものになります。このモードは、オブジェクトを明示的なアイデンティティーではなく、機能の等価性に基づいて評価する必要がある場合に使用します。
ファクト等価モードの説明として、以下のファクトの例をご覧ください。
ファクトの例
Person p1 = new Person("John", 45); Person p2 = new Person("John", 45);
Person p1 = new Person("John", 45);
Person p2 = new Person("John", 45);
identity
モードの場合、ファクト p1
および p2
は Person
クラスの異なるインスタンスであり、別々のアイデンティティーを持つため、別のオブジェクトとして扱われます。equality
モードの場合は、ファクト p1
および p2
が同じ設定を持つため、同じオブジェクトとして扱われます。このような動作の違いは、ファクトハンドルとの対話方法に影響を及ぼします。
たとえば、ファクト p1
および p2
をデシジョンエンジンに挿入し、その後 p1
のファクトハンドルを取得する必要があると仮定します。identity
モードの場合は、p1
を指定して、正確なオブジェクトに対してファクトハンドルを返す必要があります。一方、equality
モードの場合は、p1
、p2
、または new Person("John", 45)
を指定して、ファクトハンドルを返すことができます。
ファクトを挿入して identity
モードでファクトハンドルを返すコード例
ksession.insert(p1); ksession.getFactHandle(p1);
ksession.insert(p1);
ksession.getFactHandle(p1);
ファクトを挿入して equality
モードでファクトハンドルを返すコード例
ksession.insert(p1); ksession.getFactHandle(p1); // Alternate option: ksession.getFactHandle(new Person("John", 45));
ksession.insert(p1);
ksession.getFactHandle(p1);
// Alternate option:
ksession.getFactHandle(new Person("John", 45));
ファクト等価モードを設定するには、以下のいずれかのオプションを使用します。
-
システムプロパティー
drools.equalityBehavior
をidentity
(デフォルト) またはequality
に設定 プログラムを用いて KIE ベースを作成中に等価モードを設定
KieServices ks = KieServices.get(); KieBaseConfiguration kieBaseConf = ks.newKieBaseConfiguration(); kieBaseConf.setOption(EqualityBehaviorOption.EQUALITY); KieBase kieBase = kieContainer.newKieBase(kieBaseConf);
KieServices ks = KieServices.get(); KieBaseConfiguration kieBaseConf = ks.newKieBaseConfiguration(); kieBaseConf.setOption(EqualityBehaviorOption.EQUALITY); KieBase kieBase = kieContainer.newKieBase(kieBaseConf);
Copy to Clipboard Copied! 特定の Red Hat Decision Manager プロジェクトの KIE モジュール記述子ファイル (
kmodule.xml
) で等価モードを設定<kmodule> ... <kbase name="KBase2" default="false" equalsBehavior="equality" packages="org.domain.pkg2, org.domain.pkg3" includes="KBase1"> ... </kbase> ... </kmodule>
<kmodule> ... <kbase name="KBase2" default="false" equalsBehavior="equality" packages="org.domain.pkg2, org.domain.pkg3" includes="KBase1"> ... </kbase> ... </kmodule>
Copy to Clipboard Copied!