00001
00002
00003
00004 #include "common.h"
00005 #include "LMfit.h"
00006 #include "ui.h"
00007 #include "settings.h"
00008 #include "logic.h"
00009 #include <math.h>
00010 #include <vector>
00011 #include <algorithm>
00012
00013 using namespace std;
00014
00015 LMfit::LMfit(Ftk* F)
00016 : Fit(F, "levenberg_marquardt")
00017 {
00018 }
00019
00020 LMfit::~LMfit() {}
00021
00022
00023 void LMfit::init()
00024 {
00025 alpha.resize(na_*na_);
00026 alpha_.resize(na_*na_);
00027 beta.resize(na_);
00028 beta_.resize(na_);
00029 lambda = F_->get_settings()->lm_lambda_start;
00030 a = a_orig_;
00031
00032 F_->vmsg(print_matrix (a, 1, na_, "Initial A"));
00033
00034 chi2 = compute_wssr(a, dmdm_);
00035 compute_derivatives(a, dmdm_, alpha, beta);
00036 }
00037
00038 void LMfit::autoiter()
00039 {
00040 wssr_before_ = chi2;
00041 realt prev_chi2 = chi2;
00042 const SettingsMgr *sm = F_->settings_mgr();
00043 F_->vmsg("\t === Levenberg-Marquardt method ===");
00044 F_->vmsg("Initial values: lambda=" + S(lambda)
00045 + " WSSR=" + sm->format_double(chi2));
00046 F_->vmsg("Max. number of iterations: " + max_iterations_);
00047 realt stop_rel = F_->get_settings()->lm_stop_rel_change;
00048 realt max_lambda = F_->get_settings()->lm_max_lambda;
00049 if (stop_rel > 0) {
00050 F_->vmsg ("Will stop when relative change of WSSR is "
00051 "twice in row below " + S (stop_rel * 100.) + "%");
00052 }
00053 int small_change_counter = 0;
00054 for (int iter = 0; !common_termination_criteria(iter); iter++) {
00055 bool better_fit = do_iteration();
00056 if (better_fit) {
00057 realt d = prev_chi2 - chi2;
00058 F_->vmsg("#" + S(iter_nr_) + ": WSSR=" + sm->format_double(chi2)
00059 + " lambda=" + S(lambda) + " d(WSSR)=" + S(-d)
00060 + " (" + S (d / prev_chi2 * 100) + "%)");
00061
00062 if (d / prev_chi2 < stop_rel || chi2 == 0) {
00063 small_change_counter++;
00064 if (small_change_counter >= 2 || chi2 == 0) {
00065 F_->msg("... converged.");
00066 break;
00067 }
00068 }
00069 else
00070 small_change_counter = 0;
00071 prev_chi2 = chi2;
00072 }
00073 else {
00074 F_->vmsg("#" + S(iter_nr_) + ": (WSSR=" + sm->format_double(chi2_)
00075 + ") lambda=" + S(lambda));
00076 if (lambda > max_lambda) {
00077 F_->msg("In L-M method: lambda=" + S(lambda) + " > "
00078 + S(max_lambda) + ", stopped.");
00079 break;
00080 }
00081 }
00082 iteration_plot(a, chi2);
00083 }
00084 post_fit (a, chi2);
00085 }
00086
00087 bool LMfit::do_iteration()
00088
00089 {
00090 if (na_ < 1)
00091 throw ExecuteError("No parameters to fit.");
00092 iter_nr_++;
00093 alpha_ = alpha;
00094 for (int j = 0; j < na_; j++)
00095 alpha_[na_ * j + j] *= (1.0 + lambda);
00096 beta_ = beta;
00097 if (F_->get_verbosity() > 1) {
00098 F_->msg (print_matrix (beta_, 1, na_, "beta"));
00099 F_->msg (print_matrix (alpha_, na_, na_, "alpha'"));
00100 }
00101
00102
00103 Jordan (alpha_, beta_, na_);
00104
00105
00106 if (F_->get_verbosity() >= 1) {
00107 vector<realt> rel(na_);
00108 for (int q = 0; q < na_; q++)
00109 rel[q] = beta_[q] / a[q] * 100;
00110 F_->vmsg(print_matrix (rel, 1, na_, "delta(A)/A[%]"));
00111 }
00112
00113 for (int i = 0; i < na_; i++)
00114 beta_[i] = a[i] + beta_[i];
00115
00116 if (F_->get_verbosity() >= 1) {
00117 const SettingsMgr *sm = F_->settings_mgr();
00118 string s = "Trying A={ ";
00119 v_foreach (realt, j, beta_)
00120 s += sm->format_double(*j) + (j+1 == beta_.end() ? " }" : ", ");
00121 F_->vmsg(s);
00122 }
00123
00124
00125 chi2_ = compute_wssr(beta_, dmdm_);
00126 if (chi2_ < chi2) {
00127 chi2 = chi2_;
00128 a = beta_;
00129 compute_derivatives(a, dmdm_, alpha, beta);
00130 lambda /= F_->get_settings()->lm_lambda_down_factor;
00131 return true;
00132 }
00133 else {
00134 lambda *= F_->get_settings()->lm_lambda_up_factor;
00135 return false;
00136 }
00137 }
00138