# ネイティブ整数変数 :::{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 $$ :::