// $Header: /cvs/gled-1.2/Numerica/Glasses/WarmAmoeba.cxx,v 1.3 2004/06/03 12:32:48 matevz Exp $

#include "WarmAmoeba.h"

#include <Ephra/Mountain.h>
#include <Gled/GledMirDefs.h>



ClassImp(WarmAmoeba)

/**************************************************************************/
// private

 void WarmAmoeba::_init()
{
  hTrueMaster = 0; m_P = 0;

  mSeed = 0;
  mFTol = 1e-12;
  mTFactor = 3; mAlpha = 1.5;
  mMovesPerT = 1000; mNumSteps = 100;
  mT0 = mT = 0;
  mYBest = mYLast = 0;
}

 void WarmAmoeba::_calc_psum()
{
  for(Int_t i=0; i<m_n; i++) {
    m_Psum(i) = 0;
    for(Int_t j=0; j<=m_n; j++) m_Psum(i) += P(j,i);
  }
}

 void WarmAmoeba::_export_algo_values(Operator::Arg* op_arg, bool bestp)
{
  OP_EXE_OR_SP_MIR(this, SetT, m_T);
  OP_EXE_OR_SP_MIR(this, SetYLast, m_Y(0u));
  OP_EXE_OR_SP_MIR(this, SetYBest, m_y_best);
  if(bestp) {
    OP_EXE_OR_SP_MIR_SATURN(mSaturn, hTrueMaster, SetState, m_PBest);
  } else {
    OP_EXE_OR_SP_MIR_SATURN(mSaturn, hTrueMaster, SetState, m_P[0]);    
  }
}

/**************************************************************************/
// protected

 void WarmAmoeba::InitZStuff()
{
  m_Psum.ResizeTo(m_n);
  delete [] m_P;
  m_P = new TVectorF[m_n+1];
  for(Int_t i=0; i<=m_n; i++) (m_P[i]).ResizeTo(m_n);
  m_Y.ResizeTo(m_n+1);
  m_PBest.ResizeTo(m_n);
}

 Float_t WarmAmoeba::Ooze(Int_t ihi, Float_t& yhi, Float_t fac)
{
  TVectorF ptry(m_n);
  Float_t fac1 = (1-fac)/m_n;
  Float_t fac2 = fac1 - fac;
  for(Int_t j=0; j<m_n; j++) { ptry(j) = m_Psum(j)*fac1 - P(ihi,j)*fac2; }
  Float_t ytry = hTrueMaster->Foon(ptry);
  if(ytry <= m_y_best) {
    m_PBest = ptry;
    m_y_best = ytry;
  }
  Float_t yflu = ytry + m_T*TMath::Log(mRanGen.Rndm());
  if(yflu  < yhi) {
    m_Y(ihi) = ytry; yhi = yflu;
    for(Int_t j=0; j<m_n; j++) {
      m_Psum(j) += ptry(j) - P(ihi,j);
      P(ihi,j) = ptry(j);
    }
  }
  return yflu;
}

 void WarmAmoeba::WAMove()
{
  Float_t ynhi, ylo, yhi, yt;
  _calc_psum();
  while(1) {
    Int_t ilo=0, ihi=1;
    ynhi = ylo = m_Y(0u) - m_T*TMath::Log(mRanGen.Rndm());
    yhi = m_Y(1u) - m_T*TMath::Log(mRanGen.Rndm());
    if(ylo > yhi) { ihi=0; ilo=1; ynhi=yhi; yhi=ylo; ylo=ynhi; }
    for(Int_t i=2; i<=m_n; i++) {
      yt = m_Y(i) - m_T*TMath::Log(mRanGen.Rndm());
      if(yt <= ylo) { ilo=i; ylo = yt; }
      if(yt > yhi) { ynhi=yhi; ihi=i; yhi=yt; }
      else { ynhi = yt; }
    }
    Float_t rtol = 2*TMath::Abs(yhi-ylo) / (TMath::Abs(yhi) + TMath::Abs(ylo));
    if(rtol < mFTol || m_iter<0) {
      Float_t swap=m_Y(0u); m_Y(0u)=m_Y(ilo); m_Y(ilo)=swap;
      for(Int_t n=0; n<m_n; n++) {
	swap=P(0u,n); P(0u,n)=P(ilo,n); P(ilo,n)=swap;
      }
      break;
    }
    m_iter -= 2;
    Float_t ytry = Ooze(ihi, yhi, -1);
    if(ytry <= ylo) {
      ytry = Ooze(ihi, yhi, 2);
    } else if(ytry >- ynhi) {
      Float_t ysave = yhi;
      ytry = Ooze(ihi, yhi, 0.5);
      if(ytry >= ysave) {
	for(Int_t i=0; i<m_n; i++) {
	  if(i!=ilo) {
	    for(Int_t j=0; j<m_n; j++) {
	      m_Psum(j) = 0.5*(P(i,j) + P(ilo,j));
	      P(i,j) = m_Psum(j);
	    }
	    m_Y(i) = hTrueMaster->Foon(m_Psum);
	  }
	}
	m_iter -= m_n;
	_calc_psum();
      }
    } else { m_iter++; }
  }
}

