# ネイティブ整数変数
:::{container} prog-cpp
[整数変数と連立方程式の求解](../basic/integer-variables-and-linear-systems.md)では,複数のバイナリ変数を組み合わせて
整数を表現する方法を説明しました.Hi-QUBO はこれに加えて,
**整数値をそのまま保持するネイティブ整数変数**をサポートしています.
`qbpp::int_var()` で宣言した変数はバイナリ変数に展開されず,
Hi-QUBO にバンドルされているソルバー
([EasySolver](../solver/easy-solver-usage.md)・[ABS3 Solver](../solver/abs3-solver-usage.md)・[Exhaustive Solver](../solver/exhaustive-solver-usage.md))が
整数値を直接扱って効率よく探索を行います.
## 宣言と基本的な使い方
ネイティブ整数変数は,[整数変数](../basic/integer-variables-and-linear-systems.md)(`var_int`)と同じ書き方で,
名前と値の範囲(下限・上限)を範囲演算子で指定して宣言します.
範囲の指定は必須です.宣言した変数は通常の変数と同じように式の中で使えます:
```{literalinclude} /../programFiles/cppPrograms/basic/integer-variables-and-linear-systems-program1.cpp
:language: cpp
:caption: integer-variables-and-linear-systems-program1.cpp
```
プログラムの出力は以下の通りです:
```{include} /../programFiles/markDown/basic/integer-variables-and-linear-systems.md
:start-after:
:end-before:
```
`x * x` のような冪に,バイナリ変数の規則($x \cdot x = x$)は適用されず,
整数の二乗としてそのまま扱われる点に注意してください.
## 連立方程式を解く例
次のプログラムは,連立方程式 $x + 2y = 700$,$x - y = 100$ を
2 乗誤差の最小化として解きます:
```{literalinclude} /../programFiles/cppPrograms/basic/integer-variables-and-linear-systems-program2.cpp
:language: cpp
:caption: integer-variables-and-linear-systems-program2.cpp
```
プログラムの出力は以下の通りです:
```{include} /../programFiles/markDown/basic/integer-variables-and-linear-systems.md
:start-after:
:end-before:
```
## 整数変数の配列
`int_var()` に次元を渡すと,ネイティブ整数変数の配列が作れます.
要素には `s[i]` でアクセスし,`qbpp::sum()` で総和の式が作れます:
```{literalinclude} /../programFiles/cppPrograms/basic/integer-variables-and-linear-systems-program3.cpp
:language: cpp
:caption: integer-variables-and-linear-systems-program3.cpp
```
プログラムの出力は以下の通りです:
```{include} /../programFiles/markDown/basic/integer-variables-and-linear-systems.md
:start-after:
:end-before:
```
## 要素ごとに範囲が異なる配列
配列形の宣言は,全要素が同じ範囲を共有します.範囲の下限・上限に
配列を指定すると,要素ごとに個別の範囲を持つネイティブ整数変数の
配列が作られます.下限と上限が等しい要素は,その値に固定された
定数になります:
```{literalinclude} /../programFiles/cppPrograms/basic/integer-variables-and-linear-systems-program4.cpp
:language: cpp
:caption: integer-variables-and-linear-systems-program4.cpp
```
プログラムの出力は以下の通りです(`v[2]` は下限=上限なので
定数 2 に固定されます):
```{include} /../programFiles/markDown/basic/integer-variables-and-linear-systems.md
:start-after:
:end-before:
```
片側だけ配列にすることもできます(例: `0 <= qbpp::int_var("w", 3) <= upper`
は下限 0 を全要素で共有します).
また,[切り出し](../example/real/cutting-stock.md)の `var_int` と同じ
プレースホルダの書き方も使えます.`qbpp::int_var("x", 3) == 0` は
全要素が定数 0 の可変配列を作り,各要素にネイティブ整数変数を
ひとつずつ代入できます:
```{literalinclude} /../programFiles/cppPrograms/basic/integer-variables-and-linear-systems-program5.cpp
:language: cpp
:caption: integer-variables-and-linear-systems-program5.cpp
```
プログラムの出力は以下の通りです:
```{include} /../programFiles/markDown/basic/integer-variables-and-linear-systems.md
:start-after:
:end-before:
```
代入しなかった要素は定数(ここでは 0)のまま式に残ります.
定数には 0 以外の値も指定できます.
## 制約との併用
[ネイティブ制約](../basic/constraints.md)の `qbpp::cons()` は,
ネイティブ整数変数を含む式にもそのまま使えます:
```{literalinclude} /../programFiles/cppPrograms/basic/integer-variables-and-linear-systems-program6.cpp
:language: cpp
:caption: integer-variables-and-linear-systems-program6.cpp
```
プログラムの出力は以下の通りです:
```{include} /../programFiles/markDown/basic/integer-variables-and-linear-systems.md
:start-after:
:end-before:
```
## 外部ソルバーとの連携
[GurobiSolver](../solver/gurobi-solver-usage.md) などの MIP ソルバーは整数変数をそのまま
扱えるため,ネイティブ整数変数は**整数の列として直接渡されます**
(バイナリ変数には展開されません).`qbpp::GurobiSolver solver(f);` は
二次の目的関数(MIQP)まで対応します.目的関数が線形で制約を
`qbpp::cons()` で書いたモデルは,`qbpp::ScipSolver solver(f, qbpp::ilp);`
のように ILP オプションを付ければ 5 種の MIP ソルバーすべてで解けます.
一方,バイナリ変数専用の外部 QUBO ソルバーに渡す場合は,
`qbpp::binarize()` で[従来のバイナリエンコーディング](../basic/integer-variables-and-linear-systems.md)に
変換してください:
```{literalinclude} /../programFiles/cppPrograms/basic/integer-variables-and-linear-systems-program7.cpp
:language: cpp
:caption: integer-variables-and-linear-systems-program7.cpp
```
プログラムの出力は以下の通りです:
```{include} /../programFiles/markDown/basic/integer-variables-and-linear-systems.md
:start-after:
:end-before:
```
## 使い分けの指針
- 個数・時刻・在庫量など**数量**を表す変数には,ネイティブ整数変数が適しています.
- 外部のバイナリ専用ソルバーに渡すモデルは,
[バイナリエンコーディングの整数変数](../basic/integer-variables-and-linear-systems.md)(`var_int`)を使うか,
`qbpp::binarize()` で変換してください.
- 「どれを選ぶか」という**ラベル**(訪問順序・色など)には,
ネイティブ整数変数よりも one-hot 表現
([置換行列](../example/math/permutation.md)・[One-hot 制約](../advanced/onehot-integer.md))が適しています.
なお,ライセンスの変数数の上限では,ネイティブ整数変数 1 個は,
その範囲(上限 − 下限)を $r$ とすると,次の個数のバイナリ変数分として
カウントされます:
$$
\lceil \log_2 (r+1) \rceil
$$
詳細は[ライセンス管理](../licenseManage/license-manage.md)を参照してください.
:::
:::{container} prog-python
[整数変数と連立方程式の求解](../basic/integer-variables-and-linear-systems.md)では,複数のバイナリ変数を組み合わせて
整数を表現する方法を説明しました.PyQBPP はこれに加えて,
**整数値をそのまま保持するネイティブ整数変数**をサポートしています.
`qbpp.var()` の `integer=` キーワードで宣言した変数はバイナリ変数に展開されず,
Hi-QUBO にバンドルされているソルバー
([EasySolver](../solver/easy-solver-usage.md)・[ABS3 Solver](../solver/abs3-solver-usage.md)・[Exhaustive Solver](../solver/exhaustive-solver-usage.md))が
整数値を直接扱って効率よく探索を行います.
## 宣言と基本的な使い方
ネイティブ整数変数は,`integer=(下限, 上限)` を指定して宣言します.
範囲の指定は必須です.宣言した変数は通常の変数と同じように式の中で使えます:
```{literalinclude} /../programFiles/pythonPrograms/basic/integer-variables-and-linear-systems-program1.py
:language: python
:caption: integer-variables-and-linear-systems-program1.py
```
プログラムの出力は以下の通りです:
```{include} /../programFiles/markDown/basic/integer-variables-and-linear-systems.md
:start-after:
:end-before:
```
`x * x` のような冪に,バイナリ変数の規則($x \cdot x = x$)は適用されず,
整数の二乗としてそのまま扱われる点に注意してください.
## 連立方程式を解く例
次のプログラムは,連立方程式 $x + 2y = 700$,$x - y = 100$ を
2 乗誤差の最小化として解きます:
```{literalinclude} /../programFiles/pythonPrograms/basic/integer-variables-and-linear-systems-program2.py
:language: python
:caption: integer-variables-and-linear-systems-program2.py
```
プログラムの出力は以下の通りです:
```{include} /../programFiles/markDown/basic/integer-variables-and-linear-systems.md
:start-after:
:end-before:
```
## 整数変数の配列
`qbpp.var()` に次元と `integer=` を同時に指定すると,
ネイティブ整数変数の配列が作れます.要素には `s[i]` でアクセスし,
`s.sum()` で総和の式が作れます:
```{literalinclude} /../programFiles/pythonPrograms/basic/integer-variables-and-linear-systems-program3.py
:language: python
:caption: integer-variables-and-linear-systems-program3.py
```
プログラムの出力は以下の通りです:
```{include} /../programFiles/markDown/basic/integer-variables-and-linear-systems.md
:start-after:
:end-before:
```
## 要素ごとに範囲が異なる配列
`integer=` の下限・上限には,スカラーの代わりにリストも指定できます.
リストを指定すると,要素ごとに個別の範囲を持つネイティブ整数変数の
配列が作られます(スカラー側の値は全要素で共有されます).
下限と上限が等しい要素は,その値に固定された定数になります:
```{literalinclude} /../programFiles/pythonPrograms/basic/integer-variables-and-linear-systems-program4.py
:language: python
:caption: integer-variables-and-linear-systems-program4.py
```
プログラムの出力は以下の通りです:
```{include} /../programFiles/markDown/basic/integer-variables-and-linear-systems.md
:start-after:
:end-before:
```
## 制約との併用
[ネイティブ制約](../basic/constraints.md)の `qbpp.cons()` は,
ネイティブ整数変数を含む式にもそのまま使えます:
```{literalinclude} /../programFiles/pythonPrograms/basic/integer-variables-and-linear-systems-program5.py
:language: python
:caption: integer-variables-and-linear-systems-program5.py
```
プログラムの出力は以下の通りです:
```{include} /../programFiles/markDown/basic/integer-variables-and-linear-systems.md
:start-after:
:end-before:
```
## 外部ソルバーとの連携
MIP ソルバーは整数変数をそのまま扱えるため,ネイティブ整数変数は
**整数の列として直接渡されます**(バイナリ変数には展開されません).
`qbpp.GurobiSolver(f)` は二次の目的関数(MIQP)まで対応します.
目的関数が線形で制約を `qbpp.cons()` で書いたモデルは,
`qbpp.ScipSolver(f, ilp=True)` のように `ilp=True` を付ければ
5 種の MIP ソルバーすべてで解けます.
一方,バイナリ変数専用の外部 QUBO ソルバーに渡す場合は,
`qbpp.binarize()` で[従来のバイナリエンコーディング](../basic/integer-variables-and-linear-systems.md)に
変換してください:
```{literalinclude} /../programFiles/pythonPrograms/basic/integer-variables-and-linear-systems-program6.py
:language: python
:caption: integer-variables-and-linear-systems-program6.py
```
プログラムの出力は以下の通りです:
```{include} /../programFiles/markDown/basic/integer-variables-and-linear-systems.md
:start-after:
:end-before:
```
## 使い分けの指針
- 個数・時刻・在庫量など**数量**を表す変数には,ネイティブ整数変数が適しています.
- 外部のバイナリ専用ソルバーに渡すモデルは,
[バイナリエンコーディングの整数変数](../basic/integer-variables-and-linear-systems.md)(`between=`)を使うか,
`qbpp.binarize()` で変換してください.
- 「どれを選ぶか」という**ラベル**(訪問順序・色など)には,
ネイティブ整数変数よりも one-hot 表現
([置換行列](../example/math/permutation.md)・[One-hot 制約](../advanced/onehot-integer.md))が適しています.
なお,ライセンスの変数数の上限では,ネイティブ整数変数 1 個は,
その範囲(上限 − 下限)を $r$ とすると,次の個数のバイナリ変数分として
カウントされます:
$$
\lceil \log_2 (r+1) \rceil
$$
:::