Models and solves a sudoku using Cplex. Shows how to manipulate multi-dimensional variables.
This example solves a sudoku puzzle using Cplex. It demonstrates how to manipulate multi-dimensional variables in Cplex. Indeed, we use the following three-dimensional variable to model our problem:
\[
x_{ijk} = \begin{cases}
1, & \text{if number $k$ is entered in row $i$ and column $j$}, \\
0, & \text{otherwise}.
\end{cases}
\]
#include <iostream>
#include "idol/modeling.h"
#include "idol/mixed-integer/optimizers/wrappers/Cplex/Cplex.h"
using namespace idol;
int main(int t_argc, const char** t_argv) {
const Vector<char, 2> initial_grid = {
{ 5, 3, 0, 0, 7, 0, 0, 0, 0 },
{ 6, 0, 0, 1, 9, 5, 0, 0, 0 },
{ 0, 9, 8, 0, 0, 0, 0, 6, 0 },
{ 8, 0, 0, 0, 6, 0, 0, 0, 3 },
{ 4, 0, 0, 8, 0, 3, 0, 0, 1 },
{ 7, 0, 0, 0, 2, 0, 0, 0, 6 },
{ 0, 6, 0, 0, 0, 0, 2, 8, 0 },
{ 0, 0, 0, 4, 1, 9, 0, 0, 5 },
{ 0, 0, 0, 0, 8, 0, 0, 7, 9 }
};
const auto x = model.add_vars(
Dim<3>(9,9,9), 0, 1, Binary, 0,
"x");
for (unsigned int i = 0 ; i < 9 ; ++i) {
for (unsigned int j = 0; j < 9; ++j) {
model.add_ctr(idol_Sum(k,
Range(9), x[i][j][k]) == 1);
}
}
for (unsigned int i = 0 ; i < 9 ; ++i) {
for (unsigned int k = 0 ; k < 9 ; ++k) {
model.add_ctr(idol_Sum(j,
Range(9), x[i][j][k]) == 1);
}
}
for (unsigned int j = 0 ; j < 9 ; ++j) {
for (unsigned int k = 0 ; k < 9 ; ++k) {
model.add_ctr(idol_Sum(i,
Range(9), x[i][j][k]) == 1);
}
}
for (unsigned int k = 0 ; k < 9 ; ++k) {
for (unsigned int p = 1 ; p <= 3 ; ++p) {
for (unsigned int q = 1 ; q <= 3 ; ++q) {
auto c = model.add_ctr(
idol_Sum(i,
Range(3 * p - 3, 3 * p),
idol_Sum(j,
Range(3 * q - 3, 3 * q),
x[i][j][k]
)) == 1
);
}
}
}
for (unsigned int i = 0 ; i < 9 ; ++i) {
for (unsigned int j = 0 ; j < 9 ; ++j) {
const char k = initial_grid[i][j];
if (k != 0) {
model.set_var_lb(x[i][j][k-1], 1);
}
}
}
model.use(
Cplex().with_logs(
false));
model.optimize();
std::cout << "Solution status is " << model.get_status() << std::endl;
if (model.get_status() == Optimal) {
std::cout << "Solution found!" << std::endl;
for (unsigned int i = 0 ; i < 9 ; ++i) {
for (unsigned int j = 0 ; j < 9 ; ++j) {
for (unsigned int k = 0 ; k < 9 ; ++k) {
const double x_val = model.get_var_primal(x[i][j][k]);
if (equals(x_val, 1, 1e-4)) {
std::cout << k+1 << ' ';
break;
}
}
}
std::cout << '\n';
}
std::cout << std::endl;
} else {
std::cout << "No solution exists." << std::endl;
}
return 0;
}