y = ax + bの関係が成り立つとして、最適なa, bを決定する。
void(*fcn)(Int_t &, Double_t *, Double_t &f, Double_t *, Int_t)という形式の静的外部関数(クラスに属するメンバー関数不可)を要求する。上記の参考サイトの見本を使うと
void FCN(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t flag)になる。で、それぞれの変数の意味は
npar : 最小化に含まれる自由パラメーターの数 gin : 計算された勾配値 (オプション) f : 関数値そのもの par : 定数および変数パラメーターのvector flag : FCN のいくつかのアクションを切り替えるらしい。よくわからんけど、fとparだけ使えば最低限のことは出来る。
void FCN(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t flag){ double a,b; float realpeak[7] = {121.7817, 244.6975, 344.2785, 778.9040, 867.378, 964.079, 1408.006}; float rawpeak[7] = {259.4612, 521.1042, 733.0547, 1668.473, 1856.93, 2062.59, 3013.292}; double rss = 0; a = par[0]; b = par[1]; for (int i=0; i<7; i++){ double y_calced = a * rawpeak[i] + b; rss += (ealpeak[i] - y_calced) * (ealpeak[i] - y_calced); } f = rss; }
int main(){ TMinuit *min = new TMinuit(2); // パラメータ数 min->SetPrintLevel(-1); // 途中経過を非表示 (-1:非表示, 0:標準, 1:冗長表示) min->SetFCN(FCN); // 関数を設定 min->DefineParameter(0, "a", 0.4, 0.0000001, 0.2, 0.5); // パラメータ初期値と刻み幅を設定 min->DefineParameter(1, "b", 4.4, 0.001, -10, +10); // 第二引数の"a"とか"b"はnameを指定する。重複しないようにすれば適当でOK。 min->Migrad(); // 最小化処理を実行 double a,b,ea,eb; min->GetParameter(0, a, dummy); // パラメータを取得 min->GetParameter(1, b, dummy); printf("a : %f +- %f, b : %f +- %f \n", a, ea, b, eb); return 0; }
g++ sample.cxx -o sample `root-config --cflags --libs` -lMinuit