# ABS3 Solver の使用方法 :::{container} prog-cpp ABS3 Solverを使用して式 f を解くには、以下の 2 つのステップで行います: - 式 `f` に対してABS3 Solver(`qbpp::ABS3Solver`)オブジェクトを作成します。 - `search()` メンバ関数を呼び出します。パラメータは初期化子リストとして渡します。得られた解が返されます。 ## ABS3 Solver を用いた LABS 問題の解法 次の Hi-QUBO プログラムは、ABS3 Solver を使用して、**低自己相関二進列(Low Autocorrelation Binary Sequence、LABS)問題** を解きます。 ```{literalinclude} ../../programFiles/cppPrograms/solver/abs3-solver-usage-program1.cpp :language: cpp :caption: abs3-solver-usage-program1.cpp ``` このプログラムでは、まず式 `f` に対してABS3 Solverオブジェクトsolverを作成します。 次に、`search()` メンバ関数にパラメータを初期化子リストとして渡して呼び出します。`time_limit` オプションは最大探索時間を秒単位で指定し、`enable_default_callback` は探索中に新たに見つかった最良解のエネルギーとTTSを出力する組み込みコールバック関数を有効にします。 この関数は指定された制限時間内に見つかった最良解を返し、`sol` に格納されます。 プログラムは、解のエネルギーと対応する2進シーケンスを表示します。このとき、「+」は 1、「-」は 0 を表します。 このプログラムは、次のような出力を生成します。 ```{include} ../../programFiles/markDown/solver/abs3-solver-usage-program.md :start-after: :end-before: ``` ## ABS3 Solver オブジェクト ABS3 Solver(`qbpp::ABS3Solver`)オブジェクトは、与えられた式に対して作成されます。ソルバーオブジェクトが構築されると、式は内部データ形式に変換され、GPU メモリにロードされます。オプションの第 2 引数 `gpu` によって GPU の使用方法を制御できます。 - `qbpp::ABS3Solver(expression)` : 利用可能なすべての GPU を自動で使用。GPU がない場合は CPU のみで実行。 - `qbpp::ABS3Solver(expression, 0)` : CPU のみで実行(GPU は使用しない)。 - `qbpp::ABS3Solver(expression, n)` : `n` 台の GPU を使用。 探索パラメータは `search()` に初期化子リストとして直接渡します。 上記の例では: - `"time_limit", 10.0`: 制限時間を10.0秒に設定します。 - `"enable_default_callback", 1`: 新たに得られた解のエネルギーを出力する組み込みコールバック関数を有効にします。 ## ABS3 パラメータ パラメータは `search()` メソッドに初期化子リストとして直接渡します。 上記のプログラムでは、`"time_limit", 10.0` で制限時間を10.0秒に設定し、`"enable_default_callback", 1` で新たに得られた解のエネルギーを出力する組み込みコールバック関数を有効にしています。 ### 基本オプション | キー | 値 | 説明 | |------|----|------| | `time_limit` | 時間制限(秒) | 時間制限に達したら探索を終了 | | `target_energy` | 目標エネルギー値 | 目標エネルギーに達したら探索を終了 | ### 詳細オプション | キー | 値 | 説明 | |------|----|------| | `enable_default_callback` | "1" | エネルギーと TTS を出力する組み込みコールバックを有効化 | | `cpu_enable` | "0" または "1" | GPU と併用して CPU ソルバーを有効/無効化(デフォルト: "1") | | `cpu_thread_count` | CPU スレッド数 | CPU ソルバーのスレッド数(デフォルト: 自動) | | `block_count` | CUDA ブロック数/GPU | ソルバーカーネルで起動される CUDA ブロック数 | | `thread_count` | CUDA ブロックごとのスレッド数 | CUDA ブロック内のスレッド数 | | `topk_sols` | 解の数 | 最も良いエネルギーの上位 K 解を返す | | `best_energy_sols` | 最大数(”0” = 無制限) | 見つかった最良エネルギーを持つすべての解を返します | ## 複数解の収集 ABS3 Solverは探索中に複数の解を収集できます。 2つのモードが利用可能です: ### Top-K解 (`topk_sols`) `topk_sols` パラメータはエネルギーの昇順にソートされたtop-K解を収集します。 ```{include} ../../programFiles/markDown/solver/abs3-solver-usage-program.md :start-after: :end-before: ``` ### 最良エネルギー解 (`best_energy_sols`) `best_energy_sols` パラメータは見つかった最良エネルギーを共有するすべての解を収集します。 より良いエネルギーが発見されると、プールがクリアされ、新しい最良エネルギーの解のみが保持されます。 ```{include} ../../programFiles/markDown/solver/abs3-solver-usage-program.md :start-after: :end-before: ``` または、`best_energy_sols` を最大数付きで設定することもできます: ```{include} ../../programFiles/markDown/solver/abs3-solver-usage-program.md :start-after: :end-before: ``` `topk_sols` と `best_energy_sols` は同じ内部プールを共有することに注意してください。 両方が指定された場合、最後に指定されたものが有効になります。 ### 収集された解へのアクセス `search()` メソッドは `ABS3Sols` オブジェクトを返し、収集された解へのアクセスを提供します: ```{include} ../../programFiles/markDown/solver/abs3-solver-usage-program.md :start-after: :end-before: ``` `ABS3Sols` オブジェクトは以下をサポートします: - `size()` — 収集された解の数 - `sols()` — 解ベクトルへのアクセス - `operator[](i)` — i番目の解へのアクセス - 範囲ベースforループによるイテレーション ## カスタムコールバック 組み込みコールバック(`enable_default_callback` によって有効化)は、新しい最良解が見つかるたびにエネルギーと TTS を出力します。より詳細な制御が必要な場合は、`ABS3Solver` をサブクラス化して、`callback()` 仮想メソッドをオーバーライドすることができます。 コールバックは次のいずれかのイベントで呼び出されます。 | イベント | 説明 | |----------|------| | `CallbackEvent::Start` | `search()` の開始時に一度呼ばれる | | `CallbackEvent::BestUpdated` | 新しい最良解が見つかるたびに呼ばれる | | `CallbackEvent::Timer` | 設定可能な間隔で定期的に呼ばれる | コールバック内で利用可能なアクセサメソッドは次の通りです。 - `best_sol()` — 現在の最良解への `const qbpp::Sol&` を返します。`.energy()`, `.tts()`, `.get(var)` などが使用できます。 - `event()` — このコールバックをトリガーしたイベントを返します - `hint(sol)` — 探索中にソルバーにヒント解を提供します(Solution Hintを参照) - `terminate()` — 現在の探索を協調的に中断します(下記探索の中断を参照) ## タイマー制御 `Timer` イベントはデフォルトでは有効になっていません。定期的なタイマーコールバックを有効にするには、`callback()` メソッド内で `timer(seconds)` を呼び出します。 - `timer(1.0)` : 1 秒ごとに Timer コールバックを発火 - `timer(0)` : タイマーを無効化 - `timer()`を呼び出さない場合、タイマー間隔は変更されません。 通常、`timer()` は、間隔を設定するために `Start` コールバック 内で一度呼び出されます。また、`BestUpdated` や `Timer` コールバックの中で呼び出すことで、タイマーを動的に調整したり無効化したりすることもできます。 ### 例: カスタムコールバック ```{literalinclude} ../../programFiles/cppPrograms/solver/abs3-solver-usage-program2.cpp :language: cpp :caption: abs3-solver-usage-program2.cpp ``` ## 探索の中断 `terminate()` を呼び出すと、実行中の `search()` を協調的に中断させ、これまでに発見した最良解を保持したまま即座に return させることができます。 呼び出せる場所: - `callback()` の内部 — `best_sol().energy` などを観察して停止を判断 - 別スレッド — 外部からのキャンセル、シグナルハンドラ、ウォッチドッグなど `terminate()` の利点は、現在の最良解を見て柔軟に停止条件を組み立てられる ことです。`target_energy` は事前に閾値を1つ固定する必要がありますが、`terminate()` なら: - 任意の `energy` 条件(例:`energy <= 0`, `energy < prev_best * 0.99`) - 経過時間と組み合わせた条件(例:「5秒以内に改善が無ければ停止」) - 制約違反量と目的関数の重み付け(例:`onehot_violation == 0 && objective <= threshold`) - 外部要因(GUI のキャンセルボタン、別ソルバーの完了通知など) など、**実行時に評価できる任意の条件**で停止を制御できます。 同じインスタンスで再度 `search()` を呼び出すと、停止フラグは自動的にクリアされます。 ### 例: `energy` が 0 になったら停止 `target_energy` を使わず、コールバックで `energy == 0` を観測した瞬間に `terminate()` を呼び出します。 ```{literalinclude} ../../programFiles/cppPrograms/solver/abs3-solver-usage-program3.cpp :language: cpp :caption: abs3-solver-usage-program3.cpp ``` ## Solution Hint ヒント解を使用すると、以前に見つかった解で探索をウォームスタートできます。 最も簡単な方法は、`search()` の前に `params.hint(sol)` を呼び出すことです: ```{include} ../../programFiles/markDown/solver/abs3-solver-usage-program.md :start-after: :end-before: ``` 解は探索開始前にソルバーの内部データ構造に直接書き込まれます。 外部ソルバーを並行して実行するような高度なユースケースでは、コールバック中に `hint(sol)` を呼び出して動的に解を供給することもできます。 このシナリオでは、コールバックが定期的に呼び出されて新しい外部解をチェックできるように、定期的なタイマー(例:`timer(1.0)`)を設定することを推奨します。 ### 例: ヒント解の提供 以下の例は素因数分解問題を2回解きます。 1回目の実行では通常通り最適解を見つけます。 2回目の実行では `params.hint(sol)` を介して最初の解をヒントとして提供し、ソルバーの収束を大幅に高速化します。 ```{literalinclude} ../../programFiles/cppPrograms/solver/abs3-solver-usage-program3.cpp :language: cpp :caption: abs3-solver-usage-program3.cpp ``` 注: ヒント解は探索開始前にソルバーの内部データ構造に直接書き込まれます。 ソルバーはそのエネルギーを評価し、初期状態として使用した上で、より良い解の探索を続けます。 ::: :::{container} prog-python ABS3 Solver を使用して式 `f` を解くには、次の 2 つのステップを実行します。 - 式 `f` に対して ABS3Solver オブジェクトを作成する。 - キーワード引数を指定して `search()` メソッドを呼び出し、得られた解を取得する。 ## ABS3 Solver を用いた LABS 問題の解法 次の PyQBPP プログラムは、ABS3 Solver を使用して、**低自己相関二進列(Low Autocorrelation Binary Sequence、LABS)問題** を解きます。 ```{literalinclude} ../../programFiles/pythonPrograms/solver/abs3-solver-usage-program1.py :language: python :caption: abs3-solver-usage-program1.py ``` このプログラムでは、まず式 `f` に対して `ABS3Solver` オブジェクト `solver` を作成します。 次に、`search()` メソッドにパラメータをキーワード引数として渡して呼び出します。`time_limit` は最大探索時間を秒単位で指定し、`enable_default_callback=1` は探索中に新たに見つかった最良解のエネルギーとTTSを出力する組み込みコールバックを有効にします。 このメソッドは指定された制限時間内に見つかった最良解を返し、`sol` に格納されます。 プログラムは解のエネルギーと対応するバイナリ列を出力します。”+”は1を、”-“は0を表します。 このプログラムは以下のような出力を生成します: ```{include} ../../programFiles/markDown/solver/abs3-solver-usage-program.md :start-after: :end-before: ``` ## ABS3 Solver オブジェクト `ABS3Solver` オブジェクトは、与えられた式に対して作成されます。 コンストラクタは式を内部データフォーマットに変換してホストメモリにロードし、GPUが利用可能な場合はデバイスメモリにも転送します。 以降 `search()` を複数回呼び出してもこのロードは1度きりなので、同じ式に対して繰り返し探索する際のオーバーヘッドがありません。 省略可能な第2引数 `gpu` でGPUの使用を制御します: - `ABS3Solver(f)` : 利用可能なすべての GPU を自動で使用。GPU がない場合は CPU のみで実行。 - `ABS3Solver(f, 0)` : CPU のみで実行(GPU は使用しない)。 - `ABS3Solver(f, n)` : `n` 台の GPU を使用。 探索パラメータは `search()` にキーワード引数として直接渡します。 上記の例では: - `time_limit=10.0`: 制限時間を10.0秒に設定します。 - `enable_default_callback=1`: 新たに得られた解のエネルギーとTTSを出力する組み込みコールバック関数を有効にします。 ## ABS3パラメータ パラメータは `search()` メソッドにキーワード引数として直接渡します。 上記のプログラムでは、`time_limit=10.0` で制限時間を10.0秒に設定し、`enable_default_callback=1` で新たに得られた解のエネルギーを出力する組み込みコールバック関数を有効にしています。 戻り値は解で、`sol.energy`(エネルギー値)、`sol(x)`(変数値の取得)、`sol.info`(ソルバー情報の辞書)などを提供します。詳細は QR_SOLUTION を参照してください。 ### 基本オプション | キー | 型 | 説明 | |---|---|---| | `time_limit` | `float` | 制限時間(秒)。制限時間に達すると探索を終了します。 | | `target_energy` | `int` | ターゲットエネルギーが達成されると探索を終了します。 | ### 詳細オプション | キー | 型 | 説明 | |---|---|---| | `enable_default_callback` | `int` (`0` または `1`) | エネルギーと TTS を出力する組み込みコールバックを有効にします。 | | `cpu_enable` | `int` (`0` または `1`) | GPU と並行して動作する CPU ソルバーの有効 / 無効(デフォルト: `1`)。 | | `cpu_thread_count` | `int` | CPU ソルバーのスレッド数(デフォルト: 自動)。 | | `block_count` | `int` | GPU 当たりの CUDA ブロック数。 | | `thread_count` | `int` | CUDA ブロック当たりのスレッド数。 | | `topk_sols` | `int` | 最良エネルギーの top-K 解を返します。 | | `best_energy_sols` | `int` | 最大数(`0` = 無制限)。見つかった最良エネルギーを持つすべての解を返します。 | | ## 複数解の収集 ABS3 Solverは探索中に複数の解を収集できます。 2つのモードが利用可能です: ### Top-K解 (`topk_sols`) `topk_sols` パラメータはエネルギーの昇順にソートされたtop-K解を収集します。 ```{include} ../../programFiles/markDown/solver/abs3-solver-usage-program.md :start-after: :end-before: ``` ### 最良エネルギー解 (`best_energy_sols`) `best_energy_sols` パラメータは見つかった最良エネルギーを共有するすべての解を収集します。 より良いエネルギーが発見されると、プールがクリアされ、新しい最良エネルギーの解のみが保持されます。 ```{include} ../../programFiles/markDown/solver/abs3-solver-usage-program.md :start-after: :end-before: ``` または、`best_energy_sols` を最大数付きで設定することもできます: ```{include} ../../programFiles/markDown/solver/abs3-solver-usage-program.md :start-after: :end-before: ``` `topk_sols` と `best_energy_sols` は同じ内部プールを共有することに注意してください。 両方が指定された場合、最後に指定されたものが有効になります。 ### 収集された解へのアクセス `search()` の戻り値は解で、`sol.sols` プロパティを介して収集された解のリストにアクセスできます: ```{include} ../../programFiles/markDown/solver/abs3-solver-usage-program.md :start-after: :end-before: ``` 戻り値オブジェクトは以下をサポートします: - `sol.energy` — 最良解のエネルギー - `sol.tts` — 最良解が見つかるまでの時間(秒) - `sol.sols` — 収集された解のリスト(エネルギーの昇順) - `sol.sols[i]` — `i` 番目の解へのアクセス - `len(sol.sols)` — 収集された解の数 - `sol.info` — ソルバー情報の辞書 ## カスタムコールバック 組み込みコールバック(`enable_default_callback=1` で有効化)は、新しい最良解が見つかるたびにエネルギーとTTSを出力するだけです。 より細かい制御が必要な場合は、`ABS3Solver` をサブクラス化して `callback()` メソッド(引数なし)をオーバーライドします。 コールバックは以下のイベントのいずれかで呼び出されます: | イベント値 | 名前 | 説明 | |---|---|---| | `0` | `Start` | `search()` の開始時に 1 回呼び出されます。 | | `1` | `BestUpdated` | 新しい最良解が見つかるたびに呼び出されます。 | | `2` | `Timer` | 設定可能な間隔で定期的に呼び出されます。 | `callback()` 内では、以下のメソッドが利用可能です: - `self.event()` — コールバックを発火したイベント(int: 0=Start, 1=BestUpdated, 2=Timer) - `self.best_sol()` — 現在の最良解を返します。`.energy`, `.tts`, `.get(var)` などが使用できます - `self.timer(seconds)` — 定期的な `Timer` コールバックの間隔を秒単位で設定。`0` でタイマーを無効化(下記参照) - `self.hint(sol)` — 探索中にソルバーにヒント解を提供(Solution Hint を参照) - `self.terminate()` — 現在の探索を協調的に中断します(下記探索の中断を参照) ## タイマー制御 `Timer` イベントはデフォルトでは有効になっていません。 定期的なタイマーコールバックを有効にするには、`callback()` メソッド内で `self.timer(seconds)` を呼び出します: - `self.timer(1.0)` — 1秒ごとに `Timer` コールバックを発火します - `self.timer(0)` — タイマーを無効にします - `self.timer()` が呼ばれない場合、タイマー間隔は変更されません 通常、`self.timer()` は `Start` コールバック中に1回呼び出されて間隔を設定します。 `BestUpdated` や `Timer` コールバック中にも呼び出して、タイマーを動的に調整または無効にすることができます。 ## 例: カスタムコールバック ```{literalinclude} ../../programFiles/pythonPrograms/solver/abs3-solver-usage-program2.py :language: python :caption: abs3-solver-usage-program2.py ``` ## 探索の中断 `self.terminate()` を呼び出すと、実行中の `search()` を協調的に中断させ、これまでに発見した最良解を保持したまま即座に return させることができます。 呼び出せる場所: - `callback()` の内部 — `self.best_sol().energy` などを観察して停止を判断 - 別スレッド — 外部からのキャンセル、シグナルハンドラ、ウォッチドッグなど `terminate()` の利点は、**現在の最良解を見て柔軟に停止条件を組み立てられる** ことです。`target_energy` は事前に閾値を1つ固定する必要がありますが、`terminate()` なら: - 任意の `energy` 条件(例: `energy <= 0`、`energy < prev_best * 0.99`) - 経過時間と組み合わせた条件(例:「5秒以内に改善が無ければ停止」) - 制約違反量と目的関数の重み付け(例: `onehot_violation == 0 and objective <= threshold`) - 外部要因(GUI のキャンセルボタン、別ソルバーの完了通知など) など、**実行時に評価できる任意の条件**で停止を制御できます。 同じインスタンスで再度 `search()` を呼び出すと、停止フラグは自動的にクリアされます。 ## 例: energy が 0 になったら停止 `target_energy` を使わず、コールバックで `energy == 0` を観測した瞬間に `self.terminate()` を呼び出します。 ```{literalinclude} ../../programFiles/pythonPrograms/solver/abs3-solver-usage-program3.py :language: python :caption: abs3-solver-usage-program3.py ``` ## Solution Hint ヒント解を使用すると、以前に見つかった解で探索をウォームスタートできます。 最も簡単な方法は、`search()` の前に `solver.hint(sol)` を呼び出すことです: ```{include} ../../programFiles/markDown/solver/abs3-solver-usage-program.md :start-after: :end-before: ``` 解は探索開始前にソルバーの内部データ構造に直接書き込まれます。 外部ソルバーを並行して実行するような高度なユースケースでは、コールバック内で `self.hint(sol)` を呼び出して動的に解を供給することもできます。 このシナリオでは、コールバックが定期的に呼び出されて新しい外部解をチェックできるように、定期的なタイマー(例: `self.timer(1.0)`)を設定することを推奨します。 ## 例: ヒント解の提供 以下の例は素因数分解問題を2回解きます。 1回目の実行では通常通り最適解を見つけます。 2回目の実行では `solver.hint(sol1)` を介して最初の解をヒントとして提供し、ソルバーの収束を大幅に高速化します。 ```{literalinclude} ../../programFiles/pythonPrograms/solver/abs3-solver-usage-program4.py :language: python :caption: abs3-solver-usage-program4.py ``` ヒント解は探索開始前にソルバーの内部データ構造に直接書き込まれます。 ソルバーはそのエネルギーを評価し、初期状態として使用した上で、より良い解の探索を続けます。 :::