# 変数と式の定義 :::{container} prog-cpp ## ヘッダファイルと名前空間 Hi-QUBOを使用するには,ヘッダファイル **`qbpp/qbpp.hpp`** をインクルードし,**`qbpp`** 名前空間を使用します. ## 変数と式の定義 変数は **`qbpp::var("name")`** を `auto` 型推論とともに使用して定義できます. 指定した `name` は,変数を `std::cout` で出力する際に使用されます. 式は **`+`**,**`-`**,**`*`** などの標準的な算術演算子を使って構築します. 以下のサンプルプログラムでは,3つの変数 `a`,`b`,`c` と式 `f` を定義し,`std::cout` を使って出力しています. ```{literalinclude} /../programFiles/cppPrograms/basic/variables-and-expressions-program1.cpp :language: cpp :caption: variables-and-expressions-program1.cpp ``` 式 `(a + b - 1) * (b + c - 1)` は自動的に展開され,`f` に格納されます. このHi-QUBOプログラムでは,変数 `a`,`b`,`c` は **`qbpp::Var`** クラスのオブジェクトであり,式 `f` は **`qbpp::Expr`** クラスのオブジェクトです. ヘッダとライブラリのパスが適切に設定されていれば,このプログラム(**`test.cpp`** として保存)は `g++` で以下のようにコンパイルできます. ```{include} /../programFiles/markDown/basic/variables-and-expressions.md :start-after: :end-before: ``` 実行すると,展開された式が出力されます. ```{include} /../programFiles/markDown/basic/variables-and-expressions.md :start-after: :end-before: ``` > **注意** > `qbpp::var()` の変数名は省略可能です. > 省略した場合,`{0}`,`{1}` などのデフォルト名が自動的に割り当てられます. > **WARNING** > `qbpp::Expr` をはじめとするHi-QUBOのほとんどのクラスインスタンスは,`std::cout` を使ってテキストとして出力できます. > ただし,このテキスト出力は安定性が保証されておらず,フォーマットが将来のリリースで変更される可能性があるため,後続の計算の入力として使用すべきではありません. > また,Hi-QUBOドキュメントに示されている出力は古いバージョンで生成されたものである可能性があり,最新バージョンの出力とは異なる場合があります. ## 式の簡約化 **`qbpp::Expr`** オブジェクトに格納された式は,**`simplify()`** メンバ関数を呼び出すことで簡約化できます. ```{include} /../programFiles/markDown/basic/variables-and-expressions.md :start-after: :end-before: ``` この変更により,プログラムの出力は以下のようになります. ```{include} /../programFiles/markDown/basic/variables-and-expressions.md :start-after: :end-before: ``` メンバ関数 **`f.simplify()`** は式 `f` を簡約化し,結果の値を返します.その値が `std::cout` によって出力されます. すべての変数が **2値(0または1)** をとると仮定すると,恒等式 **$b^2=b$** を使って式をさらに簡約化できます. この目的には,代わりに **`simplify_as_binary()`** を使用します. ```{include} /../programFiles/markDown/basic/variables-and-expressions.md :start-after: :end-before: ``` 出力は以下のようになります. ```{include} /../programFiles/markDown/basic/variables-and-expressions.md :start-after: :end-before: ``` 簡約化関数は,各項内の変数と式内の項を並べ替え,低次の項が先に表示されるようにし,同じ次数の項は変数の辞書順でソートします. 変数自体は定義された順序で並べられます. ## スピン変数による式の簡約化 変数が **スピン値 $-1$/$+1$** をとると仮定する場合,恒等式 **$b^2 = 1$** を使って式をさらに簡約化できます. この場合,**`simplify_as_spin()`** メンバ関数を使用して式を簡約化します. ```{include} /../programFiles/markDown/basic/variables-and-expressions.md :start-after: :end-before: ``` 出力は以下のようになります. ```{include} /../programFiles/markDown/basic/variables-and-expressions.md :start-after: :end-before: ``` ## 簡約化のためのグローバル関数 メンバ関数は `f` に格納された式を更新します. `f` を変更したくない場合は,代わりにグローバル関数 **`qbpp::simplify(f)`**,**`qbpp::simplify_as_binary(f)`**,**`qbpp::simplify_as_spin(f)`** を使用できます.これらは `f` を変更せずに簡約化された式を返します. > **注意** > Hi-QUBOでは,ほとんどの **メンバ関数** はオブジェクトをその場で更新しますが,**グローバル関数** は元のオブジェクトを変更せずに新しい値を返します. ## 否定リテラル Hi-QUBOは `~` 演算子を使った **否定リテラル** をネイティブにサポートしています. 2値変数 `x` に対して,式 `~x` は $1 - x$ を表します. ```{literalinclude} /../programFiles/cppPrograms/basic/variables-and-expressions-program2.cpp :language: cpp :caption: variables-and-expressions-program2.cpp ``` 出力: ```{include} /../programFiles/markDown/basic/variables-and-expressions.md :start-after: :end-before: ``` 否定リテラル `~x` は,`1 - x` として展開されるのではなく,否定フラグを持つ単一の変数として内部的に格納されます. これはパフォーマンスにとって重要です.`~x` を単純に展開すると,`~x1 * ~x2 * ... * ~xk` のような $k$ 個の否定リテラルの積は,$(1-x_1)(1-x_2)\cdots(1-x_k)$ を展開した後に最大 $2^k$ 個の項を生成します. 例えば,上記の項 `~a*~b*~c*~d` は単一の4次項として格納されますが,展開形 $(1-a)(1-b)(1-c)(1-d)$ は16個の項を生成します. ```{include} /../programFiles/markDown/basic/variables-and-expressions.md :start-after: :end-before: ``` Hi-QUBOに同梱されているすべてのソルバー(EasySolver,ExhaustiveSolver,ABS3 GPU Solver)は否定リテラルをネイティブに処理するため,求解前に展開する必要はありません. ::: :::{container} prog-python ## PyQBPPのインストール PyQBPPを使用するには,pipでインストールしてください: ```{include} /../programFiles/markDown/basic/variables-and-expressions.md :start-after: :end-before: ``` ## ライブラリのインポート PyQBPPを使用するには,**`pyqbpp`**モジュールをインポートします: ```{literalinclude} /../programFiles/pythonPrograms/basic/variables-and-expressions-program1.py :language: python :caption: variables-and-expressions-program1.py ``` ## 変数と式の定義 変数は**`qbpp.var("name")`**を使って定義できます. 指定した`name`は変数を表示する際に使用されます. 式は**`+`**,**`-`**,**`*`**などの標準的な算術演算子を使って構築します. 以下のプログラムは,3つの変数`a`,`b`,`c`と式`f`を定義し,表示します: ```{literalinclude} /../programFiles/pythonPrograms/basic/variables-and-expressions-program2.py :language: python :caption: variables-and-expressions-program2.py ``` 式`(a + b - 1) * (b + c - 1)`は自動的に展開され,`f`に格納されます. このプログラムでは,`a`,`b`,`c`は変数であり,`f`は式です. プログラムを実行すると,展開された式が表示されます: ```{include} /../programFiles/markDown/basic/variables-and-expressions.md :start-after: :end-before: ``` > **注釈** > `qbpp.var()`の変数名は省略可能です. > 省略した場合,`{% raw %}{0}{% endraw %}`,`{% raw %}{1}{% endraw %}`,...のようなデフォルト名が自動的に割り当てられます. > **注意** > 式をはじめとするPyQBPPのほとんどのオブジェクトは,`print()`を使ってテキストとして出力できます. > ただし,このテキスト出力は安定性が保証されておらず,フォーマットが将来のリリースで変更される可能性があるため,後続の計算の入力として使用すべきではありません. > また,PyQBPPドキュメントに示されている出力は古いバージョンで生成されたものである可能性があり,最新バージョンの出力とは異なる場合があります. バイナリ変数の配列については [配列](../basic/vector-variables-and-functions.md),多次元配列については [多次元変数](../advanced/multi-dimensional-variables-and-expressions.md),整数変数については [整数変数](../basic/integer-variables-and-linear-systems.md) を参照してください. ## 式の簡約化 `f`に格納された式は,**`simplify()`**メンバ関数を呼び出すことで簡約化できます: ```{include} /../programFiles/markDown/basic/variables-and-expressions.md :start-after: :end-before: ``` この変更により,プログラムの出力は以下のようになります: ```{include} /../programFiles/markDown/basic/variables-and-expressions.md :start-after: :end-before: ``` メンバ関数呼び出し**`f.simplify()`**は式`f`をその場で簡約化し,自身を返します.その値が出力されます. ## バイナリ変数による式の簡約化 すべての変数が**バイナリ値(0または1)**を取ると仮定すると,恒等式**$b^2=b$**を使って式をさらに簡約化できます. この目的には,代わりに**`simplify_as_binary()`**を使用します: ```{include} /../programFiles/markDown/basic/variables-and-expressions.md :start-after: :end-before: ``` すると出力は以下のようになります: ```{include} /../programFiles/markDown/basic/variables-and-expressions.md :start-after: :end-before: ``` 簡約化関数は,各項内の変数と式内の項を並べ替え,低次の項が先に表示されるようにし,同じ次数の項は変数の辞書順でソートします. 変数自体は定義された順序で並べられます. ## スピン変数による式の簡約化 変数が**スピン値 $-1$/$+1$**を取ると仮定する場合,恒等式**$b^2 = 1$**を使って式をさらに簡約化できます. この場合,**`simplify_as_spin()`**メンバ関数を使って式を簡約化できます: ```{include} /../programFiles/markDown/basic/variables-and-expressions.md :start-after: :end-before: ``` すると出力は以下のようになります: ```{include} /../programFiles/markDown/basic/variables-and-expressions.md :start-after: :end-before: ``` ## 簡約化のためのグローバル関数 メンバ関数は`f`に格納された式を更新します. `f`を変更したくない場合は,代わりにグローバル関数**`qbpp.simplify(f)`**,**`qbpp.simplify_as_binary(f)`**,**`qbpp.simplify_as_spin(f)`**を使用できます.これらは`f`を変更せずに簡約化された式を返します. ```{literalinclude} /../programFiles/pythonPrograms/basic/variables-and-expressions-program3.py :language: python :caption: variables-and-expressions-program3.py ``` > **注釈** > PyQBPPでは,ほとんどの**式オブジェクトに関するメンバ関数**は処理結果でオブジェクト更新しますが,**グローバル関数**は元のオブジェクトを変更せずに新しい値を返します. ## 否定リテラル PyQBPPは`~`演算子を使った**否定リテラル**をネイティブにサポートしています. バイナリ変数`x`に対して,式`~x`は$1 - x$を表します. ```{literalinclude} /../programFiles/pythonPrograms/basic/variables-and-expressions-program4.py :language: python :caption: variables-and-expressions-program4.py ``` 出力: ```{include} /../programFiles/markDown/basic/variables-and-expressions.md :start-after: :end-before: ``` 否定リテラル`~x`は,`1 - x`として展開されるのではなく,否定フラグを持つ単一の変数として内部的に格納されます. これはパフォーマンスにとって重要です.`~x`を単純に展開すると,`~x1 * ~x2 * ... * ~xk`のような$k$個の否定リテラルの積は,$(1-x_1)(1-x_2)\cdots(1-x_k)$を展開した後に最大$2^k$個の項を生成します. 例えば,上記の項`~a*~b*~c*~d`は単一の4次項として格納されますが,展開形$(1-a)(1-b)(1-c)(1-d)$は16個の項を生成します: ```{include} /../programFiles/markDown/basic/variables-and-expressions.md :start-after: :end-before: ``` PyQBPPに同梱されているすべてのソルバー(EasySolver,ExhaustiveSolver,ABS3 GPU Solver)は否定リテラルをネイティブに処理するため,求解前に展開する必要はありません. :::