/* X - Y ne k */ int fd_minus_ne_filter(fd_constraint this) { fd_int x, y; int k; int value; x = VAR(this, 0); y = VAR(this, 1); k = this->constants[0]; // only propagate if a variable domain is a singleton if (fd_var_single(x, &value) && _fd_var_del_val(value - k, y)) { if (fd_domain_empty(y)) return FD_NOSOLUTION; fd__constraint_set_entailed(this); _fd_revise_connected(this, y); } else if (fd_var_single(y, &value) && _fd_var_del_val(k + value, x)) { if (fd_domain_empty(x)) return FD_NOSOLUTION; fd__constraint_set_entailed(this); _fd_revise_connected(this, x); } return FD_OK; } int fd_minus_ne_propagate2(fd_constraint this, fd_int culprit) { fd_int revise; int culprit_idx; int value; int changed = 0; // only propagate if culprit's domain is a singleton if (!fd_var_single(culprit, &value)) return FD_OK; culprit_idx = culprit == VAR(this, 0) ? 0 : 1; revise = VAR(this, 1 - culprit_idx); if (culprit_idx == 0) changed = _fd_var_del_val(value - this->constants[0], revise); else changed = _fd_var_del_val(this->constants[0] + value, revise); if (changed) { if (fd_domain_empty(revise)) return FD_NOSOLUTION; _fd_revise_connected(this, revise); } fd__constraint_set_entailed(this); return FD_OK; } int fd_minus_ne_propagate(fd_constraint this, fd_int revise) { fd_int other; int other_idx; int value; int changed = 0; other_idx = revise == VAR(this, 0) ? 1 : 0; other = VAR(this, other_idx); // only propagate if other's domain is a singleton if (!fd_var_single(other, &value)) return FD_OK; if (other_idx == 0) changed = _fd_var_del_val(value - this->constants[0], revise); else changed = _fd_var_del_val(this->constants[0] + value, revise); if (changed && fd_domain_empty(revise)) return FD_NOSOLUTION; fd__constraint_set_entailed(this); // XXX: enqueue further updates here? if (changed) _fd_revise_connected(this, revise); return FD_OK; } fd_constraint fd_minus_ne(fd_int x, fd_int y, int k) { fd_constraint c = _fd_constraint_new(2, 1); if (c) { c->variables[0] = FD_INT2C_VAR(x); c->variables[1] = FD_INT2C_VAR(y); c->constants[0] = k; #ifdef CONSTRAINT_CLASS c->kind = FD_CONSTR_MINUS_NE; #else /* CONSTRAINT_CLASS */ c->propagator2 = fd_minus_ne_propagate2; c->propagator = fd_minus_ne_propagate; #endif /* CONSTRAINT_CLASS */ _fd_var_add_constraint(x, c); _fd_var_add_constraint(y, c); _fd_add_constraint(c); } return c; }