/* X le Y */ static int fd_le_filter(fd_constraint this) { fd_int x, y; x = VAR(this, 0); y = VAR(this, 1); if (_fd_var_del_lt(_fd_var_min(x), y)) { if (fd_domain_empty(y)) return FD_NOSOLUTION; _fd_revise_connected(NULL, y); } if (_fd_var_del_gt(_fd_var_max(y), x)) { if (fd_domain_empty(x)) return FD_NOSOLUTION; _fd_revise_connected(NULL, x); } #if CONSTRAINT_TEMPS > 3 if (_fd_var_max(x) <= _fd_var_min(y)) fd__constraint_set_entailed(this); #endif return FD_OK; } int fd_le_propagate2(fd_constraint this, fd_int culprit) { fd_int revise; int changed = 0; if (culprit == VAR(this, 0)) { revise = VAR(this, 1); changed = _fd_var_del_lt(_fd_var_min(culprit), revise); } else { revise = VAR(this, 0); changed = _fd_var_del_gt(_fd_var_max(culprit), revise); } if (changed && fd_domain_empty(revise)) return FD_NOSOLUTION; #if CONSTRAINT_TEMPS > 3 if (_fd_var_max(VAR(this, 0)) <= _fd_var_min(VAR(this, 1))) fd__constraint_set_entailed(this); #endif if (changed) _fd_revise_connected(0, revise); return FD_OK; } int fd_le_propagate(fd_constraint this, fd_int revise) { int changed = 0; if (revise == VAR(this, 0)) changed = _fd_var_del_gt(_fd_var_max(VAR(this, 1)), revise); else changed = _fd_var_del_lt(_fd_var_min(VAR(this, 0)), revise); if (changed && fd_domain_empty(revise)) return FD_NOSOLUTION; #ifdef USE_ENTAILED if (_fd_var_max(VAR(this, 0)) <= _fd_var_min(VAR(this, 1))) _fd_constraint_set_entailed(this); #endif // XXX: enqueue further updates here? if (changed) _fd_revise_connected(this, revise); return FD_OK; } fd_constraint fd_le(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_LE; #else /* CONSTRAINT_CLASS */ c->propagator2 = fd_le_propagate2; c->propagator = fd_le_propagate; #endif /* CONSTRAINT_CLASS */ _fd_var_add_constraint(x, c); _fd_var_add_constraint(y, c); _fd_add_constraint(c); } return c; }