/**************************************************************************/
// public
/**************************************************************************/

 WarmAmoeba::WarmAmoeba(const Text_t* n, const Text_t* t) :
  Eventor(n,t), mWA_Master(0), mRanGen(0)
{ _init(); }

 WarmAmoeba::WarmAmoeba(ZGlass* m, const Text_t* n, const Text_t* t) :
  Eventor(n,t), mWA_Master(m), mRanGen(0)
{ _init(); }

 WarmAmoeba::~WarmAmoeba()
{
  delete [] m_P;
}

/**************************************************************************/
/**************************************************************************/

 Operator::Arg* WarmAmoeba::PreDance(Operator::Arg* op_arg)
{
  op_arg = Eventor::PreDance(op_arg);

  hTrueMaster = dynamic_cast<WarmAmoebaMaster*>(mWA_Master);
  if(!hTrueMaster) {
    ISerr("WarmAmoeba::PreDance master not a WarmAmoebaMaster");
    delete op_arg;
    return 0;
  }
  mRanGen.SetSeed(mSeed);
  { // Init state
    TVectorF *v = hTrueMaster->InitialState(mRanGen);
    if(v->GetNoElements() < 3) {
      ISerr("WarmAmoeba::PreDance Need at least 3 parameters for amoeba");
      delete op_arg;
      return 0;
    }
    m_n = v->GetNoElements();
    OP_EXE_OR_SP_MIR(this, SetN, m_n);
    InitZStuff();
    m_P[0] = *v; m_Y(0u) = hTrueMaster->Foon(m_P[0]);
    delete v;
  }
  { // Get perturbations
    TVectorF *v = hTrueMaster->InitialPerturbations(mRanGen);
    for(Int_t i=1; i<=m_n; i++) {
      m_P[i] = m_P[0]; P(i, i-1) += (*v)(i-1);
      m_Y(i) = hTrueMaster->Foon(m_P[i]);
    }
    delete v;
  }
  // Estimate temperature
  Float_t t=0;
  for(Int_t i=1; i<=m_n; i++) t += TMath::Abs(m_Y(0u) - m_Y(i));
  m_T = t/m_n;
  m_y_best = mYBest = 10*m_Y(0u); // Large enough
  mYLast = m_Y(0u);
  m_T0 = mTFactor * t/m_n;

  mLocBeatsDone = 0;
  OP_EXE_OR_SP_MIR(this, SetBeatsDone, 0);
  OP_EXE_OR_SP_MIR(this, SetBeatsToDo, mNumSteps);
  OP_EXE_OR_SP_MIR(this, SetT0, m_T0);
  _export_algo_values(op_arg);

  return Eventor::PreDance(op_arg);
}

 void WarmAmoeba::PostDance(Operator::Arg* op_arg)
{
  Eventor::PostDance(op_arg);
  _export_algo_values(op_arg, true);
}

/**************************************************************************/

 void WarmAmoeba::PostBeat(Operator::Arg* op_arg) throw(Operator::Exception)
{
  Eventor::PostBeat(op_arg);
  if(mStampInterval == 0 || mLocBeatsDone % mStampInterval == 0) {
      _export_algo_values(op_arg);
  }
}

/**************************************************************************/

 void WarmAmoeba::Operate(Operator::Arg* op_arg) throw(Operator::Exception)
{
  Eventor::PreOperate(op_arg);

  m_T = m_T0*TMath::Power(1 - (Float_t)mLocBeatsDone/(mBeatsToDo-1), mAlpha);
  m_iter = mMovesPerT;
  WAMove();

  Eventor::PostOperate(op_arg);
}

/**************************************************************************/

#include "WarmAmoeba.c7"


ROOT page - Home page - Class index - Class Hierarchy - Top of the page

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.