using namespace std;
#include "hmdcminimize.h"
#include "hdebug.h"
#include <iostream>
#include <iomanip>
#include <cmath>
#include "TRandom.h"
ClassImp(HMdcMinimize)
HMdcMinimize::HMdcMinimize(void) {
fObjectFit=0;
nPar=0;
fFCN=0;
}
HMdcMinimize::~HMdcMinimize(void) {
fObjectFit=0;
fFCN=0;
}
void HMdcMinimize::setFCN(TObject *obj,Double_t (*fcn)(TObject *, Int_t &, Double_t *)) {
fObjectFit=obj;
fFCN=fcn;
}
Int_t HMdcMinimize::minimize(Int_t maxIter, Int_t nParIn,
Double_t* par0, Double_t* stepPar, Double_t* parOut) {
if(fFCN==0) return -1;
if(nParIn<=0) return -1;
nPar=nParIn;
Double_t stepFit=10.;
Double_t functi,pari[200];
Double_t cosgrad[200];
Int_t istepinc = 0;
Int_t istepdec = 0;
Int_t nStepCh = 0;
Double_t stepCh[6] = {2.0, 1.5, 1.5, 2.0, 1.2, 1.1};
Double_t dFdRi;
Double_t dfunctmax = 1.5;
Double_t dfunctmin = 0.7;
Int_t iprint = 1;
Double_t funTmp;
funct0=(*fFCN)(fObjectFit,nPar,par0);
cout<< " *** Entry mimimize :" << endl << " *funct0=" << funct0
<< " nPar=" << nPar << endl << endl;;
for(Int_t k = 0; k < nPar; k++) parIn[k] = par0[k];
for(Int_t iter=0; iter < maxIter; iter++) {
istepdec = 0;
istepinc = 0;
cout<< endl << " * iter=" << iter << endl << " * Input parIn:" << endl;
printf(" * %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f \n"
,parIn[0],parIn[1],parIn[2],parIn[3],parIn[4],parIn[5],
parIn[6],parIn[7],parIn[8],parIn[9],parIn[10],parIn[11]
,parIn[12],parIn[13],parIn[14],parIn[15],parIn[16],parIn[17]
,parIn[18],parIn[19],parIn[20],parIn[21],parIn[22],parIn[23]);
functIn = (iter == 0) ? (*fFCN)(fObjectFit,nPar,parIn) : functOut;
functBest = functIn;
for(Int_t b = 0; b < nPar; b++) parBest[b] = parIn[b];
cout<< " * FunctIn=" << functIn << endl;
Double_t agrad;
calculationOfGradient(functIn,parIn,stepPar, nPar,agrad,cosgrad,1);
for(Int_t k = 0; k < nPar; k++) {
pari[k] = parIn[k] - cosgrad[k]*.01*scalePar[k];
cout << " my3 " << cosgrad[k] << " " << scalePar[k] << " " << parIn[k] << " " << pari[k] << endl;
}
funTmp = (*fFCN)(fObjectFit,nPar,pari);
if(funTmp < functBest) {
functBest = funTmp;
for(Int_t b = 0; b < nPar; b++) parBest[b] = pari[b];
}
Double_t dFdR0 = (funTmp/functIn - 1.0)/(.01);
if(dFdR0 == 0) {
if(functIn <= functBest) {
cout << endl << " *abnormal(same functional) exit after " << iter << "iteration" << endl;
cout<< " * agrad=" << agrad << endl;
return 0;
}
for(Int_t b = 0; b < nPar; b++) parOut[b] = parBest[b];
functOut = functBest;
for(Int_t k = 0; k < nPar; k++) parIn[k] = parOut[k];
cout<< " * functOut=" << functOut << endl;
cout<< " * agrad=" << agrad << endl;
cout<< " * Output parOut:" << endl;
printf(" * %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f \n"
,parOut[0],parOut[1],parOut[2],parOut[3],parOut[4],parOut[5]
,parOut[6],parOut[7],parOut[8],parOut[9],parOut[10],parOut[11]
,parOut[12],parOut[13],parOut[14],parOut[15],parOut[16],parOut[17]
,parOut[18],parOut[19],parOut[20],parOut[21],parOut[22],parOut[23]);
continue;
}
while(kTRUE) {
for(Int_t k = 0; k < nPar; k++)
pari[k] = parIn[k] - cosgrad[k]*stepFit*scalePar[k];
funTmp = (*fFCN)(fObjectFit,nPar,pari);
if(funTmp < functBest) {
functBest = funTmp;
for(Int_t b = 0; b < nPar; b++) parBest[b] = pari[b];
}
functi = funTmp/functIn;
for(Int_t k = 0; k < nPar; k++)
pari[k] = parIn[k] - cosgrad[k]*stepFit*1.01*scalePar[k];
funTmp = (*fFCN)(fObjectFit,nPar,pari);
if(funTmp < functBest) {
functBest = funTmp;
for(Int_t b = 0; b < nPar; b++) parBest[b] = pari[b];
}
dFdRi = (funTmp/functIn-functi)/(stepFit*0.01);
cout << " my " << dFdRi << " " << functi << " " << istepdec << " " << istepinc << endl;
if(dFdRi < 0) {
if(functi > 1.0 && istepdec < 2) {
stepFit = stepFit/5;
istepdec++;
if(iprint == 1) cout << " *functi(dFdRi<0)=" << functi <<
" *! step is decreased, now stepFit=" << stepFit << endl;
continue;
}
else {
if(istepinc ==2) break;
nStepCh = 3*istepinc + istepdec;
stepFit *= stepCh[nStepCh];
istepinc++;
if(iprint == 1) cout << " *functi(dFdRi<0)=" << functi <<
" *! step is increased, now stepFit=" << stepFit << endl;
continue;
}
}
else {
if(functi < dfunctmin) {
if(istepinc == 2) break;
nStepCh = 3*istepinc + istepdec;
stepFit *= stepCh[nStepCh];
istepinc++;
if(iprint == 1) cout << " *functi(dFdRi>0)=" << functi <<
" *! step is increased, now stepFit=" << stepFit << endl;
continue;
} else {
if(functi > dfunctmax) {
if(istepdec ==2) break;
nStepCh = 3*istepdec + istepinc;
stepFit /= stepCh[nStepCh];
istepdec++;
if(iprint == 1) cout << " *functi(dFdRi>0)=" << functi <<
" *! step is decreased, now stepFit=" << stepFit << endl;
continue;
}
}
}
break;
}
Double_t coeffC = 1.0;
Double_t coeffB = dFdR0;
Double_t coeffA = (functi - coeffC - coeffB*stepFit)/(stepFit*stepFit);
Double_t stepFit1 = -coeffB/(2*coeffA);
if(coeffA < 0.000001 || (stepFit1/stepFit) > 1.2)
stepFit1 = (dFdRi > 0) ? stepFit/2.0 : stepFit/1.5;
cout << " my2 " << coeffA << " " << coeffB << " " << stepFit1 << " " << endl;
for(Int_t k = 0; k < nPar; k++)
parOut[k] = parIn[k] -cosgrad[k]*stepFit1*scalePar[k];
functOut = (*fFCN)(fObjectFit,nPar,parOut);
if(functOut > functIn) {
for(Int_t k = 0; k < nPar; k++)
parOut[k] = parIn[k] -cosgrad[k]*0.03*stepFit1*scalePar[k];
functOut = (*fFCN)(fObjectFit,nPar,parOut);
}
if(functOut > functBest) {
for(Int_t b = 0; b < nPar; b++) parOut[b] = parBest[b];
functOut = functBest;
}
for(Int_t k = 0; k < nPar; k++) parIn[k] = parOut[k];
cout<< " * functOut=" << functOut << endl;
cout<< " * agrad=" << agrad << endl;
cout<< " * Output parOut:" << endl;
printf(" * %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f \n"
,parOut[0],parOut[1],parOut[2],parOut[3],parOut[4],parOut[5]
,parOut[6],parOut[7],parOut[8],parOut[9],parOut[10],parOut[11]
,parOut[12],parOut[13],parOut[14],parOut[15],parOut[16],parOut[17]
,parOut[18],parOut[19],parOut[20],parOut[21],parOut[22],parOut[23]);
if(functIn - functOut < .00001) return 1;
}
cout << " *!!! number of iteration exceeded !!!" << endl;
cout<< " * Output parOut:" << endl;
printf(" * %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f \n"
,parOut[0],parOut[1],parOut[2],parOut[3],parOut[4],parOut[5]
,parOut[6],parOut[7],parOut[8],parOut[9],parOut[10],parOut[11]
,parOut[12],parOut[13],parOut[14],parOut[15],parOut[16],parOut[17]
,parOut[18],parOut[19],parOut[20],parOut[21],parOut[22],parOut[23]);
return 1;
}
void HMdcMinimize::calculationOfGradient(
Double_t fun0, Double_t* par, Double_t* stepPar, Int_t nPar,
Double_t& agrad, Double_t* cosgrad, Int_t iflag) {
for(Int_t k = 0; k < nPar; k++) scalePar[k] = 1.0;
for(Int_t k = 0; k < nPar; k++) {
Double_t park = par[k];
par[k] = park + stepPar[k];
Double_t funk = (*fFCN)(fObjectFit,nPar,par);
par[k] = park - stepPar[k];
Double_t funk1 = (*fFCN)(fObjectFit,nPar,par);
grad[k] = (funk - funk1)/(2.0*stepPar[k]);
grad2[k][k] = (funk + funk1 - 2.0*fun0)/(stepPar[k]*stepPar[k]);
if(iflag > 0 && grad2[k][k]>0.001) {
scalePar[k] = 1./sqrt(grad2[k][k]);
grad[k] *=scalePar[k];
} else scalePar[k] = 1.0;
par[k] = park;
for(Int_t l = k+1; l < nPar; l++) {
if(iflag < 2) grad2[k][l] = grad2[l][k] = 0;
else {
par[k] = park + stepPar[k];
Double_t parl = par[l];
par[l] = parl + stepPar[k];
Double_t funkl = (*fFCN)(fObjectFit,nPar,par);
par[k] = park;
Double_t funl = (*fFCN)(fObjectFit,nPar,par);
par[l] = parl;
grad2[k][l] = grad2[l][k] = (funkl + fun0 - funk - funl)/(stepPar[k]*stepPar[k]);
}
}
}
agrad = 0.0;
for(Int_t k = 0; k < nPar; k++) agrad += grad[k]*grad[k];
agrad = sqrt(agrad);
for(Int_t k = 0; k < nPar; k++) cosgrad[k] = grad[k]/agrad;
return;
}
Int_t HMdcMinimize::minimize2(Int_t maxIter2, Int_t numOfParam,
Double_t* par0, Double_t* stepPar, Double_t* parOut) {
Double_t pari[200];
Double_t functIn;
Double_t cosgrad[200];
Double_t agrad;
for(Int_t k = 0; k < numOfParam; k++) pari[k] = par0[k];
funct0=(*fFCN)(fObjectFit,numOfParam,pari);
cout<< endl << endl << " *** Entry mimimize2 :" << endl
<< " *funct0=" << funct0 << " nPar=" << numOfParam << endl;
cout<< " * Input param:" << endl;
for(Int_t l=0; l < numOfParam; l++) printf(" %f",pari[l]);
cout<< endl;
for(Int_t iter2 = 0; iter2 < maxIter2; iter2++) {
functIn = funct0;
calculationOfGradient(functIn,pari,stepPar,numOfParam,agrad,cosgrad,2);
solutionOfLinearEquationsSystem(pari,numOfParam);
funct0=(*fFCN)(fObjectFit,numOfParam,pari);
}
for(Int_t k = 0; k < nPar; k++) parOut[k] = pari[k];
functOut = (*fFCN)(fObjectFit,numOfParam,parOut);
cout<< " * functOut2=" << functOut << endl;
cout<< " * agrad=" << agrad << endl;
cout<< " * Output parOut2:" << endl;
for(Int_t l=0; l < nPar; l++) printf(" %f",parOut[l]);
return 1;
}
void HMdcMinimize::solutionOfLinearEquationsSystem(Double_t* par,
Int_t nmOfPar) {
Double_t a[10][11];
Int_t ieq[10];
for(Int_t i = 0; i < nmOfPar; i++) {
for(Int_t j = 0; j < nmOfPar; j++) a[i][j] = grad2[i][j];
a[i][nmOfPar] = -grad[i];
ieq[i] = -1;
}
Int_t iMax = 0;
Int_t jMax = 0;
for(Int_t l = 0; l < nmOfPar; l++) {
Double_t maxA = 0.0 ;
for(Int_t i = 0; i < nmOfPar; i++) {
if(ieq[i] != -1) continue;
for(Int_t j = 0; j < nmOfPar; j++) {
if(fabs(a[i][j]) <= maxA) continue;
maxA = fabs(a[i][j]);
iMax = i;
jMax = j;
}
}
ieq[iMax] = jMax;
Double_t corr = a[iMax][jMax];
for(Int_t j = 0; j <= nmOfPar; j++) a[iMax][j] /= corr;
for(Int_t i = 0; i < nmOfPar; i++) {
if(i == iMax) continue;
corr = a[i][jMax];
for(Int_t j = 0; j <= nmOfPar; j++) a[i][j] -= a[iMax][j]*corr;
}
}
for(Int_t i = 0; i < nmOfPar; i++) {
Int_t iout = ieq[i];
if(iout>=0) par[iout] += a[i][nmOfPar];
}
return;
}
Int_t HMdcMinimize::minpar2(Int_t maxIter, Int_t nParIn,
Double_t* par0, Double_t* dpar, Double_t* parOut) {
if(fFCN==0) return -1;
if(nParIn<=0) return -1;
nPar=nParIn;
Double_t pari[25], parbest[25], A[25], b[25];
for(Int_t i = 0; i < nPar; i++) pari[i] = par0[i];
Double_t f0 = (*fFCN)(fObjectFit,nPar,pari);
Double_t fbest = 1000000000.;
for(Double_t iter = 10; iter < maxIter; iter++) {
Double_t fip[25], fim[25];
for(Int_t i = 0; i < nPar; i++) {
Double_t pard = pari[i];
pari[i] = pard + iter;
fip[i] = (*fFCN)(fObjectFit,nPar,pari);
pari[i] = pard - iter;
fim[i] = (*fFCN)(fObjectFit,nPar,pari);
pari[i] = pard;
A[i] = (fip[i] - 2.0*f0 +fim[i])/(2.0*dpar[i]*dpar[i]);
b[i] = pari[i] -
(fip[i] - fim[i])*dpar[i]/(2.0*(fip[i] - 2.0*f0 + fim[i]));
parOut[i] = b[i];
}
for(Int_t i = 0; i < nPar; i++) pari[i] = parOut[i];
f0 = (*fFCN)(fObjectFit,nPar,parOut);
cout << " ========================================================== " << endl;
if(f0 < fbest) {
fbest = f0;
for(Int_t i = 0; i < nPar; i++) parbest[i] = parOut[i];
}
}
for(Int_t i = 0; i < nPar; i++) parOut[i] = parbest[i];
for(Int_t i = 0; i < nPar; i++) cout << parbest[i] << " , ";
cout << fbest << endl;
return 1;
}
Int_t HMdcMinimize::minbar(Int_t maxIter, Int_t nParIn,
Double_t* par0, Double_t* step, Double_t* parOut) {
if(fFCN==0) return -1;
if(nParIn<=0) return -1;
Double_t stepNormW = 10;
Double_t maxDelta, delta[24], parameter[24];
Double_t newFunctional = 0;
Int_t numOfParam = nParIn;
for(Int_t i = 0; i < numOfParam; i++) parameter[i] = par0[i];
Double_t weightPar[24] = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0};
Double_t functional = (*fFCN)(fObjectFit,nPar,parameter);
for (Int_t iteration = 0; iteration < maxIter; iteration++ ) {
maxDelta = 0;
for(Int_t i = 0; i < numOfParam; i++) {
parameter[i] += stepNormW*step[i];
delta[i] = ((*fFCN)(fObjectFit,nPar,parameter) - functional)/(stepNormW*step[i]);
parameter[i] -= stepNormW*step[i];
}
for(Int_t i = 0; i < numOfParam; i++)
if (maxDelta < fabs(delta[i])) maxDelta = fabs(delta[i]);
for(Int_t i = 0; i < numOfParam; i++) {
parameter[i] -= stepNormW*step[i]*delta[i]*weightPar[i]/maxDelta;
}
newFunctional = (*fFCN)(fObjectFit,nPar,parameter);
if(newFunctional < functional) functional = newFunctional;
else {
for(Int_t i = 0; i < numOfParam; i++)
parameter[i] += 0.5*stepNormW*step[i]*delta[i]*weightPar[i]/maxDelta;
newFunctional = (*fFCN)(fObjectFit,nPar,parameter);
if( newFunctional < functional ) functional = newFunctional;
else {
for(Int_t i = 0; i < numOfParam; i++)
parameter[i] += 0.5*stepNormW*step[i]*delta[i]*weightPar[i]/maxDelta;
stepNormW /= 2;
}
}
if(stepNormW >= 0.05) continue;
}
for(Int_t i = 0; i < numOfParam; i++) parOut[i] = parameter[i];
return 1;
}
Int_t HMdcMinimize::scanXYZ(Int_t maxIter, Int_t nParIn,
Double_t* par0, Double_t* parOut) {
if(fFCN==0) return -1;
if(nParIn<=0) return -1;
nPar=nParIn;
Double_t functi, pari[200];
for(Int_t k = 0; k < nPar; k++) pari[k] = par0[k];
Int_t i = 0;
Double_t stepx = 0;
for (Double_t stepy = -10; stepy < 10.1; stepy += 1.) {
for (Double_t stepz = -10; stepz < 10.1; stepz += 1.) {
pari[0] = par0[0] + stepx;
pari[1] = par0[1] + stepy;
pari[2] = par0[2] + stepz;
functi = (*fFCN)(fObjectFit,nPar,pari);
cout << "parx[" << i << "]=" << pari[0] << ";"
<< "pary[" << i << "]=" << pari[1] << ";"
<< "parz[" << i << "]=" << pari[2] << ";"
<< "sumFunctional[" << i << "]="
<< setprecision(9) << functi << ";" << endl;
i++;
}
}
return 1;
}
Int_t HMdcMinimize::random(Int_t maxIter, Int_t nParIn,
Double_t* par0, Double_t* parOut) {
if(fFCN==0) return -1;
if(nParIn<=0) return -1;
nPar=nParIn;
Double_t functi, pari[200], par[200], alpha[200], alphamin[200], funmin = 1000000000., funstart, parmin[200];
Double_t sigma = 40.;
funstart = (*fFCN)(fObjectFit,nPar,par0);
for(Int_t k = 0; k < nPar; k++) pari[k] = par0[k];
for(Int_t iter=0; iter < maxIter; iter++) {
if(funmin >= funstart && iter) {
sigma /= 2. ;
if(sigma < 1.) {
for(Int_t k = 0; k < nPar; k++) parOut[k] = pari[k];
for(Int_t k = 0; k < nPar; k++) cout << "parOut[" << k << "] = " << parOut[k] << " ";
cout << " minFunctional = " << funstart << ";" << endl;
break;
}
}
else {
funstart = funmin;
for(Int_t k = 0; k < nPar; k++) pari[k] = parmin[k];
}
funmin = 1000000000.;
for( Int_t itry = 0 ; itry < 10; itry++ ) {
Double_t sumAlpha2 = 0;
for(Int_t k = 0; k < nPar; k++) {
alpha[k] = gRandom->Uniform(-1.,1.);
sumAlpha2 += alpha[k]*alpha[k];
}
for(Int_t k = 0; k < nPar; k++) {
alpha[k] /= sqrt(sumAlpha2);
par[k] = pari[k] + alpha[k]*sigma;
}
functi = (*fFCN)(fObjectFit,nPar,par);
if (functi < funmin) {
funmin = functi;
for(Int_t k = 0; k < nPar; k++) alphamin[k] = alpha[k];
for(Int_t k = 0; k < nPar; k++) parmin[k] = par[k];
}
}
for(Int_t k = 0; k < nPar; k++) par[k] = pari[k] + alphamin[k]*sigma/2.;
functi = (*fFCN)(fObjectFit,nPar,par);
if (functi < funmin) {
funmin = functi;
for(Int_t k = 0; k < nPar; k++) parmin[k] = par[k];
}
for(Int_t k = 0; k < nPar; k++) par[k] = pari[k] + alphamin[k]*sigma*2.;
functi = (*fFCN)(fObjectFit,nPar,par);
if (functi < funmin) {
funmin = functi;
for(Int_t k = 0; k < nPar; k++) parmin[k] = par[k];
}
for(Int_t k = 0; k < nPar; k++) cout << "parmin[" << k << "] = " << parmin[k] << "; " ;
cout << " minFunctional = " << funmin << ";" << " globalMinFunctional = " << funstart << ";" << " sigma = " << sigma << endl;
}
for(Int_t k = 0; k < nPar; k++) cout << "parmin[" << k << "]=" << parmin[k];
cout << " minFunctional = " << funstart << ";" << endl;
return 1;
}
Int_t HMdcMinimize::cog(Int_t maxIter, Int_t nParIn,
Double_t* par0, Double_t* parOut) {
if(fFCN==0) return -1;
if(nParIn<=0) return -1;
nPar=nParIn;
Double_t functi, pari[200], par[200], alpha[200], funmin = 1000000000., funstart, parsum[200];
Double_t sigma = 32.;
funstart = (*fFCN)(fObjectFit,nPar,par0);
for(Int_t k = 0; k < nPar; k++) pari[k] = par0[k];
Float_t itry = 0.;
Float_t alltry = 0.;
funmin = 200.;
itry = 0.;
alltry = 0.;
for(Int_t k = 0; k < nPar; k++) parsum[k] = 0.;
while(itry < maxIter) {
Double_t sumAlpha2 = 0;
for(Int_t k = 0; k < nPar; k++) {
alpha[k] = gRandom->Uniform(-1.,1.);
sumAlpha2 += alpha[k]*alpha[k];
}
for(Int_t k = 0; k < nPar; k++) {
alpha[k] /= sqrt(sumAlpha2);
par[k] = pari[k] + alpha[k]*sigma;
}
functi = (*fFCN)(fObjectFit,nPar,par);
if (functi < funmin) {
for(Int_t k = 0; k < nPar; k++) parsum[k] += par[k];
itry++;
cout << " itry = " << itry << endl;
}
alltry++;
}
for(Int_t k = 0; k < nPar; k++) pari[k] = parsum[k]/maxIter;
functi = (*fFCN)(fObjectFit,nPar,pari);
for(Int_t k = 0; k < nPar; k++) cout << "parmin[" << k << "] = " << pari[k] << "; " ;
cout << " minFunctional = " << funmin << ";" << " globalMinFunctional = " << functi << ";" << " sigma = " << sigma << " Ntry = " << alltry << endl;
for(Int_t k = 0; k < nPar; k++) parOut[k] = pari[k];
return 1;
}
Int_t HMdcMinimize::scan(Int_t maxIter, Int_t nParIn,
Double_t* par0, Double_t* parOut) {
if(fFCN==0) return -1;
if(nParIn<=0) return -1;
nPar=nParIn;
Double_t functi,pari[200];
for(Int_t k = 0; k < nPar; k++) pari[k] = par0[k];
for(Int_t iter=0; iter < 3; iter++) {
Int_t i = 0;
for (Double_t step = -20; step < 20.1; step += 1.) {
pari[iter+maxIter] += step;
functi = (*fFCN)(fObjectFit,nPar,pari);
cout << "par[" << i << "]=" << pari[iter+maxIter]
<< " ; sumFunctional[" << i << "]="
<< functi << ";" << endl;
pari[iter+maxIter] -= step;
i++;
}
}
return 1;
}
Last change: Sat May 22 13:02:58 2010
Last generated: 2010-05-22 13:02
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.