examples/hashi.mod
author Alpar Juttner <alpar@cs.elte.hu>
Mon, 06 Dec 2010 13:09:21 +0100
changeset 1 c445c931472f
permissions -rw-r--r--
Import glpk-4.45

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