#ifdef FAKE_ALLDIFF #warning "-DFAKE_ALLDIFF deprecated, use the fake-all-different constraint instead" #endif #include "config.h" #include "misc.h" #ifdef HAVE_WORDSIZE_H #include // XXX: to get __WORDSIZE; non portable? #endif #include #include /* internal definitions for fdc solver */ typedef struct fd_int *fd_int; #ifdef INLINE_DOMAINS # define COMPACT_DOMAINS 1 #endif #ifdef COMPACT_DOMAINS # ifndef DOMAIN_BITS # ifdef __SIZEOF_LONG_LONG__ # define DOMAIN_BITS (__SIZEOF_LONG_LONG__ << 3) # else # define DOMAIN_BITS (__SIZEOF_LONG__ << 3) # endif # endif /* _fd_bitmap is the native integral type used for the bitmaps */ # ifndef UNIT_BITS # if DOMAIN_BITS <= (__SIZEOF_INT__ << 3) # define UNIT_BITS (__SIZEOF_INT__ << 3) # elif DOMAIN_BITS == (__SIZEOF_LONG__ << 3) # define UNIT_BITS (__SIZEOF_LONG__ << 3) # elif DOMAIN_BITS == (__SIZEOF_LONG_LONG__ << 3) # define UNIT_BITS (__SIZEOF_LONG_LONG__ << 3) # else # define UNIT_BITS (__SIZEOF_LONG__ << 3) # endif # endif # if UNIT_BITS == (__SIZEOF_INT__ << 3) typedef unsigned int _fd_bitmap; # elif UNIT_BITS == (__SIZEOF_LONG__ << 3) typedef unsigned long _fd_bitmap; # elif UNIT_BITS == (__SIZEOF_LONG_LONG__ << 3) typedef unsigned long long _fd_bitmap; # else # error "invalid UNIT_BITS definition" # endif # if defined(INLINE_DOMAINS) && DOMAIN_BITS > UNIT_BITS # error "can't have INLINE_DOMAINS with those bits" # endif # define DOMAIN_MAP_WORDS ((DOMAIN_BITS + UNIT_BITS - 1) / UNIT_BITS) # ifdef DOMAIN_BOUNDS # define DOMAIN_WORDS (DOMAIN_MAP_WORDS + 1) # else # define DOMAIN_WORDS DOMAIN_MAP_WORDS # endif # if DOMAIN_BITS != DOMAIN_MAP_WORDS * UNIT_BITS # error "DOMAIN_BITS is not a multiple of UNIT_BITS" # endif # if defined(INLINE_DOMAINS) && defined(DOMAIN_BOUNDS) # error "DOMAIN_BOUNDS won't work with INLINE_DOMAINS" # endif /* _fd_value_core represents the data part of a domain (and is what is kept in a store) */ # ifdef INLINE_DOMAINS typedef _fd_bitmap _fd_value_core; typedef _fd_bitmap fd_value; # else # ifndef DOMAIN_BOUNDS typedef _fd_bitmap _fd_value_core[DOMAIN_MAP_WORDS]; typedef _fd_value_core *fd_value; # else # if UNIT_BITS == 32 typedef uint16_t _fd_boundary; # else typedef uint32_t _fd_boundary; # endif typedef struct { _fd_bitmap map[DOMAIN_MAP_WORDS]; _fd_boundary min, max; } _fd_value_core; typedef _fd_value_core *fd_value; # endif # endif # ifdef INLINE_DOMAINS typedef _fd_bitmap *fd_iterator; # else typedef fd_value fd_iterator; # endif #else /* COMPACT_DOMAINS */ typedef struct fd_value *fd_value; typedef struct fd_value *_fd_value_core; typedef struct fd_iterator *fd_iterator; #endif /* COMPACT_DOMAINS */ typedef struct fd_constraint *fd_constraint; #define FD_OK 0 #define FD_NOSOLUTION 1 /* lists */ #include "list.h" /* values */ fd_value fd_new_value(int, int); #ifndef COMPACT_DOMAINS /* kinds of value */ typedef enum { FD_EMPTY, FD_SINGLETON, FD_MULTIPLE } fd_kind; struct fd_value { fd_kind kind; union { int value; struct { int lower, upper; } interval; } value; fd_value next; // points to values greater than this one }; #else /* COMPACT_DOMAINS */ // XXX: these are kind of fictitious #define MIN_VALUE 0 #define MAX_VALUE (DOMAIN_BITS - 1) #endif /* COMPACT_DOMAINS */ /* constraints */ // type for a constraint's variables #define C_VAR_T int #define VAR(c,v) _fd_variables[(c)->variables[v]] #define FD_INT2C_VAR(v) ((v)->index) struct fd_constraint { #ifdef CONSTRAINT_TEMPS int index; #endif C_VAR_T *variables; // variables involved in the constraint int nvariables; // number of variables int *constants; // constraint's constants (where applicable) int nconstants; // number of constants #ifdef CONSTRAINT_CLASS // _fd_constraint_kind kind; // what kind of constraint is this? int kind; // what kind of constraint is this? // XXX #else /* CONSTRAINT_CLASS */ int (*propagator2)(fd_constraint, fd_int); // how to propagate changes in a variable's // domain; 2nd argument is the variable // against which to revise the domains of // the other variables in the constraint; // returns 1 if some domain becomes empty int (*filter)(fd_constraint); // performs an initial filtering of the // domains of the constraint variables int (*propagator)(fd_constraint, fd_int); // how to propagate changes in a variable's // domain; 2nd argument is the variable to // revise (against the domains of every // other variable in the constraint); // returns 1 if some domain became empty #endif /* CONSTRAINT_CLASS */ }; #define fd_cvariable(c,v) ((c)->variables[v]) // XXX: not being used int _fd_undefined(); /* variables */ #define MAX_VARIABLES (64 * (1 << 10)) // variables' flags #define FD_INSTANTIATED 0x0001 // variable has been instantiated extern int fd_variables_count; extern __thread fd_int _fd_variables[]; fd_int fd_new(int, int); // type for the variable's constraints #define VAR_C_T int #ifdef USE_STORE # include "store.h" # ifdef INLINE_DOMAINS # define DOMAIN(v) store[(v)->index] # define DOMAIN_REF(v) (store + (v)->index) # define DOMAIN_REF_T(d) fd_value *d # else # define DOMAIN(v) (store + (v)->index) # define DOMAIN_REF DOMAIN # define DOMAIN_REF_T(d) fd_value d # endif #else /* USE_STORE */ # define DOMAIN(v) (v)->domain # ifdef INLINE_DOMAINS # define DOMAIN_REF(v) (&(v)->domain) # define DOMAIN_REF_T(d) fd_value *d # else # define DOMAIN_REF DOMAIN # define DOMAIN_REF_T(d) fd_value d # endif #endif /* USE_STORE */ struct fd_int { int index; // variable index within the state (XXX: needed?) #ifndef USE_STORE fd_value domain; #endif VAR_C_T *constraints; // constraints involving the variable int nconstraints; int nconnections; // number of variables sharing a constraint // (it this the degree of the variable?) int epoch; // epoch of the last change to the domain // (for backtracking) bool assigned; // has the variable been assigned during search? int flags; #ifdef USE_VALUE int value; // the value assigned to the variable #endif }; /* global variables */ extern int _fd_counting_solutions; // are we counting solutions? /* messages */ #if defined(DISTRIBUTED_SOLVER) #if !defined(SPLITGO) #error "SPLITGO must be defined" #endif #ifdef SPLITGO_MPI typedef enum { FD_MSG_STORE, FD_MSG_SOLUTION, FD_MSG_FEED_ME, FD_MSG_NO_WORK, FD_MSG_FAIL, FD_MSG_DONE, FD_MSG_SHARE, FD_MSG_NO_SHARE, FD_MSG_COUNT, FD_MSG_QUIT, FD_MSG_BOUND, FD_MSG_READY, FD_MSG_ANY, FD_MSG_NONE = -1 // not a valid message tag } _fd_message; #endif /* SPLITGO_MPI */ #endif /* DISTRIBUTED_SOLVER */ #ifdef FAST # define _fd_debug(...) ((void) 0) #endif /* FAST */