fdc_int.h 7.11 KB
#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 <bits/wordsize.h> // XXX: to get __WORDSIZE; non portable?
#endif

#include <stdbool.h>
#include <stdint.h>


/* 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 */