bool NMfit::termination_criteria(int iter, realt convergence) { if (F_->get_verbosity() >= 1) F_->ui()->mesg("#" + S(iter_nr_) + " (ev:" + S(evaluations_) + "):" " best:" + S(best->wssr) + " worst:" + S(worst->wssr) + ", " + S(s_worst->wssr) + " [V * |" + S(volume_factor) + "|]"); bool stop = false; if (volume_factor == 1. && iter != 0) { F_->msg ("Simplex got stuck."); stop = true; } volume_factor = 1.; /*DEBUG - BEGIN* string s = "WSSR:"; for (vector<Vertex>::iterator i = vertices.begin(); i!=vertices.end(); ++i) s += " " + S(i->wssr); F_->msg (s); *DEBUG - END*/ //checking stop conditions if (common_termination_criteria(iter)) stop = true; if (is_zero(worst->wssr)) { F_->msg ("All vertices have WSSR < epsilon=" + S(epsilon)); return true; } realt r_diff = 2 * (worst->wssr - best->wssr) / (best->wssr + worst->wssr); if (r_diff < convergence) { F_->msg ("Relative difference between worst and best vertex is only " + S(r_diff) + ". Stop"); stop = true; } return stop; }
void LMfit::autoiter() { wssr_before_ = chi2; realt prev_chi2 = chi2; const SettingsMgr *sm = F_->settings_mgr(); if (F_->get_verbosity() >= 1) { F_->ui()->mesg("\t === Levenberg-Marquardt method ==="); F_->ui()->mesg("Initial values: lambda=" + S(lambda) + " WSSR=" + sm->format_double(chi2)); F_->ui()->mesg("Max. number of iterations: " + max_iterations_); } realt stop_rel = F_->get_settings()->lm_stop_rel_change; realt max_lambda = F_->get_settings()->lm_max_lambda; if (stop_rel > 0 && F_->get_verbosity() >= 1) F_->ui()->mesg("Will stop when relative change of WSSR is " "twice in row below " + S (stop_rel * 100.) + "%"); int small_change_counter = 0; for (int iter = 0; !common_termination_criteria(iter); iter++) { bool better_fit = do_iteration(); if (better_fit) { realt d = prev_chi2 - chi2; if (F_->get_verbosity() >= 1) F_->ui()->mesg("#" + S(iter_nr_) + ":" " WSSR=" + sm->format_double(chi2) + " lambda=" + S(lambda) + " d(WSSR)=" + S(-d) + " (" + S (d / prev_chi2 * 100) + "%)"); // another termination criterium: negligible change of chi2 if (d / prev_chi2 < stop_rel || chi2 == 0) { small_change_counter++; if (small_change_counter >= 2 || chi2 == 0) { F_->msg("... converged."); break; } } else small_change_counter = 0; prev_chi2 = chi2; } else { // no better fit if (F_->get_verbosity() >= 1) F_->ui()->mesg("#" + S(iter_nr_) + ":" " (WSSR=" + sm->format_double(chi2_) + ")" " lambda=" + S(lambda)); if (lambda > max_lambda) { // another termination criterium F_->msg("In L-M method: lambda=" + S(lambda) + " > " + S(max_lambda) + ", stopped."); break; } } iteration_plot(a, chi2); } post_fit (a, chi2); }
double NLfit::calculate(int n, const double* par, double* grad) { assert(n == na_); vector<realt> A(par, par+n); if (F_->get_verbosity() >= 1) output_tried_parameters(A); bool stop = common_termination_criteria(); if (stop) nlopt_force_stop(opt_); double wssr; if (!grad || stop) wssr = compute_wssr(A, fitted_datas_); else wssr = compute_wssr_gradient(A, fitted_datas_, grad); if (F_->get_verbosity() >= 1) F_->ui()->mesg(iteration_info(wssr)); return wssr; }