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

Last change on this file since 1154 was 1154, checked in by liveletlive, 14 years ago

tweaked the configuration code for number parameters.
added code required to include units of a number parameter.

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