/* X eq Y */ static int fd_eq_filter(fd_constraint this) { int i; // only propagate if culprit's domain is a singleton for (i = 0; i < 2; ++i) { fd_int revise = VAR(this, 1 - i); if (_fd_var_intersect(revise, VAR(this, i))) { if (fd_domain_empty(revise)) return FD_NOSOLUTION; _fd_revise_connected(this, revise); } } return FD_OK; } int fd_eq_propagate2(fd_constraint this, fd_int culprit) { fd_int revise; int changed = 0; revise = VAR(this, culprit == VAR(this, 0) ? 1 : 0); changed = _fd_var_intersect(revise, culprit); if (!changed) return FD_OK; if (fd_domain_empty(revise)) return FD_NOSOLUTION; _fd_revise_connected(this, revise); return FD_OK; } int fd_eq_propagate(fd_constraint this, fd_int revise) { fd_int other; int changed = 0; other = VAR(this, revise == VAR(this, 0) ? 1 : 0); changed = _fd_var_intersect(revise, other); 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_eq(fd_int x, fd_int y) { fd_constraint c = _fd_constraint_new(2, 0); if (c) { c->variables[0] = FD_INT2C_VAR(x); c->variables[1] = FD_INT2C_VAR(y); #ifdef CONSTRAINT_CLASS c->kind = FD_CONSTR_EQ; #else /* CONSTRAINT_CLASS */ c->propagator2 = fd_eq_propagate2; c->propagator = fd_eq_propagate; #endif /* CONSTRAINT_CLASS */ _fd_var_add_constraint(x, c); _fd_var_add_constraint(y, c); _fd_add_constraint(c); } return c; }