bound.c 2.42 KB
#include <stdio.h>
#include <stdlib.h>

#include <assert.h>

#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;
}