ADMB Documentation  -a65f1c97
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
newfmin.cpp
Go to the documentation of this file.
1 
2 /*
3  * $Id$
4  *
5  * Author: Unknown
6  * Copyright (c) 2009-2012 ADMB Foundation
7  *
8  * This file was originally written in FORTRAN II by an unknown author.
9  * In the 1980s, it was ported to C and C++ and extensively modified by
10  * David Fournier.
11  *
12  */
18 #include <fvar.hpp>
19 #include <admodel.h>
20 #if defined(_WIN32)
21  #include <windows.h>
22 #endif
23 #if defined(__BORLANDC__)
24  #include <signal.h>
25 #endif
26 #ifdef __ZTC__
27  #include <conio.h>
28 #endif
29 extern int ctlc_flag;
30 
31 #if defined (__WAT32__) || defined (_MSC_VER)
32  #include <conio.h>
33 #endif
34 #if defined(__CYGWIN__)
35  int kbhit(void)
36  {
37  return 0;
38  }
39 #endif
40 #ifdef __ZTC__
41  #include <iostream.hpp>
42  #include <disp.h>
43  #define endl "\n"
44 #endif
45  #include <signal.h>
46 #ifdef __NDPX__
47  #include <iostream.hxx>
48 #endif
49 
50 #if defined (_MSC_VER)
51  void __cdecl clrscr();
52 #else
53  extern "C" void clrscr();
54  #define getch getchar
55 #endif
56 
57 #include <math.h>
58 #include <stdlib.h>
59 #include <stdio.h>
60 #include <ctype.h>
61 
62 #ifdef _MSC_VER
63 BOOL CtrlHandler(DWORD fdwCtrlType)
64 {
65  if (fdwCtrlType == CTRL_C_EVENT)
66  {
67  //Should exit if CTRL_C_EVENT occurs again.
68  if (ctlc_flag) ad_exit(1);
69 
70  ctlc_flag = 1;
71  ad_printf("\npress q to quit or c to invoke derivative checker: ");
72  return true;
73  }
74  return false;
75 }
76 #else
77 extern "C" void onintr(int k)
78 {
79  signal(SIGINT, exit_handler);
80  ctlc_flag = 1;
81  ad_printf("\npress q to quit or c to invoke derivative checker"
82  " or s to stop optimizing: ");
83 }
84 #endif
85 
87 
88 double dafsqrt( double x );
89 
94  void tracing_message(int _traceflag,const char *s)
95  {
96  if (_traceflag)
97  {
98  ofstream ofs;
99  ofs.open("adtrace",ios::app);
100  ofs << s << endl;
101  ofs.close();
102  }
103  }
104 
109  void tracing_message(int _traceflag,const char *s,int *pn)
110  {
111  if (_traceflag)
112  {
113  ofstream ofs;
114  ofs.open("adtrace",ios::app);
115  ofs << s << " " << *pn << endl;
116  ofs.close();
117  }
118  }
119 
124  void tracing_message(int _traceflag,const char *s,double *pd)
125  {
126  if (_traceflag)
127  {
128  ofstream ofs;
129  ofs.open("adtrace",ios::app);
130  ofs << s << " " << *pd << endl;
131  ofs.close();
132  }
133  }
134 
139  void tracing_message(int _traceflag,const char *s,double d)
140  {
141  if (_traceflag)
142  {
143  ofstream ofs;
144  ofs.open("adtrace",ios::app);
145  ofs << s << " " << d << endl;
146  ofs.close();
147  }
148  }
150 ofstream logstream("fmin.log");
151 
156 void print_values(const double& f, const dvector & x,const dvector& g)
157 {
158  logstream << setprecision(13) << f << endl;
159  logstream << setprecision(13) << x << endl;
160  logstream << setprecision(13) << g << endl;
161 }
162 extern int traceflag;
163 //#pragma warn -sig
164 
165 std::string get_elapsed_time(
166  const std::chrono::time_point<std::chrono::system_clock>& from,
167  const std::chrono::time_point<std::chrono::system_clock>& to);
168 
169 void check_for_params_on_bounds(ostream& os);
171 std::chrono::time_point<std::chrono::system_clock> start_time;
172 
173 adstring get_maxparname(const int index)
174 {
176  adstring_array pars;
177  pars = get_param_names();
178  return pars(index);
179  }
180  else
181  {
182  adstring maxparname = "param[" + str(index) + "]";
183  return maxparname;
184  }
185 }
186 int get_maxpar(const dvector& g)
187 {
188  int min = g.indexmin();
189  int max = g.indexmax();
190 
191  double* pg = g.get_v() + min;
192  int maxpar = min;
193  double gmax = fabs(*pg);
194 
195  ++pg;
196  for (int i = min + 1; i <= max; ++i)
197  {
198  double v = fabs(*pg);
199  if (v > gmax)
200  {
201  gmax = v;
202  maxpar = i;
203  }
204  ++pg;
205  }
206  return maxpar;
207 }
254 void fmm::fmin(const double& _f, const dvector &_x, const dvector& _g)
255 {
256  std::ostream& output_stream = get_output_stream();
257 
258  if (log_values_switch)
259  {
260  print_values(_f,_x,_g);
261  }
262 
263 #if defined(DIAG)
264  adtimer fmintime;
265 #endif
266 
268 
269  /* Remember gradient and function values
270  resulted from previous function evaluation */
271  dvector& g=(dvector&) _g;
272  double& f=(double&) _f;
273 
274  /* Create local vector x as a pointer to the argument vector _x */
276  #ifdef DIAG
277  cout << "On entry to fmin: " << *this << endl;
278  #endif
280 
281 #ifdef _MSC_VER
282  SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, true);
283 #else
284  /* Check the value of control variable ireturn:
285  -1 (exit status)
286  0 (initialization of function minimizer)
287  1 (call1 - x update and convergence check)
288  2 (call2 - line search and Hessian update)
289  >=3 (derivative check)
290  */
291  if (ireturn <= 0 )
292  {
293  signal(SIGINT, &onintr);
294  }
295 #endif
296 
297 #ifdef __ZTC__
298  if (ireturn <= 0 )
299  {
300  if (disp_inited == 0)
301  {
302  disp_open();
303  disp_usebios();
304  }
305  }
306 #endif
308  if (ireturn ==1 && dcheck_flag ==0)
309  {
310  ireturn = 3;
311  }
312  if (ireturn >= 3)
313  {
314  /* Entering derivative check */
315  derch(f, x, g, n, ireturn);
316  return;
317  }
318  if (ireturn == 1) goto call1;
319  if (ireturn == 2) goto call2;
320 
321  /* we are here because ireturn=0
322  Start initializing function minimizer variables */
323  fbest=1.e+100;
325 
326  /* allocate Hessian
327  h - object of class dfsdmat, the memory is allocated
328  only for elements of lower triagonal matrix */
329  if (!h) h.allocate(n);
330 
331  /* initialize w, the dvector of size 4*n:
332  w(1,n) contains gradient vector in the point x_new = x_old + alpha*p_k
333  w(n+1,2n) contains direction of linear search, i.e. transpose(p_k)
334  w(2n+1,4n) are used for Hessian updating terms */
335  w.initialize();
336 
337  /* alpha - the Newton step size */
338  alpha=1.0; /* full Newton step at the beginning */
339  ihflag=0;
340 
341  /* validity check for dimensions and indexing of
342  independent vector and gradient vector
343  Note, this function will work correctly only if
344  indices start at 1 */
345  if (n <= 0)
346  {
347  cerr << "Error -- the number of active parameters"
348  " fmin must be > 0\n";
349  ad_exit(1);
350  }
352  if (x.indexmin() !=1)
353  {
354  cerr << "Error -- minimum valid index"
355  " for independent_variables in fmin must be 1\n"
356  << " it is " << x.indexmin() << "\n";
357  ad_exit(1);
358  }
359  if (x.size() < static_cast<unsigned int>(n))
360  {
361  cerr << "Error -- the size of the independent_variables"
362  " which is " << x.size() << " must be >= " << n << "\n"
363  << " the number of independent variables in fmin\n";
364  ad_exit(1);
365  }
367  if (g.indexmin() !=1)
368  {
369  cerr << "Error -- minimum valid index"
370  " for the gradient vector in fmin must be 1\n"
371  << " it is " << g.indexmin() << "\n";
372  ad_exit(1);
373  }
374  if (g.size() < static_cast<unsigned int>(n))
375  {
376  cerr << "Error -- the size of the gradient vector"
377  " which is " << g.size() << " must be >=\n"
378  << " the number of independent variables in fmin\n";
379  ad_exit(1);
380  }
381  /* end of validity check */
383 
384  /* xx is reserved for the updated values of independent variables,
385  at the moment put the current values */
386  {
387  double* pxi = x.get_v() + 1;
388  double* pxxi = xx.get_v() + 1;
389  for (i=1; i<=n; i++)
390  {
391  *pxxi = *pxi;
392 
393  ++pxi;
394  ++pxxi;
395  }
396  }
397  tracing_message(traceflag,"A10");
398 
399  /* itn - iteration counter */
400  itn=0;
401  /* icc - obsolete calls counter? */
402  icc=0;
403 
404  /* initialize funval vector,
405  it will contain last 10 function values (10-th is the most recent)
406  needed to stop minimization in case if f(1)-f(10)<min_improve */
407  {
408  double* pfunvali = funval.get_v() + 1;
409  for (i=1; i< 11; i++)
410  {
411  *pfunvali = 0.0;
412 
413  ++pfunvali;
414  }
415  }
416  tracing_message(traceflag,"A11");
417  ihang = 0; /* flag, =1 when function minimizer is not making progress */
418  llog=1;
419  np=n+1;
420  n1=n-1;
421  nn=n*np/2;
422  is=n;
423  iu=n;
424  iv=n+n;
425  ib=iv+n;
426  iexit=0; /* exit code */
427  tracing_message(traceflag,"A12");
428 
429  /* Initialize hessian to the unit matrix */
430  h.elem(1,1) = 1;
431  for (i=2; i<=n; i++)
432  {
433  for ( j=1; j<i; j++)
434  {
435  h.elem(i,j)=0;
436  }
437  h.elem(i,i)=1;
438  }
439  tracing_message(traceflag,"A13");
440 
441  /* dmin - minimal element of hessian used to
442  verify its positive definiteness */
443  dmin=h.elem(1,1);
444  for ( i=2; i<=n; i++)
445  {
446  if(h.elem(i,i)<dmin)
447  dmin=h.elem(i,i);
448  }
449  if (dmin <= 0.) /* hessian is not positive definite? */
450  goto label7020; /* exit */
451  if(dfn == 0.)
452  z = 0.0;
453  tracing_message(traceflag,"A14");
454  {
455  double* pxi = x.get_v() + 1;
456  double* pxxi = xx.get_v() + 1;
457  double* pxsavei = xsave.get_v() + 1;
458  for (i=1; i<=n; i++)
459  {
460  *pxsavei = *pxi;
461  *pxi= *pxxi;
462 
463  ++pxi;
464  ++pxxi;
465  ++pxsavei;
466  }
467  }
468  ireturn=1; /* upon next entry will go to call1 */
469  tracing_message(traceflag,"A15");
470  if (h.disk_save())
471  {
472  cout << "starting hessian save" << endl;
473  h.save();
474  cout << "finished hessian save" << endl;
475  }
476  tracing_message(traceflag,"A16");
477  return;
478  /* End of initialization */
479  call1: /* first line search step and x update */
480  tracing_message(traceflag,"A17");
481  if (h.disk_save())
482  {
483  cout << "starting hessian restore" << endl;
484  h.restore();
485  cout << "finished hessian restore" << endl;
486  }
487  tracing_message(traceflag,"A18");
488  {
489  double* pxi = x.get_v() + 1;
490  double* pxsavei = xsave.get_v() + 1;
491  for (i=1; i<=n; i++)
492  {
493  *pxi = *pxsavei;
494  ++pxi;
495  ++pxsavei;
496  }
497  }
498  ireturn=3;
499  tracing_message(traceflag,"A19");
500  {
501  double* pgi = g.get_v() + 1;
502  double* pgbesti = gbest.get_v() + 1;
503  for ( i=1; i<=n; i++)
504  {
505  *pgbesti = *pgi;
506 
507  ++pgi;
508  ++pgbesti;
509  }
510  }
511  tracing_message(traceflag,"A20");
512  funval.elem(10) = f;
513  df=dfn;
514  if(dfn == 0.0)
515  df = f - z;
516  if(dfn < 0.0)
517  df=fabs(df * f);
518  if(df <= 0.0)
519  df=1.;
520 label20: /* check for convergence */
521  ic=0; /* counter for number of calls */
522  iconv = 1; /* convergence flag: 1 - convergence, 2 - not yet */
523  for ( i=1; i<=9; i++)
524  funval.elem(i)= funval.elem(i+1);
525  funval.elem(10) = f;
526  /* check if function value is improving */
527  if ( itn>15 && fabs( funval.elem(1)-funval.elem(10))< min_improve )
528  ihang = 1;
529  gmax = 0;
530  /* satisfy convergence criterion? */
531  {
532  double* pg = g.get_v() + 1;
533  for (i = 1; i <= n; ++i)
534  {
535  double gi = *pg;
536  double fabsgi = fabs(gi);
537  if(fabsgi > crit) iconv = 2;
538  if(fabsgi > fabs(gmax)) gmax = gi;
539  ++pg;
540  }
541  }
542  /* exit if either convergence or no improvement has been achieved
543  during last 10 iterations */
544  if( iconv == 1 || ihang == 1)
545  {
546  ireturn=-1;
547  goto label92;
548  }
549  /* otherwise proceed to the Newton step (label21) */
550  if(iprint == 0)
551  goto label21; /* without printing */
552  if(itn == 0)
553  goto label7000; /* printing Initial statistics first */
554 #if defined(USE_DDOUBLE)
555 #undef double
556  if(fmod(double(itn),double(iprint)) != 0)
557  goto label21;
558 #define double dd_real
559 #else
560  if(fmod(double(itn),double(iprint)) != 0)
561  goto label21;
562 #endif
563  if (llog) goto label7010;
564 #if defined (_MSC_VER) && !defined (__WAT32__)
565  if (!scroll_flag) clrscr();
566 #endif
567 label7003: /* Printing table header */
568  // This is the main console output
570  int maxpar = get_maxpar(g);
571  adstring maxparname = get_maxparname(maxpar);
572  if (itn % iprint == 0)
573  {
574  ad_printf("phase=%2d | nvar=%3d | iter=%3d | nll=%.2e | mag=%.2e | par[%3d]=%s\n",
575  initial_params::current_phase, n, itn, double(f), fabs(double(gmax)), maxpar, (char*)maxparname);
576  }
577  }
578  if (iprint>0)
579  {
580  //ad_printf("%d variables; iteration %ld; function evaluation %ld", n, itn, ifn);
581  output_stream << n << " variables; iteration " << itn << "; function evaluation " << ifn;
582  if (pointer_to_phase)
583  {
584  //ad_printf("; phase %d", *pointer_to_phase);
585  output_stream << "; phase " << *pointer_to_phase;
586  }
587  //ad_printf("\nFunction value %15.7le; maximum gradient component mag %12.4le\n",
588 #if defined(USE_DDOUBLE)
589  #undef double
590  output_stream << "\nFunction value " << double(f) << "; maximum gradient component mag " << double(gmax) << "\n";
591  #define double dd_real
592 #else
593  output_stream << "\nFunction value " << std::scientific << setprecision(7) << f << "; maximum gradient component mag " << setprecision(4) << gmax << "\n";
594 #endif
595  }
596 /*label7002:*/
597  /* Printing Statistics table */
598  if (iprint>0)
599  {
600  fmmdisp(x, g, n, this->scroll_flag,noprintx);
601  }
602 label21 : /* Calculating Newton step */
603  /* found good search direction, increment iteration number */
604  itn=itn+1;
605  {
606  double* pxi = x.get_v() + 1;
607  double* pxxi = xx.get_v() + 1;
608  for (i=1; i<=n; i++)
609  {
610  *pxi = *pxxi;
611  ++pxi;
612  ++pxxi;
613  }
614  w.elem(1)=-g.elem(1);
615  }
616 
617 #if defined(DIAG)
618  cout << __FILE__ << ':' << __LINE__ << ' ' << fmintime.get_elapsed_time_and_reset() << endl;
619 #endif
620 
621  /* solving system of linear equations H_(k+1) * (x_(k+1)-x(k)) = -g_k
622  to get next search direction
623  p_k = (x_(k+1)-x(k)) = - inv(H_(k+1)) * g_k */
624  {
625  double* pgi = g.get_v() + 2;
626  double* pwi = w.get_v() + 2;
627  for (i=2; i<=n; i++)
628  {
629  i1=i-1;
630  z = -(*pgi);
631  double * pd=&(h.elem(i,1));
632  double* pw = w.get_v() + 1;
633  for (j=1; j<=i1; j++)
634  {
635  z -= *pd * *pw;
636  ++pd;
637  ++pw;
638  }
639  *pwi = z;
640 
641  ++pwi;
642  ++pgi;
643  }
644  }
645  w.elem(is+n)=w.elem(n)/h.elem(n,n);
646  {
647  dvector tmp(1,n);
648  tmp.initialize();
649  double* ptmpi = tmp.get_v() + 1;
650  for (i=1; i<=n1; i++)
651  {
652  j=i;
653  double * pd=&(h.elem(n-j+1,n-1));
654  double qd=w.elem(is+np-j);
655  double* pt = tmp.get_v() + 1;
656  for (int ii=1; ii<=n1; ii++)
657  {
658  *pt += *pd * qd;
659 
660  ++pt;
661  --pd;
662  }
663  w.elem(is+n-i)=w.elem(n-i)/h.elem(n-i,n-i) - *ptmpi;
664 
665  ++ptmpi;
666  }
667  }/* w(n+1,2n) now contains search direction
668  with current Hessian approximation */
669  gs=0.0;
670  {
671  double* pgi = g.get_v() + 1;
672  double* pwis = w.get_v() + is + 1;
673  for (i=1; i<=n; i++)
674  {
675  gs += *pwis * *pgi;/* gs = -inv(H_k)*g_k*df(x_k+alpha_k*p_k) */
676 
677  ++pwis;
678  ++pgi;
679  }
680  }
681  iexit=2;
682  if(gs >= 0.0)
683  goto label92; /* exit with error */
684  gso=gs;
685  /* compute new step length 0 < alpha <= 1 */
686  alpha=-2.0*df/gs;
687  if(alpha > 1.0)
688  alpha=1.0;
689  df=f;
690  tot=0.0;
691 label30: /* Taking a step, updating x */
692  iexit=3;
693  if (ialph) { goto label92; } /* exit if step size too small */
694  /* exit if number of function evaluations exceeded maxfn */
695  if( ifn >= maxfn)
696  {
697  maxfn_flag=1;
698  goto label92;
699  }
700  else
701  {
702  maxfn_flag=0;
703  iexit=1;
704  }
705  if(quit_flag) goto label92;
706  {
707  double* pw = w.get_v() + is + 1;
708  double* pxx = xx.get_v() + 1;
709  for (i=1; i<=n; i++)
710  {
711  /* w(n+1,2n) has the next direction to go */
712  z = alpha * *pw;
713  /* new independent vector values */
714  *pxx += z;
715 
716  ++pw;
717  ++pxx;
718  }
719  double* px = x.get_v() + 1;
720  double* pg = g.get_v() + 1;
721  pxx = xx.get_v() + 1;
722  double* pxsave = xsave.get_v() + 1;
723  double* pgsave = gsave.get_v() + 1;
724  for (i=1; i<=n; i++)
725  { /* save previous values and update x return value */
726  *pxsave = *px;
727  *pgsave = *pg;
728  *px = *pxx;
729  fsave = f;
730 
731  ++px;
732  ++pg;
733  ++pxx;
734  ++pxsave;
735  ++pgsave;
736  }
737  }
738  fsave = f;
739  ireturn=2;
740  if (h.disk_save())
741  {
742  cout << "starting hessian save" << endl;
743  h.save();
744  cout << "finished hessian save" << endl;
745  }
746  return; // end of call1
747  call2: /* Line search and Hessian update */
748  if (h.disk_save())
749  {
750  cout << "starting hessian restore" << endl;
751  h.restore();
752  cout << "finished hessian restore" << endl;
753  }
754  /* restore x_k, g(x_k) and g(x_k+alpha*p_k) */
755  {
756  double* px = x.get_v() + 1;
757  double* pw = w.get_v() + 1;
758  double* pg = g.get_v() + 1;
759  double* pgsave = gsave.get_v() + 1;
760  double* pxsave = xsave.get_v() + 1;
761  for (i=1; i<=n; i++)
762  {
763  *px = *pxsave; //x_k
764  *pw = *pg; //g(x_k+alpha*p_k)
765  *pg = *pgsave; //g(x_k)
766 
767  ++px;
768  ++pw;
769  ++pg;
770  ++pgsave;
771  ++pxsave;
772  }
773  }
774  fy = f;
775  f = fsave; /* now fy is a new function value, f is the old one */
776  ireturn=-1;
777  /* remember current best function value, gradient and parameter values */
778  if (fy <= fbest)
779  {
780  fbest=fy;
781  double* px = x.get_v() + 1;
782  double* pw = w.get_v() + 1;
783  double* pxx = xx.get_v() + 1;
784  double* pgbest = gbest.get_v() + 1;
785  for (i=1; i<=n; i++)
786  {
787  *px = *pxx;
788  *pgbest = *pw;
789 
790  ++px;
791  ++pw;
792  ++pgbest;
793  ++pxx;
794  }
795  }
796  /* what to do if CTRL-C keys were pressed */
797  if (use_control_c==1)
798  {
799 #if defined(__BORLANDC__)
800  if ( kbhit() || ctlc_flag|| ifn == dcheck_flag )
801 #elif defined(_MSC_VER)
802  //if ( kbhit() || ifn == dcheck_flag )
803  if ( _kbhit() || ctlc_flag || ifn == dcheck_flag )
804 #else
805  if(ctlc_flag || ifn == dcheck_flag )
806 #endif
807  {
808  int c=0;
809  if (ifn != dcheck_flag)
810  {
811  #if defined(__DJGPP__)
812  c = toupper(getxkey());
813  #else
814  c = toupper(getch());
815  #endif
816  }
817  else
818  c='C';
819  if ( c == 'C')
820  {
821  for (i=1; i<=n; i++)
822  {
823  x.elem(i)=xx.elem(i);
824  }
825  ireturn = 3;
826  derch(f, x , w, n, ireturn);
827  return;
828  }
829  else if(c=='S')
830  {
831  //set convergence criteria to something high to stop now
832  crit=100000.0;
833  return;
834  }
835  else
836  {
837  if ( c == 'Q'|| c == 'N')
838  {
839  quit_flag=c;
840  goto label92;
841  }
842  else
843  {
844  quit_flag=0;
845  }
846  }
847  }
848  }
849  if (quit_flag)
850  {
851  if (quit_flag==1) quit_flag='Q';
852  if (quit_flag==2) quit_flag='N';
853  goto label92;
854  }
855  /* Otherwise, continue */
856  /* Note, icc seems to be unused */
857  icc+=1;
858  if( icc >= 5)
859  icc=0;
860  /* ic - counter of calls without x update */
861  ic++;
862  if( ic >imax)
863  {
864  if (iprint>0)
865  {
866  output_stream << " ic > imax in fminim is answer attained ?\n";
867  fmmdisp(x, g, n, this->scroll_flag,noprintx);
868  }
869  ihflag=1;
870  ihang=1;
871  goto label92;
872  }
873  /* new function value was passed to fmin, will increment ifn */
874  ifn++;
875 
876  gys=0.0;
877 
878  /* gys = transpose(p_k) * df(x_k+alpha_k*p_k) */
879  {
880  double* pwi = w.get_v() + 1;
881  double* pwis = w.get_v() + is + 1;
882  for (i=1; i<= n; i++)
883  {
884  gys += *pwi * *pwis;
885 
886  ++pwi;
887  ++pwis;
888  }
889  }
890 
891  /* bad step; unless modified by the user, fringe default = 0 */
892  if(fy>f+fringe)
893  {
894  goto label40; /* backtrack */
895  }
896  /* Otherwise verify if the search step length satisfies
897  strong Wolfe condition */
898  if(fabs(gys/gso)<=.9)
899  goto label50; /* proceed to Hessian update */
900 /* or slightly modified constant in Wolfe condition for the number of
901  calls > 4 */
902  if(fabs(gys/gso)<=.95 && ic > 4)
903  goto label50; /* proceed to Hessian update */
904  if(gys>0.0) /* not a descent direction */
905  goto label40; /* backtrack */
906  tot+=alpha;
907  z=10.0;
908  if(gs<gys)
909  z=gys/(gs-gys);
910  if(z>10.0)
911  z=10.0;
912  /* increase step length */
913  alpha=alpha*z;
914  if (alpha == 0.)
915  {
916  ialph=1;
917  #ifdef __ZTC__
918  if (ireturn <= 0)
919  {
920  disp_close();
921  }
922  #endif
923  return;
924  }
925  f=fy;
926  gs=gys;
927  goto label30; /* update x with new alpha */
928 label40: /* new step is not acceptable, stepping back and
929  start backtracking along the Newton direction
930  trying a smaller value of alpha */
931  {
932  double* pxxi = xx.get_v() + 1;
933  double* pwis = w.get_v() + is + 1;
934  for (i=1;i<=n;i++)
935  {
936  *pxxi -= alpha * *pwis;
937 
938  ++pwis;
939  ++pxxi;
940  }
941  }
942  if (alpha == 0.)
943  {
944  ialph=1;
945  return;
946  }
947  /* compute new alpha */
948  z=3.0*(f-fy)/alpha+gys+gs;
949  zz=dafsqrt(z*z-gs*gys);
950  z=1.0-(gys+zz-z)/(2.0*zz+gys-gs);
951  if (fabs(fy-1.e+95) < 1.e-66)
952  {
953  alpha*=.001;
954  }
955  else
956  {
957  if (z>10.0)
958  {
959  cout << "large z" << z << endl;
960  z=10.0;
961  }
962  alpha=alpha*z;
963  }
964  if (alpha == 0.)
965  {
966  ialph=1;
967  if (ialph)
968  {
969  ad_printf("\nFunction minimizer: Step size"
970  " too small -- ialph=1");
971  }
972  return;
973  }
974  goto label30; /* update x with new alpha */
975 label50: /* compute Hessian updating terms */
976  alpha+=tot;
977  f=fy;
978  df-=f;
979  dgs=gys-gso;
980  xxlink=1;
981  if(dgs+alpha*gso>0.0)
982  goto label52;
983 
984  {
985  double* pg = g.get_v() + 1;
986  double* pw = w.get_v() + 1;
987  double* pwu = w.get_v() + iu + 1;
988  for (i=1;i<=n;i++)
989  {
990  *pwu = *pw - *pg;
991 
992  ++pg;
993  ++pw;
994  ++pwu;
995  }
996  }
997  /* now w(n+1,2n) = df(x_k+alpha_k*p_k)-df(x_k) */
998  sig=1.0/(alpha*dgs);
999  goto label70;
1000 label52: /* compute Hessian updating terms */
1001  zz=alpha/(dgs-alpha*gso);
1002  z=dgs*zz-1.0;
1003  {
1004  double* pg = g.get_v() + 1;
1005  double* pw = w.get_v() + 1;
1006  double* pwu = w.get_v() + iu + 1;
1007  for (i=1;i<=n;i++)
1008  {
1009  *pwu = z * *pg + *pw;
1010 
1011  ++pg;
1012  ++pw;
1013  ++pwu;
1014  }
1015  }
1016  sig=1.0/(zz*dgs*dgs);
1017  goto label70;
1018 label60: /* compute Hessian updating terms */
1019  xxlink=2;
1020  {
1021 double* pg = g.get_v() + 1;
1022 double* pw = w.get_v() + iu + 1;
1023  for (i=1;i<=n;i++)
1024  {
1025  *pw = *pg;
1026 
1027  ++pg;
1028  ++pw;
1029  }
1030  }
1031  if(dgs+alpha*gso>0.0)
1032  goto label62;
1033  sig=1.0/gso;
1034  goto label70;
1035 label62: /* compute Hessian updating terms */
1036  sig=-zz;
1037  goto label70;
1038 label65: /* save in g the gradient df(x_k+alpha*p_k) */
1039  {
1040  double* pg = g.get_v() + 1;
1041  double* pw = w.get_v() + 1;
1042  for (i=1;i<=n;i++)
1043  {
1044  *pg = *pw;
1045 
1046  ++pg;
1047  ++pw;
1048  }
1049  }
1050  goto label20; //convergence check
1051 label70: // Hessian update
1052  w.elem(iv+1)=w.elem(iu+1);
1053 
1054 #if defined(DIAG)
1055  cout << __FILE__ << ':' << __LINE__ << ' ' << fmintime.get_elapsed_time_and_reset() << endl;
1056 #endif
1057 
1058  {
1059  for (i=2;i<=n;i++)
1060  {
1061  i1=i-1;
1062  z=w.elem(iu+i);
1063  double* ph = &(h.elem(i,1));
1064  double* pw = &(w.elem(iv+1));
1065  for (j=1;j<=i1;j++)
1066  {
1067  z -= *ph * *pw;
1068 
1069  ++ph;
1070  ++pw;
1071  }
1072  w.elem(iv+i)=z;
1073  }
1074  }
1075 
1076 #if defined(DIAG)
1077  cout << __FILE__ << ':' << __LINE__ << ' ' << fmintime.get_elapsed_time_and_reset() << endl;
1078 #endif
1079  {
1080  double* pwiv = w.get_v() + iv + 1;
1081  double* pwib = w.get_v() + ib + 1;
1082  for (i=1;i<=n;i++)
1083  { /* BFGS updating formula */
1084  z = h.elem(i,i) + sig * *pwiv * *pwiv;
1085  if (z <= 0.0)
1086  z=dmin;
1087  if (z < dmin)
1088  dmin=z;
1089 
1090  h.elem(i,i)=z;
1091  *pwib = *pwiv * sig / z;
1092  sig -= *pwib * *pwib * z;
1093 
1094  ++pwiv;
1095  ++pwib;
1096  }
1097  double* qd = w.get_v() + iu + 2;//&(w.elem(iu+j));
1098  for (j=2;j<=n;j++)
1099  {
1100  double* pd=&(h.elem(j,1));
1101  double* rd = w.get_v() + iv + 1;//&(w.elem(iv+1));
1102  double* pwib = w.get_v() + ib + 1;
1103  for (i=1;i<j;i++)
1104  {
1105  *qd-=*pd * *rd;
1106  *pd += *pwib * *qd;
1107 
1108  ++pd;
1109  ++rd;
1110  ++pwib;
1111  }
1112 
1113  ++qd;
1114  }
1115  }
1116  if (xxlink == 1) goto label60;
1117  if (xxlink == 2) goto label65;
1118 /*label90:*/
1119  {
1120  double* pg = g.get_v() + 1;
1121  double* pw = w.get_v() + 1;
1122  for (i=1;i<=n;i++)
1123  {
1124  *pg = *pw;
1125  ++pg;
1126  ++pw;
1127  }
1128  }
1129 label92: /* Exit with error */
1130 if (iprint>0)
1131  {
1132  if (ialph)
1133  {
1134  //ad_printf("\nFunction minimizer: Step size too small -- ialph=1");
1135  output_stream << "\nFunction minimizer: Step size too small -- ialph=1\n";
1136  }
1137  if (ihang == 1)
1138  {
1139  output_stream << "Function minimizer not making progress ... is minimum attained?\n"
1140  << "Minimprove criterion = "
1141 #if defined(USE_DDOUBLE)
1142 #undef double
1143  //ad_printf("Minimprove criterion = %12.4le\n",double(min_improve));
1144  << double(min_improve)
1145 #define double dd_real
1146 #else
1147  //ad_printf("Minimprove criterion = %12.4le\n",min_improve);
1148  << std::scientific << setprecision(4) << min_improve
1149 #endif
1150  << endl;
1151  }
1153  {
1154  // Not sure this really helps the user. It just moves
1155  // on to next phase or finishes optimization and
1156  // those messgaes are more useful
1157  // cout << "Optimizer ended early due to not making progress (ialpha=" <<
1158  // ialph << ", ihang=" << ihang << ")" << endl;//try reoptimizing from .par file" << endl;
1159  }
1160  }
1161 if(iexit == 2)
1162  {
1163  if (iprint>0)
1164  {
1165  ad_printf("*** grad transpose times delta x greater >= 0\n"
1166  " --- convergence critera may be too strict\n");
1167  ireturn=-1;
1168  }
1169  }
1170 #if defined (_MSC_VER) && !defined (__WAT32__)
1171 if (scroll_flag == 0) clrscr();
1172 #endif
1173  if (maxfn_flag == 1)
1174  {
1175  if (iprint>0)
1176  {
1177  output_stream << "Maximum number of function evaluations exceeded" << endl;
1179  {
1180  cout << "Exiting without success due to excessive function evaluations (maxfn="
1181  << maxfn << ") | mag=" << fabs(double(gmax)) << endl;
1182  }
1183  }
1184  }
1185 if (iprint>0)
1186  {
1187  if (quit_flag == 'Q')
1188  ad_printf("User initiated interrupt");
1189  }
1190 // if last iteration of phase print to screen regardless of
1191 // iprint. Note that for RE models it is sometimes set iprint=0
1192 // intermediately so turn that off.
1194  // this logic should print final when no RE are used for any
1195  // iprint, and if RE is used if iprint>0. It will only not
1196  // work when user specifies iprint=0 with a RE model.
1199  // always print info from final iteration.. copied from 7003
1200  // above b/c I don't know how to get the logic write, I
1201  // can't just use goto label7003 or it loops forever.
1202  int maxpar = get_maxpar(g);
1203  adstring maxparname = get_maxparname(maxpar);
1204  if(iprint>0)
1205  ad_printf("phase=%2d | nvar=%3d | iter=%3d | nll=%.2e | mag=%.2e | par[%3d]=%s\n",
1206  initial_params::current_phase, n, itn, double(f), fabs(double(gmax)), maxpar, (char*)maxparname);
1207 
1208  // only print global stuff if in last phase
1210  {
1211  cout << "Optimization completed after "
1212  << get_elapsed_time(start_time, std::chrono::system_clock::now())
1213  << " with final statistics:\n" ;
1214  cout.flush();
1215  ad_printf(" nll=%f | mag=%.5e | par[%3d]=%s\n\n", double(f), fabs(double(gmax)), maxpar, (char*)maxparname);
1216 
1218  check_for_params_on_bounds(std::cout);
1220  }
1221  }
1222  }
1223  }
1224 
1225 // Important to be here b/c it appears other parts of ADMB-RE
1226 // code set iprint=0 then call fmin, so this exits early to
1227 // prevent excess printing.
1228 if(iprint == 0) goto label777;
1229 
1230  output_stream << "\n - final statistics:\n"
1231  << n << " variables; iteration " << itn << "; function evaluation " << ifn << '\n'
1232 #if defined(USE_DDOUBLE)
1233 #undef double
1234  //ad_printf("Function value %12.4le; maximum gradient component mag %12.4le\n", double(f), double(gmax));
1235  //ad_printf("Exit code = %ld; converg criter %12.4le\n",iexit,double(crit));
1236  << "Function value " << double(f) << "; maximum gradient component mag " << double(gmax)
1237  << "Exit code = " << iexit << "; converg criter " << double(crit)
1238 #define double dd_real
1239 #else
1240  << "Function value " << std::scientific << setprecision(4) << f
1241  << "; maximum gradient component mag " << gmax
1242  << "\nExit code = " << iexit << "; converg criter " << crit
1243 #endif
1244  << endl;
1245  fmmdisp(x, g, n, this->scroll_flag,noprintx);
1246 
1247 label777: /* Printing final Hessian approximation */
1248  if (ireturn <= 0)
1249  #ifdef DIAG
1250  ad_printf("Final values of h in fmin:\n");
1251  //cout << h << "\n";
1252  #endif
1253  #ifdef __ZTC__
1254  {
1255  disp_close();
1256  }
1257  #endif
1258  return;
1259 label7000:/* Printing Initial statistics */
1260  if (iprint>0)
1261  {
1262 #if defined (_MSC_VER) && !defined (__WAT32__)
1263  if (!scroll_flag) clrscr();
1264 #endif
1265  output_stream << "\nInitial statistics: " << std::scientific << setprecision(8);
1266  }
1267  goto label7003;
1268 label7010:/* Printing Intermediate statistics */
1269  if (iprint>0)
1270  {
1271 #if defined (_MSC_VER) && !defined (__WAT32__)
1272  if (!scroll_flag) clrscr();
1273 #endif
1274  output_stream << "\nIntermediate statistics: " << std::scientific << setprecision(8);
1275  }
1276  llog=0;
1277  goto label7003;
1278 label7020:/* Exis because Hessian is not positive definite */
1279  if (iprint > 0)
1280  {
1281  ad_printf("*** hessian not positive definite\n");
1282  }
1283 #ifdef __ZTC__
1284  if (ireturn <= 0)
1285  {
1286  disp_close();
1287  }
1288 #endif
1289 }
1295 double dafsqrt(double x)
1296 {
1297  return x > 0 ? sqrt(x) : 0.0;
1298 }
long int llog
Definition: fvar.hpp:3299
dvector funval
Definition: fvar.hpp:3295
long ialph
Definition: fvar.hpp:3190
void save(void)
Save values to file.
Definition: dfsdmat.cpp:316
double dfn
Definition: fvar.hpp:3187
void fmmdisp(const dvector &x, const dvector &g, const int &nvar, int scroll_flag, int noprintx)
Description not yet available.
Definition: fmm_disp.cpp:102
double crit
Definition: fvar.hpp:3184
int iv
Definition: fvar.hpp:3302
void derch(const double &_f, const dvector &_x, const dvector &_gg, int n, const int &_ireturn)
Description not yet available.
Definition: conjprod.cpp:1008
double & elem(int i)
Definition: dvector.h:152
adstring_array get_param_names()
Get names of active parameters.
static ofstream * global_logfile
Definition: fvar.hpp:8858
long int xxlink
Definition: fvar.hpp:3299
int is
Definition: fvar.hpp:3302
int disk_save(void)
Definition: fvar.hpp:3243
#define x
Vector of double precision numbers.
Definition: dvector.h:50
int indexmin() const
Get minimum valid index.
Definition: dvector.h:199
int maxfn_flag
Definition: fvar.hpp:3194
dvector w
Definition: fvar.hpp:3294
long maxfn
Definition: fvar.hpp:3182
int noprintx
Definition: fvar.hpp:3181
double fsave
Definition: fvar.hpp:3304
int j
Definition: fvar.hpp:3302
double gso
Definition: fvar.hpp:3300
void clrscr()
Author: David Fournier Copyright (c) 2008-2012 Regents of the University of California.
Definition: clrscr.cpp:8
double sig
Definition: fvar.hpp:3300
double fringe
Definition: fvar.hpp:3185
df1_two_variable fabs(const df1_two_variable &x)
Definition: df12fun.cpp:891
exitptr ad_exit
Definition: gradstrc.cpp:53
double zz
Definition: fvar.hpp:3300
void fmin(const double &f, const dvector &x, const dvector &g)
Function fmin contains Quasi-Newton function minimizer with inexact line search using Wolfe condition...
Definition: newfmin.cpp:254
int get_maxpar(const dvector &g)
Definition: newfmin.cpp:186
double fy
Definition: fvar.hpp:3300
std::chrono::time_point< std::chrono::system_clock > start_time
Definition: newfmin.cpp:171
double gmax
maximum gradient
Definition: fvar.hpp:3303
double z
Definition: fvar.hpp:3300
adstring get_maxparname(const int index)
Definition: newfmin.cpp:173
int log_values_switch
Definition: newfmin.cpp:149
Description not yet available.
Definition: fvar.hpp:8901
std::string get_elapsed_time(const std::chrono::time_point< std::chrono::system_clock > &from, const std::chrono::time_point< std::chrono::system_clock > &to)
Definition: mod_sd.cpp:41
void exit_handler(int k)
Description not yet available.
Definition: signalh.cpp:20
long imax
Definition: fvar.hpp:3186
double dmin
Definition: fvar.hpp:3297
long int nn
Definition: fvar.hpp:3301
prnstream & endl(prnstream &)
double fbest
Definition: fvar.hpp:3297
Description not yet available.
Definition: fvar.hpp:1937
static int current_phase
Definition: admodel.h:842
d3_array sqrt(const d3_array &arr3)
Author: David Fournier Copyright (c) 2008-2012 Regents of the University of California.
Definition: d3arr2c.cpp:11
long int i1
Definition: fvar.hpp:3299
long ihang
Definition: fvar.hpp:3192
int scroll_flag
Definition: fvar.hpp:3193
static int max_number_phases
Definition: admodel.h:841
double gs
Definition: fvar.hpp:3300
#define min(a, b)
Definition: cbivnorm.cpp:188
dvector gbest
Definition: fvar.hpp:3306
int n
Definition: fvar.hpp:3310
int indexmax() const
Get maximum valid index.
Definition: dvector.h:204
Author: David Fournier Copyright (c) 2008-2012 Regents of the University of California.
double get_elapsed_time_and_reset(void)
Returns elapsed time in milliseconds of timer object and then resets the timer to current time...
Definition: timer.cpp:31
Description not yet available.
long ifn
Definition: fvar.hpp:3188
int iu
Definition: fvar.hpp:3302
dfsdmat h
Definition: fvar.hpp:3293
int * pointer_to_phase
Definition: newfmin.cpp:86
int use_control_c
Definition: fvar.hpp:3199
int quit_flag
Definition: fvar.hpp:3195
void initialize(void)
Initialze all elements of dvector to zero.
Definition: dvect5.cpp:10
static int num_initial_params
Definition: admodel.h:836
void restore(void)
Restore values to file.
Definition: dfsdmat.cpp:367
long int n1
Definition: fvar.hpp:3299
unsigned int size() const
Get number of elements in array.
Definition: dvector.h:209
ofstream logstream("fmin.log")
int dcheck_flag
Definition: fvar.hpp:3198
adstring str(double x, int minwidth=17, int decplaces=-1)
Convert x to adstring with minimum width and total number of decimal places.
Definition: str.cpp:25
std::ostream & get_output_stream()
Definition: adglobl.cpp:45
double gys
Definition: fvar.hpp:3300
int traceflag
Definition: fvar1.cpp:18
int ib
Definition: fvar.hpp:3302
long int icc
Definition: fvar.hpp:3301
dvector xsave
Definition: fvar.hpp:3307
double dafsqrt(double x)
Robust square root.
Definition: newfmin.cpp:1295
long int ic
Definition: fvar.hpp:3299
long ihflag
Definition: fvar.hpp:3191
double dgs
Definition: fvar.hpp:3300
void print_values(const double &f, const dvector &x, const dvector &g)
Description not yet available.
Definition: newfmin.cpp:156
dvector gsave
Definition: fvar.hpp:3308
double alpha
Definition: fvar.hpp:3300
#define getch
Definition: newfmin.cpp:54
double & elem(int i, int j)
Definition: fvar.hpp:3277
dvector xx
Definition: fvar.hpp:3305
double min_improve
Definition: fvar.hpp:3196
double df
Definition: fvar.hpp:3297
static int output_flag
Definition: admodel.h:1972
double tot
Definition: fvar.hpp:3300
long int iconv
Definition: fvar.hpp:3299
void check_for_params_on_bounds(ostream &os)
check for active parameters near bounds
long iprint
Definition: fvar.hpp:3183
#define max(a, b)
Definition: cbivnorm.cpp:189
int onintr(int *k)
void tracing_message(int traceflag, const char *s)
Description not yet available.
Definition: newfmin.cpp:94
int i
Definition: fvar.hpp:3302
long int itn
Definition: fvar.hpp:3301
double *& get_v(void)
Definition: dvector.h:148
int ireturn
Definition: fvar.hpp:3197
long iexit
Definition: fvar.hpp:3189
int np
Definition: fvar.hpp:3302
void allocate(int n)
Description not yet available.
Definition: dfsdmat.cpp:142
int ad_printf(FILE *stream, const char *format, Args...args)
Definition: fvar.hpp:9487
static int random_effects_flag
Definition: admodel.h:1857
int kbhit(void)
Definition: df1b2fun.cpp:15
int ctlc_flag
Definition: gradstrc.cpp:68