constraints.c 6.89 KB
#include <stdlib.h>

#include <assert.h>

#include "fdc_int.h"
#include "values.h"
#include "variables.h"
#include "constraints.h"

#include "util.h"

#define MAX_CONSTRAINTS (512 * 512)

int _fd_constraint_count = 0;
fd_constraint _fd_constraints[MAX_CONSTRAINTS];


#define CONSTRAINT_INITIALISATION(name, code) \
  static void fd_ ## name ## _init(_fd_constraint_class data[]) \
  { \
    data[code].propagator2 = fd_ ## name ## _propagate2; \
    data[code].filter = fd_ ## name ## _filter; \
  }

#define initialise_constraint(name) fd_ ## name ## _init(_fd_constraint_data)


#ifdef CONSTRAINTS_HAVE_STATE
#define CSTR_DATA_VALID	0x01
#define CSTR_ENTAILED	0x02

static __thread uint8_t constraint_state_info[MAX_CONSTRAINTS];
#  ifdef CONSTRAINT_TEMPS
static __thread void *constraint_memory[MAX_CONSTRAINTS];
#  endif
#endif /* CONSTRAINTS_HAVE_STATE */

/* generic functions */

fd_constraint fd__constraint_new(int nvariables, int nconstants)
{
  fd_constraint c;

  if (_fd_constraint_count == MAX_CONSTRAINTS)
    fd__fatal("too many constraints, increase MAX_CONSTRAINTS");

  if (c = malloc(sizeof(struct fd_constraint)))
    {
#if defined(CONSTRAINT_TEMPS) || !defined(DISABLE_ENTAILED)
      c->index = _fd_constraint_count;
#endif
      c->variables = calloc(nvariables, sizeof(C_VAR_T)); // XXX: check for NULL
      c->nvariables = nvariables;
      if (nconstants)
	c->constants = calloc(nconstants, sizeof(int));  // XXX: check for NULL
      else
	c->constants = 0;
      c->nconstants = nconstants;
      c->kind = -1;	// XXX

      _fd_constraints[_fd_constraint_count++] = c;
    }

  return c;
}

int _fd_undefined()
{
  fd__fatal("called an undefined function");
}

#ifdef DISTRIBUTED_SOLVER

/* create a copy of CONSTRAINT that uses VARIABLES */
// XXX: no longer needed!?
fd_constraint _fd_constraint_adapt(fd_constraint constraint, fd_int variables[])
{
  return constraint;
}

/* import constraints into VARIABLES (XXX: description!) */
// XXX: no longer needed!?
void _fd_import_constraints(fd_int variables[])
{
}

#endif /* DISTRIBUTED_SOLVER */


#ifdef CONSTRAINTS_HAVE_STATE
#include <string.h>

void fd__constraint_data_reset(void)
{
  memset(constraint_state_info, 0,
	 _fd_constraint_count * sizeof(*constraint_state_info));
}
#endif /* CONSTRAINTS_HAVE_STATE */

#ifdef CONSTRAINT_TEMPS
int fd__constraint_data_valid(fd_constraint constraint)
{
  return constraint_state_info[constraint->index] & CSTR_DATA_VALID;
}

void fd__constraint_remember(fd_constraint constraint)
{
  constraint_state_info[constraint->index] |= CSTR_DATA_VALID;
}

void fd__constraint_free_memory(void)
{
  int i;

  for (i = 0; i < _fd_constraint_count; ++i)
    if (constraint_memory[i])
      free(constraint_memory[i]);
}
#endif /* CONSTRAINT_TEMPS */

#ifndef DISABLE_ENTAILED
void fd__constraint_set_entailed(fd_constraint constraint)
{
  constraint_state_info[constraint->index] |= CSTR_ENTAILED;
}

int fd__constraint_entailed(fd_constraint constraint)
{
  return constraint_state_info[constraint->index] & CSTR_ENTAILED;
}
#else /* DISABLE_ENTAILED */
#define fd__constraint_set_entailed(_) ((void) 0)
#endif /* DISABLE_ENTAILED */


/* Import the constraints' code. */

#include <constraints/lt.c>
#include <constraints/le.c>
#include <constraints/gt.c>
#include <constraints/ge.c>
#include <constraints/ne.c>
#include <constraints/eq.c>
#include <constraints/all-different.c>
#include <constraints/minus-ne.c>
#include <constraints/plus-gt.c>
#include <constraints/exactly-one.c>
#include <constraints/minus-eq.c>
#include <constraints/fake-all-different.c>
#include <constraints/nogoods.c>
#include <constraints/var-eq-minus.c>
#include <constraints/exactly.c>
#include <constraints/exactly-var.c>
#include <constraints/sum.c>
#include <constraints/var-eq-times.c>
#include <constraints/sum-prod.c>
#include <constraints/element.c>
#include <constraints/knapsack2.c>
#include <constraints/sum2.c>
#include <constraints/min.c>
#include <constraints/max.c>
#include <constraints/poly-eq.c>
#include <constraints/element-var.c>
#include <constraints/exactly-vars.c>
#include <constraints/poly-eq-k.c>
#include <constraints/poly-ne.c>
#include <constraints/poly-ne-k.c>
#include <constraints/poly-le-k.c>


