#include #include #include #include "fdc_int.h" #include "store.h" #include "bound.h" bool _fd_optimising = false; struct _fd_bound_data { int value; C_VAR_T variable; fd_constraint constraint; int (*check)(fd_constraint, _fd_store, int *); int (*valid)(int, int); int (*compare)(fd_constraint, _fd_store, _fd_store); bool (*bound)(fd_constraint, int); }; _fd_bound_data *_fd_bound = NULL; _fd_bound_data *_fd_init_bound(int n, C_VAR_T v, fd_constraint c, int (*f)(fd_constraint, _fd_store, int *), int (*g)(int, int), int (*h)(fd_constraint, _fd_store, _fd_store), bool (*i)(fd_constraint, int)) { _fd_bound_data *b; if (_fd_bound) _fd_fatal("trying to set a 2nd optimisation constraint"); if ((b = malloc(sizeof(*_fd_bound))) == NULL) _fd_fatal("could not allocate memory for the optimisation bound"); b->value = n; b->variable = v; b->constraint = c; b->check = f; b->valid = g; b->compare = h; b->bound = i; _fd_bound = b; _fd_optimising = true; return b; } bool _fd_set_bound(int value) { assert(_fd_bound != NULL); if (!_fd_bound->valid(_fd_bound->value, value)) return false; _fd_bound->value = value; return true; } int _fd_bound_value() { assert(_fd_bound != NULL); return _fd_bound->value; } bool _fd_bound_check_set(_fd_store store) { int value; assert(_fd_bound != NULL); if (!_fd_bound->check(_fd_bound->constraint, store, &value)) return false; _fd_bound->value = value; return true; } bool _fd_bound_check(_fd_store store) { int value; assert(_fd_bound != NULL); return _fd_bound->check(_fd_bound->constraint, store, &value) || value == _fd_bound->value; } int _fd_better_solution(_fd_store s1, _fd_store s2) { assert(_fd_bound != NULL); return _fd_bound->compare(_fd_bound->constraint, s1, s2) < 0; } fd_int _fd_bound_variable() { assert(_fd_bound != NULL); return _fd_variables[_fd_bound->variable]; } /* Bound the optimisation variable and propagate the change. */ int fd__bound_and_revise() { assert(_fd_bound != NULL); if (_fd_bound->bound(_fd_bound->constraint, _fd_bound_value())) { if (fd_domain_empty(_fd_bound_variable())) return FD_NOSOLUTION; if (_fd_revise_wrt_variable(_fd_bound_variable()) == FD_NOSOLUTION) { #ifdef CONSTRAINT_TEMPS fd__constraint_data_reset(); #endif return FD_NOSOLUTION; } } return FD_OK; }