1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
|
/* ObjCryst++ Object-Oriented Crystallographic Library
(c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net
2000-2001 University of Geneva (Switzerland)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* Simplex.cpp
* source file for Conjugate Gradient Algorithm object
*
*/
#include "ObjCryst/RefinableObj/Simplex.h"
#include "ObjCryst/Quirks/VFNStreamFormat.h"
namespace ObjCryst
{
SimplexObj::SimplexObj(const string name):
OptimizationObj(name)
{
}
void SimplexObj::Optimize(long &nbSteps,const bool silent,const REAL finalcost,
const REAL maxTime)
{
VFN_DEBUG_ENTRY("SimplexObj::Optimize()",10)
for(int i=0;i<mRefinedObjList.GetNb();i++) mRefinedObjList.GetObj(i).BeginOptimization(true);
this->PrepareRefParList();
const unsigned long n=mRefParList.GetNbParNotFixed();
// Create the n+1 set of parameters (n+1 vertices for the initial simplex)
// To obtain the n new vertices we just move from the starting point
// by the amount of the declared global optimization step.
CrystVector_long vIndex(n+1);
vIndex(0)=mRefParList.CreateParamSet();
CrystVector_REAL vLLK(n+1);
vLLK(0)=this->GetLogLikelihood();
for(unsigned long i=0;i<n;i++)
{
vIndex(0)=mRefParList.CreateParamSet();
mRefParList.GetParNotFixed(i).
Mutate(mRefParList.GetParNotFixed(i).GetGlobalOptimStep()*100.0);
vIndex(i+1)=mRefParList.CreateParamSet();
vLLK(i+1)=this->GetLogLikelihood();
mRefParList.RestoreParamSet(vIndex(0));
}
unsigned long best=0,worst=0,nextworst=0;
for(;nbSteps>=0;--nbSteps)
{
// determine best, worst and next worst points
if(vLLK(0)>vLLK(1)){worst=0;nextworst=1;}
else{worst=1;nextworst=0;}
for(unsigned long i=1;i<=n;i++)
{
if(vLLK(i)<=vLLK(best)) best =i;
if(vLLK(i)>vLLK(worst))
{
nextworst=worst;
worst=i;
}
else if((vLLK(i)>vLLK(nextworst)) && (i!=worst)) nextworst=i;
}
{
CrystVector_REAL center(n);
center = 0.0;
for(unsigned long i=0;i<=n;i++)
{
if(i==worst) continue;
center += mRefParList.GetParamSet(vIndex(i));
}
center /= (REAL)n;
CrystVector_REAL worstdiff;
worstdiff=mRefParList.GetParamSet(vIndex(worst));
worstdiff-=center;
for(unsigned long i=0;i<n;i++) worstdiff(i)/=mRefParList.GetParNotFixed(i).GetGlobalOptimStep();
if(!silent && (nbSteps%100==0)) cout<<"Simplex:cycle="<<nbSteps<<", cost="<<vLLK(best)
<<",best="<<best<<",worst="<<worst<<",nextworst="<<nextworst
<<", Worst diff="<<abs(worstdiff.min())+abs(worstdiff.max())<<endl;
if((abs(worstdiff.min())+abs(worstdiff.max()))<0.01) break;
}
#if 0
cout<<FormatHorizVector<REAL>(vLLK)<<endl;
cout<<FormatVertVector<REAL>(mRefParList.GetParamSet(vIndex(best)),
mRefParList.GetParamSet(vIndex(worst)),
mRefParList.GetParamSet(vIndex(nextworst)),
mRefParList.GetParamSet(vIndex(6)),
mRefParList.GetParamSet(vIndex(8)),
mRefParList.GetParamSet(vIndex(10)))<<endl;
#endif
mRefParList.RestoreParamSet(vIndex(best));
REAL llktry=this->GenerateNewSimplexConfiguration(vLLK,vIndex,worst,-1.0);
if(llktry<=vLLK(best))
llktry=this->GenerateNewSimplexConfiguration(vLLK,vIndex,worst,2.0);
else if(llktry>=vLLK(nextworst))
{
const REAL llksave=vLLK(worst);
llktry=this->GenerateNewSimplexConfiguration(vLLK,vIndex,worst,0.5);
if(llktry>=llksave)
{
CrystVector_REAL *p0=&(mRefParList.GetParamSet(vIndex(best)));
for(unsigned long i=0;i<=n;i++)
{
if(i==best) continue;
CrystVector_REAL *pi=&(mRefParList.GetParamSet(vIndex(i)));
for(unsigned long j=0;j<n;j++)
{(*pi)(j) = 0.5*((*p0)(j) + (*pi)(j));}
mRefParList.RestoreParamSet(vIndex(i));
vLLK(i)=this->GetLogLikelihood();
}
}
}
}
mRefParList.RestoreParamSet(vIndex(best));
mRefParList.EraseAllParamSet();
for(int i=0;i<mRefinedObjList.GetNb();i++) mRefinedObjList.GetObj(i).EndOptimization();
VFN_DEBUG_EXIT("SimplexObj::Optimize()",10)
}
void SimplexObj::MultiRunOptimize(long &nbCycle,long &nbSteps,const bool silent,
const REAL finalcost,const REAL maxTime)
{
const long nbStep0=nbSteps;
while(nbCycle--!=0)
{
if(!silent) cout <<"SimplexObj::MultiRunOptimize: Starting Run#"<<abs(float(nbCycle))<<endl;
nbSteps=nbStep0;
this->Optimize(nbSteps,silent,finalcost,maxTime);
if(!silent) cout <<"SimplexObj::MultiRunOptimize: Finished Run#"<<abs(float(nbCycle))<<endl;
}
}
void SimplexObj::XMLOutput(ostream &os,int indent)const
{
}
void SimplexObj::XMLInput(istream &is,const XMLCrystTag &tag)
{
}
REAL SimplexObj::GenerateNewSimplexConfiguration(CrystVector_REAL &vLLK,
CrystVector_long &vIndex,
unsigned long worst,
REAL f)
{
// Compute center of vertices
const unsigned long n=mRefParList.GetNbParNotFixed();
const unsigned long iworst=vIndex(worst);
CrystVector_REAL center(n);
center = 0.0;
for(unsigned long i=0;i<=n;i++)
{
if(i==worst) continue;
center += mRefParList.GetParamSet(vIndex(i));
}
center /= (REAL)n;
for(unsigned long i=0;i<n;i++)
{
mRefParList.GetParNotFixed(i)
.MutateTo(center(i)+f*(mRefParList.GetParamSet(iworst)(i)-center(i)));
}
const REAL llk=this->GetLogLikelihood();
//cout<<"New,f="<<f<<",worst="<<worst<<":"<<llk<<endl;
if(llk<vLLK(worst))
{
vLLK(worst)=llk;
mRefParList.SaveParamSet(iworst);
}
return llk;
}
#ifdef __WX__CRYST__
WXCrystObjBasic* SimplexObj::WXCreate(wxWindow*)
{
return NULL;
}
WXOptimizationObj* SimplexObj::WXGet()
{
return NULL;
}
void SimplexObj::WXDelete(){}
void SimplexObj::WXNotifyDelete(){}
#endif
}//namespace
|