/* Function to randomly initialize a PGA_DATATYPE_CHARACTER string using * all printable ASCII characters for the range. */ void N_InitString(PGAContext *ctx, int p, int pop) { int i; for(i=PGAGetStringLength(ctx)-1; i>=0; i--) PGASetCharacterAllele(ctx, p, pop, i, PGARandomInterval(ctx, 32, 126)); }
/* Function to print a string. Since fortran does NOT support * C file handles, we just print normally. If we we're in C, * we would print to the file "file". */ void N_PrintString(PGAContext *ctx, FILE *file, int p, int pop) { int i; char string[71]; for (i=PGAGetStringLength(ctx)-1; i>=0; i--) string[i] = PGAGetCharacterAllele(ctx, p, pop, i); string[70] = 0; fprintf(file," :%s:\n", string); }
/* After each generation, this routine is called. What is done here, * is to print the best string in our own format, then check if the * best string is close to the correct value. If it is, duplicate * checking is tunred off. This is critical, as the mutation operator * will not degrade a string, so when the strings get near the correct * solution, they all become duplicates, but none can be changed! * * Other applications have done such things as send the best string * to another process to be visualized. For here, we just call our * print string function to print the best string. */ void N_EndOfGen(PGAContext *ctx) { int best; best = PGAGetBestIndex(ctx, PGA_NEWPOP); N_PrintString(ctx, stdout, best, PGA_NEWPOP); if (PGAGetEvaluation(ctx, best, PGA_NEWPOP) >= PGAGetStringLength(ctx)-10) PGASetNoDuplicatesFlag(ctx, PGA_FALSE); }
/* Evaluate the string. A highly fit string will have many of * the characters matching Name. */ double EvalName(PGAContext *ctx, int p, int pop) { int i, count; count = 0; for (i=PGAGetStringLength(ctx)-1; i>=0; i--) { if (PGAGetCharacterAllele(ctx, p, pop, i) == Name[i]) count++; } return((double)count); }
/******************************************************************* * user defined evaluation function * * ctx - contex variable * * p - chromosome index in population * * pop - which population to refer to * *******************************************************************/ double NumberOfSetBits(PGAContext *ctx, int p, int pop) { int i, nbits, stringlen; stringlen = PGAGetStringLength(ctx); nbits = 0; for ( i=0; i<stringlen; i++ ) if ( PGAGetBinaryAllele(ctx, p, pop, i) ) nbits++; return((double) nbits); }
/* Function to check "doneness" of the GA. We check the iteration * count (by calling PGACheckStoppingConditions), then check if we have found * the string yet. */ int N_StopCond(PGAContext *ctx) { int done, best; done = PGACheckStoppingConditions(ctx); best = PGAGetBestIndex(ctx, PGA_OLDPOP); if ((done == PGA_FALSE) && (PGAGetEvaluation(ctx, best, PGA_OLDPOP) == PGAGetStringLength(ctx))) done = PGA_TRUE; return(done); }
/* Function to muatate a PGA_DATATYPE_CHARACTER string. This is done * by simply picking allele locations and replacing whatever was there. * Again, legal values are all printable ASCII characters. */ int N_Mutation(PGAContext *ctx, int p, int pop, double mr) { int i, count; count = 0; for(i=PGAGetStringLength(ctx)-1; i>=0; i--) if (PGAGetCharacterAllele(ctx, p, pop, i) != Name[i]) { if (PGARandomFlip(ctx, mr) == PGA_TRUE) { PGASetCharacterAllele(ctx, p, pop, i, PGARandomInterval(ctx, 32, 126)); count++; } } return(count); }
/* Function to compare two strings. Strings are "equalivalent" * if they match Name at the same alleles (and, thus, disagree at the * same alleles). We don't care what the disagreement is, just that * it is there. * * NOTE that because it is possible to get stuck in an infinite * loop while doing duplicate checking on this string (assuming that * the mutation operator is always beneficial), we ALWAYS return PGA_FALSE. * The code is left as an example (and for testing). */ int N_Duplicate(PGAContext *ctx, int p1, int pop1, int p2, int pop2) { int i, match; char a, b, c; match = PGA_TRUE; for (i=PGAGetStringLength(ctx)-1; match && i>=0; i--) { a = PGAGetCharacterAllele(ctx, p1, pop1, i); b = PGAGetCharacterAllele(ctx, p2, pop2, i); c = Name[i]; if (((a == c) && (b != c)) || ((a != c) && (b == c))) match = PGA_FALSE; } return(match); }
/* Function to crossover two name strings. Quite an interesting * crossover, too. Works like a normal uniform crossover, except * that, if one of the strings matches the correct value, we set * BOTH children to the correct value 50% of the time. */ void N_Crossover(PGAContext *ctx, int p1, int p2, int pop1, int c1, int c2, int pop2) { int i, length; char a, b; length = PGAGetStringLength(ctx); for (i=0; i<length; i++) { a = PGAGetCharacterAllele(ctx, p1, pop1, i); b = PGAGetCharacterAllele(ctx, p2, pop1, i); if ((a == Name[i]) || (b == Name[i])) a = b = Name[i]; if (PGARandomFlip(ctx, 0.5) == PGA_TRUE) { PGASetCharacterAllele(ctx, c1, pop2, i, a); PGASetCharacterAllele(ctx, c2, pop2, i, b); } else { PGASetCharacterAllele(ctx, c1, pop2, i, b); PGASetCharacterAllele(ctx, c2, pop2, i, a); } } }
/*U**************************************************************************** PGASetRealInitPercent - sets the upper and lower bounds for randomly initializing real-valued genes. For each gene these bounds define an interval from which the initial allele value is selected uniformly randomly. With this routine the user specifies a median value and a percent offset for each allele. Category: Initialization Inputs: ctx - context variable median - an array containing the mean value of the interval percent - an array containing the percent offset to add and subtract to the median to define the interval Outputs: Example: Set the initialization routines to select a value for each real-valued gene i uniformly randomly from the interval [i-v,i+v], where $v = i/2$. Assumes all strings are the same length. PGAContext *ctx; double *median, *percent; int i, stringlen; : stringlen = PGAGetStringLength(ctx); median = (double *) malloc(stringlen*sizeof(double)); percent = (double *) malloc(stringlen*sizeof(double)); for(i=0;i<stringlen;i++) { median[i] = (double) i; percent[i] = 0.5; } PGASetRealInitPercent(ctx, median, percent); ****************************************************************************U*/ void PGASetRealInitPercent ( PGAContext *ctx, double *median, double *percent) { int i; int stringlen; double offset; PGADebugEntered("PGASetRealInitPercent"); PGAFailIfSetUp("PGASetRealInitPercent"); PGACheckDataType("PGASetRealInitPercent", PGA_DATATYPE_REAL); stringlen = PGAGetStringLength(ctx); for (i=0; i<stringlen; i++) { offset = fabs(median[i] * percent[i]); ctx->init.RealMin[i] = median[i] - offset; ctx->init.RealMax[i] = median[i] + offset; } ctx->init.RealType = PGA_RINIT_PERCENT; PGADebugExited("PGASetRealInitPercent"); }