00001
00002
00003
00004
00005
00006
00011 #if defined(USE_DD)
00012 # define USE_DD_STUFF
00013 #endif
00014
00015 # include <admodel.h>
00016 # include <df1b2fun.h>
00017 # include <adrndeff.h>
00018 double calculate_laplace_approximation(const dvector& x,const dvector& u0,
00019 const banded_symmetric_dmatrix& bHess,const dvector& _xadjoint,
00020 const dvector& _uadjoint,
00021 const banded_symmetric_dmatrix& _bHessadjoint,function_minimizer * pmin);
00022 double calculate_laplace_approximation(const dvector& x,const dvector& u0,
00023 const dmatrix& Hess,const dvector& _xadjoint,const dvector& _uadjoint,
00024 const dmatrix& _Hessadjoint,function_minimizer * pmin);
00025
00026 #if defined(USE_DD_STUFF)
00027 # if defined(_MSC_VER)
00028 extern "C" _export void dd_newton_raphson(int n,double * v,double * diag,
00029 double * ldiag, double * yy);
00030 # else
00031 extern "C" void dd_newton_raphson(int n,double * v,double * diag,
00032 double * ldiag, double * yy);
00033 # endif
00034 #endif
00035
00040 void positivize(const banded_symmetric_dmatrix& _m,double id)
00041 {
00042 ADUNCONST(banded_symmetric_dmatrix,m)
00043 int mmin=m.indexmin();
00044 int mmax=m.indexmax();
00045 for (int i=mmin;i<=mmax;i++)
00046 {
00047 m(i,i)+=id;
00048 }
00049 }
00050
00055 class safe_choleski_solver
00056 {
00057 public:
00058 safe_choleski_solver(double id);
00059 int hadbad;
00060 int dirty;
00061 double id;
00062 double angle;
00063 dvector solve(const banded_symmetric_dmatrix& _m,const dvector&_v);
00064 };
00065
00070 safe_choleski_solver::safe_choleski_solver(double _id)
00071 {
00072 id=_id;
00073 hadbad=0;
00074 dirty=0;
00075 }
00076
00077 banded_lower_triangular_dmatrix quiet_choleski_decomp(
00078 const banded_symmetric_dmatrix& _M, int& ierr);
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00147 dvector safe_choleski_solver::solve
00148 (const banded_symmetric_dmatrix& _m,const dvector&_v)
00149 {
00150 int ierr=0;
00151 ADUNCONST(dvector,v)
00152 ADUNCONST(banded_symmetric_dmatrix,m)
00153 int mmin=m.indexmin();
00154
00155 if (hadbad && id>0.0)
00156 {
00157 positivize(m,id);
00158 dirty=1;
00159 }
00160 m.shift(1);
00161 v.shift(1);
00162 int ibreak=1;
00163 dvector w;
00164 do
00165 {
00166 const banded_lower_triangular_dmatrix& C=quiet_choleski_decomp(m,ierr);
00167 if (ierr==0)
00168 {
00169 id/=2.0;
00170 w=solve_trans(C,::solve(C,v));
00171 dvector delta=m*w;
00172 dvector err=solve_trans(C,::solve(C,v-delta));
00173 dvector w1=w+err;
00174 cout << norm(w1-w) << endl;
00175 if (norm(err)>1.e-10)
00176 {
00177 cout << "precisionerror" << endl;
00178 }
00179 angle=w*v/(norm(w)*norm(v));
00180 ibreak=0;
00181 }
00182 else
00183 {
00184 id*=2.0;
00185 positivize(m,id);
00186 ierr=0;
00187 dirty=1;
00188 hadbad=1;
00189 }
00190 }
00191 while(ibreak);
00192 m.shift(mmin);
00193 w.shift(mmin);
00194 v.shift(mmin);
00195 return w;
00196 }
00197
00201 void laplace_approximation_calculator::
00202 do_newton_raphson_state_space(function_minimizer * pfmin,double f_from_1,
00203 int& no_converge_flag)
00204 {
00205 laplace_approximation_calculator::where_are_we_flag=2;
00206 double fbest=1.e+100;
00207 double fval=1.e+100;
00208 double maxg=fabs(evaluate_function(fbest,uhat,pfmin));
00209
00210 laplace_approximation_calculator::where_are_we_flag=0;
00211 dvector uhat_old(1,usize);
00212 safe_choleski_solver scs(0.1);
00213
00214 int ii=0;
00215 for (;;)
00216 {
00217 bHess->initialize();
00218
00219 grad.initialize();
00220
00221 step=get_newton_raphson_info_banded(pfmin);
00222
00223 #ifdef DIAG
00224
00225 int check_hessian=0;
00226 if (check_hessian)
00227 {
00228 ofstream ofs("hh");
00229 ofs << colsum(dmatrix(*bHess)) << endl;
00230 }
00231 #endif
00232
00233 if (!initial_params::mc_phase)
00234 cout << "Newton raphson " << ii << " ";
00235
00236 if (quadratic_prior::get_num_quadratic_prior()>0)
00237 {
00238 quadratic_prior::get_cHessian_contribution(Hess,xsize);
00239 quadratic_prior::get_cgradient_contribution(grad,xsize);
00240 }
00241
00242
00243
00244 dvector g1(1,usize);
00245 maxg=fabs(evaluate_function(fval,uhat,g1,pfmin));
00246 if (fval>fbest)
00247 fbest=fval;
00248 if (nr_debug==1)
00249 {
00250 cout << " grad compare " << norm(g1-grad) << endl;
00251 }
00252 step=scs.solve(*bHess,g1);
00253
00254 if (nr_debug==1)
00255 {
00256 cout << " angle = " << step*grad/(norm(step)*norm(grad)) << endl;
00257 }
00258 int iic=0;
00259 double testangle=-1;
00260 int extra_try=0;
00261 dvector utry(1,usize);
00262 int smallshrink=0;
00263 for (;;)
00264 {
00265 if (++iic>10)
00266 {
00267 break;
00268 }
00269 if (extra_try==0)
00270 {
00271 utry = uhat-step;
00272 }
00273 else
00274 {
00275 utry = uhat-0.5*step;
00276 }
00277 dvector g(1,usize);
00278 maxg=fabs(evaluate_function(fval,utry,g,pfmin));
00279 if (nr_debug==1)
00280 {
00281 cout << " fbest-fval = " << setprecision(15)
00282 << fbest-fval << endl;
00283 }
00284 if (fval>fbest && maxg>1.e-10)
00285 {
00286 if (maxg<1.e-10)
00287 smallshrink=3;
00288 else if (maxg<1.e-9)
00289 smallshrink=2;
00290 else if (maxg<1.e-8)
00291 smallshrink=1;
00292
00293 if (nr_debug==1)
00294 {
00295 testangle=g*step/(norm(g)*norm(step));
00296 cout << fval-fbest << " step too large angle = " << testangle
00297 << endl;
00298 }
00299 }
00300 if (fval==fbest)
00301 {
00302 testangle=g*step/(norm(g)*norm(step));
00303 cout << " no progress angle = " << testangle << endl;
00304 }
00305 if (fval<=fbest)
00306 {
00307 uhat=utry;
00308 fbest=fval;
00309 testangle=g*step/(norm(g)*norm(step));
00310 if (nr_debug==1)
00311 {
00312 cout << "inner angle = " << testangle << endl;
00313 }
00314 if (testangle>0.4)
00315 {
00316 extra_try=extra_try+1;
00317 if (nr_debug==1)
00318 {
00319 cout << extra_try << endl;
00320 }
00321 }
00322 else
00323 {
00324 break;
00325 }
00326 }
00327 else
00328 {
00329 if (extra_try>0)
00330 {
00331 break;
00332 }
00333 else
00334 {
00335 if (smallshrink==0)
00336 step/=100.0;
00337 else if(smallshrink==1)
00338 step/=10.0;
00339 else if(smallshrink==2)
00340 step/=5;
00341 else if(smallshrink==3)
00342 step/=2;
00343 smallshrink=0;
00344 }
00345 }
00346 }
00347
00348 ii++;
00349
00350 if (scs.dirty==1)
00351 {
00352 scs.dirty=0;
00353 step=get_newton_raphson_info_banded(pfmin);
00354
00355 #ifdef DIAG
00356 int print_hessian=0;
00357 if (print_hessian)
00358 {
00359 ofstream ofs("hh1");
00360 ofs << setw(12) << setscientific() << setprecision(3) << endl;
00361 }
00362 #endif
00363
00364 if (quadratic_prior::get_num_quadratic_prior()>0)
00365 {
00366 quadratic_prior::get_cHessian_contribution(Hess,xsize);
00367 quadratic_prior::get_cgradient_contribution(grad,xsize);
00368 }
00369 if (ii>=num_nr_iters || maxg < 1.e-13 )
00370 {
00371 step=scs.solve(*bHess,g1);
00372 }
00373
00374 }
00375
00376 for (int i=1;i<=usize;i++)
00377 {
00378 y(i+xsize)=uhat(i);
00379 }
00380
00381 if (scs.dirty==0)
00382 {
00383 if (ii>=num_nr_iters || maxg < 1.e-13 )
00384 {
00385 break;
00386 }
00387 }
00388 else
00389 {
00390 scs.dirty=0;
00391 scs.hadbad=0;
00392 if (ii>100)
00393 {
00394 cerr << "Can't get positive definite Hessian in inner optimization"
00395 << endl;
00396 break;
00397 }
00398 }
00399 }
00400 }