/* minimisation */ #include "bound.h" static int fd_min_filter(fd_constraint this) { fd_int x = VAR(this, 0); if (_fd_var_del_ge(_fd_bound_value(), x)) { if (fd_domain_empty(x)) return FD_NOSOLUTION; _fd_revise_connected(this, x); } return FD_OK; } int fd_min_propagate2(fd_constraint this, fd_int culprit) { int changed = 0; changed = _fd_var_del_ge(_fd_bound_value(), culprit); if (changed) { if (fd_domain_empty(culprit)) return FD_NOSOLUTION; _fd_revise_connected(this, culprit); // XXX } return FD_OK; } #ifndef USE_STORE #error "fd_min requires USE_STORE" #endif int fd_min_satisfied(fd_constraint this, _fd_store store, int *value) { int v; // XXX: `store' appears in the expansion of DOMAIN() _fd_val_single(DOMAIN(VAR(this, 0)), &v); if (value) *value = v; return v < _fd_bound_value(); } int fd_min_valid_bound(int current, int new) { return new < current; } int fd_min_compare(fd_constraint this, _fd_store s1, _fd_store s2) { int v1, v2; // XXX: `store' appears in the expansion of DOMAIN() { _fd_store store = s1; _fd_val_single(DOMAIN(VAR(this, 0)), &v1); } { _fd_store store = s2; _fd_val_single(DOMAIN(VAR(this, 0)), &v2); } return v1 - v2; } bool fd_min_bound_variable(fd_constraint this, int bound) { return _fd_var_del_ge(bound, VAR(this, 0)) != 0; } fd_constraint fd_min(fd_int variable) { fd_constraint c = _fd_constraint_new(1, 0); if (c) { c->variables[0] = FD_INT2C_VAR(variable); #ifdef CONSTRAINT_CLASS c->kind = FD_CONSTR_MIN; #else /* CONSTRAINT_CLASS */ c->propagator2 = fd_min_propagate2; #endif /* CONSTRAINT_CLASS */ _fd_var_add_constraint(variable, c); _fd_add_constraint(c); } _fd_init_bound(MAX_VALUE + 1, FD_INT2C_VAR(variable), c, fd_min_satisfied, fd_min_valid_bound, fd_min_compare, fd_min_bound_variable); return c; }