using namespace std;
#include "hmdcminimize.h"
#include "hdebug.h"
#include <iostream>
#include <iomanip> 
#include <cmath>
#include "TRandom.h"

//*-- Author : V.Pechenov
//*-- Modified: 15.04.04 A.Ierusalimov

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=.50;
  Double_t stepFit=10.;
    
  Double_t functi,pari[200];
  Double_t cosgrad[200];
  //Double_t limGrad = 0.001;
  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++) {              //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 \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]);
    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);    

//     if(agrad < limGrad) {
//     cout << endl << "  *normal exit after " << iter << "iteration" << endl;
//     cout<< "   * agrad=" << agrad << endl;    
   
//     return 0;
//     }


    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);
//       pari[k] = parIn[k] - cosgrad[k]*0.001*scalePar[k];
//       Double_t dFdR0 = ((*fFCN)(fObjectFit,nPar,pari)/functIn - 1.0)/(0.001);
    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) {        //while

      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 {   //dFdRi > 0
        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);
    
//     Double_t dec = .03;
//     while(kTRUE) {
//       if(functOut < functIn) break;
//       for(Int_t k = 0; k < nPar; k++)     
//         parOut[k] = parIn[k] -cosgrad[k]*dec*stepFit1*scalePar[k];
//       functOut = (*fFCN)(fObjectFit,nPar,parOut);
//       dec /= 10.;
//     }
    if(functOut > functIn) {
      for(Int_t k = 0; k < nPar; k++)     
        parOut[k] = parIn[k] -cosgrad[k]*0.03*stepFit1*scalePar[k];
//         parOut[k] = parIn[k] -cosgrad[k]*0.3*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) {
    
//   Double_t grad[200];
//   Double_t grad2[200][200];
  
  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);

//     if(funk < functBest) {
//        functBest = funk;
//        for(Int_t b = 0; b < nPar; b++) parBest[b] = par[b];
//     }
    
    par[k] = park - stepPar[k];
    Double_t funk1 = (*fFCN)(fObjectFit,nPar,par);

//     if(funk1 < functBest) {
//        functBest = funk1;
//        for(Int_t b = 0; b < nPar; b++) parBest[b] = par[b];
//     }
    
    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);

//     if(funkl < functBest) {
//        functBest = funkl;
//        for(Int_t b = 0; b < nPar; b++) parBest[b] = par[b];
//     }
    
      par[k] = park;
      Double_t funl = (*fFCN)(fObjectFit,nPar,par);

//     if(funl < functBest) {
//        functBest = funl;
//        for(Int_t b = 0; b < nPar; b++) parBest[b] = par[b];
//     }
    
      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) {
//*** 2-nd method
  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) {
  //  input:  matrix grad2[i][j] (i-string, j-column),  vector grad[i]
  // output:  new param. in vector par[i]
  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];
//   Double_t dpar[25] = {10.0, 10.0, 20.0, 10.0, 10.0, 20.0,10.0,10.0,20.0,10.0,10.0,20.0};
//   Double_t dpar[25] = {10.0, 10.0, 10.0, 10.0, 10.0, 10.0,10.0,10.0,10.0,10.0,10.0,10.0};
//   Double_t dpar[25] = {5.0, 5.0, 5.0, 5.0, 5.0, 5.0,5.0,5.0,5.0,5.0,5.0,5.0};

  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++) pari[i] = par0[i];
  
    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,pari);
    f0 = (*fFCN)(fObjectFit,nPar,parOut);
    cout << " ========================================================== " << endl;
    if(f0 < fbest) {
       fbest = f0;
       for(Int_t i = 0; i < nPar; i++) parbest[i] = parOut[i];
    }
//     else break;
       
  }
  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 step[24] = {.10, .10, .20, .10, .10, .20,.10,.10,.20,.10,.10,.20};
//   Double_t step[24] = {1.0, 1.0, 2.0, 1.0, 1.0, 2.0,1.0,1.0,2.0,1.0,1.0,2.0};
  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];
  //Double_t funmin = 1000000000.;
  //Double_t  parmin[200];

  for(Int_t k = 0; k < nPar; k++) pari[k] = par0[k];

//   for(Int_t iter=0; iter < 3; iter++) {              //iter

     Int_t i = 0;
     Double_t stepx = 0;
//      for (Double_t stepx = -10; stepx < 10.1; stepx += 1.) {        // stepx loop
	for (Double_t stepy = -10; stepy < 10.1; stepy += 1.) {        // stepy loop
	   for (Double_t stepz = -10; stepz < 10.1; stepz += 1.) {        // stepz loop

	pari[0] = par0[0] + stepx;
	pari[1] = par0[1] + stepy;
	pari[2] = par0[2] + stepz;
	
	functi = (*fFCN)(fObjectFit,nPar,pari);
// 	if (functi < funmin) {
// 	   funmin = functi;
// 	   for(Int_t k = 0; k < nPar; k++) parmin[k] = pari[k];
// 	}
	   
	cout << "parx[" << i << "]=" << pari[0] << ";" 
	     << "pary[" << i << "]=" << pari[1] << ";" 
	     << "parz[" << i << "]=" << pari[2] << ";" 
	     << "sumFunctional[" << i << "]="
	     << setprecision(9) << functi << ";" << endl;
	i++;
	   }
	}
//      }
     
//      for(Int_t k = 0; k < nPar; k++) cout << "parmin[" << k << "]=" << parmin[k];
//      cout << "  minFunctional = " << funmin << ";" << endl;
  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);
//   funmin = funstart;
  
  for(Int_t k = 0; k < nPar; k++) pari[k] = par0[k];

  for(Int_t iter=0; iter < maxIter; iter++) {              //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++ ) {              //try
	
	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;
     
  }
	   
// 	cout << "parx[" << i << "]=" << pari[0] << ";" 
// 	     << "pary[" << i << "]=" << pari[1] << ";" 
// 	     << "parz[" << i << "]=" << pari[2] << ";" 
// 	     << "sumFunctional[" << i << "]="
// 	     << setprecision(9) << functi << ";" << 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 alphamin[200];
  Double_t sigma = 32.;//8.;//4.;

  funstart = (*fFCN)(fObjectFit,nPar,par0);
//   funmin = funstart;
  
  for(Int_t k = 0; k < nPar; k++) pari[k] = par0[k];

  Float_t itry = 0.;
  Float_t alltry = 0.;
     
//   for(Int_t iter=0; iter < maxIter; iter++) {              //iter
     
//      if(funmin >= funstart) {
// 	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];
//      }

//      cout << itry << " " << alltry << endl;
//      if(itry/alltry > .5) sigma *= 2;
  funmin = 200.;//140.;//139.;
     itry = 0.;
     alltry = 0.;
     for(Int_t k = 0; k < nPar; k++) parsum[k] = 0.;

     while(itry < maxIter) {              //try
	
	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++) {              //iter

     Int_t i = 0;
     for (Double_t step = -20; step < 20.1; step += 1.) {        // step loop

	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.