source: branches/uq/packages/optimizer/src/pgapack/pgapack/examples/c/namefull.c @ 5679

Last change on this file since 5679 was 5679, checked in by ldelgass, 9 years ago

Full merge 1.3 branch to uq branch to sync. Fixed partial subdirectory merge
by removing mergeinfo from lang/python/Rappture directory.

  • Property svn:eol-style set to native
File size: 7.6 KB
Line 
1/*  PGAPack test program.
2 *
3 *  The objective is to evolve a string of characters to match a string
4 *  supplied by the user.  We will stop evolving when either we run out
5 *  of iterations (500), or when the best string has the same evaluation
6 *  value for 100 generations.
7 *
8 *  One problem with this implementation is that ' ' is not in
9 *  PGA_DATATYPE_CHAR if we limit it using PGA_CINIT_MIXED, PGA_CINIT_LOWER,
10 *  or PGA_CINIT_UPPER.  To fix this, we must define our own interval, and
11 *  thus, our own mutation, initialization operators.
12 *
13 *  A user function is also used to check the "done" condition; we are
14 *  done if we've done more than 1000 iterations, or the evolved string
15 *  is correct.
16 *
17 *  Created 28 Sep 95, Brian P. Walenz.  Thanks to Dan Ashlock for the idea.
18 *
19 *  Be warned that duplicate checking will sometimes go into an infinite
20 *  loop.
21 */
22
23#include "pgapack.h"
24
25void   N_InitString (PGAContext *, int, int);
26int    N_Mutation   (PGAContext *, int, int, double);
27int    N_StopCond   (PGAContext *);
28void   N_Crossover  (PGAContext *ctx, int, int, int, int, int, int);
29int    N_Duplicate  (PGAContext *, int, int, int, int);
30void   N_PrintString(PGAContext *, FILE *, int, int);
31void   N_EndOfGen   (PGAContext *);
32double EvalName     (PGAContext *, int, int);
33void   GetStringParameter(char *, char *);
34
35/*  Global, because we use it in EvalName.  */
36char   Name[70];
37
38void main(int argc, char **argv) {
39    PGAContext *ctx;
40
41    MPI_Init(&argc, &argv);
42
43    /*  Rather than deal with standard io and strings, we'll just set
44     *  this explicitly.
45     */
46    strcpy(Name, "David M. Levine, Philip L. Hallstrom, David M. Noelle, "
47                 "Brian P. Walenz");
48
49    ctx = PGACreate(&argc, argv, PGA_DATATYPE_CHARACTER, strlen(Name),
50                    PGA_MAXIMIZE);
51   
52    PGASetRandomSeed(ctx, 42);
53   
54    PGASetUserFunction(ctx, PGA_USERFUNCTION_INITSTRING, (void *)N_InitString);
55    PGASetUserFunction(ctx, PGA_USERFUNCTION_MUTATION,   (void *)N_Mutation);
56    PGASetUserFunction(ctx, PGA_USERFUNCTION_CROSSOVER,  (void *)N_Crossover);
57    PGASetUserFunction(ctx, PGA_USERFUNCTION_DUPLICATE,  (void *)N_Duplicate);
58    PGASetUserFunction(ctx, PGA_USERFUNCTION_STOPCOND,   (void *)N_StopCond);
59    PGASetUserFunction(ctx, PGA_USERFUNCTION_PRINTSTRING,(void *)N_PrintString);
60    PGASetUserFunction(ctx, PGA_USERFUNCTION_ENDOFGEN,   (void *)N_EndOfGen);
61
62    /*  We don't want to report anything.  */
63    PGASetPrintFrequencyValue(ctx, 10000);
64    PGASetPopSize(ctx, 100);
65    PGASetNumReplaceValue(ctx, 90);
66    PGASetPopReplaceType(ctx, PGA_POPREPL_BEST);
67    PGASetNoDuplicatesFlag(ctx, PGA_TRUE);
68    PGASetMaxGAIterValue(ctx, 100);
69   
70    PGASetUp(ctx);
71    PGARun(ctx, EvalName);
72    PGADestroy(ctx);
73
74    MPI_Finalize();
75}
76
77
78/*  Function to randomly initialize a PGA_DATATYPE_CHARACTER string using
79 *  all printable ASCII characters for the range.
80 */
81void N_InitString(PGAContext *ctx, int p, int pop) {
82    int               i;
83   
84    for(i=PGAGetStringLength(ctx)-1; i>=0; i--)
85        PGASetCharacterAllele(ctx, p, pop, i,
86                              PGARandomInterval(ctx, 32, 126));
87}
88
89
90
91/*  Function to crossover two name strings.  Quite an interesting
92 *  crossover, too.  Works like a normal uniform crossover, except
93 *  that, if one of the strings matches the correct value, we set
94 *  BOTH children to the correct value 50% of the time.
95 */
96void N_Crossover(PGAContext *ctx, int p1, int p2, int pop1, int c1,
97                 int c2, int pop2) {
98    int           i, length;
99    char          a, b;
100           
101    length = PGAGetStringLength(ctx);
102
103    for (i=0; i<length; i++) {
104        a = PGAGetCharacterAllele(ctx, p1, pop1, i);
105        b = PGAGetCharacterAllele(ctx, p2, pop1, i);
106        if ((a == Name[i]) || (b == Name[i]))
107            a = b = Name[i];
108
109        if (PGARandomFlip(ctx, 0.5) == PGA_TRUE) {
110            PGASetCharacterAllele(ctx, c1, pop2, i, a);
111            PGASetCharacterAllele(ctx, c2, pop2, i, b);
112        } else {
113            PGASetCharacterAllele(ctx, c1, pop2, i, b);
114            PGASetCharacterAllele(ctx, c2, pop2, i, a);
115        }
116    }
117}
118
119
120
121/*  Function to compare two strings.  Strings are "equalivalent"
122 *  if they match Name at the same alleles (and, thus, disagree at the
123 *  same alleles).  We don't care what the disagreement is, just that
124 *  it is there.
125 *
126 *  NOTE that because it is possible to get stuck in an infinite
127 *  loop while doing duplicate checking on this string (assuming that
128 *  the mutation operator is always beneficial), we ALWAYS return PGA_FALSE.
129 *  The code is left as an example (and for testing).
130 */
131int N_Duplicate(PGAContext *ctx, int p1, int pop1, int p2, int pop2) {
132    int          i, match;
133    char         a, b, c;
134   
135    match = PGA_TRUE;
136
137    for (i=PGAGetStringLength(ctx)-1; match && i>=0; i--) {
138        a = PGAGetCharacterAllele(ctx, p1, pop1, i);
139        b = PGAGetCharacterAllele(ctx, p2, pop2, i);
140        c = Name[i];
141        if (((a == c) && (b != c)) || ((a != c) && (b == c)))
142            match = PGA_FALSE;
143    }
144
145    return(match);
146}
147
148
149/*  Function to muatate a PGA_DATATYPE_CHARACTER string.  This is done
150 *  by simply picking allele locations and replacing whatever was there.
151 *  Again, legal values are all printable ASCII characters.
152 */
153int N_Mutation(PGAContext *ctx, int p, int pop, double mr) {
154    int               i, count;
155
156    count = 0;
157    for(i=PGAGetStringLength(ctx)-1; i>=0; i--)
158        if (PGAGetCharacterAllele(ctx, p, pop, i) != Name[i]) {
159            if (PGARandomFlip(ctx, mr) == PGA_TRUE) {
160                PGASetCharacterAllele(ctx, p, pop, i,
161                                      PGARandomInterval(ctx, 32, 126));
162                count++;
163            }
164        }
165    return(count);
166}
167
168
169/*  Function to print a string.  Since fortran does NOT support
170 *  C file handles, we just print normally.  If we we're in C,
171 *  we would print to the file "file".
172 */
173void N_PrintString(PGAContext *ctx, FILE *file, int p, int pop) {
174    int          i;
175    char         string[71];
176
177    for (i=PGAGetStringLength(ctx)-1; i>=0; i--)
178        string[i] = PGAGetCharacterAllele(ctx, p, pop, i);
179    string[70] = 0;
180
181    fprintf(file," :%s:\n", string);
182}
183
184
185/*  Function to check "doneness" of the GA.  We check the iteration
186 *  count (by calling PGACheckStoppingConditions), then check if we have found
187 *  the string yet.
188 */
189int N_StopCond(PGAContext *ctx) {
190    int   done, best;
191
192    done = PGACheckStoppingConditions(ctx);
193
194    best = PGAGetBestIndex(ctx, PGA_OLDPOP);
195    if ((done == PGA_FALSE) &&
196        (PGAGetEvaluation(ctx, best, PGA_OLDPOP) ==
197         PGAGetStringLength(ctx)))
198        done = PGA_TRUE;
199
200    return(done);
201}
202
203
204
205/*  After each generation, this routine is called.  What is done here,
206 *  is to print the best string in our own format, then check if the
207 *  best string is close to the correct value.  If it is, duplicate
208 *  checking is tunred off.  This is critical, as the mutation operator
209 *  will not degrade a string, so when the strings get near the correct
210 *  solution, they all become duplicates, but none can be changed!
211 *
212 *  Other applications have done such things as send the best string
213 *  to another process to be visualized.  For here, we just call our
214 *  print string function to print the best string.
215 */
216void N_EndOfGen(PGAContext *ctx) {
217    int best;
218
219    best = PGAGetBestIndex(ctx, PGA_NEWPOP);
220    N_PrintString(ctx, stdout, best, PGA_NEWPOP);
221
222    if (PGAGetEvaluation(ctx, best, PGA_NEWPOP) >=
223        PGAGetStringLength(ctx)-10)
224        PGASetNoDuplicatesFlag(ctx, PGA_FALSE);
225}
226
227   
228/*  Evaluate the string.  A highly fit string will have many of
229 *  the characters matching Name.
230 */
231double EvalName(PGAContext *ctx, int p, int pop) {
232    int     i, count;
233   
234    count = 0;
235    for (i=PGAGetStringLength(ctx)-1; i>=0; i--) {
236        if (PGAGetCharacterAllele(ctx, p, pop, i) == Name[i])
237            count++;
238    }
239   
240    return((double)count);
241}
242
Note: See TracBrowser for help on using the repository browser.