Quick Reference: Printing Objects
Note The outputs on this page are shown for reference only. The output format may differ in the latest version. Printed text is meant for people to read and check, so do not use it in computations. When you need a value, get it with functions such as
sol(x)orf(sol)(see Quick Reference: Solutions).
Most QUBO++ objects can be printed to std::cout with the << operator.
std::cout << obj << std::endl;
Overview
| Object | Example of printed text |
|---|---|
Variable qbpp::Var | x, ~x, a[1] |
Term qbpp::Term | 2*x*y |
Expression qbpp::Expr | -4 +3*x -2*y*z +~x |
| Binary-encoded integer variable | v[0] +2*v[1] +2*v[2] |
Native integer variable qbpp::IntVar | n |
| Constraint expression made with a comparison operator | Polynomial of the penalty expression |
Expression with qbpp::cons(), qbpp::abs(), qbpp::relu() | Objective polynomial followed by one item per line |
List of constraints f.cons() | 100 * (x +y +z <= 2) |
Element of f.violations(sol) | {value: 2, lower: 1, upper: 1, violation: 1, weight: 1, satisfied: false} |
Array qbpp::Array | {a[0],a[1],a[2]} |
Solution qbpp::Sol (including solutions returned by solvers) | 0:{{x[0],0},{x[1],0},{x[2],1},{n,3}} |
qbpp::CallbackEvent | CallbackEvent::BestUpdated |
Variables, terms, and expressions
#include <qbpp/qbpp.hpp>
int main() {
auto x = qbpp::var("x");
auto y = qbpp::var("y");
auto z = qbpp::var("z");
auto a = qbpp::var("a", 3);
auto u = qbpp::var();
std::cout << x << std::endl;
std::cout << ~x << std::endl;
std::cout << a[1] << std::endl;
std::cout << u << std::endl;
std::cout << 2 * x * y << std::endl;
qbpp::Expr f = 3 * x - 2 * y * z + ~x - 4;
std::cout << f << std::endl;
}
This program produces the following output:
x
~x
a[1]
{0}
2*x*y
-4 +3*x -2*y*z +~x
- A variable created without a name (
qbpp::var()) is printed as{0},{1}, …. - An expression is printed with the constant term first, followed by the terms in the order they were created. Each term after the first is preceded by a space and its sign (
+or-). - A coefficient of 1 is omitted. A negated literal is printed as
~x.
Before and after simplification
An expression is printed in the form in which it was created; it is not simplified automatically. To see it with like terms combined, simplify it with qbpp::simplify() or qbpp::simplify_as_binary() before printing.
#include <qbpp/qbpp.hpp>
int main() {
auto x = qbpp::var("x");
auto y = qbpp::var("y");
qbpp::Expr g = x * x + x * y + y * x + 1;
std::cout << g << std::endl;
std::cout << qbpp::simplify(g) << std::endl;
std::cout << qbpp::simplify_as_binary(g) << std::endl;
}
This program produces the following output:
1 +x*x +x*y +y*x
1 +x*x +2*x*y
1 +x +2*x*y
qbpp::simplify() combines like terms, and qbpp::simplify_as_binary() additionally uses the property of binary variables (x*x = x).
Integer variables
#include <qbpp/qbpp.hpp>
int main() {
auto x = qbpp::var("x");
auto v = 0 <= qbpp::var_int("v") <= 5;
auto n = 0 <= qbpp::int_var("n") <= 5;
std::cout << v << std::endl;
std::cout << n << std::endl;
qbpp::Expr f = 2 * n + x;
std::cout << f << std::endl;
std::cout << qbpp::binarize(f) << std::endl;
}
This program produces the following output:
v[0] +2*v[1] +2*v[2]
n
2*n +x
2*n#0 +4*n#1 +4*n#2 +x
- A binary-encoded integer variable is printed as an expression of the binary variables (
v[0],v[1], …) that represent its value (see Binary-Encoded Integer Variables). - A native integer variable is printed by its name (see Integer Variables and Solving Simultaneous Equations).
- The binary variables that
qbpp::binarize()substitutes for a native integer variable are printed asn#0,n#1, ….
Auxiliary variables
Variables that QUBO++ adds when it transforms an expression are printed with names in braces.
#include <qbpp/qbpp.hpp>
int main() {
auto x = qbpp::var("x");
auto y = qbpp::var("y");
auto z = qbpp::var("z");
std::cout << qbpp::reduce(x * y * z) << std::endl;
std::cout << qbpp::simplify_as_binary(x + y + z <= 2) << std::endl;
}
This program produces the following output:
{r0} +x*y +x*z -x*{r0} +y*z -y*{r0} -z*{r0}
2*{s1} +2*x*y +2*x*z -2*x*{s1} +2*y*z -2*y*{s1} -2*z*{s1}
- Names starting with
r, such as{r0}: variables thatqbpp::reduce()adds to lower the degree (see Reducing HUBO to QUBO) - Names starting with
s, such as{s1}: slack variables added by constraint expressions made with comparison operators (see Comparison Operators)
The numbers are serial numbers assigned in the order the variables are added.
Constraints and nonlinear functions
Constraint expressions made with comparison operators
A constraint expression made with a comparison operator (==, <=, >=, or a range) is printed as the expanded polynomial of its penalty expression. Because it is printed before simplification, qbpp::simplify_as_binary() makes it shorter.
#include <qbpp/qbpp.hpp>
int main() {
auto x = qbpp::var("x");
auto y = qbpp::var("y");
std::cout << (x + y == 1) << std::endl;
std::cout << qbpp::simplify_as_binary(x + y == 1) << std::endl;
}
This program produces the following output:
1 +x*x -2*x +2*x*y +y*y -2*y
1 -x -y +2*x*y
Expressions with cons(), abs(), and relu()
An expression that contains qbpp::cons(), qbpp::abs(), or qbpp::relu() is printed as the objective polynomial followed by each of these items, one per line, in the form in which it was written.
#include <qbpp/qbpp.hpp>
int main() {
auto x = qbpp::var("x");
auto y = qbpp::var("y");
auto z = qbpp::var("z");
auto f = 3 * x + 100 * qbpp::cons(x + y + z <= 2) + qbpp::cons(x + y == 1);
std::cout << f << std::endl;
std::cout << qbpp::abs(x - y) + qbpp::relu(x + y - 1, 2) << std::endl;
std::cout << qbpp::cons(x + y + z == qbpp::equal{0, 2}) << std::endl;
std::cout << qbpp::cons(1 <= x + y + z <= 2) << std::endl;
std::cout << -5 * qbpp::cons(x + y == 1) << std::endl;
std::cout << qbpp::max(x, y) << std::endl;
}
This program produces the following output:
3*x
+100*cons(x +y +z <= 2)
+cons(x +y == 1)
abs(x -y, 1)
+relu(-1 +x +y, 2)
cons(x +y +z == {0, 2})
cons(1 <= x +y +z <= 2)
-5*cons(x +y == 1)
y
+relu(x -y, 1)
- A weight of 1 is omitted, and a negative weight is shown by the sign at the start of the line. When the objective polynomial is 0, its line is not printed.
- The second number of
abs(f, k)andrelu(f, k)is the exponent (qbpp::abs(f)is printed asabs(f, 1)andqbpp::abs(f, 2)asabs(f, 2)). qbpp::max()andqbpp::min()are printed as equivalent expressions that userelu()orabs().
For details, see Nonlinear Functions and Native Constraints.
List of constraints and violations
f.cons() returns the list of constraints in an expression, and f.violations(sol) returns the value and the amount of violation of each constraint for a solution sol. Both can be printed.
#include <qbpp/qbpp.hpp>
int main() {
auto x = qbpp::var("x");
auto y = qbpp::var("y");
auto z = qbpp::var("z");
auto f = 3 * x + 100 * qbpp::cons(x + y + z <= 2) + qbpp::cons(x + y == 1);
std::cout << f.cons() << std::endl;
qbpp::Sol sol(f);
sol.set(x, 1);
sol.set(y, 1);
for (const auto& v : f.violations(sol)) {
std::cout << v << std::endl;
}
}
This program produces the following output:
100 * (x +y +z <= 2)
(x +y == 1)
{value: 2, lower: 0, upper: 2, violation: 0, weight: 100, satisfied: true}
{value: 2, lower: 1, upper: 1, violation: 1, weight: 1, satisfied: false}
Arrays
#include <qbpp/qbpp.hpp>
int main() {
auto a = qbpp::var("a", 3);
auto b = qbpp::var("b", 2, 3);
auto c = qbpp::array({1, 2, 3});
std::cout << a << std::endl;
std::cout << b << std::endl;
std::cout << b[1] << std::endl;
std::cout << a + 1 << std::endl;
std::cout << c << std::endl;
std::cout << qbpp::vector_sum(b) << std::endl;
}
This program produces the following output:
{a[0],a[1],a[2]}
{{b[0][0],b[0][1],b[0][2]},{b[1][0],b[1][1],b[1][2]}}
{b[1][0],b[1][1],b[1][2]}
{1 +a[0],1 +a[1],1 +a[2]}
{1,2,3}
{b[0][0] +b[0][1] +b[0][2],b[1][0] +b[1][1] +b[1][2]}
- An array is printed with its elements separated by
,and enclosed in{and}. A multi-dimensional array is printed as nested braces. - A subarray such as
b[1]is printed in the same format.
Solutions
#include <qbpp/qbpp.hpp>
#include <qbpp/exhaustive_solver.hpp>
int main() {
auto x = qbpp::var("x", 3);
auto n = 0 <= qbpp::int_var("n") <= 5;
auto f = qbpp::sqr(qbpp::sum(x) - 1) + 3 * x[0] + 2 * x[1] + qbpp::sqr(n - 3);
f.simplify_as_binary();
auto sol = qbpp::ExhaustiveSolver(f).search();
std::cout << sol << std::endl;
std::cout << sol(x) << std::endl;
std::cout << sol(n) << std::endl;
qbpp::Sol s(sol);
s.set(x[0], 1);
s.set(n, 5);
std::cout << s << std::endl;
}
This program produces the following output:
0:{{x[0],0},{x[1],0},{x[2],1},{n,3}}
{0,0,1}
3
8:{{x[0],1},{x[1],0},{x[2],1},{n,5}}
- A solution is printed in the form
energy:{{variable,value},...}. Native integer variables follow the binary variables. - A solution whose values were changed with
sol.set()is printed with the energy computed for that assignment. - The values of solver information such as
sol.info("var_count")are strings (see Quick Reference: Solutions).
Multiple solutions collected by a solver (sol.sols) are printed one at a time.
#include <qbpp/qbpp.hpp>
#include <qbpp/exhaustive_solver.hpp>
int main() {
auto x = qbpp::var("x", 3);
auto f = qbpp::sqr(qbpp::sum(x) - 1) + 3 * x[0] + 2 * x[1];
f.simplify_as_binary();
auto sol = qbpp::ExhaustiveSolver(f).search({{"topk_sols", 3}});
for (const auto& s : sol.sols) {
std::cout << s << std::endl;
}
}
This program produces the following output:
0:{{x[0],0},{x[1],0},{x[2],1}}
1:{{x[0],0},{x[1],0},{x[2],0}}
2:{{x[0],0},{x[1],1},{x[2],0}}
Real coefficients
With real (double) coefficients, enabled by DOUBLE_TYPE and similar macros, each coefficient is printed as the shortest decimal number that represents the original value exactly. If its decimal exponent is at least −4 and less than 16, positional notation is used (2500, 1.5, 0.1); otherwise, scientific notation is used (1e+20, 1e-07). Integer values are printed without a decimal point.
#define DOUBLE_TYPE
#include <qbpp/qbpp.hpp>
int main() {
auto x = qbpp::var("x");
auto y = qbpp::var("y");
auto z = qbpp::var("z");
qbpp::Expr f = 100 * x + 2500 * y + 1.5 * z;
std::cout << f << std::endl;
qbpp::Expr g = 0.1 * x - 1e-7 * y + 1e20 * z;
std::cout << g << std::endl;
}
This program produces the following output:
100*x +2500*y +1.5*z
0.1*x -1e-07*y +1e+20*z
To check the expression with integer coefficients that the solver actually solves, print the result of qbpp::quantize() (see Data Types of Variables and Expressions).
Callback events
qbpp::CallbackEvent, used in ABS3 Solver callbacks, can also be printed (see ABS3 Solver Usage).
#include <qbpp/qbpp.hpp>
#include <qbpp/abs3_solver.hpp>
int main() {
std::cout << qbpp::CallbackEvent::BestUpdated << std::endl;
}
This program produces the following output:
CallbackEvent::BestUpdated
Objects that cannot be printed
- Solvers (
qbpp::EasySolver,qbpp::ExhaustiveSolver,qbpp::ABS3Solver) and search parametersqbpp::Paramscannot be printed. - The list of solutions collected by a solver,
sol.sols(std::vector<qbpp::Sol>), cannot be printed as it is; print the solutions one at a time in a loop, as in the example above.
Differences from the Python version
C++ and Python differ in some formats, following the conventions of each language.
| Object | C++ | Python |
|---|---|---|
| Array | {a[0],a[1],a[2]} | [a[0], a[1], a[2]] |
| Solution | 0:{{x,0},{y,1}} | Sol(energy=0, {x: 0, y: 1}) |
Element of violations() | {value: 2, ..., satisfied: false} | dict {'value': 2, ..., 'satisfied': False} |
CallbackEvent | CallbackEvent::BestUpdated | CallbackEvent.BestUpdated |
| Solver | Cannot be printed | <... object at 0x...> |