# 範囲制約と整数線形計画法の求解
:::{container} prog-cpp
## 範囲制約の多項式定式化
$f$ をバイナリ変数の多項式とします.
範囲制約は $l**NOTE**
> Hi-QUBOは内部的に軽量な改善を施しており,範囲制約をわずかに少ないバイナリ変数数で符号化できます.
> 詳細は[比較演算子](../advanced/comparison-operators.md)に記載されています.
## 整数線形計画法の求解
**整数線形計画法**のインスタンスは,**目的関数**と複数の**線形制約**から構成されます.
例えば,以下の整数線形計画問題は2つの変数,1つの目的関数,2つの制約を持ちます:
$$
\begin{aligned}
\text{Maximize: } & & & 5x + 4y \\
\text{Subject to: } & && 2x + 3y \le 24 \\
& & & 7x + 5y \le 54
\end{aligned}
$$
この問題の最適解は $x=4$, $y=5$ であり,目的関数値は $40$ です.
以下のHi-QUBOプログラムは,Easy Solverを使用してこの最適解を求めます:
```{literalinclude} /../programFiles/cppPrograms/basic/range-constraints-and-ilp-program1.cpp
:language: cpp
:caption: range-constraints-and-ilp-program1.cpp
```
このHi-QUBOプログラムでは,
- **`f`** は目的関数を表し,
- **`c1`** と **`c2`** は範囲制約を表し,
- **`g`** はこれらを1つの最適化式にまとめたものです.
目標が最大化であるため,目的関数は `-f` として符号を反転しています.
制約 `c1` と `c2` には重み100のペナルティを付け,高い優先度で制約が満たされるようにしています.
`g` に対してEasy Solverインスタンスを作成し,制限時間1.0秒で探索を実行します.
最適解 `sol` を取得した後,`x`,`y`,`f`,`c1`,`c2`,`c1.body(sol)`,`c2.body(sol)` の値を出力します.
プログラムの出力は以下の通りです:
```{include} /../programFiles/markDown/basic/range-constraints-and-ilp.md
:start-after:
:end-before:
```
ここで,
- **`c1`** は制約 `0 <= 2 x + 3 y <= 24` のペナルティ式(制約が満たされると 0)であり,
- **`c1.body()`** は線形式 `2 x + 3 y` を返し,`c1.body(sol)` はその値を `sol` で評価します.
ソルバーが正しく最適解を見つけたことが確認できます.
## ネイティブ制約 `cons()` による記述
上のプログラムでは,制約 `c1` と `c2` を重み付きのペナルティ式として目的関数に加えました.
Hi-QUBO では,さらに一歩進めて,制約を `qbpp::cons()` で囲んで**制約であることを明示**できます:
```{literalinclude} /../programFiles/cppPrograms/basic/range-constraints-and-ilp-program2.cpp
:language: cpp
:caption: range-constraints-and-ilp-program2.cpp
```
変更点は `100 * (c1 + c2)` を `100 * (qbpp::cons(c1) + qbpp::cons(c2))` に書き換えただけです.
`qbpp::cons()` で囲まれた部分は**制約として特別に処理**され,
バンドルされたソルバーは宣言された制約を満たすように効率よく探索を行います.
`g.cons(sol)` は解 `sol` で違反している制約の本数を返します(0 なら全制約を充足).
プログラムの出力は以下の通りです:
```{include} /../programFiles/markDown/basic/range-constraints-and-ilp.md
:start-after:
:end-before:
```
`cons()` で宣言した制約は,バンドルされた 3 つのソルバー(Easy Solver・
Exhaustive Solver・ABS3 Solver)すべてで同じ意味を持ち,Exhaustive Solver は
このペナルティ込みエネルギーの**厳密な最小解**を返します.
MIP ソルバー(Gurobi 等)では**ハード制約**(必ず満たすべき制約)として扱われます.
詳細は[ネイティブ制約](../basic/constraints.md)をご覧ください.
:::
:::{container} prog-python
## 範囲制約の多項式定式化
$f$ をバイナリ変数の多項式とします.
範囲制約は $l**NOTE**
> PyQBPPは内部的に軽量な改善を施しており,範囲制約をわずかに少ないバイナリ変数数で符号化できます.
> 詳細は[比較演算子](../advanced/comparison-operators.md)に記載されています.
## 整数線形計画法の求解
**整数線形計画法**のインスタンスは,**目的関数**と複数の**線形制約**から構成されます.
例えば,以下の整数線形計画は2つの変数,1つの目的関数,2つの制約を持ちます:
$$
\begin{aligned}
\text{Maximize: } & & & 5x + 4y \\
\text{Subject to: } & && 2x + 3y \le 24 \\
& & & 7x + 5y \le 54
\end{aligned}
$$
この問題の最適解は $x=4$, $y=5$ で,目的関数の値は $40$ です.
以下のPyQBPPプログラムは,Easy Solverを使ってこの最適解を求めます:
```{literalinclude} /../programFiles/pythonPrograms/basic/range-constraints-and-ilp-program1.py
:language: python
:caption: range-constraints-and-ilp-program1.py
```
このプログラムでは,
- **`f`** は目的関数を表し,
- **`c1`** と **`c2`** は **`constrain()`** を使って作成された範囲制約を表し,
- **`g`** はそれらを1つの最適化式にまとめたものです.
目標が最大化であるため,目的関数は `-f` として符号を反転しています.
制約 `c1` と `c2` は重み100のペナルティを付けて,高い優先度で満たされるようにしています.
`g` に対してEasy Solverのインスタンスを作成し,制限時間1.0秒を `search()` のパラメータとして渡して探索を実行します.
最適解 `sol` を得た後,プログラムは `x`,`y`,`f`,`c1`,`c2`,および制約本体の式の値を出力します.
プログラムの出力は以下の通りです:
```{include} /../programFiles/markDown/basic/range-constraints-and-ilp.md
:start-after:
:end-before:
```
ここで,
- **`c1`** は制約 `0 <= 2x + 3y <= 24` のペナルティであり,
- **`c1.body`** は線形式 `2x + 3y` を表します.
ソルバーが正しく最適解を見つけていることが確認できます.
## ネイティブ制約 `cons()` による記述
上のプログラムでは,制約 `c1` と `c2` を重み付きのペナルティ式として目的関数に加えました.
PyQBPP では,さらに一歩進めて,制約を **`qbpp.cons()`** で作成して**制約であることを明示**できます:
```{literalinclude} /../programFiles/pythonPrograms/basic/range-constraints-and-ilp-program2.py
:language: python
:caption: range-constraints-and-ilp-program2.py
```
変更点は `constrain()` の代わりに `qbpp.cons()` を使うことだけです(引数の書き方は同じで,
範囲制約は `between=(l, u)`,等式制約は `equal=n` で指定します).
`qbpp.cons()` で作成した部分は**制約として特別に処理**され,
バンドルされたソルバーは宣言された制約を満たすように効率よく探索を行います.
`g.cons(sol)` は解 `sol` で違反している制約の本数を返します(0 なら全制約を充足).
プログラムの出力は以下の通りです:
```{include} /../programFiles/markDown/basic/range-constraints-and-ilp.md
:start-after:
:end-before:
```
`cons()` で宣言した制約は,バンドルされた 3 つのソルバー(Easy Solver・
Exhaustive Solver・ABS3 Solver)すべてで同じ意味を持ち,Exhaustive Solver は
このペナルティ込みエネルギーの**厳密な最小解**を返します.
MIP ソルバー(Gurobi 等)では `ilp=True` を指定すると**ハード制約**
(必ず満たすべき制約)として扱われます.
詳細は[ネイティブ制約](../basic/constraints.md)をご覧ください.
:::