The puzzle of numbrix [1,2] is simple to state.
- We have a 9x9 board with 81 cells.
- We need to fill each cell with a unique value between 1 and 81.
- There are some prefilled cells.
- We should be able to start with the cell containing value 1 and then following a path (only going one up, down, left or right) to the next values and thus arriving at the cell with value 81.
Example
Below is an example of an input (the "given" cells) and a solution. The colors may help to see that we have a path from the cell with value 1 to the cell with value 81.
Of course, we want to see if we can create a MIP model for this.
Like in Sudoku models we use a binary variable \(\color{darkred}x_{i,j,k} \in \{0,1\}\) define by \[\color{darkred}x_{i,j,k} = \begin{cases} 1 & \text{if cell $(i,j)$ has value $k$} \\ 0 & \text{otherwise}\end{cases}\] This introduces a large number of binary variables (\(9 \times 9 \times 81=6,561\)), but it makes the model much simpler for use with a MIP model. This is really the big decision: once you have main variables defined, things follow from there.
We need to formulate just three constraints:
- Each cell can contain just one value. \[\sum_k \color{darkred}x_{i,j,k} = 1 \>\> \forall i,j\]
- Each value should occur exactly once. \[\sum_{i,j}\color{darkred}x_{i,j,k} = 1 \>\> \forall k\]
- We need: if \(\color{darkred}x_{i,j,k} = 1\) then one of its neighbors should contain value \(k+1\). A neighbor is defined as going one up, down, left or right. This can be formulated as an implication \[\color{darkred}x_{i,j,k} = 1 \Rightarrow \color{darkred}x_{i-1,j,k+1}+\color{darkred}x_{i+1,j,k+1}+\color{darkred}x_{i,j-1,k+1}+\color{darkred}x_{i,j+1,k+1} = 1\] Or, as inequality: \[\color{darkred}x_{i-1,j,k+1}+\color{darkred}x_{i+1,j,k+1}+\color{darkred}x_{i,j-1,k+1}+\color{darkred}x_{i,j+1,k+1} \ge \color{darkred}x_{i,j,k}\]
Model |
---|
\[\begin{align} & \sum_k \color{darkred}x_{i,j,k} = 1 && \forall i,j \\ & \sum_{i,j}\color{darkred}x_{i,j,k} = 1 && \forall k \\ & \color{darkred}x_{i-1,j,k+1}+\color{darkred}x_{i+1,j,k+1}+\color{darkred}x_{i,j-1,k+1}+\color{darkred}x_{i,j+1,k+1} \ge \color{darkred}x_{i,j,k} && \forall i,j, \forall k\lt 81 \end{align}\] |
sets |
---- 46 PARAMETER result
j1 j2 j3 j4 j5 j6 j7 j8 j9
i1 23222112111094243
i2 24252013141584144
i3 27261918171674045
i4 281234563946
i5 293031323334353847
i6 686766656463363748
i7 697071808162515049
i8 747372796061525354
i9 757677785958575655
Notes:
- We don't need an optcr (gap) setting: we are looking for a feasible solution.
- The k+1 in next(i,j,k+1) means that we skip the last k when generating this equation.
- We could have defined equation next in terms of \(k-1\) and \(k\). Then you would not need the k+1 in next(i,j,k+1). I.e., next(i,j,k).. x(i-1,j,k)+x(i+1,j,k)+x(i,j-1,k)+x(i,j+1,k) =g= x(i,j,k-1);
- We were lucky with addressing \(i\pm1, j\pm 1\). GAMS returning zero there when outside the domain is exactly what we want.
- Interestingly when solving as an RMIP (Relaxed MIP), Cplex will need to do a few iterations. It will still find the integer solution. I suspect this is just by accident.
- I think this model looks quite nice!