Commit eef943717e684b6713d306f59ac369edb4104387

Authored by Vasco Pedro
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
1 1 #include <stdio.h>
  2 +#include <string.h>
2 3  
3   -#include "fdc_int.h"
  4 +#include <paccs.h>
4 5  
5 6 #define N 3
6 7  
7   -main(int argc, char *argv[])
  8 +int main(int argc, char *argv[])
8 9 {
9 10 fd_int vs[N], cardinal;
10 11 int solutions = 0, one_solution = 1;
... ...
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
... ... @@ -34,7 +34,7 @@ int main(int argc, char *argv[])
34 34 use_label = 1;
35 35 else if (argc - i < 3)
36 36 {
37   - _fd_debug("must give G, K, and W (or nothing)\n");
  37 + fd__error("must give G, K, and W (or nothing)\n");
38 38 return 1;
39 39 }
40 40 else
... ...
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
1 1 /* graph colouring ร  la Gecode */
2 2  
3 3 #include <stdio.h>
  4 +#include <stdlib.h>
4 5 #include <stdint.h>
5 6 #include <string.h>
6 7  
... ...
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
... ... @@ -2,7 +2,7 @@
2 2 #include <string.h>
3 3 #include <ctype.h>
4 4  
5   -#include "fdc_int.h"
  5 +#include <paccs.h>
6 6  
7 7 #define LETTERS 26
8 8 #define MAX_SIZE (10 * LETTERS) // whatever
... ...
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
1 1 #include <stdio.h>
2 2 #include <stdlib.h>
  3 +#include <string.h>
3 4  
4   -#include <fdc_int.h>
5   -#include "variables.h"
6   -#include "values.h"
  5 +#include <paccs.h>
7 6  
8 7 int main(int argc, char *argv[])
9 8 {
... ...
src/VERSION
1   -0.90d
  1 +0.91
... ...
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(&notify_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(&quot;[%d] recovered store\n&quot;, 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(&quot;[%d] recovered store\n&quot;, 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(&quot;[%d] recovered store\n&quot;, 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(&quot;[%d] recovered store\n&quot;, 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(&quot;[%d] recovered store\n&quot;, 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(&quot;[%d] recovered store\n&quot;, 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(&quot;[%d] recovered store\n&quot;, 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(&quot;[%d] recovered store\n&quot;, 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(&quot;[%d] done (quitting = %d, ready = %d, timeout = %d)\n&quot;, 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(&quot;[%d] done (quitting = %d, ready = %d, timeout = %d)\n&quot;, 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(&quot;[%d] done (quitting = %d, ready = %d, timeout = %d)\n&quot;, 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(&quot;[%d] done (quitting = %d, ready = %d, timeout = %d)\n&quot;, 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(&quot;[%d] done (quitting = %d, ready = %d, timeout = %d)\n&quot;, 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(&quot;[%d] done (quitting = %d, ready = %d, timeout = %d)\n&quot;, 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(&quot;[%d] done (quitting = %d, ready = %d, timeout = %d)\n&quot;, 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(&quot;[%d] done (quitting = %d, ready = %d, timeout = %d)\n&quot;, 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(&quot;[%d] done (quitting = %d, ready = %d, timeout = %d)\n&quot;, 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(&quot;[%d] done (quitting = %d, ready = %d, timeout = %d)\n&quot;, 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(&quot;[%d] done (quitting = %d, ready = %d, timeout = %d)\n&quot;, 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(&quot;[%d] done (quitting = %d, ready = %d, timeout = %d)\n&quot;, 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(&quot;[%d] done (quitting = %d, ready = %d, timeout = %d)\n&quot;, 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(&quot;[%d] done (quitting = %d, ready = %d, timeout = %d)\n&quot;, 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(&quot;[%d] done (quitting = %d, ready = %d, timeout = %d)\n&quot;, 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(&quot;[%d] done (quitting = %d, ready = %d, timeout = %d)\n&quot;, 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(&quot;[%d] done (quitting = %d, ready = %d, timeout = %d)\n&quot;, 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);
... ...
src/constraints/poly-le-k.c 0 โ†’ 100644
... ... @@ -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 = &quot;@(#) $Options: &quot;
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 = &quot;@(#) $Options: &quot;
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/util.h 0 โ†’ 100644
... ... @@ -0,0 +1,8 @@
  1 +void fd__fatal(char *msg);
  2 +void fd__error(char *format, ...);
  3 +void fd__output(char *format, ...);
  4 +void fd__info(char *format, ...);
  5 +
  6 +#ifndef fd__debug
  7 +void fd__debug(char *format, ...);
  8 +#endif
... ...
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
... ... @@ -7,6 +7,8 @@
7 7 #include "fdc_int.h"
8 8 #include "values.h"
9 9  
  10 +#include "util.h"
  11 +
10 12  
11 13 #ifdef COMPACT_DOMAINS
12 14 # include "values-bitmap.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);
... ...