# 式の求解
:::{container} prog-cpp
Hi-QUBOはQUBO/HUBO式を解くための3つのソルバーを提供しています:
- **Easy Solver**
- シミュレーテッドアニーリングに基づくヒューリスティックアルゴリズムを実行します.
- マルチコアCPU上で並列に動作します.
- 最適性は保証されません.
- **Exhaustive Solver**
- すべての可能な解を探索します.
- 返される解の最適性が保証されます.
- バイナリ変数の数が約30~40以下の場合にのみ計算が現実的です.
- CUDA GPUが利用可能な場合,CPUスレッドと並行してGPUアクセラレーションが自動的に有効になります.
- **ABS3 Solver**
- CUDA GPUとマルチコアCPUを活用する高性能ソルバーです.
- 最適性は保証されませんが,Easy Solverよりはるかに強力です.
- GPUが利用できない場合はCPUのみモードにフォールバックします.
Easy Solver,Exhaustive Solver,ABS3 Solverは以下のステップで使用します:
1. ソルバーオブジェクト(**`qbpp::EasySolver`**,**`qbpp::ExhaustiveSolver`**,または**`qbpp::ABS3Solver`**)を作成します.
2. ソルバーオブジェクトの**`search()`**メンバ関数を呼び出します.パラメータは初期化子リストとして渡すことができます.得られた解を格納する**`qbpp::Sol`**オブジェクトが返されます.
> **注釈**
> `qbpp::Sol` は可変な値型です — 他の Hi-QUBO の値と同じく代入・コピー・更新が
> できます([エイリアスとコピー](../basic/variables-and-expressions.md#エイリアスとコピー)を参照).
> ソルバーオブジェクト(`EasySolver`,`ExhaustiveSolver`,`ABS3Solver`)は
> 重い計算リソースを所有しているため **コピー不可** です(コピーコンストラクタが
> 削除されています).新しいソルバーが必要な場合は別途作成してください.
## Easy Solver
**Easy Solver**を使用するには,ヘッダファイル**`qbpp/easy_solver.hpp`**をインクルードします.
名前空間**`qbpp::easy_solver`**で定義されています.
以下の式 $f(a,b,c,d)$ を例として使用します:
$$
\begin{aligned}
f(a,b,c,d,e) &= (a+2b+3c+4d-5)^2
\end{aligned}
$$
明らかに,$a+2b+3c+4d=5$ のとき,この式は最小値 $f=0$ を取ります.
したがって,$(a,b,c,d)=(0,1,1,0)$ と $(1,0,0,1)$ の2つの最適解があります.
以下のプログラムでは,シンボリック計算を使って式 `f` を作成します.
関数**`qbpp::sqr()`**は引数の2乗を返すことに注意してください.
次に,`f` をコンストラクタに渡してクラス `qbpp::EasySolver` のインスタンスを構築します.
その前に,**`simplify_as_binary()`**を呼び出して `f` をバイナリ変数用に簡約化する必要があります.
コンストラクタは**`solver`**という名前の `EasySolver` オブジェクトを返します.
最適値が $f=0$ であることがわかっているので,`search()` にターゲットエネルギーを初期化子リストとして渡します.
`solver` の**`search()`**メンバ関数を呼び出すと,クラス**`qbpp::Sol`**の解インスタンス**`sol`**が返され,`std::cout` で出力されます.
```{literalinclude} /../programFiles/cppPrograms/basic/solving-expressions-program1.cpp
:language: cpp
:caption: solving-expressions-program1.cpp
```
このプログラムの出力は以下のとおりです:
```{include} /../programFiles/markDown/basic/solving-expressions.md
:start-after:
:end-before:
```
最適解の1つが正しく出力されています.
## Exhaustive Solver
**Exhaustive Solver**を使用するには,ヘッダファイル**`qbpp/exhaustive_solver.hpp`**をインクルードします.
名前空間**`qbpp::exhaustive_solver`**で定義されています.
`f` をコンストラクタに渡してクラス**`qbpp::ExhaustiveSolver`**のインスタンス**`solver`**を構築します.
`solver` の**`search()`**メンバ関数を呼び出すと,クラス**`qbpp::Sol`**の解インスタンス**`sol`**が返され,`std::cout` で出力されます.
Exhaustive Solverはすべての可能な割り当てを探索するため,`sol` に最適解が格納されることが保証されます.
```{literalinclude} /../programFiles/cppPrograms/basic/solving-expressions-program2.cpp
:language: cpp
:caption: solving-expressions-program2.cpp
```
このプログラムの出力は以下のとおりです:
```{include} /../programFiles/markDown/basic/solving-expressions.md
:start-after:
:end-before:
```
`std::cout << sol` はデフォルトで見つかった最良解のみを出力します.
収集された全解のリストはメンバ **`sol.sols`** からアクセスでき,これはエネルギー昇順にソートされた解のリストです.
すべての最適解は `best_energy_sols` パラメータを設定することで以下のように取得できます:
```{include} /../programFiles/markDown/basic/solving-expressions.md
:start-after:
:end-before:
```
出力は以下のとおりです:
```{include} /../programFiles/markDown/basic/solving-expressions.md
:start-after:
:end-before:
```
さらに,非最適解を含むすべての解は `all_sols` パラメータを設定することで以下のように取得できます:
```{include} /../programFiles/markDown/basic/solving-expressions.md
:start-after:
:end-before:
```
Exhaustive Solverは,小さな式の解析やデバッグに非常に有用です.
## ABS3 Solver
**ABS3 Solver**を使用するには,ヘッダファイル**`qbpp/abs3_solver.hpp`**をインクルードします.
名前空間**`qbpp::abs3`**で定義されています.
ABS3 Solverは,CUDA GPUとマルチコアCPUを活用する高性能ソルバーです.
GPUが利用できない場合は,自動的にCPUのみモードにフォールバックします.
使用方法は以下の2ステップです:
1. 式に対して**`qbpp::ABS3Solver`**オブジェクトを作成します.
2. **`search()`**メンバ関数を呼び出します.パラメータは初期化子リストとして渡します.得られた解が返されます.
```{literalinclude} /../programFiles/cppPrograms/basic/solving-expressions-program3.cpp
:language: cpp
:caption: solving-expressions-program3.cpp
```
このプログラムの出力は以下のとおりです:
```{include} /../programFiles/markDown/basic/solving-expressions.md
:start-after:
:end-before:
```
パラメータ,コールバック,複数解の収集,ヒント解の詳細については**[ABS3 Solver](../solver/abs3-solver-usage.md)**をご覧ください.
:::
:::{container} prog-python
PyQBPPはQUBO/HUBO式を解くための3つのソルバーを提供しています:
- **Easy Solver**
- シミュレーテッドアニーリングに基づくヒューリスティックアルゴリズムを実行します.
- マルチコアCPU上で並列に動作します.
- 最適性は保証されません.
- **Exhaustive Solver**
- すべての可能な解を探索します.
- 返される解の最適性が保証されます.
- バイナリ変数の数が約30〜40以下の場合にのみ計算が現実的です.
- CUDA GPUが利用可能な場合,CPUスレッドと並行してGPUアクセラレーションが自動的に有効になります.
- **ABS3 Solver**
- CUDA GPUとマルチコアCPUを活用する高性能ソルバーです.
- 最適性は保証されませんが,Easy Solverよりはるかに強力です.
- GPUが利用できない場合はCPUのみモードにフォールバックします.
Easy Solver,Exhaustive Solver,ABS3 Solverは以下のステップで使用します:
1. ソルバーオブジェクト(**`qbpp.EasySolver`**,**`qbpp.ExhaustiveSolver`**,または **`qbpp.ABS3Solver`**)を作成します.
2. ソルバーオブジェクトの **`search()`** メソッドを呼び出します.パラメータはキーワード引数として渡すことができます.得られた解が返されます.
> **注釈**
> 返される解は可変オブジェクトです.別の変数に代入すると **エイリアス** が
> 作られます(Python の参照セマンティクス).独立した深いコピーが欲しい場合は
> `qbpp.Sol(other_sol)` を使ってください.詳細は
> [エイリアスとコピー](../basic/variables-and-expressions.md#エイリアスとコピー) を参照してください.
> ソルバーオブジェクトは重い計算リソースを所有しているためコピーすべきでは
> ありません.必要があれば新しいソルバーを作成してください.
## Easy Solver
**Easy Solver**を使用するには,PyQBPPが提供するクラス **`qbpp.EasySolver`** を使用します.
以下の式 $f(a,b,c,d)$ を例として使用します:
$$
\begin{aligned}
f(a,b,c,d) &= (a+2b+3c+4d-5)^2
\end{aligned}
$$
明らかに,$a+2b+3c+4d=5$ のとき,この式は最小値 $f=0$ を取ります.
したがって,$(a,b,c,d)=(0,1,1,0)$ と $(1,0,0,1)$ の2つの最適解があります.
以下のプログラムでは,シンボリック計算を使って式 `f` を作成します.
関数 **`qbpp.sqr()`** は引数の2乗を返すことに注意してください.
次に,`f` をコンストラクタに渡してクラス `qbpp.EasySolver` のインスタンスを構築します.
その前に,**`simplify_as_binary()`** を呼び出して `f` をバイナリ変数用に簡約化する必要があります.
コンストラクタは **`solver`** という名前の `EasySolver` オブジェクトを返します.
最適値が $f=0$ であることがわかっているので,`search()` にキーワード引数 `target_energy=0` を渡します.これは `f` の値が 0 以下となる解が見つかった時点で探索を終了することを意味します.
`solver` の **`search()`** メソッドを呼び出すと,解 **`sol`** が返され,`print()` で出力されます.
```{literalinclude} /../programFiles/pythonPrograms/basic/solving-expressions-program1.py
:language: python
:caption: solving-expressions-program1.py
```
このプログラムの出力は以下のとおりです:
```{include} /../programFiles/markDown/basic/solving-expressions.md
:start-after:
:end-before:
```
最適解の1つが正しく出力されています.
## Exhaustive Solver
**Exhaustive Solver**を使用するには,PyQBPPが提供するクラス **`qbpp.ExhaustiveSolver`** を使用します.
`f` をコンストラクタに渡してクラス **`qbpp.ExhaustiveSolver`** のインスタンス **`solver`** を構築します.
`solver` の **`search()`** メソッドを呼び出すと,解 **`sol`** が返され,`print()` で出力されます.
Exhaustive Solverはすべての可能な割り当てを探索するため,`sol` に最適解が格納されることが保証されます.
```{literalinclude} /../programFiles/pythonPrograms/basic/solving-expressions-program2.py
:language: python
:caption: solving-expressions-program2.py
```
このプログラムの出力は以下のとおりです:
```{include} /../programFiles/markDown/basic/solving-expressions.md
:start-after:
:end-before:
```
`print(sol)` はデフォルトで見つかった最良解のみを出力します.
収集された全解のリストは属性 **`sol.sols`** からアクセスでき,これはエネルギー昇順にソートされた解のリストです.
すべての最適解は `best_energy_sols` パラメータを設定することで以下のように取得できます:
```{include} /../programFiles/markDown/basic/solving-expressions.md
:start-after:
:end-before:
```
出力は以下のとおりです:
```{include} /../programFiles/markDown/basic/solving-expressions.md
:start-after:
:end-before:
```
さらに,非最適解を含むすべての解は `all_sols` パラメータを設定することで以下のように取得できます:
```{include} /../programFiles/markDown/basic/solving-expressions.md
:start-after:
:end-before:
```
```{include} /../programFiles/markDown/basic/solving-expressions.md
:start-after:
:end-before:
```
Exhaustive Solverは,小さな式の解析やデバッグに非常に有用です.
## ABS3 Solver
**ABS3 Solver**を使用するには,PyQBPPが提供するクラス **`qbpp.ABS3Solver`** を使用します.
ABS3 Solverは,CUDA GPUとマルチコアCPUを活用する高性能ソルバーです.
GPUが利用できない場合は,自動的にCPUのみモードにフォールバックします.
使用方法は以下の2ステップです:
1. 式に対して **`qbpp.ABS3Solver`** オブジェクトを作成します.
2. **`search()`** メソッドを呼び出します.パラメータはキーワード引数として渡します.得られた解が返されます.
```{literalinclude} /../programFiles/pythonPrograms/basic/solving-expressions-program3.py
:language: python
:caption: solving-expressions-program3.py
```
このプログラムの出力は以下のとおりです:
```{include} /../programFiles/markDown/basic/solving-expressions.md
:start-after:
:end-before:
```
パラメータ,コールバック,複数解の収集,ヒント解の詳細については **[Easy Solver](../solver/easy-solver-usage.md)**,**[Exhaustive Solver](../solver/exhaustive-solver-usage.md)**,**[ABS3 Solver](../solver/abs3-solver-usage.md)** をご覧ください.
:::