# 変数と式の定義
:::{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)は否定リテラルをネイティブに処理するため,求解前に展開する必要はありません.
:::