_fd_constraint_class _fd_constraint_data[FD_CONSTR_KINDS];


/* Define the constraints' initialisation functions. */

CONSTRAINT_INITIALISATION(ne, FD_CONSTR_NE)
CONSTRAINT_INITIALISATION(eq, FD_CONSTR_EQ)
CONSTRAINT_INITIALISATION(lt, FD_CONSTR_LT)
CONSTRAINT_INITIALISATION(le, FD_CONSTR_LE)
CONSTRAINT_INITIALISATION(minus_ne, FD_CONSTR_MINUS_NE)
CONSTRAINT_INITIALISATION(minus_eq, FD_CONSTR_MINUS_EQ)
// CONSTRAINT_INITIALISATION(plus_gt, FD_CONSTR_PLUS_GT)
CONSTRAINT_INITIALISATION(var_eq_minus, FD_CONSTR_VAR_EQ_MINUS)
CONSTRAINT_INITIALISATION(all_different, FD_CONSTR_ALL_DIFFERENT)
// CONSTRAINT_INITIALISATION(exactly_one, FD_CONSTR_EXACTLY_ONE)
// CONSTRAINT_INITIALISATION(nogoods, FD_CONSTR_NOGOODS)
CONSTRAINT_INITIALISATION(exactly, FD_CONSTR_EXACTLY)
CONSTRAINT_INITIALISATION(exactly_var, FD_CONSTR_EXACTLY_VAR)
CONSTRAINT_INITIALISATION(sum, FD_CONSTR_SUM)
CONSTRAINT_INITIALISATION(var_eq_times, FD_CONSTR_VAR_EQ_TIMES)
CONSTRAINT_INITIALISATION(sum_prod, FD_CONSTR_SUM_PROD)
CONSTRAINT_INITIALISATION(element, FD_CONSTR_ELEMENT)
CONSTRAINT_INITIALISATION(knapsack2, FD_CONSTR_KNAPSACK2)
CONSTRAINT_INITIALISATION(sum2, FD_CONSTR_SUM2)
CONSTRAINT_INITIALISATION(min, FD_CONSTR_MIN)
CONSTRAINT_INITIALISATION(max, FD_CONSTR_MAX)
CONSTRAINT_INITIALISATION(poly_eq, FD_CONSTR_POLY_EQ)
CONSTRAINT_INITIALISATION(element_var, FD_CONSTR_ELEMENT_VAR)
CONSTRAINT_INITIALISATION(exactly_vars, FD_CONSTR_EXACTLY_VARS)
CONSTRAINT_INITIALISATION(poly_eq_k, FD_CONSTR_POLY_EQ_K)
CONSTRAINT_INITIALISATION(poly_ne, FD_CONSTR_POLY_NE)
CONSTRAINT_INITIALISATION(poly_ne_k, FD_CONSTR_POLY_NE_K)
CONSTRAINT_INITIALISATION(poly_le_k, FD_CONSTR_POLY_LE_K)

/* Initialises the constraints. */
void fd__init_constraints()
{
  static int done = 0;

  if (done)
    return;

  memset(_fd_constraint_data, 0, sizeof(_fd_constraint_data)); // XXX?

  initialise_constraint(ne);
  initialise_constraint(eq);
  initialise_constraint(lt);
  initialise_constraint(le);
  initialise_constraint(minus_ne);
  initialise_constraint(minus_eq);
//  initialise_constraint(plus_gt);
  initialise_constraint(var_eq_minus);
  initialise_constraint(all_different);
//  initialise_constraint(exactly_one);
//  initialise_constraint(nogoods);
  initialise_constraint(exactly);
  initialise_constraint(exactly_var);
  initialise_constraint(sum);
  initialise_constraint(var_eq_times);
  initialise_constraint(sum_prod);
  initialise_constraint(element);
  initialise_constraint(knapsack2);
  initialise_constraint(sum2);
  initialise_constraint(min);
  initialise_constraint(max);
  initialise_constraint(poly_eq);
  initialise_constraint(element_var);
  initialise_constraint(exactly_vars);
  initialise_constraint(poly_eq_k);
  initialise_constraint(poly_ne);
  initialise_constraint(poly_ne_k);
  initialise_constraint(poly_le_k);

  done = 1;
}