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

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

Changes Made: Vanilla restart added, no modifications can be made to existing parameters in the middle of a run. Only mutation creates a new population on restart.
New configuration options added: MutationandCrossover? option. amount to be mutated made configurable. configration for (not)allowing duplicate strings added. app-qdot and simple modified to keep pace with these changes.

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