Assuming an \(n \times n\) board (with \(n\) even), we need to fill the cells \((i,j)\), with values 0 or 1, with the following restrictions:
- The number of ones in each row and in each column is equal to \(\displaystyle\frac{n}{2}\).
- Then we have also: The number of zeroes in each row and in each column is equal to \(\displaystyle\frac{n}{2}\).
- There can be no duplicate rows and no duplicate columns.
- In a row or column there cannot be more than two consecutive zeroes or ones.
A small example is given in (1):
Of course our central variable will be \(x_{i,j}\in\{0,1\}\). Condition 1 can be easily modeled using two constraints:
| \[\begin{align} &\sum_j x_{i,j} = \frac{n}{2}\>\> \forall i\\ &\sum_i x_{i,j} = \frac{n}{2}\>\> \forall j \end{align}\] |
Condition 2 we don’t need to model explicitly: this follows from the above constraints.
Condition 3 (no duplicate rows or columns) is not very easy. One way to handle this, is to calculate a value for each row and column as follows:
| \[\begin{align} &v_i = \sum_j 2^{j-1} x_{i,j}\\ &w_j = \sum_i 2^{i-1} x_{i,j} \end{align}\] |
and then make sure there are no duplicate \(v_i\)’s or duplicate \(w_j\)’s. This can be done using some all-different formulation (3). A big-M approach to implement \(v_i \le v_{i’}-1 \textbf{ or } v_i \ge v_{i’}+1, \forall i\ne i’\) can look like:
| \[\begin{align} &v_i \le v_{i’}-1 + M \delta_{i,i’}\\ &v_i \ge v_{i’}+1 – M (1-\delta_{i,i’})\\ &\delta_{i,i’} \in \{0,1\} \end{align}\] |
However I want to attack this in a different way, using an xor condition (4). The constraints involved can be conceptualized as:
| \[\begin{align} &\sum_j |x_{i,j} – x_{i’,j}| \ge 1 \>\> \forall i\ne i’\\ &\sum_i |x_{i,j} – x_{i,j’}| \ge 1 \>\> \forall j\ne j’ \end{align}\] |
The value \(z_{i,j,i’,j’}=|x_{i,j}-x_{i’,j’}|\) can be interpreted as \(z_{i,j,i’,j’}=x_{i,j} \textbf{ xor } x_{i’,j’}\): zero if \(x_{i,j}\) and \(x_{i’,j’}\) are identical and one if they are different. This in turn can be written as a set of inequalities (4):
| \[\begin{align} &z_{i,j,i’,j’}\le x_{i,j} + x_{i’,j’}\\ &z_{i,j,i’,j’}\ge x_{i,j} - x_{i’,j’}\\ &z_{i,j,i’,j’}\ge x_{i’,j’} - x_{i,j}\\ &z_{i,j,i’,j’}\le 2 - x_{i,j} - x_{i’,j’}\\ &z_{i,j,i’,j’} \in \{0,1\} \end{align}\] |
After this we just need:
| \[\begin{align} &\sum_j z_{i,j,i’,j} \ge 1 \>\> \forall i\ne i’\\ &\sum_i z_{i,j,i,j’} \ge 1 \>\> \forall j\ne j’ \end{align}\] |
Due to the nature of these conditions on \(z\) we can limit the xor constraints to
| \[\begin{align} &z_{i,j,i’,j’}\le x_{i,j} + x_{i’,j’}\\ &z_{i,j,i’,j’}\le 2 - x_{i,j} - x_{i’,j’}\\ &z_{i,j,i’,j’} \in \{0,1\} \end{align}\] |
Note that we do not need to compute all \(z\) for all combinations \((i,j)\), \((i’,j’)\) (e.g. we never compare \(x_{2,3}\) with \(x_{3,2}\)). Furthermore we can relax \(z\) to be continuous between zero and one. Also note that if we compared row \(i\) and \(i’\) then we don’t need to compare row \(i’\) and row \(i\). Similarly for the columns. So we can do:
| \[\begin{align} &\sum_j z_{i,j,i’,j} \ge 1 \>\> \forall i< i’\\ &\sum_i z_{i,j,i,j’} \ge 1 \>\> \forall j< j’ \end{align}\] |
Finally we need to handle restriction 4. This can be implemented as:
| \[\begin{align} &1\le x_{i,j}+x_{i,j+1}+x_{i,j+2}\le 2\\ &1\le x_{i,j}+x_{i+1,j}+x_{i+2,j}\le 2 \end{align}\] |
Usually we need to write this as four inequalities (unless we can specify ranged equations). If the summation was longer I would have introduced extra variables with bounds one and two to reduce the number of constraints.
Note that the lower bound of one can also be inferred from \((1-x_{i,j})+(1-x_{i,j+1})+(1-x_{i,j+2})\le 2\).
Complete model
The variables are:
The dummy variable is related to a dummy objective: we look for a feasible integer solution only.
The different \(z\) values we need to compare is encoded in a set compare:
Finally the model equations are:
The result looks like:
---- 77 VARIABLE x.L i1 i2 i3 i4 i1 1 1 |
A large problem
The site (2) contains some “very hard” 14 x 14 puzzles. An example is:
It is interesting to see how this model behaves on this problem. It turns out the problem can be solved completely in preprocessing. E.g. Cplex and Gurobi report that zero Simplex iterations were needed and solve this problem blazingly fast:
Tried aggregator 3 times. Root node processing (before b&c): |
Verifying Uniqueness
A well-formed puzzle has only one solution. To verify whether a solution is unique we can use a similar strategy as in (6):
- First solve the model to obtain a solution \(x^*_{i,j}\).
- Formulate a constraint to forbid this solution.
- Add this constraint to the model and resolve. The solver should not find a new solution but rather report that this model is infeasible.
Here the cut can be formulated as:
| \[\sum_{i,j} x^*_{i,j} x_{i,j} \le \frac{n^2}{2}-1\] |
References
- Takuzu, https://en.wikipedia.org/wiki/Takuzu
- Online Takuzu puzzles, http://www.binarypuzzle.com/
- All-different and Mixed Integer Programming, http://yetanothermathprogrammingconsultant.blogspot.com/2016/05/all-different-and-mixed-integer.html
- xor as Inequalities, http://yetanothermathprogrammingconsultant.blogspot.com/2016/02/xor-as-linear-inequalities.html
- Similar puzzles are Sudoku and KenKen: http://yetanothermathprogrammingconsultant.blogspot.com/2016/10/mip-modeling-from-sudoku-to-kenken.html
- Unique Solutions in KenKen, http://yetanothermathprogrammingconsultant.blogspot.com/2016/12/unique-solutions-in-kenken.html