Commit eef943717e684b6713d306f59ac369edb4104387
1 parent
a2ec137b
Exists in
master
Update to PaCCS version 0.91
* Renamed _fd_* output functions to fd__* (meaning that they are intended to be private to the library) and put them in the new util.h file. * Use fd__trace() and -DTRACE to produce tracing messages. fd__debug() is now reserved for real debugging output. * Use fd_const() to create variables with singleton domains. * New poly-le-k constraint. * Include paccs.h where possible. * Committed to INDEX_IN_POOL and CONSTRAINT_CLASS. * Improved domain filtering for le, lt, poly-eq, poly-eq-k and var-eq-minus. * Decoupled recording that a constraint is entailed from using CONSTRAINT_TEMPS. (Use -DDISABLE_ENTAILED to disable.)
Showing
75 changed files
with
1655 additions
and
1467 deletions
Show diff stats
Makefile
... | ... | @@ -34,11 +34,11 @@ CPPFLAGS = -I$(SRC) $(ALL_DEFINES) |
34 | 34 | |
35 | 35 | EXTRA_DEFINES = |
36 | 36 | |
37 | -DEFINES = -DFAST # -DNDEBUG | |
38 | -DEFAULTS = -DREVISION_IS_VAR -DGROWABLE_POOL -DINDEX_IN_POOL -DSTORE_IN_POOL \ | |
37 | +DEFINES = # -DTRACE -DNDEBUG | |
38 | +DEFAULTS = -DREVISION_IS_VAR -DGROWABLE_POOL -DSTORE_IN_POOL \ | |
39 | 39 | -DNEW_ENTRANCE -DRANDOM_VICTIM -DDOMAIN_BOUNDS |
40 | -REQUIRED = -DDISTRIBUTED_SOLVER -DSPLITGO -DCOMPACT_DOMAINS -DCONSTRAINT_CLASS \ | |
41 | - -DUSE_STORE -DPACK_PROBLEM | |
40 | +REQUIRED = -DDISTRIBUTED_SOLVER -DSPLITGO -DCOMPACT_DOMAINS -DUSE_STORE \ | |
41 | + -DPACK_PROBLEM | |
42 | 42 | |
43 | 43 | ALL_DEFINES = $(REQUIRED) $(DEFAULTS) $(DEFINES) $(EXTRA_DEFINES) |
44 | 44 | |
... | ... | @@ -119,6 +119,8 @@ list.o: $(SRC)/list.c $(SRC)/list.h |
119 | 119 | values.o: values.h values-bitmap.c values-intervals.c fdc_int.h |
120 | 120 | |
121 | 121 | |
122 | +queens queens-mpi : override DEFAULTS += -DDISABLE_ENTAILED | |
123 | + | |
122 | 124 | costas costas-mpi : override DEFAULTS += -DCONSTRAINT_TEMPS |
123 | 125 | |
124 | 126 | qap qap-mpi : override DEFAULTS += \ |
... | ... | @@ -131,7 +133,7 @@ graphs graphs-mpi : matching.c |
131 | 133 | |
132 | 134 | partition partition-mpi : override DEFAULTS += -DCONSTRAINT_TEMPS |
133 | 135 | |
134 | -golomb golomb-mpi : override DEFAULTS += -DDOMAIN_BOUNDS | |
136 | +golomb golomb-mpi : override DEFAULTS += -DDOMAIN_BOUNDS -DDOMAIN_BITS=128 | |
135 | 137 | |
136 | 138 | langford langford-mpi : override DEFAULTS += \ |
137 | 139 | -UDOMAIN_BOUNDS -DINLINE_DOMAINS -DCONSTRAINT_TEMPS -DDISABLE_ENTAILED |
... | ... |
README
1 | -PaCCS version 0.90d | |
1 | +PaCCS version 0.91 | |
2 | 2 | |
3 | 3 | All files Copyright (C) 2009-2016 Vasco Pedro <vp@di.uevora.pt> |
4 | 4 | All rights reserved. |
... | ... | @@ -38,7 +38,7 @@ Useful options include: |
38 | 38 | -DDOMAIN_BOUNDS include the domain's current minimum and maximum values |
39 | 39 | in its representation (DEFAULT) |
40 | 40 | |
41 | - -DFAST be quiet (DEFAULT) | |
41 | + -DTRACE show what's happening (part of it, anyway) | |
42 | 42 | |
43 | 43 | For other options, take a look at the Makefile, at src/options.c, or |
44 | 44 | at the full solver source. |
... | ... | @@ -150,6 +150,8 @@ Integer constants |
150 | 150 | |
151 | 151 | fd_int fd_new(int min, int max) create a new variable with domain |
152 | 152 | [min, max] |
153 | + fd_int fd_const(int value) create a new variable with domain | |
154 | + [value, value] | |
153 | 155 | fd_label(fd_int vars[], int nvars) set variables to be labelled (the |
154 | 156 | DEFAULT is to label all variables) |
155 | 157 | fd_var_single(fd_int var, int *val) tests whether the variable domain |
... | ... | @@ -181,6 +183,10 @@ Global constraints |
181 | 183 | fd_all_different(fd_int X[], int n) |
182 | 184 | all n variables in X have different values |
183 | 185 | |
186 | + fd_fake_all_different(fd_int X[], int n) | |
187 | + all-different implemented with pairwise fd_ne() constraints | |
188 | + between the variables in X | |
189 | + | |
184 | 190 | fd_element(fd_int X[], int n, fd_int y, int k) X[y] = k |
185 | 191 | fd_element_var(fd_int X[], int n, fd_int y, fd_int z) X[y] = z |
186 | 192 | |
... | ... | @@ -191,6 +197,7 @@ Global constraints |
191 | 197 | |
192 | 198 | fd_poly_eq(int C[], fd_int Y[], int n, fd_int z) z <= C . Y <= z |
193 | 199 | fd_poly_eq_k(int C[], fd_int Y[], int n, int k) C . Y = k |
200 | + fd_poly_le_k(int C[], fd_int Y[], int n, int k) C . Y <= k | |
194 | 201 | fd_poly_ne(int C[], fd_int Y[], int n, fd_int z) C . Y != z |
195 | 202 | fd_poly_ne_k(int C[], fd_int Y[], int n, int k) C . Y != k |
196 | 203 | fd_knapsack2(fd_int X[], fd_int Y[], int n, fd_int z) z <= X . Y <= z |
... | ... |
TUNING
... | ... | @@ -11,11 +11,14 @@ qap |
11 | 11 | costas |
12 | 12 | -DCONSTRAINT_TEMPS -DDOMAIN_BOUNDS |
13 | 13 | --label --most-constrained |
14 | + (--label --first-var performs better in some cases, at least for the 1st solution) | |
15 | + | |
14 | 16 | --split-even (first solution) |
15 | 17 | |
16 | 18 | N <= DOMAIN_BITS / 2 |
17 | 19 | |
18 | 20 | queens |
21 | + -DDISABLE_ENTAILED | |
19 | 22 | -DDOMAIN_BOUNDS ??? [not ism] |
20 | 23 | --first-fail |
21 | 24 | |
... | ... | @@ -41,7 +44,7 @@ golomb |
41 | 44 | -DDOMAIN_BOUNDS (-DCONSTRAINT_TEMPS -DDISABLE_ENTAILED [cri-lima]) |
42 | 45 | --label{, --most-connected, --most-constrained} |
43 | 46 | --split-eager |
44 | - (--split-even is generally slower, but more regular) | |
47 | + (--split-even is generally slower, but more stable) | |
45 | 48 | |
46 | 49 | langford |
47 | 50 | [bicho] |
... | ... | @@ -59,13 +62,15 @@ langford |
59 | 62 | -DINLINE_DOMAINS -DCONSTRAINT_TEMPS (third best) |
60 | 63 | -DDOMAIN_BOUNDS -DCONSTRAINT_TEMPS -DDISABLE_ENTAILED (fourth best) |
61 | 64 | -DDOMAIN_BOUNDS (fifth best) |
62 | - | |
63 | - --first-fail --val-max (--count-solutions or failure) | |
64 | - --size-degree --val-max (first solution, not always but when | |
65 | - it works, the effect is dramatic) | |
65 | + [*] | |
66 | + ? -DDOMAIN_BOUNDS | |
66 | 67 | |
67 | 68 | --split-eager |
68 | 69 | |
70 | + --first-fail {,--val-max} (--count-solutions or inconsistent instances) | |
71 | + --size-degree (first solution) | |
72 | + (--first --val-max is a good overall compromise) | |
73 | + | |
69 | 74 | golfers |
70 | 75 | -D? |
71 | 76 | --label --val-max? |
... | ... |
bench/all.c
... | ... | @@ -28,7 +28,7 @@ int main(int argc, char *argv[]) |
28 | 28 | NV = atoi(argv[i]); |
29 | 29 | |
30 | 30 | if (NV > MAX_VARIABLES) |
31 | - _fd_fatal("more than MAX_VARIABLES variables requested"); | |
31 | + fd__fatal("more than MAX_VARIABLES variables requested"); | |
32 | 32 | |
33 | 33 | for (i = 0; i < NV; ++i) |
34 | 34 | vars[i] = fd_new(0, MV); |
... | ... |
bench/bibd.c
... | ... | @@ -33,7 +33,7 @@ int main(int argc, char *argv[]) |
33 | 33 | #ifndef GECODE_STYLE |
34 | 34 | else if (argc - i < 3) |
35 | 35 | { |
36 | - _fd_debug("must give V, B, and K (or nothing)\n"); | |
36 | + fd__error("must give V, B, and K (or nothing)\n"); | |
37 | 37 | return 1; |
38 | 38 | } |
39 | 39 | else |
... | ... | @@ -47,7 +47,7 @@ int main(int argc, char *argv[]) |
47 | 47 | |
48 | 48 | if (R * V != K * B) |
49 | 49 | { |
50 | - _fd_debug("%d * %d / %d must be an integer\n", K, B, V); | |
50 | + fd__error("%d * %d / %d must be an integer\n", K, B, V); | |
51 | 51 | return 1; |
52 | 52 | } |
53 | 53 | |
... | ... | @@ -55,13 +55,13 @@ int main(int argc, char *argv[]) |
55 | 55 | |
56 | 56 | if (lambda * (V - 1) != R * (K - 1)) |
57 | 57 | { |
58 | - _fd_debug("%d * (%d - 1) / (%d - 1) must be an integer\n", R, K, V); | |
58 | + fd__error("%d * (%d - 1) / (%d - 1) must be an integer\n", R, K, V); | |
59 | 59 | return 1; |
60 | 60 | } |
61 | 61 | #else /* GECODE_STYLE */ |
62 | 62 | else if (argc - i < 3) |
63 | 63 | { |
64 | - _fd_debug("must give V, K, and lambda (or nothing)\n"); | |
64 | + fd__error("must give V, K, and lambda (or nothing)\n"); | |
65 | 65 | return 1; |
66 | 66 | } |
67 | 67 | else |
... | ... | @@ -75,7 +75,7 @@ int main(int argc, char *argv[]) |
75 | 75 | |
76 | 76 | if (B * K * (K - 1) != lambda * V * (V - 1)) |
77 | 77 | { |
78 | - _fd_debug("warning: %d * %d * (%d - 1) / %d / (%d - 1) must be an integer\n", | |
78 | + fd__error("warning: %d * %d * (%d - 1) / %d / (%d - 1) must be an integer\n", | |
79 | 79 | lambda, V, V, K, K); |
80 | 80 | // return 1; |
81 | 81 | } |
... | ... | @@ -84,12 +84,12 @@ int main(int argc, char *argv[]) |
84 | 84 | |
85 | 85 | if (R * V != K * B) |
86 | 86 | { |
87 | - _fd_debug("warning: %d * %d / %d must be an integer\n", K, B, V); | |
87 | + fd__error("warning: %d * %d / %d must be an integer\n", K, B, V); | |
88 | 88 | // return 1; |
89 | 89 | } |
90 | 90 | #endif /* GECODE_STYLE */ |
91 | 91 | |
92 | - _fd_debug("V = %d, B = %d, K = %d, R = %d, lambda = %d\n", V, B, K, R, lambda); | |
92 | + fd__info("V = %d, B = %d, K = %d, R = %d, lambda = %d\n", V, B, K, R, lambda); | |
93 | 93 | |
94 | 94 | vs = calloc(V * B, sizeof(fd_int)); |
95 | 95 | ts = calloc(V > B ? V : B, sizeof(fd_int)); |
... | ... |
bench/c-exactly.c
bench/change.c
1 | 1 | #include <stdio.h> |
2 | +#include <stdlib.h> | |
2 | 3 | #include <fcntl.h> |
3 | 4 | #include <errno.h> |
4 | 5 | #include <ctype.h> |
... | ... | @@ -6,13 +7,6 @@ |
6 | 7 | |
7 | 8 | #include "fdc_int.h" |
8 | 9 | |
9 | -// try to save on variables | |
10 | -static fd_int fd_const[MAX_VALUE + 1]; | |
11 | - | |
12 | -#define FD_CONST(n) (fd_const[n] ? fd_const[n] : (fd_const[n] = fd_new(n, n))) | |
13 | - | |
14 | -//#define FD_CONST(n) fd_new(n, n) | |
15 | - | |
16 | 10 | #define NCOINS (sizeof(coins_value) / sizeof(*coins_value)) |
17 | 11 | |
18 | 12 | int coins_value[] = { 1, 2, 5, 10, 20, 50 }; |
... | ... | @@ -33,15 +27,15 @@ int main(int argc, char *argv[]) |
33 | 27 | else if (isdigit(*argv[i])) |
34 | 28 | am = atoi(argv[i]); |
35 | 29 | else |
36 | - _fd_error("%s: unknown argument `%s'\n", argv[0], argv[i]); | |
30 | + fd__error("%s: unknown argument `%s'\n", argv[0], argv[i]); | |
37 | 31 | |
38 | 32 | for (i = 0; i < NCOINS; ++i) |
39 | - coins[i] = FD_CONST(coins_value[i]); | |
33 | + coins[i] = fd_const(coins_value[i]); | |
40 | 34 | |
41 | 35 | for (i = 0; i < NCOINS; ++i) |
42 | 36 | change[i] = fd_new(0, MAX_VALUE); |
43 | 37 | |
44 | - amount = FD_CONST(am); | |
38 | + amount = fd_const(am); | |
45 | 39 | fd_knapsack2(change, coins, NCOINS, amount); |
46 | 40 | |
47 | 41 | ncoins = fd_new(0, MAX_VALUE); |
... | ... |
bench/costas.c
... | ... | @@ -3,17 +3,10 @@ |
3 | 3 | |
4 | 4 | //#include <fcntl.h> |
5 | 5 | //#include <errno.h> |
6 | -//#include <ctype.h> | |
6 | +#include <ctype.h> | |
7 | 7 | #include <string.h> |
8 | 8 | |
9 | -#include "fdc_int.h" | |
10 | - | |
11 | -// try to save on variables | |
12 | -static fd_int fd_const[MAX_VALUE + 1]; | |
13 | - | |
14 | -#define FD_CONST(n) (fd_const[n] ? fd_const[n] : (fd_const[n] = fd_new(n, n))) | |
15 | - | |
16 | -//#define FD_CONST(n) fd_new(n, n) | |
9 | +#include <paccs.h> | |
17 | 10 | |
18 | 11 | /* |
19 | 12 | Costas arrays (communicated by Daniel Diaz) |
... | ... | @@ -57,7 +50,7 @@ int main(int argc, char *argv[]) |
57 | 50 | break; |
58 | 51 | } |
59 | 52 | else |
60 | - _fd_error("%s: unknown option `%s'\n", argv[0], argv[i]); | |
53 | + fd__error("%s: unknown option `%s'\n", argv[0], argv[i]); | |
61 | 54 | |
62 | 55 | array = calloc(N, sizeof(*array)); |
63 | 56 | |
... | ... | @@ -69,7 +62,7 @@ int main(int argc, char *argv[]) |
69 | 62 | if (strchr(argv[i], '-')) |
70 | 63 | b = atoi(strchr(argv[i], '-') + 1); |
71 | 64 | |
72 | - array[j] = (a == b) ? FD_CONST(a - 1) : fd_new(a - 1, b - 1); | |
65 | + array[j] = fd_new(a - 1, b - 1); | |
73 | 66 | } |
74 | 67 | |
75 | 68 | for (; j < N; ++j) |
... | ... | @@ -91,7 +84,7 @@ int main(int argc, char *argv[]) |
91 | 84 | for (j = 0; j < N - 1 - i; ++j) |
92 | 85 | diffs(i, j) = fd_new(0, 2 * (N - 1)); |
93 | 86 | |
94 | - diffeq[0] = FD_CONST(N - 1); | |
87 | + diffeq[0] = fd_const(N - 1); | |
95 | 88 | |
96 | 89 | for (k = 1; k < N - 1; ++k) |
97 | 90 | { |
... | ... |
bench/golfers.c
bench/golomb.c
... | ... | @@ -74,17 +74,17 @@ int main(int argc, char *argv[]) |
74 | 74 | seed = time(0); |
75 | 75 | #else |
76 | 76 | if ((dev_random = open("/dev/urandom", O_RDONLY)) == -1) |
77 | - _fd_fatal("/dev/urandom: %s\n", strerror(errno)); | |
77 | + fd__fatal("/dev/urandom: %s\n", strerror(errno)); | |
78 | 78 | |
79 | 79 | read(dev_random, &seed, sizeof(seed)); |
80 | 80 | #endif |
81 | 81 | |
82 | 82 | srandom(seed); |
83 | - _fd_debug("seed = %u\n", seed); | |
83 | + fd__trace("seed = %u\n", seed); | |
84 | 84 | #endif |
85 | 85 | |
86 | 86 | if (!fixed) |
87 | - _fd_debug("length upper bound is %d\n", DOMMAX); | |
87 | + fd__trace("length upper bound is %d\n", DOMMAX); | |
88 | 88 | |
89 | 89 | D = M * (M - 1) / 2; |
90 | 90 | |
... | ... | @@ -147,7 +147,7 @@ int main(int argc, char *argv[]) |
147 | 147 | j = 0; |
148 | 148 | for (d = 1; d < M; ++d) |
149 | 149 | { |
150 | - fd_int s = fd_new(d * (d + 1) / 2, d * (d + 1) / 2); | |
150 | + fd_int s = fd_const(d * (d + 1) / 2); | |
151 | 151 | |
152 | 152 | for (i = d; i < M; ++i) |
153 | 153 | fd_ge(differences[j++], s); |
... | ... | @@ -157,7 +157,7 @@ int main(int argc, char *argv[]) |
157 | 157 | j = 0; |
158 | 158 | for (d = 1; d < M; ++d) |
159 | 159 | { |
160 | - fd_int grl = fd_new(minimum_length[d + 1], minimum_length[d + 1]); | |
160 | + fd_int grl = fd_const(minimum_length[d + 1]); | |
161 | 161 | |
162 | 162 | for (i = d; i < M; ++i) |
163 | 163 | fd_ge(differences[j++], grl); |
... | ... |
bench/graphs.c
bench/k-queens.c
1 | 1 | #include <stdio.h> |
2 | +#include <stdlib.h> | |
2 | 3 | #include <string.h> |
3 | 4 | #include <fcntl.h> |
4 | 5 | #include <errno.h> |
... | ... | @@ -16,8 +17,6 @@ int main(int argc, char *argv[]) |
16 | 17 | fd_int queens[NMAX]; |
17 | 18 | int solutions = 0, one_solution = 1; |
18 | 19 | int i, j; |
19 | - int seed; | |
20 | - int dev_random; | |
21 | 20 | fd_int copy; |
22 | 21 | int ncopies = 4; |
23 | 22 | |
... | ... | @@ -41,7 +40,7 @@ int main(int argc, char *argv[]) |
41 | 40 | } |
42 | 41 | |
43 | 42 | if (N > NMAX) |
44 | - _fd_fatal("queens: more than NMAX queens requested"); | |
43 | + fd__fatal("queens: more than NMAX queens requested"); | |
45 | 44 | |
46 | 45 | if (ncopies < 1) |
47 | 46 | ncopies = 1; |
... | ... | @@ -49,20 +48,23 @@ int main(int argc, char *argv[]) |
49 | 48 | copy = fd_new(0, ncopies - 1); // XXX: only allows MAX_VALUE+1 copies |
50 | 49 | |
51 | 50 | #ifdef LOCAL_SEARCH |
51 | + int seed; | |
52 | 52 | #if 01 |
53 | 53 | seed = time(0); |
54 | 54 | seed = 1206987119; |
55 | 55 | //seed = 1207917731; // N = 6, best improvement termina |
56 | 56 | //seed = 0; |
57 | 57 | #else |
58 | - if ((dev_random = open("/dev/urandom", O_RDONLY)) == -1) | |
59 | - _fd_fatal("/dev/urandom: %s\n", strerror(errno)); | |
58 | + int dev_random; | |
59 | + | |
60 | + if ((dev_random = open("/dev/urandom", O_RDONLY)) == -1) | |
61 | + fd__fatal("/dev/urandom: %s\n", strerror(errno)); | |
60 | 62 | |
61 | 63 | read(dev_random, &seed, sizeof(seed)); |
62 | 64 | #endif |
63 | 65 | |
64 | 66 | srandom(seed); |
65 | - _fd_debug("seed = %u\n", seed); | |
67 | + fd__trace("seed = %u\n", seed); | |
66 | 68 | #endif |
67 | 69 | |
68 | 70 | /* |
... | ... | @@ -118,7 +120,7 @@ int main(int argc, char *argv[]) |
118 | 120 | { |
119 | 121 | int j; |
120 | 122 | |
121 | - _fd_error("\nsolution contains non-singleton variable\n"); | |
123 | + fd__error("\nsolution contains non-singleton variable\n"); | |
122 | 124 | |
123 | 125 | for (j = 0; j < N; ++j) |
124 | 126 | { |
... | ... |
bench/langford.c
1 | 1 | #include <stdio.h> |
2 | +#include <stdlib.h> | |
2 | 3 | #include <string.h> |
4 | +#include <ctype.h> | |
3 | 5 | |
4 | -#include "fdc_int.h" | |
6 | +#include <paccs.h> | |
5 | 7 | |
6 | 8 | // Langford's number problem (CSPLib 024) |
7 | 9 | |
... | ... | @@ -58,7 +60,7 @@ int main(int argc, char *argv[]) |
58 | 60 | break; |
59 | 61 | else |
60 | 62 | { |
61 | - _fd_error("%s: invalid argument `%s'\n", argv[0], argv[arg]); | |
63 | + fd__error("%s: invalid argument `%s'\n", argv[0], argv[arg]); | |
62 | 64 | |
63 | 65 | return 2; |
64 | 66 | } |
... | ... | @@ -74,7 +76,7 @@ int main(int argc, char *argv[]) |
74 | 76 | //seed = 1206468701; |
75 | 77 | //seed = 1208196137; // converges to a local minimum with MCH |
76 | 78 | srandom(seed); |
77 | - _fd_debug("seed = %u\n", seed); | |
79 | + fd__trace("seed = %u\n", seed); | |
78 | 80 | #endif |
79 | 81 | |
80 | 82 | for (i = 0; arg < argc; ++arg, ++i) |
... | ... |
bench/magic-seq.c
1 | 1 | #include <stdio.h> |
2 | +#include <stdlib.h> | |
3 | +#include <string.h> | |
2 | 4 | |
3 | -#include "fdc_int.h" | |
5 | +#include <paccs.h> | |
4 | 6 | |
5 | 7 | #define MAX_N 512 |
6 | 8 | |
... | ... | @@ -20,7 +22,7 @@ main(int argc, char *argv[]) |
20 | 22 | N = atoi(argv[i]); |
21 | 23 | |
22 | 24 | if (N > MAX_N) |
23 | - _fd_fatal("N > MAX_N"); | |
25 | + fd__fatal("N > MAX_N"); | |
24 | 26 | |
25 | 27 | for (i = 0; i < N; ++i) |
26 | 28 | vs[i] = fd_new(0, N - 1); |
... | ... |
bench/magic-square.c
1 | 1 | #include <stdio.h> |
2 | +#include <stdlib.h> | |
2 | 3 | #include <string.h> |
3 | 4 | #include <fcntl.h> |
4 | 5 | #include <errno.h> |
5 | 6 | |
6 | -#include "fdc_int.h" | |
7 | +#include <paccs.h> | |
7 | 8 | |
8 | 9 | // (CSPLib 019) |
9 | 10 | |
... | ... | @@ -37,7 +38,7 @@ int main(int argc, char *argv[]) |
37 | 38 | } |
38 | 39 | |
39 | 40 | if (N > NMAX) |
40 | - _fd_fatal("magic-square: maximum order exceeded"); | |
41 | + fd__fatal("magic-square: maximum order exceeded"); | |
41 | 42 | |
42 | 43 | j = 0; |
43 | 44 | for (++i; i < argc; ++i) |
... | ... | @@ -158,7 +159,7 @@ int main(int argc, char *argv[]) |
158 | 159 | for (l = 0; l < N; ++l) |
159 | 160 | for (c = 0; c < N; ++c) |
160 | 161 | if (!fd_var_single(square[l][c], NULL)) |
161 | - _fd_fatal("solution contains non-singleton variable"); | |
162 | + fd__fatal("solution contains non-singleton variable"); | |
162 | 163 | #endif |
163 | 164 | |
164 | 165 | for (l = 0; l < N; ++l) |
... | ... |
bench/money.c
bench/partition.c
... | ... | @@ -3,8 +3,9 @@ |
3 | 3 | |
4 | 4 | #include <stdio.h> |
5 | 5 | #include <stdlib.h> |
6 | +#include <string.h> | |
6 | 7 | |
7 | -#include "fdc_int.h" | |
8 | +#include <paccs.h> | |
8 | 9 | |
9 | 10 | int main(int argc, char *argv[]) |
10 | 11 | { |
... | ... | @@ -25,7 +26,7 @@ int main(int argc, char *argv[]) |
25 | 26 | |
26 | 27 | if ((vs = malloc(2 * N * sizeof(*vs))) == NULL || |
27 | 28 | (sqs0 = malloc(N * sizeof(*sqs0))) == NULL) |
28 | - _fd_fatal("could not allocate enough memory"); | |
29 | + fd__fatal("could not allocate enough memory"); | |
29 | 30 | |
30 | 31 | values = 2 * N; |
31 | 32 | sum = N * (2 * N + 1); |
... | ... |
bench/qap.c
... | ... | @@ -21,13 +21,6 @@ |
21 | 21 | |
22 | 22 | #include "fdc_int.h" |
23 | 23 | |
24 | -// try to save on variables | |
25 | -static fd_int fd_const[MAX_VALUE + 1]; | |
26 | - | |
27 | -#define FD_CONST(n) (fd_const[n] ? fd_const[n] : (fd_const[n] = fd_new(n, n))) | |
28 | - | |
29 | -//#define FD_CONST(n) fd_new(n, n) | |
30 | - | |
31 | 24 | #define NMAX 128 |
32 | 25 | |
33 | 26 | typedef struct { |
... | ... | @@ -249,7 +242,7 @@ int main(int argc, char *argv[]) |
249 | 242 | ; |
250 | 243 | else |
251 | 244 | { |
252 | - _fd_error("%s: invalid argument `%s'\n", argv[0], argv[j]); | |
245 | + fd__error("%s: invalid argument `%s'\n", argv[0], argv[j]); | |
253 | 246 | |
254 | 247 | return 2; |
255 | 248 | } |
... | ... | @@ -260,10 +253,10 @@ int main(int argc, char *argv[]) |
260 | 253 | N = P->size; |
261 | 254 | |
262 | 255 | if (N > NMAX) |
263 | - _fd_fatal("qap: problem too big (increase NMAX)"); | |
256 | + fd__fatal("qap: problem too big (increase NMAX)"); | |
264 | 257 | #ifdef QAP_MODEL_B |
265 | 258 | if (N * N > DOMAIN_BITS) |
266 | - _fd_fatal("qap: problem too big (model B) (increase DOMAIN_BITS)"); | |
259 | + fd__fatal("qap: problem too big (model B) (increase DOMAIN_BITS)"); | |
267 | 260 | #endif |
268 | 261 | |
269 | 262 | if (swap) |
... | ... | @@ -272,7 +265,7 @@ int main(int argc, char *argv[]) |
272 | 265 | } |
273 | 266 | |
274 | 267 | if (P->name) |
275 | - _fd_debug("%s\n", P->name); | |
268 | + fd__trace("%s\n", P->name); | |
276 | 269 | |
277 | 270 | { |
278 | 271 | int diag_cost = 0, tb = 0; |
... | ... | @@ -284,7 +277,7 @@ int main(int argc, char *argv[]) |
284 | 277 | for (c = 0; c < N; ++c) |
285 | 278 | tb += Pflow(l, c) * Pdist(l, c); |
286 | 279 | |
287 | - _fd_debug("tight bound %d (diagonal %d)\n", tb, diag_cost); | |
280 | + fd__trace("tight bound %d (diagonal %d)\n", tb, diag_cost); | |
288 | 281 | } |
289 | 282 | |
290 | 283 | // see if the problem is symmetric |
... | ... | @@ -317,11 +310,11 @@ int main(int argc, char *argv[]) |
317 | 310 | |
318 | 311 | if (symmetrical) |
319 | 312 | if (symmetrical0) |
320 | - _fd_debug("symmetrical problem with 0 diagonal\n"); | |
313 | + fd__trace("symmetrical problem with 0 diagonal\n"); | |
321 | 314 | else |
322 | - _fd_debug("symmetrical problem\n"); | |
315 | + fd__trace("symmetrical problem\n"); | |
323 | 316 | else |
324 | - _fd_debug("asymmetrical problem (%d, %d)\n", l, c); | |
317 | + fd__trace("asymmetrical problem (%d, %d)\n", l, c); | |
325 | 318 | |
326 | 319 | if (generic) |
327 | 320 | symmetrical0 = 0; |
... | ... | @@ -405,7 +398,7 @@ int main(int argc, char *argv[]) |
405 | 398 | // the *transpose* of the distance matrix |
406 | 399 | for (l = 0; l < N; ++l) |
407 | 400 | for (c = 0; c < N; ++c) |
408 | - distt[l][c] = FD_CONST(Pdist(c, l)); | |
401 | + distt[l][c] = fd_const(Pdist(c, l)); | |
409 | 402 | |
410 | 403 | for (l = 0; l < N; ++l) |
411 | 404 | for (c = 0; c < N; ++c) |
... | ... | @@ -430,7 +423,7 @@ int main(int argc, char *argv[]) |
430 | 423 | |
431 | 424 | for (l = 0; l < N; ++l) |
432 | 425 | for (c = 0; c < N; ++c) |
433 | - distt[l][c] = FD_CONST(Pflow(l, c)); | |
426 | + distt[l][c] = fd_const(Pflow(l, c)); | |
434 | 427 | |
435 | 428 | for (l = 0; l < N; ++l) |
436 | 429 | fd_knapsack2(ndist[l], distt[l], N, sums[l]); |
... | ... | @@ -443,7 +436,7 @@ int main(int argc, char *argv[]) |
443 | 436 | for (c = 0; c < N; ++c) |
444 | 437 | { |
445 | 438 | prods[0][i] = ndist[l][c]; |
446 | - prods[1][i] = FD_CONST(Pflow(l, c)); | |
439 | + prods[1][i] = fd_const(Pflow(l, c)); | |
447 | 440 | |
448 | 441 | ++i; |
449 | 442 | } |
... | ... | @@ -471,7 +464,7 @@ int main(int argc, char *argv[]) |
471 | 464 | |
472 | 465 | for (l = 1; l < N; ++l) |
473 | 466 | for (c = 0; c < l; ++c) |
474 | - distt[l][c] = FD_CONST(Pflow(l, c)); | |
467 | + distt[l][c] = fd_const(Pflow(l, c)); | |
475 | 468 | |
476 | 469 | for (l = 1; l < N; ++l) |
477 | 470 | fd_knapsack2(ndist[l], distt[l], l, sums[l - 1]); |
... | ... | @@ -484,7 +477,7 @@ int main(int argc, char *argv[]) |
484 | 477 | for (c = 0; c < l; ++c) |
485 | 478 | { |
486 | 479 | prods[0][i] = ndist[l][c]; |
487 | - prods[1][i] = FD_CONST(Pflow(l, c)); | |
480 | + prods[1][i] = fd_const(Pflow(l, c)); | |
488 | 481 | |
489 | 482 | ++i; |
490 | 483 | } |
... | ... | @@ -499,7 +492,7 @@ int main(int argc, char *argv[]) |
499 | 492 | for (c = 0; c < l; ++c) |
500 | 493 | { |
501 | 494 | prods[0][i] = ndist[l][c]; |
502 | - prods[1][i] = FD_CONST(Pflow(l, c)); | |
495 | + prods[1][i] = fd_const(Pflow(l, c)); | |
503 | 496 | |
504 | 497 | ++i; |
505 | 498 | } |
... | ... | @@ -540,7 +533,7 @@ int main(int argc, char *argv[]) |
540 | 533 | |
541 | 534 | // distances |
542 | 535 | for (i = 0; i < N * N; ++i) |
543 | - dist[i] = FD_CONST(P->dist[i]); | |
536 | + dist[i] = fd_const(P->dist[i]); | |
544 | 537 | |
545 | 538 | // costs |
546 | 539 | |
... | ... | @@ -585,8 +578,8 @@ int main(int argc, char *argv[]) |
585 | 578 | |
586 | 579 | for (l = 0; l < N; ++l) |
587 | 580 | { |
588 | - new_dist[l * N + l] = FD_CONST(0); | |
589 | - npos[l * N + l] = FD_CONST(0); | |
581 | + new_dist[l * N + l] = fd_const(0); | |
582 | + npos[l * N + l] = fd_const(0); | |
590 | 583 | } |
591 | 584 | |
592 | 585 | for (l = 1; l < N; ++l) |
... | ... |
bench/queens.c
1 | 1 | #include <stdio.h> |
2 | +#include <stdlib.h> | |
2 | 3 | #include <string.h> |
3 | 4 | #include <fcntl.h> |
4 | 5 | #include <errno.h> |
... | ... | @@ -32,7 +33,7 @@ int main(int argc, char *argv[]) |
32 | 33 | } |
33 | 34 | |
34 | 35 | if (N > NMAX) |
35 | - _fd_fatal("queens: more than NMAX queens requested"); | |
36 | + fd__fatal("queens: more than NMAX queens requested"); | |
36 | 37 | |
37 | 38 | #ifdef LOCAL_SEARCH |
38 | 39 | #if 01 |
... | ... | @@ -42,13 +43,13 @@ int main(int argc, char *argv[]) |
42 | 43 | //seed = 0; |
43 | 44 | #else |
44 | 45 | if ((dev_random = open("/dev/urandom", O_RDONLY)) == -1) |
45 | - _fd_fatal("/dev/urandom: %s\n", strerror(errno)); | |
46 | + fd__fatal("/dev/urandom: %s\n", strerror(errno)); | |
46 | 47 | |
47 | 48 | read(dev_random, &seed, sizeof(seed)); |
48 | 49 | #endif |
49 | 50 | |
50 | 51 | srandom(seed); |
51 | - _fd_debug("seed = %u\n", seed); | |
52 | + fd__trace("seed = %u\n", seed); | |
52 | 53 | #endif |
53 | 54 | |
54 | 55 | /* |
... | ... | @@ -104,7 +105,7 @@ int main(int argc, char *argv[]) |
104 | 105 | { |
105 | 106 | int j; |
106 | 107 | |
107 | - _fd_error("\nsolution contains non-singleton variable\n"); | |
108 | + fd__error("\nsolution contains non-singleton variable\n"); | |
108 | 109 | |
109 | 110 | |
110 | 111 | for (j = 0; j < N; ++j) |
... | ... |
bench/queens2.c
1 | 1 | /* solves two unconnected queens problems */ |
2 | 2 | |
3 | 3 | #include <stdio.h> |
4 | +#include <stdlib.h> | |
5 | +#include <string.h> | |
4 | 6 | #include <fcntl.h> |
5 | 7 | #include <errno.h> |
6 | 8 | |
7 | -#include "fdc_int.h" | |
9 | +#include <paccs.h> | |
8 | 10 | |
9 | 11 | #define NMAX 200 // maximum number of queens |
10 | 12 | |
... | ... | @@ -75,8 +77,6 @@ int main(int argc, char *argv[]) |
75 | 77 | fd_int queens[2 * NMAX]; |
76 | 78 | int solutions = 0, one_solution = 1; |
77 | 79 | int i, j; |
78 | - int seed; | |
79 | - int dev_random; | |
80 | 80 | |
81 | 81 | fd_init(&argc, &argv); |
82 | 82 | |
... | ... | @@ -92,20 +92,23 @@ int main(int argc, char *argv[]) |
92 | 92 | } |
93 | 93 | |
94 | 94 | #ifdef LOCAL_SEARCH |
95 | + int seed; | |
95 | 96 | #if 01 |
96 | 97 | seed = time(0); |
97 | 98 | seed = 1206987119; |
98 | 99 | //seed = 1207917731; // N = 6, best improvement termina |
99 | 100 | //seed = 0; |
100 | 101 | #else |
101 | - if ((dev_random = open("/dev/urandom", O_RDONLY)) == -1) | |
102 | - _fd_fatal("/dev/urandom: %s\n", strerror(errno)); | |
102 | + int dev_random; | |
103 | + | |
104 | + if ((dev_random = open("/dev/urandom", O_RDONLY)) == -1) | |
105 | + fd__fatal("/dev/urandom: %s\n", strerror(errno)); | |
103 | 106 | |
104 | 107 | read(dev_random, &seed, sizeof(seed)); |
105 | 108 | #endif |
106 | 109 | |
107 | 110 | srandom(seed); |
108 | - _fd_debug("seed = %u\n", seed); | |
111 | + fd__trace("seed = %u\n", seed); | |
109 | 112 | #endif |
110 | 113 | |
111 | 114 | init_queens(queens, N1); |
... | ... | @@ -120,7 +123,7 @@ int main(int argc, char *argv[]) |
120 | 123 | #if 01 |
121 | 124 | for (i = 0; i < N1; ++i) |
122 | 125 | if (!fd_var_single(queens[i], NULL)) |
123 | - _fd_fatal("solution contains non-singleton variable"); | |
126 | + fd__fatal("solution contains non-singleton variable"); | |
124 | 127 | #endif |
125 | 128 | |
126 | 129 | for (i = 0; i < N1; ++i) |
... | ... | @@ -135,7 +138,7 @@ int main(int argc, char *argv[]) |
135 | 138 | #if 01 |
136 | 139 | for (i = N1; i < N1 + N2; ++i) |
137 | 140 | if (!fd_var_single(queens[i], NULL)) |
138 | - _fd_fatal("solution contains non-singleton variable"); | |
141 | + fd__fatal("solution contains non-singleton variable"); | |
139 | 142 | #endif |
140 | 143 | |
141 | 144 | for (i = N1; i < N1 + N2; ++i) |
... | ... |
bench/sudoku.c
1 | 1 | #include <stdio.h> |
2 | +#include <stdlib.h> | |
3 | +#include <string.h> | |
2 | 4 | |
3 | -#include "fdc_int.h" | |
5 | +#include <paccs.h> | |
4 | 6 | |
5 | 7 | #define floor_sqrt(s, n) {for ((s) = 0; (s) * (s) <= (n); ++(s)); --(s);} |
6 | 8 | |
... | ... | @@ -316,7 +318,7 @@ void constrain_piece(fd_int *variables, int nvariables) |
316 | 318 | #endif |
317 | 319 | } |
318 | 320 | |
319 | -main(int argc, char *argv[]) | |
321 | +int main(int argc, char *argv[]) | |
320 | 322 | { |
321 | 323 | fd_int board[N][N]; |
322 | 324 | sudoku_i *problem; |
... | ... | @@ -324,16 +326,17 @@ main(int argc, char *argv[]) |
324 | 326 | int sqrN; |
325 | 327 | int solutions = 0, one_solution = 1; |
326 | 328 | int i, j, np = -1; |
327 | - int seed; | |
328 | 329 | |
329 | 330 | fd_init(&argc, &argv); |
330 | 331 | |
331 | 332 | #ifdef LOCAL_SEARCH |
333 | + int seed; | |
334 | + | |
332 | 335 | seed = time(0); |
333 | 336 | //seed = 1206468701; |
334 | 337 | seed = 1208196137; // converges to a local minimum with MCH |
335 | 338 | srandom(seed); |
336 | - _fd_debug("seed = %u\n", seed); | |
339 | + fd__trace("seed = %u\n", seed); | |
337 | 340 | #endif |
338 | 341 | |
339 | 342 | for (i = 1; i < argc; ++i) |
... | ... |
bench/times.c
src/VERSION
src/agents-splitgo-mpi.c
... | ... | @@ -17,6 +17,8 @@ |
17 | 17 | #include "splitting.h" |
18 | 18 | #include "bound.h" |
19 | 19 | |
20 | +#include "util.h" | |
21 | + | |
20 | 22 | #ifndef COMPACT_DOMAINS |
21 | 23 | #error "only works with COMPACT_DOMAINS" |
22 | 24 | #endif |
... | ... | @@ -135,7 +137,7 @@ void _fd_statistics_msgs() |
135 | 137 | { |
136 | 138 | extern int tid; |
137 | 139 | |
138 | - _fd_output("[%d] messages: %lu sent, %lu received\n", tid, _fd_msgs_sent, | |
140 | + fd__output("[%d] messages: %lu sent, %lu received\n", tid, _fd_msgs_sent, | |
139 | 141 | _fd_msgs_received); |
140 | 142 | } |
141 | 143 | #else /* STATS_MSGS */ |
... | ... | @@ -214,7 +216,7 @@ int _fd_agent(int n) |
214 | 216 | int result; |
215 | 217 | struct timeval ti, tis, to, tos; |
216 | 218 | |
217 | - _fd_debug("[%d.%d] agent starting\n", tid, n); | |
219 | + fd__trace("[%d.%d] agent starting\n", tid, n); | |
218 | 220 | |
219 | 221 | gettimeofday(&ti, NULL); |
220 | 222 | |
... | ... | @@ -238,17 +240,17 @@ int _fd_agent(int n) |
238 | 240 | gettimeofday(&to, NULL); |
239 | 241 | timersub(&to, &tis, &tos); |
240 | 242 | timersub(&to, &ti, &to); |
241 | - _fd_debug("[%d.%d] took %d.%06ds (%d.%06ds)\n", tid, n, | |
243 | + fd__trace("[%d.%d] took %d.%06ds (%d.%06ds)\n", tid, n, | |
242 | 244 | tos.tv_sec, tos.tv_usec, to.tv_sec, to.tv_usec); |
243 | 245 | |
244 | 246 | while (result == FD_OK) |
245 | 247 | { |
246 | - _fd_debug("[%d.%d] agent was successful\n", tid, n); | |
248 | + fd__trace("[%d.%d] agent was successful\n", tid, n); | |
247 | 249 | |
248 | 250 | // ensure that only one agent signals its success |
249 | 251 | // XXX: only good (?) if only looking for the 1st solution |
250 | 252 | pthread_mutex_lock(&success_mutex); |
251 | - _fd_debug("[%d.%d] acquired success mutex\n", tid, n); | |
253 | + fd__trace("[%d.%d] acquired success mutex\n", tid, n); | |
252 | 254 | |
253 | 255 | // tell the main thread that this agent is done |
254 | 256 | if (sem_wait(&ready_semaphore)) |
... | ... | @@ -260,14 +262,14 @@ int _fd_agent(int n) |
260 | 262 | perror("sem_post"); |
261 | 263 | |
262 | 264 | pthread_mutex_unlock(&success_mutex); |
263 | - _fd_debug("[%d.%d] released success mutex\n", tid, n); | |
265 | + fd__trace("[%d.%d] released success mutex\n", tid, n); | |
264 | 266 | |
265 | 267 | if (!_fd_optimising) |
266 | 268 | break; |
267 | 269 | |
268 | 270 | if (sem_wait(&resume_semaphore)) |
269 | 271 | perror("sem_post (resume)"); |
270 | - _fd_debug("[%d.%d] resuming, new bound is %d\n", tid, n, _fd_bound_value()); | |
272 | + fd__trace("[%d.%d] resuming, new bound is %d\n", tid, n, _fd_bound_value()); | |
271 | 273 | |
272 | 274 | // find the next solution |
273 | 275 | gettimeofday(&tis, NULL); |
... | ... | @@ -277,7 +279,7 @@ int _fd_agent(int n) |
277 | 279 | gettimeofday(&to, NULL); |
278 | 280 | timersub(&to, &tis, &tos); |
279 | 281 | timersub(&to, &ti, &to); |
280 | - _fd_debug("[%d.%d] took %d.%06ds (%d.%06ds)\n", tid, n, | |
282 | + fd__trace("[%d.%d] took %d.%06ds (%d.%06ds)\n", tid, n, | |
281 | 283 | tos.tv_sec, tos.tv_usec, to.tv_sec, to.tv_usec); |
282 | 284 | } |
283 | 285 | |
... | ... | @@ -286,7 +288,7 @@ int _fd_agent(int n) |
286 | 288 | break; |
287 | 289 | |
288 | 290 | // eventually, the agent will fail to find a solution |
289 | - _fd_debug("[%d.%d] agent was unsuccessful\n", tid, n); | |
291 | + fd__trace("[%d.%d] agent was unsuccessful\n", tid, n); | |
290 | 292 | |
291 | 293 | // tell the main thread that this agent is done |
292 | 294 | if (sem_wait(&ready_semaphore)) |
... | ... | @@ -304,7 +306,7 @@ int _fd_agent(int n) |
304 | 306 | #if STEAL_WORK >= 2 |
305 | 307 | do { |
306 | 308 | // wait for more work |
307 | - _fd_debug("[%d.%d] waiting for more work\n", tid, n); | |
309 | + fd__trace("[%d.%d] waiting for more work\n", tid, n); | |
308 | 310 | pthread_cond_wait(&continue_cond, &continue_mutex); |
309 | 311 | } while(n >= agents_to_run); |
310 | 312 | |
... | ... | @@ -325,7 +327,7 @@ int _fd_agent(int n) |
325 | 327 | unsigned long long solutions; |
326 | 328 | struct timeval ti, tis, to, tos; |
327 | 329 | |
328 | - _fd_debug("[%d.%d] agent starting\n", tid, n); | |
330 | + fd__trace("[%d.%d] agent starting\n", tid, n); | |
329 | 331 | |
330 | 332 | gettimeofday(&ti, NULL); |
331 | 333 | |
... | ... | @@ -346,10 +348,10 @@ int _fd_agent(int n) |
346 | 348 | gettimeofday(&to, NULL); |
347 | 349 | timersub(&to, &tis, &tos); |
348 | 350 | timersub(&to, &ti, &to); |
349 | - _fd_debug("[%d.%d] took %d.%06ds (%d.%06ds)\n", tid, n, | |
351 | + fd__trace("[%d.%d] took %d.%06ds (%d.%06ds)\n", tid, n, | |
350 | 352 | tos.tv_sec, tos.tv_usec, to.tv_sec, to.tv_usec); |
351 | 353 | |
352 | - _fd_debug("[%d.%d] found %llu solutions\n", tid, n, solutions); | |
354 | + fd__trace("[%d.%d] found %llu solutions\n", tid, n, solutions); | |
353 | 355 | |
354 | 356 | // tell the main thread that this agent is done |
355 | 357 | if (sem_wait(&ready_semaphore)) |
... | ... | @@ -370,7 +372,7 @@ int _fd_agent(int n) |
370 | 372 | #if STEAL_WORK >= 2 |
371 | 373 | do { |
372 | 374 | // wait for more work |
373 | - _fd_debug("[%d.%d] waiting for more work\n", tid, n); | |
375 | + fd__trace("[%d.%d] waiting for more work\n", tid, n); | |
374 | 376 | pthread_cond_wait(&continue_cond, &continue_mutex); |
375 | 377 | } while (n >= agents_to_run); |
376 | 378 | |
... | ... | @@ -406,7 +408,7 @@ static void _fd_send(int to, int tag) |
406 | 408 | MPI_Request mpi_request = MPI_REQUEST_NULL; |
407 | 409 | |
408 | 410 | if (MPI_Isend(NULL, 0, MPI_CHAR, to, tag, MPI_COMM_WORLD, &mpi_request)) |
409 | - _fd_fatal("MPI_Isend failed"); | |
411 | + fd__fatal("MPI_Isend failed"); | |
410 | 412 | } |
411 | 413 | |
412 | 414 | /* send TO a message with data (non-blocking) */ |
... | ... | @@ -415,7 +417,7 @@ static void _fd_send_data(int to, int tag, void *buf, int n, MPI_Datatype type) |
415 | 417 | MPI_Request mpi_request = MPI_REQUEST_NULL; |
416 | 418 | |
417 | 419 | if (MPI_Isend(buf, n, type, to, tag, MPI_COMM_WORLD, &mpi_request)) |
418 | - _fd_fatal("MPI_Isend failed"); | |
420 | + fd__fatal("MPI_Isend failed"); | |
419 | 421 | } |
420 | 422 | |
421 | 423 | #if STEAL_WORK >= 2 |
... | ... | @@ -427,26 +429,26 @@ static void _fd_ssend_data(int to, int tag, void *buf, int n, MPI_Datatype type, |
427 | 429 | { |
428 | 430 | #ifndef MAD_MPI |
429 | 431 | if (MPI_Issend(buf, n, type, to, tag, MPI_COMM_WORLD, request)) |
430 | - _fd_fatal("MPI_Issend failed"); | |
432 | + fd__fatal("MPI_Issend failed"); | |
431 | 433 | |
432 | 434 | #if 0 |
433 | 435 | { |
434 | 436 | int mpi_flag; |
435 | 437 | |
436 | - _fd_debug("[%d] MPI_Test = %d\n", tid, | |
438 | + fd__debug("[%d] MPI_Test = %d\n", tid, | |
437 | 439 | MPI_Test(request, &mpi_flag, MPI_STATUS_IGNORE)); |
438 | 440 | |
439 | 441 | if (mpi_flag) |
440 | - _fd_debug("[%d] send completed\n", tid); | |
442 | + fd__debug("[%d] send completed\n", tid); | |
441 | 443 | else |
442 | - _fd_debug("[%d] send didn't complete yet\n", tid); | |
444 | + fd__debug("[%d] send didn't complete yet\n", tid); | |
443 | 445 | } |
444 | 446 | #endif |
445 | 447 | #else /* MAD_MPI */ |
446 | 448 | // XXX: NMAD doesn't have MPI_Issend |
447 | 449 | // XXX: no record of the sending is left |
448 | 450 | if (MPI_Ssend(buf, n, type, to, tag, MPI_COMM_WORLD)) |
449 | - _fd_fatal("MPI_Send failed"); | |
451 | + fd__fatal("MPI_Send failed"); | |
450 | 452 | |
451 | 453 | *request = MPI_REQUEST_NULL; |
452 | 454 | #endif /* MAD_MPI */ |
... | ... | @@ -456,7 +458,7 @@ static void _fd_ssend_data(int to, int tag, void *buf, int n, MPI_Datatype type, |
456 | 458 | MPI_Request mpi_request = MPI_REQUEST_NULL; |
457 | 459 | |
458 | 460 | if (MPI_Isend(buf, n, type, to, tag, MPI_COMM_WORLD, &mpi_request)) |
459 | - _fd_fatal("MPI_Isend failed"); | |
461 | + fd__fatal("MPI_Isend failed"); | |
460 | 462 | } |
461 | 463 | } |
462 | 464 | #endif /* STEAL_WORK >= 2 */ |
... | ... | @@ -466,7 +468,7 @@ static void fd__send_empty_store(int to, int tag, _fd_store buffer, |
466 | 468 | { |
467 | 469 | if (MPI_Isend(buffer, 0, MPI_DOMAIN_TYPE, |
468 | 470 | to, tag, MPI_COMM_WORLD, request)) |
469 | - _fd_fatal("MPI_Isend failed"); | |
471 | + fd__fatal("MPI_Isend failed"); | |
470 | 472 | } |
471 | 473 | |
472 | 474 | static void _fd_send_store(int to, int tag, _fd_store buffer, |
... | ... | @@ -481,7 +483,7 @@ static void _fd_send_store(int to, int tag, _fd_store buffer, |
481 | 483 | { |
482 | 484 | if (MPI_Isend(buffer, fd_variables_count * DOMAIN_WORDS, MPI_DOMAIN_TYPE, |
483 | 485 | to, tag, MPI_COMM_WORLD, request)) |
484 | - _fd_fatal("MPI_Isend failed"); | |
486 | + fd__fatal("MPI_Isend failed"); | |
485 | 487 | } |
486 | 488 | } |
487 | 489 | |
... | ... | @@ -492,7 +494,7 @@ static int _fd_recv_store(int from, int tag, _fd_store buffer) |
492 | 494 | |
493 | 495 | if (MPI_Recv(buffer, fd_variables_count * DOMAIN_WORDS, MPI_DOMAIN_TYPE, |
494 | 496 | from, tag, MPI_COMM_WORLD, &status)) |
495 | - _fd_fatal("MPI_Recv failed"); | |
497 | + fd__fatal("MPI_Recv failed"); | |
496 | 498 | |
497 | 499 | MPI_Get_count(&status, MPI_DOMAIN_TYPE, &count); |
498 | 500 | |
... | ... | @@ -511,7 +513,7 @@ static void _fd_broadcast(int msg, int processes, int from) |
511 | 513 | mpi_request = malloc(sizeof(MPI_Request)); |
512 | 514 | |
513 | 515 | if (MPI_Isend(NULL, 0, MPI_CHAR, i, msg, MPI_COMM_WORLD, mpi_request)) |
514 | - _fd_fatal("MPI_Isend failed"); | |
516 | + fd__fatal("MPI_Isend failed"); | |
515 | 517 | |
516 | 518 | fd_list_append(pending_requests, mpi_request); |
517 | 519 | } |
... | ... | @@ -522,7 +524,7 @@ static void _fd_broadcast(int msg, int processes, int from) |
522 | 524 | for (i = 0; i < processes; ++i) |
523 | 525 | if (i != from) |
524 | 526 | if (MPI_Isend(NULL, 0, MPI_CHAR, i, msg, MPI_COMM_WORLD, &mpi_request)) |
525 | - _fd_fatal("MPI_Isend failed"); | |
527 | + fd__fatal("MPI_Isend failed"); | |
526 | 528 | #endif |
527 | 529 | } |
528 | 530 | |
... | ... | @@ -560,9 +562,9 @@ static bool _fd_probe_external(int tag, char *name, int *source, bool consume) |
560 | 562 | if (s) |
561 | 563 | { |
562 | 564 | char es[1024]; int _; |
563 | - _fd_debug("MPI_Iprobe %s returned %d\n", name, s); | |
565 | + fd__debug("MPI_Iprobe %s returned %d\n", name, s); | |
564 | 566 | MPI_Error_string(s, es, &_); |
565 | - _fd_debug("%s\n", es); | |
567 | + fd__debug("%s\n", es); | |
566 | 568 | } |
567 | 569 | #endif |
568 | 570 | |
... | ... | @@ -570,13 +572,13 @@ static bool _fd_probe_external(int tag, char *name, int *source, bool consume) |
570 | 572 | { |
571 | 573 | *source = mpi_status.MPI_SOURCE; |
572 | 574 | |
573 | - _fd_debug("[%d] got %s from %d\n", tid, name, *source); | |
575 | + fd__trace("[%d] got %s from %d\n", tid, name, *source); | |
574 | 576 | |
575 | 577 | // consume message |
576 | 578 | if (consume) |
577 | 579 | if (MPI_Recv(NULL, 0, MPI_CHAR, mpi_status.MPI_SOURCE, tag, |
578 | 580 | MPI_COMM_WORLD, &mpi_status)) |
579 | - _fd_fatal("MPI_Recv failed"); | |
581 | + fd__fatal("MPI_Recv failed"); | |
580 | 582 | |
581 | 583 | return true; |
582 | 584 | } |
... | ... | @@ -590,7 +592,7 @@ static int _fd_get_event(int running, int *source, int *timeout) |
590 | 592 | double tin, tmout = 0; |
591 | 593 | int event; |
592 | 594 | |
593 | - _fd_debug("[%d] getting next event\n", tid); | |
595 | + fd__trace("[%d] getting next event\n", tid); | |
594 | 596 | |
595 | 597 | if (timeout && *timeout) |
596 | 598 | { |
... | ... | @@ -606,14 +608,14 @@ static int _fd_get_event(int running, int *source, int *timeout) |
606 | 608 | if (sem_trywait(¬ify_semaphore)) |
607 | 609 | { |
608 | 610 | if (errno == EAGAIN) |
609 | - ; //_fd_debug("[%d] notify semaphore is busy\n", tid); | |
611 | + ; //fd__trace("[%d] notify semaphore is busy\n", tid); | |
610 | 612 | else |
611 | 613 | perror("sem_trywait (notify)"); |
612 | 614 | } |
613 | 615 | else |
614 | 616 | { |
615 | 617 | // got something from one of the agents |
616 | - _fd_debug("[%d] got something from an agent\n", tid); | |
618 | + fd__trace("[%d] got something from an agent\n", tid); | |
617 | 619 | |
618 | 620 | if (!_fd_counting_solutions) |
619 | 621 | { |
... | ... | @@ -622,7 +624,7 @@ static int _fd_get_event(int running, int *source, int *timeout) |
622 | 624 | if (sem_post(&ready_semaphore)) |
623 | 625 | perror("sem_post"); |
624 | 626 | |
625 | - _fd_debug("[%d] got an answer from %s%d\n", tid, | |
627 | + fd__trace("[%d] got an answer from %s%d\n", tid, | |
626 | 628 | s == -1 ? "-" : "", s + (s < 0)); |
627 | 629 | |
628 | 630 | if (s >= 0) |
... | ... | @@ -719,17 +721,17 @@ static int _fd_get_event(int running, int *source, int *timeout) |
719 | 721 | event = EV_EXT_READY; |
720 | 722 | break; |
721 | 723 | default: |
722 | - _fd_debug("[%d] unknown tag %d\n", tid, mpi_status.MPI_TAG); | |
723 | - _fd_fatal("unknown tag in message"); | |
724 | + fd__debug("[%d] unknown tag %d\n", tid, mpi_status.MPI_TAG); | |
725 | + fd__fatal("unknown tag in message"); | |
724 | 726 | } |
725 | 727 | |
726 | - _fd_debug("[%d] got %s from %d\n", tid, name, *source); | |
728 | + fd__trace("[%d] got %s from %d\n", tid, name, *source); | |
727 | 729 | |
728 | 730 | // consume message |
729 | 731 | if (consume) |
730 | 732 | if (MPI_Recv(NULL, 0, MPI_CHAR, mpi_status.MPI_SOURCE, |
731 | 733 | mpi_status.MPI_TAG, MPI_COMM_WORLD, &mpi_status)) |
732 | - _fd_fatal("MPI_Recv failed"); | |
734 | + fd__fatal("MPI_Recv failed"); | |
733 | 735 | |
734 | 736 | break; |
735 | 737 | } |
... | ... | @@ -862,22 +864,22 @@ static void _fd_flush_events(int procno) |
862 | 864 | while (mpi_request = fd_list_remove(pending_requests)) |
863 | 865 | { |
864 | 866 | if (MPI_Test(mpi_request, &mpi_flag, MPI_STATUS_IGNORE)) |
865 | - _fd_debug("[%d] MPI_Test failed\n", procno); | |
867 | + fd__debug("[%d] MPI_Test failed\n", procno); | |
866 | 868 | |
867 | 869 | if (!mpi_flag) |
868 | 870 | { |
869 | 871 | #if 0 // this is probably the solution just sent, not cancelling it |
870 | - _fd_debug("[%d] cancelling request\n", procno); | |
872 | + fd__trace("[%d] cancelling request\n", procno); | |
871 | 873 | |
872 | 874 | if (MPI_Cancel(mpi_request)) |
873 | - _fd_debug("[%d] MPI_Cancel failed\n", procno); | |
875 | + fd__debug("[%d] MPI_Cancel failed\n", procno); | |
874 | 876 | |
875 | - _fd_debug("[%d] waiting for cancellation completion\n", procno); | |
877 | + fd__trace("[%d] waiting for cancellation completion\n", procno); | |
876 | 878 | |
877 | 879 | if (MPI_Wait(mpi_request, MPI_STATUS_IGNORE)) |
878 | - _fd_debug("[%d] MPI_Wait failed\n", procno); | |
880 | + fd__debug("[%d] MPI_Wait failed\n", procno); | |
879 | 881 | #else |
880 | - _fd_debug("[%d] found a not completed request\n", procno); | |
882 | + fd__debug("[%d] found a not completed request\n", procno); | |
881 | 883 | #endif |
882 | 884 | } |
883 | 885 | |
... | ... | @@ -911,7 +913,7 @@ static void _fd_flush_events(int procno) |
911 | 913 | name = "FD_MSG_SOLUTION"; |
912 | 914 | type = MPI_DOMAIN_TYPE; |
913 | 915 | count = fd_variables_count * DOMAIN_WORDS; |
914 | - _fd_error("[%d] dropping %s from %d\n", tid, name, source); | |
916 | + fd__error("[%d] dropping %s from %d\n", tid, name, source); | |
915 | 917 | break; |
916 | 918 | case FD_MSG_FAIL: |
917 | 919 | name = "FD_MSG_FAIL"; |
... | ... | @@ -928,13 +930,13 @@ static void _fd_flush_events(int procno) |
928 | 930 | name = "FD_MSG_COUNT"; |
929 | 931 | type = MPI_LONG_LONG; |
930 | 932 | count = 1; |
931 | - _fd_error("[%d] dropping %s from %d\n", tid, name, source); | |
933 | + fd__error("[%d] dropping %s from %d\n", tid, name, source); | |
932 | 934 | break; |
933 | 935 | case FD_MSG_STORE: |
934 | 936 | name = "FD_MSG_STORE"; |
935 | 937 | type = MPI_DOMAIN_TYPE; |
936 | 938 | count = fd_variables_count * DOMAIN_WORDS; |
937 | - _fd_error("[%d] *** dropping %s from %d\n", tid, name, source); | |
939 | + fd__error("[%d] *** dropping %s from %d\n", tid, name, source); | |
938 | 940 | break; |
939 | 941 | case FD_MSG_FEED_ME: |
940 | 942 | name = "FD_MSG_FEED_ME"; |
... | ... | @@ -955,11 +957,11 @@ static void _fd_flush_events(int procno) |
955 | 957 | name = "FD_MSG_READY"; |
956 | 958 | break; |
957 | 959 | default: |
958 | - _fd_debug("[%d] unknown tag %d\n", tid, mpi_status.MPI_TAG); | |
959 | - _fd_fatal("unknown tag in message"); | |
960 | + fd__debug("[%d] unknown tag %d\n", tid, mpi_status.MPI_TAG); | |
961 | + fd__fatal("unknown tag in message"); | |
960 | 962 | } |
961 | 963 | |
962 | - _fd_debug("[%d] dropping %s from %d\n", tid, name, source); | |
964 | + fd__debug("[%d] dropping %s from %d\n", tid, name, source); | |
963 | 965 | |
964 | 966 | // consume message |
965 | 967 | { |
... | ... | @@ -967,7 +969,7 @@ static void _fd_flush_events(int procno) |
967 | 969 | |
968 | 970 | if (MPI_Recv(buffer, count, type, source, mpi_status.MPI_TAG, |
969 | 971 | MPI_COMM_WORLD, MPI_STATUS_IGNORE)) |
970 | - _fd_error("[%d] MPI_Recv failed (dropping %s)\n", tid, name); | |
972 | + fd__error("[%d] MPI_Recv failed (dropping %s)\n", tid, name); | |
971 | 973 | } |
972 | 974 | } |
973 | 975 | #else /* MAD_MPI */ |
... | ... | @@ -986,7 +988,7 @@ static void _fd_flush_events(int procno) |
986 | 988 | { |
987 | 989 | _fd_store null = alloca(fd_variables_count * sizeof(*null)); |
988 | 990 | |
989 | - _fd_debug("[%d] dropping FD_MSG_SOLUTION from %d\n", procno, mpi_status.MPI_SOURCE); | |
991 | + fd__trace("[%d] dropping FD_MSG_SOLUTION from %d\n", procno, mpi_status.MPI_SOURCE); | |
990 | 992 | |
991 | 993 | _fd_recv_store(mpi_status.MPI_SOURCE, FD_MSG_SOLUTION, null); |
992 | 994 | |
... | ... | @@ -997,12 +999,12 @@ static void _fd_flush_events(int procno) |
997 | 999 | |
998 | 1000 | if (mpi_flag) |
999 | 1001 | { |
1000 | - _fd_debug("[%d] dropping FD_MSG_FEED_ME from %d\n", procno, mpi_status.MPI_SOURCE); | |
1002 | + fd__trace("[%d] dropping FD_MSG_FEED_ME from %d\n", procno, mpi_status.MPI_SOURCE); | |
1001 | 1003 | |
1002 | 1004 | // consume message |
1003 | 1005 | if (MPI_Recv(NULL, 0, MPI_CHAR, mpi_status.MPI_SOURCE, FD_MSG_FEED_ME, |
1004 | 1006 | MPI_COMM_WORLD, &mpi_status)) |
1005 | - _fd_fatal("MPI_Recv failed"); | |
1007 | + fd__fatal("MPI_Recv failed"); | |
1006 | 1008 | |
1007 | 1009 | got_one++; |
1008 | 1010 | } |
... | ... | @@ -1011,12 +1013,12 @@ static void _fd_flush_events(int procno) |
1011 | 1013 | |
1012 | 1014 | if (mpi_flag) |
1013 | 1015 | { |
1014 | - _fd_debug("[%d] dropping FD_MSG_NO_WORK from %d\n", procno, mpi_status.MPI_SOURCE); | |
1016 | + fd__trace("[%d] dropping FD_MSG_NO_WORK from %d\n", procno, mpi_status.MPI_SOURCE); | |
1015 | 1017 | |
1016 | 1018 | // consume message |
1017 | 1019 | if (MPI_Recv(NULL, 0, MPI_CHAR, mpi_status.MPI_SOURCE, FD_MSG_NO_WORK, |
1018 | 1020 | MPI_COMM_WORLD, &mpi_status)) |
1019 | - _fd_fatal("MPI_Recv failed"); | |
1021 | + fd__fatal("MPI_Recv failed"); | |
1020 | 1022 | |
1021 | 1023 | got_one++; |
1022 | 1024 | } |
... | ... | @@ -1027,7 +1029,7 @@ static void _fd_flush_events(int procno) |
1027 | 1029 | { |
1028 | 1030 | _fd_store null = alloca(fd_variables_count * sizeof(*null)); |
1029 | 1031 | |
1030 | - _fd_debug("[%d] dropping FD_MSG_STORE from %d\n", procno, mpi_status.MPI_SOURCE); | |
1032 | + fd__trace("[%d] dropping FD_MSG_STORE from %d\n", procno, mpi_status.MPI_SOURCE); | |
1031 | 1033 | |
1032 | 1034 | _fd_recv_store(mpi_status.MPI_SOURCE, FD_MSG_STORE, null); |
1033 | 1035 | |
... | ... | @@ -1038,12 +1040,12 @@ static void _fd_flush_events(int procno) |
1038 | 1040 | |
1039 | 1041 | if (mpi_flag) |
1040 | 1042 | { |
1041 | - _fd_debug("[%d] dropping FD_MSG_FAIL from %d\n", procno, mpi_status.MPI_SOURCE); | |
1043 | + fd__trace("[%d] dropping FD_MSG_FAIL from %d\n", procno, mpi_status.MPI_SOURCE); | |
1042 | 1044 | |
1043 | 1045 | // consume message |
1044 | 1046 | if (MPI_Recv(NULL, 0, MPI_CHAR, mpi_status.MPI_SOURCE, FD_MSG_FAIL, |
1045 | 1047 | MPI_COMM_WORLD, &mpi_status)) |
1046 | - _fd_fatal("MPI_Recv failed"); | |
1048 | + fd__fatal("MPI_Recv failed"); | |
1047 | 1049 | |
1048 | 1050 | got_one++; |
1049 | 1051 | } |
... | ... | @@ -1052,12 +1054,12 @@ static void _fd_flush_events(int procno) |
1052 | 1054 | |
1053 | 1055 | if (mpi_flag) |
1054 | 1056 | { |
1055 | - _fd_debug("[%d] dropping FD_MSG_DONE from %d\n", procno, mpi_status.MPI_SOURCE); | |
1057 | + fd__trace("[%d] dropping FD_MSG_DONE from %d\n", procno, mpi_status.MPI_SOURCE); | |
1056 | 1058 | |
1057 | 1059 | // consume message |
1058 | 1060 | if (MPI_Recv(NULL, 0, MPI_CHAR, mpi_status.MPI_SOURCE, FD_MSG_DONE, |
1059 | 1061 | MPI_COMM_WORLD, &mpi_status)) |
1060 | - _fd_fatal("MPI_Recv failed"); | |
1062 | + fd__fatal("MPI_Recv failed"); | |
1061 | 1063 | |
1062 | 1064 | got_one++; |
1063 | 1065 | } |
... | ... | @@ -1066,12 +1068,12 @@ static void _fd_flush_events(int procno) |
1066 | 1068 | |
1067 | 1069 | if (mpi_flag) |
1068 | 1070 | { |
1069 | - _fd_debug("[%d] dropping FD_MSG_SHARE from %d\n", procno, mpi_status.MPI_SOURCE); | |
1071 | + fd__trace("[%d] dropping FD_MSG_SHARE from %d\n", procno, mpi_status.MPI_SOURCE); | |
1070 | 1072 | |
1071 | 1073 | // consume message |
1072 | 1074 | if (MPI_Recv(NULL, 0, MPI_CHAR, mpi_status.MPI_SOURCE, FD_MSG_SHARE, |
1073 | 1075 | MPI_COMM_WORLD, &mpi_status)) |
1074 | - _fd_fatal("MPI_Recv failed"); | |
1076 | + fd__fatal("MPI_Recv failed"); | |
1075 | 1077 | |
1076 | 1078 | got_one++; |
1077 | 1079 | } |
... | ... | @@ -1080,12 +1082,12 @@ static void _fd_flush_events(int procno) |
1080 | 1082 | |
1081 | 1083 | if (mpi_flag) |
1082 | 1084 | { |
1083 | - _fd_debug("[%d] dropping FD_MSG_NO_SHARE from %d\n", procno, mpi_status.MPI_SOURCE); | |
1085 | + fd__trace("[%d] dropping FD_MSG_NO_SHARE from %d\n", procno, mpi_status.MPI_SOURCE); | |
1084 | 1086 | |
1085 | 1087 | // consume message |
1086 | 1088 | if (MPI_Recv(NULL, 0, MPI_CHAR, mpi_status.MPI_SOURCE, FD_MSG_NO_SHARE, |
1087 | 1089 | MPI_COMM_WORLD, &mpi_status)) |
1088 | - _fd_fatal("MPI_Recv failed"); | |
1090 | + fd__fatal("MPI_Recv failed"); | |
1089 | 1091 | |
1090 | 1092 | got_one++; |
1091 | 1093 | } |
... | ... | @@ -1102,45 +1104,45 @@ void _fd_cleanup_mpi_state(int process) |
1102 | 1104 | // a still running process has a chance to see it |
1103 | 1105 | // XXX: New Madeleine can't cope with messages en route |
1104 | 1106 | #if 0 //#ifndef MAD_MPI |
1105 | - _fd_debug("[%d] setting up barrier 1\n", process); | |
1107 | + fd__trace("[%d] setting up barrier 1\n", process); | |
1106 | 1108 | if (MPI_Barrier(MPI_COMM_WORLD)) |
1107 | - _fd_error("[%d] MPI_Barrier failed\n", process); | |
1109 | + fd__error("[%d] MPI_Barrier failed\n", process); | |
1108 | 1110 | else |
1109 | - _fd_debug("[%d] leaving barrier 1\n", process); | |
1111 | + fd__trace("[%d] leaving barrier 1\n", process); | |
1110 | 1112 | #endif |
1111 | 1113 | |
1112 | 1114 | _fd_flush_events(process); |
1113 | 1115 | |
1114 | 1116 | #if 0 |
1115 | - _fd_debug("[%d] setting up barrier 2\n", process); | |
1117 | + fd__trace("[%d] setting up barrier 2\n", process); | |
1116 | 1118 | if (MPI_Barrier(MPI_COMM_WORLD)) |
1117 | - _fd_error("[%d] MPI_Barrier failed\n", process); | |
1119 | + fd__error("[%d] MPI_Barrier failed\n", process); | |
1118 | 1120 | else |
1119 | - _fd_debug("[%d] leaving barrier 2\n", process); | |
1121 | + fd__trace("[%d] leaving barrier 2\n", process); | |
1120 | 1122 | #endif |
1121 | 1123 | } |
1122 | 1124 | |
1123 | 1125 | _fd_statistics_msgs(); |
1124 | 1126 | |
1125 | - _fd_debug("[%d] calling MPI_Finalize\n", process); | |
1127 | + fd__trace("[%d] calling MPI_Finalize\n", process); | |
1126 | 1128 | if (MPI_Finalize()) |
1127 | - _fd_error("[%d] MPI_Finalize failed\n", process); | |
1129 | + fd__error("[%d] MPI_Finalize failed\n", process); | |
1128 | 1130 | else |
1129 | - _fd_debug("[%d] returned from MPI_Finalize\n", process); | |
1131 | + fd__trace("[%d] returned from MPI_Finalize\n", process); | |
1130 | 1132 | } |
1131 | 1133 | |
1132 | 1134 | static void _fd_exit_process(int process) |
1133 | 1135 | { |
1134 | 1136 | _fd_cleanup_mpi_state(process); |
1135 | 1137 | |
1136 | - _fd_debug("[%d] exiting\n", process); | |
1138 | + fd__trace("[%d] exiting\n", process); | |
1137 | 1139 | |
1138 | 1140 | exit(0); |
1139 | 1141 | } |
1140 | 1142 | |
1141 | 1143 | void _fd_search_space_sizes(_fd_store stores[], int n) |
1142 | 1144 | { |
1143 | -#ifndef FAST | |
1145 | +#ifdef TRACE | |
1144 | 1146 | double s; |
1145 | 1147 | int i, v; |
1146 | 1148 | |
... | ... | @@ -1155,14 +1157,14 @@ void _fd_search_space_sizes(_fd_store stores[], int n) |
1155 | 1157 | for (v = 0; v < fd__label_vars_count; ++v) |
1156 | 1158 | s *= _fd_val_size(SVALUE(stores[i][fd__label_vars[v]->index])); |
1157 | 1159 | |
1158 | - _fd_debug("[%d] search space %d size is %g\n", tid, i, s); | |
1160 | + fd__trace("[%d] search space %d size is %g\n", tid, i, s); | |
1159 | 1161 | } |
1160 | -#endif /* FAST */ | |
1162 | +#endif /* TRACE */ | |
1161 | 1163 | } |
1162 | 1164 | |
1163 | 1165 | static void count_singletons(_fd_store store) |
1164 | 1166 | { |
1165 | -#ifndef FAST | |
1167 | +#ifdef TRACE | |
1166 | 1168 | int i, n; |
1167 | 1169 | |
1168 | 1170 | n = 0; |
... | ... | @@ -1171,7 +1173,7 @@ static void count_singletons(_fd_store store) |
1171 | 1173 | if (_fd_val_single(SVALUE(store[i]), NULL)) |
1172 | 1174 | ++n; |
1173 | 1175 | |
1174 | - _fd_debug("[%d] store has %d/%d/%d singletons\n", tid, n, | |
1176 | + fd__trace("[%d] store has %d/%d/%d singletons\n", tid, n, | |
1175 | 1177 | fd__label_vars_count, fd_variables_count); |
1176 | 1178 | #endif |
1177 | 1179 | } |
... | ... | @@ -1185,7 +1187,7 @@ static int _fd_restart_agents(int tid, int nagents) |
1185 | 1187 | parts = fd__split_problem(nagents, _fd_agents_stores, fd__split_team_problem_f); |
1186 | 1188 | |
1187 | 1189 | if (parts < nagents) |
1188 | - _fd_debug("[%d] WARNING: store only good for %d agents (out of %d)\n", | |
1190 | + fd__debug("[%d] WARNING: store only good for %d agents (out of %d)\n", | |
1189 | 1191 | tid, parts, nagents); |
1190 | 1192 | |
1191 | 1193 | agents_to_run = parts; |
... | ... | @@ -1200,7 +1202,7 @@ static int _fd_restart_agents(int tid, int nagents) |
1200 | 1202 | if (pthread_mutex_unlock(&continue_mutex)) |
1201 | 1203 | perror("pthread_mutex_unlock"); |
1202 | 1204 | |
1203 | - _fd_debug("[%d] told waiting agents to proceed\n", tid); | |
1205 | + fd__trace("[%d] told waiting agents to proceed\n", tid); | |
1204 | 1206 | |
1205 | 1207 | return parts; |
1206 | 1208 | } |
... | ... | @@ -1222,7 +1224,7 @@ static int _fd_poll_next(int last, int skip) |
1222 | 1224 | if (poll >= 0) |
1223 | 1225 | { |
1224 | 1226 | // send a forceful request for work |
1225 | - _fd_debug("[%d] polling %d\n", tid, poll); | |
1227 | + fd__trace("[%d] polling %d\n", tid, poll); | |
1226 | 1228 | _fd_send(poll, FD_MSG_SHARE); |
1227 | 1229 | } |
1228 | 1230 | |
... | ... | @@ -1261,7 +1263,7 @@ static int _fd_poll_rr(bool starting, int np_or_last, int skip) |
1261 | 1263 | return -1; |
1262 | 1264 | |
1263 | 1265 | // send a forceful request for work |
1264 | - _fd_debug("[%d] polling %d\n", tid, poll); | |
1266 | + fd__trace("[%d] polling %d\n", tid, poll); | |
1265 | 1267 | _fd_send(poll, FD_MSG_SHARE); |
1266 | 1268 | |
1267 | 1269 | last_polled = poll; |
... | ... | @@ -1286,7 +1288,7 @@ static bool _fd_share_work(int peer, MPI_Request *request, fd_list saved_stores, |
1286 | 1288 | if (!mpi_flag) |
1287 | 1289 | { |
1288 | 1290 | // the previous send has not completed |
1289 | - _fd_debug("[%d] there's a store in transit to %d\n", tid, peer); | |
1291 | + fd__trace("[%d] there's a store in transit to %d\n", tid, peer); | |
1290 | 1292 | |
1291 | 1293 | /* despite MPI_Test() having failed, the store may already have |
1292 | 1294 | been received and processed; since process 0 must receive or |
... | ... | @@ -1306,7 +1308,7 @@ static bool _fd_share_work(int peer, MPI_Request *request, fd_list saved_stores, |
1306 | 1308 | memcpy(_fd_processes_stores[peer], saved, |
1307 | 1309 | fd_variables_count * sizeof(*saved)); |
1308 | 1310 | |
1309 | - _fd_debug("[%d] sending store (saved) to %d\n", tid, peer); | |
1311 | + fd__trace("[%d] sending store (saved) to %d\n", tid, peer); | |
1310 | 1312 | _fd_send_store(peer, FD_MSG_STORE, _fd_processes_stores[peer], request, |
1311 | 1313 | true); |
1312 | 1314 | |
... | ... | @@ -1315,13 +1317,9 @@ static bool _fd_share_work(int peer, MPI_Request *request, fd_list saved_stores, |
1315 | 1317 | return true; |
1316 | 1318 | } |
1317 | 1319 | |
1318 | -#ifndef INDEX_IN_POOL | |
1319 | - if (_fd_steal_store(_fd_processes_stores[peer], -1, 0)) | |
1320 | -#else | |
1321 | 1320 | if (_fd_steal_store(_fd_processes_stores[peer], NULL, -1, 0)) |
1322 | -#endif | |
1323 | 1321 | { |
1324 | - _fd_debug("[%d] sending store to %d\n", tid, peer); | |
1322 | + fd__trace("[%d] sending store to %d\n", tid, peer); | |
1325 | 1323 | _fd_send_store(peer, FD_MSG_STORE, _fd_processes_stores[peer], request, |
1326 | 1324 | true); |
1327 | 1325 | |
... | ... | @@ -1331,12 +1329,12 @@ static bool _fd_share_work(int peer, MPI_Request *request, fd_list saved_stores, |
1331 | 1329 | // tell the requester that there is no work available |
1332 | 1330 | if (polled) |
1333 | 1331 | { |
1334 | - _fd_debug("[%d] no work to share with %d\n", tid, peer); | |
1332 | + fd__trace("[%d] no work to share with %d\n", tid, peer); | |
1335 | 1333 | _fd_send(peer, FD_MSG_NO_SHARE); |
1336 | 1334 | } |
1337 | 1335 | else |
1338 | 1336 | { |
1339 | - _fd_debug("[%d] can't find work requested by %d\n", tid, peer); | |
1337 | + fd__trace("[%d] can't find work requested by %d\n", tid, peer); | |
1340 | 1338 | _fd_send(peer, FD_MSG_NO_WORK); |
1341 | 1339 | } |
1342 | 1340 | |
... | ... | @@ -1355,13 +1353,13 @@ static bool _fd_share_work(int peer, MPI_Request *request, fd_list saved_stores, |
1355 | 1353 | { \ |
1356 | 1354 | /* record polling process as idle */ \ |
1357 | 1355 | gettimeofday(&to, NULL); timersub(&to, &ti, &to); \ |
1358 | - _fd_debug("[%d] %d idled after %d.%06ds\n", tid, _p, \ | |
1356 | + fd__trace("[%d] %d idled after %d.%06ds\n", tid, _p, \ | |
1359 | 1357 | to.tv_sec, to.tv_usec); \ |
1360 | 1358 | \ |
1361 | 1359 | process_idle[_p] = true; \ |
1362 | 1360 | if (++idle_processes == live_procs - 1) \ |
1363 | 1361 | { \ |
1364 | - _fd_debug("[%d] sending 2nd quit\n", tid); \ | |
1362 | + fd__trace("[%d] sending 2nd quit\n", tid); \ | |
1365 | 1363 | \ |
1366 | 1364 | _fd_broadcast(FD_MSG_QUIT, processes, tid); \ |
1367 | 1365 | } \ |
... | ... | @@ -1401,21 +1399,21 @@ int _fd_dsolve() |
1401 | 1399 | gettimeofday(&ti, NULL); |
1402 | 1400 | |
1403 | 1401 | if (MPI_Comm_rank(MPI_COMM_WORLD, &tid)) |
1404 | - _fd_fatal("MPI_Comm_rank failed\n"); | |
1402 | + fd__fatal("MPI_Comm_rank failed\n"); | |
1405 | 1403 | |
1406 | - _fd_debug("I'm MPI rank %d\n", tid); | |
1404 | + fd__trace("I'm MPI rank %d\n", tid); | |
1407 | 1405 | |
1408 | 1406 | { |
1409 | 1407 | char host[512]; |
1410 | 1408 | |
1411 | - gethostname(host, sizeof(host)); | |
1412 | - _fd_debug("[%d] process %d at %s\n", tid, getpid(), host); | |
1409 | + fd__trace("[%d] process %d at %s\n", tid, getpid(), | |
1410 | + (gethostname(host, sizeof(host)), host)); | |
1413 | 1411 | } |
1414 | 1412 | |
1415 | 1413 | if (MPI_Comm_size(MPI_COMM_WORLD, &processes)) |
1416 | - _fd_fatal("MPI_Comm_size failed\n"); | |
1414 | + fd__fatal("MPI_Comm_size failed\n"); | |
1417 | 1415 | |
1418 | - _fd_debug("[%d] There are %d of us\n", tid, processes); | |
1416 | + fd__trace("[%d] There are %d of us\n", tid, processes); | |
1419 | 1417 | |
1420 | 1418 | pending_requests = fd_list_new(); |
1421 | 1419 | |
... | ... | @@ -1474,7 +1472,7 @@ int _fd_dsolve() |
1474 | 1472 | parts = fd__split_problem(processes, _fd_processes_stores, fd__split_problem_f); |
1475 | 1473 | _fd_search_space_sizes(_fd_processes_stores, parts); |
1476 | 1474 | if (parts < processes) |
1477 | - _fd_error("WARNING: work enough for %d processes only\n", parts); | |
1475 | + fd__error("WARNING: work enough for %d processes only\n", parts); | |
1478 | 1476 | |
1479 | 1477 | // now send the resulting parts to the other processes |
1480 | 1478 | // XXX: could each have done what this did and now pick its share? |
... | ... | @@ -1494,17 +1492,17 @@ int _fd_dsolve() |
1494 | 1492 | { |
1495 | 1493 | // code for the remaining processes |
1496 | 1494 | |
1497 | - _fd_debug("[%d] waiting for initial store\n", tid); | |
1495 | + fd__trace("[%d] waiting for initial store\n", tid); | |
1498 | 1496 | |
1499 | 1497 | // retrieve the domains assigned to the process |
1500 | 1498 | if (!_fd_recv_store(0, FD_MSG_STORE, store)) |
1501 | 1499 | { |
1502 | - _fd_debug("[%d] empty initial store\n", tid); | |
1500 | + fd__debug("[%d] empty initial store\n", tid); | |
1503 | 1501 | |
1504 | 1502 | _fd_exit_process(tid); |
1505 | 1503 | } |
1506 | 1504 | |
1507 | - _fd_debug("[%d] received initial store\n", tid); | |
1505 | + fd__trace("[%d] received initial store\n", tid); | |
1508 | 1506 | } |
1509 | 1507 | |
1510 | 1508 | #if FILTER_DOMAINS > 1 |
... | ... | @@ -1530,7 +1528,7 @@ int _fd_dsolve() |
1530 | 1528 | |
1531 | 1529 | if (parts < nagents) |
1532 | 1530 | { |
1533 | - _fd_debug("[%d] reducing to %d agents!\n", tid, parts); | |
1531 | + fd__trace("[%d] reducing to %d agents!\n", tid, parts); | |
1534 | 1532 | |
1535 | 1533 | nagents = parts; |
1536 | 1534 | } |
... | ... | @@ -1542,7 +1540,7 @@ int _fd_dsolve() |
1542 | 1540 | |
1543 | 1541 | gettimeofday(&to, NULL); |
1544 | 1542 | timersub(&to, &ti, &to); |
1545 | - _fd_debug("[%d] setup took %d.%06ds\n", tid, to.tv_sec, to.tv_usec); | |
1543 | + fd__trace("[%d] setup took %d.%06ds\n", tid, to.tv_sec, to.tv_usec); | |
1546 | 1544 | |
1547 | 1545 | #if 0 |
1548 | 1546 | for (i = 0; i < nagents; ++i) |
... | ... | @@ -1593,7 +1591,7 @@ int _fd_dsolve() |
1593 | 1591 | } |
1594 | 1592 | } |
1595 | 1593 | |
1596 | - _fd_debug("[%d] main thread waiting\n", tid); | |
1594 | + fd__trace("[%d] main thread waiting\n", tid); | |
1597 | 1595 | |
1598 | 1596 | running = started; |
1599 | 1597 | live_procs = processes; |
... | ... | @@ -1607,7 +1605,7 @@ int _fd_dsolve() |
1607 | 1605 | { |
1608 | 1606 | #if STEAL_WORK >= 2 |
1609 | 1607 | case EV_INT_TIMEOUT: |
1610 | - _fd_debug("[%d] timed out waiting for event\n", tid); | |
1608 | + fd__trace("[%d] timed out waiting for event\n", tid); | |
1611 | 1609 | |
1612 | 1610 | switch (waiting_on) |
1613 | 1611 | { |
... | ... | @@ -1644,7 +1642,7 @@ int _fd_dsolve() |
1644 | 1642 | else |
1645 | 1643 | { |
1646 | 1644 | // resend request for work |
1647 | - _fd_debug("[%d] re-asking for work\n", tid); | |
1645 | + fd__trace("[%d] re-asking for work\n", tid); | |
1648 | 1646 | _fd_broadcast(FD_MSG_FEED_ME, processes, tid); |
1649 | 1647 | |
1650 | 1648 | timeout = FEED2_TIMEOUT; |
... | ... | @@ -1687,8 +1685,8 @@ int _fd_dsolve() |
1687 | 1685 | |
1688 | 1686 | break; |
1689 | 1687 | default: |
1690 | - _fd_debug("[%d] unknown timeout: %d\n", tid, waiting_on); | |
1691 | - _fd_fatal("unknown timeout reason"); | |
1688 | + fd__debug("[%d] unknown timeout: %d\n", tid, waiting_on); | |
1689 | + fd__fatal("unknown timeout reason"); | |
1692 | 1690 | } |
1693 | 1691 | |
1694 | 1692 | break; |
... | ... | @@ -1697,7 +1695,7 @@ int _fd_dsolve() |
1697 | 1695 | /* first solution internal events (from the workers) */ |
1698 | 1696 | |
1699 | 1697 | case EV_INT_SUCCESS: |
1700 | - _fd_debug("[%d] using agent %d's results\n", tid, peer); | |
1698 | + fd__trace("[%d] using agent %d's results\n", tid, peer); | |
1701 | 1699 | |
1702 | 1700 | assert(!_fd_counting_solutions); |
1703 | 1701 | |
... | ... | @@ -1706,7 +1704,7 @@ int _fd_dsolve() |
1706 | 1704 | // check and update bound |
1707 | 1705 | if (!_fd_bound_check_set(_fd_agents_stores[peer])) |
1708 | 1706 | { |
1709 | - _fd_debug("[%d] invalid solution, releasing %d\n", tid, peer); | |
1707 | + fd__trace("[%d] invalid solution, releasing %d\n", tid, peer); | |
1710 | 1708 | if (sem_post(&resume_semaphore)) |
1711 | 1709 | perror("sem_post (resume)"); |
1712 | 1710 | |
... | ... | @@ -1720,11 +1718,11 @@ int _fd_dsolve() |
1720 | 1718 | fd_variables_count * sizeof(*solution)); |
1721 | 1719 | |
1722 | 1720 | // release agent |
1723 | - _fd_debug("[%d] releasing agent %d\n", tid, peer); | |
1721 | + fd__trace("[%d] releasing agent %d\n", tid, peer); | |
1724 | 1722 | if (sem_post(&resume_semaphore)) |
1725 | 1723 | perror("sem_post (resume)"); |
1726 | 1724 | |
1727 | - _fd_debug("[%d] bound updated to %d\n", tid, _fd_bound_value()); | |
1725 | + fd__trace("[%d] bound updated to %d\n", tid, _fd_bound_value()); | |
1728 | 1726 | |
1729 | 1727 | // broadcast new bound |
1730 | 1728 | bound = _fd_bound_value(); |
... | ... | @@ -1746,7 +1744,7 @@ int _fd_dsolve() |
1746 | 1744 | |
1747 | 1745 | break; |
1748 | 1746 | case EV_INT_FAIL: |
1749 | - _fd_debug("[%d] agent %d found no solution\n", tid, peer); | |
1747 | + fd__trace("[%d] agent %d found no solution\n", tid, peer); | |
1750 | 1748 | |
1751 | 1749 | assert(!_fd_counting_solutions); |
1752 | 1750 | |
... | ... | @@ -1770,7 +1768,7 @@ int _fd_dsolve() |
1770 | 1768 | { |
1771 | 1769 | if (!supplier) |
1772 | 1770 | { |
1773 | - _fd_debug("[%d] asking for work\n", tid); | |
1771 | + fd__trace("[%d] asking for work\n", tid); | |
1774 | 1772 | _fd_broadcast(FD_MSG_FEED_ME, processes, tid); |
1775 | 1773 | |
1776 | 1774 | waiting_on = FD_MSG_FEED_ME; |
... | ... | @@ -1802,7 +1800,7 @@ int _fd_dsolve() |
1802 | 1800 | // see if there's some store saved up |
1803 | 1801 | if (saved = fd_list_remove(saved_stores)) |
1804 | 1802 | { |
1805 | - _fd_debug("[%d] using saved store\n", tid); | |
1803 | + fd__trace("[%d] using saved store\n", tid); | |
1806 | 1804 | |
1807 | 1805 | memcpy(store, saved, |
1808 | 1806 | fd_variables_count * sizeof(*saved)); |
... | ... | @@ -1840,7 +1838,7 @@ int _fd_dsolve() |
1840 | 1838 | if (!supplier) |
1841 | 1839 | { |
1842 | 1840 | // ask the other processes for more work |
1843 | - _fd_debug("[%d] asking for work\n", tid); | |
1841 | + fd__trace("[%d] asking for work\n", tid); | |
1844 | 1842 | _fd_broadcast(FD_MSG_FEED_ME, processes, tid); |
1845 | 1843 | |
1846 | 1844 | waiting_on = FD_MSG_FEED_ME; |
... | ... | @@ -1873,18 +1871,18 @@ int _fd_dsolve() |
1873 | 1871 | /* first solution external events (from the other processes) */ |
1874 | 1872 | |
1875 | 1873 | case EV_EXT_SUCCESS: |
1876 | - _fd_debug("[%d] received a solution from %d\n", tid, peer); | |
1874 | + fd__trace("[%d] received a solution from %d\n", tid, peer); | |
1877 | 1875 | |
1878 | 1876 | assert(!_fd_counting_solutions); |
1879 | 1877 | |
1880 | 1878 | _fd_recv_store(peer, FD_MSG_SOLUTION, store); |
1881 | 1879 | |
1882 | - _fd_debug("[%d] using process %d's results\n", tid, peer); | |
1880 | + fd__trace("[%d] using process %d's results\n", tid, peer); | |
1883 | 1881 | |
1884 | 1882 | gettimeofday(&to, NULL); |
1885 | 1883 | timersub(&to, &ti, &to); |
1886 | -#if defined(STATS_PROCS) || !defined(FAST) | |
1887 | - fd__info("[%d] process %d took %d.%06ds\n", tid, peer, to.tv_sec, to.tv_usec); | |
1884 | +#if defined(STATS_PROCS) || defined(TRACE) | |
1885 | + fd__debug("[%d] process %d took %d.%06ds\n", tid, peer, to.tv_sec, to.tv_usec); | |
1888 | 1886 | #endif |
1889 | 1887 | |
1890 | 1888 | if (_fd_optimising) |
... | ... | @@ -1892,7 +1890,7 @@ int _fd_dsolve() |
1892 | 1890 | // see if it is the better solution |
1893 | 1891 | if (!have_solution || _fd_better_solution(store, solution)) |
1894 | 1892 | { |
1895 | - _fd_debug("[%d] process %d solution is better\n", tid, peer); | |
1893 | + fd__trace("[%d] process %d solution is better\n", tid, peer); | |
1896 | 1894 | |
1897 | 1895 | memcpy(solution, store, |
1898 | 1896 | fd_variables_count * sizeof(*store)); |
... | ... | @@ -1916,14 +1914,14 @@ int _fd_dsolve() |
1916 | 1914 | |
1917 | 1915 | break; |
1918 | 1916 | case EV_EXT_FAIL: |
1919 | - _fd_debug("[%d] process %d found no solution\n", tid, peer); | |
1917 | + fd__trace("[%d] process %d found no solution\n", tid, peer); | |
1920 | 1918 | |
1921 | 1919 | assert(!_fd_counting_solutions); |
1922 | 1920 | |
1923 | 1921 | gettimeofday(&to, NULL); |
1924 | 1922 | timersub(&to, &ti, &to); |
1925 | -#if defined(STATS_PROCS) || !defined(FAST) | |
1926 | - fd__info("[%d] process %d took %d.%06ds\n", tid, peer, to.tv_sec, to.tv_usec); | |
1923 | +#if defined(STATS_PROCS) || defined(TRACE) | |
1924 | + fd__debug("[%d] process %d took %d.%06ds\n", tid, peer, to.tv_sec, to.tv_usec); | |
1927 | 1925 | #endif |
1928 | 1926 | |
1929 | 1927 | live_procs--; |
... | ... | @@ -1943,7 +1941,7 @@ int _fd_dsolve() |
1943 | 1941 | |
1944 | 1942 | break; |
1945 | 1943 | case EV_EXT_DONE: |
1946 | - _fd_debug("[%d] process %d told me to stop\n", tid, peer); | |
1944 | + fd__trace("[%d] process %d told me to stop\n", tid, peer); | |
1947 | 1945 | |
1948 | 1946 | assert(!_fd_counting_solutions); |
1949 | 1947 | |
... | ... | @@ -1954,7 +1952,7 @@ int _fd_dsolve() |
1954 | 1952 | /* optimisation external events (from the other processes) */ |
1955 | 1953 | |
1956 | 1954 | case EV_EXT_BOUND: |
1957 | - _fd_debug("[%d] received new bound from %d\n", tid, peer); | |
1955 | + fd__trace("[%d] received new bound from %d\n", tid, peer); | |
1958 | 1956 | |
1959 | 1957 | assert(!_fd_counting_solutions && _fd_optimising); |
1960 | 1958 | |
... | ... | @@ -1963,24 +1961,24 @@ int _fd_dsolve() |
1963 | 1961 | |
1964 | 1962 | if (MPI_Recv(&bound, 1, MPI_INT, peer, FD_MSG_BOUND, |
1965 | 1963 | MPI_COMM_WORLD, &mpi_status)) |
1966 | - _fd_fatal("MPI_Recv failed"); | |
1964 | + fd__fatal("MPI_Recv failed"); | |
1967 | 1965 | |
1968 | 1966 | // try to set new bound |
1969 | 1967 | if (_fd_set_bound(bound)) |
1970 | 1968 | { |
1971 | - _fd_debug("[%d] new bound is %d\n", tid, bound); | |
1969 | + fd__trace("[%d] new bound is %d\n", tid, bound); | |
1972 | 1970 | |
1973 | 1971 | // bound has been reset, invalidate previous solution |
1974 | 1972 | if (have_solution && !_fd_bound_check(solution)) |
1975 | 1973 | { |
1976 | - _fd_debug("[%d] invalidating current solution\n", tid); | |
1974 | + fd__trace("[%d] invalidating current solution\n", tid); | |
1977 | 1975 | |
1978 | 1976 | status = FD_NOSOLUTION; |
1979 | 1977 | have_solution = false; |
1980 | 1978 | } |
1981 | 1979 | } |
1982 | 1980 | else |
1983 | - _fd_debug("[%d] invalid bound %d\n", tid, bound); | |
1981 | + fd__trace("[%d] invalid bound %d\n", tid, bound); | |
1984 | 1982 | } |
1985 | 1983 | |
1986 | 1984 | break; |
... | ... | @@ -1988,7 +1986,7 @@ int _fd_dsolve() |
1988 | 1986 | /* counting solutions internal events (from the workers) */ |
1989 | 1987 | |
1990 | 1988 | case EV_INT_COUNT: |
1991 | - _fd_debug("[%d] agent %d is done\n", tid, peer); | |
1989 | + fd__trace("[%d] agent %d is done\n", tid, peer); | |
1992 | 1990 | |
1993 | 1991 | assert(_fd_counting_solutions); |
1994 | 1992 | |
... | ... | @@ -2012,7 +2010,7 @@ int _fd_dsolve() |
2012 | 2010 | { |
2013 | 2011 | if (!supplier) |
2014 | 2012 | { |
2015 | - _fd_debug("[%d] asking for work\n", tid); | |
2013 | + fd__trace("[%d] asking for work\n", tid); | |
2016 | 2014 | _fd_broadcast(FD_MSG_FEED_ME, processes, tid); |
2017 | 2015 | |
2018 | 2016 | waiting_on = FD_MSG_FEED_ME; |
... | ... | @@ -2044,7 +2042,7 @@ int _fd_dsolve() |
2044 | 2042 | // see if there's some store saved up |
2045 | 2043 | if (saved = fd_list_remove(saved_stores)) |
2046 | 2044 | { |
2047 | - _fd_debug("[%d] using saved store\n", tid); | |
2045 | + fd__trace("[%d] using saved store\n", tid); | |
2048 | 2046 | |
2049 | 2047 | memcpy(store, saved, |
2050 | 2048 | fd_variables_count * sizeof(*saved)); |
... | ... | @@ -2082,7 +2080,7 @@ int _fd_dsolve() |
2082 | 2080 | if (!supplier) |
2083 | 2081 | { |
2084 | 2082 | // ask the other processes for more work |
2085 | - _fd_debug("[%d] asking for work\n", tid); | |
2083 | + fd__trace("[%d] asking for work\n", tid); | |
2086 | 2084 | _fd_broadcast(FD_MSG_FEED_ME, processes, tid); |
2087 | 2085 | |
2088 | 2086 | waiting_on = FD_MSG_FEED_ME; |
... | ... | @@ -2115,7 +2113,7 @@ int _fd_dsolve() |
2115 | 2113 | /* counting solutions external events (from the other processes) */ |
2116 | 2114 | |
2117 | 2115 | case EV_EXT_COUNT: |
2118 | - _fd_debug("[%d] receiving count from %d\n", tid, peer); | |
2116 | + fd__trace("[%d] receiving count from %d\n", tid, peer); | |
2119 | 2117 | |
2120 | 2118 | assert(_fd_counting_solutions); |
2121 | 2119 | |
... | ... | @@ -2124,17 +2122,17 @@ int _fd_dsolve() |
2124 | 2122 | |
2125 | 2123 | if (MPI_Recv(&ull, 1, MPI_LONG_LONG, peer, FD_MSG_COUNT, |
2126 | 2124 | MPI_COMM_WORLD, &mpi_status)) |
2127 | - _fd_fatal("MPI_Recv failed"); | |
2125 | + fd__fatal("MPI_Recv failed"); | |
2128 | 2126 | |
2129 | 2127 | external_solutions += ull; |
2130 | 2128 | |
2131 | - _fd_debug("[%d] process %d found %llu solutions\n", tid, peer, ull); | |
2129 | + fd__trace("[%d] process %d found %llu solutions\n", tid, peer, ull); | |
2132 | 2130 | } |
2133 | 2131 | |
2134 | 2132 | gettimeofday(&to, NULL); |
2135 | 2133 | timersub(&to, &ti, &to); |
2136 | -#if defined(STATS_PROCS) || !defined(FAST) | |
2137 | - fd__info("[%d] process %d took %d.%06ds\n", tid, peer, to.tv_sec, to.tv_usec); | |
2134 | +#if defined(STATS_PROCS) || defined(TRACE) | |
2135 | + fd__debug("[%d] process %d took %d.%06ds\n", tid, peer, to.tv_sec, to.tv_usec); | |
2138 | 2136 | #endif |
2139 | 2137 | |
2140 | 2138 | live_procs--; |
... | ... | @@ -2158,9 +2156,9 @@ int _fd_dsolve() |
2158 | 2156 | /* work stealing events (external) */ |
2159 | 2157 | |
2160 | 2158 | case EV_EXT_STORE: |
2161 | - _fd_debug("[%d] process %d sent a store\n", tid, peer); | |
2159 | + fd__trace("[%d] process %d sent a store\n", tid, peer); | |
2162 | 2160 | |
2163 | -if (waiting_on == FD_MSG_ANY) _fd_debug("[%d] recovered store\n", tid); | |
2161 | +if (waiting_on == FD_MSG_ANY) fd__trace("[%d] recovered store\n", tid); | |
2164 | 2162 | |
2165 | 2163 | if (running == 0) |
2166 | 2164 | { |
... | ... | @@ -2198,7 +2196,7 @@ if (waiting_on == FD_MSG_ANY) _fd_debug("[%d] recovered store\n", tid); |
2198 | 2196 | |
2199 | 2197 | break; |
2200 | 2198 | case EV_EXT_REQ_WORK: |
2201 | - _fd_debug("[%d] process %d wants more work\n", tid, peer); | |
2199 | + fd__trace("[%d] process %d wants more work\n", tid, peer); | |
2202 | 2200 | |
2203 | 2201 | if (supplier) |
2204 | 2202 | { |
... | ... | @@ -2216,7 +2214,7 @@ if (waiting_on == FD_MSG_ANY) _fd_debug("[%d] recovered store\n", tid); |
2216 | 2214 | |
2217 | 2215 | break; |
2218 | 2216 | case EV_EXT_NO_WORK: |
2219 | - _fd_debug("[%d] process %d can't supply work\n", tid, peer); | |
2217 | + fd__trace("[%d] process %d can't supply work\n", tid, peer); | |
2220 | 2218 | |
2221 | 2219 | // no work sharing after having been told to stop |
2222 | 2220 | if (quitting || ready) |
... | ... | @@ -2268,7 +2266,7 @@ if (waiting_on == FD_MSG_ANY) _fd_debug("[%d] recovered store\n", tid); |
2268 | 2266 | |
2269 | 2267 | break; |
2270 | 2268 | case EV_EXT_NO_SHARE: |
2271 | - _fd_debug("[%d] process %d can't share work\n", tid, peer); | |
2269 | + fd__trace("[%d] process %d can't share work\n", tid, peer); | |
2272 | 2270 | |
2273 | 2271 | // no work sharing after having been told to stop |
2274 | 2272 | if (quitting || ready) |
... | ... | @@ -2284,7 +2282,7 @@ if (waiting_on == FD_MSG_ANY) _fd_debug("[%d] recovered store\n", tid); |
2284 | 2282 | |
2285 | 2283 | if (peer != polling) |
2286 | 2284 | { |
2287 | - _fd_debug("[%d] polling %d but got answer from %d\n", | |
2285 | + fd__trace("[%d] polling %d but got answer from %d\n", | |
2288 | 2286 | tid, polling, peer); |
2289 | 2287 | |
2290 | 2288 | // belated answer, ignore |
... | ... | @@ -2331,14 +2329,14 @@ if (waiting_on == FD_MSG_ANY) _fd_debug("[%d] recovered store\n", tid); |
2331 | 2329 | |
2332 | 2330 | break; |
2333 | 2331 | case EV_EXT_REQ_SHARE: |
2334 | - _fd_debug("[%d] process %d really wants work\n", tid, peer); | |
2332 | + fd__trace("[%d] process %d really wants work\n", tid, peer); | |
2335 | 2333 | |
2336 | 2334 | // if we're idle, there's nothing to share |
2337 | 2335 | if (running == 0 || quitting || ready) // XXX: could be < nagents |
2338 | 2336 | { |
2339 | 2337 | // notify the asking process that there really isn't |
2340 | 2338 | // work to be shared |
2341 | - _fd_debug("[%d] no work to share with %d\n", tid, peer); | |
2339 | + fd__trace("[%d] no work to share with %d\n", tid, peer); | |
2342 | 2340 | _fd_send(peer, FD_MSG_NO_SHARE); |
2343 | 2341 | |
2344 | 2342 | break; |
... | ... | @@ -2352,14 +2350,14 @@ if (waiting_on == FD_MSG_ANY) _fd_debug("[%d] recovered store\n", tid); |
2352 | 2350 | break; |
2353 | 2351 | case EV_EXT_READY: |
2354 | 2352 | // peer has no work and no outgoing communications pending |
2355 | - _fd_debug("[%d] %d is done\n", tid, peer); | |
2353 | + fd__trace("[%d] %d is done\n", tid, peer); | |
2356 | 2354 | |
2357 | 2355 | assert(tid == 0); |
2358 | 2356 | |
2359 | 2357 | mark_process_idle(peer); |
2360 | 2358 | |
2361 | 2359 | // XXX: in mark_process_idle() |
2362 | - //_fd_debug("[%d] sending 2nd quit\n", tid); | |
2360 | + //fd__trace("[%d] sending 2nd quit\n", tid); | |
2363 | 2361 | //_fd_broadcast(FD_MSG_QUIT, processes, tid); |
2364 | 2362 | |
2365 | 2363 | //done = running == 0 && live_procs == 1; |
... | ... | @@ -2371,7 +2369,7 @@ if (waiting_on == FD_MSG_ANY) _fd_debug("[%d] recovered store\n", tid); |
2371 | 2369 | break; |
2372 | 2370 | case EV_EXT_QUIT: |
2373 | 2371 | // possibilities for finding work have been exhausted |
2374 | - _fd_debug("[%d] %d told me to stop\n", tid, peer); | |
2372 | + fd__trace("[%d] %d told me to stop\n", tid, peer); | |
2375 | 2373 | |
2376 | 2374 | assert(tid != 0); |
2377 | 2375 | |
... | ... | @@ -2385,12 +2383,12 @@ if (waiting_on == FD_MSG_ANY) _fd_debug("[%d] recovered store\n", tid); |
2385 | 2383 | break; |
2386 | 2384 | #endif /* STEAL_WORK >= 2 */ |
2387 | 2385 | default: |
2388 | - _fd_debug("[%d] unknown event in main loop: %d\n", tid, event); | |
2389 | - _fd_fatal("unknown event in main loop"); | |
2386 | + fd__debug("[%d] unknown event in main loop: %d\n", tid, event); | |
2387 | + fd__fatal("unknown event in main loop"); | |
2390 | 2388 | } |
2391 | 2389 | |
2392 | 2390 | #if STEAL_WORK >= 2 |
2393 | -if (done) _fd_debug("[%d] done (quitting = %d, ready = %d, timeout = %d)\n", tid, quitting, ready, timeout); | |
2391 | +if (done) fd__trace("[%d] done (quitting = %d, ready = %d, timeout = %d)\n", tid, quitting, ready, timeout); | |
2394 | 2392 | |
2395 | 2393 | // if it is important that the full search space is explored, |
2396 | 2394 | // make an extra effort for receiving messages that may have |
... | ... | @@ -2400,7 +2398,7 @@ if (done) _fd_debug("[%d] done (quitting = %d, ready = %d, timeout = %d)\n", tid |
2400 | 2398 | _fd_optimising || |
2401 | 2399 | status != FD_OK && !stopped)) |
2402 | 2400 | { |
2403 | - _fd_debug("[%d] checking for any event before leaving\n", tid); | |
2401 | + fd__trace("[%d] checking for any event before leaving\n", tid); | |
2404 | 2402 | |
2405 | 2403 | done = 0; |
2406 | 2404 | waiting_on = FD_MSG_ANY; |
... | ... | @@ -2438,14 +2436,14 @@ if (done) _fd_debug("[%d] done (quitting = %d, ready = %d, timeout = %d)\n", tid |
2438 | 2436 | |
2439 | 2437 | if (!mpi_flag) // request hasn't completed |
2440 | 2438 | { |
2441 | - _fd_debug("[%d] recovering outstanding store to %d\n", | |
2439 | + fd__trace("[%d] recovering outstanding store to %d\n", | |
2442 | 2440 | tid, i); |
2443 | 2441 | |
2444 | 2442 | // try cancelling the send (or the cancel?) |
2445 | 2443 | if (MPI_Cancel(stores_pending + i)) |
2446 | 2444 | perror("MPI_Cancel"); |
2447 | 2445 | |
2448 | - _fd_debug("[%d] cancelled request\n", tid); | |
2446 | + fd__trace("[%d] cancelled request\n", tid); | |
2449 | 2447 | |
2450 | 2448 | // allow the cancel some time to complete |
2451 | 2449 | do |
... | ... | @@ -2457,7 +2455,7 @@ if (done) _fd_debug("[%d] done (quitting = %d, ready = %d, timeout = %d)\n", tid |
2457 | 2455 | if (mpi_flag) |
2458 | 2456 | break; |
2459 | 2457 | |
2460 | - _fd_debug("[%d] cancelling store to %d didn't complete\n", | |
2458 | + fd__trace("[%d] cancelling store to %d didn't complete\n", | |
2461 | 2459 | tid, i); |
2462 | 2460 | |
2463 | 2461 | if (--tries == 0) |
... | ... | @@ -2469,7 +2467,7 @@ if (done) _fd_debug("[%d] done (quitting = %d, ready = %d, timeout = %d)\n", tid |
2469 | 2467 | |
2470 | 2468 | if (!mpi_flag) // cancel didn't complete, give up for now |
2471 | 2469 | { |
2472 | - _fd_debug("[%d] giving up cancelling store to %i for now\n", | |
2470 | + fd__trace("[%d] giving up cancelling store to %i for now\n", | |
2473 | 2471 | tid, i); |
2474 | 2472 | |
2475 | 2473 | // if no store is cancelled, will have to wait |
... | ... | @@ -2482,7 +2480,7 @@ if (done) _fd_debug("[%d] done (quitting = %d, ready = %d, timeout = %d)\n", tid |
2482 | 2480 | continue; |
2483 | 2481 | } |
2484 | 2482 | |
2485 | - _fd_debug("[%d] status = (%d, %d, %d, %d, %d)\n", tid, | |
2483 | + fd__trace("[%d] status = (%d, %d, %d, %d, %d)\n", tid, | |
2486 | 2484 | mpi_status.MPI_SOURCE, mpi_status.MPI_TAG, |
2487 | 2485 | mpi_status.MPI_ERROR, mpi_status._count, |
2488 | 2486 | mpi_status._cancelled); |
... | ... | @@ -2491,12 +2489,12 @@ if (done) _fd_debug("[%d] done (quitting = %d, ready = %d, timeout = %d)\n", tid |
2491 | 2489 | |
2492 | 2490 | if (!mpi_flag) |
2493 | 2491 | { |
2494 | - _fd_debug("[%d] cancel did not succeed\n", tid); | |
2492 | + fd__trace("[%d] cancel did not succeed\n", tid); | |
2495 | 2493 | |
2496 | 2494 | continue; |
2497 | 2495 | } |
2498 | 2496 | |
2499 | - _fd_debug("[%d] cancel succeeded\n", tid); | |
2497 | + fd__trace("[%d] cancel succeeded\n", tid); | |
2500 | 2498 | } |
2501 | 2499 | else |
2502 | 2500 | { |
... | ... | @@ -2506,7 +2504,7 @@ if (done) _fd_debug("[%d] done (quitting = %d, ready = %d, timeout = %d)\n", tid |
2506 | 2504 | if (!mpi_flag) |
2507 | 2505 | continue; // the send has completed |
2508 | 2506 | |
2509 | - _fd_debug("[%d] previously cancelled store to %d\n", | |
2507 | + fd__trace("[%d] previously cancelled store to %d\n", | |
2510 | 2508 | tid, i); |
2511 | 2509 | } |
2512 | 2510 | |
... | ... | @@ -2533,7 +2531,7 @@ if (done) _fd_debug("[%d] done (quitting = %d, ready = %d, timeout = %d)\n", tid |
2533 | 2531 | { |
2534 | 2532 | if (tid != 0) |
2535 | 2533 | { |
2536 | - _fd_debug("[%d] ready to leave\n", tid); | |
2534 | + fd__trace("[%d] ready to leave\n", tid); | |
2537 | 2535 | |
2538 | 2536 | _fd_send(0, FD_MSG_READY); |
2539 | 2537 | |
... | ... | @@ -2566,11 +2564,11 @@ if (done) _fd_debug("[%d] done (quitting = %d, ready = %d, timeout = %d)\n", tid |
2566 | 2564 | // stop the other processes |
2567 | 2565 | if (live_procs > 1) |
2568 | 2566 | { |
2569 | - _fd_debug("[%d] stopping all processes\n", tid); | |
2567 | + fd__trace("[%d] stopping all processes\n", tid); | |
2570 | 2568 | _fd_broadcast(FD_MSG_DONE, processes, tid); |
2571 | 2569 | } |
2572 | 2570 | else |
2573 | - _fd_debug("[%d] all other processes already stopped\n", tid); | |
2571 | + fd__trace("[%d] all other processes already stopped\n", tid); | |
2574 | 2572 | |
2575 | 2573 | if (_fd_optimising && status == FD_OK) |
2576 | 2574 | { |
... | ... | @@ -2581,7 +2579,7 @@ if (done) _fd_debug("[%d] done (quitting = %d, ready = %d, timeout = %d)\n", tid |
2581 | 2579 | if (ts.tv_sec) |
2582 | 2580 | { |
2583 | 2581 | timersub(&ts, &ti, &ts); |
2584 | - _fd_debug("[%d] time to solution was %d.%06ds\n", tid, | |
2582 | + fd__trace("[%d] time to solution was %d.%06ds\n", tid, | |
2585 | 2583 | ts.tv_sec, ts.tv_usec); |
2586 | 2584 | } |
2587 | 2585 | } |
... | ... | @@ -2594,7 +2592,7 @@ if (done) _fd_debug("[%d] done (quitting = %d, ready = %d, timeout = %d)\n", tid |
2594 | 2592 | { |
2595 | 2593 | MPI_Request *mpi_request = malloc(sizeof(MPI_Request)); |
2596 | 2594 | |
2597 | - _fd_debug("[%d] sending solution\n", tid); | |
2595 | + fd__trace("[%d] sending solution\n", tid); | |
2598 | 2596 | |
2599 | 2597 | if (_fd_optimising) |
2600 | 2598 | assert(have_solution); |
... | ... | @@ -2605,7 +2603,7 @@ if (done) _fd_debug("[%d] done (quitting = %d, ready = %d, timeout = %d)\n", tid |
2605 | 2603 | if (ts.tv_sec) |
2606 | 2604 | { |
2607 | 2605 | timersub(&ts, &ti, &ts); |
2608 | - _fd_debug("[%d] time to solution was %d.%06ds\n", tid, | |
2606 | + fd__trace("[%d] time to solution was %d.%06ds\n", tid, | |
2609 | 2607 | ts.tv_sec, ts.tv_usec); |
2610 | 2608 | } |
2611 | 2609 | |
... | ... | @@ -2613,19 +2611,19 @@ if (done) _fd_debug("[%d] done (quitting = %d, ready = %d, timeout = %d)\n", tid |
2613 | 2611 | } |
2614 | 2612 | else |
2615 | 2613 | { |
2616 | - _fd_debug("[%d] sending failure notice\n", tid); | |
2614 | + fd__trace("[%d] sending failure notice\n", tid); | |
2617 | 2615 | _fd_send(0, FD_MSG_FAIL); |
2618 | 2616 | } |
2619 | 2617 | } |
2620 | 2618 | |
2621 | 2619 | // stop all the agents |
2622 | - _fd_debug("[%d] stopping agents\n", tid); | |
2620 | + fd__trace("[%d] stopping agents\n", tid); | |
2623 | 2621 | for (i = 0; i < started; ++i) |
2624 | 2622 | { |
2625 | 2623 | int s; |
2626 | 2624 | |
2627 | 2625 | if ((s = pthread_cancel(threads[i])) && s != ESRCH) |
2628 | - _fd_debug("[%d] error cancelling thread %d = %d\n", tid, i, s); | |
2626 | + fd__debug("[%d] error cancelling thread %d = %d\n", tid, i, s); | |
2629 | 2627 | } |
2630 | 2628 | |
2631 | 2629 | // make sure all agents have stopped before exiting |
... | ... | @@ -2634,9 +2632,9 @@ if (done) _fd_debug("[%d] done (quitting = %d, ready = %d, timeout = %d)\n", tid |
2634 | 2632 | { |
2635 | 2633 | int s; |
2636 | 2634 | |
2637 | - _fd_debug("[%d] joining agent %d\n", tid, i); | |
2635 | + fd__trace("[%d] joining agent %d\n", tid, i); | |
2638 | 2636 | if ((s = pthread_join(threads[i], NULL)) && s != ESRCH) |
2639 | - _fd_debug("[%d] error joining thread %d = %d\n", tid, i, s); | |
2637 | + fd__debug("[%d] error joining thread %d = %d\n", tid, i, s); | |
2640 | 2638 | } |
2641 | 2639 | |
2642 | 2640 | #if STEAL_WORK >= 2 |
... | ... | @@ -2652,13 +2650,13 @@ if (done) _fd_debug("[%d] done (quitting = %d, ready = %d, timeout = %d)\n", tid |
2652 | 2650 | |
2653 | 2651 | #if STEAL_WORK >= 2 |
2654 | 2652 | // stop all the agents, which are waiting for work |
2655 | - _fd_debug("[%d] stopping agents\n", tid); | |
2653 | + fd__trace("[%d] stopping agents\n", tid); | |
2656 | 2654 | for (i = 0; i < started; ++i) |
2657 | 2655 | { |
2658 | 2656 | int s; |
2659 | 2657 | |
2660 | 2658 | if ((s = pthread_cancel(threads[i])) && s != ESRCH) |
2661 | - _fd_debug("[%d] error cancelling thread %d = %d\n", tid, i, s); | |
2659 | + fd__debug("[%d] error cancelling thread %d = %d\n", tid, i, s); | |
2662 | 2660 | } |
2663 | 2661 | |
2664 | 2662 | // make sure all agents have stopped before exiting |
... | ... | @@ -2666,13 +2664,13 @@ if (done) _fd_debug("[%d] done (quitting = %d, ready = %d, timeout = %d)\n", tid |
2666 | 2664 | { |
2667 | 2665 | int s; |
2668 | 2666 | |
2669 | - _fd_debug("[%d] joining agent %d\n", tid, i); | |
2667 | + fd__trace("[%d] joining agent %d\n", tid, i); | |
2670 | 2668 | if ((s = pthread_join(threads[i], NULL)) && s != ESRCH) |
2671 | - _fd_debug("[%d] error joining thread %d = %d\n", tid, i, s); | |
2669 | + fd__debug("[%d] error joining thread %d = %d\n", tid, i, s); | |
2672 | 2670 | } |
2673 | 2671 | |
2674 | 2672 | if (!fd_list_empty(saved_stores)) |
2675 | - _fd_fatal("saved_stores not empty on exit"); | |
2673 | + fd__fatal("saved_stores not empty on exit"); | |
2676 | 2674 | |
2677 | 2675 | fd_list_dispose(saved_stores); |
2678 | 2676 | #endif /* STEAL_WORK >= 2 */ |
... | ... | @@ -2699,15 +2697,15 @@ if (done) _fd_debug("[%d] done (quitting = %d, ready = %d, timeout = %d)\n", tid |
2699 | 2697 | |
2700 | 2698 | if (_fd_counting_solutions) |
2701 | 2699 | { |
2702 | - _fd_output("found %llu solutions\n", total_solutions + external_solutions); // XXX | |
2700 | + fd__output("found %llu solutions\n", total_solutions + external_solutions); // XXX | |
2703 | 2701 | |
2704 | 2702 | status = FD_NOSOLUTION; // XXX |
2705 | 2703 | } |
2706 | 2704 | |
2707 | 2705 | gettimeofday(&to, NULL); |
2708 | 2706 | timersub(&to, &ti, &to); |
2709 | -#if defined(STATS_PROCS) || !defined(FAST) | |
2710 | - fd__info("process %d took %d.%06ds\n", tid, to.tv_sec, to.tv_usec); | |
2707 | +#if defined(STATS_PROCS) || defined(TRACE) | |
2708 | + fd__debug("process %d took %d.%06ds\n", tid, to.tv_sec, to.tv_usec); | |
2711 | 2709 | #endif |
2712 | 2710 | |
2713 | 2711 | return status; |
... | ... |
src/agents-splitgo.c
... | ... | @@ -13,6 +13,8 @@ |
13 | 13 | #include "splitting.h" |
14 | 14 | #include "bound.h" |
15 | 15 | |
16 | +#include "util.h" | |
17 | + | |
16 | 18 | #ifndef COMPACT_DOMAINS |
17 | 19 | #error "only works with COMPACT_DOMAINS" |
18 | 20 | #endif |
... | ... | @@ -81,7 +83,7 @@ int _fd_agent(int n) |
81 | 83 | int result; |
82 | 84 | struct timeval ti, tis, to, tos; |
83 | 85 | |
84 | - _fd_debug("starting agent %d\n", n); | |
86 | + fd__trace("starting agent %d\n", n); | |
85 | 87 | |
86 | 88 | gettimeofday(&ti, NULL); |
87 | 89 | |
... | ... | @@ -93,11 +95,11 @@ int _fd_agent(int n) |
93 | 95 | |
94 | 96 | gettimeofday(&to, NULL); |
95 | 97 | timersub(&to, &ti, &to); |
96 | - _fd_debug("agent %d took %d.%06ds\n", n, to.tv_sec, to.tv_usec); | |
98 | + fd__trace("agent %d took %d.%06ds\n", n, to.tv_sec, to.tv_usec); | |
97 | 99 | |
98 | 100 | while (result == FD_OK) |
99 | 101 | { |
100 | - _fd_debug("agent %d was successful\n", n); | |
102 | + fd__trace("agent %d was successful\n", n); | |
101 | 103 | |
102 | 104 | // ensure that only one agent signals its success |
103 | 105 | // XXX: only good (?) if only looking for the 1st solution |
... | ... | @@ -106,7 +108,7 @@ int _fd_agent(int n) |
106 | 108 | // in sem_wait() |
107 | 109 | pthread_cleanup_push((void (*)(void *)) pthread_mutex_unlock, |
108 | 110 | &success_mutex); |
109 | - _fd_debug("agent %d acquired success mutex\n", n); | |
111 | + fd__trace("agent %d acquired success mutex\n", n); | |
110 | 112 | |
111 | 113 | // tell the main thread that this agent is done |
112 | 114 | if (sem_wait(&ready_semaphore)) |
... | ... | @@ -119,14 +121,14 @@ int _fd_agent(int n) |
119 | 121 | |
120 | 122 | pthread_mutex_unlock(&success_mutex); |
121 | 123 | pthread_cleanup_pop(0); |
122 | - _fd_debug("agent %d released success mutex\n", n); | |
124 | + fd__trace("agent %d released success mutex\n", n); | |
123 | 125 | |
124 | 126 | if (!_fd_optimising) |
125 | 127 | return result; |
126 | 128 | |
127 | 129 | if (sem_wait(&resume_semaphore)) |
128 | 130 | perror("sem_post (resume)"); |
129 | - _fd_debug("[%d] resuming, new bound is %d\n", n, _fd_bound_value()); | |
131 | + fd__trace("[%d] resuming, new bound is %d\n", n, _fd_bound_value()); | |
130 | 132 | |
131 | 133 | // find the next solution |
132 | 134 | gettimeofday(&tis, NULL); |
... | ... | @@ -136,12 +138,12 @@ int _fd_agent(int n) |
136 | 138 | gettimeofday(&to, NULL); |
137 | 139 | timersub(&to, &tis, &tos); |
138 | 140 | timersub(&to, &ti, &to); |
139 | - _fd_debug("agent %d took %d.%06ds (%d.%06ds)\n", n, | |
141 | + fd__trace("agent %d took %d.%06ds (%d.%06ds)\n", n, | |
140 | 142 | tos.tv_sec, tos.tv_usec, to.tv_sec, to.tv_usec); |
141 | 143 | } |
142 | 144 | |
143 | 145 | // eventually, the agent will fail to find a solution |
144 | - _fd_debug("agent %d was unsuccessful\n", n); | |
146 | + fd__trace("agent %d was unsuccessful\n", n); | |
145 | 147 | |
146 | 148 | // tell the main thread that this agent is done |
147 | 149 | if (sem_wait(&ready_semaphore)) |
... | ... | @@ -159,7 +161,7 @@ int _fd_agent(int n) |
159 | 161 | unsigned long long solutions; |
160 | 162 | struct timeval ti, to; |
161 | 163 | |
162 | - _fd_debug("starting agent %d\n", n); | |
164 | + fd__trace("starting agent %d\n", n); | |
163 | 165 | |
164 | 166 | gettimeofday(&ti, NULL); |
165 | 167 | |
... | ... | @@ -171,9 +173,9 @@ int _fd_agent(int n) |
171 | 173 | |
172 | 174 | gettimeofday(&to, NULL); |
173 | 175 | timersub(&to, &ti, &to); |
174 | - _fd_debug("agent %d took %d.%06ds\n", n, to.tv_sec, to.tv_usec); | |
176 | + fd__trace("agent %d took %d.%06ds\n", n, to.tv_sec, to.tv_usec); | |
175 | 177 | |
176 | - _fd_debug("agent %d found %llu solutions\n", n, solutions); | |
178 | + fd__trace("agent %d found %llu solutions\n", n, solutions); | |
177 | 179 | |
178 | 180 | // tell the main thread that this agent is done |
179 | 181 | if (sem_wait(&ready_semaphore)) |
... | ... | @@ -193,7 +195,7 @@ int _fd_agent(int n) |
193 | 195 | |
194 | 196 | void _fd_search_space_sizes(_fd_store stores[], int n) |
195 | 197 | { |
196 | -#ifndef FAST | |
198 | +#ifdef TRACE | |
197 | 199 | double s; |
198 | 200 | int i, v; |
199 | 201 | |
... | ... | @@ -208,9 +210,9 @@ void _fd_search_space_sizes(_fd_store stores[], int n) |
208 | 210 | for (v = 0; v < fd__label_vars_count; ++v) |
209 | 211 | s *= _fd_val_size(SVALUE(stores[i][fd__label_vars[v]->index])); |
210 | 212 | |
211 | - _fd_debug("search space %d size is %g\n", i, s); | |
213 | + fd__trace("search space %d size is %g\n", i, s); | |
212 | 214 | } |
213 | -#endif /* FAST */ | |
215 | +#endif /* TRACE */ | |
214 | 216 | } |
215 | 217 | |
216 | 218 | int _fd_dsolve() |
... | ... | @@ -265,7 +267,7 @@ int _fd_dsolve() |
265 | 267 | |
266 | 268 | if (parts < nagents) |
267 | 269 | { |
268 | - _fd_debug("reducing to %d agents!\n", parts); | |
270 | + fd__trace("reducing to %d agents!\n", parts); | |
269 | 271 | |
270 | 272 | nagents = parts; |
271 | 273 | } |
... | ... | @@ -274,7 +276,7 @@ int _fd_dsolve() |
274 | 276 | |
275 | 277 | gettimeofday(&to, NULL); |
276 | 278 | timersub(&to, &ti, &to); |
277 | - _fd_debug("setup took %d.%06ds\n", to.tv_sec, to.tv_usec); | |
279 | + fd__trace("setup took %d.%06ds\n", to.tv_sec, to.tv_usec); | |
278 | 280 | |
279 | 281 | #if 0 |
280 | 282 | for (i = 0; i < nagents; ++i) |
... | ... | @@ -316,7 +318,7 @@ int _fd_dsolve() |
316 | 318 | } |
317 | 319 | } |
318 | 320 | |
319 | - _fd_debug("main thread waiting\n"); | |
321 | + fd__trace("main thread waiting\n"); | |
320 | 322 | |
321 | 323 | running = started; |
322 | 324 | do |
... | ... | @@ -329,7 +331,7 @@ int _fd_dsolve() |
329 | 331 | if (sem_post(&ready_semaphore)) |
330 | 332 | perror("sem_post"); |
331 | 333 | |
332 | - _fd_debug("got an answer from %s%d\n", solver == -1 ? "-" : "", | |
334 | + fd__trace("got an answer from %s%d\n", solver == -1 ? "-" : "", | |
333 | 335 | solver + (solver < 0)); |
334 | 336 | |
335 | 337 | if (_fd_optimising && solver >= 0) |
... | ... | @@ -344,10 +346,10 @@ int _fd_dsolve() |
344 | 346 | memcpy(store, _fd_agents_stores[solver], |
345 | 347 | fd_variables_count * sizeof(*store)); |
346 | 348 | |
347 | - _fd_debug("releasing %d\n", solver); | |
349 | + fd__trace("releasing %d\n", solver); | |
348 | 350 | } |
349 | 351 | else |
350 | - _fd_debug("invalid solution, releasing %d\n", solver); | |
352 | + fd__trace("invalid solution, releasing %d\n", solver); | |
351 | 353 | |
352 | 354 | if (sem_post(&resume_semaphore)) |
353 | 355 | perror("sem_post (resume)"); |
... | ... | @@ -359,14 +361,14 @@ int _fd_dsolve() |
359 | 361 | } |
360 | 362 | while ((_fd_optimising || solver < 0) && running > 0); |
361 | 363 | |
362 | - _fd_debug("%s solution\n", solver < 0 ? "found no" : "got a"); | |
364 | + fd__trace("%s solution\n", solver < 0 ? "found no" : "got a"); | |
363 | 365 | |
364 | 366 | for (i = 0; i < started; ++i) |
365 | 367 | { |
366 | 368 | int s; |
367 | 369 | |
368 | 370 | if ((s = pthread_cancel(threads[i])) && s != ESRCH) |
369 | - _fd_debug("error cancelling thread %d = %d\n", i, s); | |
371 | + fd__debug("error cancelling thread %d = %d\n", i, s); | |
370 | 372 | } |
371 | 373 | |
372 | 374 | // make sure all agents have stopped before exiting |
... | ... | @@ -376,24 +378,26 @@ int _fd_dsolve() |
376 | 378 | int s; |
377 | 379 | |
378 | 380 | if ((s = pthread_join(threads[i], NULL)) && s != ESRCH) |
379 | - _fd_debug("error joining thread %d = %d\n", i, s); | |
381 | + fd__debug("error joining thread %d = %d\n", i, s); | |
380 | 382 | } |
381 | 383 | |
382 | 384 | if (_fd_optimising) |
383 | 385 | { |
384 | 386 | if (have_solution >= 0) |
385 | 387 | { |
386 | - _fd_debug("using agent %d's results\n", have_solution); | |
388 | + fd__trace("using agent %d's results\n", have_solution); | |
387 | 389 | |
390 | +#if defined(STATS_TIME_SOLUTION) || defined(TRACE) | |
388 | 391 | timersub(&ts, &ti, &ts); |
389 | - _fd_debug("time to solution was %d.%06ds\n", ts.tv_sec, ts.tv_usec); | |
392 | + fd__debug("time to solution was %d.%06ds\n", ts.tv_sec, ts.tv_usec); | |
393 | +#endif | |
390 | 394 | |
391 | 395 | status = FD_OK; |
392 | 396 | } |
393 | 397 | } |
394 | 398 | else if (solver >= 0) |
395 | 399 | { |
396 | - _fd_debug("using agent %d's results\n", solver); | |
400 | + fd__trace("using agent %d's results\n", solver); | |
397 | 401 | |
398 | 402 | status = FD_OK; |
399 | 403 | |
... | ... | @@ -404,7 +408,7 @@ int _fd_dsolve() |
404 | 408 | else /* agents == 0 */ |
405 | 409 | { |
406 | 410 | if (_fd_optimising) |
407 | - _fd_fatal("need at least one agent when optimising"); | |
411 | + fd__fatal("need at least one agent when optimising"); | |
408 | 412 | |
409 | 413 | _fd_agents_stores[0] = store; |
410 | 414 | |
... | ... | @@ -439,7 +443,7 @@ int _fd_dsolve() |
439 | 443 | started++; |
440 | 444 | } |
441 | 445 | |
442 | - _fd_debug("main thread waiting\n"); | |
446 | + fd__trace("main thread waiting\n"); | |
443 | 447 | |
444 | 448 | running = started; |
445 | 449 | do |
... | ... | @@ -465,7 +469,7 @@ int _fd_dsolve() |
465 | 469 | |
466 | 470 | _fd_statistics_steal(); |
467 | 471 | |
468 | - _fd_output("found %llu solutions\n", total_solutions); // XXX | |
472 | + fd__output("found %llu solutions\n", total_solutions); // XXX | |
469 | 473 | |
470 | 474 | return FD_NOSOLUTION; // XXX |
471 | 475 | } |
... | ... |
src/bound.c
... | ... | @@ -5,8 +5,10 @@ |
5 | 5 | |
6 | 6 | #include "fdc_int.h" |
7 | 7 | #include "store.h" |
8 | - | |
9 | 8 | #include "bound.h" |
9 | +#include "constraints.h" | |
10 | + | |
11 | +#include "util.h" | |
10 | 12 | |
11 | 13 | bool _fd_optimising = false; |
12 | 14 | |
... | ... | @@ -32,10 +34,10 @@ _fd_bound_data *_fd_init_bound(int n, C_VAR_T v, fd_constraint c, |
32 | 34 | _fd_bound_data *b; |
33 | 35 | |
34 | 36 | if (_fd_bound) |
35 | - _fd_fatal("trying to set a 2nd optimisation constraint"); | |
37 | + fd__fatal("trying to set a 2nd optimisation constraint"); | |
36 | 38 | |
37 | 39 | if ((b = malloc(sizeof(*_fd_bound))) == NULL) |
38 | - _fd_fatal("could not allocate memory for the optimisation bound"); | |
40 | + fd__fatal("could not allocate memory for the optimisation bound"); | |
39 | 41 | |
40 | 42 | b->value = n; |
41 | 43 | b->variable = v; |
... | ... | @@ -121,9 +123,7 @@ int fd__bound_and_revise() |
121 | 123 | |
122 | 124 | if (_fd_revise_wrt_variable(_fd_bound_variable()) == FD_NOSOLUTION) |
123 | 125 | { |
124 | -#ifdef CONSTRAINT_TEMPS | |
125 | 126 | fd__constraint_data_reset(); |
126 | -#endif | |
127 | 127 | |
128 | 128 | return FD_NOSOLUTION; |
129 | 129 | } |
... | ... |
src/constraints.c
... | ... | @@ -7,31 +7,46 @@ |
7 | 7 | #include "variables.h" |
8 | 8 | #include "constraints.h" |
9 | 9 | |
10 | +#include "util.h" | |
11 | + | |
10 | 12 | #define MAX_CONSTRAINTS (512 * 512) |
11 | 13 | |
12 | 14 | int _fd_constraint_count = 0; |
13 | 15 | fd_constraint _fd_constraints[MAX_CONSTRAINTS]; |
14 | 16 | |
15 | -#ifdef CONSTRAINT_TEMPS | |
17 | + | |
18 | +#define CONSTRAINT_INITIALISATION(name, code) \ | |
19 | + static void fd_ ## name ## _init(_fd_constraint_class data[]) \ | |
20 | + { \ | |
21 | + data[code].propagator2 = fd_ ## name ## _propagate2; \ | |
22 | + data[code].filter = fd_ ## name ## _filter; \ | |
23 | + } | |
24 | + | |
25 | +#define initialise_constraint(name) fd_ ## name ## _init(_fd_constraint_data) | |
26 | + | |
27 | + | |
28 | +#ifdef CONSTRAINTS_HAVE_STATE | |
16 | 29 | #define CSTR_DATA_VALID 0x01 |
17 | 30 | #define CSTR_ENTAILED 0x02 |
18 | 31 | |
19 | 32 | static __thread uint8_t constraint_state_info[MAX_CONSTRAINTS]; |
33 | +# ifdef CONSTRAINT_TEMPS | |
20 | 34 | static __thread void *constraint_memory[MAX_CONSTRAINTS]; |
21 | -#endif | |
35 | +# endif | |
36 | +#endif /* CONSTRAINTS_HAVE_STATE */ | |
22 | 37 | |
23 | 38 | /* generic functions */ |
24 | 39 | |
25 | -fd_constraint _fd_constraint_new(int nvariables, int nconstants) | |
40 | +fd_constraint fd__constraint_new(int nvariables, int nconstants) | |
26 | 41 | { |
27 | 42 | fd_constraint c; |
28 | 43 | |
29 | 44 | if (_fd_constraint_count == MAX_CONSTRAINTS) |
30 | - _fd_fatal("too many constraints, increase MAX_CONSTRAINTS"); | |
45 | + fd__fatal("too many constraints, increase MAX_CONSTRAINTS"); | |
31 | 46 | |
32 | 47 | if (c = malloc(sizeof(struct fd_constraint))) |
33 | 48 | { |
34 | -#ifdef CONSTRAINT_TEMPS | |
49 | +#if defined(CONSTRAINT_TEMPS) || !defined(DISABLE_ENTAILED) | |
35 | 50 | c->index = _fd_constraint_count; |
36 | 51 | #endif |
37 | 52 | c->variables = calloc(nvariables, sizeof(C_VAR_T)); // XXX: check for NULL |
... | ... | @@ -41,12 +56,7 @@ fd_constraint _fd_constraint_new(int nvariables, int nconstants) |
41 | 56 | else |
42 | 57 | c->constants = 0; |
43 | 58 | c->nconstants = nconstants; |
44 | -#ifdef CONSTRAINT_CLASS | |
45 | 59 | c->kind = -1; // XXX |
46 | -#else /* CONSTRAINT_CLASS */ | |
47 | - c->propagator2 = _fd_undefined; | |
48 | - c->propagator = 0; | |
49 | -#endif /* CONSTRAINT_CLASS */ | |
50 | 60 | |
51 | 61 | _fd_constraints[_fd_constraint_count++] = c; |
52 | 62 | } |
... | ... | @@ -56,7 +66,7 @@ fd_constraint _fd_constraint_new(int nvariables, int nconstants) |
56 | 66 | |
57 | 67 | int _fd_undefined() |
58 | 68 | { |
59 | - _fd_fatal("called an undefined function"); | |
69 | + fd__fatal("called an undefined function"); | |
60 | 70 | } |
61 | 71 | |
62 | 72 | #ifdef DISTRIBUTED_SOLVER |
... | ... | @@ -77,9 +87,17 @@ void _fd_import_constraints(fd_int variables[]) |
77 | 87 | #endif /* DISTRIBUTED_SOLVER */ |
78 | 88 | |
79 | 89 | |
80 | -#ifdef CONSTRAINT_TEMPS | |
90 | +#ifdef CONSTRAINTS_HAVE_STATE | |
81 | 91 | #include <string.h> |
82 | 92 | |
93 | +void fd__constraint_data_reset(void) | |
94 | +{ | |
95 | + memset(constraint_state_info, 0, | |
96 | + _fd_constraint_count * sizeof(*constraint_state_info)); | |
97 | +} | |
98 | +#endif /* CONSTRAINTS_HAVE_STATE */ | |
99 | + | |
100 | +#ifdef CONSTRAINT_TEMPS | |
83 | 101 | int fd__constraint_data_valid(fd_constraint constraint) |
84 | 102 | { |
85 | 103 | return constraint_state_info[constraint->index] & CSTR_DATA_VALID; |
... | ... | @@ -90,6 +108,16 @@ void fd__constraint_remember(fd_constraint constraint) |
90 | 108 | constraint_state_info[constraint->index] |= CSTR_DATA_VALID; |
91 | 109 | } |
92 | 110 | |
111 | +void fd__constraint_free_memory(void) | |
112 | +{ | |
113 | + int i; | |
114 | + | |
115 | + for (i = 0; i < _fd_constraint_count; ++i) | |
116 | + if (constraint_memory[i]) | |
117 | + free(constraint_memory[i]); | |
118 | +} | |
119 | +#endif /* CONSTRAINT_TEMPS */ | |
120 | + | |
93 | 121 | #ifndef DISABLE_ENTAILED |
94 | 122 | void fd__constraint_set_entailed(fd_constraint constraint) |
95 | 123 | { |
... | ... | @@ -100,27 +128,12 @@ int fd__constraint_entailed(fd_constraint constraint) |
100 | 128 | { |
101 | 129 | return constraint_state_info[constraint->index] & CSTR_ENTAILED; |
102 | 130 | } |
103 | -#else | |
131 | +#else /* DISABLE_ENTAILED */ | |
104 | 132 | #define fd__constraint_set_entailed(_) ((void) 0) |
105 | -#endif | |
106 | - | |
107 | -void fd__constraint_data_reset() | |
108 | -{ | |
109 | - memset(constraint_state_info, 0, | |
110 | - _fd_constraint_count * sizeof(*constraint_state_info)); | |
111 | -} | |
133 | +#endif /* DISABLE_ENTAILED */ | |
112 | 134 | |
113 | -void fd__constraint_free_memory() | |
114 | -{ | |
115 | - int i; | |
116 | 135 | |
117 | - for (i = 0; i < _fd_constraint_count; ++i) | |
118 | - if (constraint_memory[i]) | |
119 | - free(constraint_memory[i]); | |
120 | -} | |
121 | -#else /* CONSTRAINT_TEMPS */ | |
122 | -#define fd__constraint_set_entailed(_) ((void) 0) | |
123 | -#endif /* CONSTRAINT_TEMPS */ | |
136 | +/* Import the constraints' code. */ | |
124 | 137 | |
125 | 138 | #include <constraints/lt.c> |
126 | 139 | #include <constraints/le.c> |
... | ... | @@ -152,40 +165,45 @@ void fd__constraint_free_memory() |
152 | 165 | #include <constraints/poly-eq-k.c> |
153 | 166 | #include <constraints/poly-ne.c> |
154 | 167 | #include <constraints/poly-ne-k.c> |
168 | +#include <constraints/poly-le-k.c> | |
155 | 169 | |
156 | -#ifdef CONSTRAINT_CLASS | |
157 | 170 | |
158 | 171 | _fd_constraint_class _fd_constraint_data[FD_CONSTR_KINDS]; |
159 | 172 | |
160 | -_FD_CONSTRAINT_INITIALISATION(ne, FD_CONSTR_NE) | |
161 | -_FD_CONSTRAINT_INITIALISATION(eq, FD_CONSTR_EQ) | |
162 | -_FD_CONSTRAINT_INITIALISATION(lt, FD_CONSTR_LT) | |
163 | -_FD_CONSTRAINT_INITIALISATION(le, FD_CONSTR_LE) | |
164 | -_FD_CONSTRAINT_INITIALISATION(minus_ne, FD_CONSTR_MINUS_NE) | |
165 | -_FD_CONSTRAINT_INITIALISATION(minus_eq, FD_CONSTR_MINUS_EQ) | |
166 | -// _FD_CONSTRAINT_INITIALISATION(plus_gt, FD_CONSTR_PLUS_GT) | |
167 | -_FD_CONSTRAINT_INITIALISATION(var_eq_minus, FD_CONSTR_VAR_EQ_MINUS) | |
168 | -_FD_CONSTRAINT_INITIALISATION(all_different, FD_CONSTR_ALL_DIFFERENT) | |
169 | -// _FD_CONSTRAINT_INITIALISATION(exactly_one, FD_CONSTR_EXACTLY_ONE) | |
170 | -// _FD_CONSTRAINT_INITIALISATION(nogoods, FD_CONSTR_NOGOODS) | |
171 | -_FD_CONSTRAINT_INITIALISATION(exactly, FD_CONSTR_EXACTLY) | |
172 | -_FD_CONSTRAINT_INITIALISATION(exactly_var, FD_CONSTR_EXACTLY_VAR) | |
173 | -_FD_CONSTRAINT_INITIALISATION(sum, FD_CONSTR_SUM) | |
174 | -_FD_CONSTRAINT_INITIALISATION(var_eq_times, FD_CONSTR_VAR_EQ_TIMES) | |
175 | -_FD_CONSTRAINT_INITIALISATION(sum_prod, FD_CONSTR_SUM_PROD) | |
176 | -_FD_CONSTRAINT_INITIALISATION(element, FD_CONSTR_ELEMENT) | |
177 | -_FD_CONSTRAINT_INITIALISATION(knapsack2, FD_CONSTR_KNAPSACK2) | |
178 | -_FD_CONSTRAINT_INITIALISATION(sum2, FD_CONSTR_SUM2) | |
179 | -_FD_CONSTRAINT_INITIALISATION(min, FD_CONSTR_MIN) | |
180 | -_FD_CONSTRAINT_INITIALISATION(max, FD_CONSTR_MAX) | |
181 | -_FD_CONSTRAINT_INITIALISATION(poly_eq, FD_CONSTR_POLY_EQ) | |
182 | -_FD_CONSTRAINT_INITIALISATION(element_var, FD_CONSTR_ELEMENT_VAR) | |
183 | -_FD_CONSTRAINT_INITIALISATION(exactly_vars, FD_CONSTR_EXACTLY_VARS) | |
184 | -_FD_CONSTRAINT_INITIALISATION(poly_eq_k, FD_CONSTR_POLY_EQ_K) | |
185 | -_FD_CONSTRAINT_INITIALISATION(poly_ne, FD_CONSTR_POLY_NE) | |
186 | -_FD_CONSTRAINT_INITIALISATION(poly_ne_k, FD_CONSTR_POLY_NE_K) | |
187 | - | |
188 | -void _fd_init_constraints() | |
173 | + | |
174 | +/* Define the constraints' initialisation functions. */ | |
175 | + | |
176 | +CONSTRAINT_INITIALISATION(ne, FD_CONSTR_NE) | |
177 | +CONSTRAINT_INITIALISATION(eq, FD_CONSTR_EQ) | |
178 | +CONSTRAINT_INITIALISATION(lt, FD_CONSTR_LT) | |
179 | +CONSTRAINT_INITIALISATION(le, FD_CONSTR_LE) | |
180 | +CONSTRAINT_INITIALISATION(minus_ne, FD_CONSTR_MINUS_NE) | |
181 | +CONSTRAINT_INITIALISATION(minus_eq, FD_CONSTR_MINUS_EQ) | |
182 | +// CONSTRAINT_INITIALISATION(plus_gt, FD_CONSTR_PLUS_GT) | |
183 | +CONSTRAINT_INITIALISATION(var_eq_minus, FD_CONSTR_VAR_EQ_MINUS) | |
184 | +CONSTRAINT_INITIALISATION(all_different, FD_CONSTR_ALL_DIFFERENT) | |
185 | +// CONSTRAINT_INITIALISATION(exactly_one, FD_CONSTR_EXACTLY_ONE) | |
186 | +// CONSTRAINT_INITIALISATION(nogoods, FD_CONSTR_NOGOODS) | |
187 | +CONSTRAINT_INITIALISATION(exactly, FD_CONSTR_EXACTLY) | |
188 | +CONSTRAINT_INITIALISATION(exactly_var, FD_CONSTR_EXACTLY_VAR) | |
189 | +CONSTRAINT_INITIALISATION(sum, FD_CONSTR_SUM) | |
190 | +CONSTRAINT_INITIALISATION(var_eq_times, FD_CONSTR_VAR_EQ_TIMES) | |
191 | +CONSTRAINT_INITIALISATION(sum_prod, FD_CONSTR_SUM_PROD) | |
192 | +CONSTRAINT_INITIALISATION(element, FD_CONSTR_ELEMENT) | |
193 | +CONSTRAINT_INITIALISATION(knapsack2, FD_CONSTR_KNAPSACK2) | |
194 | +CONSTRAINT_INITIALISATION(sum2, FD_CONSTR_SUM2) | |
195 | +CONSTRAINT_INITIALISATION(min, FD_CONSTR_MIN) | |
196 | +CONSTRAINT_INITIALISATION(max, FD_CONSTR_MAX) | |
197 | +CONSTRAINT_INITIALISATION(poly_eq, FD_CONSTR_POLY_EQ) | |
198 | +CONSTRAINT_INITIALISATION(element_var, FD_CONSTR_ELEMENT_VAR) | |
199 | +CONSTRAINT_INITIALISATION(exactly_vars, FD_CONSTR_EXACTLY_VARS) | |
200 | +CONSTRAINT_INITIALISATION(poly_eq_k, FD_CONSTR_POLY_EQ_K) | |
201 | +CONSTRAINT_INITIALISATION(poly_ne, FD_CONSTR_POLY_NE) | |
202 | +CONSTRAINT_INITIALISATION(poly_ne_k, FD_CONSTR_POLY_NE_K) | |
203 | +CONSTRAINT_INITIALISATION(poly_le_k, FD_CONSTR_POLY_LE_K) | |
204 | + | |
205 | +/* Initialises the constraints. */ | |
206 | +void fd__init_constraints() | |
189 | 207 | { |
190 | 208 | static int done = 0; |
191 | 209 | |
... | ... | @@ -194,35 +212,34 @@ void _fd_init_constraints() |
194 | 212 | |
195 | 213 | memset(_fd_constraint_data, 0, sizeof(_fd_constraint_data)); // XXX? |
196 | 214 | |
197 | - _fd_init_constraint(ne); | |
198 | - _fd_init_constraint(eq); | |
199 | - _fd_init_constraint(lt); | |
200 | - _fd_init_constraint(le); | |
201 | - _fd_init_constraint(minus_ne); | |
202 | - _fd_init_constraint(minus_eq); | |
203 | -// _fd_init_constraint(plus_gt); | |
204 | - _fd_init_constraint(var_eq_minus); | |
205 | - _fd_init_constraint(all_different); | |
206 | -// _fd_init_constraint(exactly_one); | |
207 | -// _fd_init_constraint(nogoods); | |
208 | - _fd_init_constraint(exactly); | |
209 | - _fd_init_constraint(exactly_var); | |
210 | - _fd_init_constraint(sum); | |
211 | - _fd_init_constraint(var_eq_times); | |
212 | - _fd_init_constraint(sum_prod); | |
213 | - _fd_init_constraint(element); | |
214 | - _fd_init_constraint(knapsack2); | |
215 | - _fd_init_constraint(sum2); | |
216 | - _fd_init_constraint(min); | |
217 | - _fd_init_constraint(max); | |
218 | - _fd_init_constraint(poly_eq); | |
219 | - _fd_init_constraint(element_var); | |
220 | - _fd_init_constraint(exactly_vars); | |
221 | - _fd_init_constraint(poly_eq_k); | |
222 | - _fd_init_constraint(poly_ne); | |
223 | - _fd_init_constraint(poly_ne_k); | |
215 | + initialise_constraint(ne); | |
216 | + initialise_constraint(eq); | |
217 | + initialise_constraint(lt); | |
218 | + initialise_constraint(le); | |
219 | + initialise_constraint(minus_ne); | |
220 | + initialise_constraint(minus_eq); | |
221 | +// initialise_constraint(plus_gt); | |
222 | + initialise_constraint(var_eq_minus); | |
223 | + initialise_constraint(all_different); | |
224 | +// initialise_constraint(exactly_one); | |
225 | +// initialise_constraint(nogoods); | |
226 | + initialise_constraint(exactly); | |
227 | + initialise_constraint(exactly_var); | |
228 | + initialise_constraint(sum); | |
229 | + initialise_constraint(var_eq_times); | |
230 | + initialise_constraint(sum_prod); | |
231 | + initialise_constraint(element); | |
232 | + initialise_constraint(knapsack2); | |
233 | + initialise_constraint(sum2); | |
234 | + initialise_constraint(min); | |
235 | + initialise_constraint(max); | |
236 | + initialise_constraint(poly_eq); | |
237 | + initialise_constraint(element_var); | |
238 | + initialise_constraint(exactly_vars); | |
239 | + initialise_constraint(poly_eq_k); | |
240 | + initialise_constraint(poly_ne); | |
241 | + initialise_constraint(poly_ne_k); | |
242 | + initialise_constraint(poly_le_k); | |
224 | 243 | |
225 | 244 | done = 1; |
226 | 245 | } |
227 | - | |
228 | -#endif /* CONSTRAINT_CLASS */ | |
... | ... |
src/constraints.h
... | ... | @@ -4,8 +4,6 @@ extern fd_constraint _fd_constraints[]; |
4 | 4 | |
5 | 5 | #define CONSTRAINT(v,c) _fd_constraints[(v)->constraints[c]] |
6 | 6 | |
7 | -#ifdef CONSTRAINT_CLASS | |
8 | - | |
9 | 7 | typedef enum { |
10 | 8 | FD_CONSTR_NE = 0, |
11 | 9 | FD_CONSTR_EQ, |
... | ... | @@ -36,37 +34,42 @@ typedef enum { |
36 | 34 | FD_CONSTR_POLY_EQ_K, |
37 | 35 | FD_CONSTR_POLY_NE, |
38 | 36 | FD_CONSTR_POLY_NE_K, |
37 | + FD_CONSTR_POLY_LE_K, | |
39 | 38 | FD_CONSTR_KINDS // number of kinds of constraints |
40 | 39 | } _fd_constraint_kind; |
41 | 40 | |
42 | 41 | typedef struct _fd_constraint_class { |
43 | 42 | int (*propagator2)(fd_constraint, fd_int); |
43 | + // propagates changes in a variable's | |
44 | + // domain; 2nd argument is the variable | |
45 | + // against which to revise the domains of | |
46 | + // the other variables in the constraint; | |
47 | + // returns FD_NOSOLUTION if some domain | |
48 | + // becomes empty, and FD_OK otherwise | |
44 | 49 | int (*filter)(fd_constraint); |
50 | + // performs an initial filtering of the | |
51 | + // domains of the constraint variables | |
45 | 52 | } _fd_constraint_class; |
46 | 53 | |
47 | -extern _fd_constraint_class _fd_constraint_data[FD_CONSTR_KINDS]; | |
48 | - | |
49 | - | |
50 | -#define _FD_CONSTRAINT_INITIALISATION(name, code) \ | |
51 | - static void _fd_ ## name ## _init(_fd_constraint_class data[]) \ | |
52 | - { \ | |
53 | - data[code].propagator2 = fd_ ## name ## _propagate2; \ | |
54 | - data[code].filter = fd_ ## name ## _filter; \ | |
55 | - } | |
56 | - | |
57 | -#define _fd_init_constraint(name) _fd_ ## name ## _init(_fd_constraint_data) | |
54 | +extern _fd_constraint_class _fd_constraint_data[]; | |
58 | 55 | |
59 | 56 | #define _fd_propagate(c,v) (_fd_constraint_data[(c)->kind].propagator2(c, v)) |
60 | 57 | #define _fd_filter(c) (_fd_constraint_data[(c)->kind].filter(c)) |
61 | 58 | |
62 | -#else /* CONSTRAINT_CLASS */ | |
59 | +void fd__init_constraints(); | |
63 | 60 | |
64 | -#define _fd_propagate(c,v) ((c)->propagator2(c, v)) | |
65 | -#define _fd_filter(c) ((c)->filter(c)) | |
66 | 61 | |
67 | -#endif /* CONSTRAINT_CLASS */ | |
62 | +#if defined(CONSTRAINT_TEMPS) || !defined(DISABLE_ENTAILED) | |
63 | +#define CONSTRAINTS_HAVE_STATE 1 | |
64 | +#endif | |
65 | + | |
66 | +#ifdef CONSTRAINTS_HAVE_STATE | |
67 | +void fd__constraint_data_reset(void); | |
68 | +#else | |
69 | +#define fd__constraint_data_reset() ((void) 0) | |
70 | +#endif | |
68 | 71 | |
69 | -#if defined(CONSTRAINT_TEMPS) && !defined(DISABLE_ENTAILED) | |
72 | +#ifndef DISABLE_ENTAILED | |
70 | 73 | int fd__constraint_entailed(fd_constraint); |
71 | 74 | #else |
72 | 75 | #define fd__constraint_entailed(_) 0 |
... | ... |
src/constraints/all-different.c
... | ... | @@ -128,7 +128,7 @@ static int fd_all_different_propagate(fd_constraint this, fd_int revise) |
128 | 128 | #if defined(USE_ENTAILED) && 0 |
129 | 129 | // XXX: hampers performance when not optimised |
130 | 130 | if (set == this->nvariables - 1) |
131 | - _fd_constraint_set_entailed(this); | |
131 | + fd__constraint_set_entailed(this); | |
132 | 132 | #endif |
133 | 133 | |
134 | 134 | if (changed) |
... | ... | @@ -148,18 +148,14 @@ fd_constraint fd_all_different(fd_int *variables, int nvariables) |
148 | 148 | if (nvariables == 2) |
149 | 149 | return fd_ne(variables[0], variables[1]); |
150 | 150 | |
151 | - c = _fd_constraint_new(nvariables, 0); | |
151 | + c = fd__constraint_new(nvariables, 0); | |
152 | 152 | |
153 | 153 | if (c) |
154 | 154 | { |
155 | 155 | for (i = 0; i < nvariables; ++i) |
156 | 156 | c->variables[i] = FD_INT2C_VAR(variables[i]); |
157 | -#ifdef CONSTRAINT_CLASS | |
157 | + | |
158 | 158 | c->kind = FD_CONSTR_ALL_DIFFERENT; |
159 | -#else /* CONSTRAINT_CLASS */ | |
160 | - c->propagator2 = fd_all_different_propagate2; | |
161 | - c->propagator = fd_all_different_propagate; | |
162 | -#endif /* CONSTRAINT_CLASS */ | |
163 | 159 | |
164 | 160 | for (i = 0; i < nvariables; ++i) |
165 | 161 | _fd_var_add_constraint(VAR(c, i), c); |
... | ... |
src/constraints/element-var.c
... | ... | @@ -143,7 +143,7 @@ static int fd_element_var_propagate2(fd_constraint this, fd_int culprit) |
143 | 143 | fd_constraint fd_element_var(fd_int *variables, int nvariables, fd_int index, |
144 | 144 | fd_int value) |
145 | 145 | { |
146 | - fd_constraint c = _fd_constraint_new(nvariables + 2, 0); | |
146 | + fd_constraint c = fd__constraint_new(nvariables + 2, 0); | |
147 | 147 | int i; |
148 | 148 | |
149 | 149 | // XXX: add a constraint 0 <= INDEX < nvariables |
... | ... | @@ -154,11 +154,8 @@ fd_constraint fd_element_var(fd_int *variables, int nvariables, fd_int index, |
154 | 154 | c->variables[i] = FD_INT2C_VAR(variables[i]); |
155 | 155 | c->variables[nvariables] = FD_INT2C_VAR(index); |
156 | 156 | c->variables[nvariables + 1] = FD_INT2C_VAR(value); |
157 | -#ifdef CONSTRAINT_CLASS | |
157 | + | |
158 | 158 | c->kind = FD_CONSTR_ELEMENT_VAR; |
159 | -#else /* CONSTRAINT_CLASS */ | |
160 | - c->propagator2 = fd_element_var_propagate2; | |
161 | -#endif /* CONSTRAINT_CLASS */ | |
162 | 159 | |
163 | 160 | for (i = 0; i < c->nvariables; ++i) |
164 | 161 | _fd_var_add_constraint(VAR(c, i), c); |
... | ... |
src/constraints/element.c
... | ... | @@ -102,7 +102,7 @@ static int fd_element_propagate2(fd_constraint this, fd_int culprit) |
102 | 102 | |
103 | 103 | fd_constraint fd_element(fd_int *variables, int nvariables, fd_int index, int k) |
104 | 104 | { |
105 | - fd_constraint c = _fd_constraint_new(nvariables + 1, 1); | |
105 | + fd_constraint c = fd__constraint_new(nvariables + 1, 1); | |
106 | 106 | int i; |
107 | 107 | |
108 | 108 | // XXX: add a constraint 0 <= INDEX < nvariables |
... | ... | @@ -113,11 +113,8 @@ fd_constraint fd_element(fd_int *variables, int nvariables, fd_int index, int k) |
113 | 113 | c->variables[i] = FD_INT2C_VAR(variables[i]); |
114 | 114 | c->variables[nvariables] = FD_INT2C_VAR(index); |
115 | 115 | c->constants[0] = k; |
116 | -#ifdef CONSTRAINT_CLASS | |
116 | + | |
117 | 117 | c->kind = FD_CONSTR_ELEMENT; |
118 | -#else /* CONSTRAINT_CLASS */ | |
119 | - c->propagator2 = fd_element_propagate2; | |
120 | -#endif /* CONSTRAINT_CLASS */ | |
121 | 118 | |
122 | 119 | for (i = 0; i < c->nvariables; ++i) |
123 | 120 | _fd_var_add_constraint(VAR(c, i), c); |
... | ... |
src/constraints/eq.c
... | ... | @@ -62,17 +62,13 @@ int fd_eq_propagate(fd_constraint this, fd_int revise) |
62 | 62 | |
63 | 63 | fd_constraint fd_eq(fd_int x, fd_int y) |
64 | 64 | { |
65 | - fd_constraint c = _fd_constraint_new(2, 0); | |
65 | + fd_constraint c = fd__constraint_new(2, 0); | |
66 | 66 | |
67 | 67 | if (c) |
68 | 68 | { |
69 | 69 | c->variables[0] = FD_INT2C_VAR(x); c->variables[1] = FD_INT2C_VAR(y); |
70 | -#ifdef CONSTRAINT_CLASS | |
70 | + | |
71 | 71 | c->kind = FD_CONSTR_EQ; |
72 | -#else /* CONSTRAINT_CLASS */ | |
73 | - c->propagator2 = fd_eq_propagate2; | |
74 | - c->propagator = fd_eq_propagate; | |
75 | -#endif /* CONSTRAINT_CLASS */ | |
76 | 72 | |
77 | 73 | _fd_var_add_constraint(x, c); |
78 | 74 | _fd_var_add_constraint(y, c); |
... | ... |
src/constraints/exactly-one.c
... | ... | @@ -72,7 +72,7 @@ static int fd_exactly_one_propagate(fd_constraint this, fd_int revise) |
72 | 72 | |
73 | 73 | fd_constraint fd_exactly_one(fd_int *variables, int nvariables, int value) |
74 | 74 | { |
75 | - fd_constraint c = _fd_constraint_new(nvariables, 1); | |
75 | + fd_constraint c = fd__constraint_new(nvariables, 1); | |
76 | 76 | int i; |
77 | 77 | |
78 | 78 | if (c) |
... | ... | @@ -80,11 +80,8 @@ fd_constraint fd_exactly_one(fd_int *variables, int nvariables, int value) |
80 | 80 | for (i = 0; i < nvariables; ++i) |
81 | 81 | c->variables[i] = FD_INT2C_VAR(variables[i]); |
82 | 82 | c->constants[0] = value; |
83 | -#ifdef CONSTRAINT_CLASS | |
83 | + | |
84 | 84 | c->kind = FD_CONSTR_EXACTLY_ONE; |
85 | -#else /* CONSTRAINT_CLASS */ | |
86 | - c->propagator = fd_exactly_one_propagate; | |
87 | -#endif /* CONSTRAINT_CLASS */ | |
88 | 85 | |
89 | 86 | for (i = 0; i < nvariables; ++i) |
90 | 87 | _fd_var_add_constraint(VAR(c, i), c); |
... | ... |
src/constraints/exactly-var.c
... | ... | @@ -159,7 +159,7 @@ static int fd_exactly_var_propagate2(fd_constraint this, fd_int culprit) |
159 | 159 | |
160 | 160 | fd_constraint fd_exactly_var(fd_int *variables, int nvariables, fd_int card, int k) |
161 | 161 | { |
162 | - fd_constraint c = _fd_constraint_new(nvariables + 1, 1); | |
162 | + fd_constraint c = fd__constraint_new(nvariables + 1, 1); | |
163 | 163 | int i; |
164 | 164 | |
165 | 165 | if (c) |
... | ... | @@ -168,11 +168,8 @@ fd_constraint fd_exactly_var(fd_int *variables, int nvariables, fd_int card, int |
168 | 168 | c->variables[i] = FD_INT2C_VAR(variables[i]); |
169 | 169 | c->variables[nvariables] = FD_INT2C_VAR(card); |
170 | 170 | c->constants[0] = k; |
171 | -#ifdef CONSTRAINT_CLASS | |
171 | + | |
172 | 172 | c->kind = FD_CONSTR_EXACTLY_VAR; |
173 | -#else /* CONSTRAINT_CLASS */ | |
174 | - c->propagator2 = fd_exactly_var_propagate2; | |
175 | -#endif /* CONSTRAINT_CLASS */ | |
176 | 173 | |
177 | 174 | for (i = 0; i <= nvariables; ++i) |
178 | 175 | _fd_var_add_constraint(VAR(c, i), c); |
... | ... |
src/constraints/exactly-vars.c
... | ... | @@ -166,7 +166,7 @@ static int fd_exactly_vars_propagate2(fd_constraint this, fd_int culprit) |
166 | 166 | |
167 | 167 | fd_constraint fd_exactly_vars(fd_int *variables, int nvariables, fd_int card, fd_int k) |
168 | 168 | { |
169 | - fd_constraint c = _fd_constraint_new(nvariables + 2, 0); | |
169 | + fd_constraint c = fd__constraint_new(nvariables + 2, 0); | |
170 | 170 | int i; |
171 | 171 | |
172 | 172 | if (c) |
... | ... | @@ -175,11 +175,8 @@ fd_constraint fd_exactly_vars(fd_int *variables, int nvariables, fd_int card, fd |
175 | 175 | c->variables[i] = FD_INT2C_VAR(variables[i]); |
176 | 176 | c->variables[nvariables] = FD_INT2C_VAR(card); |
177 | 177 | c->variables[nvariables + 1] = FD_INT2C_VAR(k); |
178 | -#ifdef CONSTRAINT_CLASS | |
178 | + | |
179 | 179 | c->kind = FD_CONSTR_EXACTLY_VARS; |
180 | -#else /* CONSTRAINT_CLASS */ | |
181 | - c->propagator2 = fd_exactly_vars_propagate2; | |
182 | -#endif /* CONSTRAINT_CLASS */ | |
183 | 180 | |
184 | 181 | for (i = 0; i < nvariables + 2; ++i) |
185 | 182 | _fd_var_add_constraint(VAR(c, i), c); |
... | ... |
src/constraints/exactly.c
... | ... | @@ -74,7 +74,7 @@ static int fd_exactly_propagate2(fd_constraint this, fd_int culprit) |
74 | 74 | |
75 | 75 | fd_constraint fd_exactly(fd_int *variables, int nvariables, int cardinal, int k) |
76 | 76 | { |
77 | - fd_constraint c = _fd_constraint_new(nvariables, 2); | |
77 | + fd_constraint c = fd__constraint_new(nvariables, 2); | |
78 | 78 | int i; |
79 | 79 | |
80 | 80 | if (c) |
... | ... | @@ -83,11 +83,8 @@ fd_constraint fd_exactly(fd_int *variables, int nvariables, int cardinal, int k) |
83 | 83 | c->variables[i] = FD_INT2C_VAR(variables[i]); |
84 | 84 | c->constants[0] = k; |
85 | 85 | c->constants[1] = cardinal; |
86 | -#ifdef CONSTRAINT_CLASS | |
86 | + | |
87 | 87 | c->kind = FD_CONSTR_EXACTLY; |
88 | -#else /* CONSTRAINT_CLASS */ | |
89 | - c->propagator2 = fd_exactly_propagate2; | |
90 | -#endif /* CONSTRAINT_CLASS */ | |
91 | 88 | |
92 | 89 | for (i = 0; i < nvariables; ++i) |
93 | 90 | _fd_var_add_constraint(VAR(c, i), c); |
... | ... |
src/constraints/knapsack.c
... | ... | @@ -105,7 +105,7 @@ static int fd_knapsack_propagate2(fd_constraint this, fd_int culprit) |
105 | 105 | |
106 | 106 | fd_constraint fd_knapsack(fd_int variables[], int nvariables, fd_int limits) |
107 | 107 | { |
108 | - fd_constraint c = _fd_constraint_new(nvariables + 1, 0); | |
108 | + fd_constraint c = fd__constraint_new(nvariables + 1, 0); | |
109 | 109 | int i; |
110 | 110 | |
111 | 111 | if (c) |
... | ... | @@ -113,11 +113,8 @@ fd_constraint fd_knapsack(fd_int variables[], int nvariables, fd_int limits) |
113 | 113 | for (i = 0; i < nvariables; ++i) |
114 | 114 | c->variables[i] = FD_INT2C_VAR(variables[i]); |
115 | 115 | c->variables[nvariables] = FD_INT2C_VAR(limits); |
116 | -#ifdef CONSTRAINT_CLASS | |
116 | + | |
117 | 117 | c->kind = FD_CONSTR_KNAPSACK; |
118 | -#else /* CONSTRAINT_CLASS */ | |
119 | - c->propagator2 = fd_knapsack_propagate2; | |
120 | -#endif /* CONSTRAINT_CLASS */ | |
121 | 118 | |
122 | 119 | for (i = 0; i < c->nvariables; ++i) |
123 | 120 | _fd_var_add_constraint(VAR(c, i), c); |
... | ... |
src/constraints/knapsack2.c
... | ... | @@ -4,12 +4,12 @@ |
4 | 4 | |
5 | 5 | static int fd_knapsack2_filter(fd_constraint this) |
6 | 6 | { |
7 | -#ifdef CONSTRAINT_TEMPS | |
8 | 7 | int ub, lb; |
9 | 8 | int min, max; |
10 | 9 | int terms = (this->nvariables - 1) / 2; |
11 | 10 | int *mins, *maxs; // XXX: trouble possible if a variable appears repeated |
12 | 11 | int i; |
12 | +#ifdef CONSTRAINT_TEMPS | |
13 | 13 | int *base; |
14 | 14 | |
15 | 15 | assert(!fd__constraint_data_valid(this)); |
... | ... | @@ -21,6 +21,10 @@ static int fd_knapsack2_filter(fd_constraint this) |
21 | 21 | |
22 | 22 | mins = base + 4; |
23 | 23 | maxs = mins + 2 * terms; |
24 | +#else | |
25 | + mins = alloca(2 * terms * sizeof(*mins)); | |
26 | + maxs = alloca(2 * terms * sizeof(*maxs)); | |
27 | +#endif | |
24 | 28 | |
25 | 29 | lb = _fd_var_min(VAR(this, this->nvariables - 1)); // lower bound |
26 | 30 | ub = _fd_var_max(VAR(this, this->nvariables - 1)); // upper bound |
... | ... | @@ -115,6 +119,7 @@ static int fd_knapsack2_filter(fd_constraint this) |
115 | 119 | (max < ub && _fd_var_del_gt(max, VAR(this, this->nvariables - 1)))) |
116 | 120 | _fd_revise_connected(this, VAR(this, this->nvariables - 1)); |
117 | 121 | |
122 | +#ifdef CONSTRAINT_TEMPS | |
118 | 123 | // save values |
119 | 124 | *base = lb; |
120 | 125 | *(base + 1) = ub; |
... | ... | @@ -122,120 +127,16 @@ static int fd_knapsack2_filter(fd_constraint this) |
122 | 127 | *(base + 3) = max; |
123 | 128 | |
124 | 129 | fd__constraint_remember(this); |
130 | +#endif | |
125 | 131 | |
126 | 132 | return FD_OK; |
127 | -#else /* CONSTRAINT_TEMPS */ | |
128 | - int ub, lb; | |
129 | - int min, max; | |
130 | - int terms = (this->nvariables - 1) / 2; | |
131 | - int *mins, *maxs; // XXX: trouble possible if a variable appears repeated | |
132 | - int i; | |
133 | - | |
134 | - mins = alloca(2 * terms * sizeof(*mins)); | |
135 | - maxs = alloca(2 * terms * sizeof(*maxs)); | |
136 | - | |
137 | - lb = _fd_var_min(VAR(this, this->nvariables - 1)); // lower bound | |
138 | - ub = _fd_var_max(VAR(this, this->nvariables - 1)); // upper bound | |
139 | - | |
140 | - // sum the minima of the terms | |
141 | - min = 0; | |
142 | - | |
143 | - for (i = 0; i < terms; ++i) | |
144 | - { | |
145 | - mins[i] = _fd_var_min(VAR(this, i)); | |
146 | - mins[terms + i] = _fd_var_min(VAR(this, terms + i)); | |
147 | - | |
148 | - min += mins[i] * mins[terms + i]; | |
149 | - | |
150 | - if (min > ub) | |
151 | - return FD_NOSOLUTION; | |
152 | - } | |
153 | - | |
154 | - // sum the maxima of the terms | |
155 | - max = 0; | |
156 | - | |
157 | - for (i = 0; i < terms; ++i) | |
158 | - { | |
159 | - maxs[i] = _fd_var_max(VAR(this, i)); | |
160 | - maxs[terms + i] = _fd_var_max(VAR(this, terms + i)); | |
161 | - | |
162 | - max += maxs[i] * maxs[terms + i]; | |
163 | - } | |
164 | - | |
165 | - if (max < lb) | |
166 | - return FD_NOSOLUTION; | |
167 | - | |
168 | - // XXX: poor man's propagation | |
169 | - if (min == ub) | |
170 | - for (i = 0; i < terms; ++i) | |
171 | - { | |
172 | - int min_x = mins[i]; | |
173 | - int min_y = mins[terms + i]; | |
174 | - | |
175 | - if (min_x != 0 || min_y != 0) | |
176 | - { | |
177 | - if (min_y != 0 && _fd_var_del_gt(min_x, VAR(this, i))) | |
178 | - _fd_revise_connected(this, VAR(this, i)); | |
179 | - | |
180 | - if (min_x != 0 && _fd_var_del_gt(min_y, VAR(this, terms + i))) | |
181 | - _fd_revise_connected(this, VAR(this, terms + i)); | |
182 | - } | |
183 | - } | |
184 | - else if (max == lb) | |
185 | - for (i = 0; i < terms; ++i) | |
186 | - { | |
187 | - int max_x = maxs[i]; | |
188 | - int max_y = maxs[terms + i]; | |
189 | - | |
190 | - if (max_x != 0 && max_y != 0) | |
191 | - { | |
192 | - if (_fd_var_del_lt(max_x, VAR(this, i))) | |
193 | - _fd_revise_connected(this, VAR(this, i)); | |
194 | - | |
195 | - if (_fd_var_del_lt(max_y, VAR(this, terms + i))) | |
196 | - _fd_revise_connected(this, VAR(this, terms + i)); | |
197 | - } | |
198 | - } | |
199 | - else if (max > ub) | |
200 | - for (i = 0; i < terms; ++i) | |
201 | - { | |
202 | - int min_x = mins[i]; | |
203 | - int max_x = maxs[i]; | |
204 | - int min_y = mins[terms + i]; | |
205 | - int max_y = maxs[terms + i]; | |
206 | - | |
207 | - if (min_x * (max_y - min_y) > ub - min) | |
208 | - { | |
209 | - max_y = (ub - min + min_x * min_y) / min_x; | |
210 | - | |
211 | - _fd_var_del_gt(max_y, VAR(this, terms + i)); | |
212 | - | |
213 | - _fd_revise_connected(this, VAR(this, terms + i)); | |
214 | - } | |
215 | - | |
216 | - if ((max_x - min_x) * min_y > ub - min) | |
217 | - { | |
218 | - max_x = (ub - min + min_x * min_y) / min_y; | |
219 | - | |
220 | - _fd_var_del_gt(max_x, VAR(this, i)); | |
221 | - | |
222 | - _fd_revise_connected(this, VAR(this, i)); | |
223 | - } | |
224 | - } | |
225 | - | |
226 | - if ((min > lb && _fd_var_del_lt(min, VAR(this, this->nvariables - 1))) | | |
227 | - (max < ub && _fd_var_del_gt(max, VAR(this, this->nvariables - 1)))) | |
228 | - _fd_revise_connected(this, VAR(this, this->nvariables - 1)); | |
229 | - | |
230 | - return FD_OK; | |
231 | -#endif /* CONSTRAINT_TEMPS */ | |
232 | 133 | } |
233 | 134 | |
234 | 135 | static int fd_knapsack2_propagate2(fd_constraint this, fd_int culprit) |
235 | 136 | { |
236 | 137 | #ifdef CONSTRAINT_TEMPS |
237 | 138 | int ub, lb; |
238 | - unsigned int min, max; | |
139 | + int min, max; | |
239 | 140 | int terms = (this->nvariables - 1) / 2; |
240 | 141 | int *mins, *maxs; // XXX: trouble possible if a variable appears repeated |
241 | 142 | int i; |
... | ... | @@ -379,7 +280,7 @@ static int fd_knapsack2_propagate2(fd_constraint this, fd_int culprit) |
379 | 280 | |
380 | 281 | fd_constraint fd_knapsack2(fd_int xs[], fd_int ys[], int nvariables, fd_int limits) |
381 | 282 | { |
382 | - fd_constraint c = _fd_constraint_new(2 * nvariables + 1, 0); | |
283 | + fd_constraint c = fd__constraint_new(2 * nvariables + 1, 0); | |
383 | 284 | int i; |
384 | 285 | |
385 | 286 | if (c) |
... | ... | @@ -389,11 +290,8 @@ fd_constraint fd_knapsack2(fd_int xs[], fd_int ys[], int nvariables, fd_int limi |
389 | 290 | for (; i < 2 * nvariables; ++i) |
390 | 291 | c->variables[i] = FD_INT2C_VAR(ys[i - nvariables]); |
391 | 292 | c->variables[2 * nvariables] = FD_INT2C_VAR(limits); |
392 | -#ifdef CONSTRAINT_CLASS | |
293 | + | |
393 | 294 | c->kind = FD_CONSTR_KNAPSACK2; |
394 | -#else /* CONSTRAINT_CLASS */ | |
395 | - c->propagator2 = fd_knapsack2_propagate2; | |
396 | -#endif /* CONSTRAINT_CLASS */ | |
397 | 295 | |
398 | 296 | for (i = 0; i < c->nvariables; ++i) |
399 | 297 | _fd_var_add_constraint(VAR(c, i), c); |
... | ... |
src/constraints/le.c
1 | -/* X le Y */ | |
1 | +/* x <= y */ | |
2 | 2 | |
3 | 3 | static int fd_le_filter(fd_constraint this) |
4 | 4 | { |
... | ... | @@ -7,12 +7,21 @@ static int fd_le_filter(fd_constraint this) |
7 | 7 | x = VAR(this, 0); |
8 | 8 | y = VAR(this, 1); |
9 | 9 | |
10 | +#ifndef DISABLE_ENTAILED | |
11 | + if (_fd_var_max(x) <= _fd_var_min(y)) | |
12 | + { | |
13 | + fd__constraint_set_entailed(this); | |
14 | + | |
15 | + return FD_OK; | |
16 | + } | |
17 | +#endif | |
18 | + | |
10 | 19 | if (_fd_var_del_lt(_fd_var_min(x), y)) |
11 | 20 | { |
12 | 21 | if (fd_domain_empty(y)) |
13 | 22 | return FD_NOSOLUTION; |
14 | 23 | |
15 | - _fd_revise_connected(NULL, y); | |
24 | + _fd_revise_connected(this, y); | |
16 | 25 | } |
17 | 26 | |
18 | 27 | if (_fd_var_del_gt(_fd_var_max(y), x)) |
... | ... | @@ -20,10 +29,10 @@ static int fd_le_filter(fd_constraint this) |
20 | 29 | if (fd_domain_empty(x)) |
21 | 30 | return FD_NOSOLUTION; |
22 | 31 | |
23 | - _fd_revise_connected(NULL, x); | |
32 | + _fd_revise_connected(this, x); | |
24 | 33 | } |
25 | 34 | |
26 | -#if CONSTRAINT_TEMPS > 3 | |
35 | +#ifndef DISABLE_ENTAILED | |
27 | 36 | if (_fd_var_max(x) <= _fd_var_min(y)) |
28 | 37 | fd__constraint_set_entailed(this); |
29 | 38 | #endif |
... | ... | @@ -31,39 +40,63 @@ static int fd_le_filter(fd_constraint this) |
31 | 40 | return FD_OK; |
32 | 41 | } |
33 | 42 | |
34 | -int fd_le_propagate2(fd_constraint this, fd_int culprit) | |
43 | +static int fd_le_propagate2(fd_constraint this, fd_int culprit) | |
35 | 44 | { |
45 | + fd_int x, y; | |
46 | + int vmax, vmin; | |
36 | 47 | fd_int revise; |
37 | 48 | int changed = 0; |
38 | 49 | |
39 | - if (culprit == VAR(this, 0)) | |
50 | + x = VAR(this, 0); | |
51 | + y = VAR(this, 1); | |
52 | + | |
53 | +#ifndef DISABLE_ENTAILED | |
54 | + vmax = _fd_var_max(x); | |
55 | + vmin = _fd_var_min(y); | |
56 | + | |
57 | + if (vmax <= vmin) | |
40 | 58 | { |
41 | - revise = VAR(this, 1); | |
59 | + fd__constraint_set_entailed(this); | |
42 | 60 | |
43 | - changed = _fd_var_del_lt(_fd_var_min(culprit), revise); | |
61 | + return FD_OK; | |
44 | 62 | } |
45 | - else | |
63 | +#endif | |
64 | + | |
65 | + if (culprit == x) | |
46 | 66 | { |
47 | - revise = VAR(this, 0); | |
67 | + revise = y; | |
48 | 68 | |
49 | - changed = _fd_var_del_gt(_fd_var_max(culprit), revise); | |
69 | + vmin = _fd_var_min(x); | |
70 | + | |
71 | + changed = _fd_var_del_lt(vmin, y); | |
50 | 72 | } |
73 | + else | |
74 | + { | |
75 | + revise = x; | |
51 | 76 | |
52 | - if (changed && fd_domain_empty(revise)) | |
53 | - return FD_NOSOLUTION; | |
77 | + vmax = _fd_var_max(y); | |
54 | 78 | |
55 | -#if CONSTRAINT_TEMPS > 3 | |
56 | - if (_fd_var_max(VAR(this, 0)) <= _fd_var_min(VAR(this, 1))) | |
57 | - fd__constraint_set_entailed(this); | |
58 | -#endif | |
79 | + changed = _fd_var_del_gt(vmax, x); | |
80 | + } | |
59 | 81 | |
60 | 82 | if (changed) |
61 | - _fd_revise_connected(0, revise); | |
83 | + { | |
84 | + if (fd_domain_empty(revise)) | |
85 | + return FD_NOSOLUTION; | |
86 | + | |
87 | + _fd_revise_connected(this, revise); | |
88 | + | |
89 | +#ifndef DISABLE_ENTAILED | |
90 | + // see if the culprit's domain is a singleton | |
91 | + if (vmin == vmax) | |
92 | + fd__constraint_set_entailed(this); | |
93 | +#endif | |
94 | + } | |
62 | 95 | |
63 | 96 | return FD_OK; |
64 | 97 | } |
65 | 98 | |
66 | -int fd_le_propagate(fd_constraint this, fd_int revise) | |
99 | +static int fd_le_propagate(fd_constraint this, fd_int revise) | |
67 | 100 | { |
68 | 101 | int changed = 0; |
69 | 102 | |
... | ... | @@ -77,7 +110,7 @@ int fd_le_propagate(fd_constraint this, fd_int revise) |
77 | 110 | |
78 | 111 | #ifdef USE_ENTAILED |
79 | 112 | if (_fd_var_max(VAR(this, 0)) <= _fd_var_min(VAR(this, 1))) |
80 | - _fd_constraint_set_entailed(this); | |
113 | + fd__constraint_set_entailed(this); | |
81 | 114 | #endif |
82 | 115 | |
83 | 116 | // XXX: enqueue further updates here? |
... | ... | @@ -89,17 +122,13 @@ int fd_le_propagate(fd_constraint this, fd_int revise) |
89 | 122 | |
90 | 123 | fd_constraint fd_le(fd_int x, fd_int y) |
91 | 124 | { |
92 | - fd_constraint c = _fd_constraint_new(2, 0); | |
125 | + fd_constraint c = fd__constraint_new(2, 0); | |
93 | 126 | |
94 | 127 | if (c) |
95 | 128 | { |
96 | 129 | c->variables[0] = FD_INT2C_VAR(x); c->variables[1] = FD_INT2C_VAR(y); |
97 | -#ifdef CONSTRAINT_CLASS | |
130 | + | |
98 | 131 | c->kind = FD_CONSTR_LE; |
99 | -#else /* CONSTRAINT_CLASS */ | |
100 | - c->propagator2 = fd_le_propagate2; | |
101 | - c->propagator = fd_le_propagate; | |
102 | -#endif /* CONSTRAINT_CLASS */ | |
103 | 132 | |
104 | 133 | _fd_var_add_constraint(x, c); |
105 | 134 | _fd_var_add_constraint(y, c); |
... | ... |
src/constraints/lt.c
1 | -/* X lt Y */ | |
1 | +/* x < y */ | |
2 | 2 | |
3 | -int fd_lt_filter(fd_constraint this) | |
3 | +static int fd_lt_filter(fd_constraint this) | |
4 | 4 | { |
5 | 5 | fd_int x, y; |
6 | 6 | |
... | ... | @@ -9,7 +9,11 @@ int fd_lt_filter(fd_constraint this) |
9 | 9 | |
10 | 10 | #ifndef DISABLE_ENTAILED |
11 | 11 | if (_fd_var_max(x) < _fd_var_min(y)) |
12 | - fd__constraint_set_entailed(this); | |
12 | + { | |
13 | + fd__constraint_set_entailed(this); | |
14 | + | |
15 | + return FD_OK; | |
16 | + } | |
13 | 17 | #endif |
14 | 18 | |
15 | 19 | if (_fd_var_del_le(_fd_var_min(x), y)) |
... | ... | @@ -17,7 +21,7 @@ int fd_lt_filter(fd_constraint this) |
17 | 21 | if (fd_domain_empty(y)) |
18 | 22 | return FD_NOSOLUTION; |
19 | 23 | |
20 | - _fd_revise_connected(NULL, y); | |
24 | + _fd_revise_connected(this, y); | |
21 | 25 | } |
22 | 26 | |
23 | 27 | if (_fd_var_del_ge(_fd_var_max(y), x)) |
... | ... | @@ -25,19 +29,32 @@ int fd_lt_filter(fd_constraint this) |
25 | 29 | if (fd_domain_empty(x)) |
26 | 30 | return FD_NOSOLUTION; |
27 | 31 | |
28 | - _fd_revise_connected(NULL, x); | |
32 | + _fd_revise_connected(this, x); | |
29 | 33 | } |
30 | 34 | |
35 | +#ifndef DISABLE_ENTAILED | |
36 | + if (_fd_var_max(x) < _fd_var_min(y)) | |
37 | + fd__constraint_set_entailed(this); | |
38 | +#endif | |
39 | + | |
31 | 40 | return FD_OK; |
32 | 41 | } |
33 | 42 | |
34 | -int fd_lt_propagate2(fd_constraint this, fd_int culprit) | |
43 | +static int fd_lt_propagate2(fd_constraint this, fd_int culprit) | |
35 | 44 | { |
45 | + fd_int x, y; | |
46 | + int vmax, vmin; | |
36 | 47 | fd_int revise; |
37 | 48 | int changed = 0; |
38 | 49 | |
39 | -#if !defined(DISABLE_ENTAILED) && CONSTRAINT_TEMPS > 2 | |
40 | - if (_fd_var_max(VAR(this, 0)) < _fd_var_min(VAR(this, 1))) | |
50 | + x = VAR(this, 0); | |
51 | + y = VAR(this, 1); | |
52 | + | |
53 | +#ifndef DISABLE_ENTAILED | |
54 | + vmax = _fd_var_max(x); | |
55 | + vmin = _fd_var_min(y); | |
56 | + | |
57 | + if (vmax < vmin) | |
41 | 58 | { |
42 | 59 | fd__constraint_set_entailed(this); |
43 | 60 | |
... | ... | @@ -45,29 +62,41 @@ int fd_lt_propagate2(fd_constraint this, fd_int culprit) |
45 | 62 | } |
46 | 63 | #endif |
47 | 64 | |
48 | - if (culprit == VAR(this, 0)) | |
65 | + if (culprit == x) | |
49 | 66 | { |
50 | - revise = VAR(this, 1); | |
67 | + revise = y; | |
51 | 68 | |
52 | - changed = _fd_var_del_le(_fd_var_min(culprit), revise); | |
69 | + vmin = _fd_var_min(x); | |
70 | + | |
71 | + changed = _fd_var_del_le(vmin, y); | |
53 | 72 | } |
54 | 73 | else |
55 | 74 | { |
56 | - revise = VAR(this, 0); | |
75 | + revise = x; | |
57 | 76 | |
58 | - changed = _fd_var_del_ge(_fd_var_max(culprit), revise); | |
59 | - } | |
77 | + vmax = _fd_var_max(y); | |
60 | 78 | |
61 | - if (changed && fd_domain_empty(revise)) | |
62 | - return FD_NOSOLUTION; | |
79 | + changed = _fd_var_del_ge(vmax, x); | |
80 | + } | |
63 | 81 | |
64 | 82 | if (changed) |
65 | - _fd_revise_connected(0, revise); | |
83 | + { | |
84 | + if (fd_domain_empty(revise)) | |
85 | + return FD_NOSOLUTION; | |
86 | + | |
87 | + _fd_revise_connected(this, revise); | |
88 | + | |
89 | +#ifndef DISABLE_ENTAILED | |
90 | + // see if the culprit's domain is a singleton | |
91 | + if (vmin == vmax) | |
92 | + fd__constraint_set_entailed(this); | |
93 | +#endif | |
94 | + } | |
66 | 95 | |
67 | 96 | return FD_OK; |
68 | 97 | } |
69 | 98 | |
70 | -int fd_lt_propagate(fd_constraint this, fd_int revise) | |
99 | +static int fd_lt_propagate(fd_constraint this, fd_int revise) | |
71 | 100 | { |
72 | 101 | int changed = 0; |
73 | 102 | |
... | ... | @@ -81,7 +110,7 @@ int fd_lt_propagate(fd_constraint this, fd_int revise) |
81 | 110 | |
82 | 111 | #ifdef USE_ENTAILED |
83 | 112 | if (_fd_var_max(VAR(this, 0)) < _fd_var_min(VAR(this, 1))) |
84 | - _fd_constraint_set_entailed(this); | |
113 | + fd__constraint_set_entailed(this); | |
85 | 114 | #endif |
86 | 115 | |
87 | 116 | // XXX: enqueue further updates here? |
... | ... | @@ -93,17 +122,13 @@ int fd_lt_propagate(fd_constraint this, fd_int revise) |
93 | 122 | |
94 | 123 | fd_constraint fd_lt(fd_int x, fd_int y) |
95 | 124 | { |
96 | - fd_constraint c = _fd_constraint_new(2, 0); | |
125 | + fd_constraint c = fd__constraint_new(2, 0); | |
97 | 126 | |
98 | 127 | if (c) |
99 | 128 | { |
100 | 129 | c->variables[0] = FD_INT2C_VAR(x); c->variables[1] = FD_INT2C_VAR(y); |
101 | -#ifdef CONSTRAINT_CLASS | |
130 | + | |
102 | 131 | c->kind = FD_CONSTR_LT; |
103 | -#else /* CONSTRAINT_CLASS */ | |
104 | - c->propagator2 = fd_lt_propagate2; | |
105 | - c->propagator = fd_lt_propagate; | |
106 | -#endif /* CONSTRAINT_CLASS */ | |
107 | 132 | |
108 | 133 | _fd_var_add_constraint(x, c); |
109 | 134 | _fd_var_add_constraint(y, c); |
... | ... |
src/constraints/max.c
... | ... | @@ -84,16 +84,13 @@ bool fd_max_bound_variable(fd_constraint this, int bound) |
84 | 84 | |
85 | 85 | fd_constraint fd_max(fd_int variable) |
86 | 86 | { |
87 | - fd_constraint c = _fd_constraint_new(1, 0); | |
87 | + fd_constraint c = fd__constraint_new(1, 0); | |
88 | 88 | |
89 | 89 | if (c) |
90 | 90 | { |
91 | 91 | c->variables[0] = FD_INT2C_VAR(variable); |
92 | -#ifdef CONSTRAINT_CLASS | |
92 | + | |
93 | 93 | c->kind = FD_CONSTR_MAX; |
94 | -#else /* CONSTRAINT_CLASS */ | |
95 | - c->propagator2 = fd_max_propagate2; | |
96 | -#endif /* CONSTRAINT_CLASS */ | |
97 | 94 | |
98 | 95 | _fd_var_add_constraint(variable, c); |
99 | 96 | |
... | ... |
src/constraints/min.c
... | ... | @@ -84,16 +84,13 @@ bool fd_min_bound_variable(fd_constraint this, int bound) |
84 | 84 | |
85 | 85 | fd_constraint fd_min(fd_int variable) |
86 | 86 | { |
87 | - fd_constraint c = _fd_constraint_new(1, 0); | |
87 | + fd_constraint c = fd__constraint_new(1, 0); | |
88 | 88 | |
89 | 89 | if (c) |
90 | 90 | { |
91 | 91 | c->variables[0] = FD_INT2C_VAR(variable); |
92 | -#ifdef CONSTRAINT_CLASS | |
92 | + | |
93 | 93 | c->kind = FD_CONSTR_MIN; |
94 | -#else /* CONSTRAINT_CLASS */ | |
95 | - c->propagator2 = fd_min_propagate2; | |
96 | -#endif /* CONSTRAINT_CLASS */ | |
97 | 94 | |
98 | 95 | _fd_var_add_constraint(variable, c); |
99 | 96 | |
... | ... |
src/constraints/minus-eq.c
... | ... | @@ -105,18 +105,14 @@ int fd_minus_eq_propagate(fd_constraint this, fd_int revise) |
105 | 105 | |
106 | 106 | fd_constraint fd_minus_eq(fd_int x, fd_int y, int k) |
107 | 107 | { |
108 | - fd_constraint c = _fd_constraint_new(2, 1); | |
108 | + fd_constraint c = fd__constraint_new(2, 1); | |
109 | 109 | |
110 | 110 | if (c) |
111 | 111 | { |
112 | 112 | c->variables[0] = FD_INT2C_VAR(x); c->variables[1] = FD_INT2C_VAR(y); |
113 | 113 | c->constants[0] = k; |
114 | -#ifdef CONSTRAINT_CLASS | |
114 | + | |
115 | 115 | c->kind = FD_CONSTR_MINUS_EQ; |
116 | -#else /* CONSTRAINT_CLASS */ | |
117 | - c->propagator2 = fd_minus_eq_propagate2; | |
118 | - c->propagator = fd_minus_eq_propagate; | |
119 | -#endif /* CONSTRAINT_CLASS */ | |
120 | 116 | |
121 | 117 | _fd_var_add_constraint(x, c); |
122 | 118 | _fd_var_add_constraint(y, c); |
... | ... |
src/constraints/minus-ne.c
... | ... | @@ -99,18 +99,14 @@ int fd_minus_ne_propagate(fd_constraint this, fd_int revise) |
99 | 99 | |
100 | 100 | fd_constraint fd_minus_ne(fd_int x, fd_int y, int k) |
101 | 101 | { |
102 | - fd_constraint c = _fd_constraint_new(2, 1); | |
102 | + fd_constraint c = fd__constraint_new(2, 1); | |
103 | 103 | |
104 | 104 | if (c) |
105 | 105 | { |
106 | 106 | c->variables[0] = FD_INT2C_VAR(x); c->variables[1] = FD_INT2C_VAR(y); |
107 | 107 | c->constants[0] = k; |
108 | -#ifdef CONSTRAINT_CLASS | |
108 | + | |
109 | 109 | c->kind = FD_CONSTR_MINUS_NE; |
110 | -#else /* CONSTRAINT_CLASS */ | |
111 | - c->propagator2 = fd_minus_ne_propagate2; | |
112 | - c->propagator = fd_minus_ne_propagate; | |
113 | -#endif /* CONSTRAINT_CLASS */ | |
114 | 110 | |
115 | 111 | _fd_var_add_constraint(x, c); |
116 | 112 | _fd_var_add_constraint(y, c); |
... | ... |
src/constraints/ne.c
... | ... | @@ -86,17 +86,13 @@ int fd_ne_propagate(fd_constraint this, fd_int revise) |
86 | 86 | |
87 | 87 | fd_constraint fd_ne(fd_int x, fd_int y) |
88 | 88 | { |
89 | - fd_constraint c = _fd_constraint_new(2, 0); | |
89 | + fd_constraint c = fd__constraint_new(2, 0); | |
90 | 90 | |
91 | 91 | if (c) |
92 | 92 | { |
93 | 93 | c->variables[0] = FD_INT2C_VAR(x); c->variables[1] = FD_INT2C_VAR(y); |
94 | -#ifdef CONSTRAINT_CLASS | |
94 | + | |
95 | 95 | c->kind = FD_CONSTR_NE; |
96 | -#else /* CONSTRAINT_CLASS */ | |
97 | - c->propagator2 = fd_ne_propagate2; | |
98 | - c->propagator = fd_ne_propagate; | |
99 | -#endif /* CONSTRAINT_CLASS */ | |
100 | 96 | |
101 | 97 | _fd_var_add_constraint(x, c); |
102 | 98 | _fd_var_add_constraint(y, c); |
... | ... |
src/constraints/nogoods.c
... | ... | @@ -35,16 +35,13 @@ int fd_nogoods_propagate(fd_constraint this, fd_int revise) |
35 | 35 | |
36 | 36 | fd_constraint fd_nogoods(fd_int x, fd_int y, int *nogoods, int nnogoods) |
37 | 37 | { |
38 | - fd_constraint c = _fd_constraint_new(2, 2 * nnogoods); | |
38 | + fd_constraint c = fd__constraint_new(2, 2 * nnogoods); | |
39 | 39 | |
40 | 40 | if (c) |
41 | 41 | { |
42 | 42 | c->variables[0] = FD_INT2C_VAR(x); c->variables[1] = FD_INT2C_VAR(y); |
43 | -#ifdef CONSTRAINT_CLASS | |
43 | + | |
44 | 44 | c->kind = FD_CONSTR_NOGOODS; |
45 | -#else /* CONSTRAINT_CLASS */ | |
46 | - c->propagator = fd_nogoods_propagate; | |
47 | -#endif /* CONSTRAINT_CLASS */ | |
48 | 45 | |
49 | 46 | memcpy(c->constants, nogoods, 2 * nnogoods * sizeof(int)); |
50 | 47 | |
... | ... |
src/constraints/plus-gt.c
... | ... | @@ -23,17 +23,14 @@ int fd_plus_gt_propagate(fd_constraint this, fd_int revise) |
23 | 23 | |
24 | 24 | fd_constraint fd_plus_gt(fd_int x, fd_int y, int k) |
25 | 25 | { |
26 | - fd_constraint c = _fd_constraint_new(2, 1); | |
26 | + fd_constraint c = fd__constraint_new(2, 1); | |
27 | 27 | |
28 | 28 | if (c) |
29 | 29 | { |
30 | 30 | c->variables[0] = FD_INT2C_VAR(x); c->variables[1] = FD_INT2C_VAR(y); |
31 | 31 | c->constants[0] = k; |
32 | -#ifdef CONSTRAINT_CLASS | |
32 | + | |
33 | 33 | c->kind = FD_CONSTR_PLUS_GT; |
34 | -#else /* CONSTRAINT_CLASS */ | |
35 | - c->propagator = fd_plus_gt_propagate; | |
36 | -#endif /* CONSTRAINT_CLASS */ | |
37 | 34 | |
38 | 35 | _fd_var_add_constraint(x, c); |
39 | 36 | _fd_var_add_constraint(y, c); |
... | ... |
src/constraints/poly-eq-k.c
1 | 1 | /* poly-eq-k(C, X, k) == sum(C . X) = k */ |
2 | 2 | |
3 | +// caveat: may not work correctly when there are more than one | |
4 | +// occurrences of some variable | |
5 | + | |
3 | 6 | static int fd_poly_eq_k_filter(fd_constraint this) |
4 | 7 | { |
5 | 8 | int k; |
... | ... | @@ -52,142 +55,99 @@ static int fd_poly_eq_k_filter(fd_constraint this) |
52 | 55 | return FD_NOSOLUTION; |
53 | 56 | |
54 | 57 | if (min == max) |
55 | - return FD_OK; | |
56 | - | |
57 | - // XXX: poor man's propagation | |
58 | - if (min == k) | |
59 | 58 | { |
60 | - for (i = 0; i < terms; ++i) | |
61 | - { | |
62 | - int c = this->constants[i]; | |
63 | - | |
64 | - if (c && mins[i] != maxs[i]) | |
65 | - { | |
66 | - if (c > 0) | |
67 | - _fd_var_del_gt(mins[i], VAR(this, i)); | |
68 | - else | |
69 | - _fd_var_del_lt(maxs[i], VAR(this, i)); | |
70 | - | |
71 | - // check needed for when variables occur more than once | |
72 | - // and with opposite signs | |
73 | - if (fd_domain_empty(VAR(this, i))) | |
74 | - return FD_NOSOLUTION; | |
75 | - | |
76 | - _fd_revise_connected(this, VAR(this, i)); | |
77 | - } | |
78 | - } | |
79 | - | |
80 | 59 | fd__constraint_set_entailed(this); |
81 | 60 | } |
82 | - else if (max == k) | |
61 | + else | |
83 | 62 | { |
84 | - for (i = 0; i < terms; ++i) | |
85 | - { | |
86 | - int c = this->constants[i]; | |
63 | + // bounds domain filtering | |
64 | + // XXX: number of iterations depends on the size of the domains | |
87 | 65 | |
88 | - if (c && mins[i] != maxs[i]) | |
89 | - { | |
90 | - if (c > 0) | |
91 | - _fd_var_del_lt(maxs[i], VAR(this, i)); | |
92 | - else | |
93 | - _fd_var_del_gt(mins[i], VAR(this, i)); | |
66 | + int omin, omax; | |
94 | 67 | |
95 | - if (fd_domain_empty(VAR(this, i))) | |
96 | - return FD_NOSOLUTION; | |
97 | - | |
98 | - _fd_revise_connected(this, VAR(this, i)); | |
99 | - } | |
100 | - } | |
68 | + do { | |
69 | + omin = min; | |
70 | + omax = max; | |
101 | 71 | |
102 | - fd__constraint_set_entailed(this); | |
103 | - } | |
104 | - else | |
105 | - { | |
106 | - if (max > k) | |
107 | 72 | for (i = 0; i < terms; ++i) |
108 | 73 | { |
109 | 74 | int c = this->constants[i]; |
110 | - int xmin = mins[i]; | |
111 | - int xmax = maxs[i]; | |
75 | + int imin = mins[i]; | |
76 | + int imax = maxs[i]; | |
77 | + | |
78 | + if (c == 0 || imin == imax) continue; | |
112 | 79 | |
113 | 80 | if (c > 0) |
114 | 81 | { |
115 | - // enforce sum{j!=i}(c[j] * min[j]) + c[i] * max[i] <= k | |
82 | + // enforce max(sum{j!=i}(c[j] * x[j])) + c[i] * min[i] >= k | |
116 | 83 | |
117 | - if ((xmax - xmin) * c > k - min) | |
84 | + if (max + (imin - imax) * c < k) | |
118 | 85 | { |
119 | - // xmax = floor((k - min) / c) + xmin | |
120 | - xmax = (k - min) / c + xmin; | |
86 | + // imin = ceil((k - max) / c) + imax | |
87 | + imin = (k - max) / c + imax; | |
121 | 88 | |
122 | - _fd_var_del_gt(xmax, VAR(this, i)); | |
89 | + fd_update_domain_and_check(del_lt, imin, VAR(this, i)); | |
123 | 90 | |
124 | - if (fd_domain_empty(VAR(this, i))) | |
91 | + min += (imin - mins[i]) * c; | |
92 | + | |
93 | + if (min > k) | |
125 | 94 | return FD_NOSOLUTION; |
126 | 95 | |
127 | - _fd_revise_connected(this, VAR(this, i)); | |
96 | + mins[i] = imin; | |
128 | 97 | } |
129 | - } | |
130 | - else if (c < 0) | |
131 | - { | |
132 | - // enforce sum{j!=i}(c[j] * min[j]) + c[i] * min[i] <= k | |
133 | 98 | |
134 | - if ((xmin - xmax) * c > k - min) | |
99 | + // enforce min(sum{j!=i}(c[j] * x[j])) + c[i] * max[i] <= k | |
100 | + | |
101 | + if (min + (imax - imin) * c > k) | |
135 | 102 | { |
136 | - // xmin = ceil((k - min) / c) + xmax | |
137 | - xmin = (k - min) / c + xmax; | |
103 | + // imax = floor((k - min) / c) + imin | |
104 | + imax = (k - min) / c + imin; | |
138 | 105 | |
139 | - _fd_var_del_lt(xmin, VAR(this, i)); | |
106 | + fd_update_domain_and_check(del_gt, imax, VAR(this, i)); | |
140 | 107 | |
141 | - if (fd_domain_empty(VAR(this, i))) | |
142 | - return FD_NOSOLUTION; | |
108 | + max -= (maxs[i] - imax) * c; // max >= k! | |
143 | 109 | |
144 | - _fd_revise_connected(this, VAR(this, i)); | |
110 | + maxs[i] = imax; | |
145 | 111 | } |
146 | 112 | } |
147 | - } | |
148 | - | |
149 | - if (min < k) | |
150 | - for (i = 0; i < terms; ++i) | |
151 | - { | |
152 | - int c = this->constants[i]; | |
153 | - int xmin = mins[i]; | |
154 | - int xmax = maxs[i]; | |
155 | - | |
156 | - if (c > 0) | |
113 | + else | |
157 | 114 | { |
158 | - // enforce sum{j!=i}(c[j] * max[j]) + c[i] * min[i] >= k | |
115 | + // enforce max(sum{j!=i}(c[j] * x[j])) + c[i] * max[i] >= k | |
159 | 116 | |
160 | - if ((xmax - xmin) * c > max - k) | |
117 | + if (max + (imax - imin) * c < k) | |
161 | 118 | { |
162 | - // xmin = ceil((k - max) / c) + xmax | |
163 | - xmin = (k - max) / c + xmax; | |
119 | + // imax = floor((k - max) / c) + imin | |
120 | + imax = (k - max) / c + imin; | |
121 | + | |
122 | + fd_update_domain_and_check(del_gt, imax, VAR(this, i)); | |
164 | 123 | |
165 | - _fd_var_del_lt(xmin, VAR(this, i)); | |
124 | + min += (imax - maxs[i]) * c; | |
166 | 125 | |
167 | - if (fd_domain_empty(VAR(this, i))) // domains may have holes | |
126 | + if (min > k) | |
168 | 127 | return FD_NOSOLUTION; |
169 | 128 | |
170 | - _fd_revise_connected(this, VAR(this, i)); | |
129 | + maxs[i] = imax; | |
171 | 130 | } |
172 | - } | |
173 | - else if (c < 0) | |
174 | - { | |
175 | - // enforce sum{j!=i}(c[j] * max[j]) + c[i] * max[i] >= k | |
176 | 131 | |
177 | - if ((xmax - xmin) * c < k - max) | |
132 | + // enforce min(sum{j!=i}(c[j] * x[j])) + c[i] * min[i] <= k | |
133 | + | |
134 | + if (min + (imin - imax) * c > k) | |
178 | 135 | { |
179 | - // xmax = floor((k - max) / c) + xmin | |
180 | - xmax = (k - max) / c + xmin; | |
136 | + // imin = ceil((k - min) / c) + imax | |
137 | + imin = (k - min) / c + imax; | |
181 | 138 | |
182 | - _fd_var_del_gt(xmax, VAR(this, i)); | |
139 | + fd_update_domain_and_check(del_lt, imin, VAR(this, i)); | |
183 | 140 | |
184 | - if (fd_domain_empty(VAR(this, i))) // domains may have holes | |
185 | - return FD_NOSOLUTION; | |
141 | + max -= (mins[i] - imin) * c; // max >= k! | |
186 | 142 | |
187 | - _fd_revise_connected(this, VAR(this, i)); | |
143 | + mins[i] = imin; | |
188 | 144 | } |
189 | 145 | } |
190 | 146 | } |
147 | + } while (min != max && (min != omin || max != omax)); | |
148 | + | |
149 | + if (min == max) | |
150 | + fd__constraint_set_entailed(this); | |
191 | 151 | } |
192 | 152 | |
193 | 153 | #ifdef CONSTRAINT_TEMPS |
... | ... | @@ -267,170 +227,104 @@ static int fd_poly_eq_k_propagate2(fd_constraint this, fd_int culprit) |
267 | 227 | } |
268 | 228 | while (x < terms); |
269 | 229 | |
270 | - // XXX: poor man's propagation | |
271 | - if (nmin == k) | |
272 | - { | |
273 | - for (i = 0; i < terms; ++i) | |
274 | - { | |
275 | - int c = this->constants[i]; | |
276 | - | |
277 | - if (c && mins[i] != maxs[i]) | |
278 | - { | |
279 | - if (c > 0) | |
280 | - { | |
281 | - _fd_var_del_gt(mins[i], VAR(this, i)); | |
282 | - | |
283 | - maxs[i] = mins[i]; | |
284 | - } | |
285 | - else | |
286 | - { | |
287 | - _fd_var_del_lt(maxs[i], VAR(this, i)); | |
288 | - | |
289 | - mins[i] = maxs[i]; | |
290 | - } | |
291 | - | |
292 | - if (fd_domain_empty(VAR(this, i))) | |
293 | - return FD_NOSOLUTION; | |
294 | - | |
295 | - _fd_revise_connected(this, VAR(this, i)); | |
296 | - } | |
297 | - } | |
230 | + if (nmin == min && nmax == max) | |
231 | + return FD_OK; | |
298 | 232 | |
233 | + if (nmin == nmax) | |
234 | + { | |
299 | 235 | fd__constraint_set_entailed(this); |
300 | 236 | } |
301 | - else if (nmax == k) | |
237 | + else | |
302 | 238 | { |
303 | - for (i = 0; i < terms; ++i) | |
304 | - { | |
305 | - int c = this->constants[i]; | |
306 | - | |
307 | - if (c && mins[i] != maxs[i]) | |
308 | - { | |
309 | - if (c > 0) | |
310 | - { | |
311 | - _fd_var_del_lt(maxs[i], VAR(this, i)); | |
239 | + // bounds domain propagation | |
240 | + // XXX: number of iterations depends on the size of the domains | |
312 | 241 | |
313 | - mins[i] = maxs[i]; | |
314 | - } | |
315 | - else | |
316 | - { | |
317 | - _fd_var_del_gt(mins[i], VAR(this, i)); | |
242 | + int onmin, onmax; | |
318 | 243 | |
319 | - maxs[i] = mins[i]; | |
320 | - } | |
244 | + do { | |
245 | + onmin = nmin; | |
246 | + onmax = nmax; | |
321 | 247 | |
322 | - if (fd_domain_empty(VAR(this, i))) | |
323 | - return FD_NOSOLUTION; | |
324 | - | |
325 | - _fd_revise_connected(this, VAR(this, i)); | |
326 | - } | |
327 | - } | |
328 | - | |
329 | - fd__constraint_set_entailed(this); | |
330 | - } | |
331 | - | |
332 | -#if 0 // this is too expensive | |
333 | - { | |
334 | - if (nmax < max && nmax > k) | |
335 | 248 | for (i = 0; i < terms; ++i) |
336 | 249 | { |
337 | 250 | int c = this->constants[i]; |
338 | - int xmin = mins[i]; | |
339 | - int xmax = maxs[i]; | |
251 | + int imin = mins[i]; | |
252 | + int imax = maxs[i]; | |
253 | + | |
254 | + if (c == 0 || imin == imax) continue; | |
340 | 255 | |
341 | 256 | if (c > 0) |
342 | 257 | { |
343 | - // enforce sum{j!=i}(c[j] * min[j]) + c[i] * max[i] <= k | |
258 | + // enforce max(sum{j!=i}(c[j] * x[j])) + c[i] * min[i] >= k | |
344 | 259 | |
345 | - if ((xmax - xmin) * c > k - nmin) | |
260 | + if (nmax + (imin - imax) * c < k) | |
346 | 261 | { |
347 | - // xmax = floor((k - nmin) / c) + xmin | |
348 | - xmax = (k - nmin) / c + xmin; | |
262 | + // imin = ceil((k - nmax) / c) + imax | |
263 | + imin = (k - nmax) / c + imax; | |
264 | + | |
265 | + fd_update_domain_and_check(del_lt, imin, VAR(this, i)); | |
349 | 266 | |
350 | - if (_fd_var_del_gt(xmax, VAR(this, i))) | |
351 | - { | |
352 | - if (fd_domain_empty(VAR(this, i))) | |
353 | - return FD_NOSOLUTION; | |
267 | + nmin += (imin - mins[i]) * c; | |
354 | 268 | |
355 | - _fd_revise_connected(this, VAR(this, i)); | |
356 | - } | |
269 | + if (nmin > k) | |
270 | + return FD_NOSOLUTION; | |
357 | 271 | |
358 | - maxs[i] = xmax; | |
272 | + mins[i] = imin; | |
359 | 273 | } |
360 | - } | |
361 | - else if (c < 0) | |
362 | - { | |
363 | - // enforce sum{j!=i}(c[j] * min[j]) + c[i] * min[i] <= k | |
364 | 274 | |
365 | - if ((xmin - xmax) * c > k - nmin) | |
275 | + // enforce min(sum{j!=i}(c[j] * x[j])) + c[i] * max[i] <= k | |
276 | + | |
277 | + if (nmin + (imax - imin) * c > k) | |
366 | 278 | { |
367 | - // xmin = ceil((k - nmin) / c) + xmax | |
368 | - xmin = (k - nmin) / c + xmax; | |
279 | + // imax = floor((k - nmin) / c) + imin | |
280 | + imax = (k - nmin) / c + imin; | |
369 | 281 | |
370 | - if (_fd_var_del_lt(xmin, VAR(this, i))) | |
371 | - { | |
372 | - if (fd_domain_empty(VAR(this, i))) | |
373 | - return FD_NOSOLUTION; | |
282 | + fd_update_domain_and_check(del_gt, imax, VAR(this, i)); | |
374 | 283 | |
375 | - _fd_revise_connected(this, VAR(this, i)); | |
376 | - } | |
284 | + nmax -= (maxs[i] - imax) * c; // nmax >= k! | |
377 | 285 | |
378 | - mins[i] = xmin; | |
286 | + maxs[i] = imax; | |
379 | 287 | } |
380 | 288 | } |
381 | - } | |
382 | - | |
383 | - if (nmin > min && nmin < k) | |
384 | - for (i = 0; i < terms; ++i) | |
385 | - { | |
386 | - int c = this->constants[i]; | |
387 | - int xmin = mins[i]; | |
388 | - int xmax = maxs[i]; | |
389 | - | |
390 | - if (c > 0) | |
289 | + else | |
391 | 290 | { |
392 | - // enforce sum{j!=i}(c[j] * max[j]) + c[i] * min[i] >= k | |
291 | + // enforce max(sum{j!=i}(c[j] * x[j])) + c[i] * max[i] >= k | |
393 | 292 | |
394 | - if ((xmax - xmin) * c > nmax - k) | |
293 | + if (nmax + (imax - imin) * c < k) | |
395 | 294 | { |
396 | - // xmin = ceil((k - nmax) / c) + xmax | |
397 | - xmin = (k - nmax) / c + xmax; | |
295 | + // imax = floor((k - nmax) / c) + imin | |
296 | + imax = (k - nmax) / c + imin; | |
398 | 297 | |
399 | - if (_fd_var_del_lt(xmin, VAR(this, i))) | |
400 | - { | |
298 | + fd_update_domain_and_check(del_gt, imax, VAR(this, i)); | |
401 | 299 | |
402 | - if (fd_domain_empty(VAR(this, i))) // domains may have holes | |
403 | - return FD_NOSOLUTION; | |
300 | + nmin += (imax - maxs[i]) * c; | |
404 | 301 | |
405 | - _fd_revise_connected(this, VAR(this, i)); | |
406 | - } | |
302 | + if (nmin > k) | |
303 | + return FD_NOSOLUTION; | |
407 | 304 | |
408 | - mins[i] = xmin; | |
305 | + maxs[i] = imax; | |
409 | 306 | } |
410 | - } | |
411 | - else if (c < 0) | |
412 | - { | |
413 | - // enforce sum{j!=i}(c[j] * max[j]) + c[i] * max[i] >= k | |
414 | 307 | |
415 | - if ((xmax - xmin) * c < k - nmax) | |
308 | + // enforce min(sum{j!=i}(c[j] * x[j])) + c[i] * min[i] <= k | |
309 | + | |
310 | + if (nmin + (imin - imax) * c > k) | |
416 | 311 | { |
417 | - // xmax = floor((k - nmax) / c) + xmin | |
418 | - xmax = (k - nmax) / c + xmin; | |
312 | + // imin = ceil((k - nmin) / c) + imax | |
313 | + imin = (k - nmin) / c + imax; | |
419 | 314 | |
420 | - if (_fd_var_del_gt(xmax, VAR(this, i))) | |
421 | - { | |
422 | - if (fd_domain_empty(VAR(this, i))) // domains may have holes | |
423 | - return FD_NOSOLUTION; | |
315 | + fd_update_domain_and_check(del_lt, imin, VAR(this, i)); | |
424 | 316 | |
425 | - _fd_revise_connected(this, VAR(this, i)); | |
426 | - } | |
317 | + nmax -= (mins[i] - imin) * c; // nmax >= k! | |
427 | 318 | |
428 | - maxs[i] = xmax; | |
319 | + mins[i] = imin; | |
429 | 320 | } |
430 | 321 | } |
431 | 322 | } |
323 | + } while (nmin != nmax && (nmin != onmin || nmax != onmax)); | |
324 | + | |
325 | + if (nmin == nmax) | |
326 | + fd__constraint_set_entailed(this); | |
432 | 327 | } |
433 | -#endif | |
434 | 328 | |
435 | 329 | *base = nmin; |
436 | 330 | *(base + 1) = nmax; |
... | ... | @@ -443,7 +337,7 @@ static int fd_poly_eq_k_propagate2(fd_constraint this, fd_int culprit) |
443 | 337 | |
444 | 338 | fd_constraint fd_poly_eq_k(int cs[], fd_int xs[], int nterms, int k) |
445 | 339 | { |
446 | - fd_constraint c = _fd_constraint_new(nterms, nterms + 1); | |
340 | + fd_constraint c = fd__constraint_new(nterms, nterms + 1); | |
447 | 341 | int i; |
448 | 342 | |
449 | 343 | if (c) |
... | ... | @@ -453,11 +347,8 @@ fd_constraint fd_poly_eq_k(int cs[], fd_int xs[], int nterms, int k) |
453 | 347 | for (i = 0; i < nterms; ++i) |
454 | 348 | c->constants[i] = cs[i]; |
455 | 349 | c->constants[nterms] = k; |
456 | -#ifdef CONSTRAINT_CLASS | |
350 | + | |
457 | 351 | c->kind = FD_CONSTR_POLY_EQ_K; |
458 | -#else /* CONSTRAINT_CLASS */ | |
459 | - c->propagator2 = fd_poly_eq_k_propagate2; | |
460 | -#endif /* CONSTRAINT_CLASS */ | |
461 | 352 | |
462 | 353 | for (i = 0; i < c->nvariables; ++i) |
463 | 354 | _fd_var_add_constraint(VAR(c, i), c); |
... | ... |
src/constraints/poly-eq.c
1 | -/* poly-eq(C, X, y) == min(y) <= sum(C . X) <= max(y) */ | |
1 | +/* poly-eq(C, X, y) == sum(C . X) = y */ | |
2 | + | |
3 | +// caveat: may not work correctly when there are more than one | |
4 | +// occurrences of some variable | |
2 | 5 | |
3 | 6 | static int fd_poly_eq_filter(fd_constraint this) |
4 | 7 | { |
... | ... | @@ -52,154 +55,155 @@ static int fd_poly_eq_filter(fd_constraint this) |
52 | 55 | if (min > ub || max < lb) |
53 | 56 | return FD_NOSOLUTION; |
54 | 57 | |
55 | - if ((min > lb && _fd_var_del_lt(min, VAR(this, this->nvariables - 1))) | | |
56 | - (max < ub && _fd_var_del_gt(max, VAR(this, this->nvariables - 1)))) | |
58 | + if (min > lb) | |
57 | 59 | { |
58 | - if (fd_domain_empty(VAR(this, this->nvariables - 1))) | |
59 | - return FD_NOSOLUTION; | |
60 | + fd_update_domain_and_check(del_lt, min, VAR(this, this->nvariables - 1)); | |
61 | + | |
62 | + lb = min; | |
63 | + } | |
64 | + | |
65 | + if (max < ub) | |
66 | + { | |
67 | + fd_update_domain_and_check(del_gt, max, VAR(this, this->nvariables - 1)); | |
60 | 68 | |
61 | - _fd_revise_connected(this, VAR(this, this->nvariables - 1)); | |
69 | + ub = max; | |
62 | 70 | } |
63 | 71 | |
64 | 72 | if (min == max) |
65 | - return FD_OK; | |
73 | + { | |
74 | + fd__constraint_set_entailed(this); | |
75 | + } | |
76 | + else | |
77 | + { | |
78 | + // bounds domain filtering | |
79 | + // XXX: number of iterations depends on the size of the domains | |
66 | 80 | |
67 | - // XXX: poor man's propagation | |
68 | - if (min == ub) | |
69 | - for (i = 0; i < terms; ++i) | |
70 | - { | |
71 | - int c = this->constants[i]; | |
81 | + int omin, omax; | |
72 | 82 | |
73 | - if (c && mins[i] != maxs[i]) | |
83 | + do { | |
84 | + omin = min; | |
85 | + omax = max; | |
86 | + | |
87 | + if (max > ub) | |
74 | 88 | { |
75 | - if (c > 0) | |
89 | + for (i = 0; i < terms; ++i) | |
76 | 90 | { |
77 | - _fd_var_del_gt(mins[i], VAR(this, i)); | |
91 | + int c = this->constants[i]; | |
92 | + int imin = mins[i]; | |
93 | + int imax = maxs[i]; | |
78 | 94 | |
79 | - // check needed for when variables occur twice and | |
80 | - // with opposite signs | |
81 | - if (fd_domain_empty(VAR(this, i))) | |
82 | - return FD_NOSOLUTION; | |
95 | + if (c == 0 || imin == imax) continue; | |
83 | 96 | |
84 | - _fd_revise_connected(this, VAR(this, i)); | |
85 | - } | |
86 | - else | |
87 | - { | |
88 | - _fd_var_del_lt(maxs[i], VAR(this, i)); | |
97 | + if (c > 0) | |
98 | + { | |
99 | + // enforce min(sum{j!=i}(c[j] * x[j])) + c[i] * max[i] <= max[y] | |
89 | 100 | |
90 | - if (fd_domain_empty(VAR(this, i))) | |
91 | - return FD_NOSOLUTION; | |
101 | + if (min + (imax - imin) * c > ub) | |
102 | + { | |
103 | + // imax = floor((ub - min) / c) + imin | |
104 | + imax = (ub - min) / c + imin; | |
92 | 105 | |
93 | - _fd_revise_connected(this, VAR(this, i)); | |
94 | - } | |
95 | - } | |
96 | - } | |
97 | - else if (max == lb) | |
98 | - for (i = 0; i < terms; ++i) | |
99 | - { | |
100 | - int c = this->constants[i]; | |
106 | + fd_update_domain_and_check(del_gt, imax, VAR(this, i)); | |
101 | 107 | |
102 | - if (c && mins[i] != maxs[i]) | |
103 | - { | |
104 | - if (c > 0) | |
105 | - { | |
106 | - _fd_var_del_lt(maxs[i], VAR(this, i)); | |
108 | + max -= (maxs[i] - imax) * c; | |
107 | 109 | |
108 | - if (fd_domain_empty(VAR(this, i))) | |
109 | - return FD_NOSOLUTION; | |
110 | + maxs[i] = imax; | |
111 | + } | |
112 | + } | |
113 | + else | |
114 | + { | |
115 | + // enforce min(sum{j!=i}(c[j] * x[j])) + c[i] * min[i] <= max[y] | |
110 | 116 | |
111 | - _fd_revise_connected(this, VAR(this, i)); | |
112 | - } | |
113 | - else | |
114 | - { | |
115 | - _fd_var_del_gt(mins[i], VAR(this, i)); | |
117 | + if (min + (imin - imax) * c > ub) | |
118 | + { | |
119 | + // imin = ceil((ub - min) / c) + imax | |
120 | + imin = (ub - min) / c + imax; | |
121 | + | |
122 | + fd_update_domain_and_check(del_lt, imin, VAR(this, i)); | |
116 | 123 | |
117 | - if (fd_domain_empty(VAR(this, i))) | |
118 | - return FD_NOSOLUTION; | |
124 | + max -= (mins[i] - imin) * c; | |
119 | 125 | |
120 | - _fd_revise_connected(this, VAR(this, i)); | |
126 | + mins[i] = imin; | |
127 | + } | |
128 | + } | |
121 | 129 | } |
130 | + | |
131 | + if (max < lb) | |
132 | + return FD_NOSOLUTION; | |
122 | 133 | } |
123 | - } | |
124 | - else | |
125 | - { | |
126 | - if (max > ub) | |
127 | - for (i = 0; i < terms; ++i) | |
128 | - { | |
129 | - int c = this->constants[i]; | |
130 | - int xmin = mins[i]; | |
131 | - int xmax = maxs[i]; | |
132 | 134 | |
133 | - if (c > 0) | |
135 | + if (min < lb) | |
136 | + { | |
137 | + for (i = 0; i < terms; ++i) | |
134 | 138 | { |
135 | - if ((xmax - xmin) * c > ub - min) | |
139 | + int c = this->constants[i]; | |
140 | + int imin = mins[i]; | |
141 | + int imax = maxs[i]; | |
142 | + | |
143 | + if (c == 0 || imin == imax) continue; | |
144 | + | |
145 | + if (c > 0) | |
136 | 146 | { |
137 | - // xmax = floor((ub - min) / c) + xmin | |
138 | - xmax = (ub - min) / c + xmin; | |
147 | + // enforce max(sum{j!=i}(c[j] * x[j])) + c[i] * min[i] >= min[y] | |
148 | + | |
149 | + if (max + (imin - imax) * c < lb) | |
150 | + { | |
151 | + // imin = ceil((lb - max) / c) + imax | |
152 | + imin = (lb - max) / c + imax; | |
139 | 153 | |
140 | - _fd_var_del_gt(xmax, VAR(this, i)); | |
154 | + fd_update_domain_and_check(del_lt, imin, VAR(this, i)); | |
141 | 155 | |
142 | - if (fd_domain_empty(VAR(this, i))) | |
143 | - return FD_NOSOLUTION; | |
156 | + min += (imin - mins[i]) * c; | |
144 | 157 | |
145 | - _fd_revise_connected(this, VAR(this, i)); | |
158 | + mins[i] = imin; | |
159 | + } | |
146 | 160 | } |
147 | - } | |
148 | - else if (c < 0) | |
149 | - { | |
150 | - if ((xmin - xmax) * c > ub - min) | |
161 | + else | |
151 | 162 | { |
152 | - // xmin = ceil((ub - min) / c) + xmax | |
153 | - xmin = (ub - min) / c + xmax; | |
163 | + // enforce max(sum{j!=i}(c[j] * x[j])) + c[i] * max[i] >= min[y] | |
164 | + | |
165 | + if (max + (imax - imin) * c < lb) | |
166 | + { | |
167 | + // imax = floor((lb - max) / c) + imin | |
168 | + imax = (lb - max) / c + imin; | |
154 | 169 | |
155 | - _fd_var_del_lt(xmin, VAR(this, i)); | |
170 | + fd_update_domain_and_check(del_gt, imax, VAR(this, i)); | |
156 | 171 | |
157 | - if (fd_domain_empty(VAR(this, i))) | |
158 | - return FD_NOSOLUTION; | |
172 | + min += (imax - maxs[i]) * c; | |
159 | 173 | |
160 | - _fd_revise_connected(this, VAR(this, i)); | |
174 | + maxs[i] = imax; | |
175 | + } | |
161 | 176 | } |
162 | 177 | } |
178 | + | |
179 | + if (min > ub) | |
180 | + return FD_NOSOLUTION; | |
163 | 181 | } |
164 | 182 | |
165 | - if (min < lb) | |
166 | - for (i = 0; i < terms; ++i) | |
183 | + if (min > lb && _fd_var_del_lt(min, VAR(this, this->nvariables - 1))) | |
167 | 184 | { |
168 | - int c = this->constants[i]; | |
169 | - int xmin = mins[i]; | |
170 | - int xmax = maxs[i]; | |
185 | + if (fd_domain_empty(VAR(this, this->nvariables - 1))) | |
186 | + return FD_NOSOLUTION; | |
171 | 187 | |
172 | - if (c > 0) | |
173 | - { | |
174 | - if ((xmax - xmin) * c > max - lb) | |
175 | - { | |
176 | - // xmin = ceil((lb - max) / c) + xmax | |
177 | - xmin = (lb - max) / c + xmax; | |
188 | + _fd_revise_connected(this, VAR(this, this->nvariables - 1)); | |
178 | 189 | |
179 | - _fd_var_del_lt(xmin, VAR(this, i)); | |
190 | + lb = min; | |
191 | + } | |
180 | 192 | |
181 | - if (fd_domain_empty(VAR(this, i))) // domains may have holes | |
182 | - return FD_NOSOLUTION; | |
193 | + if (max < ub && _fd_var_del_gt(max, VAR(this, this->nvariables - 1))) | |
194 | + { | |
195 | + if (fd_domain_empty(VAR(this, this->nvariables - 1))) | |
196 | + return FD_NOSOLUTION; | |
183 | 197 | |
184 | - _fd_revise_connected(this, VAR(this, i)); | |
185 | - } | |
186 | - } | |
187 | - else if (c < 0) | |
188 | - { | |
189 | - if ((xmax - xmin) * c < lb - max) | |
190 | - { | |
191 | - // xmax = floor((lb - max) / c) + xmin | |
192 | - xmax = (lb - max) / c + xmin; | |
198 | + _fd_revise_connected(this, VAR(this, this->nvariables - 1)); | |
193 | 199 | |
194 | - _fd_var_del_gt(xmax, VAR(this, i)); | |
200 | + ub = max; | |
201 | + } | |
195 | 202 | |
196 | - if (fd_domain_empty(VAR(this, i))) // domains may have holes | |
197 | - return FD_NOSOLUTION; | |
203 | + } while (min != max && (min != omin || max != omax)); | |
198 | 204 | |
199 | - _fd_revise_connected(this, VAR(this, i)); | |
200 | - } | |
201 | - } | |
202 | - } | |
205 | + if (min == max) | |
206 | + fd__constraint_set_entailed(this); | |
203 | 207 | } |
204 | 208 | |
205 | 209 | #ifdef CONSTRAINT_TEMPS |
... | ... | @@ -226,6 +230,7 @@ static int fd_poly_eq_propagate2(fd_constraint this, fd_int culprit) |
226 | 230 | int *base; |
227 | 231 | int x, c; |
228 | 232 | int nmin, nmin_x, nmax, nmax_x; |
233 | + int nlb, nub; | |
229 | 234 | |
230 | 235 | if (!fd__constraint_data_valid(this)) |
231 | 236 | return fd_poly_eq_filter(this); // ignores culprit |
... | ... | @@ -237,16 +242,15 @@ static int fd_poly_eq_propagate2(fd_constraint this, fd_int culprit) |
237 | 242 | mins = base + 4; |
238 | 243 | maxs = mins + terms; |
239 | 244 | |
240 | - lb = *base; | |
241 | - ub = *(base + 1); | |
245 | + nlb = lb = *base; | |
246 | + nub = ub = *(base + 1); | |
242 | 247 | |
243 | - min = *(base + 2); | |
244 | - max = *(base + 3); | |
248 | + nmin = min = *(base + 2); | |
249 | + nmax = max = *(base + 3); | |
245 | 250 | |
246 | 251 | if (culprit == VAR(this, this->nvariables - 1)) |
247 | 252 | { |
248 | 253 | // the culprit is the sum variable |
249 | - int nlb, nub; | |
250 | 254 | |
251 | 255 | nlb = _fd_var_min(culprit); |
252 | 256 | nub = _fd_var_max(culprit); |
... | ... | @@ -254,203 +258,205 @@ static int fd_poly_eq_propagate2(fd_constraint this, fd_int culprit) |
254 | 258 | if (nlb == lb && nub == ub) |
255 | 259 | return FD_OK; |
256 | 260 | |
257 | - if (nlb != lb) | |
258 | - { | |
259 | - if (max < nlb) | |
260 | - return FD_NOSOLUTION; | |
261 | + if (min > nub || max < nlb) | |
262 | + return FD_NOSOLUTION; | |
263 | + } | |
264 | + else | |
265 | + { | |
266 | + // the culprit appears in one of the terms, find out which one(s) | |
267 | + for (x = 0; culprit != VAR(this, x); ++x) | |
268 | + ; | |
261 | 269 | |
262 | - if (max == nlb) | |
263 | - for (i = 0; i < terms; ++i) | |
264 | - { | |
265 | - if (this->constants[i] > 0) | |
266 | - { | |
267 | - if (_fd_var_del_lt(maxs[i], VAR(this, i))) | |
268 | - { | |
269 | - if (fd_domain_empty(VAR(this, i))) | |
270 | - return FD_NOSOLUTION; | |
270 | + nmin_x = _fd_var_min(VAR(this, x)); | |
271 | + nmax_x = _fd_var_max(VAR(this, x)); | |
271 | 272 | |
272 | - _fd_revise_connected(this, VAR(this, i)); | |
273 | - } | |
274 | - } | |
275 | - else if (this->constants[i] < 0) | |
276 | - { | |
277 | - if (_fd_var_del_gt(mins[i], VAR(this, i))) | |
278 | - { | |
279 | - if (fd_domain_empty(VAR(this, i))) | |
280 | - return FD_NOSOLUTION; | |
273 | + if (nmin_x == mins[x] && nmax_x == maxs[x]) | |
274 | + return FD_OK; | |
281 | 275 | |
282 | - _fd_revise_connected(this, VAR(this, i)); | |
283 | - } | |
284 | - } | |
285 | - } | |
276 | + do | |
277 | + { | |
278 | + c = this->constants[x]; | |
279 | + | |
280 | + if (c > 0) | |
281 | + { | |
282 | + nmin = nmin + (nmin_x - mins[x]) * c; | |
283 | + nmax = nmax - (maxs[x] - nmax_x) * c; | |
284 | + } | |
285 | + else if (c < 0) | |
286 | + { | |
287 | + nmin = nmin - (maxs[x] - nmax_x) * c; | |
288 | + nmax = nmax + (nmin_x - mins[x]) * c; | |
289 | + } | |
290 | + | |
291 | + if (nmin > ub || nmax < lb) | |
292 | + return FD_NOSOLUTION; | |
286 | 293 | |
287 | - if (min < nlb) | |
288 | - for (i = 0; i < terms; ++i) | |
289 | - { | |
290 | - int c = this->constants[i]; | |
291 | - int xmin = mins[i]; | |
292 | - int xmax = maxs[i]; | |
294 | + mins[x] = nmin_x; | |
295 | + maxs[x] = nmax_x; | |
293 | 296 | |
294 | - if (c > 0) | |
295 | - { | |
296 | - if ((xmax - xmin) * c > max - nlb) | |
297 | - { | |
298 | - // xmin = ceil((nlb - max) / c) + xmax | |
299 | - xmin = (nlb - max) / c + xmax; | |
297 | + while (++x < terms && culprit != VAR(this, x)) | |
298 | + ; | |
299 | + } | |
300 | + while (x < terms); | |
300 | 301 | |
301 | - _fd_var_del_lt(xmin, VAR(this, i)); | |
302 | + if (nmin == min && nmax == max) | |
303 | + return FD_OK; | |
302 | 304 | |
303 | - if (fd_domain_empty(VAR(this, i))) // domains may have holes | |
304 | - return FD_NOSOLUTION; | |
305 | + if (nmin > lb) | |
306 | + { | |
307 | + fd_update_domain_and_check(del_lt, nmin, VAR(this, this->nvariables - 1)); | |
305 | 308 | |
306 | - _fd_revise_connected(this, VAR(this, i)); | |
307 | - } | |
308 | - } | |
309 | - else if (c < 0) | |
310 | - { | |
311 | - if ((xmax - xmin) * c < nlb - max) | |
312 | - { | |
313 | - // xmax = floor((nlb - max) / c) + xmin | |
314 | - xmax = (nlb - max) / c + xmin; | |
309 | + nlb = nmin; | |
310 | + } | |
315 | 311 | |
316 | - _fd_var_del_gt(xmax, VAR(this, i)); | |
312 | + if (nmax < ub) | |
313 | + { | |
314 | + fd_update_domain_and_check(del_gt, nmax, VAR(this, this->nvariables - 1)); | |
317 | 315 | |
318 | - if (fd_domain_empty(VAR(this, i))) // domains may have holes | |
319 | - return FD_NOSOLUTION; | |
316 | + nub = nmax; | |
317 | + } | |
318 | + } | |
320 | 319 | |
321 | - _fd_revise_connected(this, VAR(this, i)); | |
322 | - } | |
323 | - } | |
324 | - } | |
320 | + // (nmin, nlb, nub, nmax) != (min, lb, ub, max) | |
325 | 321 | |
326 | - *base = nlb; | |
327 | - } | |
322 | + if (nmin == nmax) | |
323 | + { | |
324 | + fd__constraint_set_entailed(this); | |
325 | + } | |
326 | + else | |
327 | + { | |
328 | + // bounds domain propagation | |
329 | + // XXX: number of iterations depends on the size of the domains | |
328 | 330 | |
329 | - if (nub != ub) | |
330 | - { | |
331 | - if (min > nub) | |
332 | - return FD_NOSOLUTION; | |
331 | + int onmin, onmax; | |
333 | 332 | |
334 | - if (min == nub) | |
333 | + do { | |
334 | + onmin = nmin; | |
335 | + onmax = nmax; | |
336 | + | |
337 | + if (nmin < nlb) | |
338 | + { | |
335 | 339 | for (i = 0; i < terms; ++i) |
336 | 340 | { |
337 | - if (this->constants[i] > 0) | |
341 | + int c = this->constants[i]; | |
342 | + int imin = mins[i]; | |
343 | + int imax = maxs[i]; | |
344 | + | |
345 | + if (c == 0 || imin == imax) continue; | |
346 | + | |
347 | + if (c > 0) | |
338 | 348 | { |
339 | - if (_fd_var_del_gt(mins[i], VAR(this, i))) | |
349 | + // enforce max(sum{j!=i}(c[j] * x[j])) + c[i] * min[i] >= min[y] | |
350 | + | |
351 | + if (nmax + (imin - imax) * c < nlb) | |
340 | 352 | { |
341 | - if (fd_domain_empty(VAR(this, i))) | |
342 | - return FD_NOSOLUTION; | |
353 | + // imin = ceil((nlb - nmax) / c) + imax | |
354 | + imin = (nlb - nmax) / c + imax; | |
355 | + | |
356 | + fd_update_domain_and_check(del_lt, imin, VAR(this, i)); | |
357 | + | |
358 | + nmin += (imin - mins[i]) * c; | |
343 | 359 | |
344 | - _fd_revise_connected(this, VAR(this, i)); | |
360 | + mins[i] = imin; | |
345 | 361 | } |
346 | 362 | } |
347 | - else if (this->constants[i] < 0) | |
363 | + else | |
348 | 364 | { |
349 | - if (_fd_var_del_lt(maxs[i], VAR(this, i))) | |
365 | + // enforce max(sum{j!=i}(c[j] * x[j])) + c[i] * max[i] >= min[y] | |
366 | + | |
367 | + if (nmax + (imax - imin) * c < nlb) | |
350 | 368 | { |
351 | - if (fd_domain_empty(VAR(this, i))) | |
352 | - return FD_NOSOLUTION; | |
369 | + // imax = floor((nlb - nmax) / c) + imin | |
370 | + imax = (nlb - nmax) / c + imin; | |
371 | + | |
372 | + fd_update_domain_and_check(del_gt, imax, VAR(this, i)); | |
353 | 373 | |
354 | - _fd_revise_connected(this, VAR(this, i)); | |
374 | + nmin += (imax - maxs[i]) * c; | |
375 | + | |
376 | + maxs[i] = imax; | |
355 | 377 | } |
356 | 378 | } |
357 | 379 | } |
358 | 380 | |
359 | - if (max > nub) | |
360 | - for (i = 0; i < terms; ++i) | |
361 | - { | |
362 | - int c = this->constants[i]; | |
363 | - int xmin = mins[i]; | |
364 | - int xmax = maxs[i]; | |
381 | + if (nmin > nub) | |
382 | + return FD_NOSOLUTION; | |
383 | + } | |
365 | 384 | |
366 | - if (c > 0) | |
385 | + if (nmax > nub) | |
386 | + { | |
387 | + for (i = 0; i < terms; ++i) | |
367 | 388 | { |
368 | - if ((xmax - xmin) * c > nub - min) | |
389 | + int c = this->constants[i]; | |
390 | + int imin = mins[i]; | |
391 | + int imax = maxs[i]; | |
392 | + | |
393 | + if (c == 0 || imin == imax) continue; | |
394 | + | |
395 | + if (c > 0) | |
369 | 396 | { |
370 | - // xmax = floor((nub - min) / c) + xmin | |
371 | - xmax = (nub - min) / c + xmin; | |
397 | + // enforce min(sum{j!=i}(c[j] * x[j])) + c[i] * max[i] <= max[y] | |
372 | 398 | |
373 | - if (_fd_var_del_gt(xmax, VAR(this, i))) | |
399 | + if (nmin + (imax - imin) * c > nub) | |
374 | 400 | { |
375 | - if (fd_domain_empty(VAR(this, i))) | |
376 | - return FD_NOSOLUTION; | |
401 | + // imax = floor((nub - nmin) / c) + imin | |
402 | + imax = (nub - nmin) / c + imin; | |
377 | 403 | |
378 | - _fd_revise_connected(this, VAR(this, i)); | |
404 | + fd_update_domain_and_check(del_gt, imax, VAR(this, i)); | |
405 | + | |
406 | + nmax -= (maxs[i] - imax) * c; | |
407 | + | |
408 | + maxs[i] = imax; | |
379 | 409 | } |
380 | 410 | } |
381 | - } | |
382 | - else if (c < 0) | |
383 | - { | |
384 | - if ((xmin - xmax) * c > nub - min) | |
411 | + else | |
385 | 412 | { |
386 | - // xmin = ceil((nub - min) / c) + xmax | |
387 | - xmin = (nub - min) / c + xmax; | |
413 | + // enforce min(sum{j!=i}(c[j] * x[j])) + c[i] * min[i] <= max[y] | |
388 | 414 | |
389 | - if (_fd_var_del_lt(xmin, VAR(this, i))) | |
415 | + if (nmin + (imin - imax) * c > nub) | |
390 | 416 | { |
391 | - if (fd_domain_empty(VAR(this, i))) | |
392 | - return FD_NOSOLUTION; | |
417 | + // imin = ceil((nub - nmin) / c) + imax | |
418 | + imin = (nub - nmin) / c + imax; | |
419 | + | |
420 | + fd_update_domain_and_check(del_lt, imin, VAR(this, i)); | |
393 | 421 | |
394 | - _fd_revise_connected(this, VAR(this, i)); | |
422 | + nmax -= (mins[i] - imin) * c; | |
423 | + | |
424 | + mins[i] = imin; | |
395 | 425 | } |
396 | 426 | } |
397 | 427 | } |
398 | - } | |
399 | - | |
400 | - *(base + 1) = nub; | |
401 | - } | |
402 | - | |
403 | - return FD_OK; | |
404 | - } | |
405 | - | |
406 | - // the culprit appears in one of the terms, find out which one(s) | |
407 | - for (x = 0; culprit != VAR(this, x); ++x) | |
408 | - ; | |
409 | - | |
410 | - nmin_x = _fd_var_min(VAR(this, x)); | |
411 | - nmax_x = _fd_var_max(VAR(this, x)); | |
412 | - | |
413 | - if (nmin_x == mins[x] && nmax_x == maxs[x]) | |
414 | - return FD_OK; | |
415 | 428 | |
416 | - nmin = min; | |
417 | - nmax = max; | |
429 | + if (nmax < nlb) | |
430 | + return FD_NOSOLUTION; | |
431 | + } | |
418 | 432 | |
419 | - do | |
420 | - { | |
421 | - c = this->constants[x]; | |
433 | + if (nmin > nlb && _fd_var_del_lt(nmin, VAR(this, this->nvariables - 1))) | |
434 | + { | |
435 | + if (fd_domain_empty(VAR(this, this->nvariables - 1))) | |
436 | + return FD_NOSOLUTION; | |
422 | 437 | |
423 | - if (c > 0) | |
424 | - { | |
425 | - nmin = nmin + (nmin_x - mins[x]) * c; | |
426 | - nmax = nmax - (maxs[x] - nmax_x) * c; | |
427 | - } | |
428 | - else if (c < 0) | |
429 | - { | |
430 | - nmin = nmin - (maxs[x] - nmax_x) * c; | |
431 | - nmax = nmax + (nmin_x - mins[x]) * c; | |
432 | - } | |
438 | + _fd_revise_connected(this, VAR(this, this->nvariables - 1)); | |
433 | 439 | |
434 | - if (nmin > ub || nmax < lb) | |
435 | - return FD_NOSOLUTION; | |
440 | + nlb = nmin; | |
441 | + } | |
436 | 442 | |
437 | - mins[x] = nmin_x; | |
438 | - maxs[x] = nmax_x; | |
443 | + if (nmax < nub && _fd_var_del_gt(nmax, VAR(this, this->nvariables - 1))) | |
444 | + { | |
445 | + if (fd_domain_empty(VAR(this, this->nvariables - 1))) | |
446 | + return FD_NOSOLUTION; | |
439 | 447 | |
440 | - while (++x < terms && culprit != VAR(this, x)) | |
441 | - ; | |
442 | - } | |
443 | - while (x < terms); | |
448 | + _fd_revise_connected(this, VAR(this, this->nvariables - 1)); | |
444 | 449 | |
445 | - if ((nmin > lb && _fd_var_del_lt(nmin, VAR(this, this->nvariables - 1))) | | |
446 | - (nmax < ub && _fd_var_del_gt(nmax, VAR(this, this->nvariables - 1)))) | |
447 | - { | |
448 | - if (fd_domain_empty(VAR(this, this->nvariables - 1))) | |
449 | - return FD_NOSOLUTION; | |
450 | + nub = nmax; | |
451 | + } | |
452 | + } while (nmin != nmax && (nmin != onmin || nmax != onmax)); | |
450 | 453 | |
451 | - _fd_revise_connected(this, VAR(this, this->nvariables - 1)); | |
454 | + if (nmin == nmax) | |
455 | + fd__constraint_set_entailed(this); | |
452 | 456 | } |
453 | 457 | |
458 | + *(base + 0) = nlb; | |
459 | + *(base + 1) = nub; | |
454 | 460 | *(base + 2) = nmin; |
455 | 461 | *(base + 3) = nmax; |
456 | 462 | |
... | ... | @@ -462,8 +468,15 @@ static int fd_poly_eq_propagate2(fd_constraint this, fd_int culprit) |
462 | 468 | |
463 | 469 | fd_constraint fd_poly_eq(int cs[], fd_int xs[], int nterms, fd_int y) |
464 | 470 | { |
465 | - fd_constraint c = _fd_constraint_new(nterms + 1, nterms); | |
466 | - int i; | |
471 | + fd_constraint fd_poly_eq_k(int[], fd_int[], int, int); | |
472 | + fd_constraint c; | |
473 | + int i, k; | |
474 | + | |
475 | + // specialise when y is a singleton | |
476 | + if (fd_var_single(y, &k)) | |
477 | + return fd_poly_eq_k(cs, xs, nterms, k); | |
478 | + | |
479 | + c = fd__constraint_new(nterms + 1, nterms); | |
467 | 480 | |
468 | 481 | if (c) |
469 | 482 | { |
... | ... | @@ -472,11 +485,8 @@ fd_constraint fd_poly_eq(int cs[], fd_int xs[], int nterms, fd_int y) |
472 | 485 | c->variables[nterms] = FD_INT2C_VAR(y); |
473 | 486 | for (i = 0; i < nterms; ++i) |
474 | 487 | c->constants[i] = cs[i]; |
475 | -#ifdef CONSTRAINT_CLASS | |
488 | + | |
476 | 489 | c->kind = FD_CONSTR_POLY_EQ; |
477 | -#else /* CONSTRAINT_CLASS */ | |
478 | - c->propagator2 = fd_poly_eq_propagate2; | |
479 | -#endif /* CONSTRAINT_CLASS */ | |
480 | 490 | |
481 | 491 | for (i = 0; i < c->nvariables; ++i) |
482 | 492 | _fd_var_add_constraint(VAR(c, i), c); |
... | ... |
... | ... | @@ -0,0 +1,346 @@ |
1 | +/* poly-le-k(C, X, k) == sum(C . X) <= k */ | |
2 | + | |
3 | +static int fd_poly_le_k_filter(fd_constraint this) | |
4 | +{ | |
5 | + int k; | |
6 | + int min, max; | |
7 | + int terms = this->nvariables; | |
8 | + int *mins, *maxs; | |
9 | + int i; | |
10 | +#ifdef CONSTRAINT_TEMPS | |
11 | + int *base; | |
12 | + | |
13 | + assert(!fd__constraint_data_valid(this)); | |
14 | + | |
15 | + if (!constraint_memory[this->index]) | |
16 | + constraint_memory[this->index] = malloc((2 * terms + 2) * sizeof(int)); | |
17 | + | |
18 | + base = constraint_memory[this->index]; | |
19 | + | |
20 | + mins = base + 2; | |
21 | + maxs = mins + terms; | |
22 | +#else | |
23 | + mins = alloca(terms * sizeof(*mins)); | |
24 | + maxs = alloca(terms * sizeof(*maxs)); | |
25 | +#endif | |
26 | + | |
27 | + k = this->constants[terms]; | |
28 | + | |
29 | + // sum the minima and the maxima of the terms | |
30 | + min = max = 0; | |
31 | + | |
32 | + for (i = 0; i < terms; ++i) | |
33 | + { | |
34 | + int vl, vh; | |
35 | + | |
36 | + if (this->constants[i] > 0) | |
37 | + { | |
38 | + vl = mins[i] = _fd_var_min(VAR(this, i)); | |
39 | + vh = maxs[i] = _fd_var_max(VAR(this, i)); | |
40 | + } | |
41 | + else | |
42 | + { | |
43 | + vl = maxs[i] = _fd_var_max(VAR(this, i)); | |
44 | + vh = mins[i] = _fd_var_min(VAR(this, i)); | |
45 | + } | |
46 | + | |
47 | + min += this->constants[i] * vl; | |
48 | + max += this->constants[i] * vh; | |
49 | + } | |
50 | + | |
51 | + if (min > k) | |
52 | + return FD_NOSOLUTION; | |
53 | + | |
54 | + if (max <= k) | |
55 | + { | |
56 | + fd__constraint_set_entailed(this); | |
57 | + } | |
58 | + else if (min == k) | |
59 | + { | |
60 | + for (i = 0; i < terms; ++i) | |
61 | + { | |
62 | + int c = this->constants[i]; | |
63 | + | |
64 | + if (c == 0 || mins[i] == maxs[i]) continue; | |
65 | + | |
66 | + if (c > 0) | |
67 | + { | |
68 | + _fd_var_del_gt(mins[i], VAR(this, i)); | |
69 | + | |
70 | + // check needed for when variables occur more than once | |
71 | + // and with opposite signs | |
72 | + if (fd_domain_empty(VAR(this, i))) | |
73 | + return FD_NOSOLUTION; | |
74 | + | |
75 | + _fd_revise_connected(this, VAR(this, i)); | |
76 | + | |
77 | + maxs[i] = mins[i]; | |
78 | + } | |
79 | + else | |
80 | + { | |
81 | + _fd_var_del_lt(maxs[i], VAR(this, i)); | |
82 | + | |
83 | + // check needed for when variables occur more than once | |
84 | + // and with opposite signs | |
85 | + if (fd_domain_empty(VAR(this, i))) | |
86 | + return FD_NOSOLUTION; | |
87 | + | |
88 | + _fd_revise_connected(this, VAR(this, i)); | |
89 | + | |
90 | + mins[i] = maxs[i]; | |
91 | + } | |
92 | + } | |
93 | + | |
94 | + max = min; | |
95 | + | |
96 | + fd__constraint_set_entailed(this); | |
97 | + } | |
98 | + else // max > k | |
99 | + { | |
100 | + // bounds domain filtering | |
101 | + | |
102 | + for (i = 0; i < terms; ++i) | |
103 | + { | |
104 | + int c = this->constants[i]; | |
105 | + int imin = mins[i]; | |
106 | + int imax = maxs[i]; | |
107 | + | |
108 | + if (c > 0) | |
109 | + { | |
110 | + // enforce min(sum{j!=i}(c[j] * x[j])) + c[i] * max[i] <= k | |
111 | + | |
112 | + if (min + (imax - imin) * c > k) | |
113 | + { | |
114 | + // max[i] = floor((k - min) / c[i]) + min[i] | |
115 | + imax = (k - min) / c + imin; | |
116 | + | |
117 | + _fd_var_del_gt(imax, VAR(this, i)); | |
118 | + | |
119 | + if (fd_domain_empty(VAR(this, i))) | |
120 | + return FD_NOSOLUTION; | |
121 | + | |
122 | + _fd_revise_connected(this, VAR(this, i)); | |
123 | + | |
124 | + max -= (maxs[i] - imax) * c; | |
125 | + | |
126 | + maxs[i] = imax; | |
127 | + } | |
128 | + } | |
129 | + else // c < 0 (does nothing if c is 0) | |
130 | + { | |
131 | + // enforce min(sum{j!=i}(c[j] * x[j])) + c[i] * min[i] <= k | |
132 | + | |
133 | + if (min + (imin - imax) * c > k) | |
134 | + { | |
135 | + // min[i] = ceil((k - min) / c[i]) + max[i] | |
136 | + imin = (k - min) / c + imax; | |
137 | + | |
138 | + _fd_var_del_lt(imin, VAR(this, i)); | |
139 | + | |
140 | + if (fd_domain_empty(VAR(this, i))) | |
141 | + return FD_NOSOLUTION; | |
142 | + | |
143 | + _fd_revise_connected(this, VAR(this, i)); | |
144 | + | |
145 | + max -= (mins[i] - imin) * c; | |
146 | + | |
147 | + mins[i] = imin; | |
148 | + } | |
149 | + } | |
150 | + } | |
151 | + | |
152 | + if (max <= k) | |
153 | + fd__constraint_set_entailed(this); | |
154 | + } | |
155 | + | |
156 | +#ifdef CONSTRAINT_TEMPS | |
157 | + // save values | |
158 | + *base = min; | |
159 | + *(base + 1) = max; | |
160 | + | |
161 | + fd__constraint_remember(this); | |
162 | +#endif | |
163 | + | |
164 | + return FD_OK; | |
165 | +} | |
166 | + | |
167 | +static int fd_poly_le_k_propagate2(fd_constraint this, fd_int culprit) | |
168 | +{ | |
169 | +#ifdef CONSTRAINT_TEMPS | |
170 | + int k; | |
171 | + int min, max; | |
172 | + int terms = this->nvariables; | |
173 | + int *mins, *maxs; | |
174 | + int i; | |
175 | + int *base; | |
176 | + int x, c; | |
177 | + int nmin, nmin_x, nmax, nmax_x; | |
178 | + | |
179 | + if (!fd__constraint_data_valid(this)) | |
180 | + return fd_poly_le_k_filter(this); // ignores culprit | |
181 | + | |
182 | + // bounds filtering | |
183 | + | |
184 | + base = constraint_memory[this->index]; | |
185 | + | |
186 | + mins = base + 2; | |
187 | + maxs = mins + terms; | |
188 | + | |
189 | + min = *base; | |
190 | + max = *(base + 1); | |
191 | + | |
192 | + k = this->constants[terms]; | |
193 | + | |
194 | + // find the (first) term where the culprit appears | |
195 | + for (x = 0; culprit != VAR(this, x); ++x) | |
196 | + ; | |
197 | + | |
198 | + nmin_x = _fd_var_min(VAR(this, x)); | |
199 | + nmax_x = _fd_var_max(VAR(this, x)); | |
200 | + | |
201 | + if (nmin_x == mins[x] && nmax_x == maxs[x]) | |
202 | + return FD_OK; | |
203 | + | |
204 | + nmin = min; | |
205 | + nmax = max; | |
206 | + | |
207 | + do | |
208 | + { | |
209 | + c = this->constants[x]; | |
210 | + | |
211 | + if (c > 0) | |
212 | + { | |
213 | + nmin = nmin + (nmin_x - mins[x]) * c; | |
214 | + nmax = nmax - (maxs[x] - nmax_x) * c; | |
215 | + } | |
216 | + else if (c < 0) | |
217 | + { | |
218 | + nmin = nmin - (maxs[x] - nmax_x) * c; | |
219 | + nmax = nmax + (nmin_x - mins[x]) * c; | |
220 | + } | |
221 | + | |
222 | + if (nmin > k) | |
223 | + return FD_NOSOLUTION; | |
224 | + | |
225 | + mins[x] = nmin_x; | |
226 | + maxs[x] = nmax_x; | |
227 | + | |
228 | + // search for the next term where the culprit appears | |
229 | + while (++x < terms && culprit != VAR(this, x)) | |
230 | + ; | |
231 | + } | |
232 | + while (x < terms); | |
233 | + | |
234 | + if (nmin == min && nmax == max) | |
235 | + return FD_OK; | |
236 | + | |
237 | + if (nmax <= k) | |
238 | + { | |
239 | + fd__constraint_set_entailed(this); | |
240 | + } | |
241 | + else if (nmin == k) | |
242 | + { | |
243 | + for (i = 0; i < terms; ++i) | |
244 | + { | |
245 | + int c = this->constants[i]; | |
246 | + | |
247 | + if (c == 0 || mins[i] == maxs[i]) continue; | |
248 | + | |
249 | + if (c > 0) | |
250 | + { | |
251 | + fd_update_domain_and_check(del_gt, mins[i], VAR(this, i)); | |
252 | + | |
253 | + maxs[i] = mins[i]; | |
254 | + } | |
255 | + else | |
256 | + { | |
257 | + fd_update_domain_and_check(del_lt, maxs[i], VAR(this, i)); | |
258 | + | |
259 | + mins[i] = maxs[i]; | |
260 | + } | |
261 | + } | |
262 | + | |
263 | + nmax = nmin; | |
264 | + | |
265 | + fd__constraint_set_entailed(this); | |
266 | + } | |
267 | + else if (nmin > min) // nmax > k | |
268 | + { | |
269 | + // bounds domain propagation | |
270 | + | |
271 | + for (i = 0; i < terms; ++i) | |
272 | + { | |
273 | + int c = this->constants[i]; | |
274 | + int imin = mins[i]; | |
275 | + int imax = maxs[i]; | |
276 | + | |
277 | + if (c > 0) | |
278 | + { | |
279 | + // enforce min(sum{j!=i}(c[j] * x[j])) + c[i] * max[i] <= k | |
280 | + | |
281 | + if (nmin + (imax - imin) * c > k) | |
282 | + { | |
283 | + // max[i] = floor((k - nmin) / c[i]) + min[i] | |
284 | + imax = (k - nmin) / c + imin; | |
285 | + | |
286 | + fd_update_domain_and_check(del_gt, imax, VAR(this, i)); | |
287 | + | |
288 | + nmax -= (maxs[i] - imax) * c; | |
289 | + | |
290 | + maxs[i] = imax; | |
291 | + } | |
292 | + } | |
293 | + else // c < 0 (does nothing if c is 0) | |
294 | + { | |
295 | + // enforce min(sum{j!=i}(c[j] * x[j])) + c[i] * min[i] <= k | |
296 | + | |
297 | + if (nmin + (imin - imax) * c > k) | |
298 | + { | |
299 | + // min[i] = ceil((k - nmin) / c[i]) + max[i] | |
300 | + imin = (k - nmin) / c + imax; | |
301 | + | |
302 | + fd_update_domain_and_check(del_lt, imin, VAR(this, i)); | |
303 | + | |
304 | + nmax -= (mins[i] - imin) * c; | |
305 | + | |
306 | + mins[i] = imin; | |
307 | + } | |
308 | + } | |
309 | + } | |
310 | + | |
311 | + if (nmax <= k) | |
312 | + fd__constraint_set_entailed(this); | |
313 | + } | |
314 | + | |
315 | + *base = nmin; | |
316 | + *(base + 1) = nmax; | |
317 | + | |
318 | + return FD_OK; | |
319 | +#else /* CONSTRAINT_TEMPS */ | |
320 | + return fd_poly_le_k_filter(this); // ignores culprit | |
321 | +#endif /* CONSTRAINT_TEMPS */ | |
322 | +} | |
323 | + | |
324 | +fd_constraint fd_poly_le_k(int cs[], fd_int xs[], int nterms, int k) | |
325 | +{ | |
326 | + fd_constraint c = fd__constraint_new(nterms, nterms + 1); | |
327 | + int i; | |
328 | + | |
329 | + if (c) | |
330 | + { | |
331 | + for (i = 0; i < nterms; ++i) | |
332 | + c->variables[i] = FD_INT2C_VAR(xs[i]); | |
333 | + for (i = 0; i < nterms; ++i) | |
334 | + c->constants[i] = cs[i]; | |
335 | + c->constants[nterms] = k; | |
336 | + | |
337 | + c->kind = FD_CONSTR_POLY_LE_K; | |
338 | + | |
339 | + for (i = 0; i < c->nvariables; ++i) | |
340 | + _fd_var_add_constraint(VAR(c, i), c); | |
341 | + | |
342 | + _fd_add_constraint(c); | |
343 | + } | |
344 | + | |
345 | + return c; | |
346 | +} | |
... | ... |
src/constraints/poly-ne-k.c
... | ... | @@ -199,11 +199,13 @@ static int fd_poly_ne_k_propagate2(fd_constraint this, fd_int culprit) |
199 | 199 | if (this->constants[i] && mins[i] != maxs[i]) |
200 | 200 | break; |
201 | 201 | |
202 | + // m = sum{j != i} c[j] * x[j] | |
202 | 203 | if (this->constants[i] > 0) |
203 | - m = min - this->constants[i] * mins[i]; | |
204 | + m = nmin - this->constants[i] * mins[i]; | |
204 | 205 | else |
205 | - m = min - this->constants[i] * maxs[i]; | |
206 | + m = nmin - this->constants[i] * maxs[i]; | |
206 | 207 | |
208 | + // v * c[i] + m = k (if v were a real value) | |
207 | 209 | v = (k - m) / this->constants[i]; |
208 | 210 | |
209 | 211 | if (v * this->constants[i] + m == k) |
... | ... | @@ -224,7 +226,7 @@ static int fd_poly_ne_k_propagate2(fd_constraint this, fd_int culprit) |
224 | 226 | |
225 | 227 | fd_constraint fd_poly_ne_k(int cs[], fd_int xs[], int nterms, int k) |
226 | 228 | { |
227 | - fd_constraint c = _fd_constraint_new(nterms, nterms + 1); | |
229 | + fd_constraint c = fd__constraint_new(nterms, nterms + 1); | |
228 | 230 | int i; |
229 | 231 | |
230 | 232 | if (c) |
... | ... | @@ -234,11 +236,8 @@ fd_constraint fd_poly_ne_k(int cs[], fd_int xs[], int nterms, int k) |
234 | 236 | for (i = 0; i < nterms; ++i) |
235 | 237 | c->constants[i] = cs[i]; |
236 | 238 | c->constants[nterms] = k; |
237 | -#ifdef CONSTRAINT_CLASS | |
239 | + | |
238 | 240 | c->kind = FD_CONSTR_POLY_NE_K; |
239 | -#else /* CONSTRAINT_CLASS */ | |
240 | - c->propagator2 = fd_poly_ne_k_propagate2; | |
241 | -#endif /* CONSTRAINT_CLASS */ | |
242 | 241 | |
243 | 242 | for (i = 0; i < c->nvariables; ++i) |
244 | 243 | _fd_var_add_constraint(VAR(c, i), c); |
... | ... |
src/constraints/poly-ne.c
... | ... | @@ -237,11 +237,13 @@ static int fd_poly_ne_propagate2(fd_constraint this, fd_int culprit) |
237 | 237 | if (this->constants[i] && mins[i] != maxs[i]) |
238 | 238 | break; |
239 | 239 | |
240 | + // m = sum{j != i} c[j] * x[j] | |
240 | 241 | if (this->constants[i] > 0) |
241 | - m = min - this->constants[i] * mins[i]; | |
242 | + m = nmin - this->constants[i] * mins[i]; | |
242 | 243 | else |
243 | - m = min - this->constants[i] * maxs[i]; | |
244 | + m = nmin - this->constants[i] * maxs[i]; | |
244 | 245 | |
246 | + // v * c[i] + m = y (if v were a real value) | |
245 | 247 | v = (lb - m) / this->constants[i]; |
246 | 248 | |
247 | 249 | if (v * this->constants[i] + m == lb) |
... | ... | @@ -262,7 +264,7 @@ static int fd_poly_ne_propagate2(fd_constraint this, fd_int culprit) |
262 | 264 | |
263 | 265 | fd_constraint fd_poly_ne(int cs[], fd_int xs[], int nterms, fd_int y) |
264 | 266 | { |
265 | - fd_constraint c = _fd_constraint_new(nterms + 1, nterms); | |
267 | + fd_constraint c = fd__constraint_new(nterms + 1, nterms); | |
266 | 268 | int i; |
267 | 269 | |
268 | 270 | if (c) |
... | ... | @@ -272,11 +274,8 @@ fd_constraint fd_poly_ne(int cs[], fd_int xs[], int nterms, fd_int y) |
272 | 274 | c->variables[nterms] = FD_INT2C_VAR(y); |
273 | 275 | for (i = 0; i < nterms; ++i) |
274 | 276 | c->constants[i] = cs[i]; |
275 | -#ifdef CONSTRAINT_CLASS | |
277 | + | |
276 | 278 | c->kind = FD_CONSTR_POLY_NE; |
277 | -#else /* CONSTRAINT_CLASS */ | |
278 | - c->propagator2 = fd_poly_ne_propagate2; | |
279 | -#endif /* CONSTRAINT_CLASS */ | |
280 | 279 | |
281 | 280 | for (i = 0; i < c->nvariables; ++i) |
282 | 281 | _fd_var_add_constraint(VAR(c, i), c); |
... | ... |
src/constraints/sum-prod.c
... | ... | @@ -393,7 +393,7 @@ static int fd_sum_prod_propagate2(fd_constraint this, fd_int culprit) |
393 | 393 | |
394 | 394 | fd_constraint fd_sum_prod(fd_int *xs, fd_int *ys, int nvariables, int k) |
395 | 395 | { |
396 | - fd_constraint c = _fd_constraint_new(2 * nvariables, 1); | |
396 | + fd_constraint c = fd__constraint_new(2 * nvariables, 1); | |
397 | 397 | int i; |
398 | 398 | |
399 | 399 | if (c) |
... | ... | @@ -403,11 +403,8 @@ fd_constraint fd_sum_prod(fd_int *xs, fd_int *ys, int nvariables, int k) |
403 | 403 | for (; i < 2 * nvariables; ++i) |
404 | 404 | c->variables[i] = FD_INT2C_VAR(ys[i - nvariables]); |
405 | 405 | c->constants[0] = k; |
406 | -#ifdef CONSTRAINT_CLASS | |
406 | + | |
407 | 407 | c->kind = FD_CONSTR_SUM_PROD; |
408 | -#else /* CONSTRAINT_CLASS */ | |
409 | - c->propagator2 = fd_sum_prod_propagate2; | |
410 | -#endif /* CONSTRAINT_CLASS */ | |
411 | 408 | |
412 | 409 | for (i = 0; i < 2 * nvariables; ++i) |
413 | 410 | _fd_var_add_constraint(VAR(c, i), c); |
... | ... |
src/constraints/sum.c
... | ... | @@ -177,7 +177,7 @@ static int fd_sum_propagate2(fd_constraint this, fd_int culprit) |
177 | 177 | |
178 | 178 | fd_constraint fd_sum(fd_int *variables, int nvariables, int k) |
179 | 179 | { |
180 | - fd_constraint c = _fd_constraint_new(nvariables, 1); | |
180 | + fd_constraint c = fd__constraint_new(nvariables, 1); | |
181 | 181 | int i; |
182 | 182 | |
183 | 183 | if (c) |
... | ... | @@ -185,11 +185,8 @@ fd_constraint fd_sum(fd_int *variables, int nvariables, int k) |
185 | 185 | for (i = 0; i < nvariables; ++i) |
186 | 186 | c->variables[i] = FD_INT2C_VAR(variables[i]); |
187 | 187 | c->constants[0] = k; |
188 | -#ifdef CONSTRAINT_CLASS | |
188 | + | |
189 | 189 | c->kind = FD_CONSTR_SUM; |
190 | -#else /* CONSTRAINT_CLASS */ | |
191 | - c->propagator2 = fd_sum_propagate2; | |
192 | -#endif /* CONSTRAINT_CLASS */ | |
193 | 190 | |
194 | 191 | for (i = 0; i < nvariables; ++i) |
195 | 192 | _fd_var_add_constraint(VAR(c, i), c); |
... | ... |
src/constraints/sum2.c
... | ... | @@ -94,7 +94,7 @@ static int fd_sum2_propagate2(fd_constraint this, fd_int culprit) |
94 | 94 | |
95 | 95 | fd_constraint fd_sum2(fd_int *variables, int nvariables, fd_int x) |
96 | 96 | { |
97 | - fd_constraint c = _fd_constraint_new(nvariables + 1, 0); | |
97 | + fd_constraint c = fd__constraint_new(nvariables + 1, 0); | |
98 | 98 | int i; |
99 | 99 | |
100 | 100 | if (c) |
... | ... | @@ -102,11 +102,8 @@ fd_constraint fd_sum2(fd_int *variables, int nvariables, fd_int x) |
102 | 102 | for (i = 0; i < nvariables; ++i) |
103 | 103 | c->variables[i] = FD_INT2C_VAR(variables[i]); |
104 | 104 | c->variables[nvariables] = FD_INT2C_VAR(x); |
105 | -#ifdef CONSTRAINT_CLASS | |
105 | + | |
106 | 106 | c->kind = FD_CONSTR_SUM2; |
107 | -#else /* CONSTRAINT_CLASS */ | |
108 | - c->propagator2 = fd_sum2_propagate2; | |
109 | -#endif /* CONSTRAINT_CLASS */ | |
110 | 107 | |
111 | 108 | for (i = 0; i < nvariables + 1; ++i) |
112 | 109 | _fd_var_add_constraint(VAR(c, i), c); |
... | ... |
src/constraints/var-eq-minus.c
1 | -/* X = Y - Z */ | |
1 | +/* x = y - z */ | |
2 | 2 | |
3 | 3 | static int fd_var_eq_minus_filter(fd_constraint this) |
4 | 4 | { |
... | ... | @@ -10,7 +10,7 @@ static int fd_var_eq_minus_filter(fd_constraint this) |
10 | 10 | y = VAR(this, 1); |
11 | 11 | z = VAR(this, 2); |
12 | 12 | |
13 | - // XXX: just do bounds consistency, for now | |
13 | + // bounds consistency | |
14 | 14 | |
15 | 15 | xmin = _fd_var_min(x); |
16 | 16 | xmax = _fd_var_max(x); |
... | ... | @@ -28,6 +28,15 @@ static int fd_var_eq_minus_filter(fd_constraint this) |
28 | 28 | _fd_revise_connected(NULL, y); |
29 | 29 | } |
30 | 30 | |
31 | +#ifndef DISABLE_ENTAILED | |
32 | + if ((xmin == xmax) + (zmin == zmax) == 2) | |
33 | + { | |
34 | + fd__constraint_set_entailed(this); | |
35 | + | |
36 | + return FD_OK; | |
37 | + } | |
38 | +#endif | |
39 | + | |
31 | 40 | ymin = _fd_var_min(y); |
32 | 41 | ymax = _fd_var_max(y); |
33 | 42 | |
... | ... | @@ -54,98 +63,129 @@ static int fd_var_eq_minus_filter(fd_constraint this) |
54 | 63 | _fd_revise_connected(NULL, x); |
55 | 64 | } |
56 | 65 | |
57 | -#if CONSTRAINT_TEMPS > 3 | |
58 | - if (fd_var_single(x, 0) && fd_var_single(y, 0) && fd_var_single(z, 0)) | |
66 | +#ifndef DISABLE_ENTAILED | |
67 | + if ((ymin == ymax) + (zmin == zmax) == 2) | |
59 | 68 | fd__constraint_set_entailed(this); |
60 | 69 | #endif |
61 | 70 | |
62 | 71 | return FD_OK; |
63 | 72 | } |
64 | 73 | |
65 | -int fd_var_eq_minus_propagate2(fd_constraint this, fd_int culprit) | |
74 | +static int fd_var_eq_minus_propagate2(fd_constraint this, fd_int culprit) | |
66 | 75 | { |
67 | 76 | fd_int x, y, z; |
77 | + int xmin, xmax, ymin, ymax, zmin, zmax; | |
68 | 78 | int changed_x = 0, changed_y = 0, changed_z = 0; |
69 | 79 | |
70 | 80 | x = VAR(this, 0); |
71 | 81 | y = VAR(this, 1); |
72 | 82 | z = VAR(this, 2); |
73 | 83 | |
74 | - // XXX: just do bounds consistency, for now | |
84 | + // bounds consistency | |
75 | 85 | |
76 | 86 | if (culprit == x) |
77 | 87 | { |
78 | - changed_y = | |
79 | - _fd_var_del_lt(_fd_var_min(x) + _fd_var_min(z), y); | |
80 | - changed_y |= | |
81 | - _fd_var_del_gt(_fd_var_max(x) + _fd_var_max(z), y); | |
88 | + xmin = _fd_var_min(x); | |
89 | + xmax = _fd_var_max(x); | |
82 | 90 | |
83 | - if (changed_y && fd_domain_empty(y)) | |
84 | - return FD_NOSOLUTION; | |
91 | + changed_y = _fd_var_del_lt(xmin + _fd_var_min(z), y) | | |
92 | + _fd_var_del_gt(xmax + _fd_var_max(z), y); | |
93 | + | |
94 | + if (changed_y) | |
95 | + { | |
96 | + if (fd_domain_empty(y)) | |
97 | + return FD_NOSOLUTION; | |
98 | + | |
99 | + _fd_revise_connected(NULL, y); // XXX: NULL or this? | |
100 | + } | |
101 | + | |
102 | + ymin = _fd_var_min(y); | |
103 | + ymax = _fd_var_max(y); | |
85 | 104 | |
86 | 105 | changed_z = |
87 | - _fd_var_del_lt(_fd_var_min(y) - _fd_var_max(x), z); | |
88 | - changed_z |= | |
89 | - _fd_var_del_gt(_fd_var_max(y) - _fd_var_min(x), z); | |
106 | + _fd_var_del_lt(ymin - xmax, z) | _fd_var_del_gt(ymax - xmin, z); | |
90 | 107 | |
91 | - if (changed_z && fd_domain_empty(z)) | |
92 | - return FD_NOSOLUTION; | |
108 | + if (changed_z) | |
109 | + { | |
110 | + if (fd_domain_empty(z)) | |
111 | + return FD_NOSOLUTION; | |
112 | + | |
113 | + _fd_revise_connected(NULL, z); // XXX: NULL or this? | |
114 | + } | |
93 | 115 | } |
94 | 116 | else if (culprit == y) |
95 | 117 | { |
96 | - changed_x = | |
97 | - _fd_var_del_lt(_fd_var_min(y) - _fd_var_max(z), x); | |
98 | - changed_x |= | |
99 | - _fd_var_del_gt(_fd_var_max(y) - _fd_var_min(z), x); | |
118 | + ymin = _fd_var_min(y); | |
119 | + ymax = _fd_var_max(y); | |
100 | 120 | |
101 | - if (changed_x && fd_domain_empty(x)) | |
102 | - return FD_NOSOLUTION; | |
121 | + changed_x = _fd_var_del_lt(ymin - _fd_var_max(z), x) | | |
122 | + _fd_var_del_gt(ymax - _fd_var_min(z), x); | |
123 | + | |
124 | + if (changed_x) | |
125 | + { | |
126 | + if (fd_domain_empty(x)) | |
127 | + return FD_NOSOLUTION; | |
128 | + | |
129 | + _fd_revise_connected(NULL, x); // XXX: NULL or this? | |
130 | + } | |
131 | + | |
132 | + xmin = _fd_var_min(x); | |
133 | + xmax = _fd_var_max(x); | |
103 | 134 | |
104 | 135 | changed_z = |
105 | - _fd_var_del_lt(_fd_var_min(y) - _fd_var_max(x), z); | |
106 | - changed_z |= | |
107 | - _fd_var_del_gt(_fd_var_max(y) - _fd_var_min(x), z); | |
136 | + _fd_var_del_lt(ymin - xmax, z) | _fd_var_del_gt(ymax - xmin, z); | |
108 | 137 | |
109 | - if (changed_z && fd_domain_empty(z)) | |
110 | - return FD_NOSOLUTION; | |
138 | + if (changed_z) | |
139 | + { | |
140 | + if (fd_domain_empty(z)) | |
141 | + return FD_NOSOLUTION; | |
142 | + | |
143 | + _fd_revise_connected(NULL, z); // XXX: NULL or this? | |
144 | + } | |
111 | 145 | } |
112 | 146 | else // culprit == z |
113 | 147 | { |
114 | - changed_x = | |
115 | - _fd_var_del_lt(_fd_var_min(y) - _fd_var_max(z), x); | |
116 | - changed_x |= | |
117 | - _fd_var_del_gt(_fd_var_max(y) - _fd_var_min(z), x); | |
148 | + zmin = _fd_var_min(z); | |
149 | + zmax = _fd_var_max(z); | |
118 | 150 | |
119 | - if (changed_x && fd_domain_empty(x)) | |
120 | - return FD_NOSOLUTION; | |
151 | + changed_x = _fd_var_del_lt(_fd_var_min(y) - zmax, x) | | |
152 | + _fd_var_del_gt(_fd_var_max(y) - zmin, x); | |
121 | 153 | |
122 | - changed_y = | |
123 | - _fd_var_del_lt(_fd_var_min(x) + _fd_var_min(z), y); | |
124 | - changed_y |= | |
125 | - _fd_var_del_gt(_fd_var_max(x) + _fd_var_max(z), y); | |
154 | + if (changed_x) | |
155 | + { | |
156 | + if (fd_domain_empty(x)) | |
157 | + return FD_NOSOLUTION; | |
126 | 158 | |
127 | - if (changed_y && fd_domain_empty(y)) | |
128 | - return FD_NOSOLUTION; | |
129 | - } | |
159 | + _fd_revise_connected(NULL, x); // XXX: NULL or this? | |
160 | + } | |
130 | 161 | |
131 | - if (changed_x) | |
132 | - _fd_revise_connected(NULL, x); // XXX: NULL or this? | |
162 | + xmin = _fd_var_min(x); | |
163 | + xmax = _fd_var_max(x); | |
133 | 164 | |
134 | - if (changed_y) | |
135 | - _fd_revise_connected(NULL, y); // XXX: NULL or this? | |
165 | + changed_y = | |
166 | + _fd_var_del_lt(xmin + zmin, y) | _fd_var_del_gt(xmax + zmax, y); | |
136 | 167 | |
137 | - if (changed_z) | |
138 | - _fd_revise_connected(NULL, z); // XXX: NULL or this? | |
168 | + if (changed_y) | |
169 | + { | |
170 | + if (fd_domain_empty(y)) | |
171 | + return FD_NOSOLUTION; | |
139 | 172 | |
140 | -#if CONSTRAINT_TEMPS > 3 | |
141 | - if (fd_var_single(x, 0) && fd_var_single(y, 0) && fd_var_single(z, 0)) | |
173 | + _fd_revise_connected(NULL, y); // XXX: NULL or this? | |
174 | + } | |
175 | + | |
176 | + ymin = zmin + xmin; | |
177 | + ymax = zmax + xmax; | |
178 | + } | |
179 | + | |
180 | +#ifndef DISABLE_ENTAILED | |
181 | + if ((xmin == xmax) + (ymin == ymax) == 2) | |
142 | 182 | fd__constraint_set_entailed(this); |
143 | 183 | #endif |
144 | 184 | |
145 | 185 | return FD_OK; |
146 | 186 | } |
147 | 187 | |
148 | -int fd_var_eq_minus_propagate(fd_constraint this, fd_int revise) | |
188 | +static int fd_var_eq_minus_propagate(fd_constraint this, fd_int revise) | |
149 | 189 | { |
150 | 190 | fd_int x, y, z; |
151 | 191 | int changed; |
... | ... | @@ -190,19 +230,15 @@ int fd_var_eq_minus_propagate(fd_constraint this, fd_int revise) |
190 | 230 | |
191 | 231 | fd_constraint fd_var_eq_minus(fd_int x, fd_int y, fd_int z) |
192 | 232 | { |
193 | - fd_constraint c = _fd_constraint_new(3, 0); | |
233 | + fd_constraint c = fd__constraint_new(3, 0); | |
194 | 234 | |
195 | 235 | if (c) |
196 | 236 | { |
197 | 237 | c->variables[0] = FD_INT2C_VAR(x); |
198 | 238 | c->variables[1] = FD_INT2C_VAR(y); |
199 | 239 | c->variables[2] = FD_INT2C_VAR(z); |
200 | -#ifdef CONSTRAINT_CLASS | |
240 | + | |
201 | 241 | c->kind = FD_CONSTR_VAR_EQ_MINUS; |
202 | -#else /* CONSTRAINT_CLASS */ | |
203 | - c->propagator2 = fd_var_eq_minus_propagate2; | |
204 | - c->propagator = fd_var_eq_minus_propagate; | |
205 | -#endif /* CONSTRAINT_CLASS */ | |
206 | 242 | |
207 | 243 | _fd_var_add_constraint(x, c); |
208 | 244 | _fd_var_add_constraint(y, c); |
... | ... |
src/constraints/var-eq-times.c
... | ... | @@ -177,18 +177,15 @@ int fd_var_eq_times_propagate2(fd_constraint this, fd_int culprit) |
177 | 177 | |
178 | 178 | fd_constraint fd_var_eq_times(fd_int x, fd_int y, fd_int z) |
179 | 179 | { |
180 | - fd_constraint c = _fd_constraint_new(3, 0); | |
180 | + fd_constraint c = fd__constraint_new(3, 0); | |
181 | 181 | |
182 | 182 | if (c) |
183 | 183 | { |
184 | 184 | c->variables[0] = FD_INT2C_VAR(x); |
185 | 185 | c->variables[1] = FD_INT2C_VAR(y); |
186 | 186 | c->variables[2] = FD_INT2C_VAR(z); |
187 | -#ifdef CONSTRAINT_CLASS | |
187 | + | |
188 | 188 | c->kind = FD_CONSTR_VAR_EQ_TIMES; |
189 | -#else /* CONSTRAINT_CLASS */ | |
190 | - c->propagator2 = fd_var_eq_times_propagate2; | |
191 | -#endif /* CONSTRAINT_CLASS */ | |
192 | 189 | |
193 | 190 | _fd_var_add_constraint(x, c); |
194 | 191 | _fd_var_add_constraint(y, c); |
... | ... |
src/dsearch-sg.c
... | ... | @@ -15,6 +15,9 @@ |
15 | 15 | #include "variables.h" |
16 | 16 | #include "values.h" |
17 | 17 | #include "bound.h" |
18 | +#include "constraints.h" | |
19 | + | |
20 | +#include "util.h" | |
18 | 21 | |
19 | 22 | #if STEAL_WORK > 0 |
20 | 23 | #include <time.h> |
... | ... | @@ -52,9 +55,7 @@ void _fd_epoch_forward() |
52 | 55 | |
53 | 56 | void _fd_epoch_rewind() |
54 | 57 | { |
55 | -#ifdef CONSTRAINT_TEMPS | |
56 | 58 | fd__constraint_data_reset(); |
57 | -#endif | |
58 | 59 | } |
59 | 60 | |
60 | 61 | int _fd_dsearch(fd_int variables[], int agent_no) |
... | ... | @@ -69,20 +70,20 @@ int _fd_dsearch(fd_int variables[], int agent_no) |
69 | 70 | agent = agent_no; |
70 | 71 | |
71 | 72 | #if defined(NEW_ENTRANCE) && defined(DEBUG_SPLITGO) |
72 | - _fd_debug("[%d.%d] agents_searching = %d, agents_failed = %d\n", tid, agent, agents_searching, agents_failed); | |
73 | + fd__debug("[%d.%d] agents_searching = %d, agents_failed = %d\n", tid, agent, agents_searching, agents_failed); | |
73 | 74 | #endif |
74 | 75 | |
75 | 76 | _fd_init_local_depository(); |
76 | 77 | |
77 | 78 | #if DEBUG_SPLITGO > 1 |
78 | - _fd_output("[%d.%d] ", tid, agent); _fd_cprint2(variables); | |
79 | + fd__output("[%d.%d] ", tid, agent); _fd_cprint2(variables); | |
79 | 80 | #endif |
80 | 81 | |
81 | 82 | if (_fd_filter_domains() == FD_NOSOLUTION) |
82 | 83 | { |
83 | 84 | fd_int variable = NULL; |
84 | 85 | |
85 | - _fd_debug("[%d.%d] failed before beginning\n", tid, agent); | |
86 | + fd__trace("[%d.%d] failed before beginning\n", tid, agent); | |
86 | 87 | |
87 | 88 | #if STEAL_WORK > 0 |
88 | 89 | #ifdef NEW_ENTRANCE |
... | ... | @@ -106,20 +107,14 @@ int _fd_dsearch(fd_int variables[], int agent_no) |
106 | 107 | |
107 | 108 | do |
108 | 109 | { |
109 | -#ifndef INDEX_IN_POOL | |
110 | - if (!_fd_steal_store(store, agent_no, 7)) | |
111 | -#else | |
112 | 110 | if (!_fd_steal_store(store, &variable, agent_no, 7)) |
113 | -#endif | |
114 | 111 | { |
115 | - _fd_debug("[%d.%d] giving up\n", tid, agent); | |
112 | + fd__trace("[%d.%d] giving up\n", tid, agent); | |
116 | 113 | |
117 | 114 | return FD_NOSOLUTION; |
118 | 115 | } |
119 | 116 | |
120 | -#ifdef CONSTRAINT_TEMPS | |
121 | 117 | fd__constraint_data_reset(); // XXX: this doesn't belong here! |
122 | -#endif | |
123 | 118 | } |
124 | 119 | while (_fd_revise_wrt_variable(variable) == FD_NOSOLUTION); |
125 | 120 | #else /* STEAL_WORK > 0 */ |
... | ... | @@ -128,7 +123,7 @@ int _fd_dsearch(fd_int variables[], int agent_no) |
128 | 123 | } |
129 | 124 | |
130 | 125 | #if DEBUG_SPLITGO > 1 |
131 | - _fd_output("[%d.%d] ", tid, agent); _fd_cprint2(variables); | |
126 | + fd__output("[%d.%d] ", tid, agent); _fd_cprint2(variables); | |
132 | 127 | #endif |
133 | 128 | |
134 | 129 | #ifdef NEW_ENTRANCE |
... | ... | @@ -139,7 +134,7 @@ int _fd_dsearch(fd_int variables[], int agent_no) |
139 | 134 | pthread_spin_unlock(&entrance_lock); |
140 | 135 | #endif |
141 | 136 | |
142 | - _fd_debug("[%d.%d] about to start searching\n", tid, agent); | |
137 | + fd__trace("[%d.%d] about to start searching\n", tid, agent); | |
143 | 138 | |
144 | 139 | return _fd_dsearch_(variables); |
145 | 140 | } |
... | ... | @@ -170,7 +165,7 @@ static int _fd_dsearch_(fd_int _fd_variables[]) |
170 | 165 | instantiations++; |
171 | 166 | #ifdef DEBUG_PROGRESS |
172 | 167 | if (instantiations % 100000 == 0) |
173 | - _fd_debug("[%d.%d] still alive (%d stores)\n", tid, agent, | |
168 | + fd__debug("[%d.%d] still alive (%d stores)\n", tid, agent, | |
174 | 169 | next_split_index - base_split_index); |
175 | 170 | #endif |
176 | 171 | |
... | ... | @@ -202,7 +197,7 @@ static int _fd_dsearch_(fd_int _fd_variables[]) |
202 | 197 | { |
203 | 198 | if (!_fd_counting_solutions) |
204 | 199 | { |
205 | - _fd_debug("[%d.%d] performed %d instantiations and %d backtracks\n", | |
200 | + fd__trace("[%d.%d] performed %d instantiations and %d backtracks\n", | |
206 | 201 | tid, agent, instantiations, backtrack); |
207 | 202 | |
208 | 203 | _fd_statistics_pool(); |
... | ... | @@ -229,10 +224,10 @@ static int _fd_dsearch_(fd_int _fd_variables[]) |
229 | 224 | |
230 | 225 | if (!_fd_counting_solutions) |
231 | 226 | { |
232 | - _fd_debug("[%d.%d] performed %d instantiations and %d backtracks\n", tid, | |
227 | + fd__trace("[%d.%d] performed %d instantiations and %d backtracks\n", tid, | |
233 | 228 | agent, instantiations, backtrack); |
234 | 229 | |
235 | - _fd_debug("[%d.%d] %d stores in store\n", tid, agent, next_split_index - base_split_index); | |
230 | + fd__trace("[%d.%d] %d stores in store\n", tid, agent, next_split_index - base_split_index); | |
236 | 231 | |
237 | 232 | _fd_statistics_pool(); |
238 | 233 | } |
... | ... |
src/fdc_int.h
... | ... | @@ -152,33 +152,15 @@ struct fd_value { |
152 | 152 | #define FD_INT2C_VAR(v) ((v)->index) |
153 | 153 | |
154 | 154 | struct fd_constraint { |
155 | -#ifdef CONSTRAINT_TEMPS | |
155 | +#if defined(CONSTRAINT_TEMPS) || !defined(DISABLE_ENTAILED) | |
156 | 156 | int index; |
157 | 157 | #endif |
158 | 158 | C_VAR_T *variables; // variables involved in the constraint |
159 | 159 | int nvariables; // number of variables |
160 | 160 | int *constants; // constraint's constants (where applicable) |
161 | 161 | int nconstants; // number of constants |
162 | -#ifdef CONSTRAINT_CLASS | |
163 | 162 | // _fd_constraint_kind kind; // what kind of constraint is this? |
164 | 163 | int kind; // what kind of constraint is this? // XXX |
165 | -#else /* CONSTRAINT_CLASS */ | |
166 | - int (*propagator2)(fd_constraint, fd_int); | |
167 | - // how to propagate changes in a variable's | |
168 | - // domain; 2nd argument is the variable | |
169 | - // against which to revise the domains of | |
170 | - // the other variables in the constraint; | |
171 | - // returns 1 if some domain becomes empty | |
172 | - int (*filter)(fd_constraint); | |
173 | - // performs an initial filtering of the | |
174 | - // domains of the constraint variables | |
175 | - int (*propagator)(fd_constraint, fd_int); | |
176 | - // how to propagate changes in a variable's | |
177 | - // domain; 2nd argument is the variable to | |
178 | - // revise (against the domains of every | |
179 | - // other variable in the constraint); | |
180 | - // returns 1 if some domain became empty | |
181 | -#endif /* CONSTRAINT_CLASS */ | |
182 | 164 | }; |
183 | 165 | |
184 | 166 | #define fd_cvariable(c,v) ((c)->variables[v]) // XXX: not being used |
... | ... | @@ -197,6 +179,7 @@ extern int fd_variables_count; |
197 | 179 | extern __thread fd_int _fd_variables[]; |
198 | 180 | |
199 | 181 | fd_int fd_new(int, int); |
182 | +fd_int fd_const(int); | |
200 | 183 | |
201 | 184 | // type for the variable's constraints |
202 | 185 | #define VAR_C_T int |
... | ... | @@ -266,6 +249,8 @@ typedef enum { |
266 | 249 | |
267 | 250 | #endif /* DISTRIBUTED_SOLVER */ |
268 | 251 | |
269 | -#ifdef FAST | |
270 | -# define _fd_debug(...) ((void) 0) | |
271 | -#endif /* FAST */ | |
252 | +#ifdef TRACE | |
253 | +# define fd__trace fd__debug | |
254 | +#else | |
255 | +# define fd__trace(...) ((void) 0) | |
256 | +#endif | |
... | ... |
src/matching.c
... | ... | @@ -9,6 +9,10 @@ |
9 | 9 | #include "values.h" |
10 | 10 | #include "matching.h" |
11 | 11 | |
12 | +#ifdef DEBUG_MATCH | |
13 | +# include "util.h" | |
14 | +#endif | |
15 | + | |
12 | 16 | #define UNSEEN (-2) // value not seen in any domain |
13 | 17 | |
14 | 18 | #define WHITE (-1) |
... | ... | @@ -297,7 +301,7 @@ static void _fd_mark_cycles(fd_constraint c, int8_t *vgraph, int r_verts, |
297 | 301 | |
298 | 302 | if (vgraph[var * r_verts + val] == 1) |
299 | 303 | { |
300 | -// _fd_debug("marking %d in %d's domain\n", val + min, VAR(c, var)->index); | |
304 | +// fd__debug("marking %d in %d's domain\n", val + min, VAR(c, var)->index); | |
301 | 305 | |
302 | 306 | vgraph[var * r_verts + val] = 3; |
303 | 307 | } |
... | ... | @@ -604,7 +608,7 @@ static void _fd_remark_cycles(fd_constraint c, int culprit, int8_t *vgraph, |
604 | 608 | |
605 | 609 | if (vgraph[var * r_verts + val] == 1) |
606 | 610 | { |
607 | -// _fd_debug("marking %d in %d's domain\n", val + min, VAR(c, var)->index); | |
611 | +// fd__debug("marking %d in %d's domain\n", val + min, VAR(c, var)->index); | |
608 | 612 | |
609 | 613 | vgraph[var * r_verts + val] = 3; |
610 | 614 | } |
... | ... | @@ -620,7 +624,7 @@ static void _fd_remark_cycles(fd_constraint c, int culprit, int8_t *vgraph, |
620 | 624 | for (i = 0; i < nvariables; ++i) |
621 | 625 | if (l_scc[i] == r_scc[v] && vgraph[i * r_verts + v] == 1) |
622 | 626 | { |
623 | -// _fd_debug("marking %d in %d's domain\n", v + min, VAR(c, i)->index); | |
627 | +// fd__debug("marking %d in %d's domain\n", v + min, VAR(c, i)->index); | |
624 | 628 | |
625 | 629 | vgraph[i * r_verts + v] = 3; |
626 | 630 | } |
... | ... | @@ -694,7 +698,7 @@ static void _fd_mark_paths(fd_constraint c, int8_t *vgraph, int r_verts, |
694 | 698 | continue; |
695 | 699 | |
696 | 700 | #if DEBUG_MATCH > 1 |
697 | - _fd_debug("marking %d in %d's domain\n", | |
701 | + fd__debug("marking %d in %d's domain\n", | |
698 | 702 | queue[head] + min, VAR(c, v)->index); |
699 | 703 | #endif |
700 | 704 | // this edge is in an M-alternating path |
... | ... | @@ -772,7 +776,7 @@ int _fd_find_matching(fd_constraint c, int **memory) |
772 | 776 | if (*memory == NULL) |
773 | 777 | { |
774 | 778 | #ifdef DEBUG_MATCH |
775 | - _fd_debug("all-different memory size is %d\n", size); | |
779 | + fd__debug("all-different memory size is %d\n", size); | |
776 | 780 | #endif |
777 | 781 | |
778 | 782 | *memory = malloc(size); // XXX: NULL |
... | ... | @@ -784,7 +788,7 @@ int _fd_find_matching(fd_constraint c, int **memory) |
784 | 788 | { |
785 | 789 | // the allocated memory is not enough |
786 | 790 | #ifdef DEBUG_MATCH |
787 | - _fd_debug("all-different new memory size is %d\n", size); | |
791 | + fd__debug("all-different new memory size is %d\n", size); | |
788 | 792 | #endif |
789 | 793 | |
790 | 794 | *memory = realloc(*memory, size); // XXX: NULL |
... | ... | @@ -808,13 +812,13 @@ int _fd_find_matching(fd_constraint c, int **memory) |
808 | 812 | l_scc = r_edge + r_verts; |
809 | 813 | r_scc = l_scc + nvariables; |
810 | 814 | vgraph = (int8_t *) (r_scc + r_verts); |
811 | -#else | |
815 | +#else /* CONSTRAINT_TEMPS */ | |
812 | 816 | l_edge = alloca(nvariables * sizeof(*l_edge)); |
813 | 817 | r_edge = alloca(r_verts * sizeof(*r_edge)); |
814 | 818 | l_scc = alloca(nvariables * sizeof(*l_scc)); |
815 | 819 | r_scc = alloca(r_verts * sizeof(*r_scc)); |
816 | 820 | vgraph = alloca(nvariables * r_verts * sizeof(*vgraph)); |
817 | -#endif | |
821 | +#endif /* CONSTRAINT_TEMPS */ | |
818 | 822 | |
819 | 823 | l_parent = alloca(nvariables * sizeof(*l_parent)); |
820 | 824 | l_colour = alloca(nvariables * sizeof(*l_colour)); |
... | ... | @@ -967,7 +971,7 @@ int _fd_find_matching(fd_constraint c, int **memory) |
967 | 971 | if (vgraph[i * r_verts + v] == 1) |
968 | 972 | { |
969 | 973 | #ifdef DEBUG_MATCH |
970 | - _fd_debug("removing %d from %d's domain\n", v + min, | |
974 | + fd__debug("removing %d from %d's domain\n", v + min, | |
971 | 975 | VAR(c, i)->index); |
972 | 976 | #endif |
973 | 977 | changed |= _fd_var_del_val(v + min, VAR(c, i)); |
... | ... | @@ -1198,7 +1202,7 @@ int _fd_update_matching(fd_constraint c, fd_int culprit, int *memory) |
1198 | 1202 | if (vgraph[i * r_verts + v] == 1 && /* {XXX */ r_scc[v] == -1 /* XXX} */) |
1199 | 1203 | { |
1200 | 1204 | #ifdef DEBUG_MATCH |
1201 | - _fd_debug("removing %d from %d's domain\n", v + min, | |
1205 | + fd__debug("removing %d from %d's domain\n", v + min, | |
1202 | 1206 | VAR(c, i)->index); |
1203 | 1207 | #endif |
1204 | 1208 | changed |= _fd_var_del_val(v + min, VAR(c, i)); |
... | ... |
src/options.c
... | ... | @@ -117,7 +117,7 @@ static char *_fd_options = "@(#) $Options: " |
117 | 117 | #endif |
118 | 118 | |
119 | 119 | #ifdef CONSTRAINT_CLASS |
120 | - "CONSTRAINT_CLASS" " " | |
120 | +#warning "CONSTRAINT_CLASS committed (16JUN16)" | |
121 | 121 | #endif |
122 | 122 | #ifdef CONSTRAINT_TEMPS |
123 | 123 | "CONSTRAINT_TEMPS" " " |
... | ... | @@ -143,7 +143,7 @@ static char *_fd_options = "@(#) $Options: " |
143 | 143 | "GROWABLE_POOL" " " |
144 | 144 | #endif |
145 | 145 | #ifdef INDEX_IN_POOL |
146 | - "INDEX_IN_POOL" " " | |
146 | +#warning "INDEX_IN_POOL committed (24APR16)" | |
147 | 147 | #endif |
148 | 148 | #ifdef STORE_IN_POOL |
149 | 149 | "STORE_IN_POOL" " " |
... | ... |
src/paccs.h
... | ... | @@ -14,6 +14,7 @@ void fd_init(int *argc, char **argv[]); |
14 | 14 | void fd_end(void); |
15 | 15 | int fd_solve(void); |
16 | 16 | |
17 | +fd_int fd_const(int value); | |
17 | 18 | fd_int fd_new(int min, int max); |
18 | 19 | |
19 | 20 | void fd_label(fd_int vars[], int nvars); |
... | ... | @@ -40,6 +41,7 @@ fd_constraint fd_var_eq_times(fd_int x, fd_int y, fd_int z); |
40 | 41 | /* Global constraints */ |
41 | 42 | |
42 | 43 | fd_constraint fd_all_different(fd_int X[], int n); |
44 | +fd_constraint fd_fake_all_different(fd_int X[], int n); | |
43 | 45 | |
44 | 46 | fd_constraint fd_element(fd_int X[], int n, fd_int y, int k); |
45 | 47 | fd_constraint fd_element_var(fd_int X[], int n, fd_int y, fd_int z); |
... | ... | @@ -51,6 +53,7 @@ fd_constraint fd_sum_prod(fd_int X[], fd_int Y[], int n, int k); |
51 | 53 | |
52 | 54 | fd_constraint fd_poly_eq(int C[], fd_int Y[], int n, fd_int z); |
53 | 55 | fd_constraint fd_poly_eq_k(int C[], fd_int Y[], int n, int k); |
56 | +fd_constraint fd_poly_le_k(int C[], fd_int Y[], int n, int k); | |
54 | 57 | fd_constraint fd_poly_ne(int C[], fd_int Y[], int n, fd_int y); |
55 | 58 | fd_constraint fd_poly_ne_k(int C[], fd_int Y[], int n, int k); |
56 | 59 | fd_constraint fd_knapsack2(fd_int X[], fd_int Y[], int n, fd_int z); |
... | ... |
src/packed.c
... | ... | @@ -11,6 +11,8 @@ |
11 | 11 | #include "constraints.h" |
12 | 12 | #include "packed.h" |
13 | 13 | |
14 | +#include "util.h" | |
15 | + | |
14 | 16 | static struct _fd_packed_problem *packed_memory; // XXX: so it can be freed |
15 | 17 | #ifdef USE_MMAP |
16 | 18 | static size_t packed_memory_size; |
... | ... | @@ -42,7 +44,7 @@ static struct _fd_packed_problem *_fd_allocate_memory() |
42 | 44 | tconsts += _fd_constraints[i]->nconstants; |
43 | 45 | } |
44 | 46 | |
45 | - _fd_debug("packed size is %d + %d + %d + %d\n", | |
47 | + fd__trace("packed size is %d + %d + %d + %d\n", | |
46 | 48 | sizeof(*p), |
47 | 49 | p->nvariables * sizeof(*p->variables), |
48 | 50 | p->nconstraints * sizeof(*p->constraints), |
... | ... | @@ -86,7 +88,7 @@ static struct _fd_packed_problem *_fd_allocate_memory() |
86 | 88 | { |
87 | 89 | perror("mmap"); |
88 | 90 | |
89 | - _fd_fatal("mmap() failed"); | |
91 | + fd__fatal("mmap() failed"); | |
90 | 92 | } |
91 | 93 | |
92 | 94 | p = m; |
... | ... | @@ -141,10 +143,6 @@ void _fd_pack_problem() |
141 | 143 | int offset; |
142 | 144 | int i, j; |
143 | 145 | |
144 | -#ifndef CONSTRAINT_CLASS | |
145 | - _fd_fatal("packed problems require CONSTRAINT_CLASS"); | |
146 | -#endif | |
147 | - | |
148 | 146 | packed = _fd_allocate_memory(); |
149 | 147 | |
150 | 148 | assert(packed != NULL); // XXX |
... | ... |
src/packed.h
... | ... | @@ -36,7 +36,7 @@ struct _fd_packed_int { |
36 | 36 | |
37 | 37 | /* fields must correspond to an initial segment of fd_constraint */ |
38 | 38 | struct _fd_packed_constraint { |
39 | -#ifdef CONSTRAINT_TEMPS | |
39 | +#if defined(CONSTRAINT_TEMPS) || !defined(DISABLE_ENTAILED) | |
40 | 40 | int index; |
41 | 41 | #endif |
42 | 42 | C_VAR_T *variables; |
... | ... |
src/pool.c
... | ... | @@ -10,12 +10,9 @@ static __thread _fd_store alt_store; // the other side of the split |
10 | 10 | static _fd_store *split_stores_; |
11 | 11 | #define split_stores split_stores_[agent] |
12 | 12 | |
13 | -#ifndef INDEX_IN_POOL | |
14 | -static __thread fd_int *split_variable; | |
15 | -#else | |
16 | 13 | static int **split_variable_; |
17 | -static __thread int *split_variable; | |
18 | -#endif | |
14 | +static __thread int *split_variable; // (index of the) variable whose domain | |
15 | + // was split to obtain the store | |
19 | 16 | |
20 | 17 | #ifdef GROWABLE_POOL |
21 | 18 | // number of stores in the pool |
... | ... | @@ -100,9 +97,7 @@ void _fd_init_store_depository(int agents) |
100 | 97 | for (i = 0; i < agents; ++i) |
101 | 98 | split_indexes[i] = EMPTY_POOL; |
102 | 99 | |
103 | -#ifdef INDEX_IN_POOL | |
104 | 100 | split_variable_ = calloc(agents, sizeof(*split_variable_)); |
105 | -#endif | |
106 | 101 | |
107 | 102 | stores_mutexes = calloc(agents, sizeof(*stores_mutexes)); |
108 | 103 | for (i = 0; i < agents; ++i) |
... | ... | @@ -130,18 +125,15 @@ void _fd_init_store_depository(int agents) |
130 | 125 | |
131 | 126 | static void _fd_init_local_depository() |
132 | 127 | { |
133 | - if (split_stores) | |
128 | + if (split_stores) // see if it has already been initialised | |
134 | 129 | { |
135 | 130 | #ifdef STORE_IN_POOL |
136 | 131 | // copy the new store to the pool |
137 | 132 | store = split_stores; |
138 | 133 | memcpy(store, main_store, STORE_SIZE); |
139 | -#ifdef INDEX_IN_POOL | |
140 | - split_variable[next_split_index] = -1; | |
141 | -#else | |
142 | - split_variable[next_split_index] = NULL; | |
143 | -#endif | |
144 | - ++next_split_index; | |
134 | + | |
135 | + split_variable[next_split_index] = -1; // starting anew | |
136 | + next_split_index++; | |
145 | 137 | #endif /* STORE_IN_POOL */ |
146 | 138 | |
147 | 139 | return; |
... | ... | @@ -149,24 +141,24 @@ static void _fd_init_local_depository() |
149 | 141 | |
150 | 142 | #ifndef GROWABLE_POOL |
151 | 143 | #ifndef STORE_IN_POOL |
152 | - _fd_debug("[%d.%d] stores size %d + %d\n", tid, agent, | |
144 | + fd__trace("[%d.%d] stores size %d + %d\n", tid, agent, | |
153 | 145 | fd_variables_count * STORE_SIZE, |
154 | 146 | fd_variables_count * sizeof(*split_variable)); |
155 | 147 | if (posix_memalign((void **) &split_stores, sysconf(_SC_PAGESIZE), |
156 | 148 | fd_variables_count * STORE_SIZE + |
157 | 149 | fd_variables_count * sizeof(*split_variable))) |
158 | - _fd_fatal("unable to allocate pool memory"); | |
150 | + fd__fatal("unable to allocate pool memory"); | |
159 | 151 | |
160 | 152 | // XXX: alignment problems possible |
161 | 153 | split_variable = ((void *) split_stores) + fd_variables_count * STORE_SIZE; |
162 | 154 | #else |
163 | - _fd_debug("[%d.%d] stores size %d + %d\n", tid, agent, | |
155 | + fd__trace("[%d.%d] stores size %d + %d\n", tid, agent, | |
164 | 156 | (fd_variables_count + 1) * STORE_SIZE, |
165 | 157 | fd_variables_count * sizeof(*split_variable)); |
166 | 158 | if (posix_memalign((void **) &split_stores, sysconf(_SC_PAGESIZE), |
167 | 159 | (fd_variables_count + 1) * STORE_SIZE + |
168 | 160 | fd_variables_count * sizeof(*split_variable))) |
169 | - _fd_fatal("unable to allocate pool memory"); | |
161 | + fd__fatal("unable to allocate pool memory"); | |
170 | 162 | |
171 | 163 | // XXX: alignment problems possible |
172 | 164 | split_variable = ((void *) split_stores) + (fd_variables_count + 1) * STORE_SIZE; |
... | ... | @@ -180,21 +172,19 @@ static void _fd_init_local_depository() |
180 | 172 | fd__label_vars_count + 1 : POOL_DEFAULT_SIZE; |
181 | 173 | #endif |
182 | 174 | |
183 | - _fd_debug("[%d.%d] stores size %d + %d\n", tid, agent, pool_size * STORE_SIZE, | |
175 | + fd__trace("[%d.%d] stores size %d + %d\n", tid, agent, pool_size * STORE_SIZE, | |
184 | 176 | fd_variables_count * sizeof(*split_variable)); |
185 | - | |
177 | + | |
186 | 178 | if (posix_memalign((void **) &split_stores, sysconf(_SC_PAGESIZE), |
187 | 179 | pool_size * STORE_SIZE)) |
188 | - _fd_fatal("unable to allocate pool memory"); | |
180 | + fd__fatal("unable to allocate pool memory"); | |
189 | 181 | |
190 | 182 | if (posix_memalign((void **) &split_variable, sysconf(_SC_PAGESIZE), |
191 | 183 | fd_variables_count * sizeof(*split_variable))) |
192 | - _fd_fatal("unable to allocate pool variable memory"); | |
184 | + fd__fatal("unable to allocate pool variable memory"); | |
193 | 185 | #endif /* GROWABLE_POOL */ |
194 | 186 | |
195 | -#if defined(INDEX_IN_POOL) && !defined(split_variable) | |
196 | 187 | split_variable_[agent] = split_variable; |
197 | -#endif | |
198 | 188 | |
199 | 189 | local_split_indexes = calloc(POOL_INDEXES, sizeof(*local_split_indexes)); |
200 | 190 | split_indexes[agent] = local_split_indexes; |
... | ... | @@ -204,12 +194,8 @@ static void _fd_init_local_depository() |
204 | 194 | main_store = store; |
205 | 195 | store = split_stores; |
206 | 196 | memcpy(store, main_store, STORE_SIZE); |
207 | -#ifdef INDEX_IN_POOL | |
208 | 197 | split_variable[next_split_index] = -1; |
209 | -#else | |
210 | - split_variable[next_split_index] = NULL; | |
211 | -#endif | |
212 | - ++next_split_index; | |
198 | + next_split_index++; | |
213 | 199 | #endif /* STORE_IN_POOL */ |
214 | 200 | } |
215 | 201 | |
... | ... | @@ -225,11 +211,11 @@ static void _fd_grow_pool(void) |
225 | 211 | #else |
226 | 212 | nsize = (fd_variables_count + 1 < nsize) ? fd_variables_count + 1 : nsize; |
227 | 213 | #endif |
228 | - _fd_debug("[%d.%d] new pool size is %d\n", tid, agent, nsize * STORE_SIZE); | |
229 | - | |
214 | + fd__trace("[%d.%d] new pool size is %d\n", tid, agent, nsize * STORE_SIZE); | |
215 | + | |
230 | 216 | if (posix_memalign((void **) &npool, sysconf(_SC_PAGESIZE), |
231 | 217 | nsize * STORE_SIZE)) |
232 | - _fd_fatal("unable to allocate pool memory"); | |
218 | + fd__fatal("unable to allocate pool memory"); | |
233 | 219 | |
234 | 220 | memcpy(npool, split_stores, pool_size * STORE_SIZE); |
235 | 221 | |
... | ... | @@ -251,7 +237,7 @@ static void _fd_grow_pool(void) |
251 | 237 | } |
252 | 238 | #endif /* GROWABLE_POOL */ |
253 | 239 | |
254 | -/* | |
240 | +/* | |
255 | 241 | saving a store to the pool is done in two steps: |
256 | 242 | |
257 | 243 | 1. a copy of the store which is about to be split is saved (to have |
... | ... | @@ -280,30 +266,18 @@ static void _fd_start_saving_store(_fd_store *dst) |
280 | 266 | static void _fd_end_saving_store(fd_int variable) |
281 | 267 | { |
282 | 268 | #ifndef STORE_IN_POOL |
283 | -#ifndef INDEX_IN_POOL | |
284 | - split_variable[next_split_index] = variable; | |
285 | -#else | |
286 | 269 | split_variable[next_split_index] = variable->index; |
287 | -#endif | |
288 | 270 | #else /* STORE_IN_POOL */ |
289 | 271 | // here, the split also affects the store which is below the |
290 | 272 | // (about to be) current one |
291 | -#ifndef INDEX_IN_POOL | |
292 | - split_variable[next_split_index - 1] = variable; | |
293 | -#else | |
294 | 273 | split_variable[next_split_index - 1] = variable->index; |
295 | -#endif | |
296 | 274 | #endif /* STORE_IN_POOL */ |
297 | 275 | |
298 | - ++next_split_index; | |
276 | + next_split_index++; | |
299 | 277 | } |
300 | 278 | |
301 | 279 | // try to steal a store from another agent |
302 | -#ifndef INDEX_IN_POOL | |
303 | -bool _fd_steal_store(_fd_store store_, int agent, int retries) | |
304 | -#else | |
305 | 280 | bool _fd_steal_store(_fd_store store_, fd_int *variable, int agent, int retries) |
306 | -#endif | |
307 | 281 | { |
308 | 282 | #ifndef RANDOM_VICTIM |
309 | 283 | int v; // the victim |
... | ... | @@ -317,7 +291,7 @@ bool _fd_steal_store(_fd_store store_, fd_int *variable, int agent, int retries) |
317 | 291 | |
318 | 292 | #if defined(STORE_IN_POOL) && defined(DECREMENT_EARLY) |
319 | 293 | if (agent != -1) |
320 | - --next_split_index; | |
294 | + next_split_index--; | |
321 | 295 | #endif |
322 | 296 | |
323 | 297 | // only let one agent in at a time |
... | ... | @@ -381,7 +355,7 @@ bool _fd_steal_store(_fd_store store_, fd_int *variable, int agent, int retries) |
381 | 355 | v = candidate; |
382 | 356 | |
383 | 357 | if (retrying) |
384 | - _fd_debug("[%d.%d] %d tries left\n", tid, agent, retries); | |
358 | + fd__trace("[%d.%d] %d tries left\n", tid, agent, retries); | |
385 | 359 | |
386 | 360 | break; |
387 | 361 | } |
... | ... | @@ -392,10 +366,10 @@ bool _fd_steal_store(_fd_store store_, fd_int *variable, int agent, int retries) |
392 | 366 | |
393 | 367 | if (active == 0 || retries == 0) |
394 | 368 | { |
395 | - _fd_debug("[%d.%d] no agent can supply work\n", tid, agent); | |
369 | + fd__trace("[%d.%d] no agent can supply work\n", tid, agent); | |
396 | 370 | |
397 | 371 | if (retrying) |
398 | - _fd_debug("[%d.%d] %d tries left\n", tid, agent, retries); | |
372 | + fd__trace("[%d.%d] %d tries left\n", tid, agent, retries); | |
399 | 373 | |
400 | 374 | return false; |
401 | 375 | } |
... | ... | @@ -429,13 +403,13 @@ bool _fd_steal_store(_fd_store store_, fd_int *variable, int agent, int retries) |
429 | 403 | // lock access to victim's stores |
430 | 404 | pthread_mutex_lock(&stores_mutexes[v]); |
431 | 405 | #if DEBUG_STEALING > 1 |
432 | - _fd_debug("[%d.%d] locked %d stores' mutex\n", tid, agent, v); | |
406 | + fd__debug("[%d.%d] locked %d stores' mutex\n", tid, agent, v); | |
433 | 407 | #endif |
434 | 408 | |
435 | 409 | stores = split_indexes[v][1] - split_indexes[v][0]; |
436 | 410 | |
437 | 411 | #if DEBUG_STEALING > 1 |
438 | - _fd_debug("[%d.%d] %d stores left at %d\n", tid, agent, stores, v); | |
412 | + fd__debug("[%d.%d] %d stores left at %d\n", tid, agent, stores, v); | |
439 | 413 | #endif |
440 | 414 | |
441 | 415 | // don't steal the last few stores from an agent |
... | ... | @@ -445,7 +419,7 @@ bool _fd_steal_store(_fd_store store_, fd_int *variable, int agent, int retries) |
445 | 419 | pthread_mutex_unlock(&thieves_mutex); |
446 | 420 | |
447 | 421 | #ifdef DEBUG_STEALING |
448 | - _fd_debug("[%d.%d] not enough stores (%d) at %d\n", tid, agent, stores, v); | |
422 | + fd__debug("[%d.%d] not enough stores (%d) at %d\n", tid, agent, stores, v); | |
449 | 423 | #endif |
450 | 424 | |
451 | 425 | return false; |
... | ... | @@ -463,14 +437,12 @@ bool _fd_steal_store(_fd_store store_, fd_int *variable, int agent, int retries) |
463 | 437 | |
464 | 438 | memcpy(store_, &split_stores_[v][s * fd_variables_count], STORE_SIZE); |
465 | 439 | |
466 | -#ifdef INDEX_IN_POOL | |
467 | 440 | #ifndef STORE_IN_POOL |
468 | 441 | if (variable) |
469 | 442 | #else |
470 | 443 | if (variable && split_variable_[v][s] != -1) |
471 | 444 | #endif |
472 | 445 | *variable = _fd_variables[split_variable_[v][s]]; |
473 | -#endif | |
474 | 446 | |
475 | 447 | // this agent will likely become the one with the largest search space |
476 | 448 | // (if work is being stolen by the controller, most_work will be set |
... | ... | @@ -490,14 +462,10 @@ bool _fd_steal_store(_fd_store store_, fd_int *variable, int agent, int retries) |
490 | 462 | } |
491 | 463 | |
492 | 464 | #ifdef DEBUG_STEALING |
493 | -#ifdef INDEX_IN_POOL | |
494 | - _fd_debug("[%d.%d] stole work (%d/%d) from %d (var %d)\n", tid, agent, s, | |
465 | + fd__debug("[%d.%d] stole work (%d/%d) from %d (var %d)\n", tid, agent, s, | |
495 | 466 | stores, v, split_variable_[v][s]); |
496 | -#else | |
497 | - _fd_debug("[%d.%d] stole work (%d/%d) from %d\n", tid, agent, s, stores, v); | |
498 | -#endif | |
499 | 467 | #if DEBUG_STEALING > 2 |
500 | - _fd_output("[%d.%d] ", tid, agent); _fd_cprint3(store_); | |
468 | + fd__output("[%d.%d] ", tid, agent); _fd_cprint3(store_); | |
501 | 469 | #endif |
502 | 470 | #endif |
503 | 471 | |
... | ... | @@ -523,7 +491,7 @@ bool _fd_steal_store(_fd_store store_, fd_int *variable, int agent, int retries) |
523 | 491 | |
524 | 492 | #if defined(STORE_IN_POOL) && defined(DECREMENT_EARLY) |
525 | 493 | if (agent != -1) |
526 | - --next_split_index; | |
494 | + next_split_index--; | |
527 | 495 | #endif |
528 | 496 | |
529 | 497 | pthread_spin_lock(&starving_lock); |
... | ... | @@ -535,7 +503,7 @@ bool _fd_steal_store(_fd_store store_, fd_int *variable, int agent, int retries) |
535 | 503 | if (as == nagents) |
536 | 504 | { |
537 | 505 | #ifdef DEBUG_STEALING |
538 | - _fd_debug("[%d.%d] all agents starving...\n", tid, agent); | |
506 | + fd__debug("[%d.%d] all agents starving...\n", tid, agent); | |
539 | 507 | #endif |
540 | 508 | |
541 | 509 | return false; |
... | ... | @@ -565,14 +533,14 @@ bool _fd_steal_store(_fd_store store_, fd_int *variable, int agent, int retries) |
565 | 533 | // lock access to victim's stores ... |
566 | 534 | pthread_mutex_lock(&stores_mutexes[v]); |
567 | 535 | #if DEBUG_STEALING > 1 |
568 | - _fd_debug("[%d.%d] locked %d stores' mutex\n", tid, agent, v); | |
536 | + fd__debug("[%d.%d] locked %d stores' mutex\n", tid, agent, v); | |
569 | 537 | #endif |
570 | 538 | |
571 | 539 | // ... and make sure that the victim has enough stores |
572 | 540 | stores = split_indexes[v][1] - split_indexes[v][0]; |
573 | 541 | |
574 | 542 | #if DEBUG_STEALING > 1 |
575 | - _fd_debug("[%d.%d] %d stores left at %d\n", tid, agent, stores, v); | |
543 | + fd__debug("[%d.%d] %d stores left at %d\n", tid, agent, stores, v); | |
576 | 544 | #endif |
577 | 545 | |
578 | 546 | // don't steal the last few stores from an agent |
... | ... | @@ -583,7 +551,7 @@ bool _fd_steal_store(_fd_store store_, fd_int *variable, int agent, int retries) |
583 | 551 | pthread_mutex_unlock(&stores_mutexes[v]); |
584 | 552 | |
585 | 553 | #ifdef DEBUG_STEALING |
586 | - _fd_debug("[%d.%d] not enough stores (%d) at %d\n", tid, agent, | |
554 | + fd__debug("[%d.%d] not enough stores (%d) at %d\n", tid, agent, | |
587 | 555 | stores, v); |
588 | 556 | #endif |
589 | 557 | } |
... | ... | @@ -596,7 +564,7 @@ bool _fd_steal_store(_fd_store store_, fd_int *variable, int agent, int retries) |
596 | 564 | // the main thread won't keep trying |
597 | 565 | if (agent == -1) |
598 | 566 | { |
599 | - _fd_debug("[%d] giving up stealing\n", tid); | |
567 | + fd__trace("[%d] giving up stealing\n", tid); | |
600 | 568 | |
601 | 569 | return false; |
602 | 570 | } |
... | ... | @@ -608,7 +576,7 @@ bool _fd_steal_store(_fd_store store_, fd_int *variable, int agent, int retries) |
608 | 576 | if (as == nagents) |
609 | 577 | { |
610 | 578 | #ifdef DEBUG_STEALING |
611 | - _fd_debug("[%d.%d] all agents starving...\n", tid, agent); | |
579 | + fd__debug("[%d.%d] all agents starving...\n", tid, agent); | |
612 | 580 | #endif |
613 | 581 | |
614 | 582 | return false; |
... | ... | @@ -619,7 +587,7 @@ bool _fd_steal_store(_fd_store store_, fd_int *variable, int agent, int retries) |
619 | 587 | #endif |
620 | 588 | |
621 | 589 | #ifdef DEBUG_STEALING |
622 | - _fd_debug("[%d.%d] pausing...\n", tid, agent); | |
590 | + fd__debug("[%d.%d] pausing...\n", tid, agent); | |
623 | 591 | #endif |
624 | 592 | |
625 | 593 | nanosleep(&delay, NULL); |
... | ... | @@ -631,7 +599,7 @@ bool _fd_steal_store(_fd_store store_, fd_int *variable, int agent, int retries) |
631 | 599 | if (as == nagents) |
632 | 600 | { |
633 | 601 | #ifdef DEBUG_STEALING |
634 | - _fd_debug("[%d.%d] all agents starving...\n", tid, agent); | |
602 | + fd__debug("[%d.%d] all agents starving...\n", tid, agent); | |
635 | 603 | #endif |
636 | 604 | |
637 | 605 | return false; |
... | ... | @@ -667,14 +635,12 @@ bool _fd_steal_store(_fd_store store_, fd_int *variable, int agent, int retries) |
667 | 635 | |
668 | 636 | memcpy(store_, &split_stores_[v][s * fd_variables_count], STORE_SIZE); |
669 | 637 | |
670 | -#ifdef INDEX_IN_POOL | |
671 | 638 | #ifndef STORE_IN_POOL |
672 | 639 | if (variable) |
673 | 640 | #else |
674 | 641 | if (variable && split_variable_[v][s] != -1) |
675 | 642 | #endif |
676 | 643 | *variable = _fd_variables[split_variable_[v][s]]; |
677 | -#endif | |
678 | 644 | |
679 | 645 | // this agent will likely become the one with the largest search space |
680 | 646 | // (if work is being stolen by the controller, most_work will be set |
... | ... | @@ -697,14 +663,10 @@ bool _fd_steal_store(_fd_store store_, fd_int *variable, int agent, int retries) |
697 | 663 | } |
698 | 664 | |
699 | 665 | #if DEBUG_STEALING > 0 |
700 | -#ifdef INDEX_IN_POOL | |
701 | - _fd_debug("[%d.%d] stole work (%d/%d) from %d (var %d)\n", tid, agent, s, | |
666 | + fd__debug("[%d.%d] stole work (%d/%d) from %d (var %d)\n", tid, agent, s, | |
702 | 667 | stores, v, split_variable_[v][s]); |
703 | -#else | |
704 | - _fd_debug("[%d.%d] stole work (%d/%d) from %d\n", tid, agent, s, stores, v); | |
705 | -#endif | |
706 | 668 | #if DEBUG_STEALING > 2 |
707 | - _fd_output("[%d.%d] ", tid, agent); _fd_cprint3(store_); | |
669 | + fd__output("[%d.%d] ", tid, agent); _fd_cprint3(store_); | |
708 | 670 | #endif |
709 | 671 | #endif |
710 | 672 | |
... | ... | @@ -733,24 +695,20 @@ static bool _fd_restore_store(fd_int *variable) |
733 | 695 | #if STEAL_WORK < 1 |
734 | 696 | return false; |
735 | 697 | #else /* STEAL_WORK < 1 */ |
736 | -#ifndef INDEX_IN_POOL | |
737 | - return _fd_steal_store(store, agent, 0); | |
738 | -#else | |
739 | 698 | return _fd_steal_store(store, variable, agent, 0); |
740 | -#endif | |
741 | 699 | #endif /* STEAL_WORK < 1 */ |
742 | 700 | |
743 | 701 | #if STEAL_WORK > 0 |
744 | 702 | if (next_split_index - base_split_index < INDEX_SAFE) |
745 | 703 | { |
746 | - //_fd_debug("[%d.%d] have %d stores\n", tid, agent, next_split_index - base_split_index); | |
747 | -#ifndef FAST | |
704 | + //fd__trace("[%d.%d] have %d stores\n", tid, agent, next_split_index - base_split_index); | |
705 | +#ifdef TRACE | |
748 | 706 | if (pthread_mutex_trylock(&stores_mutexes[agent])) |
749 | - _fd_debug("[%d.%d] *** found stores locked [%d,%d[\n", tid, agent, | |
707 | + fd__trace("[%d.%d] *** found stores locked [%d,%d[\n", tid, agent, | |
750 | 708 | base_split_index, next_split_index), |
751 | 709 | #endif |
752 | 710 | pthread_mutex_lock(&stores_mutexes[agent]); |
753 | - //_fd_debug("[%d.%d] locked stores\n", tid, agent); | |
711 | + //fd__trace("[%d.%d] locked stores\n", tid, agent); | |
754 | 712 | |
755 | 713 | locked = true; |
756 | 714 | } |
... | ... | @@ -763,7 +721,7 @@ static bool _fd_restore_store(fd_int *variable) |
763 | 721 | ++pool_gets; |
764 | 722 | #endif |
765 | 723 | |
766 | - --next_split_index; | |
724 | + next_split_index--; | |
767 | 725 | |
768 | 726 | #ifndef STORE_IN_POOL |
769 | 727 | memcpy(store, &split_stores[next_split_index * fd_variables_count], |
... | ... | @@ -774,18 +732,10 @@ static bool _fd_restore_store(fd_int *variable) |
774 | 732 | #endif |
775 | 733 | |
776 | 734 | #ifndef STORE_IN_POOL |
777 | -# ifndef INDEX_IN_POOL | |
778 | - *variable = split_variable[next_split_index]; | |
779 | -# else | |
780 | 735 | *variable = _fd_variables[split_variable[next_split_index]]; |
781 | -# endif /* INDEX_IN_POOL */ | |
782 | 736 | #else |
783 | -# ifndef INDEX_IN_POOL | |
784 | - *variable = split_variable[next_split_index - 1]; | |
785 | -# else | |
786 | 737 | assert(split_variable[next_split_index - 1] != -1); |
787 | 738 | *variable = _fd_variables[split_variable[next_split_index - 1]]; |
788 | -# endif /* INDEX_IN_POOL */ | |
789 | 739 | #endif /* STORE_IN_POOL */ |
790 | 740 | |
791 | 741 | #if STEAL_WORK > 0 |
... | ... |
src/problem.c
... | ... | @@ -10,6 +10,8 @@ |
10 | 10 | #include "values.h" |
11 | 11 | #include "constraints.h" |
12 | 12 | |
13 | +#include "util.h" | |
14 | + | |
13 | 15 | extern int fd__workers; |
14 | 16 | |
15 | 17 | static void _fd_cleanup(void); |
... | ... | @@ -114,7 +116,7 @@ void fd_init(int *argc, char **argv[]) |
114 | 116 | { |
115 | 117 | #ifdef SPLITGO_MPI |
116 | 118 | if (MPI_Init(argc, argv)) |
117 | - _fd_fatal("MPI_Init failed"); | |
119 | + fd__fatal("MPI_Init failed"); | |
118 | 120 | #endif |
119 | 121 | |
120 | 122 | _fd_parse_general_options(argc, *argv); |
... | ... | @@ -123,9 +125,7 @@ void fd_init(int *argc, char **argv[]) |
123 | 125 | fd__init_splitgo(argc, *argv); |
124 | 126 | #endif |
125 | 127 | |
126 | -#ifdef CONSTRAINT_CLASS | |
127 | - _fd_init_constraints(); | |
128 | -#endif | |
128 | + fd__init_constraints(); | |
129 | 129 | |
130 | 130 | #ifdef USE_STORE |
131 | 131 | _fd_init_main_store(); |
... | ... |
src/revisions.c
... | ... | @@ -7,6 +7,8 @@ |
7 | 7 | #include "fdc_int.h" |
8 | 8 | #include "constraints.h" |
9 | 9 | |
10 | +#include "util.h" | |
11 | + | |
10 | 12 | #ifdef REVISION_IS_VAR |
11 | 13 | typedef fd_int revision; |
12 | 14 | #else /* REVISION_IS_VAR */ |
... | ... | @@ -181,7 +183,7 @@ int _fd_perform_revisions() |
181 | 183 | if (_fd_propagate(c, v) == FD_NOSOLUTION) |
182 | 184 | { |
183 | 185 | #ifdef COUNT_REVISIONS |
184 | - _fd_debug("failed after %d revisions\n", nr + 1); | |
186 | + fd__debug("failed after %d revisions\n", nr + 1); | |
185 | 187 | #endif |
186 | 188 | |
187 | 189 | return FD_NOSOLUTION; |
... | ... | @@ -212,7 +214,7 @@ int _fd_perform_revisions() |
212 | 214 | free(r); |
213 | 215 | |
214 | 216 | #ifdef COUNT_REVISIONS |
215 | - _fd_debug("failed after %d revisions\n", nr + 1); | |
217 | + fd__debug("failed after %d revisions\n", nr + 1); | |
216 | 218 | #endif |
217 | 219 | |
218 | 220 | return FD_NOSOLUTION; |
... | ... | @@ -228,7 +230,7 @@ int _fd_perform_revisions() |
228 | 230 | #endif /* ORDER_REVISIONS */ |
229 | 231 | |
230 | 232 | #ifdef COUNT_REVISIONS |
231 | - _fd_debug("performed %d revisions\n", nr); | |
233 | + fd__debug("performed %d revisions\n", nr); | |
232 | 234 | #endif |
233 | 235 | |
234 | 236 | return FD_OK; |
... | ... | @@ -251,7 +253,7 @@ static int filter_domains() |
251 | 253 | if (_fd_filter(c) == FD_NOSOLUTION) |
252 | 254 | { |
253 | 255 | #ifdef COUNT_REVISIONS |
254 | - _fd_debug("failed after %d filtering steps\n", nr + 1); | |
256 | + fd__debug("failed after %d filtering steps\n", nr + 1); | |
255 | 257 | #endif |
256 | 258 | |
257 | 259 | return FD_NOSOLUTION; |
... | ... | @@ -263,7 +265,7 @@ static int filter_domains() |
263 | 265 | } |
264 | 266 | |
265 | 267 | #ifdef COUNT_REVISIONS |
266 | - _fd_debug("performed %d filtering steps\n", nr); | |
268 | + fd__debug("performed %d filtering steps\n", nr); | |
267 | 269 | #endif |
268 | 270 | |
269 | 271 | // revise domains wrt the variables whose domains changed |
... | ... | @@ -272,9 +274,7 @@ static int filter_domains() |
272 | 274 | |
273 | 275 | int _fd_filter_domains() |
274 | 276 | { |
275 | -#ifdef CONSTRAINT_TEMPS | |
276 | 277 | fd__constraint_data_reset(); |
277 | -#endif | |
278 | 278 | |
279 | 279 | return filter_domains(); |
280 | 280 | } |
... | ... |
src/splitting.c
... | ... | @@ -5,6 +5,8 @@ |
5 | 5 | #include "values.h" |
6 | 6 | #include "store.h" |
7 | 7 | |
8 | +#include "util.h" | |
9 | + | |
8 | 10 | #ifndef COMPACT_DOMAINS |
9 | 11 | #error "only works with COMPACT_DOMAINS" |
10 | 12 | #endif |
... | ... | @@ -210,7 +212,7 @@ static int fd__split_even_one(int n, _fd_store stores[]) |
210 | 212 | |
211 | 213 | if (v == fd__label_vars_count) |
212 | 214 | { |
213 | - _fd_debug("[%d] cannot split %d-ways evenly, resorting to even " | |
215 | + fd__debug("[%d] cannot split %d-ways evenly, resorting to even " | |
214 | 216 | "splitting\n", tid, n); |
215 | 217 | |
216 | 218 | return fd__split_even(n, stores); |
... | ... | @@ -258,7 +260,7 @@ int fd__split_problem(int n, _fd_store stores[], |
258 | 260 | int v, p; |
259 | 261 | |
260 | 262 | #ifdef DEBUG_SPLITTING |
261 | - _fd_output("before splitting: "); _fd_cprint3(store); | |
263 | + fd__output("before splitting: "); _fd_cprint3(store); | |
262 | 264 | #endif |
263 | 265 | |
264 | 266 | parts = splitter(n, stores); |
... | ... | @@ -272,9 +274,9 @@ int fd__split_problem(int n, _fd_store stores[], |
272 | 274 | _fd_copy_value(SVALUE(stores[p][v]), DOMAIN(_fd_variables[v])); |
273 | 275 | |
274 | 276 | #ifdef DEBUG_SPLITTING |
275 | - _fd_output("split into %d out of %d stores\n", np, n); | |
277 | + fd__output("split into %d out of %d stores\n", np, n); | |
276 | 278 | for (p = 0; p < n; ++p) |
277 | - _fd_output("store %d: ", p), _fd_cprint3(stores[p]); | |
279 | + fd__output("store %d: ", p), _fd_cprint3(stores[p]); | |
278 | 280 | #endif |
279 | 281 | |
280 | 282 | return parts; |
... | ... |
src/util.c
... | ... | @@ -2,13 +2,15 @@ |
2 | 2 | #include <stdlib.h> |
3 | 3 | #include <stdarg.h> |
4 | 4 | |
5 | -void _fd_fatal(char *msg) | |
5 | +#include "util.h" | |
6 | + | |
7 | +void fd__fatal(char *msg) | |
6 | 8 | { |
7 | 9 | fprintf(stderr, "%s\n", msg); |
8 | 10 | abort(); // XXX |
9 | 11 | } |
10 | 12 | |
11 | -void _fd_error(char *format, ...) | |
13 | +void fd__error(char *format, ...) | |
12 | 14 | { |
13 | 15 | va_list args; |
14 | 16 | |
... | ... | @@ -17,7 +19,7 @@ void _fd_error(char *format, ...) |
17 | 19 | va_end (args); |
18 | 20 | } |
19 | 21 | |
20 | -void _fd_output(char *format, ...) | |
22 | +void fd__output(char *format, ...) | |
21 | 23 | { |
22 | 24 | va_list args; |
23 | 25 | |
... | ... | @@ -35,9 +37,9 @@ void fd__info(char *format, ...) |
35 | 37 | va_end (args); |
36 | 38 | } |
37 | 39 | |
38 | -#ifndef _fd_debug | |
40 | +#ifndef fd__debug | |
39 | 41 | |
40 | -void _fd_debug(char *format, ...) | |
42 | +void fd__debug(char *format, ...) | |
41 | 43 | { |
42 | 44 | va_list args; |
43 | 45 | |
... | ... |
src/values-bitmap.c
... | ... | @@ -58,10 +58,10 @@ fd_value fd_new_value(int min, int max) |
58 | 58 | fd_value v; |
59 | 59 | |
60 | 60 | if (min < MIN_VALUE) |
61 | - _fd_fatal("value less than MIN_VALUE"); | |
61 | + fd__fatal("value less than MIN_VALUE"); | |
62 | 62 | |
63 | 63 | if (max > MAX_VALUE) |
64 | - _fd_fatal("value greater than MAX_VALUE"); | |
64 | + fd__fatal("value greater than MAX_VALUE"); | |
65 | 65 | |
66 | 66 | #ifdef INLINE_DOMAINS |
67 | 67 | return (ALL_ONES >> min) & (ALL_ONES << DOMAIN_BITS - max - 1); |
... | ... | @@ -95,10 +95,10 @@ fd_value fd_new_value(int min, int max) |
95 | 95 | void _fd_init_domain(DOMAIN_REF_T(domain), int min, int max) |
96 | 96 | { |
97 | 97 | if (min < MIN_VALUE) |
98 | - _fd_fatal("value less than MIN_VALUE"); | |
98 | + fd__fatal("value less than MIN_VALUE"); | |
99 | 99 | |
100 | 100 | if (max > MAX_VALUE) |
101 | - _fd_fatal("value greater than MAX_VALUE"); | |
101 | + fd__fatal("value greater than MAX_VALUE"); | |
102 | 102 | |
103 | 103 | #if WORDS == 1 |
104 | 104 | (*domain)[0] = (ALL_ONES >> min) & (ALL_ONES << DOMAIN_BITS - max - 1); |
... | ... | @@ -1278,10 +1278,10 @@ fd_value fd_new_value(int min, int max) |
1278 | 1278 | fd_value v; |
1279 | 1279 | |
1280 | 1280 | if (min < MIN_VALUE) |
1281 | - _fd_fatal("value less than MIN_VALUE"); | |
1281 | + fd__fatal("value less than MIN_VALUE"); | |
1282 | 1282 | |
1283 | 1283 | if (max > MAX_VALUE) |
1284 | - _fd_fatal("value greater than MAX_VALUE"); | |
1284 | + fd__fatal("value greater than MAX_VALUE"); | |
1285 | 1285 | |
1286 | 1286 | #if WORDS == 1 |
1287 | 1287 | if (v = malloc(sizeof(*v))) |
... | ... | @@ -1320,10 +1320,10 @@ fd_value fd_new_value(int min, int max) |
1320 | 1320 | void _fd_init_domain(DOMAIN_REF_T(domain), int min, int max) |
1321 | 1321 | { |
1322 | 1322 | if (min < MIN_VALUE) |
1323 | - _fd_fatal("value less than MIN_VALUE"); | |
1323 | + fd__fatal("value less than MIN_VALUE"); | |
1324 | 1324 | |
1325 | 1325 | if (max > MAX_VALUE) |
1326 | - _fd_fatal("value greater than MAX_VALUE"); | |
1326 | + fd__fatal("value greater than MAX_VALUE"); | |
1327 | 1327 | |
1328 | 1328 | #if WORDS == 1 |
1329 | 1329 | *domain->map = (ALL_ONES >> min) & (ALL_ONES << DOMAIN_BITS - max - 1); |
... | ... |
src/values-intervals.c
... | ... | @@ -90,10 +90,10 @@ int _fd_val_max(fd_value domain) |
90 | 90 | case FD_MULTIPLE: |
91 | 91 | return v->value.interval.upper; |
92 | 92 | case FD_EMPTY: |
93 | - _fd_fatal("empty domain in _fd_val_max"); | |
93 | + fd__fatal("empty domain in _fd_val_max"); | |
94 | 94 | /* NOTREACHED */ |
95 | 95 | default: |
96 | - _fd_fatal("corrupt domain in _fd_val_max?"); | |
96 | + fd__fatal("corrupt domain in _fd_val_max?"); | |
97 | 97 | /* NOTREACHED */ |
98 | 98 | } |
99 | 99 | } |
... | ... | @@ -108,10 +108,10 @@ int _fd_val_min(fd_value domain) |
108 | 108 | case FD_MULTIPLE: |
109 | 109 | return domain->value.interval.lower; |
110 | 110 | case FD_EMPTY: |
111 | - _fd_fatal("empty domain in _fd_val_min"); | |
111 | + fd__fatal("empty domain in _fd_val_min"); | |
112 | 112 | /* NOTREACHED */ |
113 | 113 | default: |
114 | - _fd_fatal("corrupt domain in _fd_val_min?"); | |
114 | + fd__fatal("corrupt domain in _fd_val_min?"); | |
115 | 115 | /* NOTREACHED */ |
116 | 116 | } |
117 | 117 | } |
... | ... | @@ -151,10 +151,10 @@ int _fd_val_del_min(fd_value domain) |
151 | 151 | |
152 | 152 | break; |
153 | 153 | case FD_EMPTY: |
154 | - _fd_fatal("empty domain in _fd_val_del_min"); | |
154 | + fd__fatal("empty domain in _fd_val_del_min"); | |
155 | 155 | /* NOTREACHED */ |
156 | 156 | default: |
157 | - _fd_fatal("corrupt domain in _fd_val_del_min?"); | |
157 | + fd__fatal("corrupt domain in _fd_val_del_min?"); | |
158 | 158 | /* NOTREACHED */ |
159 | 159 | } |
160 | 160 | |
... | ... | @@ -198,10 +198,10 @@ int _fd_val_del_max(fd_value domain) |
198 | 198 | |
199 | 199 | break; |
200 | 200 | case FD_EMPTY: |
201 | - _fd_fatal("empty domain in _fd_val_del_max"); | |
201 | + fd__fatal("empty domain in _fd_val_del_max"); | |
202 | 202 | /* NOTREACHED */ |
203 | 203 | default: |
204 | - _fd_fatal("corrupt domain in _fd_val_del_max?"); | |
204 | + fd__fatal("corrupt domain in _fd_val_del_max?"); | |
205 | 205 | /* NOTREACHED */ |
206 | 206 | } |
207 | 207 | |
... | ... | @@ -230,10 +230,10 @@ int _fd_val_contains_val(fd_value domain, int value) |
230 | 230 | |
231 | 231 | break; |
232 | 232 | case FD_EMPTY: |
233 | - _fd_fatal("empty domain in _fd_val_contains_val"); | |
233 | + fd__fatal("empty domain in _fd_val_contains_val"); | |
234 | 234 | /* NOTREACHED */ |
235 | 235 | default: |
236 | - _fd_fatal("corrupt domain in _fd_val_contains_val?"); | |
236 | + fd__fatal("corrupt domain in _fd_val_contains_val?"); | |
237 | 237 | /* NOTREACHED */ |
238 | 238 | } |
239 | 239 | |
... | ... | @@ -249,7 +249,7 @@ void _fd_val_set_value(fd_value domain, int value) |
249 | 249 | switch (domain->kind) |
250 | 250 | { |
251 | 251 | case FD_EMPTY: |
252 | - _fd_fatal("_fd_val_set_val called on a variable with empty domain"); | |
252 | + fd__fatal("_fd_val_set_val called on a variable with empty domain"); | |
253 | 253 | /* NOTREACHED */ |
254 | 254 | case FD_MULTIPLE: |
255 | 255 | domain->kind = FD_SINGLETON; |
... | ... | @@ -262,7 +262,7 @@ void _fd_val_set_value(fd_value domain, int value) |
262 | 262 | } |
263 | 263 | break; |
264 | 264 | default: |
265 | - _fd_fatal("corrupt domain in _fd_val_set_value?"); | |
265 | + fd__fatal("corrupt domain in _fd_val_set_value?"); | |
266 | 266 | /* NOTREACHED */ |
267 | 267 | } |
268 | 268 | } |
... | ... | @@ -702,7 +702,7 @@ fd_value _fd_val_clone(fd_value value) |
702 | 702 | *next = fd_new_value(1, 0); |
703 | 703 | break; |
704 | 704 | default: |
705 | - _fd_fatal("corrupt domain in _fd_val_clone?"); | |
705 | + fd__fatal("corrupt domain in _fd_val_clone?"); | |
706 | 706 | /* NOTREACHED */ |
707 | 707 | } |
708 | 708 | |
... | ... | @@ -744,7 +744,7 @@ void _fd_val_copy(fd_value to, fd_value from) |
744 | 744 | break; |
745 | 745 | #endif |
746 | 746 | default: |
747 | - _fd_fatal("corrupt domain in _fd_val_copy?"); | |
747 | + fd__fatal("corrupt domain in _fd_val_copy?"); | |
748 | 748 | /* NOTREACHED */ |
749 | 749 | } |
750 | 750 | |
... | ... | @@ -769,7 +769,7 @@ int _fd_val_size(fd_value domain) |
769 | 769 | s += v->value.interval.upper - v->value.interval.lower + 1; |
770 | 770 | break; |
771 | 771 | default: |
772 | - _fd_fatal("corrupt domain in _fd_val_size?"); | |
772 | + fd__fatal("corrupt domain in _fd_val_size?"); | |
773 | 773 | /* NOTREACHED */ |
774 | 774 | } |
775 | 775 | |
... | ... |
src/values.c
src/variables.c
... | ... | @@ -9,18 +9,31 @@ |
9 | 9 | #include "store.h" |
10 | 10 | #include "constraints.h" |
11 | 11 | |
12 | +#include "util.h" | |
13 | + | |
12 | 14 | int fd_variables_count = 0; |
13 | 15 | __thread fd_int _fd_variables[MAX_VARIABLES]; |
14 | 16 | |
17 | +// variables with singleton domains (ie, constants) | |
18 | +static fd_int fd__constants[MAX_VALUE + 1]; | |
19 | + | |
15 | 20 | fd_int *fd__label_vars = 0; // variables subject to labelling |
16 | 21 | int fd__label_vars_count = 0; |
17 | 22 | bool *fd__var_labelled; // identifies the variables subject to labelling |
18 | 23 | |
19 | -fd_int fd_new(int min, int max) | |
24 | + | |
25 | +/* | |
26 | + Create and return a new variable with domain { MIN, ..., MAX }. | |
27 | + Also store it in the global variable table. | |
28 | +*/ | |
29 | +static fd_int create_variable(int min, int max) | |
20 | 30 | { |
21 | - fd_int v = malloc(sizeof(struct fd_int)); | |
31 | + fd_int v; | |
22 | 32 | |
23 | - assert(fd_variables_count < MAX_VARIABLES); | |
33 | + if (fd_variables_count == MAX_VARIABLES) | |
34 | + fd__fatal("too many variables, increase MAX_VARIABLES"); | |
35 | + | |
36 | + v = malloc(sizeof(struct fd_int)); | |
24 | 37 | |
25 | 38 | if (v) |
26 | 39 | { |
... | ... | @@ -39,6 +52,31 @@ fd_int fd_new(int min, int max) |
39 | 52 | return v; |
40 | 53 | } |
41 | 54 | |
55 | +/* Return a variable with singleton domain { VALUE }. */ | |
56 | +fd_int fd_const(int value) | |
57 | +{ | |
58 | + if (value < MIN_VALUE) | |
59 | + fd__fatal("value less than MIN_VALUE"); | |
60 | + | |
61 | + if (value > MAX_VALUE) | |
62 | + fd__fatal("value greater than MAX_VALUE"); | |
63 | + | |
64 | + // only create the variable if it has not yet been created | |
65 | + if (fd__constants[value] == NULL) | |
66 | + fd__constants[value] = create_variable(value, value); | |
67 | + | |
68 | + return fd__constants[value]; | |
69 | +} | |
70 | + | |
71 | +/* Return a variable with domain { MIN, ..., MAX }. */ | |
72 | +fd_int fd_new(int min, int max) | |
73 | +{ | |
74 | + if (min == max) | |
75 | + return fd_const(min); | |
76 | + else | |
77 | + return create_variable(min, max); | |
78 | +} | |
79 | + | |
42 | 80 | #ifdef SPLITGO |
43 | 81 | /* create a skeletal copy of VARIABLE */ // XXX: description |
44 | 82 | fd_int _fd_var_copy(fd_int variable) |
... | ... | @@ -302,7 +340,7 @@ void _fd_var_set_value(fd_int variable, int value) |
302 | 340 | void fd_label(fd_int variables[], int n) |
303 | 341 | { |
304 | 342 | if (fd__label_vars) |
305 | - _fd_fatal("fd_label() can only be called once"); | |
343 | + fd__fatal("fd_label() can only be called once"); | |
306 | 344 | |
307 | 345 | fd__label_vars = malloc(n * sizeof(*fd__label_vars)); // XXX: NULL |
308 | 346 | fd__label_vars_count = n; |
... | ... |
src/variables.h
... | ... | @@ -7,6 +7,7 @@ extern fd_int *fd__label_vars; |
7 | 7 | extern int fd__label_vars_count; |
8 | 8 | extern bool *fd__var_labelled; |
9 | 9 | |
10 | +fd_int fd_const(int value); | |
10 | 11 | fd_int fd_new(int min, int max); |
11 | 12 | fd_int _fd_var_copy(fd_int variable); |
12 | 13 | void _fd_var_copy_domain(fd_int to, fd_int from); |
... | ... | @@ -36,15 +37,15 @@ int _fd_var_intersect(fd_int variable1, fd_int variable2); |
36 | 37 | int _fd_var_contains_val(fd_int variable, int value); |
37 | 38 | void _fd_var_set_value(fd_int variable, int value); |
38 | 39 | |
39 | -#define fd_update_domain(op,var,value) \ | |
40 | - { \ | |
41 | - _fd_var_ ## op(var, value); \ | |
42 | - \ | |
43 | - _fd_revise_connected(var); \ | |
44 | - } | |
40 | +#define fd_update_domain(op, val, var) \ | |
41 | + do { \ | |
42 | + _fd_var_ ## op(val, var); \ | |
43 | + \ | |
44 | + _fd_revise_connected(this, var); \ | |
45 | + } while (0) | |
45 | 46 | |
46 | 47 | #define fd_update_domain_and_check(op, val, var) \ |
47 | - { \ | |
48 | + do { \ | |
48 | 49 | if (_fd_var_ ## op(val, var)) \ |
49 | 50 | { \ |
50 | 51 | if (fd_domain_empty(var)) \ |
... | ... | @@ -52,7 +53,7 @@ void _fd_var_set_value(fd_int variable, int value); |
52 | 53 | \ |
53 | 54 | _fd_revise_connected(this, var); \ |
54 | 55 | } \ |
55 | - } | |
56 | + } while (0) | |
56 | 57 | |
57 | 58 | // SEARCH |
58 | 59 | extern int (*fd__cmp_variables)(fd_int, fd_int); |
... | ... |