You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

118 lines
3.4 KiB

2 months ago
  1. /* Rectifiable polyomino tilings generator */
  2. /* Written and converted to GNU MathProg by NASZVADI, Peter, 2007-2017
  3. <vuk@cs.elte.hu> */
  4. /*
  5. This model searches for a maximal packing of a given polyomino
  6. composed of unit squares in a given rectangle. In a feasible packing, a
  7. placed polyomino and its intersection of a unit square's inner part in
  8. the rectangle must be the square or empty. If there exists a packing
  9. that covers totally the rectangle, then the polyomino is called
  10. "rectifiable"
  11. Summary:
  12. Decides if an Im * Jm rectangle could be tiled with given pattern
  13. and prints a (sub)optimal solution if found
  14. Generated magic numbers are implicit tables, check them:
  15. # for magic in 3248 688 1660 3260
  16. do printf "Magic % 5d:" "$magic"
  17. for e in 0 1 2 3 4 5 6 7
  18. do printf "% 3d" "$((-1 + ((magic / (3**e)) % 3)))"
  19. done
  20. echo
  21. done
  22. Magic 3248: 1 1 -1 -1 0 0 0 0
  23. Magic 688: 0 0 0 0 1 1 -1 -1
  24. Magic 1660: 0 0 0 0 1 -1 1 -1
  25. Magic 3260: 1 -1 1 -1 0 0 0 0
  26. #
  27. */
  28. param Im, default 3;
  29. /* vertical edge length of the box */
  30. param Jm, default 3;
  31. /* horizontal edge length of the box */
  32. set S, default {(0, 0), (1, 0), (2, 0), (0, 1), (1, 1), (2, 1), (0, 2)};
  33. /* P-heptomino is the default shape. More info on this heptomino:
  34. http://www.cflmath.com/Polyomino/7omino4_rect.html */
  35. set I := 1..Im;
  36. /* rows of rectangle */
  37. set J := 1..Jm;
  38. /* columns of rectangle */
  39. set IJ := I cross J;
  40. /* the rectangle itself */
  41. set E := 0..7;
  42. /* helper set to allow iterating on all transformations of the S shape */
  43. set Shifts := setof{(i, j, e) in IJ cross E:
  44. setof{(x, y) in S}
  45. ((x * (-1 + floor(3248 / 3^e) mod 3)) +
  46. (y * (-1 + floor(688 / 3^e) mod 3)) + i,
  47. (x * (-1 + floor(1660 / 3^e) mod 3)) +
  48. (y * (-1 + floor(3260 / 3^e) mod 3)) + j) within IJ}(i, j, e);
  49. /* all shifted, flipped, rotated, mirrored mappings of polyomino that
  50. contained by the rectangle */
  51. var cell{IJ}, binary;
  52. /* booleans denoting if a cell is covered in the rectangle */
  53. var tile{Shifts}, binary;
  54. /* booleans denoting usage of a shift */
  55. var objvalue;
  56. s.t. covers{(i, j) in IJ}: sum{(k, l, e, a, b) in Shifts cross S:
  57. i = k + a * (-1 + floor(3248 / 3^e) mod 3) +
  58. b * (-1 + floor(688 / 3^e) mod 3)
  59. and
  60. j = l + a * (-1 + floor(1660 / 3^e) mod 3) +
  61. b * (-1 + floor(3260 / 3^e) mod 3)
  62. }tile[k, l, e] = cell[i, j];
  63. s.t. objeval: sum{(i, j) in IJ}cell[i, j] - objvalue = 0;
  64. maximize obj: objvalue;
  65. solve;
  66. printf '\nCovered cells/all cells = %d/%d\n\n', objvalue.val, Im * Jm;
  67. printf '\nA tiling:\n\n';
  68. for{i in I}{
  69. for{j in J}{
  70. printf '%s', if cell[i, j].val then '' else ' *** ';
  71. for{(k, l, e, a, b) in Shifts cross S:
  72. cell[i, j].val
  73. and i = k + a * (-1 + floor(3248 / 3^e) mod 3) +
  74. b * (-1 + floor(688 / 3^e) mod 3)
  75. and j = l + a * (-1 + floor(1660 / 3^e) mod 3) +
  76. b * (-1 + floor(3260 / 3^e) mod 3)
  77. and tile[k, l, e].val
  78. }{
  79. printf '% 5d', (k * Jm + l) * 8 + e;
  80. }
  81. }
  82. printf '\n';
  83. }
  84. printf '\n';
  85. data;
  86. param Im := 14;
  87. /* here can be set rectangle's one side */
  88. param Jm := 14;
  89. /* here can be set rectangle's other side */
  90. set S := (0,0),(1,0),(2,0),(0,1),(1,1),(2,1),(0,2);
  91. /* here you can specify arbitrary polyomino */
  92. end;