Changeset 1086
- Timestamp:
- Jun 24, 2004, 2:46:17 PM (22 years ago)
- Location:
- trunk/psLib/src
- Files:
-
- 2 edited
-
dataManip/psMinimize.c (modified) (4 diffs)
-
math/psMinimize.c (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/dataManip/psMinimize.c
r1079 r1086 13 13 #include "psMemory.h" 14 14 #include "psVector.h" 15 #include "psImage.h" 15 16 #include "psTrace.h" 16 17 #include "psError.h" … … 27 28 typedef struct 28 29 { 29 size_t n; 30 psVector *initialGuess; 30 size_t n; // Number of data points points in domain. 31 int count; // Number of non-masked parameters. 32 psVector *restrict initialGuess; 33 psImage *domain; // 31 34 psVector *data; 32 35 psVector *errors; 33 36 psVector *paramMask; 37 // The first argument to evalModel() and 38 // d_evalModel() specifies the data point. 39 // It must have the same size as the second 40 // dimension of *domain. 41 // The second argument must have the same size 42 // as *initialGuess and *paramMask. 34 43 float (*evalModel) (psVector *, psVector *); 35 44 float (*d_evalModel) (psVector *, psVector *); 36 45 } 37 psmodeldata; 38 39 46 psModelData; 40 47 41 48 … … 53 60 54 61 62 /****************************************************************************** 63 ****************************************************************************** 64 gsl_function_f(x, params, f): This function serves as a standardized wrapper 65 for the user supplied function which is to be minimized. The GSL 66 minimization routines have no knowledge of the user-supplied function. They 67 only clal this routine, which then calls the user-supplied function. The 68 arguments are: 69 x: These are the parameter which are to be varied by GSL in order to 70 minimized chi2 over the data set. 71 params: 72 f 73 74 75 ****************************************************************************** 76 *****************************************************************************/ 55 77 int gsl_function_f(const gsl_vector *x, 56 78 void *params, 57 79 gsl_vector *f) 58 80 { 59 size_t n = ((psmodeldata *)params)->n;60 psVector *data = ((psmodeldata *)params)->data;61 psVector *errors = ((psmodeldata *) params)->errors;62 psVector *mask = ((psmodeldata *) params)->paramMask;63 psVector *initial guess = ((psmodeldata *)params)->initialguess;64 int count = 0;65 float (*evalModel) = ((psmodeldata *) params)->evalModel;81 psImage *domain = ((psModelData *)params)->domain; 82 psVector *data = ((psModelData *)params)->data; 83 psVector *errors = ((psModelData *) params)->errors; 84 psVector *mask = ((psModelData *) params)->paramMask; 85 psVector *initialGuess = ((psModelData *)params)->initialGuess; 86 psVector *inputParameterList = NULL; 87 // float (*evalModel)(psVector *, psVector *) = ((psModelData *) params)->evalModel; 66 88 size_t i; 67 68 for (i=0;i<initialguess->n;i++) { 69 if (mask->data.U8[i] != 0) { 70 count++; 71 } 72 } 89 int j; 90 float tmpf; 91 92 // The GSL routines will call this functions with the masked parameters 93 // removed. However, the user-supplied function (to be modified) does not 94 // have those parameters removed. Here will create a new parameter list 95 // with the masked parameters added (we expand initialGuess). 96 inputParameterList = psVectorAlloc(initialGuess->n, PS_TYPE_F32); 73 97 74 98 if (mask != NULL) { 75 99 j = 0; 76 inputparameterlist = psVectorAlloc(count, PS_TYPE_F32); 77 for (i=0;i<initialguess->n;i++) { 78 if (mask->data.U8[i] == 0) { 79 inputparameterlist->data.F32[j++] = initialguess->data.F32[i]; 100 for (i=0;i<mask->n;i++) { 101 if (mask->data.U8[i] != 0) { 102 inputParameterList->data.F32[i] = initialGuess->data.F32[i]; 103 } else { 104 inputParameterList->data.F32[i] = gsl_vector_get(x, j++); 80 105 } 81 106 } 82 107 } else { 83 for (i=0;i<initialguess->n;i++) { 84 inputparameterlist->data.F32[i] = initialguess->data.F32[i]; 85 } 86 } 87 // PAUL: what is this? 88 evalModel(entiredomain, inputparameterlist); 89 ??? 90 91 loop i over domain size n 92 { 93 gsl_vector_set (f, i, (modelvalue[i] - data[i])/errors[i]); 94 } 108 for (i=0;i<initialGuess->n;i++) { 109 inputParameterList->data.F32[i] = initialGuess->data.F32[i]; 110 } 111 } 112 113 for (i=0;i<domain->numRows;i++) { 114 //GUS tmpf = evalModel(inputParameterList, domain->data.F32[i]); 115 gsl_vector_set(f, i, (tmpf - data->data.F32[i])/errors->data.F32[i]); 116 } 117 95 118 return GSL_SUCCESS; 96 119 } 97 120 98 int gsl_function_df(const gsl_vector * x,121 int gsl_function_df(const gsl_vector *x, 99 122 void *params, 100 gsl_matrix* J) 101 { 102 size_t n = ((psmodeldata *)params)->n; 103 psVector *data = ((psmodeldata *)params)->data; 104 psVector *errors = ((psmodeldata *) params)->errors; 105 psVector *mask = ((psmodeldata *) params)->paramMask; 106 psVector *initialguess = ((psmodeldata *)params)->initialguess; 107 int count = 0; 108 float (*d_evalModel) = ((psmodeldata *) params)->evalModel; 123 gsl_matrix *J) 124 { 125 // size_t n = ((psModelData *)params)->n; 126 psImage *domain = ((psModelData *)params)->domain; 127 // psVector *data = ((psModelData *)params)->data; 128 psVector *errors = ((psModelData *) params)->errors; 129 psVector *mask = ((psModelData *) params)->paramMask; 130 psVector *initialGuess = ((psModelData *)params)->initialGuess; 131 psVector *inputParameterList = NULL; 132 // int count = 0; 133 // float (*d_evalModel) = ((psModelData *) params)->evalModel; 109 134 size_t i; 110 111 f or (i=0;i<initialguess->n;i++) {112 if (mask->data.U8[i] != 0) { 113 count++;114 }115 }116 117 135 int j; 136 float tmpf; 137 138 // The GSL routines will call this functions with the masked parameters 139 // removed. However, the user-supplied function (to be modified) does not 140 // have those parameters removed. Here will create a new parameter list 141 // with the masked parameters added (we expand initialGuess). 142 inputParameterList = psVectorAlloc(initialGuess->n, PS_TYPE_F32); 118 143 if (mask != NULL) { 119 144 j = 0; 120 inputparameterlist = psVectorAlloc(count, PS_TYPE_F32); 121 for (i=0;i<initialguess->n;i++) { 122 if (mask->data.U8[i] == 0) { 123 inputparameterlist->data.F32[j++] = initialguess->data.F32[i]; 145 for (i=0;i<mask->n;i++) { 146 if (mask->data.U8[i] != 0) { 147 inputParameterList->data.F32[i] = initialGuess->data.F32[i]; 148 } else { 149 inputParameterList->data.F32[i] = gsl_vector_get(x, j++); 124 150 } 125 151 } 126 152 } else { 127 for (i=0;i<initialguess->n;i++) { 128 inputparameterlist->data.F32[i] = initialguess->data.F32[i]; 129 } 130 } 131 132 d_evalModel(entiredomain, inputparameterlist); 133 ??? 134 loop i over domain size n 135 // Jacobian matrix J(i,j) = dfi / dxj, where fi = (Modeli - datai)/errors[i] 136 { 137 loop j over the number of coefficients in model (excluding masks) 138 { 139 gsl_matrix_set (J, i, j, (d_modelvalue[i][j])/errors[i]); 140 } 141 } 153 for (i=0;i<initialGuess->n;i++) { 154 inputParameterList->data.F32[i] = initialGuess->data.F32[i]; 155 } 156 } 157 158 for (i=0;i<domain->numRows;i++) { 159 for (j=0;j<inputParameterList->n;j++) { 160 //GUS tmpf = d_evalModel(inputParameterList, domain->data.F32[i], j); 161 162 gsl_matrix_set(J, i, j, (tmpf/errors->data.F32[i])); 163 } 164 } 165 142 166 return GSL_SUCCESS; 143 167 } 144 168 145 int gsl_ function_fdf(const gsl_vector *x,146 void *params,147 gsl_vector *f,148 gsl_matrix *J)149 { 150 gsl_function_f (x, params, f);151 gsl_function_df (x, params, J);169 int gsl_my_function_fdf(const gsl_vector *x, 170 void *params, 171 gsl_vector *f, 172 gsl_matrix *J) 173 { 174 gsl_function_f(x, params, f); 175 gsl_function_df(x, params, J); 152 176 153 177 return GSL_SUCCESS; … … 166 190 const psVector *restrict errors, 167 191 psVector *restrict initialGuess, 168 const psVector *restrict paramMask )169 { 170 size_t n = size(domain); 171 size_t p = size(initialGuess);172 gsl_multifit_fdfsolver_type *T = NULL;173 gsl_multifit_fdfsolver *s = NULL;192 const psVector *restrict paramMask, 193 float *chiSq) 194 { 195 size_t n = domain->n; 196 const gsl_multifit_fdfsolver_type *T = gsl_multifit_fdfsolver_lmsder; 197 gsl_multifit_fdfsolver *s = NULL; 174 198 int status; 175 199 size_t i = 0; 200 int j = 0; 176 201 size_t iter = 0; 177 ps modeldata inputdata = { n, initialguess, data, errors, paramMask, evalmodel, d_evalmodel};202 psModelData *inputData = NULL; 178 203 gsl_multifit_function_fdf f; 179 double *x_init = NULL; 180 181 182 //GUS: call psStatsGetnValues, allocate x_init. 183 /* compress initialguess in light of mask */ 184 j = 0; 185 loop i over length of initialguess 186 { 187 if not masked[i] 188 { 189 x_init[j] = initialguess[i]; 190 j++; 191 } else 192 { /* reduce p accordingly */ 193 p--; 194 } 195 } 196 197 198 // Creates the vector for x which GSL uses. Must deallocate. 199 gsl_vector_view x = gsl_vector_view_array (x_init, p); 200 201 const gsl_rng_type * type; 204 double *xInit = NULL; 205 206 inputData = (psModelData *) psAlloc(sizeof(psModelData)); 207 inputData->n = n; 208 inputData->count = 0; 209 inputData->initialGuess = initialGuess; 210 // inputData->domain = domain; 211 // inputData->data = data; 212 // inputData->errors = errors; 213 // inputData->paramMask = paramMask; 214 // inputData->evalModel = evalModel; 215 // inputData->d_evalModel = DevalModel; 216 217 inputData->count = 0; 218 if (paramMask != NULL) { 219 for (i=0;i<paramMask->n;i++) { 220 if (paramMask->data.U8[i] != 0) { 221 inputData->count++; 222 } 223 } 224 } else { 225 inputData->count= initialGuess->n; 226 } 227 228 229 230 // The initial guess at the parameters for the function are written into 231 // the vector inputParameterList. If the paramMask is not NULL, then those 232 // parameters are masked out. How can this possibly work? The user- 233 // supplied function will require a fixed number of parameters. 234 235 xInit = (double *) psAlloc(inputData->count * sizeof(double)); 236 if (paramMask != NULL) { 237 j = 0; 238 for (i=0;i<initialGuess->n;i++) { 239 if (paramMask->data.U8[i] == 0) { 240 xInit[j++] = initialGuess->data.F32[i]; 241 } 242 } 243 } else { 244 for (i=0;i<initialGuess->n;i++) { 245 xInit[i] = initialGuess->data.F32[i]; 246 } 247 } 248 249 // Creates the vector for x which GSL uses. Must deallocate. 250 gsl_vector_view x = gsl_vector_view_array(xInit, inputData->count); 251 252 const gsl_rng_type *type; 202 253 gsl_rng *r; 203 254 gsl_rng_env_setup(); 204 255 205 256 type = gsl_rng_default; 206 r = gsl_rng_alloc (type);257 r = gsl_rng_alloc(type); 207 258 208 259 f.f = &gsl_function_f; 209 260 f.df = &gsl_function_df; 210 f.fdf = &gsl_ function_fdf;261 f.fdf = &gsl_my_function_fdf; 211 262 f.n = n; 212 f.p = p; 213 f.params = &inputdata; 214 215 T = gsl_multifit_fdfsolver_lmsder; 216 s = gsl_multifit_fdfsolver_alloc (T, n, p); 217 gsl_multifit_fdfsolver_set (s, &f, &x.vector); 218 219 print_state (iter, s); 220 263 f.p = inputData->count; 264 f.params = &inputData; 265 266 // This tells GSL to use the Levenberg-Marquardt algorithm for chi2 267 // minimization. 268 // T = gsl_multifit_fdfsolver_lmsder; 269 270 // Creates an instance of the GSL solver that we will be iterating on. 271 s = gsl_multifit_fdfsolver_alloc(T, n, inputData->count); 272 273 // Initialize the GSL minimizer. 274 gsl_multifit_fdfsolver_set(s, &f, &x.vector); 275 276 // print_state(iter, s); 221 277 do { 222 278 iter++; 223 status = gsl_multifit_fdfsolver_iterate (s); 224 225 printf ("status = %s\n", gsl_strerror (status)); 226 227 print_state (iter, s); 228 229 // Figure this out 230 if (status) 231 break; 279 // Perform an iteration of the GSL solver. 280 status = gsl_multifit_fdfsolver_iterate(s); 281 282 // printf("status = %s\n", gsl_strerror(status)); 283 // print_state(iter, s); 284 285 // If there was a problem, abort. 286 if (status) { 287 psAbort(__func__, "gsl_multifit_fdfsolver_iterate()\n"); 288 } 232 289 233 290 // Checks whether the (L2-norm) computed derivative and the difference 234 // between the real/actual for that test x-vector. If were close enough 235 // exit loop. 236 status = gsl_multifit_test_delta (s->dx, s->x, 237 1e-4, 1e-4); 291 // between the real/actual for that test x-vector. If were close 292 // enough exit loop. 293 294 // Test if the parameters changed by a small enough amount. 295 status = gsl_multifit_test_delta(s->dx, s->x, 1e-4, 1e-4); 238 296 } while (status == GSL_CONTINUE && iter < 500); 239 gsl_matrix *covar = gsl_matrix_alloc (p, p); 240 gsl_multifit_covar (s->J, 0.0, covar); 241 gsl_matrix_fprintf (stdout, covar, "%g"); 242 243 /* add in masked values */ 244 j = 0; 245 loop i over the length of initialguess 246 { 247 if mask(i) 248 { 249 // do nothing, initialguess shouldn't have changed */ 250 } else 251 { 252 initialguess(i) = gsl_vector_get(s->x, j); /* output */ 253 uncertainity = sqrt(gsl_matrix_get(covar,j,j)); 254 j++; 255 } 256 } 257 double chi = gsl_blas_dnrm2(s->f); 258 gsl_multifit_fdfsolver_free (s); 259 return 0; 260 } 261 262 // For 3-element vectors 263 int print_state(size_t iter, 264 gsl_multifit_fdfsolver * s) 265 { 266 printf ("iter: %3u x = % 15.8f % 15.8f % 15.8f " 267 "|f(x)| = %g\n", 268 iter, 269 gsl_vector_get (s->x, 0), 270 gsl_vector_get (s->x, 1), 271 gsl_vector_get (s->x, 2), 272 gsl_blas_dnrm2 (s->f)); 273 } 274 275 276 277 278 279 297 298 299 300 301 if (paramMask != NULL) { 302 j = 0; 303 for (i=0;i<initialGuess->n;i++) { 304 if (paramMask->data.U8[i] == 0) { 305 initialGuess->data.F32[i] = gsl_vector_get(s->x, j++); 306 } else { 307 initialGuess->data.F32[i] = initialGuess->data.F32[i]; 308 } 309 } 310 } else { 311 for (i=0;i<initialGuess->n;i++) { 312 initialGuess->data.F32[i] = gsl_vector_get(s->x, i); 313 } 314 } 315 316 *chiSq = gsl_blas_dnrm2(s->f); 317 gsl_multifit_fdfsolver_free(s); 318 // Free all allocated memory 319 psFree(xInit); 320 psFree(inputData); 321 322 return(initialGuess); 323 } 280 324 281 325 /** @brief This procedure calculates various combinations of powers of x and y -
trunk/psLib/src/math/psMinimize.c
r1079 r1086 13 13 #include "psMemory.h" 14 14 #include "psVector.h" 15 #include "psImage.h" 15 16 #include "psTrace.h" 16 17 #include "psError.h" … … 27 28 typedef struct 28 29 { 29 size_t n; 30 psVector *initialGuess; 30 size_t n; // Number of data points points in domain. 31 int count; // Number of non-masked parameters. 32 psVector *restrict initialGuess; 33 psImage *domain; // 31 34 psVector *data; 32 35 psVector *errors; 33 36 psVector *paramMask; 37 // The first argument to evalModel() and 38 // d_evalModel() specifies the data point. 39 // It must have the same size as the second 40 // dimension of *domain. 41 // The second argument must have the same size 42 // as *initialGuess and *paramMask. 34 43 float (*evalModel) (psVector *, psVector *); 35 44 float (*d_evalModel) (psVector *, psVector *); 36 45 } 37 psmodeldata; 38 39 46 psModelData; 40 47 41 48 … … 53 60 54 61 62 /****************************************************************************** 63 ****************************************************************************** 64 gsl_function_f(x, params, f): This function serves as a standardized wrapper 65 for the user supplied function which is to be minimized. The GSL 66 minimization routines have no knowledge of the user-supplied function. They 67 only clal this routine, which then calls the user-supplied function. The 68 arguments are: 69 x: These are the parameter which are to be varied by GSL in order to 70 minimized chi2 over the data set. 71 params: 72 f 73 74 75 ****************************************************************************** 76 *****************************************************************************/ 55 77 int gsl_function_f(const gsl_vector *x, 56 78 void *params, 57 79 gsl_vector *f) 58 80 { 59 size_t n = ((psmodeldata *)params)->n;60 psVector *data = ((psmodeldata *)params)->data;61 psVector *errors = ((psmodeldata *) params)->errors;62 psVector *mask = ((psmodeldata *) params)->paramMask;63 psVector *initial guess = ((psmodeldata *)params)->initialguess;64 int count = 0;65 float (*evalModel) = ((psmodeldata *) params)->evalModel;81 psImage *domain = ((psModelData *)params)->domain; 82 psVector *data = ((psModelData *)params)->data; 83 psVector *errors = ((psModelData *) params)->errors; 84 psVector *mask = ((psModelData *) params)->paramMask; 85 psVector *initialGuess = ((psModelData *)params)->initialGuess; 86 psVector *inputParameterList = NULL; 87 // float (*evalModel)(psVector *, psVector *) = ((psModelData *) params)->evalModel; 66 88 size_t i; 67 68 for (i=0;i<initialguess->n;i++) { 69 if (mask->data.U8[i] != 0) { 70 count++; 71 } 72 } 89 int j; 90 float tmpf; 91 92 // The GSL routines will call this functions with the masked parameters 93 // removed. However, the user-supplied function (to be modified) does not 94 // have those parameters removed. Here will create a new parameter list 95 // with the masked parameters added (we expand initialGuess). 96 inputParameterList = psVectorAlloc(initialGuess->n, PS_TYPE_F32); 73 97 74 98 if (mask != NULL) { 75 99 j = 0; 76 inputparameterlist = psVectorAlloc(count, PS_TYPE_F32); 77 for (i=0;i<initialguess->n;i++) { 78 if (mask->data.U8[i] == 0) { 79 inputparameterlist->data.F32[j++] = initialguess->data.F32[i]; 100 for (i=0;i<mask->n;i++) { 101 if (mask->data.U8[i] != 0) { 102 inputParameterList->data.F32[i] = initialGuess->data.F32[i]; 103 } else { 104 inputParameterList->data.F32[i] = gsl_vector_get(x, j++); 80 105 } 81 106 } 82 107 } else { 83 for (i=0;i<initialguess->n;i++) { 84 inputparameterlist->data.F32[i] = initialguess->data.F32[i]; 85 } 86 } 87 // PAUL: what is this? 88 evalModel(entiredomain, inputparameterlist); 89 ??? 90 91 loop i over domain size n 92 { 93 gsl_vector_set (f, i, (modelvalue[i] - data[i])/errors[i]); 94 } 108 for (i=0;i<initialGuess->n;i++) { 109 inputParameterList->data.F32[i] = initialGuess->data.F32[i]; 110 } 111 } 112 113 for (i=0;i<domain->numRows;i++) { 114 //GUS tmpf = evalModel(inputParameterList, domain->data.F32[i]); 115 gsl_vector_set(f, i, (tmpf - data->data.F32[i])/errors->data.F32[i]); 116 } 117 95 118 return GSL_SUCCESS; 96 119 } 97 120 98 int gsl_function_df(const gsl_vector * x,121 int gsl_function_df(const gsl_vector *x, 99 122 void *params, 100 gsl_matrix* J) 101 { 102 size_t n = ((psmodeldata *)params)->n; 103 psVector *data = ((psmodeldata *)params)->data; 104 psVector *errors = ((psmodeldata *) params)->errors; 105 psVector *mask = ((psmodeldata *) params)->paramMask; 106 psVector *initialguess = ((psmodeldata *)params)->initialguess; 107 int count = 0; 108 float (*d_evalModel) = ((psmodeldata *) params)->evalModel; 123 gsl_matrix *J) 124 { 125 // size_t n = ((psModelData *)params)->n; 126 psImage *domain = ((psModelData *)params)->domain; 127 // psVector *data = ((psModelData *)params)->data; 128 psVector *errors = ((psModelData *) params)->errors; 129 psVector *mask = ((psModelData *) params)->paramMask; 130 psVector *initialGuess = ((psModelData *)params)->initialGuess; 131 psVector *inputParameterList = NULL; 132 // int count = 0; 133 // float (*d_evalModel) = ((psModelData *) params)->evalModel; 109 134 size_t i; 110 111 f or (i=0;i<initialguess->n;i++) {112 if (mask->data.U8[i] != 0) { 113 count++;114 }115 }116 117 135 int j; 136 float tmpf; 137 138 // The GSL routines will call this functions with the masked parameters 139 // removed. However, the user-supplied function (to be modified) does not 140 // have those parameters removed. Here will create a new parameter list 141 // with the masked parameters added (we expand initialGuess). 142 inputParameterList = psVectorAlloc(initialGuess->n, PS_TYPE_F32); 118 143 if (mask != NULL) { 119 144 j = 0; 120 inputparameterlist = psVectorAlloc(count, PS_TYPE_F32); 121 for (i=0;i<initialguess->n;i++) { 122 if (mask->data.U8[i] == 0) { 123 inputparameterlist->data.F32[j++] = initialguess->data.F32[i]; 145 for (i=0;i<mask->n;i++) { 146 if (mask->data.U8[i] != 0) { 147 inputParameterList->data.F32[i] = initialGuess->data.F32[i]; 148 } else { 149 inputParameterList->data.F32[i] = gsl_vector_get(x, j++); 124 150 } 125 151 } 126 152 } else { 127 for (i=0;i<initialguess->n;i++) { 128 inputparameterlist->data.F32[i] = initialguess->data.F32[i]; 129 } 130 } 131 132 d_evalModel(entiredomain, inputparameterlist); 133 ??? 134 loop i over domain size n 135 // Jacobian matrix J(i,j) = dfi / dxj, where fi = (Modeli - datai)/errors[i] 136 { 137 loop j over the number of coefficients in model (excluding masks) 138 { 139 gsl_matrix_set (J, i, j, (d_modelvalue[i][j])/errors[i]); 140 } 141 } 153 for (i=0;i<initialGuess->n;i++) { 154 inputParameterList->data.F32[i] = initialGuess->data.F32[i]; 155 } 156 } 157 158 for (i=0;i<domain->numRows;i++) { 159 for (j=0;j<inputParameterList->n;j++) { 160 //GUS tmpf = d_evalModel(inputParameterList, domain->data.F32[i], j); 161 162 gsl_matrix_set(J, i, j, (tmpf/errors->data.F32[i])); 163 } 164 } 165 142 166 return GSL_SUCCESS; 143 167 } 144 168 145 int gsl_ function_fdf(const gsl_vector *x,146 void *params,147 gsl_vector *f,148 gsl_matrix *J)149 { 150 gsl_function_f (x, params, f);151 gsl_function_df (x, params, J);169 int gsl_my_function_fdf(const gsl_vector *x, 170 void *params, 171 gsl_vector *f, 172 gsl_matrix *J) 173 { 174 gsl_function_f(x, params, f); 175 gsl_function_df(x, params, J); 152 176 153 177 return GSL_SUCCESS; … … 166 190 const psVector *restrict errors, 167 191 psVector *restrict initialGuess, 168 const psVector *restrict paramMask )169 { 170 size_t n = size(domain); 171 size_t p = size(initialGuess);172 gsl_multifit_fdfsolver_type *T = NULL;173 gsl_multifit_fdfsolver *s = NULL;192 const psVector *restrict paramMask, 193 float *chiSq) 194 { 195 size_t n = domain->n; 196 const gsl_multifit_fdfsolver_type *T = gsl_multifit_fdfsolver_lmsder; 197 gsl_multifit_fdfsolver *s = NULL; 174 198 int status; 175 199 size_t i = 0; 200 int j = 0; 176 201 size_t iter = 0; 177 ps modeldata inputdata = { n, initialguess, data, errors, paramMask, evalmodel, d_evalmodel};202 psModelData *inputData = NULL; 178 203 gsl_multifit_function_fdf f; 179 double *x_init = NULL; 180 181 182 //GUS: call psStatsGetnValues, allocate x_init. 183 /* compress initialguess in light of mask */ 184 j = 0; 185 loop i over length of initialguess 186 { 187 if not masked[i] 188 { 189 x_init[j] = initialguess[i]; 190 j++; 191 } else 192 { /* reduce p accordingly */ 193 p--; 194 } 195 } 196 197 198 // Creates the vector for x which GSL uses. Must deallocate. 199 gsl_vector_view x = gsl_vector_view_array (x_init, p); 200 201 const gsl_rng_type * type; 204 double *xInit = NULL; 205 206 inputData = (psModelData *) psAlloc(sizeof(psModelData)); 207 inputData->n = n; 208 inputData->count = 0; 209 inputData->initialGuess = initialGuess; 210 // inputData->domain = domain; 211 // inputData->data = data; 212 // inputData->errors = errors; 213 // inputData->paramMask = paramMask; 214 // inputData->evalModel = evalModel; 215 // inputData->d_evalModel = DevalModel; 216 217 inputData->count = 0; 218 if (paramMask != NULL) { 219 for (i=0;i<paramMask->n;i++) { 220 if (paramMask->data.U8[i] != 0) { 221 inputData->count++; 222 } 223 } 224 } else { 225 inputData->count= initialGuess->n; 226 } 227 228 229 230 // The initial guess at the parameters for the function are written into 231 // the vector inputParameterList. If the paramMask is not NULL, then those 232 // parameters are masked out. How can this possibly work? The user- 233 // supplied function will require a fixed number of parameters. 234 235 xInit = (double *) psAlloc(inputData->count * sizeof(double)); 236 if (paramMask != NULL) { 237 j = 0; 238 for (i=0;i<initialGuess->n;i++) { 239 if (paramMask->data.U8[i] == 0) { 240 xInit[j++] = initialGuess->data.F32[i]; 241 } 242 } 243 } else { 244 for (i=0;i<initialGuess->n;i++) { 245 xInit[i] = initialGuess->data.F32[i]; 246 } 247 } 248 249 // Creates the vector for x which GSL uses. Must deallocate. 250 gsl_vector_view x = gsl_vector_view_array(xInit, inputData->count); 251 252 const gsl_rng_type *type; 202 253 gsl_rng *r; 203 254 gsl_rng_env_setup(); 204 255 205 256 type = gsl_rng_default; 206 r = gsl_rng_alloc (type);257 r = gsl_rng_alloc(type); 207 258 208 259 f.f = &gsl_function_f; 209 260 f.df = &gsl_function_df; 210 f.fdf = &gsl_ function_fdf;261 f.fdf = &gsl_my_function_fdf; 211 262 f.n = n; 212 f.p = p; 213 f.params = &inputdata; 214 215 T = gsl_multifit_fdfsolver_lmsder; 216 s = gsl_multifit_fdfsolver_alloc (T, n, p); 217 gsl_multifit_fdfsolver_set (s, &f, &x.vector); 218 219 print_state (iter, s); 220 263 f.p = inputData->count; 264 f.params = &inputData; 265 266 // This tells GSL to use the Levenberg-Marquardt algorithm for chi2 267 // minimization. 268 // T = gsl_multifit_fdfsolver_lmsder; 269 270 // Creates an instance of the GSL solver that we will be iterating on. 271 s = gsl_multifit_fdfsolver_alloc(T, n, inputData->count); 272 273 // Initialize the GSL minimizer. 274 gsl_multifit_fdfsolver_set(s, &f, &x.vector); 275 276 // print_state(iter, s); 221 277 do { 222 278 iter++; 223 status = gsl_multifit_fdfsolver_iterate (s); 224 225 printf ("status = %s\n", gsl_strerror (status)); 226 227 print_state (iter, s); 228 229 // Figure this out 230 if (status) 231 break; 279 // Perform an iteration of the GSL solver. 280 status = gsl_multifit_fdfsolver_iterate(s); 281 282 // printf("status = %s\n", gsl_strerror(status)); 283 // print_state(iter, s); 284 285 // If there was a problem, abort. 286 if (status) { 287 psAbort(__func__, "gsl_multifit_fdfsolver_iterate()\n"); 288 } 232 289 233 290 // Checks whether the (L2-norm) computed derivative and the difference 234 // between the real/actual for that test x-vector. If were close enough 235 // exit loop. 236 status = gsl_multifit_test_delta (s->dx, s->x, 237 1e-4, 1e-4); 291 // between the real/actual for that test x-vector. If were close 292 // enough exit loop. 293 294 // Test if the parameters changed by a small enough amount. 295 status = gsl_multifit_test_delta(s->dx, s->x, 1e-4, 1e-4); 238 296 } while (status == GSL_CONTINUE && iter < 500); 239 gsl_matrix *covar = gsl_matrix_alloc (p, p); 240 gsl_multifit_covar (s->J, 0.0, covar); 241 gsl_matrix_fprintf (stdout, covar, "%g"); 242 243 /* add in masked values */ 244 j = 0; 245 loop i over the length of initialguess 246 { 247 if mask(i) 248 { 249 // do nothing, initialguess shouldn't have changed */ 250 } else 251 { 252 initialguess(i) = gsl_vector_get(s->x, j); /* output */ 253 uncertainity = sqrt(gsl_matrix_get(covar,j,j)); 254 j++; 255 } 256 } 257 double chi = gsl_blas_dnrm2(s->f); 258 gsl_multifit_fdfsolver_free (s); 259 return 0; 260 } 261 262 // For 3-element vectors 263 int print_state(size_t iter, 264 gsl_multifit_fdfsolver * s) 265 { 266 printf ("iter: %3u x = % 15.8f % 15.8f % 15.8f " 267 "|f(x)| = %g\n", 268 iter, 269 gsl_vector_get (s->x, 0), 270 gsl_vector_get (s->x, 1), 271 gsl_vector_get (s->x, 2), 272 gsl_blas_dnrm2 (s->f)); 273 } 274 275 276 277 278 279 297 298 299 300 301 if (paramMask != NULL) { 302 j = 0; 303 for (i=0;i<initialGuess->n;i++) { 304 if (paramMask->data.U8[i] == 0) { 305 initialGuess->data.F32[i] = gsl_vector_get(s->x, j++); 306 } else { 307 initialGuess->data.F32[i] = initialGuess->data.F32[i]; 308 } 309 } 310 } else { 311 for (i=0;i<initialGuess->n;i++) { 312 initialGuess->data.F32[i] = gsl_vector_get(s->x, i); 313 } 314 } 315 316 *chiSq = gsl_blas_dnrm2(s->f); 317 gsl_multifit_fdfsolver_free(s); 318 // Free all allocated memory 319 psFree(xInit); 320 psFree(inputData); 321 322 return(initialGuess); 323 } 280 324 281 325 /** @brief This procedure calculates various combinations of powers of x and y
Note:
See TracChangeset
for help on using the changeset viewer.
