#include /* binary constraint (between X and Y) defined through the disallowed pairs */ int fd_nogoods_propagate(fd_constraint this, fd_int revise) { fd_int other; int rx, ox; // variables' indexes within the constraint int value; int changed = 0; int i; rx = revise == VAR(this, 0) ? 0 : 1; ox = 1 - rx; other = VAR(this, ox); // only propagate if other's domain is a singleton if (!fd_var_single(other, &value)) return FD_OK; for (i = 0; i < this->nconstants; i += 2) if (this->constants[i + ox] == value) changed |= _fd_var_del_val(this->constants[i + rx], revise); if (changed && fd_domain_empty(revise)) return FD_NOSOLUTION; // XXX: enqueue further updates here? if (changed) _fd_revise_connected(this, revise); return FD_OK; } fd_constraint fd_nogoods(fd_int x, fd_int y, int *nogoods, int nnogoods) { fd_constraint c = _fd_constraint_new(2, 2 * nnogoods); if (c) { c->variables[0] = FD_INT2C_VAR(x); c->variables[1] = FD_INT2C_VAR(y); #ifdef CONSTRAINT_CLASS c->kind = FD_CONSTR_NOGOODS; #else /* CONSTRAINT_CLASS */ c->propagator = fd_nogoods_propagate; #endif /* CONSTRAINT_CLASS */ memcpy(c->constants, nogoods, 2 * nnogoods * sizeof(int)); _fd_var_add_constraint(x, c); _fd_var_add_constraint(y, c); _fd_add_constraint(c); } return c; }