QUBO++ Library with QUBO Solver APIs
Author: Koji Nakano, License: Non-commercial research and evaluation purposes without any guarantees.
qbpp_multiplier.hpp
Go to the documentation of this file.
1 
7 #ifndef QBPP_MULTIPLIER_HPP
8 #define QBPP_MULTIPLIER_HPP
9 
10 #include "qbpp.hpp"
11 
12 namespace qbpp {
14 namespace factorization {
15 
26 inline Expr and_gate(const Expr &a, const Expr &b, Var x, MapList &opt_sol) {
27  opt_sol.push_back({x, eval(a, opt_sol) & eval(b, opt_sol)});
28  return a * b - 2 * a * x - 2 * b * x + 3 * x;
29 }
30 
43 inline Expr half_adder(const Expr &x, const Expr &y, Var s, Var c,
44  MapList &opt_sol) {
45  auto val_x = eval(x, opt_sol);
46  auto val_y = eval(y, opt_sol);
47  opt_sol.push_back({s, val_x ^ val_y});
48  opt_sol.push_back({c, val_x & val_y});
49  return s + x + y + 4 * c - 4 * c * x - 4 * c * y - 2 * s * x - 2 * s * y +
50  2 * x * y + 4 * c * s;
51 }
52 
66 inline Expr full_adder(const Expr &x, const Expr &y, const Expr &z, Var s,
67  Var c, MapList &opt_sol) {
68  auto val_x = eval(x, opt_sol);
69  auto val_y = eval(y, opt_sol);
70  auto val_z = eval(z, opt_sol);
71  opt_sol.push_back({s, val_x ^ val_y ^ val_z});
72  opt_sol.push_back({c, (val_x & val_y) | (val_y & val_z) | (val_z & val_x)});
73  return s + x + y + z + 4 * c - 4 * c * x - 4 * c * y - 4 * c * z - 2 * s * x -
74  2 * s * y - 2 * s * z + 2 * x * y + 2 * x * z + 2 * y * z + 4 * c * s;
75 }
76 
94 template <typename T, typename U>
96  const qbpp::Vector<Var> &s, const qbpp::Vector<Var> &c,
97  MapList &opt_sol) {
98  size_t n = x.size();
99  if (n != y.size() || n != s.size() || n != c.size()) {
100  throw std::runtime_error("Invalid input size");
101  }
102  Expr expr = half_adder(x[0], y[0], s[0], c[0], opt_sol);
103  for (size_t i = 1; i < x.size(); i++) {
104  expr += full_adder(x[i], y[i], c[i - 1], s[i], c[i], opt_sol);
105  }
106  return expr;
107 }
108 
121 template <typename T, typename U>
123  const qbpp::Vector<Var> &z, MapList &opt_sol) {
124  int Xsize = static_cast<int>(x.size());
125  int Ysize = static_cast<int>(y.size());
126  int Zsize = static_cast<int>(z.size());
127  if (Xsize + Ysize != Zsize) {
128  throw std::runtime_error("Invalid input size");
129  }
130 
131  // The resulting QUBO expression is stored in expr.
132  Expr expr;
133 
134  // Creates variable array p of size Ysize * Xsize
135  auto p = var("p", Ysize, Xsize);
136  // Takes minimum value 0 if p[i][j] = y[i] * x[j].
137  for (int i = 0; i < Ysize; i++)
138  for (int j = 0; j < Xsize; j++) {
139  expr += and_gate(y[i], x[j], p[i][j], opt_sol);
140  }
141  // Creates variable array s of size Ysize - 1 * Xsize
142  // s is the output s of a half/full adder in an Xsize-bit adder
143  // Each s[i] is a vector of the output s of the i-th adder.
144  auto s = var("s", Ysize - 1, Xsize);
145  // Creates variable array c of size Ysize * Xsize
146  // c is the output c of a half/full adder in an Xsize-bit adder
147  // Each c[i] is a vector of the output c of the i-th adder.
148  auto c = var("c", Ysize, Xsize);
149 
150  // Temporary vector P of variables to be given to the 0-th adder
151  qbpp::Vector<Expr> P(p[0].begin() + 1, p[0].end());
152  P.emplace_back(0);
153 
154  // QUBO expression for the 0-th adder
155  expr += adder(P, p[1], s[0], c[0], opt_sol);
156  // QUBO expression for the i-th adder (1 <= i < Ysize - 1)
157  for (int i = 1; i < Ysize - 1; ++i) {
158  qbpp::Vector<Expr> S(s[i - 1].begin() + 1, s[i - 1].end());
159  S.emplace_back(c[i - 1][Xsize - 1]);
160  expr += adder(p[i + 1], S, s[i], c[i], opt_sol);
161  }
162 
163  // p[0][0] is replaced by z[0]
164  MapList map = {{p[0][0], z[0]}};
165  // s[1][0], s[2][0],..., s[Ysize - 2][0] are replaced by z[1],
166  // z[2],...,z[Ysize - 2]
167  for (int i = 1; i < Ysize; ++i) {
168  map.push_back({s[i - 1][0], z[i]});
169  }
170  // s[Ysize - 2][1], s[Ysize - 2][2],..., s[Ysize - 2][Xsize - 1] are replaced
171  // by z[Ysize - 1], z[Ysize],...,z[Xsize + Ysize - 2]
172  for (int j = 1; j < Xsize; ++j) {
173  map.push_back({s[Ysize - 2][j], z[j + Ysize - 1]});
174  }
175  // c[Ysize - 2][Xsize - 1] is replaced by z[Xsize + Ysize - 1]
176  map.push_back({c[Ysize - 2][Xsize - 1], z[Xsize + Ysize - 1]});
177 
178  // Replacement is performed and then simplified as a binary expression.
180 
181  return expr;
182 }
183 } // namespace factorization
184 } // namespace qbpp
185 
186 #endif
Expr & simplify_as_binary()
Definition: qbpp.hpp:1956
Expr & replace(const MapList &map_list)
Definition: qbpp.hpp:2045
void emplace_back(T &&t)
Definition: qbpp.hpp:377
void push_back(const T &t)
Definition: qbpp.hpp:375
size_t size() const
Definition: qbpp.hpp:385
Expr and_gate(const Expr &a, const Expr &b, Var x, MapList &opt_sol)
Function to generate a QUBO expression Expr object for the AND gate.
Expr multiplier(const qbpp::Vector< T > &x, const qbpp::Vector< U > &y, const qbpp::Vector< Var > &z, MapList &opt_sol)
Function to generate QUBO expression for multiplier.
Expr adder(const qbpp::Vector< T > &x, const qbpp::Vector< U > &y, const qbpp::Vector< Var > &s, const qbpp::Vector< Var > &c, MapList &opt_sol)
function to generate QUBO expression for n-bit adder
Expr half_adder(const Expr &x, const Expr &y, Var s, Var c, MapList &opt_sol)
Function to generates a QUBO expression Expr object for the Half Adder.
Expr full_adder(const Expr &x, const Expr &y, const Expr &z, Var s, Var c, MapList &opt_sol)
Function to generate a QUBO expression Expr object for the Full Adder.
Generates a QUBO Expression for the Graph Coloring Problem using QUBO++ library.
Definition: qbpp.hpp:53
Var var(const std::string &var_str)
Definition: qbpp.hpp:2172
energy_t eval(const Expr &expr, const Sol &sol)
Definition: qbpp.hpp:2109
Expr expr()
Definition: qbpp.hpp:2318
std::list< std::pair< std::variant< Var, VarInt >, Expr > > MapList
Definition: qbpp.hpp:134
QUBO++, a C++ library for generating expressions for binary and spin variables.