Hi-QUBO

式の評価

qbpp::Maplist を使用した評価

式の評価は、変数とその値のペアのリストとして、すべての要素に値を割り当てることで簡単に実行できます。 リストqbpp::MapListはオブジェクトとして定義できます。 たとえば、次のプログラムは $(x,y,z)=(0,1,1)$ に対する関数 $f(x,y,z)$ を計算します。

#include "qbpp.hpp"

int main() {
  auto x = qbpp::var("x");
  auto y = qbpp::var("y");
  auto z = qbpp::var("z");
  auto f = qbpp::sqr(x + 2 * y + 3 * z - 3);
  qbpp::MapList ml;
  ml.push_back({x, 0});
  ml.push_back({y, 1});
  ml.push_back({z, 1});
  std::cout << ml << std::endl;
  std::cout << "f(0,1,1) = " << f(ml) << std::endl;
}

このプログラムでは、 qbpp::MapList オブジェクト ml が定義され、 値の割り当て {x, 0}, {y, 1}{z, 1} が追加されます。 ml。 次に f(ml) $f(0,1,1)$の値を返す。 このプログラムは以下の出力を表示する:

{{x,0},{y,1},{z,1}}
f(0,1,1) = 4

あるいは、次のように直接代入を指定することもできます:

#include "qbpp.hpp"

int main() {
  auto x = qbpp::var("x");
  auto y = qbpp::var("y");
  auto z = qbpp::var("z");
  auto f = qbpp::sqr(x + 2 * y + 3 * z - 3);
  std::cout << "f(0,1,1) = " << f({{x, 0}, {y, 1}, {z, 1}}) << std::endl;
}

qbpp::Sol を使用した評価

ソリューションオブジェクト (qbpp::Sol) を使用して式 (qbpp::Expr) の値を評価できます。 これを行うには、まず qbpp::Sol オブジェクト sol を構築します f。 新しく作成されたqbpp::Sol オブジェクトは、すべてゼロの代入で初期化されます。

sol のset()メンバ関数 qbpp::Solを使用すると、個々の変数に値を代入できます。 その後、solに格納された代入条件のもとで、f式の評価値をsol(f)f(sol)solおよびsolが返します。 さらに、solcomp_energy()のメンバ関数は同じ値を計算して返します。

#include "qbpp.hpp"

int main() {
  auto x = qbpp::var("x");
  auto y = qbpp::var("y");
  auto z = qbpp::var("z");
  auto f = qbpp::sqr(x + 2 * y + 3 * z - 3);
  qbpp::Sol sol(f);
  sol.set(y, 1);
  sol.set(z, 1);
  std::cout << "f(0,1,1) = " << f(sol) << std::endl;
  std::cout << "f(0,1,1) = " << sol(f) << std::endl;
  std::cout << "f(0,1,1) = " << sol.comp_energy() << std::endl;
}

なお、ソリューションオブジェクトのメンバcomp_energy()関数 sol はエネルギー値を計算し内部でキャッシュします。 また、ソルバーから返される解オブジェクトは既にエネルギー値が計算・キャッシュ済みです。 再計算せずにエネルギーを取得するには、以下に示すメンバー関数を使用できますenergy():

#include "qbpp.hpp"
#include "qbpp_easy_solver.hpp"

int main() {
  auto x = qbpp::var("x");
  auto y = qbpp::var("y");
  auto z = qbpp::var("z");
  auto f = qbpp::sqr(x + 2 * y + 3 * z - 4);
  f.simplify_as_binary();
  auto solver = qbpp::easy_solver::EasySolver(f);
  solver.target_energy(0);
  auto sol = solver.search();
  std::cout << "sol = " << sol << std::endl;
  std::cout << "energy = " << sol.energy() << std::endl;
  sol.flip(z);
  std::cout << "flipped sol = " << sol << std::endl;
  std::cout << "flipped energy = " << sol.energy() << std::endl;
}

このプログラムでは、 sol.energy() は正しく 0 を返します。 しかし、変数 zを反転させた後、キャッシュされたエネルギー値は無効になります。 エネルギーを再計算せずに sol.energy() を呼び出すと、以下に示すようにランタイムエラーが発生します:

sol = 0:{{x,1},{y,0},{z,1}}
energy = 0
terminate called after throwing an instance of 'std::runtime_error'

この問題を解決するには、ソリューションを変更した後、sol.comp_energy()以下のように明示的にエネルギーを再計算する必要があります:

  std::cout << "sol = " << sol << std::endl;
  std::cout << "energy = " << sol.energy() << std::endl;
  sol.flip(z);
  std::cout << "sol.comp_energy() = " << sol.comp_energy() << std::endl;
  std::cout << "flipped sol = " << sol << std::endl;
  std::cout << "flipped energy = " << sol.energy() << std::endl;

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

sol = 0:{{x,1},{y,0},{z,1}}
energy = 0
sol.comp_energy() = 9
flipped sol = 9:{{x,1},{y,0},{z,0}}
flipped energy = 9

最終更新日: 2026.01.07