#include "pgapack.h"
#ifndef M_PI
#define M_PI        3.14159265358979323846
#endif
double rastrigin(PGAContext *, int, int);
int myMutation(PGAContext *, int, int, double);

int main(int argc, char **argv)
{
     PGAContext *ctx;
     int maxiter, len;
     double lower[20] = { -5.12, -5.12, -5.12, -5.12, -5.12, -5.12, -5.12,
			       -5.12, -5.12, -5.12, -5.12, -5.12, -5.12, -5.12,
			       -5.12, -5.12, -5.12, -5.12, -5.12, -5.12 };
     double upper[20] = { 5.11, 5.11, 5.11, 5.11, 5.11, 5.11, 5.11, 5.11, 5.11,
			       5.11, 5.11, 5.11, 5.11, 5.11, 5.11, 5.11, 5.11,
			       5.11, 5.11, 5.11 };

     printf("What string length? ");
     scanf("%d", &len);
     printf("How many iterations: ");
     scanf("%d", &maxiter);
     ctx = PGACreate(&argc, argv, PGA_DATATYPE_REAL, len, PGA_MINIMIZE);
     PGASetRealInitLU(ctx, lower, upper);
     PGASetRandomSeed(ctx, 1);
     PGASetMaxIter(ctx, maxiter);
     PGASetUserFunction(ctx, PGA_USERFUNCTION_MUTATION, (void *)myMutation);
     PGASetUp(ctx);
     PGARun(ctx, rastrigin);
     PGADestroy(ctx);
     return 0;
}

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

     stringlen = PGAGetStringLen(ctx);
     for (i = 0; i < stringlen; i++)
     {
	  term = PGAGetRealAllele(ctx, p, pop, i);
	  sum += (term * term - 10 * cos(2 * M_PI * term));
     }
     return (stringlen * 10 + sum);
}

int myMutation(PGAContext *ctx, int p, int pop, double mr)
{
     int stringlen, i, count = 0;
     double k;

     stringlen = PGAGetStringLen(ctx);
     for (i = 0; i < stringlen; i++)
          if (PGARandomFlip(ctx, mr))
          {
               k = PGARandomUniform(ctx, -5.12, 5.11);
               PGASetRealAllele(ctx, p, pop, i, k);
               count++;
          }

     return ((double) count);
}
