-
Notifications
You must be signed in to change notification settings - Fork 2
/
hashi.mod
168 lines (147 loc) · 7.53 KB
/
hashi.mod
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
/* 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;