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