costas.c 2.74 KB
#include <stdio.h>
#include <stdlib.h>

//#include <fcntl.h>
//#include <errno.h>
#include <ctype.h>
#include <string.h>

#include <paccs.h>

/*
  Costas arrays (communicated by Daniel Diaz)
 */

#define diffs(a, b) diffs[(a) * (N - 1) + (b)]

int main(int argc, char *argv[])
{
  int solutions = 0, one_solution = 1;
  int use_label = 0;
  int i, j;

  int verbose = 0;
  fd_int *array, *diffs;
  int N = 10;
  int coeffs[] = { 1, 1, -1 };
  fd_int diffeq[3];
  int k;

  fd_init(&argc, &argv);

  for (i = 1; i < argc; ++i)
    if (!strcmp(argv[i], "--all"))
      one_solution = 0;
    else if (!strcmp(argv[i], "--label"))
      use_label = 1;
    else if (!strncmp(argv[i], "-v", 2))
      {
	char *s = argv[i] + 1;

	while (*s++ == 'v')
	  verbose++;
      }
    else if (isdigit(*argv[i]))
      {
	N = atoi(argv[i]);

	i++;

	break;
      }
    else
      fd__error("%s: unknown option `%s'\n", argv[0], argv[i]);

  array = calloc(N, sizeof(*array));

  for (j = 0; i < argc; ++j, ++i)
    {
      int a, b;

      a = b = atoi(argv[i]);
      if (strchr(argv[i], '-'))
	b = atoi(strchr(argv[i], '-') + 1);

      array[j] = fd_new(a - 1, b - 1);
    }

  for (; j < N; ++j)
    array[j] = fd_new(0, N - 1);

  fd_all_different(array, N);

  if (use_label)
    fd_label(array, N);

  // differences:
  //   0 <= array[] < N
  //     ->  -(N-1) <= array[i] - array[j] <= N-1
  //     ->  0 <= array[i] - array[j] + N-1 <= 2*(N-1)

  diffs = calloc((N - 2) * (N - 1), sizeof(*diffs));

  for (i = 0; i < N - 2; ++i)
    for (j = 0; j < N - 1 - i; ++j)
      diffs(i, j) = fd_new(0, 2 * (N - 1));

  diffeq[0] = fd_const(N - 1);

  for (k = 1; k < N - 1; ++k)
    {
      for (i = k; i < N; ++i)
	{
	  diffeq[1] = array[i];
	  diffeq[2] = array[i - k];

	  fd_poly_eq(coeffs, diffeq, 3, diffs(k - 1, i - k));

	  if (verbose >= 2)
	    printf("x[%d] - x[%d] -> (%d,%d)\n", i, i-k, k-1, i-k);
	}

      fd_all_different(&diffs(k - 1, 0), N - k);
    }

  while (fd_solve() == FD_OK)
    {
      printf("solution %d:\n", ++solutions);

      for (i = 0; i < N; ++i)
	{
	  printf("%d", fd_var_value(array[i]) + 1);

	  if (i != N - 1)
	    putchar(' ');
	}
      putchar('\n');

      if (verbose >= 1)
	for (k = 1; k < N - 1; ++k)
	  {
	    printf("%*s", k, "");

	    for (i = k; i < N; ++i)
	      printf("%d ", fd_var_value(diffs(k - 1, i - k)) - (N - 1));
	    putchar('\n');
	  }

#if !(defined(LOCAL_SEARCH) || defined(DISTRIBUTED_SOLVER))
      if (one_solution)
#endif
	break;
    }

  fd_end();

  {
    // avoid failure messages from mpirun
    extern int _fd_counting_solutions;	// XXX: private variable

    if (_fd_counting_solutions)
      return 0;
  }

  if (solutions)
    printf("%d solutions found\n", solutions);
  else
    printf("inconsistent CSP\n");

  return !solutions;
}