GLAMERDOC++
Gravitational Lensing Code Library
Loading...
Searching...
No Matches
powell.h
1#include <math.h>
2#include <nrutil.h>
3#include <vector>
4#include <stdexcept>
5
6#define TINY 1.0e-25
7#define ITMAX 5000
8#define ITMAX1 500
9#define SHFT(a,b,c,d) (a)=(b);(b)=(c);(c)=(d);
10#define CGOLD 0.3819660
11#define ZEPS 1.0e-10
12#define GOLD 1.618034
13#define GLIMIT 100.0
14#define TINY1 1.0e-20
15#define TOL 2.0e-6
16
17//shift in pointer that goes into functor ?
18
19template <typename T,typename F>
20T f1dim_tp(T x,std::vector<T> &pcom,std::vector<T> &xicom,F &functor)
21{
22 int j;
23 T f;
24 int ncom = pcom.size()-1;
25 std::vector<T> xt(ncom+1);
26 for (j=1;j<=ncom;j++) xt[j] = pcom[j] + x * xicom[j];
27 f = functor(xt.data() + 1);
28
29 return f;
30}
31
32template <typename T,typename F>
33T brent_tp(T ax, T bx, T cx, T tol,T *xmin,std::vector<T> &pcom,std::vector<T> &xicom,F &functor)
34{
35 int iter;
36 T a,b,d,etemp,fu,fv,fw,fx,p,q,r,tol1,tol2,u,v,w,x,xm;
37 T e=0.0;
38
39 a=(ax < cx ? ax : cx);
40 b=(ax > cx ? ax : cx);
41 x=w=v=bx;
42 fw=fv=fx=f1dim_tp(x,pcom,xicom,functor);
43 for (iter=1;iter<=ITMAX1;iter++) {
44 xm=0.5*(a+b);
45 tol2=2.0*(tol1=tol*fabs(x)+ZEPS);
46 if (fabs(x-xm) <= (tol2-0.5*(b-a))) {
47 *xmin=x;
48 return fx;
49 }
50 if (fabs(e) > tol1) {
51 r=(x-w)*(fx-fv);
52 q=(x-v)*(fx-fw);
53 p=(x-v)*q-(x-w)*r;
54 q=2.0*(q-r);
55 if (q > 0.0) p = -p;
56 q=fabs(q);
57 etemp=e;
58 e=d;
59 if (fabs(p) >= fabs(0.5*q*etemp) || p <= q*(a-x) || p >= q*(b-x))
60 d=CGOLD*(e=(x >= xm ? a-x : b-x));
61 else {
62 d=p/q;
63 u=x+d;
64 if (u-a < tol2 || b-u < tol2)
65 d=SIGN(tol1,xm-x);
66 }
67 } else {
68 d=CGOLD*(e=(x >= xm ? a-x : b-x));
69 }
70 u=(fabs(d) >= tol1 ? x+d : x+SIGN(tol1,d));
71 fu=f1dim_tp(u,pcom,xicom,functor);
72 if (fu <= fx) {
73 if (u >= x) a=x; else b=x;
74 SHFT(v,w,x,u)
75 SHFT(fv,fw,fx,fu)
76 } else {
77 if (u < x) a=u; else b=u;
78 if (fu <= fw || w == x) {
79 v=w;
80 w=u;
81 fv=fw;
82 fw=fu;
83 } else if (fu <= fv || v == x || v == w) {
84 v=u;
85 fv=fu;
86 }
87 }
88 }
89 throw std::runtime_error("Too many iterations in brent_tpd");
90 *xmin=x;
91 return fx;
92}
93
94
95template <typename T,typename F>
96void mnbrak_tp(T *ax, T *bx, T *cx, T *fa, T *fb, T *fc,std::vector<T> &pcom,std::vector<T> &xicom
97 ,F &functor)
98{
99 T ulim,u,r,q,fu,dum;
100
101 *fa=f1dim_tp(*ax,pcom,xicom,functor);
102 *fb=f1dim_tp(*bx,pcom,xicom,functor);
103 if (*fb > *fa) {
104 SHFT(dum,*ax,*bx,dum)
105 SHFT(dum,*fb,*fa,dum)
106 }
107 *cx=(*bx)+GOLD*(*bx-*ax);
108 *fc=f1dim_tp(*cx,pcom,xicom,functor);
109 while (*fb > *fc) {
110 r=(*bx-*ax)*(*fb-*fc);
111 q=(*bx-*cx)*(*fb-*fa);
112 u=(*bx)-((*bx-*cx)*q-(*bx-*ax)*r)/
113 (2.0*SIGN(DMAX(fabs(q-r),TINY1),q-r));
114 ulim=(*bx)+GLIMIT*(*cx-*bx);
115 if ((*bx-u)*(u-*cx) > 0.0) {
116 fu=f1dim_tp(u,pcom,xicom,functor);
117 if (fu < *fc) {
118 *ax=(*bx);
119 *bx=u;
120 *fa=(*fb);
121 *fb=fu;
122 return;
123 } else if (fu > *fb) {
124 *cx=u;
125 *fc=fu;
126 return;
127 }
128 u=(*cx)+GOLD*(*cx-*bx);
129 fu=f1dim_tp(u,pcom,xicom,functor);
130 } else if ((*cx-u)*(u-ulim) > 0.0) {
131 fu=f1dim_tp(u,pcom,xicom,functor);
132 if (fu < *fc) {
133 SHFT(*bx,*cx,u,*cx+GOLD*(*cx-*bx))
134 SHFT(*fb,*fc,fu,f1dim_tp(u,pcom,xicom,functor))
135 }
136 } else if ((u-ulim)*(ulim-*cx) >= 0.0) {
137 u=ulim;
138 fu=f1dim_tp(u,pcom,xicom,functor);
139 } else {
140 u=(*cx)+GOLD*(*cx-*bx);
141 fu=f1dim_tp(u,pcom,xicom,functor);
142 }
143 SHFT(*ax,*bx,*cx,u)
144 SHFT(*fa,*fb,*fc,fu)
145 }
146}
147
148template <typename T,typename F>
149void linmind_tp(T p[], T xi[], int n, T *fret, F &functor)
150{
151
152 int j;
153 T xx,xmin,fx,fb,fa,bx,ax;
154
155 std::vector<T> pcom(n+1);
156 std::vector<T> xicom(n+1);
157 //nrfunc=func;
158 for (j=1;j<=n;j++) {
159 pcom[j]=p[j];
160 xicom[j]=xi[j];
161 }
162 ax=0.0;
163 xx=1.0;
164 mnbrak_tp(&ax,&xx,&bx,&fa,&fx,&fb,pcom,xicom,functor);
165 *fret=brent_tp(ax,xx,bx,TOL,&xmin,pcom,xicom,functor);
166 for (j=1;j<=n;j++) {
167 xi[j] *= xmin;
168 p[j] += xi[j];
169 }
170}
171
179template <typename T,typename F>
180void powell_tp(
181 T *pp
182 , int n
183 , T ftol
184 , int *iter
185 , T *fret
186 ,F &functor
187 )
188{
189 int i,ibig,j;
190 T del,fp,fptt,t;
191 T *p = pp-1;
192
193 //Utilities::D2Matrix<T> xi(n+1, n+1);
194 std::vector<T> simplex((n+1)*(n+1));
195
196 T **xi = new T*[n+1];
197 xi[0] = simplex.data();
198 for (long i = 1; i <= n; ++i) xi[i] = xi[0] + i * (n+1);
199
200 for (long i = 0; i <= n; ++i){
201 xi[i][i] = 2*sqrt(ftol);
202 for (long j = i+1; j <= n; ++j) {
203 xi[i][j] = xi[j][i] = 0;
204 }
205 }
206
207 std::vector<T> pt(n+1);
208 std::vector<T> ptt(n+1);
209 std::vector<T> xit(n+1);
210 *fret = functor(p+1);
211 for (j=1;j<=n;j++) pt[j]=p[j];
212 for (*iter=1;;++(*iter)) {
213 fp=(*fret);
214 ibig=0;
215 del=0.0;
216 for (i=1;i<=n;i++) {
217 for (j=1;j<=n;j++) xit[j]=xi[j][i];
218 fptt=(*fret);
219 linmind_tp(p,xit.data(),n,fret,functor);
220 if (fptt-(*fret) > del) {
221 del=fptt-(*fret);
222 ibig=i;
223 }
224 }
225 if (2.0*(fp-(*fret)) <= ftol*(fabs(fp)+fabs(*fret))+TINY) {
226 return;
227 }
228 if (*iter == ITMAX){
229 throw std::runtime_error("powell_tp exceeding maximum iterations.");
230 };
231 for (j=1;j<=n;j++) {
232 ptt[j]=2.0*p[j]-pt[j];
233 xit[j]=p[j]-pt[j];
234 pt[j]=p[j];
235 }
236 fptt=functor(ptt.data()+1);
237 if (fptt < fp) {
238 t=2.0*(fp-2.0*(*fret)+fptt)*sqrt(fp-(*fret)-del)-del*sqrt(fp-fptt);
239 if (t < 0.0) {
240 linmind_tp(p,xit.data(),n,fret,functor);
241 for (j=1;j<=n;j++) {
242 xi[j][ibig]=xi[j][n];
243 xi[j][n]=xit[j];
244 }
245 }
246 }
247 }
248 delete [] xi;
249}
250
251/* note #undef's at end of file */
252
253
254/* note #undef's at end of file */
255
256
257#undef ITMAX
258#undef ITMAX1
259#undef NRANSI
260#undef TOL
261#undef GOLD
262#undef GLIMIT
263#undef TINY
264#undef TINY1
265#undef SHFT
266#undef CGOLD
267#undef ZEPS
268