整数変数と制約に関する演算と関数¶
qbpp::Expr は通常の式・整数変数・制約式を 統一的に表現する型 です.3 つとも同じ型で,持つメタデータが違うだけです.
Expr は 3 つの「顔」を持ちます:
通常の式 (多項式):
x + 2*y*zなどの算術式整数変数:
l <= qbpp::var_int("x") <= uなどで作ったExpr.範囲・ビット分解のメタデータを保持制約式:
e == 5/lo <= e <= hiなどで作ったExpr.penalty + body のメタデータを保持
基本原則
qbpp::Exprの演算・関数はすべて,どの「顔」の Expr にも適用できる固有 accessor (
min_val(),body等) は対応する「顔」の Expr でのみ有効.合わない Expr で呼ぶと runtime abort(エラーメッセージ付き)式を変更するメンバ関数 (
+=,-=,*=,/=,sqr(),replace()) を呼ぶと,内部表現は通常の式に戻る(固有メタデータは破棄され,固有 accessor は以後呼べなくなる)例外:
simplify*()は固有メタデータを保ったまま,保持している式のみを簡約する.「顔」は維持される
is_varint()/is_exprexpr()で現在の「顔」を実行時に確認できる
1. 整数変数
このページの整数変数は,複数のバイナリ変数に展開されるものです.
整数値をそのまま保持するネイティブ整数変数(qbpp::IntVar)は
qbpp::Expr とは別の型で,リファレンスは変数と式にあります.
cons() の制約式には,どちらの整数変数も使えます.
生成
構文 |
戻り値 |
|---|---|
|
|
|
整数変数の多次元配列 |
使える演算・関数
カテゴリ |
例 |
戻り値 |
備考 |
|---|---|---|---|
単項 |
|
|
|
算術 (右辺 Expr) |
|
|
|
算術 (右辺 整数変数) |
|
|
|
比較 (== int) |
|
|
制約生成 |
比較 (範囲) |
|
|
between 制約 |
グローバル関数 |
|
|
|
整数変数固有メタ情報 |
|
|
read-only |
整数変数固有構造メンバ |
|
各種 |
read-only |
配列アクセス |
|
|
read-only |
複合代入 |
|
|
以後は通常の式相当(固有メタは破棄) |
二乗 |
|
|
以後は通常の式相当 |
置換 |
|
|
以後は通常の式相当 |
in-place 簡約 |
|
|
保持式のみ簡約,整数変数のメタは保たれる |
代入 |
|
|
同じ型 |
注意:
vi += 1等の式変更系を呼んだ後,静的な型は引き続きqbpp::Exprですが内部状態は通常の式相当です.vi.min_val()等の整数変数固有 accessor は runtime error になります.
2. 制約式
生成
構文 |
戻り値 |
意味 (penalty / body) |
|---|---|---|
|
|
penalty = |
|
|
penalty = |
ここで f は整数変数以外の式 (Var, Term, Expr, 整数変数 Expr).
使える演算・関数
カテゴリ |
例 |
戻り値 |
備考 |
|---|---|---|---|
単項 |
|
|
penalty を反転 |
算術 (右辺 Expr) |
|
|
|
算術 (右辺 制約式) |
|
|
penalty 同士 |
グローバル関数 |
|
|
penalty に適用 |
body 取得 |
|
|
clone |
解での評価 |
|
|
制約満足度の検証に使用 |
複合代入 |
|
|
以後は通常の式相当(body 参照不可に) |
二乗 |
|
|
以後は通常の式相当 |
置換 |
|
|
以後は通常の式相当 |
in-place 簡約 |
|
|
penalty と body を同時に簡約,制約式のまま |
代入 |
|
|
同じ型 |
注意:
ee += 1等の式変更系を呼ぶと penalty のみが更新され body は参照できなくなります.一方ee.simplify*()は penalty と body 両方に同じ rule を適用するため,制約式の整合性が保たれます.
Python との挙動の違い: Python では
+=等の複合代入は silent rebind (新しいExprに再束縛).一方 C++ は同じ object の内部状態が通常の式相当に変わります.詳細は Hi-QUBO (C++) と PyQBPP (Python) の違い を参照.
3. ネイティブ制約 (cons)
比較や制約式を qbpp::cons() で囲むと,ネイティブ制約として宣言された式になります.
宣言された制約は制約として特別に処理され,バンドルされたソルバーは制約を満たすように効率よく探索します.
詳細はネイティブ制約を参照してください.
生成
構文 |
意味 |
|---|---|
|
等式制約 |
|
片側制約 |
|
両側の範囲制約 |
|
離散許容値集合( |
|
要素ごとに1本の制約 |
|
重み |
|
|
演算・関数
制約宣言を含む式 f に対して:
例 |
戻り値 |
説明 |
|---|---|---|
|
|
制約宣言を含むか |
|
|
ソルバーが報告する Energy と一致(目的関数+ペナルティ) |
|
|
解 |
|
表示用ビュー |
|
|
リスト |
各制約の値・境界・違反量・重みを報告 |
|
|
全制約を充足しているか |
|
|
目的関数と制約の両方を簡約,宣言は維持 |
|
|
変数置換,宣言は維持 |
|
|
従来のペナルティ式に展開(宣言は消える) |
|
— |
宣言を壊す演算は明示的に runtime error |
4. グローバル関数: 新しい Expr を返す
整数変数・制約式を引数に取れる主要なグローバル関数.いずれも引数を変更せず,新しい qbpp::Expr を返します:
関数 |
戻り値 |
説明 |
|---|---|---|
|
|
|
|
|
同類項マージ |
|
|
binary (0/1) ルールで簡約 |
|
|
spin (±1) ルールで簡約 |
|
|
変数置換 |
|
|
ネイティブ制約として宣言 |
|
|
宣言された制約をペナルティ式に展開 |
引数 x は Var, Term, 任意の顔の Expr のいずれでも OK (内部では Expr として扱われる).
5. 配列版
整数変数の配列および制約式の配列も同じ性質:
算術では各要素が
Exprとして扱われる → 結果はArray<Dim, Expr>in-place mutator (
+=,*=等) は使えるが,要素ごとに上記と同じく通常の式相当に戻る
// 整数変数の配列
auto x = 0 <= qbpp::var_int("x", 3) <= 7; // Array<1, Expr> の整数変数配列
auto sum = qbpp::sum(x); // Expr (各要素を Expr として合計)
// 制約式の配列 (要素ごとの制約)
auto m = qbpp::var("m", 3, 4); // Array<2, Var>
auto rows = qbpp::vector_sum(m, 0); // Array<1, Expr> (各行の和)
auto onehot = (rows == 1); // Array<1, Expr> の制約式
auto penalty = qbpp::sum(onehot); // Expr (全制約の合計)
要素ごとの body アクセスは qbpp::Expr(arr[i]).body().
関連ページ
pyqbpp.Expr は通常の式・整数変数・制約式を 統一的に表現する型 です.3 つとも同じ型で,持つメタデータが違うだけです.
Expr は 3 つの「顔」を持ちます:
通常の式 (多項式):
x + 2*y*zなどの算術式整数変数:
qbpp.var("x", between=(0, 10))で作ったExpr制約式:
qbpp.constrain(e, equal=5)などで作ったExpr
基本原則
pyqbpp.Exprの演算・関数はすべて,どの「顔」の Expr にも適用できる固有 accessor (
min_val,body等) は対応する「顔」の Expr でのみ有効.合わない Expr で呼ぶと runtime abort式を変更するメソッド (
+=,-=,*=,/=,//=,sqr(),replace()) を呼ぶと,内部表現は通常の式に戻る(固有メタデータは破棄)例外:
simplify*()は固有メタデータを保ったまま簡約
e.is_varint()/e.is_exprexpr()で現在の「顔」を実行時に確認できる
1. 整数変数
このページの整数変数は,複数のバイナリ変数に展開されるものです.
整数値をそのまま保持するネイティブ整数変数(IntVar)は
Expr とは別の型で,リファレンスは変数と式にあります.
cons() の制約式には,どちらの整数変数も使えます.
生成
構文 |
戻り値 |
|---|---|
|
|
|
整数変数 |
|
多次元の整数変数配列 |
|
placeholder の整数変数配列 (各要素を後から代入) |
演算・関数
カテゴリ |
例 |
戻り値 |
備考 |
|---|---|---|---|
単項 |
|
|
|
算術 (右辺 Expr 系) |
|
|
|
算術 (右辺 整数変数) |
|
|
|
制約 (等値) |
|
|
制約生成 |
制約 (範囲) |
|
|
範囲制約 |
グローバル関数 |
|
|
|
整数変数固有メタ情報 |
|
各種 |
read-only |
整数変数固有構造 |
|
各種 |
read-only |
配列プロパティ |
|
|
read-only |
Expr 取得 |
|
|
|
複合代入 |
|
( |
以後整数変数固有 accessor は使えなくなる |
二乗 |
|
( |
|
置換 |
|
( |
|
in-place 簡約 |
|
|
保持式のみ簡約,整数変数のメタは保たれる |
代入 |
|
(再束縛) |
Python の通常の代入 |
注意:
vi += 1等を呼んだ後,Python の型は引き続きExprですが内部状態は通常の式相当です.vi.min_val等の整数変数固有 accessor は runtime error になります.
2. 制約式
生成
構文 |
戻り値 |
意味 (penalty / body) |
|---|---|---|
|
|
penalty = |
|
|
penalty = between, body = |
|
|
|
|
|
|
f は整数変数以外の式 (Var, Term, Expr, 整数変数 Expr),n, l, u は整数.
演算・関数
カテゴリ |
例 |
戻り値 |
備考 |
|---|---|---|---|
単項 |
|
|
penalty を反転 |
算術 (右辺 Expr 系) |
|
|
|
算術 (右辺 制約式) |
|
|
penalty 同士 |
グローバル関数 |
|
|
penalty に適用 |
プロパティ |
|
|
clone |
解での評価 |
|
|
制約満足度の検証 |
複合代入 |
|
( |
body は参照不可に |
二乗 |
|
( |
|
置換 |
|
( |
|
in-place 簡約 |
|
|
penalty と body を同時に簡約,制約式のまま |
代入 |
|
(再束縛) |
Python の通常の代入 |
注意:
ee += 1等の式変更系を呼ぶと penalty のみが更新され body は参照できなくなります.ee.simplify*()は penalty と body 両方に同じ rule を適用するため,制約式の整合性が保たれます.
3. ネイティブ制約 (cons)
制約を qbpp.cons() で作成すると,ネイティブ制約として宣言された式になります.
宣言された制約は制約として特別に処理され,バンドルされたソルバーは制約を満たすように効率よく探索します.
詳細はネイティブ制約を参照してください.
生成
構文 |
意味 |
|---|---|
|
等式制約 |
|
離散許容値集合( |
|
範囲制約(片側は |
|
|
|
要素ごとに1本の制約 |
|
重み |
|
|
演算・関数
制約宣言を含む式 f に対して:
例 |
戻り値 |
説明 |
|---|---|---|
|
|
制約宣言を含むか |
|
|
ソルバーが報告する Energy と一致(目的関数+ペナルティ) |
|
|
解 |
|
|
宣言済み制約リストの文字列( |
|
|
各制約の値・境界・違反量・重みを報告 |
|
|
全制約を充足しているか |
|
|
目的関数と制約の両方を簡約,宣言は維持 |
|
|
変数置換,宣言は維持 |
|
|
従来のペナルティ式に展開(宣言は消える) |
|
— |
宣言を壊す演算は明示的に runtime error |
4. グローバル関数: 新しい Expr を返す
整数変数・制約式を引数に取れる主要なグローバル関数.いずれも引数を変更せず,新しい pyqbpp.Expr を返します:
関数 |
戻り値 |
説明 |
|---|---|---|
|
|
|
|
|
同類項マージ |
|
|
binary (0/1) ルールで簡約 |
|
|
spin (±1) ルールで簡約 |
|
|
変数置換 |
|
|
等値制約 |
|
|
範囲制約 |
|
|
ネイティブ制約として宣言 |
|
|
宣言された制約をペナルティ式に展開 |
引数 x は Var, Term, 任意の顔の Expr のいずれでも OK (内部では Expr として扱われる).
5. 配列版
整数変数・制約式の配列も同じ規則:
算術では各要素が
Exprとして扱われる → 結果はExpr配列in-place mutator (
+=,*=等) も使えるが,要素ごとに上記と同じく通常の式相当に戻る
# 整数変数の配列
x = qbpp.var("x", shape=3, between=(0, 7)) # 整数変数 Expr の配列
sum_expr = qbpp.sum(x) # Expr
f = qbpp.sqr(sum_expr - 5) # Expr
# 制約式の配列 (要素ごとの制約)
m = qbpp.var("m", shape=(3, 4)) # 2D Var 配列
rows = qbpp.vector_sum(m, axis=0) # 各行の和 (Expr 配列)
onehot = qbpp.constrain(rows, equal=1) # 制約式 Expr の配列
penalty = qbpp.sum(onehot) # Expr (全制約の合計)
要素ごとの body アクセスは arr[i].body.
6. C++ 版との差異
C++ / Python とも += 等の式変更操作は許可されますが,その後の挙動が異なります:
C++: 同じ object の内部状態が通常の式相当に変わる.固有 accessor 呼出は runtime error
Python: 同じオブジェクトの中身が変わる.Python の object identity は保たれるが,固有 accessor は同じく runtime error
関連ページ
整数変数と連立方程式の求解 —
qbpp.var(..., between=...)とqbpp.constrain(...)を使った例比較制約 —
qbpp.constrain(f, equal=n)による制約生成ネイティブ制約 —
qbpp.cons()の詳細な使い方とソルバーごとの意味論置換関数 —
qbpp.replace(...)の使用例