source: GLBFrejus/HEAD/src/glb_min_sup.c@ 151

Last change on this file since 151 was 2, checked in by campagne, 20 years ago

first import

File size: 9.1 KB
Line 
1/* GLoBES -- General LOng Baseline Experiment Simulator
2 * (C) 2002 - 2004, The GLoBES Team
3 *
4 * GLoBES is mainly intended for academic purposes. Proper
5 * credit must be given if you use GLoBES or parts of it. Please
6 * read the section 'Credit' in the README file.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23
24
25#include <math.h>
26#include <stdio.h>
27
28/* new */
29/*#include <stdlib.h>
30#include <math.h>
31#include <string.h> */
32
33#include "glb_error.h"
34#include "glb_min_sup.h"
35
36static void glb_minimizer_error(char error_text[])
37{
38 glb_fatal(error_text);
39}
40
41double *glb_alloc_vec(int nl,int nh)
42{
43 double *v;
44 v=(double *)glb_malloc((unsigned) (nh-nl+1)*sizeof(double));
45 return v-nl;
46}
47
48double **glb_alloc_mat(int nrl,int nrh, int ncl,int nch)
49{
50 int i;
51 double **m;
52
53 m=(double **) glb_malloc((unsigned) (nrh-nrl+1)*sizeof(double*));
54 m -= nrl;
55 for(i=nrl;i<=nrh;i++)
56 {
57 m[i]=(double *) glb_malloc((unsigned)
58 (nch-ncl+1)*sizeof(double));
59 m[i] -= ncl;
60 }
61 return m;
62}
63
64void glb_free_vec(double *v,int nl,int nh)
65{
66 glb_free((char*) (v+nl));
67}
68
69void glb_free_mat(double **m,int nrl,int nrh,int ncl,int nch)
70{
71 int i;
72 for(i=nrh;i>=nrl;i--) glb_free((char*) (m[i]+ncl));
73 glb_free((char*) (m+nrl));
74}
75
76
77
78
79#define TOL 2.0e-4
80
81
82typedef struct {
83 int ncom;
84 double *pcom;
85 double *xicom;
86 double (*nrfunc)(double*);
87} glb_min_data;
88
89
90static double one_dim_projection(double x,glb_min_data *in)
91{
92 int j;
93 double f,*xt;
94
95 xt=glb_alloc_vec(1,in->ncom);
96 for (j=1;j<=in->ncom;j++) xt[j]=in->pcom[j]+x*in->xicom[j];
97 f=in->nrfunc(xt);
98 glb_free_vec(xt,1,in->ncom);
99 return f;
100}
101
102
103
104#define ITMAX 100
105#define CGOLD 0.3819660
106#define ZEPS 1.0e-10
107#define SIGN(a,b) ((b) > 0.0 ? fabs(a) : -fabs(a))
108#define SHFT(a,b,c,d) (a)=(b);(b)=(c);(c)=(d);
109
110static double glb_brent_min(double ax,double bx,double cx,
111 double (*f)(double,glb_min_data*),
112 double tol,double *xmin,glb_min_data *in)
113{
114 int iter;
115 double a,b,d,etemp,fu,fv,fw,fx,p,q,r,tol1,tol2,u,v,w,x,xm;
116 double e=0.0;
117
118 a=((ax < cx) ? ax : cx);
119 b=((ax > cx) ? ax : cx);
120 x=w=v=bx;
121 fw=fv=fx=(*f)(x,in);
122 for (iter=1;iter<=ITMAX;iter++) {
123 xm=0.5*(a+b);
124 tol2=2.0*(tol1=tol*fabs(x)+ZEPS);
125 if (fabs(x-xm) <= (tol2-0.5*(b-a))) {
126 *xmin=x;
127 return fx;
128 }
129 if (fabs(e) > tol1) {
130 r=(x-w)*(fx-fv);
131 q=(x-v)*(fx-fw);
132 p=(x-v)*q-(x-w)*r;
133 q=2.0*(q-r);
134 if (q > 0.0) p = -p;
135 q=fabs(q);
136 etemp=e;
137 e=d;
138 if (fabs(p) >= fabs(0.5*q*etemp) || p <= q*(a-x) || p >= q*(b-x))
139 d=CGOLD*(e=(x >= xm ? a-x : b-x));
140 else {
141 d=p/q;
142 u=x+d;
143 if (u-a < tol2 || b-u < tol2)
144 d=SIGN(tol1,xm-x);
145 }
146 } else {
147 d=CGOLD*(e=(x >= xm ? a-x : b-x));
148 }
149 u=(fabs(d) >= tol1 ? x+d : x+SIGN(tol1,d));
150 fu=(*f)(u,in);
151 if (fu <= fx) {
152 if (u >= x) a=x; else b=x;
153 SHFT(v,w,x,u)
154 SHFT(fv,fw,fx,fu)
155 } else {
156 if (u < x) a=u; else b=u;
157 if (fu <= fw || w == x) {
158 v=w;
159 w=u;
160 fv=fw;
161 fw=fu;
162 } else if (fu <= fv || v == x || v == w) {
163 v=u;
164 fv=fu;
165 }
166 }
167 }
168 glb_minimizer_error("glb_brent_min");
169 *xmin=x;
170 return fx;
171}
172
173#undef ITMAX
174#undef CGOLD
175#undef ZEPS
176#undef SIGN
177
178
179
180
181#define GOLD 1.618034
182#define GLIMIT 100.0
183#define TINY 1.0e-20
184#define MAX(a,b) ((a) > (b) ? (a) : (b))
185#define SIGN(a,b) ((b) > 0.0 ? fabs(a) : -fabs(a))
186#define SHFT(a,b,c,d) (a)=(b);(b)=(c);(c)=(d);
187
188static void bracket(double *ax,double *bx,double *cx,double *fa,double *fb,
189 double *fc, double (*func)(double,glb_min_data*),glb_min_data *in)
190{
191 double ulim,u,r,q,fu,dum;
192
193 *fa=(*func)(*ax,in);
194 *fb=(*func)(*bx,in);
195 if (*fb > *fa) {
196 SHFT(dum,*ax,*bx,dum)
197 SHFT(dum,*fb,*fa,dum)
198 }
199 *cx=(*bx)+GOLD*(*bx-*ax);
200 *fc=(*func)(*cx,in);
201 while (*fb > *fc) {
202 r=(*bx-*ax)*(*fb-*fc);
203 q=(*bx-*cx)*(*fb-*fa);
204 u=(*bx)-((*bx-*cx)*q-(*bx-*ax)*r)/
205 (2.0*SIGN(MAX(fabs(q-r),TINY),q-r));
206 ulim=(*bx)+GLIMIT*(*cx-*bx);
207 if ((*bx-u)*(u-*cx) > 0.0) {
208 fu=(*func)(u,in);
209 if (fu < *fc) {
210 *ax=(*bx);
211 *bx=u;
212 *fa=(*fb);
213 *fb=fu;
214 return;
215 } else if (fu > *fb) {
216 *cx=u;
217 *fc=fu;
218 return;
219 }
220 u=(*cx)+GOLD*(*cx-*bx);
221 fu=(*func)(u,in);
222 } else if ((*cx-u)*(u-ulim) > 0.0) {
223 fu=(*func)(u,in);
224 if (fu < *fc) {
225 SHFT(*bx,*cx,u,*cx+GOLD*(*cx-*bx))
226 SHFT(*fb,*fc,fu,(*func)(u,in))
227 }
228 } else if ((u-ulim)*(ulim-*cx) >= 0.0) {
229 u=ulim;
230 fu=(*func)(u,in);
231 } else {
232 u=(*cx)+GOLD*(*cx-*bx);
233 fu=(*func)(u,in);
234 }
235 SHFT(*ax,*bx,*cx,u)
236 SHFT(*fa,*fb,*fc,fu)
237 }
238}
239
240
241
242#undef GOLD
243#undef GLIMIT
244#undef TINY
245#undef MAX
246#undef SIGN
247#undef SHFT
248
249
250static void line_minimization(double p[],double xi[],int n,double *fret,
251 double (*func)(double*),
252 glb_min_data *in)
253{
254 int j;
255 double xx,xmin,fx,fb,fa,bx,ax;
256 int ncom=0;
257 double *pcom=0,*xicom=0,(*nrfunc)(double*);
258
259 ncom=n;
260 pcom=glb_alloc_vec(1,n);
261 xicom=glb_alloc_vec(1,n);
262 nrfunc=func;
263 for (j=1;j<=n;j++) {
264 pcom[j]=p[j];
265 xicom[j]=xi[j];
266 }
267
268 in->ncom=n;
269 in->pcom=pcom;
270 in->xicom=xicom;
271 in->nrfunc=func;
272 ax=0.0;
273 xx=1.0;
274 bx=2.0;
275 bracket(&ax,&xx,&bx,&fa,&fx,&fb,one_dim_projection,in);
276 *fret=glb_brent_min(ax,xx,bx,one_dim_projection,TOL,&xmin,in);
277 for (j=1;j<=n;j++) {
278 xi[j] *= xmin;
279 p[j] += xi[j];
280 }
281 glb_free_vec(xicom,1,n);
282 glb_free_vec(pcom,1,n);
283}
284
285
286
287
288
289
290
291#define ITMAX 10000 /* was 500 */
292static double sqrarg;
293#define SQR(a) (sqrarg=(a),sqrarg*sqrarg)
294
295void glb_powell(double p[],double **xi,int n,
296 double ftol,int *iter,double *fret,
297 double (*func)(double*))
298{
299 int i,ibig,j;
300 double t,fptt,fp,del;
301 double *pt,*ptt,*xit;
302 glb_min_data in;
303 pt=glb_alloc_vec(1,n);
304 ptt=glb_alloc_vec(1,n);
305 xit=glb_alloc_vec(1,n);
306 *fret=(*func)(p);
307 for (j=1;j<=n;j++) pt[j]=p[j];
308 for (*iter=1;;(*iter)++) {
309 fp=(*fret);
310 ibig=0;
311 del=0.0;
312 for (i=1;i<=n;i++) {
313 for (j=1;j<=n;j++) xit[j]=xi[j][i];
314 fptt=(*fret);
315 line_minimization(p,xit,n,fret,func,&in);
316 if (fabs(fptt-(*fret)) > del) {
317 del=fabs(fptt-(*fret));
318 ibig=i;
319 }
320 }
321 if (2.0*fabs(fp-(*fret)) <= ftol*(fabs(fp)+fabs(*fret))) {
322 glb_free_vec(xit,1,n);
323 glb_free_vec(ptt,1,n);
324 glb_free_vec(pt,1,n);
325 return;
326 }
327 if (*iter == ITMAX)
328 { /* modified by WW */
329 /* glb_minimizer_error("empty (1)"); */
330 glb_free_vec(xit,1,n);
331 glb_free_vec(ptt,1,n);
332 glb_free_vec(pt,1,n);
333 (*fret) = 999999.0;
334 printf("At Point: ");
335 for (j=1;j<=n;j++) printf("%g ",p[j]);
336 printf("\n");
337 glb_error("Minimizer error: no convergence (1)");
338 return;
339 }
340 for (j=1;j<=n;j++) {
341 ptt[j]=2.0*p[j]-pt[j];
342 xit[j]=p[j]-pt[j];
343 pt[j]=p[j];
344 }
345 fptt=(*func)(ptt);
346 if (fptt < fp) {
347 t=2.0*(fp-2.0*(*fret)+fptt)*SQR(fp-(*fret)-del)-del*SQR(fp-fptt);
348 if (t < 0.0) {
349 line_minimization(p,xit,n,fret,func,&in);
350 for (j=1;j<=n;j++) xi[j][ibig]=xit[j];
351 }
352 }
353 }
354}
355
356
357void glb_powell2(double p[],double **xi,int n,double ftol,
358 int *iter,double *fret,
359 double (*func)(double*))
360{
361 int i,ibig,j;
362 double t,fptt,fp,del;
363 double *pt,*ptt,*xit;
364 glb_min_data in;
365 pt=glb_alloc_vec(1,n);
366 ptt=glb_alloc_vec(1,n);
367 xit=glb_alloc_vec(1,n);
368 *fret=(*func)(p);
369 for (j=1;j<=n;j++) pt[j]=p[j];
370 for (*iter=1;;(*iter)++) {
371 fp=(*fret);
372 ibig=0;
373 del=0.0;
374 for (i=1;i<=n;i++) {
375 for (j=1;j<=n;j++) xit[j]=xi[j][i];
376 fptt=(*fret);
377 line_minimization(p,xit,n,fret,func,&in);
378 if (fabs(fptt-(*fret)) > del) {
379 del=fabs(fptt-(*fret));
380 ibig=i;
381 }
382 }
383 if (2.0*fabs(fp-(*fret)) <= ftol*(fabs(fp)+fabs(*fret))) {
384 glb_free_vec(xit,1,n);
385 glb_free_vec(ptt,1,n);
386 glb_free_vec(pt,1,n);
387 return;
388 }
389 if (*iter == ITMAX)
390 { /* modified by WW */
391 /* glb_minimizer_error("empty (2)"); */
392 glb_free_vec(xit,1,n);
393 glb_free_vec(ptt,1,n);
394 glb_free_vec(pt,1,n);
395 (*fret) = 999999.0;
396 printf("At Point: ");
397 for (j=1;j<=n;j++) printf("%g ",p[j]);
398 printf("\n");
399 glb_error("Minimizer error: no convergence (2)");
400 return;
401 }
402
403 for (j=1;j<=n;j++) {
404 ptt[j]=2.0*p[j]-pt[j];
405 xit[j]=p[j]-pt[j];
406 pt[j]=p[j];
407 }
408 fptt=(*func)(ptt);
409 if (fptt < fp) {
410 t=2.0*(fp-2.0*(*fret)+fptt)*SQR(fp-(*fret)-del)-del*SQR(fp-fptt);
411 if (t < 0.0) {
412 line_minimization(p,xit,n,fret,func,&in);
413 for (j=1;j<=n;j++) xi[j][ibig]=xit[j];
414 }
415 }
416 }
417}
418
419
420
421#undef ITMAX
422#undef SQR
423#undef TOL
Note: See TracBrowser for help on using the repository browser.