This is a simple puzzle: given a grid with some cells containing a positive integer, form rectangles such that
One possible approach is a two-step algorithm:
The problem of how to generate all feasible rectangles is easier said than done, especially if you want to do this efficiently for larger instances. This is mainly a programming exercise, rather than a modeling problem.
The second part is surprisingly simple. Assume all \(k\in K\) rectangles are stored in a single large boolean data structure: \[\mathit{allRectangles}_{k,i,j} = \begin{cases} 1 & \text{if cell \((i,j)\) is part of rectangle \(k\)}\\ 0 & \text{otherwise}\end{cases}\] then the optimization model is a simple set covering model:
In this case, we don't have an objective. We simply state that every cell \((i,j)\) must be covered by exactly one rectangle.
This is a tiny model and solves very easily. Typically it can be solved completely in the presolve phase:
The solution can look like:
The model selects 11 rectangles. We could have predicted this: there are 11 numbered cells in the input data. The parameter result displays the selected rectangle numbers on the grid. You should be able to match this up with the picture of the feasible rectangles shown earlier.
Notes:
Again the presolver could eliminate all rows and columns.
- Each rectangle contains exactly one cell with a number
- The size of the rectangle is equal to this number
- Every cell in the grid is covered by exactly one rectangle
| Shikaku Problem and Solution |
Approach
One possible approach is a two-step algorithm:
- Generate all feasible rectangles,
- Use a simple MIP model to select a subset of these rectangles such that each cell is covered exactly once.
For the problem above, we just have 31 feasible rectangles. Feasible means here: (a) rectangle contains exactly one cell with a number, (b) the size of the rectangle is equal to that number.
| All feasible rectangles |
The problem of how to generate all feasible rectangles is easier said than done, especially if you want to do this efficiently for larger instances. This is mainly a programming exercise, rather than a modeling problem.
The second part is surprisingly simple. Assume all \(k\in K\) rectangles are stored in a single large boolean data structure: \[\mathit{allRectangles}_{k,i,j} = \begin{cases} 1 & \text{if cell \((i,j)\) is part of rectangle \(k\)}\\ 0 & \text{otherwise}\end{cases}\] then the optimization model is a simple set covering model:
| Set Covering Problem |
|---|
| \[\begin{align}\min\>& 0\\ &\sum_k \color{darkblue}{\mathit{allRectangles}}_{k,i,j} \color{darkred}x_{k} = 1&& \forall i,j\\ &\color{darkred}x_{k} \in \{0,1\} \end{align}\] |
In this case, we don't have an objective. We simply state that every cell \((i,j)\) must be covered by exactly one rectangle.
This is a tiny model and solves very easily. Typically it can be solved completely in the presolve phase:
Tried aggregator 1 time.
MIP Presolve eliminated 37 rows and 32 columns.
MIP Presolve modified 3 coefficients.
All rows and columns eliminated.
The solution can look like:
---- 89 VARIABLE x.L selection of rectangles
k1 1.000, k3 1.000, k5 1.000, k8 1.000, k9 1.000, k12 1.000, k20 1.000, k22 1.000
k26 1.000, k29 1.000, k31 1.000
---- 97 PARAMETER result solution: selected rectangles
c1 c2 c3 c4 c5 c6
r1 135589
r2 135589
r3 1235589
r4 12320202222
r5 12326262626
r6 292929293131
The model selects 11 rectangles. We could have predicted this: there are 11 numbered cells in the input data. The parameter result displays the selected rectangle numbers on the grid. You should be able to match this up with the picture of the feasible rectangles shown earlier.
GAMS Model
$ontext Cell Block or Shikaku puzzle Set Covering model for (small) square grids erwin@amsterdamoptimization.com $offtext sets i 'rows'/r1*r6/ j 'columns'/c1*c6/ ; scalars m 'rows' n 'columns' ; m = card(i); n = card(j); alias(i,p,h); alias(j,q,w); table grid(i,j) c1 c2 c3 c4 c5 c6 r1 2 3 r2 6 3 r3 5 r4 3 2 2 r5 4 r6 4 2 ; scalar nn 'sum of numbers'; nn = sum((i,j),grid(i,j)); display nn; abort$(nn <> card(i)*card(j)) "error in grid specification"; *------------------------------------------ * generate all possible rectangles * requirements: * 1. block contains exactly one number from grid * 2. size of block is equal to this number *------------------------------------------ set k 'rectangle number'/k1*k10000/ allRectangles(k,i,j) r(i,j) 'current rectangle' ; singletonset kk(k) 'current index'/k1/ ; loop((p,q), loop((w,h)$(ord(p)+ord(h)-1<=m andord(q)+ord(w)-1<=n), * candidate rectangle r(i,j) = (ord(i)>=ord(p) andord(i)<=ord(p)+ord(h)-1 and ord(j)>=ord(q) andord(j)<=ord(q)+ord(w)-1); * check: only one grid number and size = gridnumber if(sum(r$grid(r),1)=1 andcard(r)=sum(r,grid(r)), allRectangles(kk,r) = yes; kk(k)=kk(k-1); ); ); ); *------------------------------------------ * model: select rectangles such that each * cell is covered exactly once *------------------------------------------ binaryvariable x(k) 'selection of rectangles'; variable z 'dummy objective'; equations dummy 'dummy objective' covering(i,j) 'each cell is covered by exactly one rectangle' ; covering(i,j).. sum(allRectangles(k,i,j),x(k)) =e= 1; dummy.. z =e= 0; model cover /all/; * just need feasibility solve cover minimizing z using mip; display x.l; * reporting parameter result(i,j) 'solution: selected rectangles'; loop(k$(x.l(k)>0.5), result(i,j)$allRectangles(k,i,j) = ord(k); ); option result:0; display result; |
- The data check makes sure the sum of the numbers is equal to the size (area) of the grid.
- The enumeration of the feasible rectangles is using a simplistic and crude algorithm. It may need to be refined for larger instances.
- allRectangles(k,i,j) is implemented as a set.
- As we are looking for a feasible solution only, there is no need to specify a gap with the optcr option.
A larger problem
A larger problem is taken from [1].
| 17 x 15 problem |
Some statistics:
- This problem has 17 rows and 15 columns.
- The number of feasible rectangles is 253.
- The number of numbered cells is 66. This is also the number of rectangles we need to select.
- If one wants to make a big impression, mention that the number of ways we can choose 66 out of 253 is: \[ {253 \choose 66} = 66 281 207 211 442 081 043 167 193 447 008 690 678 844 358 496 354 619 442 275 550\]
The results look like:
---- 105 VARIABLE x.L selection of rectangles
k1 1.000, k3 1.000, k6 1.000, k11 1.000, k13 1.000, k16 1.000, k30 1.000, k34 1.000
k36 1.000, k37 1.000, k41 1.000, k44 1.000, k45 1.000, k51 1.000, k54 1.000, k63 1.000
k65 1.000, k69 1.000, k73 1.000, k82 1.000, k84 1.000, k87 1.000, k90 1.000, k91 1.000
k94 1.000, k103 1.000, k107 1.000, k110 1.000, k112 1.000, k125 1.000, k128 1.000, k130 1.000
k132 1.000, k134 1.000, k136 1.000, k140 1.000, k143 1.000, k150 1.000, k152 1.000, k154 1.000
k159 1.000, k162 1.000, k171 1.000, k174 1.000, k190 1.000, k192 1.000, k195 1.000, k199 1.000
k201 1.000, k202 1.000, k203 1.000, k204 1.000, k209 1.000, k216 1.000, k219 1.000, k222 1.000
k226 1.000, k228 1.000, k235 1.000, k238 1.000, k244 1.000, k245 1.000, k247 1.000, k249 1.000
k251 1.000, k253 1.000
---- 113 PARAMETER result solution: selected rectangles
c1 c2 c3 c4 c5 c6 c7 c8 c9
r1 1336611111111
r2 1336611111111
r3 303030303434363737
r4 303030303434365151
r5 303030303434636565
r6 737373733434636565
r7 878790909191946565
r8 10310310310310310394107107
r9 10310310310310310394125125
r10 134136136140140143143125125
r11 134154154159159159159159159
r12 171154154174174174174174174
r13 171190190192195195195199199
r14 204190190192195195195209209
r15 204190190216216219219222222
r16 204190190216216235235235238
r17 204244244245245245247247249
+ c10 c11 c12 c13 c14 c15
r1 111113131616
r2 111113131616
r3 414113134445
r4 545413134445
r5 545469694445
r6 828484844445
r7 828484844445
r8 1071101101124445
r9 128128130112132132
r10 128128130150150152
r11 162162130150150152
r12 162162130150150152
r13 199201201202203203
r14 209209209202203203
r15 222222222226226228
r16 238238238226226228
r17 249249251251253253
Questions
I still have some lingering questions about this problem.
- How would a better algorithm that enumerates all feasible rectangles look like? I guess it would start with the cells containing numbers.
- Can we use the solution pool to automate this step?
- Is the solution unique?
- Are there cases where the presolver is not solving the complete problem?