ADMB Documentation  -a65f1c97
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
output_checks.cpp
Go to the documentation of this file.
1 
2 #include "admodel.h"
3 #include<ctime>
4 
6 
50  // Read in the number of steps and optional tolerance
51  int N_hess_steps=5;
52  int _N_hess_steps;
53  int on, nopt;
54  if ( (on=option_match(ad_comm::argc,ad_comm::argv,"-hess_step",nopt))>-1) {
55  if (!nopt){
56  //cout << "Number of hess_steps not specified, using default of 1" << endl;
57  } else {
58  istringstream ist(ad_comm::argv[on+1]);
59  ist >> _N_hess_steps;
60  if (_N_hess_steps<=0) {
61  cerr << "Error: hess_step tolerance must be positive";
62  ad_exit(1);
63  } else {
64  N_hess_steps=_N_hess_steps;
65  }
66  }
67  }
68  double eps=1e-12;
69  double _eps;
70  if ( (on=option_match(ad_comm::argc,ad_comm::argv,"-hess_step_tol",nopt))>-1) {
71  if (!nopt){
72  cout << "No tolerance given, using default of 1e-12" << endl;
73  } else {
74  istringstream ist(ad_comm::argv[on+1]);
75  ist >> _eps;
76  if (_eps<=0) {
77  cerr << "Error: hess_step tolerance must be positive";
78  ad_exit(1);
79  } else {
80  eps=_eps;
81  }
82  }
83  }
84  cout << endl << "Experimental feature to take up to " << N_hess_steps;
85  cout << " Newton step(s) using the inverse Hessian" << endl << endl;
86 
88  int nvar=initial_params::nvarcalc(); // get the number of active parameters
89  int aiopt,biopt;
92  if(biopt==-1 && aiopt==-1){
93  std::string m=get_filename((char*)ad_comm::adprogram_name);
94  cout << "Warning: Parameter inputs via '-ainp' and '-binp' were not detected." << endl;
95  cout << " It is recommended to add option '-binp " << m << ".bar' when using -hess_step." << endl;
96  cout << " Otherwise inactive parameters (and thus gradients) may not initialize correctly." << endl << endl;
97  }
98 
99  // Let x'=x-inv(Hessian)*gradient, where x is MLE in
100  // unbounded space and it's corresponding gradient and
101  // Hessian. Need to calculate x' then push through
102  // model and calculate SD report stuff
103  independent_variables mle(1,nvar); // original bounded MLE
104  independent_variables mle2(1,nvar); // updated bounded MLE
105  independent_variables x(1,nvar); // original unbounded MLE
106  independent_variables x2(1,nvar); // updated unbounded MLE
107  dvector gr0(1,nvar); // original gradients
108  dvector gr(1,nvar); //
109  dvector gr2(1,nvar); // updated gradients
110  dvariable nll,nll2; // minimal values
111  //double maxgrad;
112  double maxgrad0, mingrad0, maxgrad2, mingrad2;
113  read_mle_hmc(nvar, mle); // takes MLE from admodel.hes file
114 
115  // Push the original bounded MLE through the model
117  gradient_structure::set_YES_DERIVATIVES(); // don't know what this does
118  // This copies the unbounded parameters into x
120  dvar_vector vx=dvar_vector(x);
123  userfunction();
124  gradcalc(nvar,gr0); // initial unbounded gradient
125  maxgrad0=max(fabs(gr0));
126  mingrad0=min(fabs(gr0));
128  adstring_array pars(1,nvar);
129  pars = get_param_names();
130 
131  int maxpar=1;
132  dvariable grMax=fabs(gr0[1]);
133  for (int i = 1; i<=nvar; i++){
134  if (fabs(gr0[i]) > grMax){
135  grMax = fabs(gr0[i]);
136  maxpar=i;
137  }
138  }
139 
140  if(maxgrad0<eps) {
141  cout << "Initial max gradient already below threshold of " << eps << " so quitting now" << endl;
142  return;
143  }
144 
145  cout << "Hess step 0: Max gradient=" << maxgrad0 << " (" << pars[maxpar] << ") and min gradient= " << mingrad0 << endl;
146  // for(int i=1; i<=5; i++) {cout << "i=" << i << " varsptr=" << 1 << " mle=" << mle(i) << " gradient=" << gr0(i) << endl;}
147  dmatrix S(1,nvar,1,nvar); // covar (inverse Hess) in unbounded space
148  dvector scale(1,nvar); // dummy var
149  int hbf; // dummy var
150 
151  // Initial for first iteration
152  gr=gr0; //maxgrad=maxgrad0;
153  int Nstep=0;
154  for(int ii=1; ii<=N_hess_steps; ii++){
155  Nstep++;
156  // Get the covar matrix from file, assuming last run was good
157  read_covariance_matrix(S,nvar, hbf, scale);
158  x2=x-S*gr; // the updated MLE in unbounded space
159  // Push the new unbounded MLE through the model
160  dvar_vector vx2=dvar_vector(x2);
163  userfunction();
165  // Updated quantities after taking step
166  gradcalc(nvar,gr2);
167  maxgrad2=max(fabs(gr2));
168  mingrad2=min(fabs(gr2));
169  // stupid way to do which.max()
170  maxpar=1; grMax=fabs(gr2[1]);
171  for (int i = 1; i<=nvar; i++){
172  if (fabs(gr2[i]) > grMax){
173  grMax = fabs(gr2[i]);
174  maxpar=i;
175  }
176  }
177  if(grMax!=maxgrad2) cerr << "Warning: which parameter has largest gradient may be unreliable" << endl;
178 
180  // Check whether to break out of loop early
181  if(maxgrad2 < eps){
182  cout << "Hess step " << ii << ": Max gradient="<< maxgrad2 << " (" << pars[maxpar] <<
183  ") is below threshold of " << eps << " so exiting early" << endl;
184  break;
185  }
186  // Was successful but not good enough to break early
187  cout << "Hess step " << ii << ": Max gradient=" << maxgrad2 << " (" << pars[maxpar] <<
188  ") and min gradient= " << mingrad2 << endl;
189  x=x2; gr=gr2; //maxgrad=maxgrad2;
190  // If not the last step then want to skip the sd_calcs
191  // which are slow so manually update admodel.cov whereas
192  // below computations1() runs everything so do that if last
193  // step
194  if(ii!=N_hess_steps){
195  int oldoutput = function_minimizer::output_flag;
197  cout << " Updating Hessian for next step (output suppressed)...";
198  hess_routine(); // Calculate new Hessian
199  depvars_routine(); // calculate derivatives of sdreport variables
200  hess_inv(); // Invert Hess and write to admodel.cov
202  cout << "done" << endl;
203  }
204  } // end loop over hess_steps
205 
206  if(maxgrad2>maxgrad0){
207  // worse gradient
208  cerr << "Experimental feature -hess_step resulted in worse gradients." << endl <<
209  "Consider reoptimizing model to reset files. This suggests that the" << endl <<
210  "the negative log-likelihood is not quadratic at the mode, or that the" << endl <<
211  "Hessian does not approximate it well. In short, it suggests the model is" << endl <<
212  "not converged. Check model structure and other output files to investigate" << endl <<
213  "potential causes and solutions." << endl;
214  ad_exit(1);
215  } else {
216  // Finished successully so run the opitmizer without
217  // taking any steps to produce updated output files
218  // with this new MLE value.
220  cout << endl << "Redoing uncertainty calculations and updating files (output suppressed)...";
221  int oldoutput = function_minimizer::output_flag;
225  cout << " done" << endl;
226  cout << endl << "The " << Nstep << " Hessian step(s) reduced maxgrad from " <<
227  maxgrad0 << " to " << maxgrad2 << " and NLL by " << nll-nll2 << "." << endl <<
228  "All output files should be updated, but confirm as this is experimental still." << endl <<
229  "The fact this was successful gives strong evidence of convergence to a mode" << endl <<
230  "with quadratic log-likelihood surface." << endl;
231  }
232 }
233 
234 static int debug = 0;//flag to print debugging info
235 
240  //define and allocate adstring array
241  int nvar = initial_params::nvarcalc(); // get the number of active parameters
242  if (debug) cout<<"--num initial params = "<< initial_params::num_initial_params <<endl;
243  if (debug) cout<<"--num active params = "<<nvar<<endl;
244  adstring_array par_names;
245  if (nvar>0){
246  par_names.allocate(1,nvar);
247 
248  //loop over parameters and vectors and create names
249  int kk = 0;
250  for (int i = 0; i < initial_params::num_initial_params; ++i) {
253  int jmax = varptr->size_count();
254  for (int j = 1; j <= jmax; ++j) {
255  kk++;
256  par_names[kk] = varptr->label();
257  if (jmax > 1) par_names[kk] += "["+str(j)+"]";//might have to do something similar to alternative above if this doesn't work
258  }//--j loop
259  }//--if
260  }//--i loop
261  if (nvar!=kk) cerr<<"Error in initial_params::get_param_names: number of parameters does not match"<<endl;
262  } else {
263  if (debug) cout<<"--initial_params::get_param_names(): Model appears to be autodiff only."<<endl;
264  par_names.allocate();
265  }
266  return(par_names);
267 }
268 
270 {
271  constexpr const std::type_info& typeid_param_init_bounded_number = typeid(param_init_bounded_number);
272  constexpr const std::type_info& typeid_param_init_bounded_vector = typeid(param_init_bounded_vector);
273  constexpr const std::type_info& typeid_param_init_bounded_dev_vector = typeid(param_init_bounded_dev_vector);
274  constexpr const std::type_info& typeid_param_init_bounded_matrix = typeid(param_init_bounded_matrix);
275 
276  const std::type_info& id = typeid(*p);
277  if (id == typeid_param_init_bounded_number
278  || id == typeid_param_init_bounded_vector
279  || id == typeid_param_init_bounded_dev_vector
280  || id == typeid_param_init_bounded_matrix)
281  {
282  return true;
283  }
284  //cout << id.name() << endl;
285 
286  return false;
287 }
293 void check_for_params_on_bounds(ostream& os){
294  if (debug) os<<std::endl<<"Starting initial_params::check_parameters_on_bounds"<<std::endl;
295  int nvar = initial_params::nvarcalc(); // get the number of active parameters
296  if (debug) os<<"--num initial params = "<< initial_params::num_initial_params <<endl;
297  if (debug) os<<"--num active params = "<<nvar<<endl;
298  int counter=0;
299  if (nvar>0){
300  //loop over parameters and vectors and create names
301  //int kk = 0;
302  for (int i = 0; i < initial_params::num_initial_params; ++i) {
304  adstring par_name_base = varptr->label();
306  if (has_bounds(varptr))
307  {
308  if (debug) os<<"----"<<par_name_base<<" is active, bounded, and will be checked."<<endl;
309  int jmax = varptr->size_count();
310  if (debug) os<<" jmax = "<<jmax<<endl;
311  if (dynamic_cast<param_init_bounded_number*>(varptr) != nullptr){
312  if (debug) os<<" "<<par_name_base<<" is a param_init_bounded_number."<<endl;
313  param_init_bounded_number* p = dynamic_cast<param_init_bounded_number*>(varptr);
314  double minb = p->get_minb();
315  double maxb = p->get_maxb();
316  double valp = ::value(*p);
317  adstring par_name = par_name_base;
318  if (debug) os<<" "<<par_name<<": "<<minb<<" < "<<valp<<" < "<<maxb<<"?"<<endl;
319  if ((valp-minb)/(maxb-minb)<0.001) {
320  if(counter==0){os << "Warning: the following parameters had issues" << endl; counter++;}
321  os<<" "<<par_name<<" is within 0.1\% of lower bound: "<<minb<<" < "<<valp<<" < "<<maxb<<endl;
322  } else if ((valp-minb)/(maxb-minb)<0.01) {
323  if(counter==0){os << "Warning: the following parameters had issues" << endl; counter++;}
324  os<<" "<<par_name<<" is within 1% of lower bound: "<<minb<<" < "<<valp<<" < "<<maxb<<endl;
325  }
326  if ((maxb-valp)/(maxb-minb)<0.001) {
327  if(counter==0){os << "Warning: the following parameters had issues" << endl; counter++;}
328  os<<" "<<par_name<<" is within 0.1\% of upper bound: "<<minb<<" < "<<valp<<" < "<<maxb<<endl;
329  } else if ((maxb-valp)/(maxb-minb)<0.01) {
330  if(counter==0){os << "Warning: the following parameters had issues" << endl; counter++;}
331  os<<" "<<par_name<<" is within 1\% of upper bound: "<<minb<<" < "<<valp<<" < "<<maxb<<endl;
332  }
333  } else if (dynamic_cast<param_init_bounded_dev_vector*>(varptr) != nullptr) {
334  if (debug) os<<" "<<par_name_base<<" is a param_init_bounded_dev_vector with "<<jmax<<" elements."<<endl;
335  param_init_bounded_vector* p = dynamic_cast<param_init_bounded_vector*>(varptr);//note: can cast to _vector here
336  double minb = p->get_minb();
337  double maxb = p->get_maxb();
338  for (int j=p->indexmin();j<=p->indexmax();j++){
339  double valp = ::value(p->elem(j));
340  adstring par_name = par_name_base+"["+str(j)+"]";
341  if (debug) os<<" "<<par_name<<": "<<minb<<" < "<<valp<<" < "<<maxb<<"?"<<endl;
342  if ((valp-minb)/(maxb-minb)<0.001) {
343  if(counter==0){os << "Warning: the following parameters had issues" << endl; counter++;}
344  os<<" "<<par_name<<" is within 0.1\% of lower bound: "<<minb<<" < "<<valp<<" < "<<maxb<<endl;
345  } else if ((valp-minb)/(maxb-minb)<0.01) {
346  if(counter==0){os << "Warning: the following parameters had issues" << endl; counter++;}
347  os<<" "<<par_name<<" is within 1% of lower bound: "<<minb<<" < "<<valp<<" < "<<maxb<<endl;
348  }
349  if ((maxb-valp)/(maxb-minb)<0.001) {
350  if(counter==0){os << "Warning: the following parameters had issues" << endl; counter++;}
351  os<<" "<<par_name<<" is within 0.1\% of upper bound: "<<minb<<" < "<<valp<<" < "<<maxb<<endl;
352  } else if ((maxb-valp)/(maxb-minb)<0.01) {
353  if(counter==0){os << "Warning: the following parameters had issues" << endl; counter++;}
354  os<<" "<<par_name<<" is within 1\% of upper bound: "<<minb<<" < "<<valp<<" < "<<maxb<<endl;
355  }
356  }//-j
357  } else if (dynamic_cast<param_init_bounded_vector*>(varptr) != nullptr) {
358  if (debug) os<<" "<<par_name_base<<" is a param_init_bounded_vector with "<<jmax<<" elements."<<endl;
359  param_init_bounded_vector* p = dynamic_cast<param_init_bounded_vector*>(varptr);
360  double minb = p->get_minb();
361  double maxb = p->get_maxb();
362  for (int j=p->indexmin();j<=p->indexmax();j++){
363  double valp = ::value(p->elem(j));
364  adstring par_name = par_name_base+"["+str(j)+"]";
365  if (debug) os<<" "<<par_name<<": "<<minb<<" < "<<valp<<" < "<<maxb<<"?"<<endl;
366  if ((valp-minb)/(maxb-minb)<0.001) {
367  if(counter==0){os << "Warning: the following parameters had issues" << endl; counter++;}
368  os<<" "<<par_name<<" is within 0.1\% of lower bound: "<<minb<<" < "<<valp<<" < "<<maxb<<endl;
369  } else if ((valp-minb)/(maxb-minb)<0.01) {
370  if(counter==0){os << "Warning: the following parameters had issues" << endl; counter++;}
371  os<<" "<<par_name<<" is within 1% of lower bound: "<<minb<<" < "<<valp<<" < "<<maxb<<endl;
372  }
373  if ((maxb-valp)/(maxb-minb)<0.001) {
374  if(counter==0){os << "Warning: the following parameters had issues" << endl; counter++;}
375  os<<" "<<par_name<<" is within 0.1\% of upper bound: "<<minb<<" < "<<valp<<" < "<<maxb<<endl;
376  } else if ((maxb-valp)/(maxb-minb)<0.01) {
377  if(counter==0){os << "Warning: the following parameters had issues" << endl; counter++;}
378  os<<" "<<par_name<<" is within 1\% of upper bound: "<<minb<<" < "<<valp<<" < "<<maxb<<endl;
379  }
380  }//-j
381  } else if (dynamic_cast<param_init_bounded_matrix*>(varptr)!=nullptr) {
382  param_init_bounded_matrix* p = dynamic_cast<param_init_bounded_matrix*>(varptr);
383  if (debug) os<<" "<<par_name_base<<" is a param_init_bounded_matrix with "<<jmax<<" elements."<<endl;
384  double minb = p->get_minb();
385  double maxb = p->get_maxb();
386  for (int j=p->indexmin();j<=p->indexmax();j++){
387  dvar_vector v = p->elem(j);
388  for (int k=v.indexmin();k<=v.index_max;k++){
389  adstring par_name = par_name_base+"["+str(j)+"]"+"["+str(k)+"]";
390  double valp = ::value(v[k]);
391  if (debug) os<<" "<<par_name<<": "<<minb<<" < "<<valp<<" < "<<maxb<<"?"<<endl;
392  if ((valp-minb)/(maxb-minb)<0.001) {
393  if(counter==0){os << "Warning: the following parameters had issues" << endl; counter++;}
394  os<<" "<<par_name<<" is within 0.1\% of lower bound: "<<minb<<" < "<<valp<<" < "<<maxb<<endl;
395  } else if ((valp-minb)/(maxb-minb)<0.01) {
396  if(counter==0){os << "Warning: the following parameters had issues" << endl; counter++;}
397  os<<" "<<par_name<<" is within 1% of lower bound: "<<minb<<" < "<<valp<<" < "<<maxb<<endl;
398  }
399  if ((maxb-valp)/(maxb-minb)<0.001) {
400  if(counter==0){os << "Warning: the following parameters had issues" << endl; counter++;}
401  os<<" "<<par_name<<" is within 0.1\% of upper bound: "<<minb<<" < "<<valp<<" < "<<maxb<<endl;
402  } else if ((maxb-valp)/(maxb-minb)<0.01) {
403  if(counter==0){os << "Warning: the following parameters had issues" << endl; counter++;}
404  os<<" "<<par_name<<" is within 1\% of upper bound: "<<minb<<" < "<<valp<<" < "<<maxb<<endl;
405  }
406  }//-k
407  }//-j
408  }
409  } else {
410  if (debug) os<<"----"<<par_name_base<<" is active but not bounded and will not be checked."<<endl;
411  }
412  } else {
413  if (debug) os<<"--"<<par_name_base<<" is inactive and will not be checked for bounds."<<endl;
414  }
415  }//--i loop
416  } else {
417  if (debug) os<<"--Model appears to be autodiff only: no bounds checking performed."<<endl;
418  }
419  if (debug) os<<"Finished initial_params::check_parameters_on_bounds"<<endl;
420  if (counter > 0) os << endl;
421 }
bool hess_inv()
Symmetrize and invert the hessian.
Definition: mod_hess.cpp:574
void computations1(int argc, char *argv[])
Definition: modspmin.cpp:138
static void restore_all_values(const dvector &x, const int &ii)
Definition: model3.cpp:105
dvar_vector & elem(int i)
Definition: fvar.hpp:2507
virtual unsigned int size_count() const =0
adstring_array get_param_names()
Get names of active parameters.
int withinbound(int lb, int n, int ub)
Definition: model.cpp:45
void read_mle_hmc(int nvar, dvector &mle)
#define x
Vector of double precision numbers.
Definition: dvector.h:50
double get_maxb() const
Returns maximum bounds value for param_init_bounded_vector.
Definition: model50.cpp:36
static char ** argv
Definition: fvar.hpp:8866
Description not yet available.
Definition: admodel.h:1409
df1_two_variable fabs(const df1_two_variable &x)
Definition: df12fun.cpp:891
exitptr ad_exit
Definition: gradstrc.cpp:53
prevariable elem(int i)
Definition: fvar.hpp:2221
static dvariable reset(const dvar_vector &x)
Definition: model.cpp:345
double get_maxb() const
Returns maximum bounds value for param_init_bounded_matrix.
Definition: model50.cpp:52
ADMB variable vector.
Definition: fvar.hpp:2172
virtual const char * label()=0
Description not yet available.
Definition: admodel.h:814
static adstring adprogram_name
Definition: fvar.hpp:8860
double get_maxb() const
Returns maximum bounds value for param_init_bounded_number.
Definition: model50.cpp:20
void gradcalc(int nvar, const dvector &g)
Definition: sgradclc.cpp:77
static int debug
static int nvarcalc()
Definition: model.cpp:152
Description not yet available.
Definition: admodel.h:1228
Description not yet available.
Definition: admodel.h:1058
void allocate(int min, int max)
Allocate vector of adstring with range [min, max].
Definition: string5.cpp:80
prnstream & endl(prnstream &)
Description not yet available.
Definition: fvar.hpp:1937
static int current_phase
Definition: admodel.h:842
static int max_number_phases
Definition: admodel.h:841
#define min(a, b)
Definition: cbivnorm.cpp:188
static int argc
Definition: fvar.hpp:8863
static objective_function_value * pobjfun
Definition: admodel.h:2394
Description not yet available.
static void xinit(const dvector &x)
Definition: model.cpp:226
Description not yet available.
Definition: fvar.hpp:2819
void read_covariance_matrix(const dmatrix &S, int nvar, int &hbf, dvector &sscale)
Definition: xxmcmc.cpp:1320
static int num_initial_params
Definition: admodel.h:836
static void copy_all_values(const dvector &x, const int &ii)
Definition: model3.cpp:9
int option_match(int argc, char *argv[], const char *string)
Checks if the program has been invoked with a particular command line argument (&quot;string&quot;).
Definition: optmatch.cpp:25
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
int indexmin() const
Definition: fvar.hpp:2287
int indexmax(void) const
Definition: fvar.hpp:2572
Description not yet available.
Definition: admodel.h:1135
bool has_bounds(initial_params *p)
void hess_step()
hess_step is used for HMC. See details in function_minimizer::hess_step.
double eps
Definition: ftweak.cpp:13
int phase_start
Definition: admodel.h:848
static void set_YES_DERIVATIVES(void)
Enable accumulation of derivative information.
Definition: gradstrc.cpp:650
static int output_flag
Definition: admodel.h:1972
dvector value(const df1_one_vector &v)
Definition: df11fun.cpp:69
virtual void userfunction(void)=0
void check_for_params_on_bounds(ostream &os)
check for active parameters near bounds
std::string get_filename(const char *f)
#define max(a, b)
Definition: cbivnorm.cpp:189
void depvars_routine(void)
Calculate the derivatives of dependent variables with respect to the independent variables.
Definition: mod_hess.cpp:488
int indexmin(void) const
Definition: fvar.hpp:2568
int indexmax() const
Definition: fvar.hpp:2292
Fundamental data type for reverse mode automatic differentiation.
Definition: fvar.hpp:1518
static adlist_ptr varsptr
Definition: admodel.h:838
void hess_routine(void)
Definition: mod_hess.cpp:21
int index_max
Definition: fvar.hpp:2177