source: trunk/packages/optimizer/src/plugin_pgapack.c @ 1202

Last change on this file since 1202 was 1202, checked in by liveletlive, 16 years ago

Changes made to include the following items:
1) Hard restart
2) SBX
3) Random population replacement proportion
4) Definitions and macros for the above functions in pgapack.h

File size: 38.0 KB
Line 
1/*
2 * ----------------------------------------------------------------------
3 *  OPTIMIZER PLUG-IN:  Pgapack
4 *
5 *  This code connects Pgapack into the Rappture Optimization
6 *  infrastructure.
7 *
8 * ======================================================================
9 *  AUTHOR:  Michael McLennan, Purdue University
10 *  Copyright (c) 2008  Purdue Research Foundation
11 *
12 *  See the file "license.terms" for information on usage and
13 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14 * ======================================================================
15 */
16#include "pgapack.h"
17#include "rp_optimizer.h"
18
19typedef struct PgapackData {
20    int operation;       /* operation <=> PGA_MINIMIZE/PGA_MAXIMIZE */
21    int maxRuns;         /* maximum runs <=> PGASetMaxGAIterValue() */
22    int popSize;         /* population size <=> PGASetPopSize() */
23    int popRepl;         /* replacement <=> PGASetPopReplacementType() */
24    int numReplPerPop;    /* number of new strings created per population, the rest are the best strings from the previous population*/
25    int stpcriteria;     /*stoppage criteria <=> PGASetStoppingRuleType()*/
26    int randnumseed;  /*Random Number Seed <=> PGASetRandomSeed()*/
27    double mutnrate;     /*Mutation Rate <=> PGASetMutationProb()*/
28    double mutnValue;     /*use this value while mutating*/
29    double crossovrate;  /*Crossover Rate <=> PGASetCrossoverProb();*/
30    int crossovtype;    /*Crossover Type <=> UNIFORM/SBX (SBX Defined from Deb and Kumar 1995)*/
31    int allowdup;        /*Allow duplicate strings in the population or not*/
32    int mutnandcrossover;/*By default strings that do not undergo crossover undergo mutation, this option allows strings to crossover and be mutated*/
33    double randReplProp; /*By default, random replacement is off, therefore randReplaceProp is zero by default, */
34                                                /*a nonzero replacement value causes random generation of individuals in later generations*/
35} PgapackData;
36
37RpCustomTclOptionGet RpOption_GetStpCriteria;
38RpCustomTclOptionParse RpOption_ParseStpCriteria;
39RpTclOptionType RpOption_StpCriteria = {
40        "pga_stpcriteria", RpOption_ParseStpCriteria,RpOption_GetStpCriteria,NULL
41};
42
43RpCustomTclOptionParse RpOption_ParseOper;
44RpCustomTclOptionGet RpOption_GetOper;
45RpTclOptionType RpOption_Oper = {
46    "pga_operation", RpOption_ParseOper, RpOption_GetOper, NULL
47};
48
49RpCustomTclOptionParse RpOption_ParseCrossovType;
50RpCustomTclOptionGet RpOption_GetCrossovType;
51RpTclOptionType RpOption_CrossovType = {
52        "pga_crossovtype", RpOption_ParseCrossovType,RpOption_GetCrossovType,NULL
53};
54
55RpCustomTclOptionParse RpOption_ParsePopRepl;
56RpCustomTclOptionGet RpOption_GetPopRepl;
57RpTclOptionType RpOption_PopRepl = {
58    "pga_poprepl", RpOption_ParsePopRepl, RpOption_GetPopRepl, NULL
59};
60
61
62typedef struct PgapackRuntimeDataTable{
63        double **data;                          /*Actual data per sample, like values of the genes, fitness of a sample, etc*/
64        int num_of_rows;                        /*Number of rows alloced..should be constant for a run*/
65        int no_of_samples_evaled;       /*Number of samples evaluated so far*/
66        int no_of_columns;                                      /*Number of columns allocated to the data table so far*/
67}PgapackRuntimeDataTable;
68
69RpTclOption PgapackOptions[] = {
70  {"-maxruns", RP_OPTION_INT, Rp_Offset(PgapackData,maxRuns)},
71  {"-operation", &RpOption_Oper, Rp_Offset(PgapackData,operation)},
72  {"-poprepl", &RpOption_PopRepl, Rp_Offset(PgapackData,popRepl)},
73  {"-numReplPerPop",RP_OPTION_INT,Rp_Offset(PgapackData,numReplPerPop)},
74  {"-popsize", RP_OPTION_INT, Rp_Offset(PgapackData,popSize)},
75  {"-mutnrate",RP_OPTION_DOUBLE,Rp_Offset(PgapackData,mutnrate)},
76  {"-mutnValue",RP_OPTION_DOUBLE,Rp_Offset(PgapackData,mutnValue)},
77  {"-crossovrate",RP_OPTION_DOUBLE,Rp_Offset(PgapackData,crossovrate)},
78  {"-crossovtype",&RpOption_CrossovType,Rp_Offset(PgapackData,crossovtype)},
79  {"-randnumseed",RP_OPTION_INT,Rp_Offset(PgapackData,randnumseed)},
80  {"-stpcriteria",&RpOption_StpCriteria,Rp_Offset(PgapackData,stpcriteria)},
81  {"-allowdup",RP_OPTION_BOOLEAN,Rp_Offset(PgapackData,allowdup)},
82  {"-mutnandcrossover",RP_OPTION_BOOLEAN,Rp_Offset(PgapackData,mutnandcrossover)},
83  {"-randReplProp",RP_OPTION_DOUBLE,Rp_Offset(PgapackData,randReplProp)},
84  {NULL, NULL, 0}
85};
86
87static double PgapEvaluate _ANSI_ARGS_((PGAContext *ctx, int p, int pop));
88static void PgapCreateString _ANSI_ARGS_((PGAContext *ctx, int, int, int));
89static int PgapMutation _ANSI_ARGS_((PGAContext *ctx, int, int, double));
90static void PgapCrossover _ANSI_ARGS_((PGAContext *ctx, int, int, int,
91    int, int, int));
92static void PgapPrintString _ANSI_ARGS_((PGAContext *ctx, FILE*, int, int));
93static void PgapCopyString _ANSI_ARGS_((PGAContext *ctx, int, int, int, int));
94static int PgapDuplicateString _ANSI_ARGS_((PGAContext *ctx, int, int, int, int));
95static MPI_Datatype PgapBuildDT _ANSI_ARGS_((PGAContext *ctx, int, int));
96
97static void PgapLinkContext2Env _ANSI_ARGS_((PGAContext *ctx,
98    RpOptimEnv *envPtr));
99static RpOptimEnv* PgapGetEnvForContext _ANSI_ARGS_((PGAContext *ctx));
100static void PgapUnlinkContext2Env _ANSI_ARGS_((PGAContext *ctx));
101void PGARuntimeDataTableInit _ANSI_ARGS_((RpOptimEnv *envPtr));
102void PGARuntimeDataTableDeInit();
103void GetSampleInformation _ANSI_ARGS_((char *buffer, int sampleNumber));
104void PGARuntimeDataTableSetSampleValue _ANSI_ARGS_((RpOptimParam *chrom, double fitness));
105static PgapackRuntimeDataTable table;
106/*
107 * ----------------------------------------------------------------------
108 * PgapackInit()
109 *
110 * This routine is called whenever a new optimization object is created
111 * to initialize Pgapack.  Returns a pointer to PgapackData that is
112 * used in later routines.
113 * ----------------------------------------------------------------------
114 */
115ClientData
116PgapackInit()
117{
118    PgapackData *dataPtr;
119
120    dataPtr = (PgapackData*)malloc(sizeof(PgapackData));
121    dataPtr->operation = PGA_MINIMIZE;
122    dataPtr->maxRuns = 10000;
123    dataPtr->popRepl = PGA_POPREPL_BEST;
124    dataPtr->crossovtype = PGA_CROSSOVER_UNIFORM;
125    dataPtr->popSize = 200;
126    dataPtr->numReplPerPop = (dataPtr->popSize)/10; /*10% replaced by default, change to whatever value you need*/
127    dataPtr->crossovrate = 0.85;
128    dataPtr->mutnrate = 0.05; /*by default in PGAPack 1/stringlength*/
129    dataPtr->mutnValue = 0.01;/*value of this number will be changed by plus/minus hundredth of its current value*/
130    dataPtr->randnumseed = 1; /*should be a number greater than one, PGAPack requires it*/
131    dataPtr->stpcriteria = PGA_STOP_NOCHANGE;
132    dataPtr->allowdup = PGA_FALSE; /*Do not allow duplicate strings by default*/
133    dataPtr->mutnandcrossover = PGA_FALSE;/*do not allow mutation and crossover to take place on the same string by default*/
134    dataPtr->randReplProp = 0; /*0 randomly generated individuals after initialization, per generation*/
135    return (ClientData)dataPtr;
136}
137
138int pgapack_abort = 0;
139int pgapack_restart_user_action = 0;
140
141/*
142 * ----------------------------------------------------------------------
143 * PgapackRun()
144 *
145 * This routine is called to kick off an optimization run.  Sets up
146 * a PGApack context and starts invoking runs.
147 * ----------------------------------------------------------------------
148 */
149RpOptimStatus
150PgapackRun(envPtr, evalProc, fitnessExpr)
151    RpOptimEnv *envPtr;           /* optimization environment */
152    RpOptimEvaluator *evalProc;   /* call this proc to run tool */
153    char *fitnessExpr;            /* fitness function in string form */
154{
155    PgapackData *dataPtr =(PgapackData*)envPtr->pluginData;
156    PGAContext *ctx;
157
158    /* pgapack requires at least one arg -- the executable name */
159    /* fake it here by just saying something like "rappture" */
160    int argc = 1; char *argv[] = {"rappture"};
161
162    pgapack_abort = 0;          /* FALSE */
163    PGASetAbortVar(&pgapack_abort);
164    PGASetRestartUserAction(&pgapack_restart_user_action);
165
166    ctx = PGACreate(&argc, argv, PGA_DATATYPE_USER, envPtr->numParams,
167        dataPtr->operation);
168
169    PGASetMaxGAIterValue(ctx, dataPtr->maxRuns);
170    PGASetPopSize(ctx, dataPtr->popSize);
171    PGASetPopReplaceType(ctx, dataPtr->popRepl);
172    PGASetStoppingRuleType(ctx, dataPtr->stpcriteria);
173    PGASetMutationProb(ctx,dataPtr->mutnrate);
174    PGASetMutationRealValue(ctx,dataPtr->mutnValue);
175    PGASetCrossoverProb(ctx,dataPtr->crossovrate);
176    PGASetRandomSeed(ctx,dataPtr->randnumseed);
177    PGASetCrossoverType(ctx, dataPtr->crossovtype);
178    PGASetNoDuplicatesFlag(ctx,!(dataPtr->allowdup));
179    PGASetMutationAndCrossoverFlag(ctx,dataPtr->mutnandcrossover);
180    PGASetNumReplaceValue(ctx,dataPtr->numReplPerPop);
181    PGASetRandReplProp(ctx,dataPtr->randReplProp);
182
183
184    PGASetUserFunction(ctx, PGA_USERFUNCTION_CREATESTRING, PgapCreateString);
185    PGASetUserFunction(ctx, PGA_USERFUNCTION_MUTATION, PgapMutation);
186    PGASetUserFunction(ctx, PGA_USERFUNCTION_CROSSOVER, PgapCrossover);
187    PGASetUserFunction(ctx, PGA_USERFUNCTION_PRINTSTRING, PgapPrintString);
188    PGASetUserFunction(ctx, PGA_USERFUNCTION_COPYSTRING, PgapCopyString);
189    PGASetUserFunction(ctx, PGA_USERFUNCTION_DUPLICATE, PgapDuplicateString);
190    PGASetUserFunction(ctx, PGA_USERFUNCTION_BUILDDATATYPE, PgapBuildDT);
191
192    envPtr->evalProc = evalProc;   /* plug these in for later during eval */
193    envPtr->fitnessExpr = fitnessExpr;
194
195    /*
196     * We need a way to convert from a PGAContext to our RpOptimEnv
197     * data.  This happens when Pgapack calls routines like
198     * PgapCreateString, passing in the PGAContext, but nothing else.
199     * Call PgapLinkContext2Env() here, so later on we can figure
200     * out how many parameters, names, types, etc.
201     */
202    PgapLinkContext2Env(ctx, envPtr);
203
204    PGASetUp(ctx);
205    PGARun(ctx, PgapEvaluate);
206    PGADestroy(ctx);
207    PgapUnlinkContext2Env(ctx);
208
209    if (pgapack_abort) {
210        return RP_OPTIM_ABORTED;
211    }
212    return RP_OPTIM_SUCCESS;
213}
214
215/*
216 * ----------------------------------------------------------------------
217 * PgapackEvaluate()
218 *
219 * Called by PGApack whenever a set of input values needs to be
220 * evaluated.  Passes the values on to the underlying Rappture tool,
221 * launches a run, and computes the value of the fitness function.
222 * Returns the value for the fitness function.
223 * ----------------------------------------------------------------------
224 */
225double
226PgapEvaluate(ctx, p, pop)
227    PGAContext *ctx;  /* pgapack context for this optimization */
228    int p;            /* sample #p being run */
229    int pop;          /* identifier for this population */
230   
231{
232    double fit = 0.0;
233    RpOptimEnv *envPtr;
234    RpOptimParam *paramPtr;
235    RpOptimStatus status;
236    envPtr = PgapGetEnvForContext(ctx);
237    paramPtr = (RpOptimParam*)PGAGetIndividual(ctx, p, pop)->chrom;
238    status = (*envPtr->evalProc)(envPtr, paramPtr, envPtr->numParams, &fit);
239       
240    if (pgapack_abort) {
241        fprintf(stderr, "==WARNING: run aborted!");
242        return 0.0;
243    }
244       
245    if (status != RP_OPTIM_SUCCESS) {
246        fprintf(stderr, "==WARNING: run failed!");
247        PgapPrintString(ctx, stderr, p, pop);
248    }
249       
250        /*populate the table with this sample*/
251        PGARuntimeDataTableSetSampleValue(paramPtr,fit);
252    return fit;
253}
254
255/*
256 * ----------------------------------------------------------------------
257 * PgapackCleanup()
258 *
259 * This routine is called whenever an optimization object is deleted
260 * to clean up data associated with the object.  Frees the data
261 * allocated in PgapackInit.
262 * ----------------------------------------------------------------------
263 */
264void
265PgapackCleanup(cdata)
266    ClientData cdata;  /* data from to be cleaned up */
267{
268    PgapackData *dataPtr = (PgapackData*)cdata;
269    free(dataPtr);
270}
271
272/*
273 * ======================================================================
274 *  ROUTINES FOR MANAGING DATA STRINGS
275 * ======================================================================
276 * PgapCreateString()
277 *
278 * Called by pgapack to create the so-called "string" of data used for
279 * an evaluation.
280 * ----------------------------------------------------------------------
281 */
282void
283PgapCreateString(ctx, p, pop, initFlag)
284    PGAContext *ctx;  /* pgapack context for this optimization */
285    int p;            /* sample #p being run */
286    int pop;          /* identifier for this population */
287    int initFlag;     /* non-zero => fields should be initialized */
288{
289    int n, ival;
290    double dval;
291    RpOptimEnv *envPtr;
292    RpOptimParam *oldParamPtr, *newParamPtr;
293    PGAIndividual *newData;
294    RpOptimParamNumber *numPtr;
295    RpOptimParamString *strPtr;
296
297    envPtr = PgapGetEnvForContext(ctx);
298
299    newData = PGAGetIndividual(ctx, p, pop);
300    newData->chrom = malloc(envPtr->numParams*sizeof(RpOptimParam));
301    newParamPtr = (RpOptimParam*)newData->chrom;
302
303    for (n=0; n < envPtr->numParams; n++) {
304        oldParamPtr = envPtr->paramList[n];
305        newParamPtr[n].name = oldParamPtr->name;
306        newParamPtr[n].type = oldParamPtr->type;
307        switch (oldParamPtr->type) {
308        case RP_OPTIMPARAM_NUMBER:
309            newParamPtr[n].value.dval = 0.0;
310            break;
311        case RP_OPTIMPARAM_STRING:
312            newParamPtr[n].value.sval.num = -1;
313            newParamPtr[n].value.sval.str = NULL;
314            break;
315        default:
316            panic("bad parameter type in PgapCreateString()");
317        }
318    }
319
320    if (initFlag) {
321        for (n=0; n < envPtr->numParams; n++) {
322            switch (newParamPtr[n].type) {
323            case RP_OPTIMPARAM_NUMBER:
324                numPtr = (RpOptimParamNumber*)envPtr->paramList[n];
325                if(numPtr->randdist == RAND_NUMBER_DIST_UNIFORM){
326                        dval = PGARandom01(ctx,0);
327                        newParamPtr[n].value.dval = (numPtr->max - numPtr->min)*dval + numPtr->min;
328                }else if(numPtr->randdist == RAND_NUMBER_DIST_GAUSSIAN){
329                                dval = PGARandomGaussian(ctx,numPtr->mean,numPtr->stddev);
330                                if(numPtr->strictmax){
331                                        if(dval>numPtr->max){
332                                                dval = numPtr->max;
333                                        }
334                                }
335                                if(numPtr->strictmin){
336                                        if(dval<numPtr->min){
337                                                dval = numPtr->min;
338                                        }
339                                }
340                                newParamPtr[n].value.dval = dval;
341                }else{
342                        panic("Incorrect Random Number distribution option in PgapcreateString()");
343                }
344                break;
345            case RP_OPTIMPARAM_STRING:
346                strPtr = (RpOptimParamString*)envPtr->paramList[n];
347                ival = (int)floor(PGARandom01(ctx,0) * strPtr->numValues);
348                envPtr->paramList[n]->value.sval.num = ival;
349                envPtr->paramList[n]->value.sval.str = strPtr->values[ival];
350                break;
351            default:
352                panic("bad parameter type in PgapCreateString()");
353            }
354        }
355    }
356}
357
358/*
359 * ----------------------------------------------------------------------
360 * PgapMutation()
361 *
362 * Called by pgapack to perform random mutations on the input data
363 * used for evaluation.
364 * ----------------------------------------------------------------------
365 */
366int
367PgapMutation(ctx, p, pop, mr)
368    PGAContext *ctx;  /* pgapack context for this optimization */
369    int p;            /* sample #p being run */
370    int pop;          /* identifier for this population */
371    double mr;        /* probability of mutation for each gene */
372{
373    int count = 0;    /* number of mutations */
374
375    int n, ival,tempmr;
376    double mutnVal;
377    RpOptimEnv *envPtr;
378    RpOptimParam *paramPtr;
379    RpOptimParamNumber *numPtr;
380    RpOptimParamString *strPtr;
381
382    envPtr = PgapGetEnvForContext(ctx);
383    paramPtr = (RpOptimParam*)PGAGetIndividual(ctx, p, pop)->chrom;
384
385    for (n=0; n < envPtr->numParams; n++) {
386
387
388            switch (paramPtr[n].type) {
389            case RP_OPTIMPARAM_NUMBER:
390                numPtr = (RpOptimParamNumber*)envPtr->paramList[n];
391                if(numPtr->mutnrate!=PARAM_NUM_UNSPEC_MUTN_RATE){
392                        tempmr = numPtr->mutnrate;
393                        mutnVal = numPtr->mutnValue;
394                }else{
395                        tempmr = mr;
396                        mutnVal = PGAGetMutationRealValue(ctx);
397                }
398                if (PGARandomFlip(ctx, tempmr)) {
399                            /* won the coin toss -- change this parameter */
400                                count++;
401                               
402                        /* bump the value up/down a little, randomly */
403                        if (PGARandomFlip(ctx, 0.5)) {
404                            paramPtr[n].value.dval += mutnVal*paramPtr[n].value.dval; /*Made the mutation amount configurable*/
405                        } else {
406                            paramPtr[n].value.dval -= mutnVal*paramPtr[n].value.dval;
407                        }
408                        /* make sure the resulting value is still in bounds */
409                        if(numPtr->randdist == RAND_NUMBER_DIST_UNIFORM ||
410                         (numPtr->randdist == RAND_NUMBER_DIST_GAUSSIAN && numPtr->strictmax)){
411                                if (paramPtr[n].value.dval > numPtr->max) {
412                                    paramPtr[n].value.dval = numPtr->max;
413                                }
414                         }
415                         /*also make sure it obeys configured parameters when gaussian*/
416                         if(numPtr->randdist == RAND_NUMBER_DIST_UNIFORM ||
417                         (numPtr->randdist == RAND_NUMBER_DIST_GAUSSIAN && numPtr->strictmin)){
418                                if (paramPtr[n].value.dval < numPtr->min) {
419                                    paramPtr[n].value.dval = numPtr->min;
420                                }
421                         }
422                       
423                }
424                break;
425               
426
427            case RP_OPTIMPARAM_STRING:
428                    if (PGARandomFlip(ctx, mr)) {
429                    /* won the coin toss -- change this parameter */
430                        count++;
431               
432                        ival = paramPtr[n].value.sval.num;
433                        if (PGARandomFlip(ctx, 0.5)) {
434                            ival += 1;
435                        } else {
436                            ival -= 1;
437                        }
438                        strPtr = (RpOptimParamString*)envPtr->paramList[n];
439                        if (ival < 0) ival = 0;
440                        if (ival >= strPtr->numValues) ival = strPtr->numValues-1;
441                        paramPtr[n].value.sval.num = ival;
442                        paramPtr[n].value.sval.str = strPtr->values[ival];
443                    }
444                   
445                    break;
446                   
447            default:
448                panic("bad parameter type in PgapMutation()");
449            }
450       
451    }
452    return count;
453}
454
455/*
456 * ----------------------------------------------------------------------
457 * PgapCrossover()
458 *
459 * Called by pgapack to perform cross-over mutations on the input data
460 * used for evaluation.
461 * ----------------------------------------------------------------------
462 */
463void
464PgapCrossover(ctx, p1, p2, pop1, c1, c2, pop2)
465    PGAContext *ctx;  /* pgapack context for this optimization */
466    int p1;           /* sample # for parent of input string1 */
467    int p2;           /* sample # for parent of input string2 */
468    int pop1;         /* population containing p1 and p2 */
469    int c1;           /* sample # for child of input string1 */
470    int c2;           /* sample # for child of input string2 */
471    int pop2;         /* population containing c1 and c2 */
472{
473    int n;
474    RpOptimEnv *envPtr;
475    RpOptimParam *parent1, *parent2, *child1, *child2;
476    double pu;
477    PgapackData *dataPtr;
478    /*declare variables for SBX*/
479    double ui,beta,eta,powVal;
480
481    envPtr = PgapGetEnvForContext(ctx);
482    parent1 = (RpOptimParam*)PGAGetIndividual(ctx, p1, pop1)->chrom;
483    parent2 = (RpOptimParam*)PGAGetIndividual(ctx, p2, pop1)->chrom;
484    child1  = (RpOptimParam*)PGAGetIndividual(ctx, c1, pop2)->chrom;
485    child2  = (RpOptimParam*)PGAGetIndividual(ctx, c2, pop2)->chrom;
486       
487        pu = PGAGetCrossoverProb(ctx);
488        dataPtr =(PgapackData*)envPtr->pluginData;
489       
490        for (n=0; n < envPtr->numParams; n++) {
491        if (PGARandomFlip(ctx, pu)) {
492            /* crossover */
493            switch(dataPtr->crossovtype){
494                case PGA_CROSSOVER_UNIFORM:
495                        memcpy(&child1[n], &parent2[n], sizeof(RpOptimParam));
496                        memcpy(&child2[n], &parent1[n], sizeof(RpOptimParam));
497                        break;
498                case PGA_CROSSOVER_SBX:
499                        /*Implement a Simulated Binary Crossover for Real Encoding*/
500                        /*From Deb and Agrawal, 1995; Deb and Kumar, 1995)*/
501                        switch(parent1[n].type){
502                                case RP_OPTIMPARAM_NUMBER:
503                                        ui = PGARandom01(ctx,0);
504                                        eta = 1.5;/*We can adjust eta later....keeping it 1.5 for now*/
505                                        powVal = 1/(eta+1);
506                                        if(ui<=0.5){
507                                                beta = pow(2*ui,powVal);
508                                        }else{
509                                                beta = pow(0.5/(1-ui),powVal);
510                                        }
511                                        child1[n].value.dval = 0.5*((1+beta)*(parent1[n].value.dval) + (1-beta)*(parent2[n].value.dval));
512                                        child2[n].value.dval = 0.5*((1-beta)*(parent1[n].value.dval) + (1+beta)*(parent2[n].value.dval));
513                                        break;
514                                default:
515                                        panic("Bad Optim Param Type in PgapCrossover()");
516                        }
517                        break;
518                default:
519                        panic("bad parameter type in PgapCrossover()");
520            }
521        } else {
522            /* child inherits from parent */
523            memcpy(&child1[n], &parent1[n], sizeof(RpOptimParam));
524            memcpy(&child2[n], &parent2[n], sizeof(RpOptimParam));
525        }
526    }
527                       
528               
529}
530
531/*
532 * ----------------------------------------------------------------------
533 * PgapPrintString()
534 *
535 * Called by pgapack to format the values for a particular string of
536 * input data.
537 * ----------------------------------------------------------------------
538 */
539void
540PgapPrintString(ctx, fp, p, pop)
541    PGAContext *ctx;  /* pgapack context for this optimization */
542    FILE *fp;         /* write to this file pointer */
543    int p;            /* sample #p being run */
544    int pop;          /* identifier for this population */
545{
546    int n;
547    RpOptimEnv *envPtr;
548    RpOptimParam *paramPtr;
549
550    envPtr = PgapGetEnvForContext(ctx);
551    paramPtr = (RpOptimParam*)PGAGetIndividual(ctx, p, pop)->chrom;
552
553    for (n=0; n < envPtr->numParams; n++) {
554        fprintf(fp, "#%4d: ", n);
555        switch (paramPtr[n].type) {
556        case RP_OPTIMPARAM_NUMBER:
557            fprintf(fp, "[%11.7g] (%s)\n", paramPtr[n].value.dval,
558                paramPtr[n].name);
559            break;
560        case RP_OPTIMPARAM_STRING:
561            fprintf(fp, "[%d]=\"%s\" (%s)\n", paramPtr[n].value.sval.num,
562                paramPtr[n].value.sval.str, paramPtr[n].name);
563            break;
564        default:
565            panic("bad parameter type in PgapPrintString()");
566        }
567    }
568}
569
570/*
571 * ----------------------------------------------------------------------
572 * PgapCopyString()
573 *
574 * Called by pgapack to copy one input string to another.
575 * ----------------------------------------------------------------------
576 */
577void
578PgapCopyString(ctx, p1, pop1, p2, pop2)
579    PGAContext *ctx;  /* pgapack context for this optimization */
580    int p1;           /* source sample # being run */
581    int pop1;         /* population containing p1 */
582    int p2;           /* destination sample # being run */
583    int pop2;         /* population containing p1 */
584{
585    int n;
586    RpOptimEnv *envPtr;
587    RpOptimParam *src, *dst;
588
589    envPtr = PgapGetEnvForContext(ctx);
590    src = (RpOptimParam*)PGAGetIndividual(ctx, p1, pop1)->chrom;
591    dst = (RpOptimParam*)PGAGetIndividual(ctx, p2, pop2)->chrom;
592
593    for (n=0; n < envPtr->numParams; n++) {
594        dst[n].type = src[n].type;
595        switch (src[n].type) {
596        case RP_OPTIMPARAM_NUMBER:
597            dst[n].value.dval = src[n].value.dval;
598            break;
599        case RP_OPTIMPARAM_STRING:
600            dst[n].value.sval.num = src[n].value.sval.num;
601            dst[n].value.sval.str = src[n].value.sval.str;
602            break;
603        default:
604            panic("bad parameter type in PgapCopyString()");
605        }
606    }
607}
608
609/*
610 * ----------------------------------------------------------------------
611 * PgapDuplicateString()
612 *
613 * Called by pgapack to compare two input strings.  Returns non-zero if
614 * the two are duplicates and 0 otherwise.
615 * ----------------------------------------------------------------------
616 */
617int
618PgapDuplicateString(ctx, p1, pop1, p2, pop2)
619    PGAContext *ctx;  /* pgapack context for this optimization */
620    int p1;           /* sample #p being run */
621    int pop1;         /* population containing p1 */
622    int p2;           /* sample #p being run */
623    int pop2;         /* population containing p1 */
624{
625    int n;
626    RpOptimEnv *envPtr;
627    RpOptimParam *param1, *param2;
628
629    envPtr = PgapGetEnvForContext(ctx);
630    param1 = (RpOptimParam*)PGAGetIndividual(ctx, p1, pop1)->chrom;
631    param2 = (RpOptimParam*)PGAGetIndividual(ctx, p2, pop2)->chrom;
632
633    for (n=0; n < envPtr->numParams; n++) {
634        if (param1[n].type != param2[n].type) {
635            return 0;  /* different! */
636        }
637        switch (param1[n].type) {
638        case RP_OPTIMPARAM_NUMBER:
639            if (param1[n].value.dval != param2[n].value.dval) {
640                return 0;  /* different! */
641            }
642            break;
643        case RP_OPTIMPARAM_STRING:
644            if (param1[n].value.sval.num != param2[n].value.sval.num) {
645                return 0;  /* different! */
646            }
647            break;
648        default:
649            panic("bad parameter type in PgapDuplicateString()");
650        }
651    }
652    return 1;
653}
654
655
656
657/*
658 * ----------------------------------------------------------------------
659 * PgapCopyString()
660 *
661 * Called by pgapack to copy one input string to another.
662 * ----------------------------------------------------------------------
663 */
664MPI_Datatype
665PgapBuildDT(ctx, p, pop)
666    PGAContext *ctx;  /* pgapack context for this optimization */
667    int p;            /* sample # being run */
668    int pop;          /* population containing sample */
669{
670    panic("MPI support not implemented!");
671    return NULL;
672}
673
674/*
675 * ======================================================================
676 *  OPTION:  -operation <=> PGA_MINIMIZE / PGA_MAXIMIZE
677 * ======================================================================
678 */
679int
680RpOption_ParseOper(interp, valObj, cdata, offset)
681    Tcl_Interp *interp;  /* interpreter handling this request */
682    Tcl_Obj *valObj;     /* set option to this new value */
683    ClientData cdata;    /* save in this data structure */
684    int offset;          /* save at this offset in cdata */
685{
686    int *ptr = (int*)(cdata+offset);
687    char *val = Tcl_GetStringFromObj(valObj, (int*)NULL);
688    if (strcmp(val,"minimize") == 0) {
689        *ptr = PGA_MINIMIZE;
690    }
691    else if (strcmp(val,"maximize") == 0) {
692        *ptr = PGA_MAXIMIZE;
693    }
694    else {
695        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
696            "bad value \"", val, "\": should be minimize, maximize",
697            (char*)NULL);
698        return TCL_ERROR;
699    }
700    return TCL_OK;
701}
702
703int
704RpOption_GetOper(interp, cdata, offset)
705    Tcl_Interp *interp;  /* interpreter handling this request */
706    ClientData cdata;    /* get from this data structure */
707    int offset;          /* get from this offset in cdata */
708{
709    int *ptr = (int*)(cdata+offset);
710    switch (*ptr) {
711    case PGA_MINIMIZE:
712        Tcl_SetResult(interp, "minimize", TCL_STATIC);
713        break;
714    case PGA_MAXIMIZE:
715        Tcl_SetResult(interp, "maximize", TCL_STATIC);
716        break;
717    default:
718        Tcl_SetResult(interp, "???", TCL_STATIC);
719        break;
720    }
721    return TCL_OK;
722}
723
724
725/*
726 * ======================================================================
727 *  OPTION:  -crossovtype <=> PGA_CROSSOVER_UNIFORM / PGA_CROSSOVER_SBX
728 * ======================================================================
729 */
730int
731RpOption_ParseCrossovType(interp, valObj, cdata, offset)
732    Tcl_Interp *interp;  /* interpreter handling this request */
733    Tcl_Obj *valObj;     /* set option to this new value */
734    ClientData cdata;    /* save in this data structure */
735    int offset;          /* save at this offset in cdata */
736{
737    int *ptr = (int*)(cdata+offset);
738    char *val = Tcl_GetStringFromObj(valObj, (int*)NULL);
739    if (strcmp(val,"uniform") == 0) {
740        *ptr = PGA_CROSSOVER_UNIFORM;
741    }
742    else if (strcmp(val,"sbx") == 0) {
743        *ptr = PGA_CROSSOVER_SBX;
744    }
745    else {
746        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
747            "bad value \"", val, "\": should be either 'uniform' or 'sbx'",
748            (char*)NULL);
749        return TCL_ERROR;
750    }
751    return TCL_OK;
752}
753
754int
755RpOption_GetCrossovType(interp, cdata, offset)
756    Tcl_Interp *interp;  /* interpreter handling this request */
757    ClientData cdata;    /* get from this data structure */
758    int offset;          /* get from this offset in cdata */
759{
760    int *ptr = (int*)(cdata+offset);
761    switch (*ptr) {
762    case PGA_CROSSOVER_UNIFORM:
763        Tcl_SetResult(interp, "uniform", TCL_STATIC);
764        break;
765    case PGA_CROSSOVER_SBX:
766        Tcl_SetResult(interp, "sbx", TCL_STATIC);
767        break;
768    default:
769        Tcl_SetResult(interp, "???", TCL_STATIC);
770        break;
771    }
772    return TCL_OK;
773}
774
775
776
777
778/*
779 * ======================================================================
780 *  OPTION:  -poprepl <=> PGASetPopReplacementType()
781 * ======================================================================
782 */
783int
784RpOption_ParsePopRepl(interp, valObj, cdata, offset)
785    Tcl_Interp *interp;  /* interpreter handling this request */
786    Tcl_Obj *valObj;     /* set option to this new value */
787    ClientData cdata;    /* save in this data structure */
788    int offset;          /* save at this offset in cdata */
789{
790    int *ptr = (int*)(cdata+offset);
791    char *val = Tcl_GetStringFromObj(valObj, (int*)NULL);
792    if (*val == 'b' && strcmp(val,"best") == 0) {
793        *ptr = PGA_POPREPL_BEST;
794    }
795    else if (*val == 'r' && strcmp(val,"random-repl") == 0) {
796        *ptr = PGA_POPREPL_RANDOM_REP;
797    }
798    else if (*val == 'r' && strcmp(val,"random-norepl") == 0) {
799        *ptr = PGA_POPREPL_RANDOM_NOREP;
800    }
801    else {
802        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
803            "bad value \"", val, "\": should be best, random-norepl,"
804            " or random-repl", (char*)NULL);
805        return TCL_ERROR;
806    }
807    return TCL_OK;
808}
809
810int
811RpOption_GetPopRepl(interp, cdata, offset)
812    Tcl_Interp *interp;  /* interpreter handling this request */
813    ClientData cdata;    /* get from this data structure */
814    int offset;          /* get from this offset in cdata */
815{
816    int *ptr = (int*)(cdata+offset);
817    switch (*ptr) {
818    case PGA_POPREPL_BEST:
819        Tcl_SetResult(interp, "best", TCL_STATIC);
820        break;
821    case PGA_POPREPL_RANDOM_REP:
822        Tcl_SetResult(interp, "random-repl", TCL_STATIC);
823        break;
824    case PGA_POPREPL_RANDOM_NOREP:
825        Tcl_SetResult(interp, "random-norepl", TCL_STATIC);
826        break;
827    default:
828        Tcl_SetResult(interp, "???", TCL_STATIC);
829        break;
830    }
831    return TCL_OK;
832}
833
834/*
835 * ======================================================================
836 *  OPTION:  -stpcriteria <=> PGA_STOP_MAXITER / PGA_STOP_NOCHANGE / PGA_STOP_TOOSIMILAR
837 * ======================================================================
838 */
839int
840RpOption_ParseStpCriteria(interp, valObj, cdata, offset)
841    Tcl_Interp *interp;  /* interpreter handling this request */
842    Tcl_Obj *valObj;     /* set option to this new value */
843    ClientData cdata;    /* save in this data structure */
844    int offset;          /* save at this offset in cdata */
845{
846    int *ptr = (int*)(cdata+offset);
847    char *val = Tcl_GetStringFromObj(valObj, (int*)NULL);
848    if (strcmp(val,"maxiter") == 0) {
849        *ptr = PGA_STOP_MAXITER;
850    }
851    else if (strcmp(val,"nochange") == 0) {
852        *ptr = PGA_STOP_NOCHANGE;
853    }
854    else if (strcmp(val,"toosimilar") == 0){
855        *ptr = PGA_STOP_TOOSIMILAR;
856    }
857    else {
858        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
859            "bad value \"", val, "\": should be maxiter, nochange or toosimilar",
860            (char*)NULL);
861        return TCL_ERROR;
862    }
863    return TCL_OK;
864}
865
866int
867RpOption_GetStpCriteria(interp, cdata, offset)
868    Tcl_Interp *interp;  /* interpreter handling this request */
869    ClientData cdata;    /* get from this data structure */
870    int offset;          /* get from this offset in cdata */
871{
872    int *ptr = (int*)(cdata+offset);
873    switch (*ptr) {
874    case PGA_STOP_MAXITER:
875        Tcl_SetResult(interp, "maxiter", TCL_STATIC);
876        break;
877    case PGA_STOP_NOCHANGE:
878        Tcl_SetResult(interp, "nochange", TCL_STATIC);
879        break;
880    case PGA_STOP_TOOSIMILAR:
881        Tcl_SetResult(interp, "toosimilar", TCL_STATIC);
882        break;
883    default:
884        Tcl_SetResult(interp, "???", TCL_STATIC);
885        break;
886    }
887    return TCL_OK;
888}
889
890/*
891 * ======================================================================
892 *  ROUTINES FOR CONNECTING PGACONTEXT <=> RPOPTIMENV
893 * ======================================================================
894 * PgapLinkContext2Env()
895 *   This routine is used internally to establish a relationship between
896 *   a PGAContext token and its corresponding RpOptimEnv data.  The
897 *   PGA routines don't provide a way to pass the RpOptimEnv data along,
898 *   so we use these routines to find the correspondence.
899 *
900 * PgapGetEnvForContext()
901 *   Returns the RpOptimEnv associated with a given PGAContext.  If the
902 *   link has not been established via PgapLinkContext2Env(), then this
903 *   routine returns NULL.
904 *
905 * PgapUnlinkContext2Env()
906 *   Breaks the link between a PGAContext and its RpOptimEnv.  Should
907 *   be called when the PGAContext is destroyed and is no longer valid.
908 * ----------------------------------------------------------------------
909 */
910static Tcl_HashTable *Pgacontext2Rpenv = NULL;
911
912void
913PgapLinkContext2Env(ctx, envPtr)
914    PGAContext *ctx;      /* pgapack context for this optimization */
915    RpOptimEnv *envPtr;   /* corresponding Rappture optimization data */
916{
917    Tcl_HashEntry *ctxEntry;
918    int newEntry;
919
920    if (Pgacontext2Rpenv == NULL) {
921        Pgacontext2Rpenv = (Tcl_HashTable*)malloc(sizeof(Tcl_HashTable));
922        Tcl_InitHashTable(Pgacontext2Rpenv, TCL_ONE_WORD_KEYS);
923    }
924    ctxEntry = Tcl_CreateHashEntry(Pgacontext2Rpenv, (char*)ctx, &newEntry);
925    Tcl_SetHashValue(ctxEntry, (ClientData)envPtr);
926}
927
928RpOptimEnv*
929PgapGetEnvForContext(ctx)
930    PGAContext *ctx;
931{
932    Tcl_HashEntry *entryPtr;
933
934    if (Pgacontext2Rpenv) {
935        entryPtr = Tcl_FindHashEntry(Pgacontext2Rpenv, (char*)ctx);
936        if (entryPtr) {
937            return (RpOptimEnv*)Tcl_GetHashValue(entryPtr);
938        }
939    }
940    return NULL;
941}
942
943void
944PgapUnlinkContext2Env(ctx)
945    PGAContext *ctx;
946{
947    Tcl_HashEntry *entryPtr;
948
949    if (Pgacontext2Rpenv) {
950        entryPtr = Tcl_FindHashEntry(Pgacontext2Rpenv, (char*)ctx);
951        if (entryPtr) {
952            Tcl_DeleteHashEntry(entryPtr);
953        }
954    }
955}
956/*---------------------------------------------------------------------------------
957 * PGARuntimeDTInit(): It initializes the runtime data table.
958 * The table is organized slightly counter-intuitively
959 * Instead of a
960 *  param1|param2|param3  |param4...
961 *      val11 |val12 |val13   |val14...
962 *      val12 |val22 |val23   |val24....
963 * orientation, it is organized as
964 *      param1|val11|val12
965 *      param2|val21|val22
966 *      param3|val31|val32
967 *      param4|val41|val42
968 * Reallocating for additional columns is easier than reallocating additional rows and then
969 * reallocating for columns
970 * --------------------------------------------------------------------------------
971 */
972
973void PGARuntimeDataTableInit(envPtr)
974RpOptimEnv *envPtr;
975{   
976        int i;
977        if(envPtr != NULL){
978                table.num_of_rows = (envPtr->numParams)+1;
979                table.data = malloc((table.num_of_rows)*sizeof(double*));
980                if(table.data == NULL){
981                        panic("\nAllocation for Runtime Data Table failed\n");
982                }
983                for(i=0;i<table.num_of_rows;i++){
984                        table.data[i] = malloc(PGAPACK_RUNTIME_TABLE_DEFAULT_SIZE*sizeof(double));
985                        if(table.data[i] == NULL){
986                                panic("\nAllocation for Runtime Data Table failed\n");
987                        }                       
988                }
989                table.no_of_samples_evaled = 0;
990                table.no_of_columns = PGAPACK_RUNTIME_TABLE_DEFAULT_SIZE;
991               
992        }else{
993                panic("\nError: NULL Environment variable OR Table pointer passed to Data Table Init\n");
994        }
995}
996
997void PGARuntimeDataTableDeInit()
998{       
999        int i;
1000        if((&table) == NULL){
1001                panic("Error: Table not present, therefore cannot free memory..");
1002        }
1003        for(i=0;i<table.num_of_rows;i++){
1004                free(table.data[i]);
1005        }
1006        free(table.data);
1007}
1008
1009void PGARuntimeDataTableSetSampleValue(chrom,fitness)
1010RpOptimParam *chrom;
1011double fitness;
1012{
1013        int i;
1014        //printf("\nSetting sample value.......................\n");
1015        if(chrom!=NULL && (&table)!=NULL){
1016                (table.no_of_samples_evaled)+=1;
1017                if((table.no_of_samples_evaled) > table.no_of_columns){
1018                        /* then Reallocate space for more columns)*/
1019                        (table.no_of_columns)+=(table.no_of_columns);
1020                                //TODO GTG: Delete printing stuff
1021                        for(i=0;i<(table.num_of_rows);i++){
1022                                table.data[i] = realloc(table.data[i],table.no_of_columns);
1023                                if(table.data[i]==NULL){
1024                                        panic("\nError: Could not Reallocate more space for the table");
1025                                }                               
1026                        }
1027                }else{
1028                        if(chrom->type == RP_OPTIMPARAM_NUMBER){
1029                                for(i=0;i<(table.num_of_rows);i++){
1030                                        if(i==0){
1031                                                table.data[i][(table.no_of_samples_evaled)-1] = fitness;
1032                                                //printf("\nSample Number %d:- Fitness: %lf\t",table.no_of_samples_evaled,fitness);
1033                                        }else{
1034                                                table.data[i][(table.no_of_samples_evaled)-1] = chrom[i-1].value.dval;
1035                                                //printf("Param %d %lf\t",i,table.data[i][(table.no_of_samples_evaled)-1]);
1036                                        }
1037                }
1038                        }else{
1039                                panic("\n Chromosome value is RP_OPTIMPARAM_STRING\n");
1040                                //GTG TODO: find out what happens in this case. Will we be better off handling Tcl_objects?
1041                        }       
1042                }
1043        }else{
1044                panic("\nError:Either Chromosome, or table passed to PGARuntimeDataTableSetSampleValue() is NULL\n");
1045        }
1046       
1047}
1048
1049void GetSampleInformation(buffer,sampleNumber)
1050        char *buffer;
1051        int sampleNumber;
1052{
1053        int i;
1054        char tempBuff[50];
1055        printf("\nFetching sample information.........................\n");
1056        if((&table) == NULL){
1057                panic("Table uninitialized");
1058        }
1059        if(sampleNumber<=0){
1060                sprintf(buffer,"\nNumber of Samples Evaluated so far: %d\n",(table.no_of_samples_evaled)+1);
1061                return;
1062        }
1063        if(((table.num_of_rows)-1)*10>SINGLE_SAMPLE_DATA_BUFFER_DEFAULT_SIZE){
1064                buffer = realloc(buffer,50+25*(table.num_of_rows));
1065                //resizing the buffer, keeping 50 for display related jazz, around 12-15 characs for param names
1066                //and 10 characs for Fl.pt. display of the value
1067                if(buffer == NULL){
1068                        panic("\nError: Could not reallocate space for sample data buffer");
1069                }
1070        }
1071        for(i=0;i<(table.num_of_rows);i++){
1072                if(i==0){
1073                        sprintf(buffer,"\nSample Number %d ----> Fitness: %lf  ",sampleNumber,table.data[i][sampleNumber-1]);
1074                }else{
1075                        sprintf(tempBuff,"Param %d: %lf  ",i,table.data[i][sampleNumber-1]);
1076                        strcat(buffer,tempBuff);
1077                }
1078        }
1079        strcat(buffer,"\n");
1080}
Note: See TracBrowser for help on using the repository browser.