第2章 デシジョンエンジンにおける Phreak ルールアルゴリズム
Red Hat Process Automation Manager のデシジョンエンジンは、ルール評価に Phreak アルゴリズムを使用します。Phreak は、Rete アルゴリズムから発展したもので、これには強化された Rete アルゴリズムの ReteOO も含まれます。ReteOO は、オブジェクト指向システム向けに Red Hat Process Automation Manager の以前のバージョンに導入されました。全体として Phreak は、Rete および ReteOO よりスケーラブルで、大規模なシステムでより迅速に対応します。
Rete は Eager (即時ルール評価) でデータ指向と考えられていますが、Phreak は Lazy (遅延ルール評価) で目標指向と考えられています。Rete アルゴリズムは、すべてのルールに対して部分的な一致を見つけ出すために insert、update、および delete の各アクションを実行中に、多数のアクションを実行します。ルールの一致において Rete アルゴリズムは活発なため、最終的にルールを実行するまでに長い時間がかかります。これは大規模なシステムにおいて特に顕著です。Phreak の場合は、ルールの部分的な一致を意図的に遅延させ、大量のデータをより効率的に処理します。
Phreakアルゴリズムは、以前の Rete アルゴリズムに次の機能拡張セットを追加します。
- コンテキストメモリーの 3 つの層: ノード、セグメント、およびルールメモリータイプ
- ルールベース、セグメントベース、およびノードベースのリンク
- Lazy (遅延) ルール評価
- 一時停止と再開を使用したスタックベースの評価
- 孤立したルール評価
- セット指向の伝播
2.1. Phreak でのルール評価 リンクのコピーリンクがクリップボードにコピーされました!
デシジョンエンジンが開始すると、すべてのルールは、ルールのトリガーが可能なパターン一致データに リンクされていない と見なされます。この段階で、デシジョンエンジンの Phreak アルゴリズムはルールを評価しません。insert、update、および delete の各アクションはキューに入れられ、Phreak は、実行する可能性が最も高いルールに基づいてヒューリスティックを使用し、次に評価するルールを計算して選択します。すべての必要な入力値がルールに生成されると、ルールは関連するパターン一致データに リンクされている と見なされます。続いて Phreak は、このルールを表す目標を作成し、ルールの顕著性によって順序付けられた優先度キューにこの目標を置きます。目標が作成されたルールのみが評価され、その他の潜在的なルール評価は遅延されます。個別のルールは評価されますが、ノードの共有は引き続きセグメンテーション処理を通じて行われます。
タプル指向の Rete とは異なり、Phreak 伝播はコレクション指向です。評価されているルールの場合、デシジョンエンジンは最初のノードにアクセスし、キューに入れられたすべての insert、update、および delete の各アクションを処理します。結果は 1 つのセットに追加され、そのセットは子ノードに伝播されます。子ノードでは、キューに入れられたすべての insert、update、および delete の各アクションが処理され、その結果を同じセットに追加します。続いてそのセットは次の子ノードに伝播され、同じ処理が終了ノードに達するまで繰り返されます。このサイクルは、特定のルール構成にパフォーマンス上の利点を提供できるバッチ処理効果をもたらします。
ルールをリンクしたり、リンクを外したりすることは、ネットワークセグメンテーションに基づいて、レイヤー化されたビットマスクシステムを通じて行われます。ルールネットワークが構築されると、同じルールのセットで共有されるルールネットワークノードのセグメントが作成されます。ルールはセグメントのパスで構成されます。ルールが他のどのルールともノードを一切共有しない場合は、このルールは単一のセグメントになります。
セグメントの各ノードにビットマスクの補正値が割り当てられます。別のビットマスクは、以下の要件に従って、ルールのパスの各セグメントに割り当てられます:
-
ノードの入力が少なくとも 1 つ存在する場合、ノードビットは
オン状態に設定されます。 -
セグメントの各ノードのビットが
オン状態に設定されている場合、セグメントビットもオン状態に設定されています。 -
いずれかのノードビットが
オフ状態に設定されている場合、セグメントもオフ状態に設定されています。 -
ルールのパスの各セグメントが
オン状態に設定されている場合、ルールはリンクされていると見なされ、目標が作成されてルールを評価するためのスケジュールが組まれます。
変更されたノード、セグメント、およびルールを追跡する際に、同じビットマスクの手法が使用されます。この追跡機能により、リンクされたルールの評価目標が作成後に変更された場合、このルールの評価をスケジュールから外すことができます。その結果、ルールは部分的な一致を一切評価することができなくなりました。
Rete におけるメモリーの単一ユニットとは対照的に、Phreak には、ノード、セグメント、およびルールのメモリータイプから成る 3 つのレイヤーのコンテキストメモリーがあります。そのため、このルール評価の処理は Phreak で可能となります。このようなレイヤーがあることで、ルールを評価する際は、より深くコンテキストを解釈することが可能になります。
図2.1 Phreak の 3 つのレイヤーから成るメモリーシステム
以下の例では、Phreak の 3 つのレイヤーから成るメモリーシステムで、ルールがどのように組織化および評価されているかについて説明しています。
例 1: 3 つのパターンがある単一のルール (R1): A、B、および C。ルールは、ノード用にビット 1、2、および 4 を持つ単一のセグメントを形成します。単一のセグメントのビットの補正値は 1 です。
図2.2 例 1: 単一ルール
例 2: ルール R2 が追加され、パターン A を共有します。
図2.3 例 2: パターン共有の 2 つのルール
パターン A は独自のセグメントに置かれ、その結果、各ルールには 2 つのセグメントが作成されます。これら 2 つのセグメントは、各ルールのパスを作成します。1 つ目のセグメントは、両方のパスで共有されます。パターン A がリンクされると、セグメントはリンクされます。続いてこのセグメントは、共有される各パスでこれを繰り返します。この時ビット 1 は on に設定されます。パターン B および C がその後オンになると、パス R1 の 2 つ目のセグメントがリンクされ、これによりビット 2 が R1 に対してオンになります。ビット 1 およびビット 2 が R1 に対してオンになったことで、ルールがリンクされるようになり、目標が作成され、ルールを今後評価して実行するためのスケジュールが立てられます。
ルールが評価されると、セグメントによって一致の結果が共有できるようになります。各セグメントには、そのセグメントのすべての insert、update、および delete をキューに入れるステージングメモリーがあります。R1 が評価されるとルールはパターン A を処理し、これにより一連のタプルが作成されます。アルゴリズムがセグメンテーションの分割を検出し、セット内の各 insert、update、および delete にピアタプルを作成します。そして、これらを R2 のステージングメモリーに追加します。次にこれらのタプルは、既存のステージタプルとマージされ、最終的に R2 が評価されると実行されます。
例 3: ルール R3 とルール R4 が追加され、パターン A とパターン B を共有します。
図2.4 例 3: パターン共有の 3 つのルール
ルール R3 と ルール R4 にはセグメントが 3 つあり、R1 にはセグメントが 2 つあります。R1、R3、および R4 がパターン A とパターン B を共有し、R3 と R4 がパターン D を共有しています。
例 4: パターンの共有なしでサブネットワークがある単一ルール (R1)
図2.5 例 4: パターンの共有なしで、サブネットワークがある単一のルール
Not、Exists、または Accumulate ノードに 1 つ以上の要素がある場合、サブネットワークが形成されます。この例では、要素 B not( C ) がサブネットワークを形成します。要素 not( C ) は、サブネットワークを必要としない単一要素のため、Not ノード内にマージされます。サブネットワークは専用のセグメントを使用します。ルール R1 には、依然として 2 つのセグメントのパスがあり、サブネットワークは別の内部のパスを形成します。サブネットワークがリンクされると、これは外部のセグメントにもリンクされます。
例 5: ルール R2 と共有するサブネットワークのあるルール R1
図2.6 例 5: 2 つのルールのうち、1 つはサブネットワークとパターンを共有
ルールのサブネットワークノードは、サブネットワークのない別のルールと共有することができます。このように共有することで、サブネットワークのセグメントが 2 つのセグメントに分割されることになります。
制約のある Not ノードおよび Accumulate ノードは、セグメントのリンクを外すことは一切できず、ビットがオンになっていると常に考えられています。
Phreak 評価のアルゴリズムは、メソッド再帰ベースではなく、スタックベースです。StackEntry を使用して現在評価中のノードを表す場合は、いつでもルール評価を一時的に停止したり、再開したりすることができます。
ルール評価がサブネットワークに到達すると、StackEntry オブジェクトが、外部パスのセグメントおよびサブネットワークセグメント用に作成されます。最初にサブネットワークのセグメントが評価され、セットがサブネットワークパスの終わりに到達すると、そのセグメントがフィードする外部ノードのステージングリストにマージされます。次に、以前の StackEntry オブジェクトが再開し、サブネットワークの結果を処理できるようになります。この処理には、子ノードに伝播される前にすべての作業がバッチで完了するという付加的な利点があります。これは、Accumulate ノードにとって特に有利です。
同じスタックシステムは、効率的な後向き連鎖に使用されます。ルール評価がクエリーノードに到達すると、評価は一時的に停止し、クエリーがスタックに追加されます。続いてクエリーは、結果セットを生成するために評価されます。結果セットは、再開した StackEntry オブジェクトのメモリーロケーションに保存され、回収されて子ノードに伝播されます。クエリー自体が他のクエリーを呼び出した場合はこの処理は繰り返され、その一方で、現在のクエリーは一時的に停止し、現在のクエリーノード用に新しい評価が設定されます。
2.1.1. 前向き連鎖と後向き連鎖を使用したルール評価 リンクのコピーリンクがクリップボードにコピーされました!
Red Hat Process Automation Manager のデシジョンエンジンは、前向き連鎖と後向き連鎖の両方を使用してルールを評価する、ハイブリッドの理由付けシステムです。前向き連鎖のルールシステムは、デシジョンエンジンのワーキングメモリーにあるファクトで開始して、そのファクトへの変更に反応するデータ駆動型のシステムです。オブジェクトがワーキングメモリーに挿入されると、その変更の結果として True となったルールの条件は、アジェンダにより実行がスケジュールされます。
反対に、後向き連鎖のルールシステムは、通常再帰を使用して、デシジョンエンジンが満たそうとする結論から開始する目的駆動型のシステムです。システムが結論または目的に到達できない場合には、サブとなる目的、つまり、現在の目的の一部を完了する結論を検索します。システムは、最初の結論が満たされるか、すべてのサブとなる目的が満たされるまで続行されます。
以下の図は、デシジョンエンジンが、ロジックフローで後向き連鎖のセグメントと、前向き連鎖全体とを使用してルールを評価する方法を例示します。
図2.7 前向き連鎖と後向き連鎖を使用したルール評価のロジック
2.2. ルールベースの設定 リンクのコピーリンクがクリップボードにコピーされました!
Red Hat Process Automation Manager には、RuleBaseConfiguration.java オブジェクトが含まれます。これを使用して、デシジョンエンジンで例外ハンドラーの設定、マルチスレッドの実行、および順次モードを設定することができます。
ルールベースの設定オプションに関しては、Red Hat カスタマーポータル から Red Hat Process Automation Manager [VERSION] Source Distribution の ZIP ファイルをダウンロードし、~/rhpam-7.4.0-sources/src/drools-$VERSION/drools-core/src/main/java/org/drools/core/RuleBaseConfiguration.java に移動してください。
以下のルールベースの設定オプションは、デシジョンエンジンで利用可能です:
- drools.consequenceExceptionHandler
設定されると、このシステムプロパティーは、ルールの結果によって例外のスローを管理するクラスを定義します。このプロパティーを使用して、デシジョンエンジンのルール評価にカスタムの例外ハンドラーを指定できます。
デフォルト値:
org.drools.core.runtime.rule.impl.DefaultConsequenceExceptionHandler以下のオプションのいずれかを使用して、カスタムの例外ハンドラーを指定できます:
システムプロパティーで例外ハンドラーを指定:
drools.consequenceExceptionHandler=org.drools.core.runtime.rule.impl.MyCustomConsequenceExceptionHandlerプログラムを用いて KIE ベースを作成中に例外ハンドラーを指定:
KieServices ks = KieServices.Factory.get(); KieBaseConfiguration kieBaseConf = ks.newKieBaseConfiguration(); kieBaseConf.setOption(ConsequenceExceptionHandlerOption.get(MyCustomConsequenceExceptionHandler.class)); KieBase kieBase = kieContainer.newKieBase(kieBaseConf);
- drools.multithreadEvaluation
有効化されると、このシステムプロパティーは、Phreak のルールネットワークを個々のパーティションに分割することで、デシジョンエンジンが並列してルールを評価できるようにします。
デフォルト値:
false以下のオプションのいずれかを使用してマルチスレッド評価を有効化できます:
マルチスレッド評価のシステムプロパティーを有効化:
drools.multithreadEvaluation=trueプログラムを用いて KIE ベースを作成中にマルチスレッド評価を有効化:
KieServices ks = KieServices.Factory.get(); KieBaseConfiguration kieBaseConf = ks.newKieBaseConfiguration(); kieBaseConf.setOption(MultithreadEvaluationOption.YES); KieBase kieBase = kieContainer.newKieBase(kieBaseConf);
警告クエリー、顕著性、またはアジェンダグループを使用するルールは現在、並列のデシジョンエンジンではサポートされていません。これらのルールの要素が KIE ベースに存在する場合、コンパイラーは警告を発し、自動的にシングルスレッドの評価に切り替えます。しかし、ケースによっては、デシジョンエンジンはサポートされていないルールの要素を検出できず、ルールが間違って評価される可能性があります。たとえば、ルールが DRL ファイル内のルールの順序によって与えられた暗黙の顕著性に依存する場合、デシジョンエンジンは検出できない可能性があり、その結果、サポートされていない顕著性の属性により、間違った評価となります。
- drools.sequential
有効化されると、このシステムプロパティーは、デシジョンエンジンの順次モードを有効化します。順次モードでは、デシジョンエンジンは、ワーキングメモリーでの変更に関係なく、デシジョンエンジンアジェンダにリスト化された順番でルールを一度評価します。これは、デシジョンエンジンがルールの
insert、modify、またはupdateステートメントをすべて無視し、ルールを単一シーケンスで実行することを意味します。その結果、ルールの実行は順次モードの方が速くなりますが、重要な更新はルールに適用されない可能性があります。ステートレスな KIE セッションを使用し、アジェンダ内の後続のルールに対してルールの実行による影響を及ぼしたくない場合は、このプロパティーを使用できます。順次モードは、ステートレスな KIE セッションにのみ適用されます。デフォルト値:
false以下のオプションのいずれかを使用して、順次モードを有効化できます。
順次モードのシステムプロパティーの有効化:
drools.sequential=trueKIE ベースをプログラムを用いて作成中に順次モードを有効化:
KieServices ks = KieServices.Factory.get(); KieBaseConfiguration kieBaseConf = ks.newKieBaseConfiguration(); kieBaseConf.setOption(SequentialOption.YES); KieBase kieBase = kieContainer.newKieBase(kieBaseConf);
2.3. Phreak における順次モード リンクのコピーリンクがクリップボードにコピーされました!
順次モードは、デシジョンエンジンにおける高度なルールベースの設定で、Phreak がサポートしています。順次モードでは、デシジョンエンジンは、ワーキングメモリーでの変更に関係なく、デシジョンエンジンアジェンダにリスト化された順番でルールを一度評価します。順次モードでは、デシジョンエンジンがルールの insert、modify、または update ステートメントをすべて無視し、ルールを単一シーケンスで実行します。その結果、ルールの実行は順次モードの方が速くなりますが、重要な更新はルールに適用されない可能性があります。
ステートフルな KIE セッションは、以前呼び出された KIE セッションのデータを本質的に使用するため、順次モードが適用されるのはステートレスな KIE セッションのみとなります。ステートレスな KIE セッションを使用し、アジェンダ内の後続のルールに対してルールの実行による影響を及ぼしたい場合は、順次モードを有効化しないでください。デシジョンエンジンでは、デフォルトで順次モードは無効となっています。
以下のオプションのいずれかを使用して、順次モードを有効化します:
-
システムプロパティー
drools.sequentialをtrueに設定: KIE ベースをプログラムを用いて作成中に順次モードを有効化:
KieServices ks = KieServices.Factory.get(); KieBaseConfiguration kieBaseConf = ks.newKieBaseConfiguration(); kieBaseConf.setOption(SequentialOption.YES); KieBase kieBase = kieContainer.newKieBase(kieBaseConf);
以下のオプションのいずれかを使用して、順次モードが動的アジェンダを使用するように設定します:
-
システムプロパティー
drools.sequential.agendaをdynamicに設定: KIE ベースをプログラムを用いて作成中に順次アジェンダオプションを設定:
KieServices ks = KieServices.Factory.get(); KieBaseConfiguration kieBaseConf = ks.newKieBaseConfiguration(); kieBaseConf.setOption(SequentialAgendaOption.DYNAMIC); KieBase kieBase = kieContainer.newKieBase(kieBaseConf);
順次モードを有効化すると、以下の方法でデシジョンエンジンがルールを評価します:
- ルールは、ルールセットの顕著性および位置によって順序付けられます。
- 考えられるルールの一致ごとの要素が作成されました。要素の位置が実行の順番を示しています。
- right-input オブジェクトメモリーを除いて、ノードメモリーは無効化されました。
-
left-input アダプターノードの伝播は切断され、ノードを持つオブジェクトは
Commandオブジェクトで参照されます。Commandオブジェクトは、後で実行するためにワーキングメモリーのリストに追加されます。 -
すべてのオブジェクトがアサートされると、
Commandオブジェクトのリストが確認され、実行されます。 - リストの実行によって生じるすべての一致は、ルールのシーケンス番号に基づいて要素に追加されます。
- 一致を含む要素は、順次実行されます。ルール実行の最大数を設定している場合、デシジョンエンジンがアジェンダで実行するルールの数は、この最大数を超えることはありません。
順次モードでは、LeftInputAdapterNode ノードが Command オブジェクトを作成し、これをデシジョンエンジンのワーキングメモリーリストに追加します。この Command オブジェクトには、LeftInputAdapterNode ノードおよび伝播されたオブジェクトへの参照が含まれます。これらの参照は、right-input 伝播が left-input の結合を試みる必要が一切ないように、挿入時にあらゆる left-input 伝播を停止します。また、参照により、left-input メモリーが不要となります。
すべてのノードのメモリーはオフになっています。これには、left-input のタプルメモリーも含まれますが、right-input オブジェクトメモリーは除外されます。すべてのアサーションが終了し、すべてのオブジェクトの right-input メモリーが生成されると、デシジョンエンジンは LeftInputAdatperNode と Command オブジェクトのリストを繰り返します。オブジェクトはネットワークを伝播し、right-input オブジェクトに結合しようと試みますが、left input では保持されません。
タプルをスケジュールする優先度キューを持つアジェンダは、各ルールの要素に置き換えられます。RuleTerminalNode ノードのシーケンス番号は、一致をどこに置くかを要素に示します。すべての Command オブジェクトが終了すると、要素が確認され、既存の一致は実行されます。パフォーマンスを向上させるために、要素で最初と最後に生成されたセルは保持されます。
ネットワークが構築されると、各 RuleTerminalNode ノードは、顕著性の番号とネットワークに追加された順序をベースとするシーケンス番号を受け取ります。
right-input ノードメモリーは通常、オブジェクトをすばやく削除するためのハッシュマップです。オブジェクトの削除はサポートされていないので、オブジェクトの値がインデックス化されていない場合、Phreak はオブジェクトリストを使用します。大量のオブジェクトに対しては、インデックス化されたハッシュマップがパフォーマンスを向上させます。オブジェクトのインスタンスが少しだけの場合、Phreak はインデックスの代わりにオブジェクトリストを使用します。