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
168 lines
7.5 KiB
/* A solver for the Japanese number-puzzle Hashiwokakero
|
|
* (http://en.wikipedia.org/wiki/Hashiwokakero)
|
|
*
|
|
* Sebastian Nowozin <nowozin@gmail.com>, 13th January 2009
|
|
*/
|
|
|
|
param n := 25;
|
|
set rows := 1..n;
|
|
set cols := 1..n;
|
|
param givens{rows, cols}, integer, >= 0, <= 8, default 0;
|
|
|
|
/* Set of vertices as (row,col) coordinates */
|
|
set V := { (i,j) in { rows, cols }: givens[i,j] != 0 };
|
|
|
|
/* Set of feasible horizontal edges from (i,j) to (k,l) rightwards */
|
|
set Eh := { (i,j,k,l) in { V, V }:
|
|
i = k and j < l and # Same row and left to right
|
|
card({ (s,t) in V: s = i and t > j and t < l }) = 0 # No vertex inbetween
|
|
};
|
|
|
|
/* Set of feasible vertical edges from (i,j) to (k,l) downwards */
|
|
set Ev := { (i,j,k,l) in { V, V }:
|
|
j = l and i < k and # Same column and top to bottom
|
|
card({ (s,t) in V: t = j and s > i and s < k }) = 0 # No vertex inbetween
|
|
};
|
|
|
|
set E := Eh union Ev;
|
|
|
|
/* Indicators: use edge once/twice */
|
|
var xe1{E}, binary;
|
|
var xe2{E}, binary;
|
|
|
|
/* Constraint: Do not use edge or do use once or do use twice */
|
|
s.t. edge_sel{(i,j,k,l) in E}:
|
|
xe1[i,j,k,l] + xe2[i,j,k,l] <= 1;
|
|
|
|
/* Constraint: There must be as many edges used as the node value */
|
|
s.t. satisfy_vertex_demand{(s,t) in V}:
|
|
sum{(i,j,k,l) in E: (i = s and j = t) or (k = s and l = t)}
|
|
(xe1[i,j,k,l] + 2.0*xe2[i,j,k,l]) = givens[s,t];
|
|
|
|
/* Constraint: No crossings */
|
|
s.t. no_crossing1{(i,j,k,l) in Eh, (s,t,u,v) in Ev:
|
|
s < i and u > i and j < t and l > t}:
|
|
xe1[i,j,k,l] + xe1[s,t,u,v] <= 1;
|
|
s.t. no_crossing2{(i,j,k,l) in Eh, (s,t,u,v) in Ev:
|
|
s < i and u > i and j < t and l > t}:
|
|
xe1[i,j,k,l] + xe2[s,t,u,v] <= 1;
|
|
s.t. no_crossing3{(i,j,k,l) in Eh, (s,t,u,v) in Ev:
|
|
s < i and u > i and j < t and l > t}:
|
|
xe2[i,j,k,l] + xe1[s,t,u,v] <= 1;
|
|
s.t. no_crossing4{(i,j,k,l) in Eh, (s,t,u,v) in Ev:
|
|
s < i and u > i and j < t and l > t}:
|
|
xe2[i,j,k,l] + xe2[s,t,u,v] <= 1;
|
|
|
|
|
|
/* Model connectivity by auxiliary network flow problem:
|
|
* One vertex becomes a target node and all other vertices send a unit flow
|
|
* to it. The edge selection variables xe1/xe2 are VUB constraints and
|
|
* therefore xe1/xe2 select the feasible graph for the max-flow problems.
|
|
*/
|
|
set node_target := { (s,t) in V:
|
|
card({ (i,j) in V: i < s or (i = s and j < t) }) = 0};
|
|
set node_sources := { (s,t) in V: (s,t) not in node_target };
|
|
|
|
var flow_forward{ E }, >= 0;
|
|
var flow_backward{ E }, >= 0;
|
|
s.t. flow_conservation{ (s,t) in node_target, (p,q) in V }:
|
|
/* All incoming flows */
|
|
- sum{(i,j,k,l) in E: k = p and l = q} flow_forward[i,j,k,l]
|
|
- sum{(i,j,k,l) in E: i = p and j = q} flow_backward[i,j,k,l]
|
|
/* All outgoing flows */
|
|
+ sum{(i,j,k,l) in E: k = p and l = q} flow_backward[i,j,k,l]
|
|
+ sum{(i,j,k,l) in E: i = p and j = q} flow_forward[i,j,k,l]
|
|
= 0 + (if (p = s and q = t) then card(node_sources) else -1);
|
|
|
|
/* Variable-Upper-Bound (VUB) constraints: xe1/xe2 bound the flows.
|
|
*/
|
|
s.t. connectivity_vub1{(i,j,k,l) in E}:
|
|
flow_forward[i,j,k,l] <= card(node_sources)*(xe1[i,j,k,l] + xe2[i,j,k,l]);
|
|
s.t. connectivity_vub2{(i,j,k,l) in E}:
|
|
flow_backward[i,j,k,l] <= card(node_sources)*(xe1[i,j,k,l] + xe2[i,j,k,l]);
|
|
|
|
/* A feasible solution is enough
|
|
*/
|
|
minimize cost: 0;
|
|
|
|
solve;
|
|
|
|
/* Output solution graphically */
|
|
printf "\nSolution:\n";
|
|
for { row in rows } {
|
|
for { col in cols } {
|
|
/* First print this cell information: givens or space */
|
|
printf{0..0: givens[row,col] != 0} "%d", givens[row,col];
|
|
printf{0..0: givens[row,col] = 0 and
|
|
card({(i,j,k,l) in Eh: i = row and col >= j and col < l and
|
|
xe1[i,j,k,l] = 1}) = 1} "-";
|
|
printf{0..0: givens[row,col] = 0 and
|
|
card({(i,j,k,l) in Eh: i = row and col >= j and col < l and
|
|
xe2[i,j,k,l] = 1}) = 1} "=";
|
|
printf{0..0: givens[row,col] = 0
|
|
and card({(i,j,k,l) in Ev: j = col and row >= i and row < k and
|
|
xe1[i,j,k,l] = 1}) = 1} "|";
|
|
printf{0..0: givens[row,col] = 0
|
|
and card({(i,j,k,l) in Ev: j = col and row >= i and row < k and
|
|
xe2[i,j,k,l] = 1}) = 1} '"';
|
|
printf{0..0: givens[row,col] = 0
|
|
and card({(i,j,k,l) in Eh: i = row and col >= j and col < l and
|
|
(xe1[i,j,k,l] = 1 or xe2[i,j,k,l] = 1)}) = 0
|
|
and card({(i,j,k,l) in Ev: j = col and row >= i and row < k and
|
|
(xe1[i,j,k,l] = 1 or xe2[i,j,k,l] = 1)}) = 0} " ";
|
|
|
|
/* Now print any edges */
|
|
printf{(i,j,k,l) in Eh: i = row and col >= j and col < l and xe1[i,j,k,l] = 1} "-";
|
|
printf{(i,j,k,l) in Eh: i = row and col >= j and col < l and xe2[i,j,k,l] = 1} "=";
|
|
|
|
printf{(i,j,k,l) in Eh: i = row and col >= j and col < l and
|
|
xe1[i,j,k,l] = 0 and xe2[i,j,k,l] = 0} " ";
|
|
printf{0..0: card({(i,j,k,l) in Eh: i = row and col >= j and col < l}) = 0} " ";
|
|
}
|
|
printf "\n";
|
|
for { col in cols } {
|
|
printf{(i,j,k,l) in Ev: j = col and row >= i and row < k and xe1[i,j,k,l] = 1} "|";
|
|
printf{(i,j,k,l) in Ev: j = col and row >= i and row < k and xe2[i,j,k,l] = 1} '"';
|
|
printf{(i,j,k,l) in Ev: j = col and row >= i and row < k and
|
|
xe1[i,j,k,l] = 0 and xe2[i,j,k,l] = 0} " ";
|
|
/* No vertical edges: skip also a field */
|
|
printf{0..0: card({(i,j,k,l) in Ev: j = col and row >= i and row < k}) = 0} " ";
|
|
printf " ";
|
|
}
|
|
printf "\n";
|
|
}
|
|
|
|
data;
|
|
|
|
/* This is a difficult 25x25 Hashiwokakero.
|
|
*/
|
|
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
|
|
25 :=
|
|
1 2 . 2 . 2 . . 2 . 2 . . 2 . . . . 2 . 2 . 2 . 2 .
|
|
2 . 1 . . . . 2 . . . 4 . . 5 . 2 . . 1 . 2 . 2 . 1
|
|
3 2 . . 5 . 4 . . 3 . . . . . 1 . . 4 . 5 . 1 . 1 .
|
|
4 . . . . . . . . . . . 1 . 3 . . 1 . . . . . . . .
|
|
5 2 . . 6 . 6 . . 8 . 5 . 2 . . 3 . 5 . 7 . . 2 . .
|
|
6 . 1 . . . . . . . . . 1 . . 2 . . . . . 1 . . . 3
|
|
7 2 . . . . 5 . . 6 . 4 . . 2 . . . 2 . 5 . 4 . 2 .
|
|
8 . 2 . 2 . . . . . . . . . . . 3 . . 3 . . . 1 . 2
|
|
9 . . . . . . . . . . 4 . 2 . 2 . . 1 . . . 3 . 1 .
|
|
10 2 . 3 . . 6 . . 2 . . . . . . . . . . 3 . . . . .
|
|
11 . . . . 1 . . 2 . . 5 . . 1 . 4 . 3 . . . . 2 . 4
|
|
12 . . 2 . . 1 . . . . . . 5 . 4 . . . . 4 . 3 . . .
|
|
13 2 . . . 3 . 1 . . . . . . . . 3 . . 5 . 5 . . 2 .
|
|
14 . . . . . 2 . 5 . . 7 . 5 . 3 . 1 . . 1 . . 1 . 4
|
|
15 2 . 5 . 3 . . . . 1 . 2 . 1 . . . . 2 . 4 . . 2 .
|
|
16 . . . . . 1 . . . . . . . . . . 2 . . 2 . 1 . . 3
|
|
17 2 . 6 . 6 . . 2 . . 2 . 2 . 5 . . . . . 2 . . . .
|
|
18 . . . . . 1 . . . 3 . . . . . 1 . . 1 . . 4 . 3 .
|
|
19 . . 4 . 5 . . 2 . . . 2 . . 6 . 6 . . 3 . . . . 3
|
|
20 2 . . . . . . . . . 2 . . 1 . . . . . . 1 . . 1 .
|
|
21 . . 3 . . 3 . 5 . 5 . . 4 . 6 . 7 . . 4 . 6 . . 4
|
|
22 2 . . . 3 . 5 . 2 . 1 . . . . . . . . . . . . . .
|
|
23 . . . . . . . . . 1 . . . . . . 3 . 2 . . 5 . . 5
|
|
24 2 . 3 . 3 . 5 . 4 . 3 . 3 . 4 . . 2 . 2 . . . 1 .
|
|
25 . 1 . 2 . 2 . . . 2 . 2 . . . 2 . . . . 2 . 2 . 2
|
|
;
|
|
|
|
end;
|