#include "pgapack.h"

#ifndef M_PI
#define M_PI        3.14159265358979323846
#endif
double rastrigin(PGAContext *, int, int);
double (*g)(PGAContext *, int, int, int, int, double, double);
void   printResultInterpretation(PGAContext *);

int main(int argc, char **argv)
{
     PGAContext *ctx;
     char useGray;
     int maxiter, len;

     printf("Do you want to use Gray-coding (y/n)? ");
     scanf("%c", &useGray);
     if (useGray == 'y')
     {
	  printf("Graycoding in use . . .\n");
	  g = PGAGetRealFromGrayCode;
     }
     else
     {
	  printf("Graycoding not in use . . .\n");
	  g = PGAGetRealFromBinary;
     }
     printf("What string length? ");
     scanf("%d", &len);
     printf("How many iterations? ");
     scanf("%d", &maxiter);
     ctx = PGACreate(&argc, argv, PGA_DATATYPE_BINARY, 10 * len, PGA_MINIMIZE);
     PGASetRandomSeed(ctx, 1);
     PGASetMaxIter(ctx, maxiter);
     PGASetUp(ctx);
     PGARun(ctx, rastrigin);
     printResultInterpretation(ctx);
     PGADestroy(ctx);
     return (0);
}

double rastrigin(PGAContext *ctx, int p, int pop)
{
     int i, stringlen, len;
     double term, sum;

     sum = 0;
     stringlen = PGAGetStringLen(ctx);
     len = stringlen / 10;
     for (i = 0; i < len; i++)
     {
	  term = (*g)(ctx, p, pop, i * 10, i * 10 + 9, -5.12, 5.11);
	  sum += (term * term - 10 * cos(2 * M_PI * term));
     }
     return (stringlen + sum);
}     

void printResultInterpretation(PGAContext *ctx)
{
     int best, i, stringlen, len;
     double *string;

     best = PGAGetBest(ctx, PGA_OLDPOP);
     len = (stringlen = PGAGetStringLen(ctx)) / 10;
     if (!(string = (double *)malloc(len * sizeof(double))))
     {
	  fprintf(stderr, "No room for string.\n");
	  exit(1);
     }
     printf("The real interpretation:\n");
     for (i = 0; i < len; i++)
     {
	  string[i] = (*g)(ctx, best, PGA_OLDPOP, i * 10, i * 10 + 9, -5.12,
			   5.11);
	  switch ( i % 5 )
	  {
	  case 0:
	       printf ("#%4d: [%11.7g]",i,string[i]);
	       break;
	  case 1:
	  case 2:
	  case 3:
	       printf (", [%11.7g]",string[i]);
	       break;
	  case 4:
	       printf (", [%11.7g]",string[i]);
	       if (i+1 < len)
		    printf ("\n");
	       break;
	  }
     }
     printf("\n");
}
