SINFONI Pipeline Reference Manual  2.5.2
sinfo_fit.c
1 /*
2  * This file is part of the ESO SINFONI Pipeline
3  * Copyright (C) 2004,2005 European Southern Observatory
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA
18  */
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
22 #include <sinfo_fit.h>
23 #include <sinfo_msg.h>
24 #include <stdio.h>
25 #include <math.h>
33 static double
34 sinfo_spline(double x, double cons[], double ak[], double *sp, double *spp,
35  double *sppp, int n);
36 
51 double
52 sinfo_amsub(double d0[], double d1[], double d2[], double value[],
53  double range[], double tol, int ivorf[], int ncon, int nref, double
54  (*ftbm)(double[], int ncon))
55 
56 {
57  double alpha = 1.0, loc_gamma = 1.5;
58  double sf, bsave, temp, sum, cval, ccval, beta;
59  int idone, nvar, nvec, nrefl, i, j, k, kd1, kval, isign, jvar, imin, imax,
60  i2max, it1, it2, itemp;
61  idone = 0;
62  isign = 1;
63  // we require that nvec=nvar+1, define nvar
64  nvar = 0;
65  for (i = 0; i < ncon; ++i) {
66  if (ivorf[i] == 1) {
67  nvar = nvar + 1;
68  }
69  }
70  nvec = nvar + 1;
71  // sf is the 'shrink' factor
72  sf = 1e5 * nvec;
73  nrefl = 0;
74  value[0] = (*ftbm)(d2, ncon);
75  // sinfo_msg("value[0] = %lg",value[0]);
76  // initial and shrink calculation of the d1 array, uses range
77  // set d2 in the first position -- using Fortran convention of 1st
78  // array element moving first
79  cont20: kd1 = -1;
80  for (i = 0; i < ncon; ++i) {
81  if (ivorf[i] == 1) {
82  kd1 = kd1 + 1;
83  d1[kd1] = d2[i];
84  }
85  }
86  // now for the next nvar values
87  kval = 0;
88  for (jvar = 0; jvar < ncon; ++jvar) {
89  if (ivorf[jvar] == 1) {
90  kval = kval + 1;
91  bsave = d2[jvar];
92  isign = -isign;
93  d2[jvar] = d2[jvar] + isign * range[jvar];
94  value[kval] = (*ftbm)(d2, ncon);
95  for (i = 0; i < ncon; ++i) {
96  if (ivorf[i] == 1) {
97  kd1 = kd1 + 1;
98  d1[kd1] = d2[i];
99  }
100  }
101  d2[jvar] = bsave;
102  }
103  }
104  // sinfo_msg(" d1 ");
105  // for (j=0;j<nvec;++j) {
106  // for(i=0;i<nvar;++i) {
107  // sinfo_msg("%12.4lg ",d1[i+j*nvar]);
108  // }
109  // }
110  /* find highest, second highest, and minimum values
111  imax points to the vector with the largest value
112  i2max points to the vector with the second largest value
113  imin points to the vector with the smallest value */
114  cont40: imin = 1;
115  if (value[0] > value[1]) {
116  imax = 0;
117  i2max = 1;
118  }
119  else {
120  imax = 1;
121  i2max = 0;
122  }
123  for (i = 0; i < nvec; ++i) {
124  if (value[i] < value[imin])
125  imin = i;
126  if (value[i] > value[imax]) {
127  i2max = imax;
128  imax = i;
129  }
130  else if ((value[i] > value[i2max]) && (i != imax)) {
131  i2max = i;
132  }
133  }
134  // sinfo_msg(" values after sorting ");
135  // for(i=0;i<nvec;++i)sinfo_msg("%12.4lg ",value[i]);
136  // sinfo_msg("imin %d,i2max %d,imax %d",imin,i2max,imax);
137  // scanf("%d",&itest);
138 
139  // check if done
140 
141  if (nrefl >= nref) {
142  sinfo_msg(" maximum number of reflection reached");
143  idone = 1;
144  goto cont400;
145  }
146  if (value[imin] != 0.0) {
147  temp = (value[imax] - value[imin]) / value[imin];
148  if (fabs(temp) <= tol) {
149  sinfo_msg(" reached tolerance %lg temp %lg tol", temp, tol);
150  idone = 1;
151  goto cont400;
152  }
153  }
154  if (value[imax] - value[imin] <= tol) {
155  sinfo_msg("value[max]-value[min]<=tol");
156  idone = 1;
157  goto cont400;
158  }
159 
160  // *** form d0 the average of all but imax
161  for (j = 0; j < nvar; ++j) {
162  sum = 0.0;
163  for (i = 0; i < nvec; ++i) {
164  if (i != imax)
165  sum = sum + d1[i * nvar + j];
166  }
167  d0[j] = sum / (nvec - 1);
168  }
169  // sinfo_msg(" D0 values ");
170  // for(i=0;i<nvar;++i)sinfo_msg("%12.4lg ",d0[i]);
171  // scanf("%d",&itest);
172  // reflection
173 
174  nrefl = nrefl + 1;
175  k = -1;
176  for (j = 0; j < ncon; ++j) {
177  if (ivorf[j] == 1) {
178  k = k + 1;
179  it1 = imax * nvar + k;
180  d2[j] = (1 + alpha) * d0[k] - alpha * d1[it1];
181  }
182  }
183 
184  // sinfo_msg(" refl d2 ");
185  // for(i=0;i<nvar;++i) sinfo_msg("%12.4lg ",d2[i]);
186 
187  cval = (*ftbm)(d2, ncon);
188  // sinfo_msg("refl ftbm %lg",cval);
189 
190  // value is higher than i2max so do contraction
191  if (cval >= value[i2max])
192  goto cont200;
193 
194  // value is less than i2max - normal - update d1 and value
195 
196  value[imax] = cval;
197  k = -1;
198  for (j = 0; j < ncon; ++j) {
199  if (ivorf[j] == 1) {
200  k = k + 1;
201  it1 = imax * nvar + k;
202  d1[it1] = d2[j];
203  }
204  }
205 
206  // value is less than imin, try expansion
207  if (cval < value[imin])
208  goto cont300;
209  goto cont40;
210 
211  // contraction
212  cont200:
213  // sinfo_msg(" contraction ");
214  beta = 0.75;
215  for (itemp = 0; itemp < 3; ++itemp) {
216  if (cval <= value[imax]) {
217  value[imax] = cval;
218  k = -1;
219  for (j = 0; j < ncon; ++j) {
220  if (ivorf[j] == 1) {
221  k = k + 1;
222  it1 = imax * nvar + k;
223  d1[it1] = d2[j];
224  }
225  }
226  }
227  k = -1;
228  for (j = 0; j < ncon; ++j) {
229  if (ivorf[j] == 1) {
230  k = k + 1;
231  it1 = imax * nvar + k;
232  d2[j] = beta * d1[it1] + (1. - beta) * d0[k];
233  }
234  }
235  cval = ftbm(d2, ncon);
236 
237  // sinfo_msg(" contraction beta %lg cval %lg ",beta,cval);
238  // value is better
239  if (cval < value[i2max]) {
240  value[imax] = cval;
241  k = -1;
242  for (j = 0; j < ncon; ++j) {
243  if (ivorf[j] == 1) {
244  k = k + 1;
245  it1 = imax * nvar + k;
246  d1[it1] = d2[j];
247  }
248  }
249  if (cval < value[imin])
250  sinfo_msg(" contraction minimum %lg", cval);
251  goto cont40;
252  }
253  beta = beta - 0.25;
254  }
255  sinfo_msg(" contraction failed ==>shrink");
256  // scanf("%d",&itest);
257  // value is worse so shrink it
258 
259  goto cont400;
260 
261  // expansion
262 
263  cont300:
264  sinfo_msg(" reflection min %lg \n", cval);
265  k = -1;
266  for (j = 0; j < ncon; ++j) {
267  if (ivorf[j] == 1) {
268  k = k + 1;
269  d2[j] = loc_gamma * d2[j] + (1. - loc_gamma) * d0[k];
270  }
271  }
272  ccval = (*ftbm)(d2, ncon);
273  // value is higher than reflected value ==> discard
274  if (ccval > cval)
275  goto cont40;
276  // value is better so use it rather than the reflected point
277  sinfo_msg(" expansion minimum %lg \n", ccval);
278  value[imax] = ccval;
279  k = -1;
280  for (j = 0; j < ncon; ++j) {
281  if (ivorf[j] == 1) {
282  k = k + 1;
283  it1 = imax * nvar + k;
284  d1[it1] = d2[j];
285  }
286  }
287  goto cont40;
288 
289  cont400:
290  // sinfo_msg(" following cont400 ");
291  // scanf("%d",&itest);
292  // recalculate d2 and range
293  // the range is the average of dist**2 from d1 with min value
294  k = -1;
295  for (j = 0; j < ncon; ++j) {
296  if (ivorf[j] == 1) {
297  k = k + 1;
298  it1 = imin * nvar + k;
299  d2[j] = d1[it1];
300  sum = 0.0;
301  for (i = 0; i < nvec; ++i) {
302  it1 = i * nvar + k;
303  it2 = imin * nvar + k;
304  sum = sum + (d1[it1] - d1[it2]) * (d1[it1] - d1[it2]);
305  }
306  range[j] = sf * sqrt(sum / (nvec - 1));
307  }
308  }
309  value[1] = value[imin];
310  sf = .75 * sf;
311  if (sf < 0.1)
312  idone = 1;
313  sinfo_msg(" shrink factor %lg ", sf);
314  if (idone != 1)
315  goto cont20;
316  return value[1];
317 
318 }
319 
320 static double
321 sinfo_spline(double x, double cons[], double ak[], double *sp, double *spp,
322  double *sppp, int n)
323 {
324  double retval = 0;
325  double xm = 0;
326  double xm2 = 0;
327  double xm3 = 0;
328 
329  int i = 0;
330 
331  *sp = 0;
332  *spp = 0;
333  *sppp = 0;
334 
335  for (i = 0; i < n; ++i) {
336  if (ak[i] >= x) {
337  xm = ak[i] - x;
338  xm2 = xm * xm;
339  xm3 = xm * xm2;
340  sinfo_msg("cons=%g", cons[i]);
341  retval += cons[i] * xm3;
342  *sp -= 3 * cons[i] * xm2;
343  *spp += 6 * cons[i] * xm;
344  *sppp -= 6 * cons[i];
345  }
346  }
347  sinfo_msg("1x=%g retval=%g", x, retval);
348  return retval;
349 
350 }
351 
352 double
353 sinfo_ftbm(const double x, double cons[])
354 {
355  double retval = 0;
356  double ak[4] =
357  { -1, -.666666666666666, -.333333333333, 0 };
358  double sm1 = 0;
359  double spm1 = 0;
360  double sppm1 = 0;
361  double spppm1 = 0;
362 
363  int n = 4;
364 
365  sm1 = sinfo_spline(x, cons, ak, &spm1, &sppm1, &spppm1, n) - 1;
366  sinfo_msg("x=%g val=%g", x, sm1 + 1);
367 
368  retval = sm1 * sm1 + spm1 * spm1 + sppm1 * sppm1 + spppm1 * spppm1;
369  sinfo_msg("fitbm: x=%g retval=%g", x, retval);
370 
371  return retval;
372 
373 }
374