00001
00002
00003
00004 #include <stdlib.h>
00005 #include <time.h>
00006 #include <math.h>
00007 #include <vector>
00008
00009 #include "common.h"
00010 #include "NMfit.h"
00011 #include "logic.h"
00012 #include "settings.h"
00013
00014 using namespace std;
00015
00016 NMfit::NMfit(Ftk* F)
00017 : Fit(F, "nelder_mead_simplex")
00018 {
00019 }
00020
00021 NMfit::~NMfit() {}
00022
00023 void NMfit::init()
00024 {
00025 bool move_all = F_->get_settings()->nm_move_all;
00026 char distrib = F_->get_settings()->nm_distribution[0];
00027 realt factor = F_->get_settings()->nm_move_factor;
00028
00029
00030 Vertex v(a_orig_);
00031 vertices = vector<Vertex> (na_ + 1, v);
00032
00033 for (int i = 0; i < na_; i++) {
00034 vertices[i + 1].a[i] = draw_a_from_distribution(i, distrib, factor);
00035 if (move_all) {
00036 realt d2 = (vertices[i + 1].a[i] - vertices[0].a[i]) / 2;
00037 for (vector<Vertex>::iterator j = vertices.begin();
00038 j != vertices.end(); j++)
00039 j->a[i] -= d2;
00040 }
00041 }
00042 for (vector<Vertex>::iterator i = vertices.begin(); i!=vertices.end(); i++)
00043 compute_v (*i);
00044
00045 find_best_worst();
00046 compute_coord_sum();
00047 volume_factor = 1.;
00048
00049 }
00050
00051 void NMfit::find_best_worst()
00052 {
00053
00054 if (vertices[0].wssr < vertices[1].wssr) {
00055 worst = vertices.begin() + 1;
00056 s_worst = best = vertices.begin();
00057 }
00058 else {
00059 worst = vertices.begin();
00060 s_worst = best = vertices.begin() + 1;
00061 }
00062 for (vector<Vertex>::iterator i = vertices.begin(); i!=vertices.end() ;i++){
00063 if (i->wssr < best->wssr)
00064 best = i;
00065 if (i->wssr > worst->wssr) {
00066 s_worst = worst;
00067 worst = i;
00068 }
00069 else if (i->wssr > s_worst->wssr && i != worst)
00070 s_worst = i;
00071 }
00072 }
00073
00074 void NMfit::autoiter()
00075 {
00076 realt convergence = F_->get_settings()->nm_convergence;
00077 wssr_before_ = compute_wssr(a_orig_, dmdm_);
00078 F_->msg("WSSR before starting simplex fit: " + S(wssr_before_));
00079 for (int iter = 0; !termination_criteria(iter, convergence); ++iter) {
00080 ++iter_nr_;
00081 change_simplex();
00082 find_best_worst();
00083 iteration_plot(best->a, best->wssr);
00084 }
00085 post_fit (best->a, best->wssr);
00086 }
00087
00088 void NMfit::change_simplex()
00089 {
00090 realt t = try_new_worst (-1.);
00091 if (t <= best->wssr)
00092 try_new_worst (2.);
00093 else if (t >= s_worst->wssr) {
00094 realt old = worst->wssr;
00095 realt t = try_new_worst(0.5);
00096 if (t >= old) {
00097 for (vector<Vertex>::iterator i = vertices.begin();
00098 i != vertices.end() ;i++) {
00099 if (i == best)
00100 continue;
00101 for (int j = 0; j < na_; j++)
00102 i->a[j] = (i->a[j] + best->a[j]) / 2;
00103 compute_v (*i);
00104 volume_factor *= 0.5;
00105 }
00106 compute_coord_sum();
00107 }
00108 }
00109 }
00110
00111 realt NMfit::try_new_worst(realt f)
00112
00113
00114
00115 {
00116 Vertex t(na_);
00117 realt f1 = (1 - f) / na_;
00118 realt f2 = f1 - f;
00119 for (int i = 0; i < na_; i++)
00120 t.a[i] = coord_sum[i] * f1 - worst->a[i] * f2;
00121 compute_v (t);
00122 if (t.wssr < worst->wssr) {
00123 for (int i = 0; i < na_; i++)
00124 coord_sum[i] += t.a[i] - worst->a[i];
00125 *worst = t;
00126 volume_factor *= f;
00127 }
00128 return t.wssr;
00129 }
00130
00131 void NMfit::compute_coord_sum()
00132 {
00133 coord_sum.resize(na_);
00134 fill (coord_sum.begin(), coord_sum.end(), 0.);
00135 for (int i = 0; i < na_; i++)
00136 for (vector<Vertex>::iterator j = vertices.begin();
00137 j != vertices.end(); j++)
00138 coord_sum[i] += j->a[i];
00139 }
00140
00141 bool NMfit::termination_criteria(int iter, realt convergence)
00142 {
00143 F_->vmsg("#" + S(iter_nr_) + " (ev:" + S(evaluations_) + "): best:"
00144 + S(best->wssr) + " worst:" + S(worst->wssr) + ", "
00145 + S(s_worst->wssr) + " [V * |" + S(volume_factor) + "|]");
00146 bool stop = false;
00147 if (volume_factor == 1. && iter != 0) {
00148 F_->msg ("Simplex got stuck.");
00149 stop = true;
00150 }
00151 volume_factor = 1.;
00152
00153
00154
00155
00156
00157
00158
00159
00160 if (common_termination_criteria(iter))
00161 stop = true;
00162 if (is_zero(worst->wssr)) {
00163 F_->msg ("All vertices have WSSR < epsilon=" + S(epsilon));
00164 return true;
00165 }
00166 realt r_diff = 2 * (worst->wssr - best->wssr) / (best->wssr + worst->wssr);
00167 if (r_diff < convergence) {
00168 F_->msg ("Relative difference between worst and best vertex is only "
00169 + S(r_diff) + ". Stop");
00170 stop = true;
00171 }
00172 return stop;
00173 }
00174
00175 void NMfit::compute_v(Vertex& v)
00176 {
00177 assert (!v.a.empty());
00178 v.wssr = compute_wssr(v.a, dmdm_);
00179 v.computed = true;
00180 }
00181