source: trunk/optimizer/src/rp_optimizer.c @ 816

Last change on this file since 816 was 809, checked in by mmc, 17 years ago

Created the initial API for the optimizer. Type "make" in this directory
and then run the "rptest" program to see how it works. The guts of
rp_optimizer.c are missing, but the rest of it works.

File size: 8.9 KB
Line 
1/*
2 * ----------------------------------------------------------------------
3 *  rp_optimizer
4 *
5 *  This is the C language API for the optimization package in
6 *  Rappture.  It lets you set up an optimization of some fitness
7 *  function with respect to a set of inputs.
8 *
9 * ======================================================================
10 *  AUTHOR:  Michael McLennan, Purdue University
11 *  Copyright (c) 2004-2007  Purdue Research Foundation
12 *
13 *  See the file "license.terms" for information on usage and
14 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
15 * ======================================================================
16 */
17#include <math.h>
18#include <stdlib.h>
19#include <string.h>
20#include "rp_optimizer.h"
21
22/*
23 * ----------------------------------------------------------------------
24 * RpOptimCreate()
25 *
26 * Used to create the context for an optimization.  Creates an empty
27 * context and returns a pointer to it.  The context can be updated
28 * by calling functions like RpOptimAddParamNumber to define various
29 * input parameters.
30 * ----------------------------------------------------------------------
31 */
32RpOptimEnv*
33RpOptimCreate()
34{
35    RpOptimEnv *envPtr;
36    envPtr = (RpOptimEnv*)malloc(sizeof(RpOptimEnv));
37    envPtr->numParams = 0;
38    envPtr->maxParams = 2;
39    envPtr->paramList = (RpOptimParam**)malloc(
40        (size_t)(envPtr->maxParams*sizeof(RpOptimParam*))
41    );
42
43    return envPtr;
44}
45
46/*
47 * ----------------------------------------------------------------------
48 * RpOptimAddParam()
49 *
50 * Used internally to add a new parameter into the given optimization
51 * context.  The internal list of parameters is resized, if necessary,
52 * to accommodate the new parameter.
53 * ----------------------------------------------------------------------
54 */
55void
56RpOptimAddParam(envPtr, paramPtr)
57    RpOptimEnv *envPtr;      /* context for this optimization */
58    RpOptimParam *paramPtr;  /* parameter being added */
59{
60    RpOptimParam **newParamList;
61
62    /*
63     * Add the new parameter at the end of the list.
64     */
65    envPtr->paramList[envPtr->numParams++] = paramPtr;
66
67    /*
68     * Out of space?  Then double the space available for params.
69     */
70    if (envPtr->numParams >= envPtr->maxParams) {
71        envPtr->maxParams *= 2;
72        newParamList = (RpOptimParam**)malloc(
73            (size_t)(envPtr->maxParams*sizeof(RpOptimParam*))
74        );
75        memcpy(newParamList, envPtr->paramList,
76            (size_t)(envPtr->numParams*sizeof(RpOptimParam*)));
77        free(envPtr->paramList);
78        envPtr->paramList = newParamList;
79    }
80}
81
82/*
83 * ----------------------------------------------------------------------
84 * RpOptimAddParamNumber()
85 *
86 * Used to add a number parameter as an input to an optimization.
87 * Each number has a name and a double precision value that can be
88 * constrained between min/max values.  Adds this number to the end
89 * of the parameter list in the given optimization context.
90 * ----------------------------------------------------------------------
91 */
92void
93RpOptimAddParamNumber(envPtr, name, min, max)
94    RpOptimEnv *envPtr;   /* context for this optimization */
95    char *name;           /* name of this parameter */
96    double min;           /* minimum value for this parameter */
97    double max;           /* minimum value for this parameter */
98{
99    RpOptimParamNumber *numPtr;
100    numPtr = (RpOptimParamNumber*)malloc(sizeof(RpOptimParamNumber));
101    numPtr->base.name = strdup(name);
102    numPtr->base.type = RP_OPTIMPARAM_NUMBER;
103    numPtr->base.value.num = 0.0;
104    numPtr->min = min;
105    numPtr->max = max;
106
107    RpOptimAddParam(envPtr, (RpOptimParam*)numPtr);
108}
109
110/*
111 * ----------------------------------------------------------------------
112 * RpOptimAddParamString()
113 *
114 * Used to add a string parameter as an input to an optimization.
115 * Each string has a name and a list of allowed values terminated
116 * by a NULL.  Adds this string to the end of the parameter list
117 * in the given optimization context.
118 * ----------------------------------------------------------------------
119 */
120void
121RpOptimAddParamString(envPtr, name, allowedValues)
122    RpOptimEnv *envPtr;   /* context for this optimization */
123    char *name;           /* name of this parameter */
124    char **allowedValues; /* null-term list of allowed values */
125{
126    int n;
127    RpOptimParam **endPtrPtr;
128    RpOptimParamString *strPtr;
129    strPtr = (RpOptimParamString*)malloc(sizeof(RpOptimParamString));
130    strPtr->base.name = strdup(name);
131    strPtr->base.type = RP_OPTIMPARAM_STRING;
132    strPtr->base.value.str = NULL;
133
134    /* count the number of allowed values */
135    if (allowedValues) {
136        for (n=0; allowedValues[n] != NULL; n++)
137            ;
138    } else {
139        n = 0;
140    }
141    strPtr->numValues = n;
142    strPtr->values = (char**)malloc(n*sizeof(char*));
143
144    /* build a null-terminated list of copies of allowed values */
145    for (n=0; n < strPtr->numValues; n++) {
146        strPtr->values[n] = strdup(allowedValues[n]);
147    }
148
149    RpOptimAddParam(envPtr, (RpOptimParam*)strPtr);
150}
151
152/*
153 * ----------------------------------------------------------------------
154 * RpOptimPerform()
155 *
156 * Used to perform an optimization in the given context.  Each run is
157 * performed by calling an evaluation function represented by a
158 * function pointer.  If an optimum value is found within the limit
159 * on the number of runs, then this procedure returns RP_OPTIM_SUCCESS.
160 * Values for the optimum input parameters are returned through the
161 * paramList within the context.  If the optimization fails, this
162 * function returns RP_OPTIM_FAILURE.
163 * ----------------------------------------------------------------------
164 */
165RpOptimStatus
166RpOptimPerform(envPtr, evalFuncPtr, maxRuns)
167    RpOptimEnv *envPtr;               /* context for this optimization */
168    RpOptimEvaluator *evalFuncPtr;    /* function called to handle run */
169    int maxRuns;                      /* limit on number of runs,
170                                       * or 0 for no limit */
171{
172    RpOptimStatus status = RP_OPTIM_UNKNOWN;
173
174    int n, nruns, ival;
175    double dval, fitness;
176    RpOptimParamNumber *numPtr;
177    RpOptimParamString *strPtr;
178    RpOptimStatus runStatus;
179
180    if (envPtr->numParams == 0) {    /* no input parameters? */
181        return RP_OPTIM_FAILURE;     /* then we can't optimize! */
182    }
183
184    /*
185     * Call the evaluation function a number of times with different
186     * values and perform the optimization.
187     */
188    nruns = 0;
189    while (status == RP_OPTIM_UNKNOWN) {
190        /*
191         * Pick random values for all inputs.
192         */
193        for (n=0; n < envPtr->numParams; n++) {
194            switch (envPtr->paramList[n]->type) {
195                case RP_OPTIMPARAM_NUMBER:
196                    numPtr = (RpOptimParamNumber*)envPtr->paramList[n];
197                    dval = drand48();
198                    envPtr->paramList[n]->value.num =
199                        (numPtr->max - numPtr->min)*dval + numPtr->min;
200                    break;
201                case RP_OPTIMPARAM_STRING:
202                    strPtr = (RpOptimParamString*)envPtr->paramList[n];
203                    ival = (int)floor(drand48() * strPtr->numValues);
204                    envPtr->paramList[n]->value.str = strPtr->values[ival];
205                    break;
206            }
207        }
208
209        /*
210         * Call the evaluation function to get the fitness value.
211         */
212        runStatus = (*evalFuncPtr)(envPtr->paramList, envPtr->numParams,
213            &fitness);
214
215        if (runStatus == RP_OPTIM_SUCCESS) {
216            /*
217             * Is the fitness function any better?
218             * Change the input values here based on fitness.
219             *  ...
220             */
221        }
222
223        if (++nruns >= maxRuns && maxRuns > 0) {
224            status = RP_OPTIM_FAILURE;  /* reached the limit of runs */
225        }
226    }
227
228    return status;
229}
230
231/*
232 * ----------------------------------------------------------------------
233 * RpOptimDelete()
234 *
235 * Used to delete the context for an optimization once it is finished
236 * or no longer needed.  Frees up the memory needed to store the
237 * context and all input parameters.  After this call, the context
238 * should not be used again.
239 * ----------------------------------------------------------------------
240 */
241void
242RpOptimDelete(envPtr)
243    RpOptimEnv *envPtr;   /* context for this optimization */
244{
245    int n;
246    RpOptimParam *paramPtr;
247    RpOptimParamNumber *numPtr;
248    RpOptimParamString *strPtr;
249
250    for (n=0; n < envPtr->numParams; n++) {
251        paramPtr = envPtr->paramList[n];
252        free(paramPtr->name);
253        switch (paramPtr->type) {
254            case RP_OPTIMPARAM_NUMBER:
255                numPtr = (RpOptimParamNumber*)paramPtr;
256                /* nothing special to free here */
257                break;
258            case RP_OPTIMPARAM_STRING:
259                strPtr = (RpOptimParamString*)paramPtr;
260                for (n=0; n < strPtr->numValues; n++) {
261                    free(strPtr->values[n]);
262                }
263                break;
264        }
265        free(paramPtr);
266    }
267    free(envPtr->paramList);
268    free(envPtr);
269}
Note: See TracBrowser for help on using the repository browser.