Stop the analysis pass in Loopy's redraw routine from being
[sgt/puzzles] / dsf.c
CommitLineData
f1010613 1/*
121aae4b 2 * dsf.c: some functions to handle a disjoint set forest,
f1010613 3 * which is a data structure useful in any solver which has to
4 * worry about avoiding closed loops.
5 */
6
121aae4b 7#include <assert.h>
8#include <string.h>
9
986cc2de 10#include "puzzles.h"
11
1a739e2f 12/*void print_dsf(int *dsf, int size)
f1010613 13{
121aae4b 14 int *printed_elements = snewn(size, int);
15 int *equal_elements = snewn(size, int);
16 int *inverse_elements = snewn(size, int);
17 int printed_count = 0, equal_count, inverse_count;
18 int i, n, inverse;
19
20 memset(printed_elements, -1, sizeof(int) * size);
f1010613 21
121aae4b 22 while (1) {
23 equal_count = 0;
24 inverse_count = 0;
25 for (i = 0; i < size; ++i) {
26 if (!memchr(printed_elements, i, sizeof(int) * size))
27 break;
28 }
29 if (i == size)
30 goto done;
f1010613 31
121aae4b 32 i = dsf_canonify(dsf, i);
33
34 for (n = 0; n < size; ++n) {
35 if (edsf_canonify(dsf, n, &inverse) == i) {
36 if (inverse)
37 inverse_elements[inverse_count++] = n;
38 else
39 equal_elements[equal_count++] = n;
40 }
41 }
42
43 for (n = 0; n < equal_count; ++n) {
44 fprintf(stderr, "%d ", equal_elements[n]);
45 printed_elements[printed_count++] = equal_elements[n];
46 }
47 if (inverse_count) {
48 fprintf(stderr, "!= ");
49 for (n = 0; n < inverse_count; ++n) {
50 fprintf(stderr, "%d ", inverse_elements[n]);
51 printed_elements[printed_count++] = inverse_elements[n];
52 }
53 }
54 fprintf(stderr, "\n");
f1010613 55 }
121aae4b 56done:
f1010613 57
121aae4b 58 sfree(printed_elements);
59 sfree(equal_elements);
60 sfree(inverse_elements);
1a739e2f 61}*/
121aae4b 62
74198235 63void dsf_init(int *dsf, int size)
121aae4b 64{
65 int i;
74198235 66
8b3b3223 67 for (i = 0; i < size; i++) dsf[i] = 6;
68 /* Bottom bit of each element of this array stores whether that
69 * element is opposite to its parent, which starts off as
70 * false. Second bit of each element stores whether that element
71 * is the root of its tree or not. If it's not the root, the
72 * remaining 30 bits are the parent, otherwise the remaining 30
73 * bits are the number of elements in the tree. */
74198235 74}
75
76int *snew_dsf(int size)
77{
78 int *ret;
79
80 ret = snewn(size, int);
81 dsf_init(ret, size);
121aae4b 82
83 /*print_dsf(ret, size); */
84
85 return ret;
86}
87
88int dsf_canonify(int *dsf, int index)
89{
90 return edsf_canonify(dsf, index, NULL);
f1010613 91}
92
93void dsf_merge(int *dsf, int v1, int v2)
94{
121aae4b 95 edsf_merge(dsf, v1, v2, FALSE);
f1010613 96}
66a74a18 97
8b3b3223 98int dsf_size(int *dsf, int index) {
99 return dsf[dsf_canonify(dsf, index)] >> 2;
100}
101
121aae4b 102int edsf_canonify(int *dsf, int index, int *inverse_return)
66a74a18 103{
121aae4b 104 int start_index = index, canonical_index;
105 int inverse = 0;
106
107/* fprintf(stderr, "dsf = %p\n", dsf); */
108/* fprintf(stderr, "Canonify %2d\n", index); */
109
110 assert(index >= 0);
111
112 /* Find the index of the canonical element of the 'equivalence class' of
113 * which start_index is a member, and figure out whether start_index is the
114 * same as or inverse to that. */
8b3b3223 115 while ((dsf[index] & 2) == 0) {
121aae4b 116 inverse ^= (dsf[index] & 1);
8b3b3223 117 index = dsf[index] >> 2;
121aae4b 118/* fprintf(stderr, "index = %2d, ", index); */
119/* fprintf(stderr, "inverse = %d\n", inverse); */
120 }
121 canonical_index = index;
122
123 if (inverse_return)
124 *inverse_return = inverse;
125
126 /* Update every member of this 'equivalence class' to point directly at the
127 * canonical member. */
128 index = start_index;
129 while (index != canonical_index) {
8b3b3223 130 int nextindex = dsf[index] >> 2;
121aae4b 131 int nextinverse = inverse ^ (dsf[index] & 1);
8b3b3223 132 dsf[index] = (canonical_index << 2) | inverse;
121aae4b 133 inverse = nextinverse;
134 index = nextindex;
135 }
136
137 assert(inverse == 0);
138
139/* fprintf(stderr, "Return %2d\n", index); */
140
141 return index;
142}
143
144void edsf_merge(int *dsf, int v1, int v2, int inverse)
145{
146 int i1, i2;
8b3b3223 147
121aae4b 148/* fprintf(stderr, "dsf = %p\n", dsf); */
149/* fprintf(stderr, "Merge [%2d,%2d], %d\n", v1, v2, inverse); */
150
151 v1 = edsf_canonify(dsf, v1, &i1);
8b3b3223 152 assert(dsf[v1] & 2);
121aae4b 153 inverse ^= i1;
154 v2 = edsf_canonify(dsf, v2, &i2);
8b3b3223 155 assert(dsf[v2] & 2);
121aae4b 156 inverse ^= i2;
157
158/* fprintf(stderr, "Doing [%2d,%2d], %d\n", v1, v2, inverse); */
159
160 if (v1 == v2)
161 assert(!inverse);
8b3b3223 162 else {
163 assert(inverse == 0 || inverse == 1);
07682b79 164 /*
165 * We always make the smaller of v1 and v2 the new canonical
166 * element. This ensures that the canonical element of any
167 * class in this structure is always the first element in
c8c23a7f 168 * it. 'Keen' depends critically on this property.
07682b79 169 *
170 * (Jonas Koelker previously had this code choosing which
171 * way round to connect the trees by examining the sizes of
172 * the classes being merged, so that the root of the
173 * larger-sized class became the new root. This gives better
174 * asymptotic performance, but I've changed it to do it this
175 * way because I like having a deterministic canonical
176 * element.)
177 */
178 if (v1 > v2) {
8b3b3223 179 int v3 = v1;
180 v1 = v2;
181 v2 = v3;
182 }
183 dsf[v1] += (dsf[v2] >> 2) << 2;
184 dsf[v2] = (v1 << 2) | !!inverse;
185 }
121aae4b 186
187 v2 = edsf_canonify(dsf, v2, &i2);
188 assert(v2 == v1);
189 assert(i2 == inverse);
66a74a18 190
121aae4b 191/* fprintf(stderr, "dsf[%2d] = %2d\n", v2, dsf[v2]); */
66a74a18 192}