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

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

Added changes to accomodate gaussian profiles and random number distribution selection on a per gene basis.
also changed the mutation to a per gene based mutation if specified.

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 =
296                    (numPtr->max - numPtr->min)*dval + numPtr->min;
297                }else if(numPtr->randdist == RAND_NUMBER_DIST_GAUSSIAN){
298                                dval = PGARandomGaussian(ctx,numPtr->mean,numPtr->stddev);
299                                if(numPtr->strictmax){
300                                        if(dval>numPtr->max){
301                                                dval = numPtr->max;
302                                        }
303                                }
304                                if(numPtr->strictmin){
305                                        if(dval<numPtr->min){
306                                                dval = numPtr->min;
307                                        }
308                                }
309                                newParamPtr[n].value.dval = dval;
310                }else{
311                        panic("Incorrect Random Number distribution option in PgapcreateString()");
312                }
313                break;
314            case RP_OPTIMPARAM_STRING:
315                strPtr = (RpOptimParamString*)envPtr->paramList[n];
316                ival = (int)floor(PGARandom01(ctx,0) * strPtr->numValues);
317                envPtr->paramList[n]->value.sval.num = ival;
318                envPtr->paramList[n]->value.sval.str = strPtr->values[ival];
319                break;
320            default:
321                panic("bad parameter type in PgapCreateString()");
322            }
323        }
324    }
325}
326
327/*
328 * ----------------------------------------------------------------------
329 * PgapMutation()
330 *
331 * Called by pgapack to perform random mutations on the input data
332 * used for evaluation.
333 * ----------------------------------------------------------------------
334 */
335int
336PgapMutation(ctx, p, pop, mr)
337    PGAContext *ctx;  /* pgapack context for this optimization */
338    int p;            /* sample #p being run */
339    int pop;          /* identifier for this population */
340    double mr;        /* probability of mutation for each gene */
341{
342    int count = 0;    /* number of mutations */
343
344    int n, ival,tempmr;
345    RpOptimEnv *envPtr;
346    RpOptimParam *paramPtr;
347    RpOptimParamNumber *numPtr;
348    RpOptimParamString *strPtr;
349
350    envPtr = PgapGetEnvForContext(ctx);
351    paramPtr = (RpOptimParam*)PGAGetIndividual(ctx, p, pop)->chrom;
352
353    for (n=0; n < envPtr->numParams; n++) {
354
355
356            switch (paramPtr[n].type) {
357            case RP_OPTIMPARAM_NUMBER:
358                numPtr = (RpOptimParamNumber*)envPtr->paramList[n];
359                if(numPtr->mutnrate!=PARAM_NUM_UNSPEC_MUTN_RATE){
360                        tempmr = numPtr->mutnrate;
361                }else{
362                        tempmr = mr;
363                }
364                if (PGARandomFlip(ctx, tempmr)) {
365                            /* won the coin toss -- change this parameter */
366                                count++;
367                               
368                        /* bump the value up/down a little, randomly */
369                        if (PGARandomFlip(ctx, 0.5)) {
370                            paramPtr[n].value.dval += 0.1*paramPtr[n].value.dval;
371                        } else {
372                            paramPtr[n].value.dval -= 0.1*paramPtr[n].value.dval;
373                        }
374                        /* make sure the resulting value is still in bounds */
375                        if(numPtr->randdist == RAND_NUMBER_DIST_UNIFORM ||
376                         (numPtr->randdist == RAND_NUMBER_DIST_GAUSSIAN && numPtr->strictmax)){
377                                if (paramPtr[n].value.dval > numPtr->max) {
378                                    paramPtr[n].value.dval = numPtr->max;
379                                }
380                         }
381                         /*also make sure it obeys configured parameters when gaussian*/
382                         if(numPtr->randdist == RAND_NUMBER_DIST_UNIFORM ||
383                         (numPtr->randdist == RAND_NUMBER_DIST_GAUSSIAN && numPtr->strictmin)){
384                                if (paramPtr[n].value.dval < numPtr->min) {
385                                    paramPtr[n].value.dval = numPtr->min;
386                                }
387                         }
388                       
389                }
390                break;
391               
392
393            case RP_OPTIMPARAM_STRING:
394                    if (PGARandomFlip(ctx, mr)) {
395                    /* won the coin toss -- change this parameter */
396                        count++;
397               
398                        ival = paramPtr[n].value.sval.num;
399                        if (PGARandomFlip(ctx, 0.5)) {
400                            ival += 1;
401                        } else {
402                            ival -= 1;
403                        }
404                        strPtr = (RpOptimParamString*)envPtr->paramList[n];
405                        if (ival < 0) ival = 0;
406                        if (ival >= strPtr->numValues) ival = strPtr->numValues-1;
407                        paramPtr[n].value.sval.num = ival;
408                        paramPtr[n].value.sval.str = strPtr->values[ival];
409                    }
410                   
411                    break;
412                   
413            default:
414                panic("bad parameter type in PgapMutation()");
415            }
416       
417    }
418    return count;
419}
420
421/*
422 * ----------------------------------------------------------------------
423 * PgapCrossover()
424 *
425 * Called by pgapack to perform cross-over mutations on the input data
426 * used for evaluation.
427 * ----------------------------------------------------------------------
428 */
429void
430PgapCrossover(ctx, p1, p2, pop1, c1, c2, pop2)
431    PGAContext *ctx;  /* pgapack context for this optimization */
432    int p1;           /* sample # for parent of input string1 */
433    int p2;           /* sample # for parent of input string2 */
434    int pop1;         /* population containing p1 and p2 */
435    int c1;           /* sample # for child of input string1 */
436    int c2;           /* sample # for child of input string2 */
437    int pop2;         /* population containing c1 and c2 */
438{
439    int n;
440    RpOptimEnv *envPtr;
441    RpOptimParam *parent1, *parent2, *child1, *child2;
442    double pu;
443
444    envPtr = PgapGetEnvForContext(ctx);
445    parent1 = (RpOptimParam*)PGAGetIndividual(ctx, p1, pop1)->chrom;
446    parent2 = (RpOptimParam*)PGAGetIndividual(ctx, p2, pop1)->chrom;
447    child1  = (RpOptimParam*)PGAGetIndividual(ctx, c1, pop2)->chrom;
448    child2  = (RpOptimParam*)PGAGetIndividual(ctx, c2, pop2)->chrom;
449
450    pu = PGAGetUniformCrossoverProb(ctx);
451
452    for (n=0; n < envPtr->numParams; n++) {
453        if (PGARandomFlip(ctx, pu)) {
454            /* child inherits from parent */
455            memcpy(&child1[n], &parent1[n], sizeof(RpOptimParam));
456            memcpy(&child2[n], &parent2[n], sizeof(RpOptimParam));
457        } else {
458            /* crossover */
459            memcpy(&child1[n], &parent2[n], sizeof(RpOptimParam));
460            memcpy(&child2[n], &parent1[n], sizeof(RpOptimParam));
461        }
462    }
463}
464
465/*
466 * ----------------------------------------------------------------------
467 * PgapPrintString()
468 *
469 * Called by pgapack to format the values for a particular string of
470 * input data.
471 * ----------------------------------------------------------------------
472 */
473void
474PgapPrintString(ctx, fp, p, pop)
475    PGAContext *ctx;  /* pgapack context for this optimization */
476    FILE *fp;         /* write to this file pointer */
477    int p;            /* sample #p being run */
478    int pop;          /* identifier for this population */
479{
480    int n;
481    RpOptimEnv *envPtr;
482    RpOptimParam *paramPtr;
483
484    envPtr = PgapGetEnvForContext(ctx);
485    paramPtr = (RpOptimParam*)PGAGetIndividual(ctx, p, pop)->chrom;
486
487    for (n=0; n < envPtr->numParams; n++) {
488        fprintf(fp, "#%4d: ", n);
489        switch (paramPtr[n].type) {
490        case RP_OPTIMPARAM_NUMBER:
491            fprintf(fp, "[%11.7g] (%s)\n", paramPtr[n].value.dval,
492                paramPtr[n].name);
493            break;
494        case RP_OPTIMPARAM_STRING:
495            fprintf(fp, "[%d]=\"%s\" (%s)\n", paramPtr[n].value.sval.num,
496                paramPtr[n].value.sval.str, paramPtr[n].name);
497            break;
498        default:
499            panic("bad parameter type in PgapPrintString()");
500        }
501    }
502}
503
504/*
505 * ----------------------------------------------------------------------
506 * PgapCopyString()
507 *
508 * Called by pgapack to copy one input string to another.
509 * ----------------------------------------------------------------------
510 */
511void
512PgapCopyString(ctx, p1, pop1, p2, pop2)
513    PGAContext *ctx;  /* pgapack context for this optimization */
514    int p1;           /* source sample # being run */
515    int pop1;         /* population containing p1 */
516    int p2;           /* destination sample # being run */
517    int pop2;         /* population containing p1 */
518{
519    int n;
520    RpOptimEnv *envPtr;
521    RpOptimParam *src, *dst;
522
523    envPtr = PgapGetEnvForContext(ctx);
524    src = (RpOptimParam*)PGAGetIndividual(ctx, p1, pop1)->chrom;
525    dst = (RpOptimParam*)PGAGetIndividual(ctx, p2, pop2)->chrom;
526
527    for (n=0; n < envPtr->numParams; n++) {
528        dst[n].type = src[n].type;
529        switch (src[n].type) {
530        case RP_OPTIMPARAM_NUMBER:
531            dst[n].value.dval = src[n].value.dval;
532            break;
533        case RP_OPTIMPARAM_STRING:
534            dst[n].value.sval.num = src[n].value.sval.num;
535            dst[n].value.sval.str = src[n].value.sval.str;
536            break;
537        default:
538            panic("bad parameter type in PgapCopyString()");
539        }
540    }
541}
542
543/*
544 * ----------------------------------------------------------------------
545 * PgapDuplicateString()
546 *
547 * Called by pgapack to compare two input strings.  Returns non-zero if
548 * the two are duplicates and 0 otherwise.
549 * ----------------------------------------------------------------------
550 */
551int
552PgapDuplicateString(ctx, p1, pop1, p2, pop2)
553    PGAContext *ctx;  /* pgapack context for this optimization */
554    int p1;           /* sample #p being run */
555    int pop1;         /* population containing p1 */
556    int p2;           /* sample #p being run */
557    int pop2;         /* population containing p1 */
558{
559    int n;
560    RpOptimEnv *envPtr;
561    RpOptimParam *param1, *param2;
562
563    envPtr = PgapGetEnvForContext(ctx);
564    param1 = (RpOptimParam*)PGAGetIndividual(ctx, p1, pop1)->chrom;
565    param2 = (RpOptimParam*)PGAGetIndividual(ctx, p2, pop2)->chrom;
566
567    for (n=0; n < envPtr->numParams; n++) {
568        if (param1[n].type != param2[n].type) {
569            return 0;  /* different! */
570        }
571        switch (param1[n].type) {
572        case RP_OPTIMPARAM_NUMBER:
573            if (param1[n].value.dval != param2[n].value.dval) {
574                return 0;  /* different! */
575            }
576            break;
577        case RP_OPTIMPARAM_STRING:
578            if (param1[n].value.sval.num != param2[n].value.sval.num) {
579                return 0;  /* different! */
580            }
581            break;
582        default:
583            panic("bad parameter type in PgapDuplicateString()");
584        }
585    }
586    return 1;
587}
588
589
590
591/*
592 * ----------------------------------------------------------------------
593 * PgapCopyString()
594 *
595 * Called by pgapack to copy one input string to another.
596 * ----------------------------------------------------------------------
597 */
598MPI_Datatype
599PgapBuildDT(ctx, p, pop)
600    PGAContext *ctx;  /* pgapack context for this optimization */
601    int p;            /* sample # being run */
602    int pop;          /* population containing sample */
603{
604    panic("MPI support not implemented!");
605    return NULL;
606}
607
608/*
609 * ======================================================================
610 *  OPTION:  -operation <=> PGA_MINIMIZE / PGA_MAXIMIZE
611 * ======================================================================
612 */
613int
614RpOption_ParseOper(interp, valObj, cdata, offset)
615    Tcl_Interp *interp;  /* interpreter handling this request */
616    Tcl_Obj *valObj;     /* set option to this new value */
617    ClientData cdata;    /* save in this data structure */
618    int offset;          /* save at this offset in cdata */
619{
620    int *ptr = (int*)(cdata+offset);
621    char *val = Tcl_GetStringFromObj(valObj, (int*)NULL);
622    if (strcmp(val,"minimize") == 0) {
623        *ptr = PGA_MINIMIZE;
624    }
625    else if (strcmp(val,"maximize") == 0) {
626        *ptr = PGA_MAXIMIZE;
627    }
628    else {
629        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
630            "bad value \"", val, "\": should be minimize, maximize",
631            (char*)NULL);
632        return TCL_ERROR;
633    }
634    return TCL_OK;
635}
636
637int
638RpOption_GetOper(interp, cdata, offset)
639    Tcl_Interp *interp;  /* interpreter handling this request */
640    ClientData cdata;    /* get from this data structure */
641    int offset;          /* get from this offset in cdata */
642{
643    int *ptr = (int*)(cdata+offset);
644    switch (*ptr) {
645    case PGA_MINIMIZE:
646        Tcl_SetResult(interp, "minimize", TCL_STATIC);
647        break;
648    case PGA_MAXIMIZE:
649        Tcl_SetResult(interp, "maximize", TCL_STATIC);
650        break;
651    default:
652        Tcl_SetResult(interp, "???", TCL_STATIC);
653        break;
654    }
655    return TCL_OK;
656}
657
658/*
659 * ======================================================================
660 *  OPTION:  -poprepl <=> PGASetPopReplacementType()
661 * ======================================================================
662 */
663int
664RpOption_ParsePopRepl(interp, valObj, cdata, offset)
665    Tcl_Interp *interp;  /* interpreter handling this request */
666    Tcl_Obj *valObj;     /* set option to this new value */
667    ClientData cdata;    /* save in this data structure */
668    int offset;          /* save at this offset in cdata */
669{
670    int *ptr = (int*)(cdata+offset);
671    char *val = Tcl_GetStringFromObj(valObj, (int*)NULL);
672    if (*val == 'b' && strcmp(val,"best") == 0) {
673        *ptr = PGA_POPREPL_BEST;
674    }
675    else if (*val == 'r' && strcmp(val,"random-repl") == 0) {
676        *ptr = PGA_POPREPL_RANDOM_REP;
677    }
678    else if (*val == 'r' && strcmp(val,"random-norepl") == 0) {
679        *ptr = PGA_POPREPL_RANDOM_NOREP;
680    }
681    else {
682        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
683            "bad value \"", val, "\": should be best, random-norepl,"
684            " or random-repl", (char*)NULL);
685        return TCL_ERROR;
686    }
687    return TCL_OK;
688}
689
690int
691RpOption_GetPopRepl(interp, cdata, offset)
692    Tcl_Interp *interp;  /* interpreter handling this request */
693    ClientData cdata;    /* get from this data structure */
694    int offset;          /* get from this offset in cdata */
695{
696    int *ptr = (int*)(cdata+offset);
697    switch (*ptr) {
698    case PGA_POPREPL_BEST:
699        Tcl_SetResult(interp, "best", TCL_STATIC);
700        break;
701    case PGA_POPREPL_RANDOM_REP:
702        Tcl_SetResult(interp, "random-repl", TCL_STATIC);
703        break;
704    case PGA_POPREPL_RANDOM_NOREP:
705        Tcl_SetResult(interp, "random-norepl", TCL_STATIC);
706        break;
707    default:
708        Tcl_SetResult(interp, "???", TCL_STATIC);
709        break;
710    }
711    return TCL_OK;
712}
713
714/*
715 * ======================================================================
716 *  OPTION:  -stpcriteria <=> PGA_STOP_MAXITER / PGA_STOP_NOCHANGE / PGA_STOP_TOOSIMILAR
717 * ======================================================================
718 */
719int
720RpOption_ParseStpCriteria(interp, valObj, cdata, offset)
721    Tcl_Interp *interp;  /* interpreter handling this request */
722    Tcl_Obj *valObj;     /* set option to this new value */
723    ClientData cdata;    /* save in this data structure */
724    int offset;          /* save at this offset in cdata */
725{
726    int *ptr = (int*)(cdata+offset);
727    char *val = Tcl_GetStringFromObj(valObj, (int*)NULL);
728    if (strcmp(val,"maxiter") == 0) {
729        *ptr = PGA_STOP_MAXITER;
730    }
731    else if (strcmp(val,"nochange") == 0) {
732        *ptr = PGA_STOP_NOCHANGE;
733    }
734    else if (strcmp(val,"toosimilar") == 0){
735        *ptr = PGA_STOP_TOOSIMILAR;
736    }
737    else {
738        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
739            "bad value \"", val, "\": should be maxiter, nochange or toosimilar",
740            (char*)NULL);
741        return TCL_ERROR;
742    }
743    return TCL_OK;
744}
745
746int
747RpOption_GetStpCriteria(interp, cdata, offset)
748    Tcl_Interp *interp;  /* interpreter handling this request */
749    ClientData cdata;    /* get from this data structure */
750    int offset;          /* get from this offset in cdata */
751{
752    int *ptr = (int*)(cdata+offset);
753    switch (*ptr) {
754    case PGA_STOP_MAXITER:
755        Tcl_SetResult(interp, "maxiter", TCL_STATIC);
756        break;
757    case PGA_STOP_NOCHANGE:
758        Tcl_SetResult(interp, "nochange", TCL_STATIC);
759        break;
760    case PGA_STOP_TOOSIMILAR:
761        Tcl_SetResult(interp, "toosimilar", TCL_STATIC);
762        break;
763    default:
764        Tcl_SetResult(interp, "???", TCL_STATIC);
765        break;
766    }
767    return TCL_OK;
768}
769
770/*
771 * ======================================================================
772 *  ROUTINES FOR CONNECTING PGACONTEXT <=> RPOPTIMENV
773 * ======================================================================
774 * PgapLinkContext2Env()
775 *   This routine is used internally to establish a relationship between
776 *   a PGAContext token and its corresponding RpOptimEnv data.  The
777 *   PGA routines don't provide a way to pass the RpOptimEnv data along,
778 *   so we use these routines to find the correspondence.
779 *
780 * PgapGetEnvForContext()
781 *   Returns the RpOptimEnv associated with a given PGAContext.  If the
782 *   link has not been established via PgapLinkContext2Env(), then this
783 *   routine returns NULL.
784 *
785 * PgapUnlinkContext2Env()
786 *   Breaks the link between a PGAContext and its RpOptimEnv.  Should
787 *   be called when the PGAContext is destroyed and is no longer valid.
788 * ----------------------------------------------------------------------
789 */
790static Tcl_HashTable *Pgacontext2Rpenv = NULL;
791
792void
793PgapLinkContext2Env(ctx, envPtr)
794    PGAContext *ctx;      /* pgapack context for this optimization */
795    RpOptimEnv *envPtr;   /* corresponding Rappture optimization data */
796{
797    Tcl_HashEntry *ctxEntry;
798    int newEntry;
799
800    if (Pgacontext2Rpenv == NULL) {
801        Pgacontext2Rpenv = (Tcl_HashTable*)malloc(sizeof(Tcl_HashTable));
802        Tcl_InitHashTable(Pgacontext2Rpenv, TCL_ONE_WORD_KEYS);
803    }
804    ctxEntry = Tcl_CreateHashEntry(Pgacontext2Rpenv, (char*)ctx, &newEntry);
805    Tcl_SetHashValue(ctxEntry, (ClientData)envPtr);
806}
807
808RpOptimEnv*
809PgapGetEnvForContext(ctx)
810    PGAContext *ctx;
811{
812    Tcl_HashEntry *entryPtr;
813
814    if (Pgacontext2Rpenv) {
815        entryPtr = Tcl_FindHashEntry(Pgacontext2Rpenv, (char*)ctx);
816        if (entryPtr) {
817            return (RpOptimEnv*)Tcl_GetHashValue(entryPtr);
818        }
819    }
820    return NULL;
821}
822
823void
824PgapUnlinkContext2Env(ctx)
825    PGAContext *ctx;
826{
827    Tcl_HashEntry *entryPtr;
828
829    if (Pgacontext2Rpenv) {
830        entryPtr = Tcl_FindHashEntry(Pgacontext2Rpenv, (char*)ctx);
831        if (entryPtr) {
832            Tcl_DeleteHashEntry(entryPtr);
833        }
834    }
835}
836/*---------------------------------------------------------------------------------
837 * PGARuntimeDTInit(): It initializes the runtime data table.
838 * The table is organized slightly counter-intuitively
839 * Instead of a
840 *  param1|param2|param3  |param4...
841 *      val11 |val12 |val13   |val14...
842 *      val12 |val22 |val23   |val24....
843 * orientation, it is organized as
844 *      param1|val11|val12
845 *      param2|val21|val22
846 *      param3|val31|val32
847 *      param4|val41|val42
848 * Reallocating for additional columns is easier than reallocating additional rows and then
849 * reallocating for columns
850 * --------------------------------------------------------------------------------
851 */
852
853void PGARuntimeDataTableInit(envPtr)
854RpOptimEnv *envPtr;
855{   
856        int i;
857        if(envPtr != NULL){
858                table.num_of_rows = (envPtr->numParams)+1;
859                table.data = malloc((table.num_of_rows)*sizeof(double*));
860                if(table.data == NULL){
861                        panic("\nAllocation for Runtime Data Table failed\n");
862                }
863                for(i=0;i<table.num_of_rows;i++){
864                        table.data[i] = malloc(PGAPACK_RUNTIME_TABLE_DEFAULT_SIZE*sizeof(double));
865                        if(table.data[i] == NULL){
866                                panic("\nAllocation for Runtime Data Table failed\n");
867                        }                       
868                }
869                table.no_of_samples_evaled = 0;
870                table.no_of_columns = PGAPACK_RUNTIME_TABLE_DEFAULT_SIZE;
871               
872        }else{
873                panic("\nError: NULL Environment variable OR Table pointer passed to Data Table Init\n");
874        }
875}
876
877void PGARuntimeDataTableDeInit()
878{       
879        int i;
880        if((&table) == NULL){
881                panic("Error: Table not present, therefore cannot free memory..");
882        }
883        for(i=0;i<table.num_of_rows;i++){
884                free(table.data[i]);
885        }
886        free(table.data);
887}
888
889void PGARuntimeDataTableSetSampleValue(chrom,fitness)
890RpOptimParam *chrom;
891double fitness;
892{
893        int i;
894        printf("\nSetting sample value.......................\n");
895        if(chrom!=NULL && (&table)!=NULL){
896                (table.no_of_samples_evaled)+=1;
897                if((table.no_of_samples_evaled) > table.no_of_columns){
898                        /* then Reallocate space for more columns)*/
899                        (table.no_of_columns)+=(table.no_of_columns);
900                                //TODO GTG: Delete printing stuff
901                        for(i=0;i<(table.num_of_rows);i++){
902                                table.data[i] = realloc(table.data[i],table.no_of_columns);
903                                if(table.data[i]==NULL){
904                                        panic("\nError: Could not Reallocate more space for the table");
905                                }                               
906                        }
907                }else{
908                        if(chrom->type == RP_OPTIMPARAM_NUMBER){
909                                for(i=0;i<(table.num_of_rows);i++){
910                                        if(i==0){
911                                                table.data[i][(table.no_of_samples_evaled)-1] = fitness;
912                                                printf("\nSample Number %d:- Fitness: %lf\t",table.no_of_samples_evaled,fitness);
913                                        }else{
914                                                table.data[i][(table.no_of_samples_evaled)-1] = chrom[i-1].value.dval;
915                                                printf("Param %d %lf\t",i,table.data[i][(table.no_of_samples_evaled)-1]);
916                                        }
917                }
918                        }else{
919                                panic("\n Chromosome value is RP_OPTIMPARAM_STRING\n");
920                                //GTG TODO: find out what happens in this case. Will we be better off handling Tcl_objects?
921                        }       
922                }
923        }else{
924                panic("\nError:Either Chromosome, or table passed to PGARuntimeDataTableSetSampleValue() is NULL\n");
925        }
926       
927}
928
929void GetSampleInformation(buffer,sampleNumber)
930        char *buffer;
931        int sampleNumber;
932{
933        int i;
934        char tempBuff[50];
935        printf("\nFetching sample information.........................\n");
936        if((&table) == NULL){
937                panic("Table uninitialized");
938        }
939        if(sampleNumber<=0){
940                sprintf(buffer,"\nNumber of Samples Evaluated so far: %d\n",(table.no_of_samples_evaled)+1);
941                return;
942        }
943        if(((table.num_of_rows)-1)*10>SINGLE_SAMPLE_DATA_BUFFER_DEFAULT_SIZE){
944                buffer = realloc(buffer,50+25*(table.num_of_rows));
945                //resizing the buffer, keeping 50 for display related jazz, around 12-15 characs for param names
946                //and 10 characs for Fl.pt. display of the value
947                if(buffer == NULL){
948                        panic("\nError: Could not reallocate space for sample data buffer");
949                }
950        }
951        for(i=0;i<(table.num_of_rows);i++){
952                if(i==0){
953                        sprintf(buffer,"\nSample Number %d ----> Fitness: %lf  ",sampleNumber,table.data[i][sampleNumber-1]);
954                }else{
955                        sprintf(tempBuff,"Param %d: %lf  ",i,table.data[i][sampleNumber-1]);
956                        strcat(buffer,tempBuff);
957                }
958        }
959        strcat(buffer,"\n");
960}
Note: See TracBrowser for help on using the repository browser.