Changeset 898


Ignore:
Timestamp:
Feb 21, 2008 6:43:57 PM (15 years ago)
Author:
mmc
Message:

Optimization part is getting better. Fleshed out the plug-in for
PGApack, and integrated a first cut that includes the data handling.

Location:
trunk/optimizer
Files:
4 added
6 deleted
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/optimizer/src/Makefile.in

    r897 r898  
    396396          fi; \
    397397        done
    398         # Uncomment when you are ready to install tcl rappture library bindings
    399         #$(TCLSH_PROG) $(srcdir)/tclconfig/mkindex.tcl $(DESTDIR)$(pkglibdir)/scripts
    400         $(INSTALL_DATA) init.tcl $(DESTDIR)$(pkglibdir)/init.tcl
    401         @list='$(PKG_TCL_SOURCES)'; for p in $$list; do \
    402           if test -f $(srcdir)/$$p; then \
    403             destp=`basename $$p`; \
    404             echo " Install $$destp $(DESTDIR)$(pkglibdir)/$$destp"; \
    405             $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(pkglibdir)/$$destp; \
    406           fi; \
    407         done
    408398        @if test "x$(SHARED_BUILD)" = "x1"; then \
    409399            echo " Install pkgIndex.tcl $(DESTDIR)$(pkglibdir)"; \
  • trunk/optimizer/src/configure.in

    r897 r898  
    7474TEA_ADD_SOURCES([rp_optimizer.c rp_tcloptions.c rp_optimizer_tcl.c plugin_pgapack.c])
    7575TEA_ADD_HEADERS([])
    76 TEA_ADD_INCLUDES([])
    77 TEA_ADD_CFLAGS([])
     76TEA_ADD_INCLUDES([-Ipgapack/pgapack/include])
     77TEA_ADD_CFLAGS([-DWL=32])
    7878TEA_ADD_STUB_SOURCES([])
    7979# uncomment this and mkindex.tcl line in makefile when you are ready to
     
    8181#TEA_ADD_TCL_SOURCES([scripts/exec.tcl scripts/value.tcl init.tcl ../../tcl/scripts/library.tcl ../../tcl/scripts/result.tcl])
    8282TEA_ADD_TCL_SOURCES([])
     83TEA_ADD_LIBS([-Lpgapack/pgapack/lib/linux -lpgaO])
    8384
    8485#--------------------------------------------------------------------
  • trunk/optimizer/src/plugin_pgapack.c

    r897 r898  
    1414 * ======================================================================
    1515 */
     16#include "pgapack.h"
    1617#include "rp_optimizer_plugin.h"
    1718
    1819typedef struct PgapackData {
    19     int foo;                        /* data used by Pgapack... */
     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() */
    2024} PgapackData;
    2125
     26RpCustomTclOptionParse RpOption_ParseOper;
     27RpCustomTclOptionGet RpOption_GetOper;
     28RpTclOptionType RpOption_Oper = {
     29    "pga_operation", RpOption_ParseOper, RpOption_GetOper, NULL
     30};
     31
     32RpCustomTclOptionParse RpOption_ParsePopRepl;
     33RpCustomTclOptionGet RpOption_GetPopRepl;
     34RpTclOptionType RpOption_PopRepl = {
     35    "pga_poprepl", RpOption_ParsePopRepl, RpOption_GetPopRepl, NULL
     36};
     37
    2238RpTclOption PgapackOptions[] = {
    23   {"-foo", RP_OPTION_INT, NULL, Rp_Offset(PgapackData,foo)},
    24   {NULL, NULL, NULL, 0}
     39  {"-maxruns", RP_OPTION_INT, Rp_Offset(PgapackData,maxRuns)},
     40  {"-operation", &RpOption_Oper, Rp_Offset(PgapackData,operation)},
     41  {"-poprepl", &RpOption_PopRepl, Rp_Offset(PgapackData,popRepl)},
     42  {"-popsize", RP_OPTION_INT, Rp_Offset(PgapackData,popSize)},
     43  {NULL, NULL, 0}
    2544};
     45
     46static double PgapEvaluate _ANSI_ARGS_((PGAContext *ctx, int p, int pop));
     47static void PgapCreateString _ANSI_ARGS_((PGAContext *ctx, int, int, int));
     48static int PgapMutation _ANSI_ARGS_((PGAContext *ctx, int, int, double));
     49static void PgapCrossover _ANSI_ARGS_((PGAContext *ctx, int, int, int,
     50    int, int, int));
     51static void PgapPrintString _ANSI_ARGS_((PGAContext *ctx, FILE*, int, int));
     52static void PgapCopyString _ANSI_ARGS_((PGAContext *ctx, int, int, int, int));
     53static int PgapDuplicateString _ANSI_ARGS_((PGAContext *ctx, int, int, int, int));
     54static MPI_Datatype PgapBuildDT _ANSI_ARGS_((PGAContext *ctx, int, int));
     55
     56static void PgapLinkContext2Env _ANSI_ARGS_((PGAContext *ctx,
     57    RpOptimEnv *envPtr));
     58static RpOptimEnv* PgapGetEnvForContext _ANSI_ARGS_((PGAContext *ctx));
     59static void PgapUnlinkContext2Env _ANSI_ARGS_((PGAContext *ctx));
     60
    2661
    2762/*
     
    3873{
    3974    PgapackData *dataPtr;
     75
    4076    dataPtr = (PgapackData*)malloc(sizeof(PgapackData));
    41     dataPtr->foo = 1;
     77    dataPtr->operation = PGA_MINIMIZE;
     78    dataPtr->maxRuns = 10000;
     79    dataPtr->popRepl = PGA_POPREPL_BEST;
     80    dataPtr->popSize = 200;
     81
    4282    return (ClientData)dataPtr;
     83}
     84
     85/*
     86 * ----------------------------------------------------------------------
     87 * PgapackRun()
     88 *
     89 * This routine is called to kick off an optimization run.  Sets up
     90 * a PGApack context and starts invoking runs.
     91 * ----------------------------------------------------------------------
     92 */
     93RpOptimStatus
     94PgapackRun(envPtr, evalProc)
     95    RpOptimEnv *envPtr;           /* optimization environment */
     96    RpOptimEvaluator *evalProc;   /* call this proc to run tool */
     97{
     98    PgapackData *dataPtr =(PgapackData*)envPtr->pluginData;
     99    PGAContext *ctx;
     100
     101    /* pgapack requires at least one arg -- the executable name */
     102    /* fake it here by just saying something like "rappture" */
     103    int argc = 1; char *argv[] = {"rappture"};
     104
     105    ctx = PGACreate(&argc, argv, PGA_DATATYPE_USER, envPtr->numParams,
     106        dataPtr->operation);
     107
     108    PGASetMaxGAIterValue(ctx, dataPtr->maxRuns);
     109    PGASetPopSize(ctx, dataPtr->popSize);
     110    PGASetPopReplaceType(ctx, dataPtr->popRepl);
     111
     112    PGASetUserFunction(ctx, PGA_USERFUNCTION_CREATESTRING, PgapCreateString);
     113    PGASetUserFunction(ctx, PGA_USERFUNCTION_MUTATION, PgapMutation);
     114    PGASetUserFunction(ctx, PGA_USERFUNCTION_CROSSOVER, PgapCrossover);
     115    PGASetUserFunction(ctx, PGA_USERFUNCTION_PRINTSTRING, PgapPrintString);
     116    PGASetUserFunction(ctx, PGA_USERFUNCTION_COPYSTRING, PgapCopyString);
     117    PGASetUserFunction(ctx, PGA_USERFUNCTION_DUPLICATE, PgapDuplicateString);
     118    PGASetUserFunction(ctx, PGA_USERFUNCTION_BUILDDATATYPE, PgapBuildDT);
     119
     120    envPtr->evalProc = evalProc;  /* call this later for evaluations */
     121
     122    /*
     123     * We need a way to convert from a PGAContext to our RpOptimEnv
     124     * data.  This happens when Pgapack calls routines like
     125     * PgapCreateString, passing in the PGAContext, but nothing else.
     126     * Call PgapLinkContext2Env() here, so later on we can figure
     127     * out how many parameters, names, types, etc.
     128     */
     129    PgapLinkContext2Env(ctx, envPtr);
     130
     131    PGASetUp(ctx);
     132    PGARun(ctx, PgapEvaluate);
     133    PGADestroy(ctx);
     134
     135    PgapUnlinkContext2Env(ctx);
     136
     137    return RP_OPTIM_SUCCESS;
     138}
     139
     140/*
     141 * ----------------------------------------------------------------------
     142 * PgapackEvaluate()
     143 *
     144 * Called by PGApack whenever a set of input values needs to be
     145 * evaluated.  Passes the values on to the underlying Rappture tool,
     146 * launches a run, and computes the value of the fitness function.
     147 * Returns the value for the fitness function.
     148 * ----------------------------------------------------------------------
     149 */
     150double
     151PgapEvaluate(ctx, p, pop)
     152    PGAContext *ctx;  /* pgapack context for this optimization */
     153    int p;            /* sample #p being run */
     154    int pop;          /* identifier for this population */
     155{
     156    double fit = 0.0;
     157    RpOptimEnv *envPtr;
     158    RpOptimParam *paramPtr;
     159    RpOptimStatus status;
     160
     161    envPtr = PgapGetEnvForContext(ctx);
     162    paramPtr = (RpOptimParam*)PGAGetIndividual(ctx, p, pop)->chrom;
     163
     164    status = (*envPtr->evalProc)(envPtr, paramPtr, envPtr->numParams, &fit);
     165
     166    if (status != RP_OPTIM_SUCCESS) {
     167        fprintf(stderr, "==WARNING: run failed!");
     168        PgapPrintString(ctx, stderr, p, pop);
     169    }
     170
     171    return fit;
    43172}
    44173
     
    57186{
    58187    PgapackData *dataPtr = (PgapackData*)cdata;
    59     dataPtr->foo = 0;
    60188    free(dataPtr);
    61189}
     190
     191/*
     192 * ======================================================================
     193 *  ROUTINES FOR MANAGING DATA STRINGS
     194 * ======================================================================
     195 * PgapCreateString()
     196 *
     197 * Called by pgapack to create the so-called "string" of data used for
     198 * an evaluation.
     199 * ----------------------------------------------------------------------
     200 */
     201void
     202PgapCreateString(ctx, p, pop, initFlag)
     203    PGAContext *ctx;  /* pgapack context for this optimization */
     204    int p;            /* sample #p being run */
     205    int pop;          /* identifier for this population */
     206    int initFlag;     /* non-zero => fields should be initialized */
     207{
     208    int n, ival;
     209    double dval;
     210    RpOptimEnv *envPtr;
     211    RpOptimParam *oldParamPtr, *newParamPtr;
     212    PGAIndividual *newData;
     213    RpOptimParamNumber *numPtr;
     214    RpOptimParamString *strPtr;
     215
     216    envPtr = PgapGetEnvForContext(ctx);
     217
     218    newData = PGAGetIndividual(ctx, p, pop);
     219    newData->chrom = malloc(envPtr->numParams*sizeof(RpOptimParam));
     220    newParamPtr = (RpOptimParam*)newData->chrom;
     221
     222    for (n=0; n < envPtr->numParams; n++) {
     223        oldParamPtr = envPtr->paramList[n];
     224        newParamPtr[n].name = oldParamPtr->name;
     225        newParamPtr[n].type = oldParamPtr->type;
     226        switch (oldParamPtr->type) {
     227        case RP_OPTIMPARAM_NUMBER:
     228            newParamPtr[n].value.dval = 0.0;
     229            break;
     230        case RP_OPTIMPARAM_STRING:
     231            newParamPtr[n].value.sval.num = -1;
     232            newParamPtr[n].value.sval.str = NULL;
     233            break;
     234        default:
     235            panic("bad parameter type in PgapCreateString()");
     236        }
     237    }
     238
     239    if (initFlag) {
     240        for (n=0; n < envPtr->numParams; n++) {
     241            switch (newParamPtr[n].type) {
     242            case RP_OPTIMPARAM_NUMBER:
     243                numPtr = (RpOptimParamNumber*)envPtr->paramList[n];
     244                dval = PGARandom01(ctx,0);
     245                newParamPtr[n].value.dval =
     246                    (numPtr->max - numPtr->min)*dval + numPtr->min;
     247                break;
     248            case RP_OPTIMPARAM_STRING:
     249                strPtr = (RpOptimParamString*)envPtr->paramList[n];
     250                ival = (int)floor(PGARandom01(ctx,0) * strPtr->numValues);
     251                envPtr->paramList[n]->value.sval.num = ival;
     252                envPtr->paramList[n]->value.sval.str = strPtr->values[ival];
     253                break;
     254            default:
     255                panic("bad parameter type in PgapCreateString()");
     256            }
     257        }
     258    }
     259}
     260
     261/*
     262 * ----------------------------------------------------------------------
     263 * PgapMutation()
     264 *
     265 * Called by pgapack to perform random mutations on the input data
     266 * used for evaluation.
     267 * ----------------------------------------------------------------------
     268 */
     269int
     270PgapMutation(ctx, p, pop, mr)
     271    PGAContext *ctx;  /* pgapack context for this optimization */
     272    int p;            /* sample #p being run */
     273    int pop;          /* identifier for this population */
     274    double mr;        /* probability of mutation for each gene */
     275{
     276    int count = 0;    /* number of mutations */
     277
     278    int n, ival;
     279    RpOptimEnv *envPtr;
     280    RpOptimParam *paramPtr;
     281    RpOptimParamNumber *numPtr;
     282    RpOptimParamString *strPtr;
     283
     284    envPtr = PgapGetEnvForContext(ctx);
     285    paramPtr = (RpOptimParam*)PGAGetIndividual(ctx, p, pop)->chrom;
     286
     287    for (n=0; n < envPtr->numParams; n++) {
     288        if (PGARandomFlip(ctx, mr)) {
     289            /* won the coin toss -- change this parameter */
     290            count++;
     291
     292            switch (paramPtr[n].type) {
     293            case RP_OPTIMPARAM_NUMBER:
     294                /* bump the value up/down a little, randomly */
     295                if (PGARandomFlip(ctx, 0.5)) {
     296                    paramPtr[n].value.dval += 0.1*paramPtr[n].value.dval;
     297                } else {
     298                    paramPtr[n].value.dval -= 0.1*paramPtr[n].value.dval;
     299                }
     300                /* make sure the resulting value is still in bounds */
     301                numPtr = (RpOptimParamNumber*)envPtr->paramList[n];
     302                if (paramPtr[n].value.dval > numPtr->max) {
     303                    paramPtr[n].value.dval = numPtr->max;
     304                }
     305                if (paramPtr[n].value.dval < numPtr->min) {
     306                    paramPtr[n].value.dval = numPtr->min;
     307                }
     308                break;
     309
     310            case RP_OPTIMPARAM_STRING:
     311                ival = paramPtr[n].value.sval.num;
     312                if (PGARandomFlip(ctx, 0.5)) {
     313                    ival += 1;
     314                } else {
     315                    ival -= 1;
     316                }
     317                strPtr = (RpOptimParamString*)envPtr->paramList[n];
     318                if (ival < 0) ival = 0;
     319                if (ival >= strPtr->numValues) ival = strPtr->numValues-1;
     320                paramPtr[n].value.sval.num = ival;
     321                paramPtr[n].value.sval.str = strPtr->values[ival];
     322                break;
     323
     324            default:
     325                panic("bad parameter type in PgapMutation()");
     326            }
     327        }
     328    }
     329    return count;
     330}
     331
     332/*
     333 * ----------------------------------------------------------------------
     334 * PgapCrossover()
     335 *
     336 * Called by pgapack to perform cross-over mutations on the input data
     337 * used for evaluation.
     338 * ----------------------------------------------------------------------
     339 */
     340void
     341PgapCrossover(ctx, p1, p2, pop1, c1, c2, pop2)
     342    PGAContext *ctx;  /* pgapack context for this optimization */
     343    int p1;           /* sample # for parent of input string1 */
     344    int p2;           /* sample # for parent of input string2 */
     345    int pop1;         /* population containing p1 and p2 */
     346    int c1;           /* sample # for child of input string1 */
     347    int c2;           /* sample # for child of input string2 */
     348    int pop2;         /* population containing c1 and c2 */
     349{
     350    int n;
     351    RpOptimEnv *envPtr;
     352    RpOptimParam *parent1, *parent2, *child1, *child2;
     353    double pu;
     354
     355    envPtr = PgapGetEnvForContext(ctx);
     356    parent1 = (RpOptimParam*)PGAGetIndividual(ctx, p1, pop1)->chrom;
     357    parent2 = (RpOptimParam*)PGAGetIndividual(ctx, p2, pop1)->chrom;
     358    child1  = (RpOptimParam*)PGAGetIndividual(ctx, c1, pop2)->chrom;
     359    child2  = (RpOptimParam*)PGAGetIndividual(ctx, c2, pop2)->chrom;
     360
     361    pu = PGAGetUniformCrossoverProb(ctx);
     362
     363    for (n=0; n < envPtr->numParams; n++) {
     364        if (PGARandomFlip(ctx, pu)) {
     365            /* child inherits from parent */
     366            memcpy(&child1[n], &parent1[n], sizeof(RpOptimParam));
     367            memcpy(&child2[n], &parent2[n], sizeof(RpOptimParam));
     368        } else {
     369            /* crossover */
     370            memcpy(&child1[n], &parent2[n], sizeof(RpOptimParam));
     371            memcpy(&child2[n], &parent1[n], sizeof(RpOptimParam));
     372        }
     373    }
     374}
     375
     376/*
     377 * ----------------------------------------------------------------------
     378 * PgapPrintString()
     379 *
     380 * Called by pgapack to format the values for a particular string of
     381 * input data.
     382 * ----------------------------------------------------------------------
     383 */
     384void
     385PgapPrintString(ctx, fp, p, pop)
     386    PGAContext *ctx;  /* pgapack context for this optimization */
     387    FILE *fp;         /* write to this file pointer */
     388    int p;            /* sample #p being run */
     389    int pop;          /* identifier for this population */
     390{
     391    int n;
     392    RpOptimEnv *envPtr;
     393    RpOptimParam *paramPtr;
     394
     395    envPtr = PgapGetEnvForContext(ctx);
     396    paramPtr = (RpOptimParam*)PGAGetIndividual(ctx, p, pop)->chrom;
     397
     398    for (n=0; n < envPtr->numParams; n++) {
     399        fprintf(fp, "#%4d: ", n);
     400        switch (paramPtr[n].type) {
     401        case RP_OPTIMPARAM_NUMBER:
     402            fprintf(fp, "[%11.7g] (%s)\n", paramPtr[n].value.dval,
     403                paramPtr[n].name);
     404            break;
     405        case RP_OPTIMPARAM_STRING:
     406            fprintf(fp, "[%d]=\"%s\" (%s)\n", paramPtr[n].value.sval.num,
     407                paramPtr[n].value.sval.str, paramPtr[n].name);
     408            break;
     409        default:
     410            panic("bad parameter type in PgapPrintString()");
     411        }
     412    }
     413}
     414
     415/*
     416 * ----------------------------------------------------------------------
     417 * PgapCopyString()
     418 *
     419 * Called by pgapack to copy one input string to another.
     420 * ----------------------------------------------------------------------
     421 */
     422void
     423PgapCopyString(ctx, p1, pop1, p2, pop2)
     424    PGAContext *ctx;  /* pgapack context for this optimization */
     425    int p1;           /* source sample # being run */
     426    int pop1;         /* population containing p1 */
     427    int p2;           /* destination sample # being run */
     428    int pop2;         /* population containing p1 */
     429{
     430    int n;
     431    RpOptimEnv *envPtr;
     432    RpOptimParam *src, *dst;
     433
     434    envPtr = PgapGetEnvForContext(ctx);
     435    src = (RpOptimParam*)PGAGetIndividual(ctx, p1, pop1)->chrom;
     436    dst = (RpOptimParam*)PGAGetIndividual(ctx, p2, pop2)->chrom;
     437
     438    for (n=0; n < envPtr->numParams; n++) {
     439        dst[n].type = src[n].type;
     440        switch (src[n].type) {
     441        case RP_OPTIMPARAM_NUMBER:
     442            dst[n].value.dval = src[n].value.dval;
     443            break;
     444        case RP_OPTIMPARAM_STRING:
     445            dst[n].value.sval.num = src[n].value.sval.num;
     446            dst[n].value.sval.str = src[n].value.sval.str;
     447            break;
     448        default:
     449            panic("bad parameter type in PgapCopyString()");
     450        }
     451    }
     452}
     453
     454/*
     455 * ----------------------------------------------------------------------
     456 * PgapDuplicateString()
     457 *
     458 * Called by pgapack to compare two input strings.  Returns non-zero if
     459 * the two are duplicates and 0 otherwise.
     460 * ----------------------------------------------------------------------
     461 */
     462int
     463PgapDuplicateString(ctx, p1, pop1, p2, pop2)
     464    PGAContext *ctx;  /* pgapack context for this optimization */
     465    int p1;           /* sample #p being run */
     466    int pop1;         /* population containing p1 */
     467    int p2;           /* sample #p being run */
     468    int pop2;         /* population containing p1 */
     469{
     470    int n;
     471    RpOptimEnv *envPtr;
     472    RpOptimParam *param1, *param2;
     473
     474    envPtr = PgapGetEnvForContext(ctx);
     475    param1 = (RpOptimParam*)PGAGetIndividual(ctx, p1, pop1)->chrom;
     476    param2 = (RpOptimParam*)PGAGetIndividual(ctx, p2, pop2)->chrom;
     477
     478    for (n=0; n < envPtr->numParams; n++) {
     479        if (param1[n].type != param2[n].type) {
     480            return 0;  /* different! */
     481        }
     482        switch (param1[n].type) {
     483        case RP_OPTIMPARAM_NUMBER:
     484            if (param1[n].value.dval != param2[n].value.dval) {
     485                return 0;  /* different! */
     486            }
     487            break;
     488        case RP_OPTIMPARAM_STRING:
     489            if (param1[n].value.sval.num != param2[n].value.sval.num) {
     490                return 0;  /* different! */
     491            }
     492            break;
     493        default:
     494            panic("bad parameter type in PgapDuplicateString()");
     495        }
     496    }
     497    return 1;
     498}
     499
     500/*
     501 * ----------------------------------------------------------------------
     502 * PgapCopyString()
     503 *
     504 * Called by pgapack to copy one input string to another.
     505 * ----------------------------------------------------------------------
     506 */
     507MPI_Datatype
     508PgapBuildDT(ctx, p, pop)
     509    PGAContext *ctx;  /* pgapack context for this optimization */
     510    int p;            /* sample # being run */
     511    int pop;          /* population containing sample */
     512{
     513    panic("MPI support not implemented!");
     514    return NULL;
     515}
     516
     517/*
     518 * ======================================================================
     519 *  OPTION:  -operation <=> PGA_MINIMIZE / PGA_MAXIMIZE
     520 * ======================================================================
     521 */
     522int
     523RpOption_ParseOper(interp, valObj, cdata, offset)
     524    Tcl_Interp *interp;  /* interpreter handling this request */
     525    Tcl_Obj *valObj;     /* set option to this new value */
     526    ClientData cdata;    /* save in this data structure */
     527    int offset;          /* save at this offset in cdata */
     528{
     529    int *ptr = (int*)(cdata+offset);
     530    char *val = Tcl_GetStringFromObj(valObj, (int*)NULL);
     531    if (strcmp(val,"minimize") == 0) {
     532        *ptr = PGA_MINIMIZE;
     533    }
     534    else if (strcmp(val,"maximize") == 0) {
     535        *ptr = PGA_MAXIMIZE;
     536    }
     537    else {
     538        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
     539            "bad value \"", val, "\": should be minimize, maximize",
     540            (char*)NULL);
     541        return TCL_ERROR;
     542    }
     543    return TCL_OK;
     544}
     545
     546int
     547RpOption_GetOper(interp, cdata, offset)
     548    Tcl_Interp *interp;  /* interpreter handling this request */
     549    ClientData cdata;    /* get from this data structure */
     550    int offset;          /* get from this offset in cdata */
     551{
     552    int *ptr = (int*)(cdata+offset);
     553    switch (*ptr) {
     554    case PGA_MINIMIZE:
     555        Tcl_SetResult(interp, "minimize", TCL_STATIC);
     556        break;
     557    case PGA_MAXIMIZE:
     558        Tcl_SetResult(interp, "maximize", TCL_STATIC);
     559        break;
     560    default:
     561        Tcl_SetResult(interp, "???", TCL_STATIC);
     562        break;
     563    }
     564    return TCL_OK;
     565}
     566
     567/*
     568 * ======================================================================
     569 *  OPTION:  -poprepl <=> PGASetPopReplacementType()
     570 * ======================================================================
     571 */
     572int
     573RpOption_ParsePopRepl(interp, valObj, cdata, offset)
     574    Tcl_Interp *interp;  /* interpreter handling this request */
     575    Tcl_Obj *valObj;     /* set option to this new value */
     576    ClientData cdata;    /* save in this data structure */
     577    int offset;          /* save at this offset in cdata */
     578{
     579    int *ptr = (int*)(cdata+offset);
     580    char *val = Tcl_GetStringFromObj(valObj, (int*)NULL);
     581    if (*val == 'b' && strcmp(val,"best") == 0) {
     582        *ptr = PGA_POPREPL_BEST;
     583    }
     584    else if (*val == 'r' && strcmp(val,"random-repl") == 0) {
     585        *ptr = PGA_POPREPL_RANDOM_REP;
     586    }
     587    else if (*val == 'r' && strcmp(val,"random-norepl") == 0) {
     588        *ptr = PGA_POPREPL_RANDOM_NOREP;
     589    }
     590    else {
     591        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
     592            "bad value \"", val, "\": should be best, random-norepl,"
     593            " or random-repl", (char*)NULL);
     594        return TCL_ERROR;
     595    }
     596    return TCL_OK;
     597}
     598
     599int
     600RpOption_GetPopRepl(interp, cdata, offset)
     601    Tcl_Interp *interp;  /* interpreter handling this request */
     602    ClientData cdata;    /* get from this data structure */
     603    int offset;          /* get from this offset in cdata */
     604{
     605    int *ptr = (int*)(cdata+offset);
     606    switch (*ptr) {
     607    case PGA_POPREPL_BEST:
     608        Tcl_SetResult(interp, "best", TCL_STATIC);
     609        break;
     610    case PGA_POPREPL_RANDOM_REP:
     611        Tcl_SetResult(interp, "random-repl", TCL_STATIC);
     612        break;
     613    case PGA_POPREPL_RANDOM_NOREP:
     614        Tcl_SetResult(interp, "random-norepl", TCL_STATIC);
     615        break;
     616    default:
     617        Tcl_SetResult(interp, "???", TCL_STATIC);
     618        break;
     619    }
     620    return TCL_OK;
     621}
     622
     623/*
     624 * ======================================================================
     625 *  ROUTINES FOR CONNECTING PGACONTEXT <=> RPOPTIMENV
     626 * ======================================================================
     627 * PgapLinkContext2Env()
     628 *   This routine is used internally to establish a relationship between
     629 *   a PGAContext token and its corresponding RpOptimEnv data.  The
     630 *   PGA routines don't provide a way to pass the RpOptimEnv data along,
     631 *   so we use these routines to find the correspondence.
     632 *
     633 * PgapGetEnvForContext()
     634 *   Returns the RpOptimEnv associated with a given PGAContext.  If the
     635 *   link has not been established via PgapLinkContext2Env(), then this
     636 *   routine returns NULL.
     637 *
     638 * PgapUnlinkContext2Env()
     639 *   Breaks the link between a PGAContext and its RpOptimEnv.  Should
     640 *   be called when the PGAContext is destroyed and is no longer valid.
     641 * ----------------------------------------------------------------------
     642 */
     643static Tcl_HashTable *Pgacontext2Rpenv = NULL;
     644
     645void
     646PgapLinkContext2Env(ctx, envPtr)
     647    PGAContext *ctx;      /* pgapack context for this optimization */
     648    RpOptimEnv *envPtr;   /* corresponding Rappture optimization data */
     649{
     650    Tcl_HashEntry *ctxEntry;
     651    int newEntry;
     652
     653    if (Pgacontext2Rpenv == NULL) {
     654        Pgacontext2Rpenv = (Tcl_HashTable*)malloc(sizeof(Tcl_HashTable));
     655        Tcl_InitHashTable(Pgacontext2Rpenv, TCL_ONE_WORD_KEYS);
     656    }
     657    ctxEntry = Tcl_CreateHashEntry(Pgacontext2Rpenv, (char*)ctx, &newEntry);
     658    Tcl_SetHashValue(ctxEntry, (ClientData)envPtr);
     659}
     660
     661RpOptimEnv*
     662PgapGetEnvForContext(ctx)
     663    PGAContext *ctx;
     664{
     665    Tcl_HashEntry *entryPtr;
     666
     667    if (Pgacontext2Rpenv) {
     668        entryPtr = Tcl_FindHashEntry(Pgacontext2Rpenv, (char*)ctx);
     669        if (entryPtr) {
     670            return (RpOptimEnv*)Tcl_GetHashValue(entryPtr);
     671        }
     672    }
     673    return NULL;
     674}
     675
     676void
     677PgapUnlinkContext2Env(ctx)
     678    PGAContext *ctx;
     679{
     680    Tcl_HashEntry *entryPtr;
     681
     682    if (Pgacontext2Rpenv) {
     683        entryPtr = Tcl_FindHashEntry(Pgacontext2Rpenv, (char*)ctx);
     684        if (entryPtr) {
     685            Tcl_DeleteHashEntry(entryPtr);
     686        }
     687    }
     688}
  • trunk/optimizer/src/rp_optimizer.c

    r897 r898  
    3333 */
    3434RpOptimEnv*
    35 RpOptimCreate(pluginData, cleanupPtr)
     35RpOptimCreate(pluginData, cleanupProc)
    3636    ClientData pluginData;        /* special data created for this env */
    37     RpOptimCleanup *cleanupPtr;   /* routine to clean up pluginData */
     37    RpOptimCleanup *cleanupProc;  /* routine to clean up pluginData */
    3838{
    3939    RpOptimEnv *envPtr;
    4040    envPtr = (RpOptimEnv*)malloc(sizeof(RpOptimEnv));
    41     envPtr->pluginData = pluginData;
    42     envPtr->cleanupPtr = cleanupPtr;
     41    envPtr->pluginData  = pluginData;
     42    envPtr->cleanupProc = cleanupProc;
     43    envPtr->toolData    = NULL;
    4344
    4445    envPtr->numParams = 0;
     
    106107    numPtr->base.name = strdup(name);
    107108    numPtr->base.type = RP_OPTIMPARAM_NUMBER;
    108     numPtr->base.value.num = 0.0;
     109    numPtr->base.value.dval = 0.0;
    109110    numPtr->min = -DBL_MAX;
    110111    numPtr->max = DBL_MAX;
     
    134135    strPtr->base.name = strdup(name);
    135136    strPtr->base.type = RP_OPTIMPARAM_STRING;
    136     strPtr->base.value.str = NULL;
     137    strPtr->base.value.sval.num = -1;
     138    strPtr->base.value.sval.str = NULL;
    137139    strPtr->values = NULL;
     140    strPtr->numValues = 0;
    138141
    139142    RpOptimAddParam(envPtr, (RpOptimParam*)strPtr);
     
    194197/*
    195198 * ----------------------------------------------------------------------
    196  * RpOptimPerform()
    197  *
    198  * Used to perform an optimization in the given context.  Each run is
    199  * performed by calling an evaluation function represented by a
    200  * function pointer.  If an optimum value is found within the limit
    201  * on the number of runs, then this procedure returns RP_OPTIM_SUCCESS.
    202  * Values for the optimum input parameters are returned through the
    203  * paramList within the context.  If the optimization fails, this
    204  * function returns RP_OPTIM_FAILURE.
    205  * ----------------------------------------------------------------------
    206  */
    207 RpOptimStatus
    208 RpOptimPerform(envPtr, evalFuncPtr, maxRuns)
    209     RpOptimEnv *envPtr;               /* context for this optimization */
    210     RpOptimEvaluator *evalFuncPtr;    /* function called to handle run */
    211     int maxRuns;                      /* limit on number of runs,
    212                                        * or 0 for no limit */
    213 {
    214     RpOptimStatus status = RP_OPTIM_UNKNOWN;
    215 
    216     int n, nruns, ival, nvals;
    217     double dval, fitness;
    218     RpOptimParamNumber *numPtr;
    219     RpOptimParamString *strPtr;
    220     RpOptimStatus runStatus;
    221 
    222     if (envPtr->numParams == 0) {    /* no input parameters? */
    223         return RP_OPTIM_FAILURE;     /* then we can't optimize! */
    224     }
    225 
    226     /*
    227      * Call the evaluation function a number of times with different
    228      * values and perform the optimization.
    229      */
    230     nruns = 0;
    231     while (status == RP_OPTIM_UNKNOWN) {
    232         /*
    233          * Pick random values for all inputs.
    234          */
    235         for (n=0; n < envPtr->numParams; n++) {
    236             switch (envPtr->paramList[n]->type) {
    237                 case RP_OPTIMPARAM_NUMBER:
    238                     numPtr = (RpOptimParamNumber*)envPtr->paramList[n];
    239                     dval = drand48();
    240                     envPtr->paramList[n]->value.num =
    241                         (numPtr->max - numPtr->min)*dval + numPtr->min;
    242                     break;
    243                 case RP_OPTIMPARAM_STRING:
    244                     strPtr = (RpOptimParamString*)envPtr->paramList[n];
    245                     for (nvals=0; strPtr->values[nvals]; nvals++)
    246                         ;  /* count values */
    247                     ival = (int)floor(drand48() * nvals);
    248                     envPtr->paramList[n]->value.str = strPtr->values[ival];
    249                     break;
    250             }
    251         }
    252 
    253         /*
    254          * Call the evaluation function to get the fitness value.
    255          */
    256         runStatus = (*evalFuncPtr)(envPtr->paramList, envPtr->numParams,
    257             &fitness);
    258 
    259         if (runStatus == RP_OPTIM_SUCCESS) {
    260             /*
    261              * Is the fitness function any better?
    262              * Change the input values here based on fitness.
    263              *  ...
    264              */
    265         }
    266 
    267         if (++nruns >= maxRuns && maxRuns > 0) {
    268             status = RP_OPTIM_FAILURE;  /* reached the limit of runs */
    269         }
    270     }
    271 
    272     return status;
    273 }
    274 
    275 /*
    276  * ----------------------------------------------------------------------
    277199 * RpOptimDelete()
    278200 *
     
    292214        RpOptimCleanupParam(envPtr->paramList[n]);
    293215    }
    294     if (envPtr->cleanupPtr) {
    295         (*envPtr->cleanupPtr)(envPtr->pluginData);
     216    if (envPtr->cleanupProc) {
     217        (*envPtr->cleanupProc)(envPtr->pluginData);
    296218    }
    297219    free(envPtr->paramList);
  • trunk/optimizer/src/rp_optimizer.h

    r897 r898  
    3232
    3333/*
     34 * During each optimization, a function of the following type is
     35 * called again and again to evaluate input parameters and compute
     36 * the fitness function.
     37 */
     38typedef enum {
     39    RP_OPTIM_SUCCESS=0, RP_OPTIM_UNKNOWN, RP_OPTIM_FAILURE, RP_OPTIM_ABORTED
     40} RpOptimStatus;
     41
     42struct RpOptimEnv;   /* defined below */
     43struct RpOptimParam;
     44
     45typedef RpOptimStatus (RpOptimEvaluator) _ANSI_ARGS_((
     46    struct RpOptimEnv *envPtr, struct RpOptimParam *values, int numValues,
     47    double *fitnessPtr));
     48
     49typedef RpOptimStatus (RpOptimHandler) _ANSI_ARGS_((
     50    struct RpOptimEnv *envPtr, RpOptimEvaluator *evalProc));
     51
     52/*
    3453 * This is the basic definition for each parameter within an optimization.
    3554 * Each parameter has a name, type, and value.  The value is important
     
    4160} RpOptimParamType;
    4261
     62typedef struct RpDiscreteString {
     63    int num;                        /* integer representing this string */
     64    char *str;                      /* actual string selected */
     65} RpDiscreteString;
     66
    4367typedef struct RpOptimParam {
    4468    char *name;                     /* name of this parameter */
    4569    RpOptimParamType type;          /* paramter type -- number, string, etc */
    4670    union {
    47         double num;                 /* slot for number value */
    48         char *str;                  /* slot for string value */
     71        double dval;                /* slot for number value */
     72        int ival;                   /* slot for integer value */
     73        RpDiscreteString sval;      /* slot for string value */
    4974    } value;
    5075} RpOptimParam;
     
    6590    RpOptimParam base;              /* basic parameter info */
    6691    char **values;                  /* array of allowed values */
     92    int numValues;                  /* number of allowed values */
    6793} RpOptimParamString;
    6894
     
    7298 */
    7399typedef struct RpOptimEnv {
     100    RpOptimEvaluator *evalProc;     /* called during optimization to do run */
    74101    ClientData pluginData;          /* data created by plugin init routine */
    75     RpOptimCleanup *cleanupPtr;     /* cleanup routine for pluginData */
     102    RpOptimCleanup *cleanupProc;    /* cleanup routine for pluginData */
     103    ClientData toolData;            /* data used during tool execution */
    76104    RpOptimParam **paramList;       /* list of input parameters to vary */
    77105    int numParams;                  /* current number of parameters */
     
    80108
    81109/*
    82  * During each optimization, a function of the following type is
    83  * called againa and again to evaluate input parameters and compute
    84  * the fitness function.
    85  */
    86 typedef enum {
    87     RP_OPTIM_SUCCESS=0, RP_OPTIM_UNKNOWN, RP_OPTIM_FAILURE
    88 } RpOptimStatus;
    89 
    90 typedef RpOptimStatus (RpOptimEvaluator)_ANSI_ARGS_((RpOptimParam **values,
    91     int numValues, double *fitnessPtr));
    92 
    93 /*
    94110 *  Here are the functions in the API:
    95111 */
    96112EXTERN RpOptimEnv* RpOptimCreate _ANSI_ARGS_((ClientData pluginData,
    97     RpOptimCleanup *cleanupPtr));
     113    RpOptimCleanup *cleanupProc));
    98114
    99115EXTERN RpOptimParam* RpOptimAddParamNumber _ANSI_ARGS_((RpOptimEnv *envPtr,
     
    108124EXTERN void RpOptimDeleteParam _ANSI_ARGS_((RpOptimEnv *envPtr, char *name));
    109125
    110 EXTERN RpOptimStatus RpOptimPerform _ANSI_ARGS_((RpOptimEnv *envPtr,
    111     RpOptimEvaluator *evalFuncPtr, int maxRuns));
    112 
    113126EXTERN void RpOptimDelete _ANSI_ARGS_((RpOptimEnv *envPtr));
    114127
  • trunk/optimizer/src/rp_optimizer_plugin.h

    r897 r898  
    3030 */
    3131typedef struct RpOptimPlugin {
    32     char *name;                    /* name of this package for -using */
    33     RpOptimInit *initPtr;          /* initialization routine */
    34     RpOptimCleanup *cleanupPtr;    /* cleanup routine */
    35     RpTclOption *optionSpec;       /* specs for config options */
     32    char *name;                   /* name of this package for -using */
     33    RpOptimInit *initProc;        /* initialization routine */
     34    RpOptimHandler *runProc;      /* handles the core optimization */
     35    RpOptimCleanup *cleanupProc;  /* cleanup routine */
     36    RpTclOption *optionSpec;      /* specs for config options */
    3637} RpOptimPlugin;
    3738
  • trunk/optimizer/src/rp_optimizer_tcl.c

    r897 r898  
    2626 */
    2727RpOptimInit PgapackInit;
     28RpOptimHandler PgapackRun;
    2829RpOptimCleanup PgapackCleanup;
    2930extern RpTclOption PgapackOptions;
    3031
    3132static RpOptimPlugin rpOptimPlugins[] = {
    32     {"pgapack", PgapackInit, PgapackCleanup, &PgapackOptions},
     33    {"pgapack", PgapackInit, PgapackRun, PgapackCleanup, &PgapackOptions},
    3334    {NULL, NULL, NULL},
    3435};
     
    3940} RpOptimPluginData;
    4041
     42typedef struct RpOptimToolData {
     43    Tcl_Interp *interp;             /* interp handling this tool */
     44    Tcl_Obj *toolPtr;               /* command for tool object */
     45    Tcl_Obj *updateCmdPtr;          /* command used to look for abort */
     46} RpOptimToolData;
     47
    4148/*
    4249 * ----------------------------------------------------------------------
     
    4552 */
    4653RpTclOption rpOptimNumberOpts[] = {
    47   {"-min", RP_OPTION_DOUBLE, NULL, Rp_Offset(RpOptimParamNumber,min)},
    48   {"-max", RP_OPTION_DOUBLE, NULL, Rp_Offset(RpOptimParamNumber,max)},
    49   {NULL, NULL, NULL, 0}
     54  {"-min", RP_OPTION_DOUBLE, Rp_Offset(RpOptimParamNumber,min)},
     55  {"-max", RP_OPTION_DOUBLE, Rp_Offset(RpOptimParamNumber,max)},
     56  {NULL, NULL, 0}
    5057};
    5158
    5259RpTclOption rpOptimStringOpts[] = {
    53   {"-values", RP_OPTION_LIST, NULL, Rp_Offset(RpOptimParamString,values)},
    54   {NULL, NULL, NULL, 0}
     60  {"-values", RP_OPTION_LIST, Rp_Offset(RpOptimParamString,values)},
     61  {NULL, NULL, 0}
    5562};
    5663
     
    6168    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
    6269static void RpOptimInstanceCleanup _ANSI_ARGS_((ClientData cdata));
     70static RpOptimStatus RpOptimizerPerformInTcl _ANSI_ARGS_((RpOptimEnv *envPtr,
     71    RpOptimParam *values, int numValues, double *fitnessPtr));
     72static int RpOptimizerUpdateInTcl _ANSI_ARGS_((RpOptimEnv *envPtr));
    6373
    6474#ifdef BUILD_Rappture
     
    111121    RpOptimPlugin *usingPluginPtr = &rpOptimPlugins[0];
    112122
     123    /* no good default for the tool being optimized */
     124    Tcl_Obj *toolPtr = NULL;
     125
     126    /* no name for this object by default */
    113127    char *name = NULL;
    114128
     
    116130    RpOptimPlugin* pluginPtr;
    117131    RpOptimPluginData* pluginDataPtr;
     132    RpOptimToolData* toolDataPtr;
     133
    118134    int n;
    119135    char *option, autoname[32], *sep;
     
    174190            n += 2;
    175191        }
     192        else if (strcmp(option,"-tool") == 0) {
     193            if (n+1 >= objc) {
     194                Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
     195                    "missing value for option \"", option, "\"",
     196                    (char*)NULL);
     197                return TCL_ERROR;
     198            }
     199            toolPtr = objv[n+1];
     200            Tcl_IncrRefCount(toolPtr);
     201            n += 2;
     202        }
    176203        else {
    177204            Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
    178205                "bad option \"", option, "\": should be ",
    179                 "-using", (char*)NULL);
     206                "-tool, -using", (char*)NULL);
    180207            return TCL_ERROR;
    181208        }
     
    198225    pluginDataPtr->pluginDefn = usingPluginPtr;
    199226    pluginDataPtr->clientData = NULL;
    200     if (usingPluginPtr->initPtr) {
    201         pluginDataPtr->clientData = (*usingPluginPtr->initPtr)();
     227    if (usingPluginPtr->initProc) {
     228        pluginDataPtr->clientData = (*usingPluginPtr->initProc)();
    202229    }
    203230    envPtr = RpOptimCreate((ClientData)pluginDataPtr, RpOptimInstanceCleanup);
     231
     232    toolDataPtr = (RpOptimToolData*)malloc(sizeof(RpOptimToolData));
     233    toolDataPtr->interp = interp;
     234    toolDataPtr->toolPtr = toolPtr;
     235    toolDataPtr->updateCmdPtr = NULL;
     236    envPtr->toolData = (ClientData)toolDataPtr;
    204237
    205238    Tcl_CreateObjCommand(interp, name, RpOptimInstanceCmd,
     
    224257{
    225258    RpOptimEnv *envPtr = (RpOptimEnv*)cdata;
     259    RpOptimToolData *toolDataPtr;
    226260    int n;
    227261    ClientData paramdata;
     262
     263    if (envPtr->toolData) {
     264        toolDataPtr = (RpOptimToolData*)envPtr->toolData;
     265        if (toolDataPtr->toolPtr) {
     266            Tcl_DecrRefCount(toolDataPtr->toolPtr);
     267        }
     268        if (toolDataPtr->updateCmdPtr) {
     269            Tcl_DecrRefCount(toolDataPtr->updateCmdPtr);
     270        }
     271        free(toolDataPtr);
     272        envPtr->toolData = NULL;
     273    }
    228274
    229275    for (n=0; n < envPtr->numParams; n++) {
     
    252298 *      <name> get ?<glob>? ?-option?
    253299 *      <name> configure ?-option? ?value -option value ...?
    254  *      <name> perform ?-maxruns <num>? ?-abortvar <varName>?
     300 *      <name> perform ?-tool <tool>? ?-updatecommand <varName>?
     301 *      <name> using
    255302 *
    256303 *  The "add" command is used to add various parameter types to the
     
    268315    RpOptimEnv* envPtr = (RpOptimEnv*)cdata;
    269316    RpOptimPluginData* pluginDataPtr = (RpOptimPluginData*)envPtr->pluginData;
    270 
    271     int n, j, nmatches;
     317    RpOptimToolData* toolDataPtr = (RpOptimToolData*)envPtr->toolData;
     318
     319    int n, j, nvals, nmatches;
    272320    char *option, *type, *path;
    273321    RpOptimParam *paramPtr;
     322    RpOptimParamString *strPtr;
     323    RpOptimStatus status;
    274324    RpTclOption *optSpecPtr;
    275     Tcl_Obj *rval, *rrval;
     325    Tcl_Obj *rval, *rrval, *toolPtr, *updateCmdPtr;
    276326
    277327    if (objc < 2) {
     
    314364                return TCL_ERROR;
    315365            }
     366
     367            /* list of values just changed -- patch up the count */
     368            strPtr = (RpOptimParamString*)paramPtr;
     369            for (nvals=0; strPtr->values[nvals]; nvals++)
     370                ; /* count the values */
     371            strPtr->numValues = nvals;
    316372        }
    317373        else {
     
    496552
    497553    /*
    498      * OPTION:  perform ?-maxruns num? ?-abortvar name?
     554     * OPTION:  perform ?-tool name? ?-updatecommand name?
    499555     */
    500556    else if (*option == 'p' && strcmp(option,"perform") == 0) {
     557        /* use this tool by default */
     558        toolPtr = toolDataPtr->toolPtr;
     559
     560        /* no -updatecommand by default */
     561        updateCmdPtr = NULL;
     562
     563        n = 2;
     564        while (n < objc) {
     565            option = Tcl_GetStringFromObj(objv[n], (int*)NULL);
     566            if (n+1 >= objc) {
     567                Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
     568                    "missing value for option \"", option, "\"",
     569                    (char*)NULL);
     570                return TCL_ERROR;
     571            }
     572            if (strcmp(option,"-tool") == 0) {
     573                toolPtr = objv[n+1];
     574                n += 2;
     575            }
     576            else if (strcmp(option,"-updatecommand") == 0) {
     577                updateCmdPtr = objv[n+1];
     578                n += 2;
     579            }
     580            else {
     581                Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
     582                    "bad option \"", option, "\": should be -tool,"
     583                    " -updatecommand", (char*)NULL);
     584                return TCL_ERROR;
     585            }
     586        }
     587
     588        /*
     589         * Must have a tool object at this point, or else we
     590         * don't know what to optimize.
     591         */
     592        if (toolPtr == NULL) {
     593            Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
     594                "tool being optimized not specified via -tool option",
     595                (char*)NULL);
     596            return TCL_ERROR;
     597        }
     598
     599        Tcl_IncrRefCount(toolPtr);
     600        if (updateCmdPtr) {
     601            Tcl_IncrRefCount(updateCmdPtr);
     602            toolDataPtr->updateCmdPtr = updateCmdPtr;
     603        }
     604
     605        /* call the main optimization routine here */
     606        status = (*pluginDataPtr->pluginDefn->runProc)(envPtr,
     607            RpOptimizerPerformInTcl);
     608
     609        Tcl_DecrRefCount(toolPtr);
     610        if (updateCmdPtr) {
     611            Tcl_DecrRefCount(updateCmdPtr);
     612            toolDataPtr->updateCmdPtr = NULL;
     613        }
     614
     615        switch (status) {
     616        case RP_OPTIM_SUCCESS:
     617            Tcl_SetResult(interp, "success", TCL_STATIC);
     618            break;
     619        case RP_OPTIM_FAILURE:
     620            Tcl_SetResult(interp, "failure", TCL_STATIC);
     621            break;
     622        case RP_OPTIM_ABORTED:
     623            Tcl_SetResult(interp, "aborted", TCL_STATIC);
     624            break;
     625        case RP_OPTIM_UNKNOWN:
     626        default:
     627            Tcl_SetResult(interp, "???", TCL_STATIC);
     628            break;
     629        }
     630        return TCL_OK;
     631    }
     632
     633    /*
     634     * OPTION:  using
     635     */
     636    else if (*option == 'u' && strcmp(option,"using") == 0) {
     637        if (objc > 2) {
     638            Tcl_WrongNumArgs(interp, 1, objv, "using");
     639            return TCL_ERROR;
     640        }
     641        Tcl_SetResult(interp, pluginDataPtr->pluginDefn->name, TCL_STATIC);
     642        return TCL_OK;
    501643    }
    502644
    503645    else {
    504646        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
    505             "bad option \"", option, "\": should be add, perform",
    506             (char*)NULL);
     647            "bad option \"", option, "\": should be add, configure, "
     648            "get, perform, using", (char*)NULL);
    507649        return TCL_ERROR;
    508650    }
     
    535677
    536678    /* call a specialized cleanup routine to handle the rest */
    537     if (pluginDataPtr->pluginDefn->cleanupPtr) {
    538         (*pluginDataPtr->pluginDefn->cleanupPtr)(pluginDataPtr->clientData);
     679    if (pluginDataPtr->pluginDefn->cleanupProc) {
     680        (*pluginDataPtr->pluginDefn->cleanupProc)(pluginDataPtr->clientData);
    539681    }
    540682    pluginDataPtr->clientData = NULL;
     
    543685    free((char*)pluginDataPtr);
    544686}
     687
     688/*
     689 * ------------------------------------------------------------------------
     690 *  RpOptimizerPerformInTcl()
     691 *
     692 *  Invoked as a call-back within RpOptimPerform() to handle each
     693 *  optimization run.  Launches a run of a Rappture-based tool using
     694 *  the given values and computes the value for the fitness function.
     695 *
     696 *  Returns RP_OPTIM_SUCCESS if the run was successful, along with
     697 *  the value in the fitness function in fitnessPtr.  If something
     698 *  goes wrong with the run, it returns RP_OPTIM_FAILURE.
     699 * ------------------------------------------------------------------------
     700 */
     701static RpOptimStatus
     702RpOptimizerPerformInTcl(envPtr, values, numValues, fitnessPtr)
     703    RpOptimEnv *envPtr;       /* optimization environment */
     704    RpOptimParam *values;     /* incoming values for the simulation */
     705    int numValues;            /* number of incoming values */
     706    double *fitnessPtr;       /* returns: computed value of fitness func */
     707{
     708    printf("running...\n");
     709    *fitnessPtr = 0.0;
     710    return RP_OPTIM_SUCCESS;
     711}
     712
     713/*
     714 * ------------------------------------------------------------------------
     715 *  RpOptimizerUpdateInTcl()
     716 *
     717 *  Invoked as a call-back within RpOptimPerform() to update the
     718 *  application and look for an "abort" signal.  Evaluates a bit of
     719 *  optional code stored in the optimization environment.  Returns 0
     720 *  if everything is okay, and non-zero if the user wants to abort.
     721 * ------------------------------------------------------------------------
     722 */
     723static int
     724RpOptimizerUpdateInTcl(envPtr)
     725    RpOptimEnv *envPtr;       /* optimization environment */
     726{
     727    RpOptimToolData *toolDataPtr = (RpOptimToolData*)envPtr->toolData;
     728    int status;
     729
     730    if (toolDataPtr->updateCmdPtr) {
     731        status = Tcl_GlobalEvalObj(toolDataPtr->interp,
     732            toolDataPtr->updateCmdPtr);
     733
     734        if (status == TCL_ERROR) {
     735            Tcl_BackgroundError(toolDataPtr->interp);
     736            return 0;
     737        }
     738        if (status == TCL_BREAK || status == TCL_RETURN) {
     739            return 1;  /* abort! */
     740        }
     741    }
     742    return 0;  /* keep going... */
     743}
  • trunk/optimizer/src/rp_tcloptions.c

    r897 r898  
    2323 *  Built-in types:
    2424 */
     25RpCustomTclOptionParse RpOption_ParseBoolean;
     26RpCustomTclOptionGet RpOption_GetBoolean;
     27RpTclOptionType RpOption_Boolean = {
     28    "boolean", RpOption_ParseBoolean, RpOption_GetBoolean, NULL
     29};
     30
    2531RpCustomTclOptionParse RpOption_ParseInt;
    2632RpCustomTclOptionGet RpOption_GetInt;
     
    175181/*
    176182 * ======================================================================
     183 *  BOOLEAN
     184 * ======================================================================
     185 */
     186int
     187RpOption_ParseBoolean(interp, valObj, cdata, offset)
     188    Tcl_Interp *interp;  /* interpreter handling this request */
     189    Tcl_Obj *valObj;     /* set option to this new value */
     190    ClientData cdata;    /* save in this data structure */
     191    int offset;          /* save at this offset in cdata */
     192{
     193    int *ptr = (int*)(cdata+offset);
     194    if (Tcl_GetBooleanFromObj(interp, valObj, ptr) != TCL_OK) {
     195        return TCL_ERROR;
     196    }
     197    return TCL_OK;
     198}
     199
     200int
     201RpOption_GetBoolean(interp, cdata, offset)
     202    Tcl_Interp *interp;  /* interpreter handling this request */
     203    ClientData cdata;    /* get from this data structure */
     204    int offset;          /* get from this offset in cdata */
     205{
     206    int *ptr = (int*)(cdata+offset);
     207    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(*ptr));
     208    return TCL_OK;
     209}
     210
     211/*
     212 * ======================================================================
    177213 *  INTEGER
    178214 * ======================================================================
     
    335371    *(char***)(cdata+offset) = NULL;
    336372}
     373
     374/*
     375 * ======================================================================
     376 *  CHOICES
     377 * ======================================================================
     378 */
     379int
     380RpOption_ParseChoices(interp, valObj, cdata, offset)
     381    Tcl_Interp *interp;  /* interpreter handling this request */
     382    Tcl_Obj *valObj;     /* set option to this new value */
     383    ClientData cdata;    /* save in this data structure */
     384    int offset;          /* save at this offset in cdata */
     385{
     386    char **ptr = (char**)(cdata+offset);
     387    char *value = Tcl_GetStringFromObj(valObj, (int*)NULL);
     388    *ptr = strdup(value);
     389    return TCL_OK;
     390}
     391
     392int
     393RpOption_GetChoices(interp, cdata, offset)
     394    Tcl_Interp *interp;  /* interpreter handling this request */
     395    ClientData cdata;    /* get from this data structure */
     396    int offset;          /* get from this offset in cdata */
     397{
     398    char *ptr = (char*)(cdata+offset);
     399    Tcl_SetObjResult(interp, Tcl_NewStringObj(ptr,-1));
     400    return TCL_OK;
     401}
     402
     403void
     404RpOption_CleanupChoices(cdata, offset)
     405    ClientData cdata;    /* cleanup in this data structure */
     406    int offset;          /* cleanup at this offset in cdata */
     407{
     408    char **ptr = (char**)(cdata+offset);
     409    if (*ptr != NULL) {
     410        free((char*)(*ptr));
     411        *ptr = NULL;
     412    }
     413}
  • trunk/optimizer/src/rp_tcloptions.h

    r897 r898  
    4949    char *optname;             /* name of option: -switch */
    5050    RpTclOptionType *typePtr;  /* type of this switch */
    51     ClientData extraInfo;      /* extra data needed for switch type */
    5251    int offset;                /* location of data within struct */
    5352} RpTclOption;
     
    5655 *  Built-in types defined in rp_tcloptions.c
    5756 */
     57extern RpTclOptionType RpOption_Boolean;
     58#define RP_OPTION_BOOLEAN &RpOption_Boolean
     59
    5860extern RpTclOptionType RpOption_Int;
    5961#define RP_OPTION_INT &RpOption_Int
     
    6769extern RpTclOptionType RpOption_List;
    6870#define RP_OPTION_LIST &RpOption_List
     71
     72extern RpTclOptionType RpOption_Choices;
     73#define RP_OPTION_CHOICES &RpOption_Choices
    6974
    7075/*
  • trunk/optimizer/tests/aaa.test

    r897 r898  
    4343test aaa-1.4 {optimizer creation takes certain args} {
    4444  list [catch {Rappture::optimizer -foo} result] $result
    45 } {1 {bad option "-foo": should be -using}}
     45} {1 {bad option "-foo": should be -tool, -using}}
    4646
    4747test aaa-1.5 {optimizer creation: -using requires a value} {
     
    5555test aaa-1.7 {optimizer creation: extra args are processed} {
    5656  list [catch {Rappture::optimizer -using pgapack -foo bar} result] $result
    57 } {1 {bad option "-foo": should be -using}}
     57} {1 {bad option "-foo": should be -tool, -using}}
    5858
    5959test aaa-1.8 {optimizer can be destroyed without dumping core} {
Note: See TracChangeset for help on using the changeset viewer.