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

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

Committing changes related to command <name> samples ?number?

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