00001
00002
00003
00004 #include <algorithm>
00005 #include <string>
00006 #include <vector>
00007 #include <ctype.h>
00008 #include "common.h"
00009 #include "model.h"
00010 #include "func.h"
00011 #include "var.h"
00012 #include "mgr.h"
00013 #include "logic.h"
00014 #include "ast.h"
00015
00016 using namespace std;
00017
00018 Model::Model(Ftk *F)
00019 : F_(F), mgr(*F)
00020 {
00021 mgr.register_model(this);
00022 }
00023
00024 Model::~Model()
00025 {
00026 mgr.unregister_model(this);
00027 }
00028
00029
00030
00031 bool Model::is_dependent_on_var(int idx) const
00032 {
00033 const vector<Variable*>& vv = mgr.variables();
00034 v_foreach (int, i, ff_.idx)
00035 if (mgr.get_function(*i)->is_dependent_on(idx, vv))
00036 return true;
00037 v_foreach (int, i, zz_.idx)
00038 if (mgr.get_function(*i)->is_dependent_on(idx, vv))
00039 return true;
00040 return false;
00041 }
00042
00043 realt Model::value(realt x) const
00044 {
00045 x += zero_shift(x);
00046 realt y = 0;
00047 v_foreach (int, i, ff_.idx)
00048 y += mgr.get_function(*i)->calculate_value(x);
00049 return y;
00050 }
00051
00052 realt Model::zero_shift(realt x) const
00053 {
00054 realt z = 0;
00055 v_foreach (int, i, zz_.idx)
00056 z += mgr.get_function(*i)->calculate_value(x);
00057 return z;
00058 }
00059
00060 void Model::compute_model(vector<realt> &x, vector<realt> &y,
00061 int ignore_func) const
00062 {
00063
00064 v_foreach (int, i, zz_.idx)
00065 mgr.get_function(*i)->calculate_value(x, x);
00066
00067 v_foreach (int, i, ff_.idx)
00068 if (*i != ignore_func)
00069 mgr.get_function(*i)->calculate_value(x, y);
00070 }
00071
00072
00073
00074
00075
00076
00077
00078 void Model::compute_model_with_derivs(vector<realt> &x, vector<realt> &y,
00079 vector<realt> &dy_da) const
00080 {
00081 assert(y.size() == x.size());
00082 if (x.empty())
00083 return;
00084 fill (dy_da.begin(), dy_da.end(), 0);
00085
00086
00087 v_foreach (int, i, zz_.idx)
00088 mgr.get_function(*i)->calculate_value(x, x);
00089
00090
00091 v_foreach (int, i, ff_.idx)
00092 mgr.get_function(*i)->calculate_value_deriv(x, y, dy_da, false);
00093 v_foreach (int, i, zz_.idx)
00094 mgr.get_function(*i)->calculate_value_deriv(x, y, dy_da, true);
00095 }
00096
00097 vector<realt> Model::get_symbolic_derivatives(realt x) const
00098 {
00099 int n = mgr.parameters().size();
00100 vector<realt> dy_da(n+1);
00101 vector<realt> xx(1, x);
00102 vector<realt> yy(1);
00103 compute_model_with_derivs(xx, yy, dy_da);
00104 return dy_da;
00105 }
00106
00107 vector<realt> Model::get_numeric_derivatives(realt x, realt numerical_h) const
00108 {
00109 vector<realt> av_numder = mgr.parameters();
00110 int n = av_numder.size();
00111 vector<realt> dy_da(n+1);
00112 const double small_number = 1e-10;
00113 for (int k = 0; k < n; k++) {
00114 realt acopy = av_numder[k];
00115 realt h = max(fabs(acopy), small_number) * numerical_h;
00116 av_numder[k] -= h;
00117 mgr.use_external_parameters(av_numder);
00118 realt y_aless = value(x);
00119 av_numder[k] = acopy + h;
00120 mgr.use_external_parameters(av_numder);
00121 realt y_amore = value(x);
00122 dy_da[k] = (y_amore - y_aless) / (2 * h);
00123 av_numder[k] = acopy;
00124 }
00125 mgr.use_parameters();
00126 realt h = max(fabs(x), small_number) * numerical_h;
00127 dy_da[n] = (value(x+h) - value(x-h)) / (2 * h);
00128 return dy_da;
00129 }
00130
00131 realt Model::approx_max(realt x_min, realt x_max) const
00132 {
00133 mgr.use_parameters();
00134 realt x = x_min;
00135 realt y_max = value(x);
00136 vector<realt> xx;
00137 v_foreach (int, i, ff_.idx) {
00138 realt ctr;
00139 if (mgr.get_function(*i)->get_center(&ctr)
00140 && x_min < ctr && ctr < x_max)
00141 xx.push_back(ctr);
00142 }
00143 xx.push_back(x_max);
00144 sort(xx.begin(), xx.end());
00145 v_foreach (realt, i, xx) {
00146 realt x_between = (x + *i)/2.;
00147 x = *i;
00148 realt y = max(value(x_between), value(x));
00149 if (y > y_max)
00150 y_max = y;
00151 }
00152 return y_max;
00153 }
00154
00155
00156 string Model::get_peak_parameters(const vector<realt>& errors) const
00157 {
00158 string s;
00159 const SettingsMgr *sm = F_->settings_mgr();
00160 s += "# PeakType\tCenter\tHeight\tArea\tFWHM\tparameters...\n";
00161 v_foreach (int, i, ff_.idx) {
00162 const Function* p = mgr.get_function(*i);
00163 s += "%" + p->name + " " + p->tp()->name;
00164 realt a;
00165 if (p->get_center(&a))
00166 s += "\t" + sm->format_double(a);
00167 else
00168 s += "\tx";
00169 if (p->get_height(&a))
00170 s += "\t" + sm->format_double(a);
00171 else
00172 s += "\tx";
00173 if (p->get_area(&a))
00174 s += "\t" + sm->format_double(a);
00175 else
00176 s += "\tx";
00177 if (p->get_fwhm(&a))
00178 s += "\t" + sm->format_double(a);
00179 else
00180 s += "\tx";
00181 s += "\t";
00182 for (int j = 0; j < p->get_vars_count(); ++j) {
00183 s += " " + sm->format_double(p->av()[j]);
00184 if (!errors.empty()) {
00185 const Variable* var = mgr.get_variable(p->get_var_idx(j));
00186 if (var->is_simple()) {
00187 realt err = errors[var->get_nr()];
00188 s += " +/- " + sm->format_double(err);
00189 }
00190 else
00191 s += " +/- ?";
00192 }
00193 }
00194 s += "\n";
00195 }
00196 return s;
00197 }
00198
00199
00200 string Model::get_formula(bool simplify) const
00201 {
00202 if (ff_.names.empty())
00203 return "0";
00204 string shift;
00205 v_foreach (int, i, zz_.idx)
00206 shift += "+(" + mgr.get_function(*i)->get_current_formula() + ")";
00207 string x = "(x" + shift + ")";
00208 string formula;
00209 v_foreach (int, i, ff_.idx)
00210 formula += (i==ff_.idx.begin() ? "" : "+")
00211 + mgr.get_function(*i)->get_current_formula(x);
00212 if (simplify) {
00213
00214 bool has_upper = false;
00215 for (size_t i = 0; i < formula.size(); ++i)
00216 if (isupper(formula[i])) {
00217 has_upper = true;
00218 break;
00219 }
00220
00221 if (!has_upper)
00222 formula = simplify_formula(formula);
00223 }
00224 return formula;
00225 }
00226
00227 const string& Model::get_func_name(char c, int idx) const
00228 {
00229 const vector<string>& names = get_fz(c).names;
00230 if (idx < 0)
00231 idx += names.size();
00232 if (!is_index(idx, names))
00233 throw ExecuteError("wrong [index]: " + S(idx));
00234 return names[idx];
00235 }
00236
00237 realt Model::numarea(realt x1, realt x2, int nsteps) const
00238 {
00239 x1 += zero_shift(x1);
00240 x2 += zero_shift(x2);
00241 realt a = 0;
00242 v_foreach (int, i, ff_.idx)
00243 a += mgr.get_function(*i)->numarea(x1, x2, nsteps);
00244 return a;
00245 }
00246