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