基本演算子と関数

単項演算子および二項演算子

Hi-QUBO は、式(すなわち qbpp::Expr オブジェクト)を構築するために、次の基本的な二項演算子をサポートしています。

  • + : オペランドの和を返します。

  • - : オペランドの差を返します。

  • * : オペランドの積を返します。

  • / : オペランドの商を返します。除数は整数でなければなりません。また、被除数の定数項およびすべての係数が除数で割り切れる必要があります。

  • 単項 - : オペランドの符号を反転した値を返します。

これらの演算子の優先順位は、標準的な C++ の演算子優先順位規則に従います。

次のプログラムは、これらの演算子を用いて式を構築する方法を示しています。

basic-operators-and-functions-program1.cpp
#include <qbpp/qbpp.hpp>

int main() {
  auto x = qbpp::var("x");
  auto y = qbpp::var("y");
  auto f = 6 * -(x + 1) * (y - 1);
  auto g = f / 3;

  std::cout << "f = " << f << std::endl;
  std::cout << "g = " << g << std::endl;
}

このプログラムは、次の出力を生成します。

f = 6 -6*x*y +6*x -6*y
g = 2 -2*x*y +2*x -2*y

複合代入演算子

qbpp::Expr オブジェクトを更新するために、次の複合代入演算子もサポートされています。

  • += : 右辺のオペランドを左辺に加算します。

  • -= : 右辺のオペランドを左辺から減算します。

  • *= : 右辺のオペランドを左辺に乗算します。

  • /= : 左辺のオペランドを右辺で除算します。右辺は整数でなければならず、左辺の定数項およびすべての係数が割り切れる必要があります。

次のプログラムは、これらの複合代入演算子を用いて式を構築する方法を示しています。

basic-operators-and-functions-program2.cpp
#include <qbpp/qbpp.hpp>

int main() {
  auto x = qbpp::var("x");
  auto y = qbpp::var("y");
  auto f = 6 * x + 4;

  f += 3 * y;
  std::cout << "f = " << f << std::endl;
  
  f -= 12;
  std::cout << "f = " << f << std::endl;
  
  f *= 2 * y;
  std::cout << "f = " << f << std::endl;
  
  f /= 2;
  std::cout << "f = " << f << std::endl;
}

このプログラムは、次の出力を生成します。

f = 4 +6*x +3*y
f = -8 +6*x +3*y
f = 12*x*y +6*y*y -16*y
f = 6*x*y +3*y*y -8*y

Square 関数

QUBO++は、式の二乗を計算するためのグローバル関数 qbpp::sqr()qbpp::Expr クラスのメンバ関数 sqr() の両方を提供しています。

以下のプログラムでは、qbpp::Expr オブジェクトfに対して、グローバル関数 qbpp::sqr(f)f の二乗を表す新しい qbpp::Expr オブジェクトを返し、 一方メンバ関数 f.sqr()f をその場でその二乗に置き換えて更新します。

basic-operators-and-functions-program3.cpp
#include <qbpp/qbpp.hpp>

int main() {
  auto x = qbpp::var("x");
  auto f = x + 1;

  std::cout << "f = " << qbpp::sqr(f) << std::endl;
  std::cout << "f = " << f << std::endl;

  f.sqr();
  std::cout << "f = " << f << std::endl;
}

このプログラムは、次の出力を生成します。

f = 1 +x*x +x +x
f = 1 +x
f = 1 +x*x +x +x

simplify 関数

qbpp::Expr オブジェクトに対して演算子や関数を適用すると、式は自動的に展開されます。項をソートし、結果の式を簡約するには、simplify 関数を明示的に呼び出す必要があります。

Hi=QUBO は、次の3つのグローバルな simplify 関数を提供しています。

  • qbpp::simplify()
    同一項の係数をまとめた簡約式を返します。

  • qbpp::simplify_as_binary()
    すべての変数が2値(0 または 1)をとると仮定して簡約式を返します。すなわち、恒等式 \(x^2=x\) が成り立つと仮定します。

  • qbpp::simplify_as_spin()
    すべての変数がスピン値(-1 または 1)をとると仮定して簡約式を返します。すなわち、恒等式 \(x^2=1\) が成り立つと仮定します。

次のプログラムは、これらの simplify 関数の動作を示しています。

basic-operators-and-functions-program4.cpp
#include <qbpp/qbpp.hpp>

int main() {
  auto x = qbpp::var("x");
  auto f = qbpp::sqr(x - 1);

  std::cout << "f = " << f << std::endl;
  std::cout << "simplified(f) = " << qbpp::simplify(f) << std::endl;
  std::cout << "simplified_as_binary(f) = " << qbpp::simplify_as_binary(f) << std::endl;
  std::cout << "simplified_as_spin(f) = " << qbpp::simplify_as_spin(f) << std::endl;
}

このプログラムは、次の出力を生成します。

f = 1 +x*x -x -x
simplified(f) = 1 -2*x +x*x
simplified_as_binary(f) = 1 -x
simplified_as_spin(f) = 2 -2*x

