/* Social golfers */ #include #include #include #include "fdc_int.h" #define MAX_P MAX_VARIABLES #define MAX_G MAX_VARIABLES int main(int argc, char *argv[]) { int P = 12; // no. of players int G = 4; // no. of groups per week int K = 3; // players per group int W = 2; // no. of weeks int GW; // total groups fd_int *vs; #define vs(r, c) vs[(r) * GW + (c)] fd_int *ts, *us; int p, g, p0, p1, g0, g1, w; int solutions = 0, one_solution = 1; int use_label = 0; int i; fd_init(&argc, &argv); for (i = 1; i < argc; ++i) if (!strcmp(argv[i], "--all")) one_solution = 0; else if (!strcmp(argv[i], "--label")) use_label = 1; else if (argc - i < 3) { _fd_debug("must give G, K, and W (or nothing)\n"); return 1; } else { G = atoi(argv[i++]); K = atoi(argv[i++]); W = atoi(argv[i]); } P = G * K; GW = G * W; vs = calloc(P * GW, sizeof(fd_int)); ts = calloc(P > GW ? P : GW, sizeof(fd_int)); us = calloc(P > GW ? P : GW, sizeof(fd_int)); for (p = 0; p < P; ++p) for (g = 0; g < GW; ++g) vs(p, g) = fd_new(0, 1); if (use_label) fd_label(vs, P * GW); // a player appears in W groups for (p = 0; p < P; ++p) fd_sum(vs + GW * p, GW, W); // K players per group for (g = 0; g < GW; ++g) { for (p = 0; p < P; ++p) ts[p] = vs(p, g); fd_sum(ts, P, K); } // no player should be in another group with another player more // than once: the scalar (or dot) product between any two rows must // not exceed 1 for (p0 = 0; p0 < P; ++p0) for (p1 = p0 + 1; p1 < P; ++p1) { for (g = 0; g < GW; ++g) { ts[g] = vs(p0, g); us[g] = vs(p1, g); } fd_knapsack2(ts, us, GW, fd_new(0,1)); } // every G groups correspond to one week and no player can be in // more than one: the scalar product between any two columns within // every G groups must be 0 for (w = 0; w < W; ++w) for (g0 = 0; g0 < G; ++g0) for (g1 = g0 + 1; g1 < G; ++g1) { for (p = 0; p < P; ++p) { ts[p] = vs(p, w * G + g0); us[p] = vs(p, w * G + g1); } fd_sum_prod(ts, us, P, 0); } // try to eliminate solutions which result from exchanging rows // and/or columns // XXX: quite incomplete #if 0 // constrain the first row to be of the form 1 0...0 1 0...0 ... 1 0...0 { fd_int zero = fd_new(0, 0); for (g = 0; g < W; ++g) fd_gt(vs(0, g * G), zero); } #endif // constrain the first column to be of the form 1 ... 1 0 ... 0 for (p = 1; p < P; ++p) fd_ge(vs(p - 1, 0), vs(p, 0)); while (fd_solve() == FD_OK) { printf("solution %d:\n", ++solutions); for (p = 0; p < P; ++p) { for (g = 0; g < GW; ++g) { fd_print(vs(p, g)); putchar(' '); } putchar('\n'); } for (w = 0; w < W; ++w) { for (g = 0; g < G; ++g) { printf(" ("); for (p = 0, p0 = 0; p0 < K; ++p) if (fd_var_value(vs(p, w * G + g)) == 1) printf("%d%c", p, ++p0 == K ? ')' : ' '); } putchar('\n'); } #if !(defined(LOCAL_SEARCH) || defined(DISTRIBUTED_SOLVER)) if (one_solution) #endif break; } if (solutions) printf("%d solutions found\n", solutions); else printf("inconsistent CSP\n"); fd_end(); return !solutions; }