89.8. 数独例のデシジョン (複雑なパターン一致、コールバック、および GUI 統合)
数独例のデシジョンセットは、人気の数字パズルゲーム数独をもとにしています。このセットでは、Red Hat Decision Manager のルールを使用してさまざまな制約をもとに、多数の考えられる回答スペースの中で回答を導き出す方法を例示します。またこの例では、Red Hat Decision Manager ルールとグラフィカルユーザーインターフェイス (GUI) の統合方法が分かります。今回は Swing ベースのデスクトップアプリケーションを使用します。また、この例では、コールバックを使用して実行中のデシジョンエンジンと通信し、ランタイム時に加えられたワーキングメモリー内の変更をもとに GUI を更新する方法を例示しています。
以下は数独の例の概要です。
-
名前:
sudoku -
Main クラス: (
src/main/java内の)org.drools.examples.sudoku.SudokuExample -
モジュール:
drools-examples - タイプ: Java アプリケーション
-
ルールファイル: (
src/main/resources内の)org.drools.examples.sudoku.*.drl - 目的: 複雑なパターン一致、問題解決、コールバック、および GUI 統合を例示します。
数独は、ロジックベースの数字配置パズルです。目的は、各列、各行、および各 3x3 ゾーンに 1 から 9 の数字が一度だけ含まれるように 9x9 のグリッドを埋めることです。パズルセッターでは、グリッド内の一部だけ記入されており、上記の制約ですべての空白を埋めるのがパズルの回答者のタスクです。
問題解決の一般的なストラテジーとして、新しい番号の挿入時に、特定の 3x3 ゾーン、行、および列で同じ番号がないことを確認します。この数独例のデシジョンセットでは、Red Hat Decision Manager ルールを使用して、さまざまな難易度の数独パズルを解き、無効なエントリーが含まれ、不備のあるパズルの解決を試みます。
数独例の実行および対話
他の Red Hat Decision Manager のデシジョン例と同じように、お使いの IDE で org.drools.examples.sudoku.SudokuExample クラスを Java アプリケーションとして実行し、数独の例を実行します。
数独の例を実行すると、GUI ウィンドウ Drools Sudoku Example が表示されます。このウィンドウには空のグリッドが含まれていますが、プログラムには内部に保存されたさまざまなグリッドが含まれ、読み込んで解決できます。
File
図89.19 起動後の数独例の GUI
Simple サンプルを読み込むと、パズルの最初の状態に合わせて、グリッドが埋められます。
図89.20 Simple サンプルを読み込んだ後の数独例の GUI
以下のオプションから選択します。
Solve をクリックして、数独の例に定義されているルールを実行し、残りの値を埋めていき、このボタンを再度無効にします。
図89.21 Simple サンプルの解決
Step をクリックして、ルールセットに含まれる次の数字を表示します。IDE のコンソールウィンドウでは、解決手順を実行するルールに関する情報が詳細に表示されます。
IDE コンソールでの手順実行の出力
Copy to Clipboard Copied! Toggle word wrap Toggle overflow Dump をクリックしてグリッドの状態を表示します。セルには、解決済みの値か、残りの候補値が表示されます。
IDE コンソールでのダンプ実行の出力
Copy to Clipboard Copied! Toggle word wrap Toggle overflow
数独の例には、不備のあるサンプルファイルが意図的に含められています。このファイルは、例で定義したルールを使用して解決できます。
File 5 の値を 2 回表示できないにもかかわらず表示されるなど、問題が含まれた状態で表示されます。
図89.22 不備のある数独例の最初の状態
Solve をクリックしてこの無効なグリッドに解決ルールを適用します。数独の例に含まれる関連の解決ルールにより、サンプルの問題が検出され、できる限りパズルを解決します。このプロセスでは、すべてを完了させず、空白のセルをいくつか残します。
解決ルールのアクティビティーが IDE コンソールウィンドウに表示されます。
不備のあるサンプルでの問題検出
cell [0,8]: 5 has a duplicate in row 0 cell [0,0]: 5 has a duplicate in row 0 cell [6,0]: 8 has a duplicate in col 0 cell [4,0]: 8 has a duplicate in col 0 Validation complete.
cell [0,8]: 5 has a duplicate in row 0
cell [0,0]: 5 has a duplicate in row 0
cell [6,0]: 8 has a duplicate in col 0
cell [4,0]: 8 has a duplicate in col 0
Validation complete.
図89.23 不備のあるサンプルの解決試行
Hard のラベルの付いた数独サンプルファイルはより複雑で、解決ルールを使用しても解決できない可能性があります。解決をしようとして失敗した場合は、IDE コンソールウィンドウに表示されます。
解決不可の Hard サンプル
Validation complete. ... Sorry - can't solve this grid.
Validation complete.
...
Sorry - can't solve this grid.
不備のあるサンプルを解決するためのルールでは、セルの候補となりえる値をもとにした標準の解決手法を実装します。たとえば、セットに値が 1 つ含まれる場合は、これが値になります。セルが 9 個あるグループの 1 つに値が 1 度挿入された場合に、ルールを使用して、特定のセルに対する値を持ち、タイプが Setting のファクトを挿入します。このファクトにより、そのセルが含まれるグループにある他のすべてのセルからこの値が削除され、この値が取り消されます。
この例の他のルールで、セルに入力可能な値を減らしていきます。"naked pair"、"hidden pair in row"、"hidden pair in column"、および "hidden pair in square" のルールでは、候補の絞り込みはできますが、回答を得ることはできません。"X-wings in rows"、"`X-wings in columns"`、"intersection removal row"、および "intersection removal column" のルールは、より高度な絞り込みを実行します。
数独例のクラス
org.drools.examples.sudoku.swing パッケージには、以下のように、数独パズルのフレームワークを実装する主なクラスセットが含まれます。
-
SudokuGridModelは、9x9 グリッドのCellオブジェクトとして数独パズルを格納するために実装可能なインターフェイスを定義しています。 -
SudokuGridViewクラスは Swing コンポーネントで、SudokuGridModelクラス実装の視覚化が可能です。 -
SudokuGridEventクラスおよびSudokuGridListenerクラスは、モデルとビューの間のステータスの変化をやり取りするために使用します。セルの値が解決または変更すると、イベントが実行します。 -
SudokuGridSamplesクラスは、デモ目的に一部入力されている数独パズルを複数提供します。
このパッケージには、Red Hat Decision Manager ライブラリーの依存関係は含まれません。
org.drools.examples.sudoku パッケージには、以下のように、基本的な Cell オブジェクトと各種アグリゲーションを実装する主なクラスセットが含まれます。
-
CellRow、CellCol、およびCellSqrのサブタイプを含むCellFileクラス。これはすべて、CellGroupクラスのサブタイプになります。 CellとCellGroupはSetOfNineのサブクラスで、Set<Integer>型のfreeプロパティーを提供します。Cellクラスは、個別の候補セットを表します。CellGroupは、セルの全候補セットの統合 (割り当ての必要がある数値セット) です。数独の例には、81 個の
Cellと 27 個のCellGroupオブジェクト、CellプロパティーのcellRow、cellCol、およびcellSqrが提供するリンク、CellGroupプロパティーcells(Cellオブジェクトリスト) が提供するリストが含まれます。これらのコンポーネントを使用して、セルに値を割り当てたり、候補セットから値を取り除いたりできるように、特定の状態を検出するルールを記述できます。-
Settingクラスを使用して、値の割り当てに伴うオペレーションをトリガーします。Settingファクトは、整合性の取れない中間の状態に対して反応しないように、新しい状況を検出する全ルールに配置して使用します。 -
Steppingクラスは、優先順位が低いルールに使用して、"Step"が予期なく中断された場合に緊急停止を行います。この動作は、プログラムでパズルを解決できないということです。 -
Main クラス
org.drools.examples.sudoku.SudokuExampleは、全コンポーネントを統合する Java アプリケーションを実装します。
数独の検証ルール (validate.drl)
数独の例の validate.drl ファイルには、セルグループで数が重複している状況を検出する検証ルールが含まれます。このグループは、"validate" アジェンダグループに統合され、ユーザーがパズルを読み込むと、明示的にルールをアクティベートできます。
"duplicate in cell …" の 3 つのルールの when 条件はすべて以下の方法で機能します。
- このルールの最初の条件で、割り当てられた値でセルを特定します。
- このルールの 2 番目の条件では、3 つのセルグループのどれかを所属先にプルします。
- 最終条件は、ルールに従い、最初のセル、同じ行、列、または四角に入る値と同じセル (上記のセル以外) を検索します。
ルール "duplicate in cell …"
ルール "terminate group" は最後に実行されます。このルールは、メッセージを出力して、シーケンスを停止します。
ルール "terminate group"
数独の解決ルール (sudoku.drl)
数独の例の sudoku.drl ファイルには、3 種類のルールタイプが含まれます。1 つ目のグループは、セルへの数値の割り当てを処理して、2 つ目は実行可能な割り当てを検出して、3 つ目は候補セットからの値を削除します。
"set a value"、"eliminate a value from Cell"、および "retract setting" のルールは、Setting オブジェクトの有無により左右されます。最初のルールは、セルへの割り当てと、3 つのセルグループの free セットから値を削除する操作を処理します。また、ゼロの場合は、このグループでカウンターが 1 つ減り、fireUntilHalt() を呼び出した Java アプリケーションに制御を戻します。
"eliminate a value from Cell" ルールの目的は、新たに割り当てられたセルに関連する全セルの候補リストを絞り込むことです。最後に、すべての除外が完了したら、"retract setting" ルールにより、トリガーされている Setting ファクトを取り消します。
ルール "set a value"、"eliminate a value from a Cell"、および "retract setting"
解決ルールを 2 つ使用して、セルに数字を割り当てることができる状況を検出します。"single" のルールは、Cell に、数字が 1 つだけの候補セットが含まれる場合に実行します。"hidden single" ルールは、候補が 1 つだけのセルが存在しない場合に実行しますが、セルに候補が含まれる場合は、セルが所属する 3 つのグループの 1 つに含まれるその他のすべてのセルに、この候補が存在しないということです。いずれのルールも Setting ファクトを作成して、挿入します。
ルール "single" および "hidden single"
最大グループからのルール (個別または 2 ~ 3 のグループ単位) は、数独パズルを手作業で解決するのに使用する、さまざまな解決手法を実装します。
"naked pair" ルールは、グループの 2 つのセルで、全く同じ候補セットでサイズ 2 のものを検出します。これらの 2 つの値は、対象グループにあるその他のすべての候補セットから削除できます。
ルール "naked pair"
3 つのルールの "hidden pair in …" 関数は、ルール "naked pair" と同じように機能します。ルールはグループの 2 つのセルで 2 つの数字を検出します。どの値もこのグループの他のセルには入りません。つまり、他の候補はすべて、隠れたペアを持つ 2 つのセルから削除します。
ルール "hidden pair in …"
2 つのルールは行と列で "X-wings" を処理します。2 つの異なる行 (または列) で、ある値を入力できるセルが 2 つしかなく、これらの候補が同じ列 (または行) に入る場合に、この列 (または行) のこの値に対する他の候補は除外できます。これらのルールの 1 つに含まれるパターンシーケンスに従うと、same、only などの用語で都合よく表現されている条件は、適切な制約が付けられたパターンになるか、not のプリフィックスが付きます。
ルール "X-wings in …"
この 2 つのルール "intersection removal …" は、1 つの行または 1 つの列のいずれかで、1 つの四角の中で一部の数字が制限されたことに基づきます。これは、この番号が行または列の 2 つまたは 3 つのセルのいずれかにある必要があり、グループの他のすべてのセルの候補セットから削除できることを意味します。このパターンは、発生制限を確立して、同じセルファイルの中、かつ四角の外のセルそれぞれに対して実行されます。
ルール "intersection removal …"
これらのルールは、すべてではありませんが、多くの数独パズルでは十分です。非常に難度の高いグリッドを解決するには、ルールセットにさらに複雑なルールが必要です。(最終的には、パズルは試行錯誤でしか解決できません)。