source: trunk/packages/optimizer/src/rp_optimizer.c @ 1052

Last change on this file since 1052 was 899, checked in by mmc, 15 years ago

Added a -fitness option to the "perform" operation. Right now, you can
specify just the name of an output quantity, and that quantity can be
minimized or maximized. In the future, there should be an expression
parser so you can enter any function of Rappture quantities.

Fixed up the example so that it runs the Rosenbrock function, which is
difficult to minimize. Added a visualize.tcl script, so you can visualize
the output from many different runXXXX.xml files.

File size: 8.2 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) 2008  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
22static void RpOptimCleanupParam _ANSI_ARGS_((RpOptimParam *paramPtr));
23
24/*
25 * ----------------------------------------------------------------------
26 * RpOptimCreate()
27 *
28 * Used to create the context for an optimization.  Creates an empty
29 * context and returns a pointer to it.  The context can be updated
30 * by calling functions like RpOptimAddParamNumber to define various
31 * input parameters.
32 * ----------------------------------------------------------------------
33 */
34RpOptimEnv*
35RpOptimCreate(pluginDefn)
36    RpOptimPlugin *pluginDefn;    /* plug-in handling this optimization */
37{
38    RpOptimEnv *envPtr;
39    envPtr = (RpOptimEnv*)malloc(sizeof(RpOptimEnv));
40
41    envPtr->pluginDefn = pluginDefn;
42    envPtr->pluginData = NULL;
43    envPtr->toolData   = NULL;
44
45    if (pluginDefn->initProc) {
46        envPtr->pluginData = (*pluginDefn->initProc)();
47    }
48
49    envPtr->numParams = 0;
50    envPtr->maxParams = 5;
51    envPtr->paramList = (RpOptimParam**)malloc(
52        (size_t)(envPtr->maxParams*sizeof(RpOptimParam*))
53    );
54
55    return envPtr;
56}
57
58/*
59 * ----------------------------------------------------------------------
60 * RpOptimAddParam()
61 *
62 * Used internally to add a new parameter into the given optimization
63 * context.  The internal list of parameters is resized, if necessary,
64 * to accommodate the new parameter.
65 * ----------------------------------------------------------------------
66 */
67void
68RpOptimAddParam(envPtr, paramPtr)
69    RpOptimEnv *envPtr;      /* context for this optimization */
70    RpOptimParam *paramPtr;  /* parameter being added */
71{
72    RpOptimParam **newParamList;
73
74    /*
75     * Add the new parameter at the end of the list.
76     */
77    envPtr->paramList[envPtr->numParams++] = paramPtr;
78
79    /*
80     * Out of space?  Then double the space available for params.
81     */
82    if (envPtr->numParams >= envPtr->maxParams) {
83        envPtr->maxParams *= 2;
84        newParamList = (RpOptimParam**)malloc(
85            (size_t)(envPtr->maxParams*sizeof(RpOptimParam*))
86        );
87        memcpy(newParamList, envPtr->paramList,
88            (size_t)(envPtr->numParams*sizeof(RpOptimParam*)));
89        free(envPtr->paramList);
90        envPtr->paramList = newParamList;
91    }
92}
93
94/*
95 * ----------------------------------------------------------------------
96 * RpOptimAddParamNumber()
97 *
98 * Used to add a number parameter as an input to an optimization.
99 * Each number has a name and a double precision value that can be
100 * constrained between min/max values.  Adds this number to the end
101 * of the parameter list in the given optimization context.
102 * ----------------------------------------------------------------------
103 */
104RpOptimParam*
105RpOptimAddParamNumber(envPtr, name)
106    RpOptimEnv *envPtr;   /* context for this optimization */
107    char *name;           /* name of this parameter */
108{
109    RpOptimParamNumber *numPtr;
110    numPtr = (RpOptimParamNumber*)malloc(sizeof(RpOptimParamNumber));
111    numPtr->base.name = strdup(name);
112    numPtr->base.type = RP_OPTIMPARAM_NUMBER;
113    numPtr->base.value.dval = 0.0;
114    numPtr->min = -DBL_MAX;
115    numPtr->max = DBL_MAX;
116
117    RpOptimAddParam(envPtr, (RpOptimParam*)numPtr);
118
119    return (RpOptimParam*)numPtr;
120}
121
122/*
123 * ----------------------------------------------------------------------
124 * RpOptimAddParamString()
125 *
126 * Used to add a string parameter as an input to an optimization.
127 * Each string has a name and a list of allowed values terminated
128 * by a NULL.  Adds this string to the end of the parameter list
129 * in the given optimization context.
130 * ----------------------------------------------------------------------
131 */
132RpOptimParam*
133RpOptimAddParamString(envPtr, name)
134    RpOptimEnv *envPtr;   /* context for this optimization */
135    char *name;           /* name of this parameter */
136{
137    RpOptimParamString *strPtr;
138    strPtr = (RpOptimParamString*)malloc(sizeof(RpOptimParamString));
139    strPtr->base.name = strdup(name);
140    strPtr->base.type = RP_OPTIMPARAM_STRING;
141    strPtr->base.value.sval.num = -1;
142    strPtr->base.value.sval.str = NULL;
143    strPtr->values = NULL;
144    strPtr->numValues = 0;
145
146    RpOptimAddParam(envPtr, (RpOptimParam*)strPtr);
147
148    return (RpOptimParam*)strPtr;
149}
150
151/*
152 * ----------------------------------------------------------------------
153 * RpOptimFindParam()
154 *
155 * Used to look for an existing parameter with the specified name.
156 * Returns a pointer to the parameter, or NULL if not found.
157 * ----------------------------------------------------------------------
158 */
159RpOptimParam*
160RpOptimFindParam(envPtr, name)
161    RpOptimEnv *envPtr;   /* context for this optimization */
162    char *name;           /* name of this parameter */
163{
164    int n;
165    for (n=0; envPtr->numParams; n++) {
166        if (strcmp(name, envPtr->paramList[n]->name) == 0) {
167            return envPtr->paramList[n];
168        }
169    }
170    return NULL;
171}
172
173/*
174 * ----------------------------------------------------------------------
175 * RpOptimDeleteParam()
176 *
177 * Used to delete a parameter from the environment.  This is especially
178 * useful when an error is found while configuring the parameter, just
179 * after it was created.  If the name is not recognized, this function
180 * does nothing.
181 * ----------------------------------------------------------------------
182 */
183void
184RpOptimDeleteParam(envPtr, name)
185    RpOptimEnv *envPtr;   /* context for this optimization */
186    char *name;           /* name of this parameter */
187{
188    int n, j;
189    for (n=0; envPtr->numParams; n++) {
190        if (strcmp(name, envPtr->paramList[n]->name) == 0) {
191            RpOptimCleanupParam(envPtr->paramList[n]);
192            for (j=n+1; j < envPtr->numParams; j++) {
193                envPtr->paramList[j-1] = envPtr->paramList[j];
194            }
195            envPtr->numParams--;
196            break;
197        }
198    }
199}
200
201/*
202 * ----------------------------------------------------------------------
203 * RpOptimDelete()
204 *
205 * Used to delete the context for an optimization once it is finished
206 * or no longer needed.  Frees up the memory needed to store the
207 * context and all input parameters.  After this call, the context
208 * should not be used again.
209 * ----------------------------------------------------------------------
210 */
211void
212RpOptimDelete(envPtr)
213    RpOptimEnv *envPtr;   /* context for this optimization */
214{
215    int n;
216
217    if (envPtr->pluginDefn && envPtr->pluginDefn->cleanupProc) {
218        (*envPtr->pluginDefn->cleanupProc)(envPtr->pluginData);
219    }
220    for (n=0; n < envPtr->numParams; n++) {
221        RpOptimCleanupParam(envPtr->paramList[n]);
222    }
223    free(envPtr->paramList);
224    free(envPtr);
225}
226
227/*
228 * ----------------------------------------------------------------------
229 * RpOptimCleanupParam()
230 *
231 * Used internally to free up the data associated with an optimization
232 * parameter.  Looks at the parameter type and frees up the appropriate
233 * data.
234 * ----------------------------------------------------------------------
235 */
236static void
237RpOptimCleanupParam(paramPtr)
238    RpOptimParam *paramPtr;  /* data to be freed */
239{
240    int n;
241    RpOptimParamNumber *numPtr;
242    RpOptimParamString *strPtr;
243
244    free(paramPtr->name);
245    switch (paramPtr->type) {
246        case RP_OPTIMPARAM_NUMBER:
247            numPtr = (RpOptimParamNumber*)paramPtr;
248            /* nothing special to free here */
249            break;
250        case RP_OPTIMPARAM_STRING:
251            strPtr = (RpOptimParamString*)paramPtr;
252            if (strPtr->values) {
253                for (n=0; strPtr->values[n]; n++) {
254                    free(strPtr->values[n]);
255                }
256            }
257            break;
258    }
259    free(paramPtr);
260}
Note: See TracBrowser for help on using the repository browser.