14 using namespace Eigen;
18 NewtonMinimizerGradHessian::NewtonMinimizerGradHessian()
24 NewtonMinimizerGradHessian::~NewtonMinimizerGradHessian()
34 fixparameter.assign(func->
nPars(), 0);
38 void NewtonMinimizerGradHessian::fixParameter(
unsigned int par)
40 if(par < fixparameter.size())
42 fixparameter[par] = 1;
47 void NewtonMinimizerGradHessian::unfixParameter(
unsigned int par)
49 if(par < fixparameter.size())
51 fixparameter[par] = 0;
56 bool NewtonMinimizerGradHessian::zoom(
const double& wolfe1,
const double& wolfe2,
double& lo,
double& hi, VectorXd& try_grad, VectorXd& direction,
double& grad0_dir,
double& val0,
double& val_lo, VectorXd& init_params, VectorXd& try_params,
unsigned int max_iter,
double& result)
59 double alpha = tryval;
60 double temp1 = tryval;
61 double temp2 = tryval;
62 double temp3 = tryval;
65 unsigned int counter = 1;
70 try_params = direction;
72 try_params += init_params;
73 bounds =
function->calcValGrad(try_params, tryval, try_grad);
74 for(
unsigned int i=0;i<fixparameter.size();++i)
76 if(fixparameter[i] != 0)
85 if( ( tryval > temp1 ) || ( tryval >= val_lo ) || (bounds ==
false) )
88 if( (fabs((tryval - val_lo)/(tryval)) < 1.0e-4) ){result =
alpha;
return true;}
93 temp1 = try_grad.dot(direction);
94 temp2 = -wolfe2*grad0_dir;
97 if( temp3 <= fabs(temp2) )
112 if(counter > max_iter){
return false;}
117 bool NewtonMinimizerGradHessian::lineSearch(
double&
alpha,
const double& wolfe1,
const double& wolfe2, VectorXd& try_grad, VectorXd& direction,
double& grad0_dir,
double& val0, VectorXd& init_params, VectorXd& try_params,
const double& ,
const double& ,
unsigned int max_iter,
double& result)
119 double tryval = val0;
120 double prev_val = tryval;
121 double prev_alpha = tryval;
124 double temp1 = tryval;
125 double temp2 = tryval;
126 double temp3 = tryval;
133 try_params = direction;
135 try_params += init_params;
137 bounds =
function->calcValGrad(try_params, tryval, try_grad);
138 for(
unsigned int j=0;j<fixparameter.size();++j)
140 if(fixparameter[j] != 0)
150 try_params = direction;
152 try_params += init_params;
154 bounds =
function->calcValGrad(try_params, tryval, try_grad);
155 for(
unsigned int j=0;j<fixparameter.size();++j)
157 if(fixparameter[j] != 0)
170 if(i>max_iter){
return false;}
176 alpha = 0.5*(prev_alpha +
alpha);
178 if(i > max_iter){
return false;}
182 temp1 = wolfe1*
alpha;
185 if( ( tryval > temp1 ) || ( ( tryval > prev_val ) && (i>1) ))
189 return zoom(wolfe1, wolfe2, lo, hi, try_grad, direction, grad0_dir, val0, prev_val, init_params, try_params, max_iter, result);
191 temp1 = try_grad.dot(direction);
192 temp2 = -wolfe2*grad0_dir;
195 if( temp3 <= fabs(temp2) )
204 return zoom(wolfe1, wolfe2, lo, hi, try_grad, direction, grad0_dir, val0, tryval, init_params, try_params, max_iter, result);
210 if(i > max_iter){
return false;}
215 bool NewtonMinimizerGradHessian::findSaddlePoint(
const VectorXd& start_point, VectorXd& min_point,
double tol,
unsigned int max_iter,
double abs_tol)
219 if(!
function){
throw (
char*)(
"minimize called but function has not been set");}
223 cout<<
"Exception from NewtonMinimizerGradHessian: "<<str<<endl;
228 unsigned int npars =
function->nPars();
232 if(!(npars>0)){
throw (
char*)(
"function to be minimized has zero dimensions");}
233 if(start_point.rows()!=(int)npars){
throw (
char*)(
"input to minimizer not of dimension required by function to be minimized");}
237 cout<<
"Exception from NewtonMinimizerGradHessian: "<<str<<endl;
246 VectorXd working_points[2];
247 working_points[0] = VectorXd::Zero(npars);
248 working_points[1] = VectorXd::Zero(npars);
250 VectorXd* current_point = &(working_points[0]);
251 VectorXd* try_point = &(working_points[1]);
253 (*current_point) = start_point;
256 double prev_value=0.;
260 double scale_temp = 1.;
261 double grad0_dir = 0.;
263 bool good_value =
true;
266 unsigned int search_iter = 64;
269 grad[0] = VectorXd::Zero(npars);
270 grad[1] = VectorXd::Zero(npars);
271 VectorXd* current_grad = &(grad[0]);
272 VectorXd* try_grad = &(grad[1]);
274 VectorXd newgrad = VectorXd::Zero(npars);
276 MatrixXd hessian = MatrixXd::Zero(npars, npars);
278 VectorXd move = VectorXd::Zero(npars);
279 VectorXd unit_move = VectorXd::Zero(npars);
283 function = &gradsquared;
287 move = -hessian.fullPivLu().solve(*current_grad);
288 gradsquared.
calcValGrad((*current_point), value, newgrad);
290 for(
unsigned int i=0;i<npars;++i){
if(!(move(i) == move(i))){good_value=
false;
break;}}
291 if(good_value ==
false){move = -newgrad;}
292 dir_der = newgrad.dot(move);
293 if(dir_der>0.){move = -move;}
295 grad0_dir = newgrad.dot(move);
298 bounds = lineSearch(scale_temp, c1, c2, (*try_grad), move, grad0_dir, value, (*current_point), (*try_point), tol, abs_tol, search_iter, scale);
299 if(bounds ==
false){min_point = start_point;
function=orig_func;
return false;}
301 (*try_point) = ((*current_point) + move);
303 gradsquared.
calcValGrad((*try_point), prev_value, newgrad);
304 swap(current_point, try_point);
305 swap(current_grad, try_grad);
306 swap(value, prev_value);
308 unsigned long int count = 1;
309 bool converged=
false;
310 while(converged==
false)
312 if((fabs((prev_value - value)/prev_value)<tol || fabs(prev_value - value)<abs_tol)){converged=
true;
break;}
315 move = -hessian.fullPivLu().solve(*current_grad);
316 gradsquared.
calcValGrad((*current_point), value, newgrad);
319 for(
unsigned int i=0;i<npars;++i){
if(!(move(i) == move(i))){good_value=
false;
break;}}
321 scale_temp = fabs(value/newgrad.dot(move));
322 if(good_value ==
false){move = -newgrad;scale_temp = fabs(value/move.dot(move));}
323 dir_der = newgrad.dot(move);
324 if(dir_der>0.){move = -move;}
326 grad0_dir = newgrad.dot(move);
328 bounds = lineSearch(scale_temp, c1, c2, (*try_grad), move, grad0_dir, value, (*current_point), (*try_point), tol, abs_tol, search_iter, scale);
329 if(bounds ==
false){min_point = (*current_point);
function=orig_func;
return false;}
331 (*try_point) = ((*current_point) + move);
333 gradsquared.
calcValGrad((*try_point), value, newgrad);
334 swap(current_point, try_point);
335 swap(current_grad, try_grad);
337 if(count > max_iter){
break;}
340 min_point = (*current_point);
341 function=orig_func;
return converged;
345 bool NewtonMinimizerGradHessian::minimize(
const VectorXd& start_point, VectorXd& min_point,
double tol,
unsigned int max_iter,
double abs_tol)
349 if(!
function){
throw (
char*)(
"minimize called but function has not been set");}
353 cout<<
"Exception from NewtonMinimizerGradHessian: "<<str<<endl;
358 unsigned int npars =
function->
nPars();
362 if(!(npars>0)){
throw (
char*)(
"function to be minimized has zero dimensions");}
363 if(start_point.rows()!=(int)npars){
throw (
char*)(
"input to minimizer not of dimension required by function to be minimized");}
367 cout<<
"Exception from NewtonMinimizerGradHessian: "<<str<<endl;
378 VectorXd working_points[2];
379 working_points[0] = VectorXd::Zero(npars);
380 working_points[1] = VectorXd::Zero(npars);
382 VectorXd* current_point = &(working_points[0]);
383 VectorXd* try_point = &(working_points[1]);
385 (*current_point) = start_point;
388 double prev_value=0.;
392 double scale_temp = 1.;
393 double grad0_dir = 0.;
395 bool good_value =
true;
398 unsigned int search_iter = 32;
401 grad[0] = VectorXd::Zero(npars);
402 grad[1] = VectorXd::Zero(npars);
403 VectorXd* current_grad = &(grad[0]);
404 VectorXd* try_grad = &(grad[1]);
407 MatrixXd hessian = MatrixXd::Zero(npars, npars);
409 VectorXd move = VectorXd::Zero(npars);
410 VectorXd unit_move = VectorXd::Zero(npars);
413 function->calcValGradHessian((*current_point), value, (*current_grad), hessian);
414 for(
unsigned int i=0;i<fixparameter.size();++i)
416 if(fixparameter[i] != 0)
418 (*current_grad)[i] = 0.;
419 for(
unsigned int j=0;j<npars;++j)
428 move = -hessian.fullPivLu().solve(*current_grad);
430 for(
unsigned int i=0;i<npars;++i){
if(!(move(i) == move(i))){good_value=
false;
break;}}
431 if(good_value ==
false){move = - (*current_grad);}
432 dir_der = (*current_grad).dot(move);
438 function->rescaleMove((*current_point), move);
439 grad0_dir = (*current_grad).dot(move);
442 bounds = lineSearch(scale_temp, c1, c2, (*try_grad), move, grad0_dir, value, (*current_point), (*try_point), tol, abs_tol, search_iter, scale);
443 if(bounds ==
false){min_point = start_point;
return false;}
445 (*try_point) = ((*current_point) + move);
446 function->calcValGradHessian((*try_point), prev_value, (*try_grad), hessian);
447 for(
unsigned int i=0;i<fixparameter.size();++i)
449 if(fixparameter[i] != 0)
452 for(
unsigned int j=0;j<npars;++j)
460 swap(current_point, try_point);
461 swap(current_grad, try_grad);
462 swap(value, prev_value);
464 unsigned long int count = 1;
465 bool converged=
false;
466 while(converged==
false)
468 if((fabs((prev_value - value)/prev_value)<tol || fabs(prev_value - value)<abs_tol)){converged=
true;
break;}
472 move = -hessian.fullPivLu().solve(*current_grad);
474 for(
unsigned int i=0;i<npars;++i){
if(!(move(i) == move(i))){good_value=
false;
break;}}
475 if(good_value ==
false){move = - (*current_grad);}
476 dir_der = (*current_grad).dot(move);
482 function->rescaleMove((*current_point), move);
483 grad0_dir = (*current_grad).dot(move);
487 bounds = lineSearch(scale_temp, c1, c2, (*try_grad), move, grad0_dir, value, (*current_point), (*try_point), tol, abs_tol, search_iter, scale);
488 if(bounds ==
false){min_point = (*current_point);
return false;}
490 (*try_point) = ((*current_point) + move);
491 function->calcValGradHessian((*try_point), value, (*try_grad), hessian);
492 for(
unsigned int i=0;i<fixparameter.size();++i)
494 if(fixparameter[i] != 0)
497 for(
unsigned int j=0;j<npars;++j)
505 swap(current_point, try_point);
506 swap(current_grad, try_grad);
509 if(count > max_iter){
break;}
511 function->computeCovariance(value, hessian);
513 min_point = (*current_point);