これらの簡約化関数のメンバ関数版も qbpp::Expr オブジェクトに対して提供されており、オブジェクトをその場で簡約化された結果に更新します。

例えば、次のプログラムでは simplify() を適用して f を更新しています。

basic-operators-and-functions-program5.cpp
#include <qbpp/qbpp.hpp>

int main() {
  auto x = qbpp::var("x");
  auto f = qbpp::sqr(x - 1);
  
  f.simplify();
  std::cout << "f = " << f << std::endl;
}

このプログラムは、次の出力を表示します。

f = 1 -2*x +x*x

PyQBPP は、式を構築するために、次の基本的な二項演算子をサポートしています。

  • + : オペランドの和を返します。

  • - : オペランドの差を返します。

  • * : オペランドの積を返します。

  • / : オペランドの商を返します。除数は整数でなければなりません。また、被除数の定数項およびすべての係数が除数で割り切れる必要があります。

  • 単項 - : オペランドの符号を反転した値を返します。

次のプログラムは、これらの演算子を用いて式を構築する方法を示しています。

basic-operators-and-functions-program1.py
import pyqbpp as qbpp

x = qbpp.var("x")
y = qbpp.var("y")
f = 6 * -(x + 1) * (y - 1)
g = f / 3

print("f =", f)
print("g =", g)

このプログラムは、次の出力を生成します。

f = 6 -6*x*y +6*x -6*y
g = 2 -2*x*y +2*x -2*y

複合代入演算子

Expr オブジェクトを更新するために、次の複合代入演算子もサポートされています。

  • += : 右辺のオペランドを左辺に加算します。

  • -= : 右辺のオペランドを左辺から減算します。

  • *= : 右辺のオペランドを左辺に乗算します。

  • /= : 左辺のオペランドを右辺で除算します。右辺は整数でなければならず、左辺の定数項およびすべての係数が割り切れる必要があります。

次のプログラムは、これらの複合代入演算子を用いて式を構築する方法を示しています。

basic-operators-and-functions-program2.py
import pyqbpp as qbpp

x = qbpp.var("x")
y = qbpp.var("y")
f = 6 * x + 4

f += 3 * y
print("f =", f)

f -= 12
print("f =", f)

f *= 2 * y
print("f =", f)

f /= 2
print("f =", f)

このプログラムは、次の出力を生成します。

f = 4 +6*x +3*y
f = -8 +6*x +3*y
f = 12*x*y +6*y*y -16*y
f = 6*x*y +3*y*y -8*y

Square 関数

PyQBPPは、式の二乗を計算するためのグローバル関数 qbpp.sqr()Expr クラスのメンバ関数 sqr() の両方を提供しています。

以下のプログラムでは、式 f に対して、グローバル関数 qbpp.sqr(f)f を変更せずに f の二乗を表す新しい式を返します。 一方、メンバ関数 f.sqr()f をその場でその二乗に置き換えて更新します。

basic-operators-and-functions-program3.py
import pyqbpp as qbpp

x = qbpp.var("x")
f = x + 1

print("qbpp.sqr(f) =", qbpp.sqr(f))
print("f =", f)

f.sqr()
print("f =", f)

このプログラムは、次の出力を生成します。

f = 1 +x*x +x +x
f = 1 +x
f = 1 +x*x +x +x

simplify 関数

Expr オブジェクトに対して演算子や関数を適用すると、式は自動的に展開されます。項をソートし、結果の式を簡約するには、simplify 関数を明示的に呼び出す必要があります。

PyQBPP は、次の3つのグローバルな simplify 関数を提供しています。

  • qbpp.simplify()
    同一項の係数をまとめた簡約式を返します。

  • qbpp.simplify_as_binary()
    すべての変数が2値(0 または 1)をとると仮定して簡約式を返します。すなわち、恒等式 \(x^2=x\) が成り立つと仮定します。

  • simplify_as_spin()
    すべての変数がスピン値(-1 または 1)をとると仮定して簡約式を返します。すなわち、恒等式 \(x^2=1\) が成り立つと仮定します。

次のプログラムは、これらの simplify 関数の動作を示しています。

basic-operators-and-functions-program4.py
import pyqbpp as qbpp

x = qbpp.var("x")
f = qbpp.sqr(x - 1)

print("f =", f)
print("simplify(f) =", qbpp.simplify(f))
print("simplify_as_binary(f) =", qbpp.simplify_as_binary(f))
print("simplify_as_spin(f) =", qbpp.simplify_as_spin(f))

このプログラムは、次の出力を生成します。

f = 1 +x*x -x -x
simplified(f) = 1 -2*x +x*x
simplified_as_binary(f) = 1 -x
simplified_as_spin(f) = 2 -2*x

注意 PyQBPPでは、メンバ関数(例: f.simplify()f.sqr())はオブジェクトをその場で更新しますが、グローバル関数(例: qbpp.simplify(f)qbpp.sqr(f))は元のオブジェクトを変更せずに新しい値を返します。