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.

168 lines
7.5 KiB

  1. /* A solver for the Japanese number-puzzle Hashiwokakero
  2. * (http://en.wikipedia.org/wiki/Hashiwokakero)
  3. *
  4. * Sebastian Nowozin <nowozin@gmail.com>, 13th January 2009
  5. */
  6. param n := 25;
  7. set rows := 1..n;
  8. set cols := 1..n;
  9. param givens{rows, cols}, integer, >= 0, <= 8, default 0;
  10. /* Set of vertices as (row,col) coordinates */
  11. set V := { (i,j) in { rows, cols }: givens[i,j] != 0 };
  12. /* Set of feasible horizontal edges from (i,j) to (k,l) rightwards */
  13. set Eh := { (i,j,k,l) in { V, V }:
  14. i = k and j < l and # Same row and left to right
  15. card({ (s,t) in V: s = i and t > j and t < l }) = 0 # No vertex inbetween
  16. };
  17. /* Set of feasible vertical edges from (i,j) to (k,l) downwards */
  18. set Ev := { (i,j,k,l) in { V, V }:
  19. j = l and i < k and # Same column and top to bottom
  20. card({ (s,t) in V: t = j and s > i and s < k }) = 0 # No vertex inbetween
  21. };
  22. set E := Eh union Ev;
  23. /* Indicators: use edge once/twice */
  24. var xe1{E}, binary;
  25. var xe2{E}, binary;
  26. /* Constraint: Do not use edge or do use once or do use twice */
  27. s.t. edge_sel{(i,j,k,l) in E}:
  28. xe1[i,j,k,l] + xe2[i,j,k,l] <= 1;
  29. /* Constraint: There must be as many edges used as the node value */
  30. s.t. satisfy_vertex_demand{(s,t) in V}:
  31. sum{(i,j,k,l) in E: (i = s and j = t) or (k = s and l = t)}
  32. (xe1[i,j,k,l] + 2.0*xe2[i,j,k,l]) = givens[s,t];
  33. /* Constraint: No crossings */
  34. s.t. no_crossing1{(i,j,k,l) in Eh, (s,t,u,v) in Ev:
  35. s < i and u > i and j < t and l > t}:
  36. xe1[i,j,k,l] + xe1[s,t,u,v] <= 1;
  37. s.t. no_crossing2{(i,j,k,l) in Eh, (s,t,u,v) in Ev:
  38. s < i and u > i and j < t and l > t}:
  39. xe1[i,j,k,l] + xe2[s,t,u,v] <= 1;
  40. s.t. no_crossing3{(i,j,k,l) in Eh, (s,t,u,v) in Ev:
  41. s < i and u > i and j < t and l > t}:
  42. xe2[i,j,k,l] + xe1[s,t,u,v] <= 1;
  43. s.t. no_crossing4{(i,j,k,l) in Eh, (s,t,u,v) in Ev:
  44. s < i and u > i and j < t and l > t}:
  45. xe2[i,j,k,l] + xe2[s,t,u,v] <= 1;
  46. /* Model connectivity by auxiliary network flow problem:
  47. * One vertex becomes a target node and all other vertices send a unit flow
  48. * to it. The edge selection variables xe1/xe2 are VUB constraints and
  49. * therefore xe1/xe2 select the feasible graph for the max-flow problems.
  50. */
  51. set node_target := { (s,t) in V:
  52. card({ (i,j) in V: i < s or (i = s and j < t) }) = 0};
  53. set node_sources := { (s,t) in V: (s,t) not in node_target };
  54. var flow_forward{ E }, >= 0;
  55. var flow_backward{ E }, >= 0;
  56. s.t. flow_conservation{ (s,t) in node_target, (p,q) in V }:
  57. /* All incoming flows */
  58. - sum{(i,j,k,l) in E: k = p and l = q} flow_forward[i,j,k,l]
  59. - sum{(i,j,k,l) in E: i = p and j = q} flow_backward[i,j,k,l]
  60. /* All outgoing flows */
  61. + sum{(i,j,k,l) in E: k = p and l = q} flow_backward[i,j,k,l]
  62. + sum{(i,j,k,l) in E: i = p and j = q} flow_forward[i,j,k,l]
  63. = 0 + (if (p = s and q = t) then card(node_sources) else -1);
  64. /* Variable-Upper-Bound (VUB) constraints: xe1/xe2 bound the flows.
  65. */
  66. s.t. connectivity_vub1{(i,j,k,l) in E}:
  67. flow_forward[i,j,k,l] <= card(node_sources)*(xe1[i,j,k,l] + xe2[i,j,k,l]);
  68. s.t. connectivity_vub2{(i,j,k,l) in E}:
  69. flow_backward[i,j,k,l] <= card(node_sources)*(xe1[i,j,k,l] + xe2[i,j,k,l]);
  70. /* A feasible solution is enough
  71. */
  72. minimize cost: 0;
  73. solve;
  74. /* Output solution graphically */
  75. printf "\nSolution:\n";
  76. for { row in rows } {
  77. for { col in cols } {
  78. /* First print this cell information: givens or space */
  79. printf{0..0: givens[row,col] != 0} "%d", givens[row,col];
  80. printf{0..0: givens[row,col] = 0 and
  81. card({(i,j,k,l) in Eh: i = row and col >= j and col < l and
  82. xe1[i,j,k,l] = 1}) = 1} "-";
  83. printf{0..0: givens[row,col] = 0 and
  84. card({(i,j,k,l) in Eh: i = row and col >= j and col < l and
  85. xe2[i,j,k,l] = 1}) = 1} "=";
  86. printf{0..0: givens[row,col] = 0
  87. and card({(i,j,k,l) in Ev: j = col and row >= i and row < k and
  88. xe1[i,j,k,l] = 1}) = 1} "|";
  89. printf{0..0: givens[row,col] = 0
  90. and card({(i,j,k,l) in Ev: j = col and row >= i and row < k and
  91. xe2[i,j,k,l] = 1}) = 1} '"';
  92. printf{0..0: givens[row,col] = 0
  93. and card({(i,j,k,l) in Eh: i = row and col >= j and col < l and
  94. (xe1[i,j,k,l] = 1 or xe2[i,j,k,l] = 1)}) = 0
  95. and card({(i,j,k,l) in Ev: j = col and row >= i and row < k and
  96. (xe1[i,j,k,l] = 1 or xe2[i,j,k,l] = 1)}) = 0} " ";
  97. /* Now print any edges */
  98. printf{(i,j,k,l) in Eh: i = row and col >= j and col < l and xe1[i,j,k,l] = 1} "-";
  99. printf{(i,j,k,l) in Eh: i = row and col >= j and col < l and xe2[i,j,k,l] = 1} "=";
  100. printf{(i,j,k,l) in Eh: i = row and col >= j and col < l and
  101. xe1[i,j,k,l] = 0 and xe2[i,j,k,l] = 0} " ";
  102. printf{0..0: card({(i,j,k,l) in Eh: i = row and col >= j and col < l}) = 0} " ";
  103. }
  104. printf "\n";
  105. for { col in cols } {
  106. printf{(i,j,k,l) in Ev: j = col and row >= i and row < k and xe1[i,j,k,l] = 1} "|";
  107. printf{(i,j,k,l) in Ev: j = col and row >= i and row < k and xe2[i,j,k,l] = 1} '"';
  108. printf{(i,j,k,l) in Ev: j = col and row >= i and row < k and
  109. xe1[i,j,k,l] = 0 and xe2[i,j,k,l] = 0} " ";
  110. /* No vertical edges: skip also a field */
  111. printf{0..0: card({(i,j,k,l) in Ev: j = col and row >= i and row < k}) = 0} " ";
  112. printf " ";
  113. }
  114. printf "\n";
  115. }
  116. data;
  117. /* This is a difficult 25x25 Hashiwokakero.
  118. */
  119. param givens : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
  120. 25 :=
  121. 1 2 . 2 . 2 . . 2 . 2 . . 2 . . . . 2 . 2 . 2 . 2 .
  122. 2 . 1 . . . . 2 . . . 4 . . 5 . 2 . . 1 . 2 . 2 . 1
  123. 3 2 . . 5 . 4 . . 3 . . . . . 1 . . 4 . 5 . 1 . 1 .
  124. 4 . . . . . . . . . . . 1 . 3 . . 1 . . . . . . . .
  125. 5 2 . . 6 . 6 . . 8 . 5 . 2 . . 3 . 5 . 7 . . 2 . .
  126. 6 . 1 . . . . . . . . . 1 . . 2 . . . . . 1 . . . 3
  127. 7 2 . . . . 5 . . 6 . 4 . . 2 . . . 2 . 5 . 4 . 2 .
  128. 8 . 2 . 2 . . . . . . . . . . . 3 . . 3 . . . 1 . 2
  129. 9 . . . . . . . . . . 4 . 2 . 2 . . 1 . . . 3 . 1 .
  130. 10 2 . 3 . . 6 . . 2 . . . . . . . . . . 3 . . . . .
  131. 11 . . . . 1 . . 2 . . 5 . . 1 . 4 . 3 . . . . 2 . 4
  132. 12 . . 2 . . 1 . . . . . . 5 . 4 . . . . 4 . 3 . . .
  133. 13 2 . . . 3 . 1 . . . . . . . . 3 . . 5 . 5 . . 2 .
  134. 14 . . . . . 2 . 5 . . 7 . 5 . 3 . 1 . . 1 . . 1 . 4
  135. 15 2 . 5 . 3 . . . . 1 . 2 . 1 . . . . 2 . 4 . . 2 .
  136. 16 . . . . . 1 . . . . . . . . . . 2 . . 2 . 1 . . 3
  137. 17 2 . 6 . 6 . . 2 . . 2 . 2 . 5 . . . . . 2 . . . .
  138. 18 . . . . . 1 . . . 3 . . . . . 1 . . 1 . . 4 . 3 .
  139. 19 . . 4 . 5 . . 2 . . . 2 . . 6 . 6 . . 3 . . . . 3
  140. 20 2 . . . . . . . . . 2 . . 1 . . . . . . 1 . . 1 .
  141. 21 . . 3 . . 3 . 5 . 5 . . 4 . 6 . 7 . . 4 . 6 . . 4
  142. 22 2 . . . 3 . 5 . 2 . 1 . . . . . . . . . . . . . .
  143. 23 . . . . . . . . . 1 . . . . . . 3 . 2 . . 5 . . 5
  144. 24 2 . 3 . 3 . 5 . 4 . 3 . 3 . 4 . . 2 . 2 . . . 1 .
  145. 25 . 1 . 2 . 2 . . . 2 . 2 . . . 2 . . . . 2 . 2 . 2
  146. ;
  147. end;