FOX/ObjCryst++  2022
GlobalOptimObj.cpp
1 /* ObjCryst++ Object-Oriented Crystallographic Library
2  (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net
3  2000-2001 University of Geneva (Switzerland)
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19 /*
20 * source file for Global Optimization Objects
21 *
22 */
23 #include <iomanip>
24 
25 #include "ObjCryst/RefinableObj/GlobalOptimObj.h"
26 #include "ObjCryst/ObjCryst/Crystal.h"
27 #include "ObjCryst/Quirks/VFNStreamFormat.h"
28 #include "ObjCryst/Quirks/VFNDebug.h"
29 #include "ObjCryst/Quirks/Chronometer.h"
30 #include "ObjCryst/ObjCryst/IO.h"
31 #include "ObjCryst/RefinableObj/LSQNumObj.h"
32 
33 #include "ObjCryst/ObjCryst/Molecule.h"
34 
35 #ifdef __WX__CRYST__
36  #include "ObjCryst/wxCryst/wxRefinableObj.h"
37  #undef GetClassName // Conflict from wxMSW headers ? (cygwin)
38 #endif
39 
40 //For some reason, with wxWindows this must be placed after wx headers (Borland c++)
41 #include <fstream>
42 #include <sstream>
43 #include <stdio.h>
44 #include <boost/format.hpp>
45 
46 namespace ObjCryst
47 {
48 void CompareWorlds(const CrystVector_long &idx,const CrystVector_long &swap, const RefinableObj &obj)
49 {
50  const long nb=swap.numElements();
51  const CrystVector_REAL *pv0=&(obj.GetParamSet(idx(swap(nb-1))));
52  for(long i=0;i<idx.numElements();++i)
53  {
54  REAL d=0.0;
55  const CrystVector_REAL *pv1=&(obj.GetParamSet(idx(swap(i))));
56  for(long j=0;j<pv0->numElements();++j) d += ((*pv0)(j)-(*pv1)(j))*((*pv0)(j)-(*pv1)(j));
57  cout<<"d("<<i<<")="<<sqrt(d)<<endl;
58  }
59  cout<<endl;
60 }
61 //#################################################################################
62 //
63 // OptimizationObj
64 //
65 //#################################################################################
66 ObjRegistry<OptimizationObj> gOptimizationObjRegistry("List of all Optimization objects");
67 
69 mName(""),mSaveFileName("GlobalOptim.save"),
70 mNbTrialPerRun(10000000),mNbTrial(0),mRun(0),mBestCost(-1),
71 mBestParSavedSetIndex(-1),
72 mContext(0),
73 mIsOptimizing(false),mStopAfterCycle(false),
74 mRefinedObjList("OptimizationObj: "+mName+" RefinableObj registry"),
75 mRecursiveRefinedObjList("OptimizationObj: "+mName+" recursive RefinableObj registry"),
76 mLastOptimTime(0)
77 {
78  VFN_DEBUG_ENTRY("OptimizationObj::OptimizationObj()",5)
79  // This must be done in a real class to avoid calling a pure virtual method
80  // if a graphical representation is automatically called upon registration.
81  // gOptimizationObjRegistry.Register(*this);
82 
83  static bool need_initRandomSeed=true;
84  if(need_initRandomSeed==true)
85  {
86  srand(time(NULL));
87  need_initRandomSeed=false;
88  }
89  // We only copy parameters, so do not delete them !
91  VFN_DEBUG_EXIT("OptimizationObj::OptimizationObj()",5)
92 }
93 
95 mName(name),mSaveFileName("GlobalOptim.save"),
96 mNbTrialPerRun(10000000),mNbTrial(0),mRun(0),mBestCost(-1),
97 mBestParSavedSetIndex(-1),
98 mContext(0),
99 mIsOptimizing(false),mStopAfterCycle(false),
100 mRefinedObjList("OptimizationObj: "+mName+" RefinableObj registry"),
101 mRecursiveRefinedObjList("OptimizationObj: "+mName+" recursive RefinableObj registry"),
102 mLastOptimTime(0)
103 {
104  VFN_DEBUG_ENTRY("OptimizationObj::OptimizationObj()",5)
105  // This must be done in a real class to avoid calling a pure virtual method
106  // if a graphical representation is automatically called upon registration.
107  // gOptimizationObjRegistry.Register(*this);
108 
109  static bool need_initRandomSeed=true;
110  if(need_initRandomSeed==true)
111  {
112  srand(time(NULL));
113  need_initRandomSeed=false;
114  }
115  // We only copy parameters, so do not delete them !
117  VFN_DEBUG_EXIT("OptimizationObj::OptimizationObj()",5)
118 }
119 
121 mName(old.mName),mSaveFileName(old.mSaveFileName),
122 mNbTrialPerRun(old.mNbTrialPerRun),mNbTrial(old.mNbTrial),mRun(old.mRun),mBestCost(old.mBestCost),
123 mBestParSavedSetIndex(-1),
124 mContext(0),
125 mIsOptimizing(false),mStopAfterCycle(false),
126 mRefinedObjList("OptimizationObj: "+mName+" RefinableObj registry"),
127 mRecursiveRefinedObjList("OptimizationObj: "+mName+" recursive RefinableObj registry"),
128 mLastOptimTime(0)
129 {
130  VFN_DEBUG_ENTRY("OptimizationObj::OptimizationObj(&old)",5)
131  // This must be done in a real class to avoid calling a pure virtual method
132  // if a graphical representation is automatically called upon registration.
133  // gOptimizationObjRegistry.Register(*this);
134 
135  static bool need_initRandomSeed=true;
136  if(need_initRandomSeed==true)
137  {
138  srand(time(NULL));
139  need_initRandomSeed=false;
140  }
141  // We only copy parameters, so do not delete them !
143 
144  for(unsigned int i=0;i<old.mRefinedObjList.GetNb();i++)
145  this->AddRefinableObj(old.mRefinedObjList.GetObj(i));
146 
147  VFN_DEBUG_EXIT("OptimizationObj::OptimizationObj(&old)",5)
148 }
149 
151 {
152  VFN_DEBUG_ENTRY("OptimizationObj::~OptimizationObj()",5)
153  gOptimizationObjRegistry.DeRegister(*this);
154  VFN_DEBUG_EXIT("OptimizationObj::~OptimizationObj()",5)
155 }
156 
158 {
159  VFN_DEBUG_ENTRY("OptimizationObj::RandomizeStartingConfig()",5)
160  this->PrepareRefParList();
161  for(int j=0;j<mRefParList.GetNbParNotFixed();j++)
162  {
163  if(true==mRefParList.GetParNotFixed(j).IsLimited())
164  {
165  const REAL min=mRefParList.GetParNotFixed(j).GetMin();
166  const REAL max=mRefParList.GetParNotFixed(j).GetMax();
167  mRefParList.GetParNotFixed(j).MutateTo(min+(max-min)*(rand()/(REAL)RAND_MAX) );
168  }
169  else if(true==mRefParList.GetParNotFixed(j).IsPeriodic())
171  Mutate(mRefParList.GetParNotFixed(j).GetPeriod()*rand()/(REAL)RAND_MAX);
172  }
173  //else cout << mRefParList.GetParNotFixed(j).Name() <<" Not limited :-(" <<endl;
174  VFN_DEBUG_EXIT("OptimizationObj::RandomizeStartingConfig()",5)
175 }
176 
178 {
179  VFN_DEBUG_ENTRY("OptimizationObj::FixAllPar()",5)
180  this->BuildRecursiveRefObjList();
181  for(int i=0;i<mRecursiveRefinedObjList.GetNb();i++)
182  mRecursiveRefinedObjList.GetObj(i).FixAllPar();
183  VFN_DEBUG_EXIT("OptimizationObj::FixAllPar():End",5)
184 }
185 void OptimizationObj::SetParIsFixed(const string& parName,const bool fix)
186 {
187  this->BuildRecursiveRefObjList();
188  for(int i=0;i<mRecursiveRefinedObjList.GetNb();i++)
189  mRecursiveRefinedObjList.GetObj(i).SetParIsFixed(parName,fix);
190 }
191 void OptimizationObj::SetParIsFixed(const RefParType *type,const bool fix)
192 {
193  this->BuildRecursiveRefObjList();
194  for(int i=0;i<mRecursiveRefinedObjList.GetNb();i++)
195  mRecursiveRefinedObjList.GetObj(i).SetParIsFixed(type,fix);
196 }
197 
199 {
200  this->BuildRecursiveRefObjList();
201  for(int i=0;i<mRecursiveRefinedObjList.GetNb();i++)
202  mRecursiveRefinedObjList.GetObj(i).UnFixAllPar();
203 }
204 
205 void OptimizationObj::SetParIsUsed(const string& parName,const bool use)
206 {
207  this->BuildRecursiveRefObjList();
208  for(int i=0;i<mRecursiveRefinedObjList.GetNb();i++)
209  mRecursiveRefinedObjList.GetObj(i).SetParIsUsed(parName,use);
210 }
211 void OptimizationObj::SetParIsUsed(const RefParType *type,const bool use)
212 {
213  this->BuildRecursiveRefObjList();
214  for(int i=0;i<mRecursiveRefinedObjList.GetNb();i++)
215  mRecursiveRefinedObjList.GetObj(i).SetParIsUsed(type,use);
216 }
217 void OptimizationObj::SetLimitsRelative(const string &parName,
218  const REAL min, const REAL max)
219 {
220  this->BuildRecursiveRefObjList();
221  for(int i=0;i<mRecursiveRefinedObjList.GetNb();i++)
222  mRecursiveRefinedObjList.GetObj(i).SetLimitsRelative(parName,min,max);
223 }
225  const REAL min, const REAL max)
226 {
227  this->BuildRecursiveRefObjList();
228  for(int i=0;i<mRecursiveRefinedObjList.GetNb();i++)
229  mRecursiveRefinedObjList.GetObj(i).SetLimitsRelative(type,min,max);
230 }
231 void OptimizationObj::SetLimitsAbsolute(const string &parName,
232  const REAL min, const REAL max)
233 {
234  this->BuildRecursiveRefObjList();
235  for(int i=0;i<mRecursiveRefinedObjList.GetNb();i++)
236  mRecursiveRefinedObjList.GetObj(i).SetLimitsAbsolute(parName,min,max);
237 }
239  const REAL min, const REAL max)
240 {
241  this->BuildRecursiveRefObjList();
242  for(int i=0;i<mRecursiveRefinedObjList.GetNb();i++)
243  mRecursiveRefinedObjList.GetObj(i).SetLimitsAbsolute(type,min,max);
244 }
245 
247 {
248  TAU_PROFILE("OptimizationObj::GetLogLikelihood()","void ()",TAU_DEFAULT);
249  REAL cost =0.;
250  for(int i=0;i<mRecursiveRefinedObjList.GetNb();i++)
251  {
252  const REAL tmp=mRecursiveRefinedObjList.GetObj(i).GetLogLikelihood();
253  if(tmp!=0.)
254  {
256  [&(mRecursiveRefinedObjList.GetObj(i))]);
257  st->mTotalLogLikelihood += tmp;
259  (tmp-st->mLastLogLikelihood)*(tmp-st->mLastLogLikelihood);
260  st->mLastLogLikelihood=tmp;
261  }
262  cost += mvObjWeight[&(mRecursiveRefinedObjList.GetObj(i))].mWeight * tmp;
263  }
264  return cost;
265 }
267 {
268  VFN_DEBUG_MESSAGE("OptimizationObj::StopAfterCycle()",5)
269  if(mIsOptimizing)
270  {
271  #ifdef __WX__CRYST__
272  wxMutexLocker lock(mMutexStopAfterCycle);
273  #endif
274  mStopAfterCycle=true;
275  }
276 }
277 
279 {
280  //:TODO: ask all objects to print their own report ?
281 }
282 
284 {
285  VFN_DEBUG_MESSAGE("OptimizationObj::AddRefinableObj():"<<obj.GetName(),5)
286  //in case some object has been modified, to avoid rebuilding the entire list
287  this->BuildRecursiveRefObjList();
288 
289  mRefinedObjList.Register(obj);
291  #ifdef __WX__CRYST__
292  if(0!=this->WXGet()) this->WXGet()->AddRefinedObject(obj);
293  #endif
294 }
295 
297 {
298  if(rebuild) this->PrepareRefParList();
299  return mRefParList;
300 }
301 
302 const string& OptimizationObj::GetName()const { return mName;}
303 void OptimizationObj::SetName(const string& name) {mName=name;}
304 
305 const string OptimizationObj::GetClassName()const { return "OptimizationObj";}
306 
307 void OptimizationObj::Print()const {this->XMLOutput(cout);}
308 
310 {
311  //:TODO: check list of refinableObj has not changed, and the list of
312  // RefPar has not changed in all sub-objects.
314 }
315 
317 
319 {
320  for(int i=0;i<mRecursiveRefinedObjList.GetNb();i++)
321  mRecursiveRefinedObjList.GetObj(i).TagNewBestConfig();
322  mMainTracker.AppendValues(mNbTrial);
323 }
324 
326 {
327  return mLastOptimTime;
328 }
329 
331 
333 
334 RefObjOpt& OptimizationObj::GetXMLAutoSaveOption() {return mXMLAutoSave;}
335 const RefObjOpt& OptimizationObj::GetXMLAutoSaveOption()const {return mXMLAutoSave;}
336 
337 const REAL& OptimizationObj::GetBestCost()const{return mBestCost;}
339 
340 void OptimizationObj::BeginOptimization(const bool allowApproximations, const bool enableRestraints)
341 {
342  mvContextObjStats.clear();
343  for(int i=0;i<mRefinedObjList.GetNb();i++)
344  {
345  mRefinedObjList.GetObj(i).BeginOptimization(allowApproximations,enableRestraints);
346  }
347 }
348 
350 {
351  for(int i=0;i<mRefinedObjList.GetNb();i++) mRefinedObjList.GetObj(i).EndOptimization();
352 }
353 
355 
356 const long& OptimizationObj::NbTrialPerRun() const {return mNbTrialPerRun;}
357 
358 long OptimizationObj::GetTrial() const {return mNbTrial;}
359 
360 long OptimizationObj::GetRun() const {return mRun;}
361 
362 unsigned int OptimizationObj::GetNbOption()const
363 {
364  return mOptionRegistry.GetNb();
365 }
366 
368 {
369  return mOptionRegistry;
370 }
371 
372 RefObjOpt& OptimizationObj::GetOption(const unsigned int i)
373 {
374  VFN_DEBUG_MESSAGE("RefinableObj::GetOption()"<<i,3)
375  //:TODO: Check
376  return mOptionRegistry.GetObj(i);
377 }
378 
380 {
381  VFN_DEBUG_MESSAGE("OptimizationObj::GetOption()"<<name,3)
382  const long i=mOptionRegistry.Find(name);
383  if(i<0)
384  {
385  this->Print();
386  throw ObjCrystException("OptimizationObj::GetOption(): cannot find option: "+name+" in object:"+this->GetName());
387  }
388  return mOptionRegistry.GetObj(i);
389 }
390 
391 const RefObjOpt& OptimizationObj::GetOption(const unsigned int i)const
392 {
393  VFN_DEBUG_MESSAGE("RefinableObj::GetOption()"<<i,3)
394  //:TODO: Check
395  return mOptionRegistry.GetObj(i);
396 }
397 
398 const RefObjOpt& OptimizationObj::GetOption(const string & name)const
399 {
400  VFN_DEBUG_MESSAGE("OptimizationObj::GetOption()"<<name,3)
401  const long i=mOptionRegistry.Find(name);
402  if(i<0)
403  {
404  this->Print();
405  throw ObjCrystException("OptimizationObj::GetOption(): cannot find option: "+name+" in object:"+this->GetName());
406  }
407  return mOptionRegistry.GetObj(i);
408 }
409 
411 {
412  return mRefinedObjList;
413 }
414 
415 unsigned int OptimizationObj::GetNbParamSet() const
416 {
417  return mvSavedParamSet.size();
418 }
419 
420 long OptimizationObj::GetParamSetIndex(const unsigned int i) const
421 {
422  if(i>=mvSavedParamSet.size())
423  throw ObjCrystException("OptimizationObj::GetSavedParamSetIndex(i): i > nb saved param set");
424 
425  return mvSavedParamSet[i].first;
426 }
427 
428 long OptimizationObj::GetParamSetCost(const unsigned int i) const
429 {
430  if(i>=mvSavedParamSet.size())
431  throw ObjCrystException("OptimizationObj::GetSavedParamSetCost(i): i > nb saved param set");
432  return mvSavedParamSet[i].second;
433 }
434 
435 void OptimizationObj::RestoreParamSet(const unsigned int i, const bool update_display)
436 {
438  if(update_display) this->UpdateDisplay();
439 }
440 
442 {
443  VFN_DEBUG_ENTRY("OptimizationObj::PrepareRefParList()",6)
444 
445  this->BuildRecursiveRefObjList();
446  // As any parameter been added in the recursive list of objects ?
447  // or has any object been added/removed ?
448  RefinableObjClock clock;
450  if( (clock>mRefParList.GetRefParListClock())
451  ||(mRecursiveRefinedObjList.GetRegistryClock()>mRefParList.GetRefParListClock()) )
452  {
453  VFN_DEBUG_MESSAGE("OptimizationObj::PrepareRefParList():Rebuild list",6)
456  for(int i=0;i<mRecursiveRefinedObjList.GetNb();i++)
458  mvSavedParamSet.clear();
459  mBestParSavedSetIndex=mRefParList.CreateParamSet("Best Configuration");
460  mvSavedParamSet.push_back(make_pair(mBestParSavedSetIndex,mBestCost));
461 
463 
464  REAL (OptimizationObj::*fl)() const;
467  (this->GetName()+"::Overall LogLikelihood",*this,fl));
468 
469  for(long i=0;i<mRecursiveRefinedObjList.GetNb();i++)
470  {
471  REAL (RefinableObj::*fp)() const;
474  (mRecursiveRefinedObjList.GetObj(i).GetName()+"::LogLikelihood",mRecursiveRefinedObjList.GetObj(i),fp));
475 
476  if(mRecursiveRefinedObjList.GetObj(i).GetClassName()=="Crystal")
477  {
478  REAL (Crystal::*fc)() const;
479  const Crystal *pCryst=dynamic_cast<const Crystal *>(&(mRecursiveRefinedObjList.GetObj(i)));
481  mMainTracker.AddTracker(new TrackerObject<Crystal>
482  (pCryst->GetName()+"::BumpMergeCost",*pCryst,fc));
484  mMainTracker.AddTracker(new TrackerObject<Crystal>
485  (pCryst->GetName()+"::BondValenceCost",*pCryst,fc));
486 
487  fc=&Crystal::GetInterMolDistCost;
488  mMainTracker.AddTracker(new TrackerObject<Crystal>
489  (pCryst->GetName()+"::InterMolDistCost",*pCryst,fc));
490  }
491  }
492  }
493  // Prepare for refinement, ie get the list of not fixed parameters,
494  // and prepare the objects...
496  for(int i=0;i<mRecursiveRefinedObjList.GetNb();i++)
497  mRecursiveRefinedObjList.GetObj(i).PrepareForRefinement();
498  VFN_DEBUG_EXIT("OptimizationObj::PrepareRefParList()",6)
499 }
500 
502 {
503  VFN_DEBUG_MESSAGE("OptimizationObj::InitOptions()",5)
504  static string xmlAutoSaveName;
505  static string xmlAutoSaveChoices[6];
506 
507  static bool needInitNames=true;
508  if(true==needInitNames)
509  {
510  xmlAutoSaveName="Save Best Config Regularly";
511  xmlAutoSaveChoices[0]="No";
512  xmlAutoSaveChoices[1]="Every day";
513  xmlAutoSaveChoices[2]="Every hour";
514  xmlAutoSaveChoices[3]="Every 10mn";
515  xmlAutoSaveChoices[4]="Every new best config (a lot ! Not Recommended !)";
516  xmlAutoSaveChoices[5]="Every Run (Recommended)";
517 
518  needInitNames=false;//Only once for the class
519  }
520  mXMLAutoSave.Init(6,&xmlAutoSaveName,xmlAutoSaveChoices);
521  this->AddOption(&mXMLAutoSave);
522  VFN_DEBUG_MESSAGE("OptimizationObj::InitOptions():End",5)
523 }
524 
526 {
527  Chronometer chrono;
528  for(int i=0;i<mRefinedObjList.GetNb();i++)
529  mRefinedObjList.GetObj(i).UpdateDisplay();
531 }
532 
534 {
535  // First check if anything has changed (ie if a sub-object has been
536  // added or removed in the recursive refinable object list)
537  RefinableObjClock clock;
539  if(clock>mRecursiveRefinedObjList.GetRegistryClock())
540  {
541  VFN_DEBUG_ENTRY("OptimizationObj::BuildRecursiveRefObjList()",5)
542  mRecursiveRefinedObjList.DeRegisterAll();
543  for(int i=0;i<mRefinedObjList.GetNb();i++)
545  VFN_DEBUG_EXIT("OptimizationObj::BuildRecursiveRefObjList()",5)
546  }
547 }
548 
550 {
551  VFN_DEBUG_ENTRY("OptimizationObj::AddOption()",5)
552  mOptionRegistry.Register(*opt);
553  VFN_DEBUG_EXIT("OptimizationObj::AddOption()",5)
554 }
555 
556 //#################################################################################
557 //
558 // MonteCarloObj
559 //
560 //#################################################################################
562 OptimizationObj(""),
563 mCurrentCost(-1),
564 mTemperatureMax(1e6),mTemperatureMin(.001),mTemperatureGamma(1.0),
565 mMutationAmplitudeMax(8.),mMutationAmplitudeMin(.125),mMutationAmplitudeGamma(1.0),
566 mNbTrialRetry(0),mMinCostRetry(0)
567 #ifdef __WX__CRYST__
568 ,mpWXCrystObj(0)
569 #endif
570 {
571  VFN_DEBUG_ENTRY("MonteCarloObj::MonteCarloObj()",5)
572  this->InitOptions();
573  mGlobalOptimType.SetChoice(GLOBAL_OPTIM_PARALLEL_TEMPERING);
574  mAnnealingScheduleTemp.SetChoice(ANNEALING_SMART);
575  mAnnealingScheduleMutation.SetChoice(ANNEALING_EXPONENTIAL);
576  mXMLAutoSave.SetChoice(5);//Save after each Run
577  mAutoLSQ.SetChoice(0);
578  gOptimizationObjRegistry.Register(*this);
579  VFN_DEBUG_EXIT("MonteCarloObj::MonteCarloObj()",5)
580 }
581 
582 MonteCarloObj::MonteCarloObj(const string name):
583 OptimizationObj(name),
584 mCurrentCost(-1),
585 mTemperatureMax(1e6),mTemperatureMin(.001),mTemperatureGamma(1.0),
586 mMutationAmplitudeMax(8.),mMutationAmplitudeMin(.125),mMutationAmplitudeGamma(1.0),
587 mNbTrialRetry(0),mMinCostRetry(0)
588 #ifdef __WX__CRYST__
589 ,mpWXCrystObj(0)
590 #endif
591 {
592  VFN_DEBUG_ENTRY("MonteCarloObj::MonteCarloObj()",5)
593  this->InitOptions();
594  mGlobalOptimType.SetChoice(GLOBAL_OPTIM_PARALLEL_TEMPERING);
595  mAnnealingScheduleTemp.SetChoice(ANNEALING_SMART);
596  mAnnealingScheduleMutation.SetChoice(ANNEALING_EXPONENTIAL);
597  mXMLAutoSave.SetChoice(5);//Save after each Run
598  mAutoLSQ.SetChoice(0);
599  gOptimizationObjRegistry.Register(*this);
600  VFN_DEBUG_EXIT("MonteCarloObj::MonteCarloObj()",5)
601 }
602 
604 OptimizationObj(old),
605 mCurrentCost(old.mCurrentCost),
606 mTemperatureMax(old.mTemperatureMax),mTemperatureMin(old.mTemperatureMin),
607 mTemperatureGamma(old.mTemperatureGamma),
608 mMutationAmplitudeMax(old.mMutationAmplitudeMax),mMutationAmplitudeMin(old.mMutationAmplitudeMin),
609 mMutationAmplitudeGamma(old.mMutationAmplitudeGamma),
610 mNbTrialRetry(old.mNbTrialRetry),mMinCostRetry(old.mMinCostRetry)
611 #ifdef __WX__CRYST__
612 ,mpWXCrystObj(0)
613 #endif
614 {
615  VFN_DEBUG_ENTRY("MonteCarloObj::MonteCarloObj(&old)",5)
616  this->InitOptions();
617  for(unsigned int i=0;i<this->GetNbOption();i++)
618  this->GetOption(i).SetChoice(old.GetOption(i).GetChoice());
619 
620  gOptimizationObjRegistry.Register(*this);
621  VFN_DEBUG_EXIT("MonteCarloObj::MonteCarloObj(&old)",5)
622 }
623 
624 MonteCarloObj::MonteCarloObj(const bool internalUseOnly):
625 OptimizationObj(""),
626 mCurrentCost(-1),
627 mTemperatureMax(.03),mTemperatureMin(.003),mTemperatureGamma(1.0),
628 mMutationAmplitudeMax(16.),mMutationAmplitudeMin(.125),mMutationAmplitudeGamma(1.0),
629 mNbTrialRetry(0),mMinCostRetry(0)
630 #ifdef __WX__CRYST__
631 ,mpWXCrystObj(0)
632 #endif
633 {
634  VFN_DEBUG_ENTRY("MonteCarloObj::MonteCarloObj(bool)",5)
635  this->InitOptions();
636  mGlobalOptimType.SetChoice(GLOBAL_OPTIM_PARALLEL_TEMPERING);
637  mAnnealingScheduleTemp.SetChoice(ANNEALING_SMART);
638  mAnnealingScheduleMutation.SetChoice(ANNEALING_EXPONENTIAL);
639  mXMLAutoSave.SetChoice(5);//Save after each Run
640  mAutoLSQ.SetChoice(0);
641  if(false==internalUseOnly) gOptimizationObjRegistry.Register(*this);
642  VFN_DEBUG_EXIT("MonteCarloObj::MonteCarloObj(bool)",5)
643 }
644 
646 {
647  VFN_DEBUG_ENTRY("MonteCarloObj::~MonteCarloObj()",5)
648  gOptimizationObjRegistry.DeRegister(*this);
649  VFN_DEBUG_EXIT ("MonteCarloObj::~MonteCarloObj()",5)
650 }
652  const REAL tMax, const REAL tMin,
653  const AnnealingSchedule scheduleMutation,
654  const REAL mutMax, const REAL mutMin,
655  const long nbTrialRetry,const REAL minCostRetry)
656 {
657  VFN_DEBUG_MESSAGE("MonteCarloObj::SetAlgorithmSimulAnnealing()",5)
658  mGlobalOptimType.SetChoice(GLOBAL_OPTIM_SIMULATED_ANNEALING);
659  mTemperatureMax=tMax;
660  mTemperatureMin=tMin;
661  mAnnealingScheduleTemp.SetChoice(scheduleTemp);
662 
663 
664  mMutationAmplitudeMax=mutMax;
665  mMutationAmplitudeMin=mutMin;
666  mAnnealingScheduleMutation.SetChoice(scheduleMutation);
667  mNbTrialRetry=nbTrialRetry;
668  mMinCostRetry=minCostRetry;
669  VFN_DEBUG_MESSAGE("MonteCarloObj::SetAlgorithmSimulAnnealing():End",3)
670 }
671 
673  const REAL tMax, const REAL tMin,
674  const AnnealingSchedule scheduleMutation,
675  const REAL mutMax, const REAL mutMin)
676 {
677  VFN_DEBUG_MESSAGE("MonteCarloObj::SetAlgorithmParallTempering()",5)
678  mGlobalOptimType.SetChoice(GLOBAL_OPTIM_PARALLEL_TEMPERING);
679  mTemperatureMax=tMax;
680  mTemperatureMin=tMin;
681  mAnnealingScheduleTemp.SetChoice(scheduleTemp);
682 
683  mMutationAmplitudeMax=mutMax;
684  mMutationAmplitudeMin=mutMin;
685  mAnnealingScheduleMutation.SetChoice(scheduleMutation);
686  //mNbTrialRetry=nbTrialRetry;
687  //mMinCostRetry=minCostRetry;
688  VFN_DEBUG_MESSAGE("MonteCarloObj::SetAlgorithmParallTempering():End",3)
689 }
690 void MonteCarloObj::Optimize(long &nbStep,const bool silent,const REAL finalcost,
691  const REAL maxTime)
692 {
693  //:TODO: Other algorithms !
694  TAU_PROFILE("MonteCarloObj::Optimize()","void (long)",TAU_DEFAULT);
695  VFN_DEBUG_ENTRY("MonteCarloObj::Optimize()",5)
696  this->BeginOptimization(true);
697  this->PrepareRefParList();
698 
699  this->InitLSQ(false);
700 
701  mIsOptimizing=true;
706  // prepare all objects
707  this->TagNewBestConfig();
710  mvObjWeight.clear();
712  Chronometer chrono;
713  chrono.start();
714  switch(mGlobalOptimType.GetChoice())
715  {
716  case GLOBAL_OPTIM_SIMULATED_ANNEALING:
717  {
718  this->RunSimulatedAnnealing(nbStep,silent,finalcost,maxTime);
719  break;
720  }//case GLOBAL_OPTIM_SIMULATED_ANNEALING
721  case GLOBAL_OPTIM_PARALLEL_TEMPERING:
722  {
723  this->RunParallelTempering(nbStep,silent,finalcost,maxTime);
724  break;
725  }//case GLOBAL_OPTIM_PARALLEL_TEMPERING
726  case GLOBAL_OPTIM_RANDOM_LSQ: //:TODO:
727  {
728  long cycles = 1;
729  this->RunRandomLSQMethod(cycles);
730  break;
731  }//case GLOBAL_OPTIM_GENETIC
732  }
733  mIsOptimizing=false;
734  #ifdef __WX__CRYST__
735  mMutexStopAfterCycle.Lock();
736  #endif
737  mStopAfterCycle=false;
738  #ifdef __WX__CRYST__
739  mMutexStopAfterCycle.Unlock();
740  #endif
741 
743  this->EndOptimization();
744  (*fpObjCrystInformUser)((boost::format("Finished Optimization, final cost=%12.2f (dt=%.1fs)") % this->GetLogLikelihood() % chrono.seconds()).str());
745 
746  if(mSaveTrackedData.GetChoice()==1)
747  {
748  ofstream outTracker;
749  outTracker.imbue(std::locale::classic());
750  const string outTrackerName=this->GetName()+"-Tracker.dat";
751  outTracker.open(outTrackerName.c_str());
752  mMainTracker.SaveAll(outTracker);
753  outTracker.close();
754  }
755 
756  for(vector<pair<long,REAL> >::iterator pos=mvSavedParamSet.begin();pos!=mvSavedParamSet.end();++pos)
757  if(pos->first==mBestParSavedSetIndex)
758  {
759  if( (pos->second>mBestCost)
760  ||(pos->second<0))
761  {
762  pos->second=mBestCost;
763  break;
764  }
765  }
766 
767  this->UpdateDisplay();
768 
769  VFN_DEBUG_EXIT("MonteCarloObj::Optimize()",5)
770 }
771 void MonteCarloObj::MultiRunOptimize(long &nbCycle,long &nbStep,const bool silent,
772  const REAL finalcost,const REAL maxTime)
773 {
774  //:TODO: Other algorithms !
775  TAU_PROFILE("MonteCarloObj::MultiRunOptimize()","void (long)",TAU_DEFAULT);
776  VFN_DEBUG_ENTRY("MonteCarloObj::MultiRunOptimize()",5)
777  //Keep a copy of the total number of steps, and decrement nbStep
778  const long nbStep0=nbStep;
779  this->BeginOptimization(true);
780  this->PrepareRefParList();
781 
782  this->InitLSQ(false);
783 
784  mIsOptimizing=true;
789  // prepare all objects
792  this->TagNewBestConfig();
793  mvObjWeight.clear();
794  long nbTrialCumul=0;
795  const long nbCycle0=nbCycle;
796  Chronometer chrono;
797  mRun = 0;
798  while(nbCycle!=0)
799  {
800  if(!silent) cout <<"MonteCarloObj::MultiRunOptimize: Starting Run#"<<abs(nbCycle)<<endl;
801  nbStep=nbStep0;
802  for(int i=0;i<mRefinedObjList.GetNb();i++) mRefinedObjList.GetObj(i).RandomizeConfiguration();
804  chrono.start();
805  switch(mGlobalOptimType.GetChoice())
806  {
807  case GLOBAL_OPTIM_SIMULATED_ANNEALING:
808  {
809  try{this->RunSimulatedAnnealing(nbStep,silent,finalcost,maxTime);}
810  catch(...){cout<<"Unhandled exception in MonteCarloObj::MultiRunOptimize() ?"<<endl;}
811  break;
812  }
813  case GLOBAL_OPTIM_PARALLEL_TEMPERING:
814  {
815  try{this->RunParallelTempering(nbStep,silent,finalcost,maxTime);}
816  catch(...){cout<<"Unhandled exception in MonteCarloObj::MultiRunOptimize() ?"<<endl;}
817  break;
818  }
819  case GLOBAL_OPTIM_RANDOM_LSQ:
820  {
821  try{this->RunRandomLSQMethod(nbCycle);}
822  catch(...){cout<<"Unhandled exception in MonteCarloObj::RunRandomLSQMethod() ?"<<endl;}
823  //nbCycle=1;
824  break;
825  }
826  }
827  nbTrialCumul+=(nbStep0-nbStep);
828  if(finalcost>1)
829  (*fpObjCrystInformUser)((boost::format("Finished Run #%d, final cost=%12.2f, nbTrial=%d (dt=%.1fs), so far <nbTrial>=%d")
830  % (nbCycle0-nbCycle) % this->GetLogLikelihood() % (nbStep0-nbStep) % chrono.seconds() % (nbTrialCumul/(nbCycle0-nbCycle+1))).str());
831  else
832  (*fpObjCrystInformUser)((boost::format("Finished Run #%d, final cost=%12.2f, nbTrial=%d (dt=%.1fs)")
833  % (nbCycle0-nbCycle) % this->GetLogLikelihood() % (nbStep0-nbStep) % chrono.seconds()).str());
834 
835 
836  nbStep=nbStep0;
837  if(false==mStopAfterCycle) this->UpdateDisplay();
838  stringstream s;
839  s<<"Run #"<<abs(nbCycle);
840  mvSavedParamSet.push_back(make_pair(mRefParList.CreateParamSet(s.str()),mCurrentCost));
841  if(!silent) cout <<"MonteCarloObj::MultiRunOptimize: Finished Run#"
842  <<abs(nbCycle)<<", Run Best Cost:"<<mCurrentCost
843  <<", Overall Best Cost:"<<mBestCost<<endl;
844  if(mXMLAutoSave.GetChoice()==5)
845  {
846  string saveFileName=this->GetName();
847  time_t date=time(0);
848  char strDate[40];
849  strftime(strDate,sizeof(strDate),"%Y-%m-%d_%H-%M-%S",localtime(&date));//%Y-%m-%dT%H:%M:%S%Z
850  char costAsChar[30];
851  sprintf(costAsChar,"-Run#%ld-Cost-%f",abs(nbCycle),this->GetLogLikelihood());
852  saveFileName=saveFileName+(string)strDate+(string)costAsChar+(string)".xml";
853  XMLCrystFileSaveGlobal(saveFileName);
854  }
855  if(mSaveTrackedData.GetChoice()==1)
856  {
857  ofstream outTracker;
858  outTracker.imbue(std::locale::classic());
859  char runNum[40];
860  sprintf(runNum,"-Tracker-Run#%ld.dat",abs(nbCycle));
861  const string outTrackerName=this->GetName()+runNum;
862  outTracker.open(outTrackerName.c_str());
863  mMainTracker.SaveAll(outTracker);
864  outTracker.close();
865  }
866  nbCycle--;
867  #ifdef __WX__CRYST__
868  mMutexStopAfterCycle.Lock();
869  #endif
870  if(mStopAfterCycle)
871  {
872  #ifdef __WX__CRYST__
873  mMutexStopAfterCycle.Unlock();
874  #endif
875  break;
876  }
877  #ifdef __WX__CRYST__
878  mMutexStopAfterCycle.Unlock();
879  #endif
880  mRun++;
881  }
882  mIsOptimizing=false;
883 
885 
886  for(vector<pair<long,REAL> >::iterator pos=mvSavedParamSet.begin();pos!=mvSavedParamSet.end();++pos)
887  if(pos->first==mBestParSavedSetIndex)
888  {
889  if( (pos->second>mBestCost)
890  ||(pos->second<0))
891  {
892  pos->second=mBestCost;
893  break;
894  }
895  }
896 
897  this->EndOptimization();
898 
899  if(false==mStopAfterCycle) this->UpdateDisplay();
900 
901  #ifdef __WX__CRYST__
902  mMutexStopAfterCycle.Lock();
903  #endif
904  mStopAfterCycle=false;
905  #ifdef __WX__CRYST__
906  mMutexStopAfterCycle.Unlock();
907  #endif
908 
909  if(finalcost>1)
910  cout<<endl<<"Finished all runs, number of trials to reach cost="
911  <<finalcost<<" : <nbTrial>="<<nbTrialCumul/(nbCycle0-nbCycle)<<endl;
912  VFN_DEBUG_EXIT("MonteCarloObj::MultiRunOptimize()",5)
913 }
914 
915 void MonteCarloObj::RunSimulatedAnnealing(long &nbStep,const bool silent,
916  const REAL finalcost,const REAL maxTime)
917 {
918  //Keep a copy of the total number of steps, and decrement nbStep
919  const long nbSteps=nbStep;
920  unsigned int accept;// 1 if last trial was accepted? 2 if new best config ? else 0
921  mNbTrial=0;
922  // time (in seconds) when last autoSave was made (if enabled)
923  unsigned long secondsWhenAutoSave=0;
924 
925  if(!silent) cout << "Starting Simulated Annealing Optimization for"<<nbSteps<<" trials"<<endl;
926  if(!silent) this->DisplayReport();
927  REAL runBestCost;
929  runBestCost=mCurrentCost;
930  const long lastParSavedSetIndex=mRefParList.CreateParamSet("MonteCarloObj:Last parameters (SA)");
931  const long runBestIndex=mRefParList.CreateParamSet("Best parameters for current run (SA)");
932  //Report each ... cycles
933  const int nbTryReport=3000;
934  // Keep record of the number of accepted moves
935  long nbAcceptedMoves=0;//since last report
936  long nbAcceptedMovesTemp=0;//since last temperature/mutation rate change
937  // Number of tries since best configuration found
938  long nbTriesSinceBest=0;
939  // Change temperature (and mutation) every...
940  const int nbTryPerTemp=300;
941 
944 
945  // Do we need to update the display ?
946  bool needUpdateDisplay=false;
947  Chronometer chrono;
948  chrono.start();
949  for(mNbTrial=1;mNbTrial<=nbSteps;)
950  {
951  if((mNbTrial % nbTryPerTemp) == 1)
952  {
953  VFN_DEBUG_MESSAGE("-> Updating temperature and mutation amplitude.",3)
954  // Temperature & displacements amplitude
955  switch(mAnnealingScheduleTemp.GetChoice())
956  {
957  case ANNEALING_BOLTZMANN:
958  mTemperature=
959  mTemperatureMin*log((REAL)nbSteps)/log((REAL)(mNbTrial+1));break;
960  case ANNEALING_CAUCHY:
961  mTemperature=mTemperatureMin*nbSteps/mNbTrial;break;
962  //case ANNEALING_QUENCHING:
963  case ANNEALING_EXPONENTIAL:
966  mNbTrial/(REAL)nbSteps);break;
967  case ANNEALING_GAMMA:
969  *pow(mNbTrial/(REAL)nbSteps,mTemperatureGamma);break;
970  case ANNEALING_SMART:
971  {
972  if((nbAcceptedMovesTemp/(REAL)nbTryPerTemp)>0.30)
973  mTemperature/=1.5;
974  if((nbAcceptedMovesTemp/(REAL)nbTryPerTemp)<0.10)
975  mTemperature*=1.5;
978  nbAcceptedMovesTemp=0;
979  break;
980  }
981  default: mTemperature=mTemperatureMin;break;
982  }
983  switch(mAnnealingScheduleMutation.GetChoice())
984  {
985  case ANNEALING_BOLTZMANN:
987  mMutationAmplitudeMin*log((REAL)nbSteps)/log((REAL)(mNbTrial+1));
988  break;
989  case ANNEALING_CAUCHY:
991  //case ANNEALING_QUENCHING:
992  case ANNEALING_EXPONENTIAL:
995  mNbTrial/(REAL)nbSteps);break;
996  case ANNEALING_GAMMA:
998  *pow(mNbTrial/(REAL)nbSteps,mMutationAmplitudeGamma);break;
999  case ANNEALING_SMART:
1000  if((nbAcceptedMovesTemp/(REAL)nbTryPerTemp)>0.3) mMutationAmplitude*=2.;
1001  if((nbAcceptedMovesTemp/(REAL)nbTryPerTemp)<0.1) mMutationAmplitude/=2.;
1006  nbAcceptedMovesTemp=0;
1007  break;
1009  }
1010  }
1011 
1012  this->NewConfiguration();
1013  accept=0;
1014  REAL cost=this->GetLogLikelihood();
1015  if(cost<mCurrentCost)
1016  {
1017  accept=1;
1018  mCurrentCost=cost;
1019  mRefParList.SaveParamSet(lastParSavedSetIndex);
1020  if(mCurrentCost<runBestCost)
1021  {
1022  accept=2;
1023  runBestCost=mCurrentCost;
1024  this->TagNewBestConfig();
1025  needUpdateDisplay=true;
1026  mRefParList.SaveParamSet(runBestIndex);
1027  if(runBestCost<mBestCost)
1028  {
1031  if(!silent) cout << "Trial :" << mNbTrial
1032  << " Temp="<< mTemperature
1033  << " Mutation Ampl.: "<<mMutationAmplitude
1034  << " NEW OVERALL Best Cost="<<runBestCost<< endl;
1035  }
1036  else if(!silent) cout << "Trial :" << mNbTrial
1037  << " Temp="<< mTemperature
1038  << " Mutation Ampl.: "<<mMutationAmplitude
1039  << " NEW Run Best Cost="<<runBestCost<< endl;
1040  nbTriesSinceBest=0;
1041  }
1042  nbAcceptedMoves++;
1043  nbAcceptedMovesTemp++;
1044  }
1045  else
1046  {
1047  if( log((rand()+1)/(REAL)RAND_MAX) < (-(cost-mCurrentCost)/mTemperature) )
1048  {
1049  accept=1;
1050  mCurrentCost=cost;
1051  mRefParList.SaveParamSet(lastParSavedSetIndex);
1052  nbAcceptedMoves++;
1053  nbAcceptedMovesTemp++;
1054  }
1055  }
1056  if(accept==0) mRefParList.RestoreParamSet(lastParSavedSetIndex);
1057 
1058  if( (mNbTrial % nbTryReport) == 0)
1059  {
1060  if(!silent) cout <<"Trial :" << mNbTrial << " Temp="<< mTemperature;
1061  if(!silent) cout <<" Mutation Ampl.: " <<mMutationAmplitude<< " Best Cost=" << runBestCost
1062  <<" Current Cost=" << mCurrentCost
1063  <<" Accepting "<<(int)((REAL)nbAcceptedMoves/nbTryReport*100)
1064  <<"% moves" << endl;
1065  nbAcceptedMoves=0;
1066  #ifdef __WX__CRYST__
1067  if(0!=mpWXCrystObj) mpWXCrystObj->UpdateDisplayNbTrial();
1068  #endif
1069  }
1070  mNbTrial++;nbStep--;
1071 
1072  #ifdef __WX__CRYST__
1073  mMutexStopAfterCycle.Lock();
1074  #endif
1075  if((runBestCost<finalcost) || mStopAfterCycle ||( (maxTime>0)&&(chrono.seconds()>maxTime)))
1076  {
1077  #ifdef __WX__CRYST__
1078  mMutexStopAfterCycle.Unlock();
1079  #endif
1080  if(!silent) cout << endl <<endl << "Refinement Stopped."<<endl;
1081  break;
1082  }
1083  #ifdef __WX__CRYST__
1084  mMutexStopAfterCycle.Unlock();
1085  #endif
1086  nbTriesSinceBest++;
1087  if( ((mXMLAutoSave.GetChoice()==1)&&((chrono.seconds()-secondsWhenAutoSave)>86400))
1088  ||((mXMLAutoSave.GetChoice()==2)&&((chrono.seconds()-secondsWhenAutoSave)>3600))
1089  ||((mXMLAutoSave.GetChoice()==3)&&((chrono.seconds()-secondsWhenAutoSave)> 600))
1090  ||((mXMLAutoSave.GetChoice()==4)&&(accept==2)) )
1091  {
1092  secondsWhenAutoSave=(unsigned long)chrono.seconds();
1093  string saveFileName=this->GetName();
1094  time_t date=time(0);
1095  char strDate[40];
1096  strftime(strDate,sizeof(strDate),"%Y-%m-%d_%H-%M-%S",localtime(&date));//%Y-%m-%dT%H:%M:%S%Z
1097  char costAsChar[30];
1099  sprintf(costAsChar,"-Cost-%f",this->GetLogLikelihood());
1100  saveFileName=saveFileName+(string)strDate+(string)costAsChar+(string)".xml";
1101  XMLCrystFileSaveGlobal(saveFileName);
1102  if(accept!=2) mRefParList.RestoreParamSet(lastParSavedSetIndex);
1103  }
1104  if((mNbTrial%300==0)&&needUpdateDisplay)
1105  {
1106  this->UpdateDisplay();
1107  needUpdateDisplay=false;
1108  mRefParList.RestoreParamSet(lastParSavedSetIndex);
1109  }
1110 
1111  }
1112  //cout<<"Beginning final LSQ refinement? ... ";
1113  if(mAutoLSQ.GetChoice()>0)
1114  {// LSQ
1115  if(!silent) cout<<"Beginning final LSQ refinement"<<endl;
1116  for(int i=0;i<mRefinedObjList.GetNb();i++) mRefinedObjList.GetObj(i).SetApproximationFlag(false);
1117  mRefParList.RestoreParamSet(runBestIndex);
1119  try {mLSQ.Refine(-50,true,true,false,0.001);}
1120  catch(const ObjCrystException &except){};
1121  if(!silent) cout<<"LSQ cost: "<<mCurrentCost<<" -> "<<this->GetLogLikelihood()<<endl;
1122 
1123  // Need to go back to optimization with approximations allowed (they are not during LSQ)
1124  for(int i=0;i<mRefinedObjList.GetNb();i++) mRefinedObjList.GetObj(i).SetApproximationFlag(true);
1125 
1126  REAL cost=this->GetLogLikelihood();
1127  if(cost<mCurrentCost)
1128  {
1129  mCurrentCost=cost;
1130  mRefParList.SaveParamSet(lastParSavedSetIndex);
1131  if(mCurrentCost<runBestCost)
1132  {
1133  runBestCost=mCurrentCost;
1134  mRefParList.SaveParamSet(runBestIndex);
1135  if(runBestCost<mBestCost)
1136  {
1139  if(!silent) cout << "LSQ : NEW OVERALL Best Cost="<<runBestCost<< endl;
1140  }
1141  else if(!silent) cout << " LSQ : NEW Run Best Cost="<<runBestCost<< endl;
1142  }
1143  }
1144  if(!silent) cout<<"Finished LSQ refinement"<<endl;
1145  }
1146 
1147 
1148  mLastOptimTime=chrono.seconds();
1149  //Restore Best values
1150  mRefParList.RestoreParamSet(runBestIndex);
1151  mRefParList.ClearParamSet(runBestIndex);
1152  mRefParList.ClearParamSet(lastParSavedSetIndex);
1154  if(!silent) this->DisplayReport();
1155  if(!silent) chrono.print();
1156 }
1157 /*
1158 void MonteCarloObj::RunNondestructiveLSQRefinement( int nbCycle,bool useLevenbergMarquardt,
1159  const bool silent, const bool callBeginEndOptimization,
1160  const float minChi2var )
1161 {
1162  float bsigma=-1, bdelta=-1;
1163  float asigma=-1, adelta=-1;
1164  //set the sigma values lower - it makes the molecular model more stable for LSQ
1165  for(int i=0;i<mRefinedObjList.GetNb();i++) {
1166  if(mRefinedObjList.GetObj(i).GetClassName()=="Crystal") {
1167  try {
1168  Crystal * pCryst = dynamic_cast<Crystal *>(&(mRefinedObjList.GetObj(i)));
1169  for(int s=0;s<pCryst->GetScattererRegistry().GetNb();s++) {
1170  Molecule *pMol=dynamic_cast<Molecule*>(&(pCryst->GetScatt(s)));
1171  if(pMol==NULL) continue; // not a Molecule
1172  for(vector<MolBond*>::iterator pos = pMol->GetBondList().begin(); pos != pMol->GetBondList().end();++pos) {
1173  bsigma = (*pos)->GetLengthSigma();
1174  bdelta = (*pos)->GetLengthDelta();
1175  (*pos)->SetLengthDelta(0.02);
1176  (*pos)->SetLengthSigma(0.001);
1177  }
1178  for(vector<MolBondAngle*>::iterator pos=pMol->GetBondAngleList().begin();pos != pMol->GetBondAngleList().end();++pos)
1179  {
1180  asigma = (*pos)->GetAngleSigma();
1181  adelta = (*pos)->GetAngleDelta();
1182  (*pos)->SetAngleDelta(0.2*DEG2RAD);
1183  (*pos)->SetAngleSigma(0.01*DEG2RAD);
1184  }
1185  }
1186  } catch (const std::bad_cast& e) {
1187 
1188  }
1189  }
1190  }
1191  for(int i=0;i<mRefinedObjList.GetNb();i++) mRefinedObjList.GetObj(i).SetApproximationFlag(false);
1192  try {
1193  mLSQ.Refine(nbCycle,useLevenbergMarquardt,silent,callBeginEndOptimization,minChi2var);
1194  }
1195  catch(const ObjCrystException &except) {
1196 
1197  };
1198  for(int i=0;i<mRefinedObjList.GetNb();i++) mRefinedObjList.GetObj(i).SetApproximationFlag(true);
1199 
1200  if(bsigma<0 || bdelta<0 || asigma<0 || adelta<0) return;
1201  //restore the delta and sigma values
1202  for(int i=0;i<mRefinedObjList.GetNb();i++) {
1203  if(mRefinedObjList.GetObj(i).GetClassName()=="Crystal") {
1204  try {
1205  Crystal * pCryst = dynamic_cast<Crystal *>(&(mRefinedObjList.GetObj(i)));
1206  for(int s=0;s<pCryst->GetScattererRegistry().GetNb();s++) {
1207  Molecule *pMol=dynamic_cast<Molecule*>(&(pCryst->GetScatt(s)));
1208  if(pMol==NULL) continue; // not a Molecule
1209  for(vector<MolBond*>::iterator pos = pMol->GetBondList().begin(); pos != pMol->GetBondList().end();++pos) {
1210  (*pos)->SetLengthDelta(bdelta);
1211  (*pos)->SetLengthSigma(bsigma);
1212  }
1213  for(vector<MolBondAngle*>::iterator pos=pMol->GetBondAngleList().begin();pos != pMol->GetBondAngleList().end();++pos)
1214  {
1215  (*pos)->SetAngleDelta(adelta);
1216  (*pos)->SetAngleSigma(asigma);
1217  }
1218  }
1219  } catch (const std::bad_cast& e) {
1220 
1221  }
1222  }
1223  }
1224 }
1225 */
1226 void MonteCarloObj::RunRandomLSQMethod(long &nbCycle)
1227 {
1228  //perform random move
1230  float bsigma=-1, bdelta=-1;
1231  float asigma=-1, adelta=-1;
1232 
1233  //set the delta and sigma values - low values are good for LSQ!
1234  for(int i=0;i<mRefinedObjList.GetNb();i++) {
1235  if(mRefinedObjList.GetObj(i).GetClassName()=="Crystal") {
1236  try {
1237  Crystal * pCryst = dynamic_cast<Crystal *>(&(mRefinedObjList.GetObj(i)));
1238  for(int s=0;s<pCryst->GetScattererRegistry().GetNb();s++)
1239  {
1240  Molecule *pMol=dynamic_cast<Molecule*>(&(pCryst->GetScatt(s)));
1241  if(pMol==NULL) continue; // not a Molecule
1242  for(vector<MolBond*>::iterator pos = pMol->GetBondList().begin(); pos != pMol->GetBondList().end();++pos) {
1243  bsigma = (*pos)->GetLengthSigma();
1244  bdelta = (*pos)->GetLengthDelta();
1245  (*pos)->SetLengthDelta(0.02);
1246  (*pos)->SetLengthSigma(0.001);
1247  }
1248  for(vector<MolBondAngle*>::iterator pos=pMol->GetBondAngleList().begin();pos != pMol->GetBondAngleList().end();++pos)
1249  {
1250  asigma = (*pos)->GetAngleSigma();
1251  adelta = (*pos)->GetAngleDelta();
1252  (*pos)->SetAngleDelta(0.2*DEG2RAD);
1253  (*pos)->SetAngleSigma(0.01*DEG2RAD);
1254  }
1255  }
1256  } catch (const std::bad_cast& e){
1257 
1258  }
1259  }
1260  }
1261 
1262  const long starting_point=mRefParList.CreateParamSet("MonteCarloObj:Last parameters (RANDOM-LSQ)");
1263  mRefParList.SaveParamSet(starting_point);
1264  mRun = 0;
1265  while(nbCycle!=0) {
1266  nbCycle--;
1267  mRefParList.RestoreParamSet(starting_point);
1268  //this->NewConfiguration();
1269  for(int i=0;i<mRefinedObjList.GetNb();i++) mRefinedObjList.GetObj(i).RandomizeConfiguration();
1270  this->UpdateDisplay();
1271 
1272  //perform LSQ
1273  for(int i=0;i<mRefinedObjList.GetNb();i++) mRefinedObjList.GetObj(i).SetApproximationFlag(false);
1274  //mCurrentCost=this->GetLogLikelihood();
1275  try {
1276  mLSQ.Refine(20,true,true,false,0.001);
1277  }
1278  catch(const ObjCrystException &except) {
1279  //cout<<"Something wrong?"<<endl;
1280  };
1281  for(int i=0;i<mRefinedObjList.GetNb();i++) mRefinedObjList.GetObj(i).SetApproximationFlag(true);
1282  //cout<<"LSQ cost: "<<mCurrentCost<<" -> "<<this->GetLogLikelihood()<<endl;
1283  REAL lsq_cost=this->GetLogLikelihood();
1284  mCurrentCost = lsq_cost;
1285  //mRefParList.SaveParamSet(lsqtParSavedSetIndex);
1287  {
1290  }
1291  this->UpdateDisplay();
1292 
1293  //save it to the file
1294  string saveFileName=this->GetName();
1295  time_t date=time(0);
1296  char strDate[40];
1297  strftime(strDate,sizeof(strDate),"%Y-%m-%d_%H-%M-%S",localtime(&date));//%Y-%m-%dT%H:%M:%S%Z
1298  char costAsChar[30];
1299  sprintf(costAsChar,"#Run%ld-Cost-%f",nbCycle, mCurrentCost);
1300  saveFileName=saveFileName+(string)strDate+(string)costAsChar+(string)".xml";
1301  XMLCrystFileSaveGlobal(saveFileName);
1302 
1303  #ifdef __WX__CRYST__
1304  mMutexStopAfterCycle.Lock();
1305  #endif
1306  if(mStopAfterCycle)
1307  {
1308  #ifdef __WX__CRYST__
1309  mMutexStopAfterCycle.Unlock();
1310  #endif
1311  break;
1312  }
1313  #ifdef __WX__CRYST__
1314  mMutexStopAfterCycle.Unlock();
1315  #endif
1316  mRun++;
1317  }
1318 
1319  if(bsigma<0 || bdelta<0 || asigma<0 || adelta<0) return;
1320  //restore the delta and sigma values
1321  for(int i=0;i<mRefinedObjList.GetNb();i++) {
1322  if(mRefinedObjList.GetObj(i).GetClassName()=="Crystal") {
1323  try {
1324  Crystal * pCryst = dynamic_cast<Crystal *>(&(mRefinedObjList.GetObj(i)));
1325  for(int s=0;s<pCryst->GetScattererRegistry().GetNb();s++)
1326  {
1327  Molecule *pMol=dynamic_cast<Molecule*>(&(pCryst->GetScatt(s)));
1328  if(pMol==NULL) continue; // not a Molecule
1329  for(vector<MolBond*>::iterator pos = pMol->GetBondList().begin(); pos != pMol->GetBondList().end();++pos) {
1330  (*pos)->SetLengthDelta(bdelta);
1331  (*pos)->SetLengthSigma(bsigma);
1332  }
1333  for(vector<MolBondAngle*>::iterator pos=pMol->GetBondAngleList().begin();pos != pMol->GetBondAngleList().end();++pos)
1334  {
1335  (*pos)->SetAngleDelta(adelta);
1336  (*pos)->SetAngleSigma(asigma);
1337  }
1338  }
1339  } catch (const std::bad_cast& e){
1340 
1341  }
1342  }
1343  }
1344 }
1345 
1346 void MonteCarloObj::RunParallelTempering(long &nbStep,const bool silent,
1347  const REAL finalcost,const REAL maxTime)
1348 {
1349  TAU_PROFILE("MonteCarloObj::RunParallelTempering()","void ()",TAU_DEFAULT);
1350  TAU_PROFILE_TIMER(timer0a,"MonteCarloObj::RunParallelTempering() Begin 1","", TAU_FIELD);
1351  TAU_PROFILE_TIMER(timer0b,"MonteCarloObj::RunParallelTempering() Begin 2","", TAU_FIELD);
1352  TAU_PROFILE_TIMER(timer1,"MonteCarloObj::RunParallelTempering() New Config + LLK","", TAU_FIELD);
1353  TAU_PROFILE_TIMER(timerN,"MonteCarloObj::RunParallelTempering() Finish","", TAU_FIELD);
1354  TAU_PROFILE_START(timer0a);
1355  //Keep a copy of the total number of steps, and decrement nbStep
1356  const long nbSteps=nbStep;
1357  unsigned int accept;// 1 if last trial was accepted? 2 if new best config ? else 0
1358  mNbTrial=0;
1359  // time (in seconds) when last autoSave was made (if enabled)
1360  unsigned long secondsWhenAutoSave=0;
1361 
1362  // Periodicity of the automatic LSQ refinements (if the option is set)
1363  const unsigned int autoLSQPeriod=150000;
1364 
1365  if(!silent) cout << "Starting Parallel Tempering Optimization"<<endl;
1366  //Total number of parallel refinements,each is a 'World'. The most stable
1367  // world must be i=nbWorld-1, and the most changing World (high mutation,
1368  // high temperature) is i=0.
1369  const long nbWorld=30;
1370  CrystVector_long worldSwapIndex(nbWorld);
1371  for(int i=0;i<nbWorld;++i) worldSwapIndex(i)=i;
1372  // Number of successive trials for each World. At the end of these trials
1373  // a swap is tried with the upper World (eg i-1). This number effectvely sets
1374  // the rate of swapping.
1375  const int nbTryPerWorld=10;
1376  // Initialize the costs
1378  REAL runBestCost=mCurrentCost;
1379  CrystVector_REAL currentCost(nbWorld);
1380  currentCost=mCurrentCost;
1381  // Init the different temperatures
1382  CrystVector_REAL simAnnealTemp(nbWorld);
1383  for(int i=0;i<nbWorld;i++)
1384  {
1385  switch(mAnnealingScheduleTemp.GetChoice())
1386  {
1387  case ANNEALING_BOLTZMANN:
1388  simAnnealTemp(i)=
1389  mTemperatureMin*log((REAL)nbWorld)/log((REAL)(i+2));break;
1390  case ANNEALING_CAUCHY:
1391  simAnnealTemp(i)=mTemperatureMin*nbWorld/(i+1);break;
1392  //case ANNEALING_QUENCHING:
1393  case ANNEALING_EXPONENTIAL:
1394  simAnnealTemp(i)=mTemperatureMax
1396  i/(REAL)(nbWorld-1));break;
1397  case ANNEALING_GAMMA:
1399  *pow(i/(REAL)(nbWorld-1),mTemperatureGamma);break;
1400  case ANNEALING_SMART:
1401  simAnnealTemp(i)=mCurrentCost/(100.+(REAL)i/(REAL)nbWorld*900.);break;
1402  default:
1403  simAnnealTemp(i)=mCurrentCost/(100.+(REAL)i/(REAL)nbWorld*900.);break;
1404  }
1405  }
1406  //Init the different mutation rate parameters
1407  CrystVector_REAL mutationAmplitude(nbWorld);
1408  for(int i=0;i<nbWorld;i++)
1409  {
1410  switch(mAnnealingScheduleMutation.GetChoice())
1411  {
1412  case ANNEALING_BOLTZMANN:
1413  mutationAmplitude(i)=
1414  mMutationAmplitudeMin*log((REAL)(nbWorld-1))/log((REAL)(i+2));
1415  break;
1416  case ANNEALING_CAUCHY:
1417  mutationAmplitude(i)=mMutationAmplitudeMin*(REAL)(nbWorld-1)/(i+1);break;
1418  //case ANNEALING_QUENCHING:
1419  case ANNEALING_EXPONENTIAL:
1420  mutationAmplitude(i)=mMutationAmplitudeMax
1422  i/(REAL)(nbWorld-1));break;
1423  case ANNEALING_GAMMA:
1425  *pow(i/(REAL)(nbWorld-1),mMutationAmplitudeGamma);break;
1426  case ANNEALING_SMART:
1427  mutationAmplitude(i)=sqrt(mMutationAmplitudeMin*mMutationAmplitudeMax);break;
1428  default:
1429  mutationAmplitude(i)=sqrt(mMutationAmplitudeMin*mMutationAmplitudeMax);break;
1430  }
1431  }
1432  // Init the parameter sets for each World
1433  // All Worlds start from the same (current) configuration.
1434  CrystVector_long worldCurrentSetIndex(nbWorld);
1435  for(int i=nbWorld-1;i>=0;i--)
1436  {
1437  if((i!=(nbWorld-1))&&(i%2==0))
1438  for(int j=0;j<mRecursiveRefinedObjList.GetNb();j++)
1439  mRecursiveRefinedObjList.GetObj(j).RandomizeConfiguration();
1440  worldCurrentSetIndex(i)=mRefParList.CreateParamSet();
1441  mRefParList.RestoreParamSet(worldCurrentSetIndex(nbWorld-1));
1442  }
1443  TAU_PROFILE_STOP(timer0a);
1444  TAU_PROFILE_START(timer0b);
1445  //mNbTrial=nbSteps;;
1446  const long lastParSavedSetIndex=mRefParList.CreateParamSet("MonteCarloObj:Last parameters (PT)");
1447  const long runBestIndex=mRefParList.CreateParamSet("Best parameters for current run (PT)");
1448  CrystVector_REAL swapPar;
1449  //Keep track of how many trials are accepted for each World
1450  CrystVector_long worldNbAcceptedMoves(nbWorld);
1451  worldNbAcceptedMoves=0;
1452  //Do a report each... And check if mutation rate is OK (for annealing_smart)s
1453  const int nbTrialsReport=3000;
1454  // TEST : allow GENETIC mating of configurations
1455  //Get gene groups list :TODO: check for missing groups
1456  CrystVector_uint refParGeneGroupIndex(mRefParList.GetNbPar());
1457  unsigned int first=1;
1458  for(int i=0;i<mRecursiveRefinedObjList.GetNb();i++)
1459  mRecursiveRefinedObjList.GetObj(i).GetGeneGroup(mRefParList,refParGeneGroupIndex,first);
1460  #if 0
1461  if(!silent)
1462  for(int i=0;i<mRefParList.GetNbPar();i++)
1463  {
1464  cout << "Gene Group:"<<refParGeneGroupIndex(i)<<" :";
1465  mRefParList.GetPar(i).Print();
1466  }
1467  #endif
1468  // number of gene groups
1469  // to select which gene groups are exchanged in the mating
1470  //const unsigned int nbGeneGroup=refParGeneGroupIndex.max();
1471  //CrystVector_int crossoverGroupIndex(nbGeneGroup);
1472  //const long parSetOffspringA=mRefParList.CreateParamSet("Offspring A");
1473  //const long parSetOffspringB=mRefParList.CreateParamSet("Offspring B");
1474  // record the statistical distribution n=f(cost function) for each World
1475  //CrystMatrix_REAL trialsDensity(100,nbWorld+1);
1476  //trialsDensity=0;
1477  //for(int i=0;i<100;i++) trialsDensity(i,0)=i/(float)100;
1478  // Do we need to update the display ?
1479  bool needUpdateDisplay=false;
1480  //Do the refinement
1481  bool makeReport=false;
1482  Chronometer chrono;
1483  chrono.start();
1484  float lastUpdateDisplayTime=chrono.seconds();
1485  TAU_PROFILE_STOP(timer0b);
1486  for(;mNbTrial<nbSteps;)
1487  {
1488  for(int i=0;i<nbWorld;i++)
1489  {
1490  mContext=i;
1491  //mRefParList.RestoreParamSet(worldCurrentSetIndex(i));
1492  mMutationAmplitude=mutationAmplitude(i);
1493  mTemperature=simAnnealTemp(i);
1494  for(int j=0;j<nbTryPerWorld;j++)
1495  {
1496  //mRefParList.SaveParamSet(lastParSavedSetIndex);
1497  TAU_PROFILE_START(timer1);
1498  mRefParList.RestoreParamSet(worldCurrentSetIndex(i));
1499  this->NewConfiguration();
1500  accept=0;
1501  REAL cost=this->GetLogLikelihood();
1502  TAU_PROFILE_STOP(timer1);
1503  //trialsDensity((long)(cost*100.),i+1)+=1;
1504  if(cost<currentCost(i))
1505  {
1506  accept=1;
1507  currentCost(i)=cost;
1508  mRefParList.SaveParamSet(worldCurrentSetIndex(i));
1509  if(cost<runBestCost)
1510  {
1511  accept=2;
1512  runBestCost=currentCost(i);
1513  this->TagNewBestConfig();
1514  needUpdateDisplay=true;
1515 
1516  mRefParList.SaveParamSet(runBestIndex);
1517  if(runBestCost<mBestCost)
1518  {
1519  mBestCost=currentCost(i);
1521  if(!silent) cout << "->Trial :" << mNbTrial
1522  << " World="<< worldSwapIndex(i)
1523  << " Temp="<< mTemperature
1524  << " Mutation Ampl.: "<<mMutationAmplitude
1525  << " NEW OVERALL Best Cost="<<mBestCost<< endl;
1526  }
1527  else if(!silent) cout << "->Trial :" << mNbTrial
1528  << " World="<< worldSwapIndex(i)
1529  << " Temp="<< mTemperature
1530  << " Mutation Ampl.: "<<mMutationAmplitude
1531  << " NEW RUN Best Cost="<<runBestCost<< endl;
1532  if(!silent) this->DisplayReport();
1533  }
1534  worldNbAcceptedMoves(i)++;
1535  }
1536  else
1537  {
1538  if(log((rand()+1)/(REAL)RAND_MAX)<(-(cost-currentCost(i))/mTemperature) )
1539  {
1540  accept=1;
1541  currentCost(i)=cost;
1542  mRefParList.SaveParamSet(worldCurrentSetIndex(i));
1543  worldNbAcceptedMoves(i)++;
1544  }
1545  }
1546  //if(accept==1 && i==(nbWorld-1)){this->UpdateDisplay();}
1547  if( ((mXMLAutoSave.GetChoice()==1)&&((chrono.seconds()-secondsWhenAutoSave)>86400))
1548  ||((mXMLAutoSave.GetChoice()==2)&&((chrono.seconds()-secondsWhenAutoSave)>3600))
1549  ||((mXMLAutoSave.GetChoice()==3)&&((chrono.seconds()-secondsWhenAutoSave)> 600))
1550  ||((mXMLAutoSave.GetChoice()==4)&&(accept==2)) )
1551  {
1552  secondsWhenAutoSave=(unsigned long)chrono.seconds();
1553  string saveFileName=this->GetName();
1554  time_t date=time(0);
1555  char strDate[40];
1556  strftime(strDate,sizeof(strDate),"%Y-%m-%d_%H-%M-%S",localtime(&date));//%Y-%m-%dT%H:%M:%S%Z
1557  char costAsChar[30];
1559  sprintf(costAsChar,"-Cost-%f",this->GetLogLikelihood());
1560  saveFileName=saveFileName+(string)strDate+(string)costAsChar+(string)".xml";
1561  XMLCrystFileSaveGlobal(saveFileName);
1562  //if(accept!=2) mRefParList.RestoreParamSet(lastParSavedSetIndex);
1563  }
1564  //if(accept==0) mRefParList.RestoreParamSet(lastParSavedSetIndex);
1565  mNbTrial++;nbStep--;
1566  if((mNbTrial%nbTrialsReport)==0) makeReport=true;
1567  }//nbTryPerWorld trials
1568  }//For each World
1569 
1570  if(mAutoLSQ.GetChoice()==2)
1571  if((mNbTrial%autoLSQPeriod)<(nbTryPerWorld*nbWorld))
1572  {// Try a quick LSQ ?
1573  for(int i=0;i<mRefinedObjList.GetNb();i++) mRefinedObjList.GetObj(i).SetApproximationFlag(false);
1574  for(int i=nbWorld-5;i<nbWorld;i++)
1575  {
1576  #ifdef __WX__CRYST__
1577  mMutexStopAfterCycle.Lock();
1578  if(mStopAfterCycle)
1579  {
1580  mMutexStopAfterCycle.Unlock();
1581  break;
1582  }
1583  mMutexStopAfterCycle.Unlock();
1584  #endif
1585 
1586  mRefParList.RestoreParamSet(worldCurrentSetIndex(i));
1587 
1588  #if 0
1589  // Report GoF values (Chi^2 / nbObs) values for all objects
1590  for(map<RefinableObj*,unsigned int>::iterator pos=mLSQ.GetRefinedObjMap().begin();pos!=mLSQ.GetRefinedObjMap().end();++pos)
1591  if(pos->first->GetNbLSQFunction()>0)
1592  {
1593  CrystVector_REAL tmp;
1594  tmp =pos->first->GetLSQCalc(pos->second);
1595  tmp-=pos->first->GetLSQObs (pos->second);
1596  tmp*=tmp;
1597  tmp*=pos->first->GetLSQWeight(pos->second);
1598  cout<<pos->first->GetClassName()<<":"<<pos->first->GetName()<<": GoF="<<tmp.sum()/tmp.numElements();
1599  }
1600  cout<<endl;
1601  #endif
1602 
1603  const REAL cost0=this->GetLogLikelihood();// cannot use currentCost(i), approximations changed...
1604  if(!silent) cout<<"LSQ: World="<<worldSwapIndex(i)<<": cost="<<cost0;
1605  try {mLSQ.Refine(-30,true,true,false,0.001);}
1606  catch(const ObjCrystException &except){};
1607  #if 0
1608  // Report GoF values (Chi^2 / nbObs) values for all objects
1609  for(map<RefinableObj*,unsigned int>::iterator pos=mLSQ.GetRefinedObjMap().begin();pos!=mLSQ.GetRefinedObjMap().end();++pos)
1610  if(pos->first->GetNbLSQFunction()>0)
1611  {
1612  CrystVector_REAL tmp;
1613  tmp =pos->first->GetLSQCalc(pos->second);
1614  tmp-=pos->first->GetLSQObs (pos->second);
1615  tmp*=tmp;
1616  tmp*=pos->first->GetLSQWeight(pos->second);
1617  cout<<pos->first->GetClassName()<<":"<<pos->first->GetName()<<": GoF="<<tmp.sum()/tmp.numElements();
1618  }
1619  cout<<endl;
1620  #endif
1621  const REAL cost=this->GetLogLikelihood();
1622  if(!silent) cout<<" -> "<<cost<<endl;
1623  if(cost<cost0) mRefParList.SaveParamSet(worldCurrentSetIndex(i));
1624  }
1625  // Need to go back to optimization with approximations allowed (they are not during LSQ)
1626  for(int i=0;i<mRefinedObjList.GetNb();i++) mRefinedObjList.GetObj(i).SetApproximationFlag(true);
1627  // And recompute LLK - since they will be lower
1628  for(int i=nbWorld-5;i<nbWorld;i++)
1629  {
1630  mRefParList.RestoreParamSet(worldCurrentSetIndex(i));
1631  const REAL cost=this->GetLogLikelihood();
1632  if(!silent) cout<<"LSQ2:"<<currentCost(i)<<"->"<<cost<<endl;
1633  if(cost<currentCost(i))
1634  {
1635  const REAL oldcost=currentCost(i);
1636  mRefParList.SaveParamSet(worldCurrentSetIndex(i));
1637  currentCost(i)=cost;
1638  if(cost<runBestCost)
1639  {
1640  runBestCost=currentCost(i);
1641  this->TagNewBestConfig();
1642  needUpdateDisplay=true;
1643 
1644  mRefParList.SaveParamSet(runBestIndex);
1645  if(runBestCost<mBestCost)
1646  {
1647  mBestCost=currentCost(i);
1649  if(!silent) cout << "->Trial :" << mNbTrial
1650  << " World="<< worldSwapIndex(i)
1651  << " LSQ2: NEW OVERALL Best Cost="<<mBestCost<< endl;
1652  }
1653  else if(!silent) cout << "->Trial :" << mNbTrial
1654  << " World="<< worldSwapIndex(i)
1655  << " LSQ2: NEW RUN Best Cost="<<runBestCost<< endl;
1656  if(!silent) this->DisplayReport();
1657  }
1658  // KLUDGE - after a successful LSQ, we will be close to a minimum,
1659  // which will make most successive global optimization trials to
1660  // be rejected, until the temperature is increased a lot - this
1661  // is a problem as the temperature increases so much that the
1662  // benefit of the LSQ is essentially negated.
1663  // So we need to use a higher recorded cost, so that successive trials
1664  // may be accepted
1665  #if 0
1666  mMutationAmplitude=mutationAmplitude(i);
1667  for(unsigned int ii=0;ii<4;ii++) this->NewConfiguration(gpRefParTypeObjCryst,false);
1668  currentCost(i)=(this->GetLogLikelihood()+cost)/2;
1669  if(!silent) cout<<"LSQ3: #"<<worldSwapIndex(i)<<":"<<cost<<"->"<<currentCost(i)<<endl;
1670  #else
1671  currentCost(i)=oldcost;
1672  #endif
1673  }
1674  }
1675  }
1676 
1677  //Try swapping worlds
1678  for(int i=1;i<nbWorld;i++)
1679  {
1680  #if 0
1681  mRefParList.RestoreParamSet(worldCurrentSetIndex(i));
1682  mMutationAmplitude=mutationAmplitude(i);
1683  cout<<i<<":"<<currentCost(i)<<":"<<this->GetLogLikelihood()<<endl;
1684  #endif
1685  #if 1
1686  if( log((rand()+1)/(REAL)RAND_MAX)
1687  < (-(currentCost(i-1)-currentCost(i))/simAnnealTemp(i)))
1688  #else
1689  // Compare World (i-1) and World (i) with the same amplitude,
1690  // hence the same max likelihood error
1691  mRefParList.RestoreParamSet(worldCurrentSetIndex(i-1));
1692  mMutationAmplitude=mutationAmplitude(i);
1693  if( log((rand()+1)/(REAL)RAND_MAX)
1694  < (-(this->GetLogLikelihood()-currentCost(i))/simAnnealTemp(i)))
1695  #endif
1696  {
1697  /*
1698  if(i>2)
1699  {
1700  cout <<"->Swapping Worlds :" << i <<"(cost="<<currentCost(i)<<")"
1701  <<" with "<< (i-1) <<"(cost="<< currentCost(i-1)<<")"<<endl;
1702  }
1703  */
1704  swapPar=mRefParList.GetParamSet(worldCurrentSetIndex(i));
1705  mRefParList.GetParamSet(worldCurrentSetIndex(i))=
1706  mRefParList.GetParamSet(worldCurrentSetIndex(i-1));
1707  mRefParList.GetParamSet(worldCurrentSetIndex(i-1))=swapPar;
1708  const REAL tmp=currentCost(i);
1709  currentCost(i)=currentCost(i-1);
1710  currentCost(i-1)=tmp;
1711  const long tmpIndex=worldSwapIndex(i);
1712  worldSwapIndex(i)=worldSwapIndex(i-1);
1713  worldSwapIndex(i-1)=tmpIndex;
1714  #if 0
1715  // Compute correct costs in the case we use maximum likelihood
1716  mRefParList.RestoreParamSet(worldCurrentSetIndex(i));
1717  mMutationAmplitude=mutationAmplitude(i);
1718  currentCost(i)=this->GetLogLikelihood();
1719 
1720  mRefParList.RestoreParamSet(worldCurrentSetIndex(i-1));
1721  mMutationAmplitude=mutationAmplitude(i-1);
1722  currentCost(i-1)=this->GetLogLikelihood();
1723  #endif
1724  }
1725  }
1726  #if 0
1727  //Try mating worlds- NEW !
1728  TAU_PROFILE_TIMER(timer1,\
1729  "MonteCarloObj::Optimize (Try mating Worlds)"\
1730  ,"", TAU_FIELD);
1731  TAU_PROFILE_START(timer1);
1732  if( (rand()/(REAL)RAND_MAX)<.1)
1733  for(int k=nbWorld-1;k>nbWorld/2;k--)
1734  for(int i=k-nbWorld/3;i<k;i++)
1735  {
1736  #if 0
1737  // Random switching of gene groups
1738  for(unsigned int j=0;j<nbGeneGroup;j++)
1739  crossoverGroupIndex(j)= (int) floor(rand()/((REAL)RAND_MAX-1)*2);
1740  for(int j=0;j<mRefParList.GetNbPar();j++)
1741  {
1742  if(0==crossoverGroupIndex(refParGeneGroupIndex(j)-1))
1743  {
1744  mRefParList.GetParamSet(parSetOffspringA)(j)=
1745  mRefParList.GetParamSet(worldCurrentSetIndex(i))(j);
1746  mRefParList.GetParamSet(parSetOffspringB)(j)=
1747  mRefParList.GetParamSet(worldCurrentSetIndex(k))(j);
1748  }
1749  else
1750  {
1751  mRefParList.GetParamSet(parSetOffspringA)(j)=
1752  mRefParList.GetParamSet(worldCurrentSetIndex(k))(j);
1753  mRefParList.GetParamSet(parSetOffspringB)(j)=
1754  mRefParList.GetParamSet(worldCurrentSetIndex(i))(j);
1755  }
1756  }
1757  #endif
1758  #if 1
1759  // Switch gene groups in two parts
1760  unsigned int crossoverPoint1=
1761  (int)(1+floor(rand()/((REAL)RAND_MAX-1)*(nbGeneGroup)));
1762  unsigned int crossoverPoint2=
1763  (int)(1+floor(rand()/((REAL)RAND_MAX-1)*(nbGeneGroup)));
1764  if(crossoverPoint2<crossoverPoint1)
1765  {
1766  int tmp=crossoverPoint1;
1767  crossoverPoint1=crossoverPoint2;
1768  crossoverPoint2=tmp;
1769  }
1770  if(crossoverPoint1==crossoverPoint2) crossoverPoint2+=1;
1771  for(int j=0;j<mRefParList.GetNbPar();j++)
1772  {
1773  if((refParGeneGroupIndex(j)>crossoverPoint1)&&refParGeneGroupIndex(j)<crossoverPoint2)
1774  {
1775  mRefParList.GetParamSet(parSetOffspringA)(j)=
1776  mRefParList.GetParamSet(worldCurrentSetIndex(i))(j);
1777  mRefParList.GetParamSet(parSetOffspringB)(j)=
1778  mRefParList.GetParamSet(worldCurrentSetIndex(k))(j);
1779  }
1780  else
1781  {
1782  mRefParList.GetParamSet(parSetOffspringA)(j)=
1783  mRefParList.GetParamSet(worldCurrentSetIndex(k))(j);
1784  mRefParList.GetParamSet(parSetOffspringB)(j)=
1785  mRefParList.GetParamSet(worldCurrentSetIndex(i))(j);
1786  }
1787  }
1788  #endif
1789  // Try both offspring
1790  for(int junk=0;junk<2;junk++)
1791  {
1792  if(junk==0) mRefParList.RestoreParamSet(parSetOffspringA);
1793  else mRefParList.RestoreParamSet(parSetOffspringB);
1794  REAL cost=this->GetLogLikelihood();
1795  //if(log((rand()+1)/(REAL)RAND_MAX)
1796  // < (-(cost-currentCost(k))/simAnnealTemp(k)))
1797  if(cost<currentCost(k))
1798  {
1799  // Also exchange genes for higher-temperature World ?
1800  //if(junk==0)
1801  // mRefParList.GetParamSet(worldCurrentSetIndex(i))=
1802  // mRefParList.GetParamSet(parSetOffspringB);
1803  //else
1804  // mRefParList.GetParamSet(worldCurrentSetIndex(i))=
1805  // mRefParList.GetParamSet(parSetOffspringA);
1806  currentCost(k)=cost;
1807  mRefParList.SaveParamSet(worldCurrentSetIndex(k));
1808  //worldNbAcceptedMoves(k)++;
1809  if(!silent) cout << "Accepted mating :"<<k<<"(with"<<i<<")"
1810  <<" (crossoverGene1="<< crossoverPoint1<<","
1811  <<" crossoverGene2="<< crossoverPoint2<<")"
1812  <<endl;
1813  if(cost<runBestCost)
1814  {
1815  runBestCost=cost;
1816  this->TagNewBestConfig();
1817  needUpdateDisplay=true;
1818  mRefParList.SaveParamSet(runBestIndex);
1819  if(cost<mBestCost)
1820  {
1821  mBestCost=cost;
1823  if(!silent) cout << "->Trial :" << mNbTrial
1824  << " World="<< worldSwapIndex(k)
1825  << " Temp="<< simAnnealTemp(k)
1826  << " Mutation Ampl.: "<<mMutationAmplitude
1827  << " NEW OVERALL Best Cost="<<mBestCost<< "(MATING !)"<<endl;
1828  }
1829  else if(!silent) cout << "->Trial :" << mNbTrial
1830  << " World="<< worldSwapIndex(k)
1831  << " Temp="<< simAnnealTemp(k)
1832  << " Mutation Ampl.: "<<mMutationAmplitude
1833  << " NEW RUN Best Cost="<<runBestCost<< "(MATING !)"<<endl;
1834  bestConfigNb=mNbTrial;
1835  if(!silent) this->DisplayReport();
1836  //for(int i=0;i<mRefinedObjList.GetNb();i++)
1837  // mRefinedObjList.GetObj(i).Print();
1838  }
1839  i=k;//Don't test other Worlds
1840  break;
1841  }
1842  //mNbTrial++;nbStep--;
1843  //if((mNbTrial%nbTrialsReport)==0) makeReport=true;
1844  }
1845  }
1846  TAU_PROFILE_STOP(timer1);
1847  #endif
1848  if(true==makeReport)
1849  {
1850  makeReport=false;
1851  worldNbAcceptedMoves*=nbWorld;
1852  if(!silent)
1853  {
1854  #if 0
1855  {// Experimental, dynamical weighting
1856  REAL max=0.;
1857  map<const RefinableObj*,REAL> ll,llvar;
1858  map<const RefinableObj*,LogLikelihoodStats>::iterator pos;
1859  for(pos=mvContextObjStats[0].begin();pos!=mvContextObjStats[0].end();++pos)
1860  {
1861  ll [pos->first]=0.;
1862  llvar[pos->first]=0.;
1863  }
1864  for(int i=0;i<nbWorld;i++)
1865  {
1866  for(pos=mvContextObjStats[0].begin();pos!=mvContextObjStats[0].end();++pos)
1867  {
1868  ll [pos->first] += pos->second.mTotalLogLikelihood;
1869  llvar[pos->first] += pos->second.mTotalLogLikelihoodDeltaSq;
1870  }
1871  }
1872  for(pos=mvContextObjStats[0].begin();pos!=mvContextObjStats[0].end();++pos)
1873  {
1874  cout << pos->first->GetName()
1875  << " " << llvar[pos->first]
1876  << " " << mvObjWeight[pos->first].mWeight
1877  << " " << max<<endl;
1878  llvar[pos->first] *= mvObjWeight[pos->first].mWeight;
1879  if(llvar[pos->first]>max) max=llvar[pos->first];
1880  }
1881  map<const RefinableObj*,REAL>::iterator pos2;
1882  for(pos2=llvar.begin();pos2!=llvar.end();++pos2)
1883  {
1884  const REAL d=pos2->second;
1885  if(d<(max/mvObjWeight.size()/10.))
1886  {
1887  if(d<1) continue;
1888  mvObjWeight[pos2->first].mWeight *=2;
1889  }
1890  }
1891  REAL ll1=0;
1892  REAL llt=0;
1893  for(pos2=ll.begin();pos2!=ll.end();++pos2)
1894  {
1895  llt += pos2->second;
1896  ll1 += pos2->second * mvObjWeight[pos2->first].mWeight;
1897  }
1898  map<const RefinableObj*,DynamicObjWeight>::iterator posw;
1899  for(posw=mvObjWeight.begin();posw!=mvObjWeight.end();++posw)
1900  {
1901  posw->second.mWeight *= llt/ll1;
1902  }
1903  }
1904  #endif //Experimental dynamical weighting
1905  #if 1 //def __DEBUG__
1906  for(int i=0;i<nbWorld;i++)
1907  {
1908  cout<<" World :"<<worldSwapIndex(i)<<":";
1909  map<const RefinableObj*,LogLikelihoodStats>::iterator pos;
1910  for(pos=mvContextObjStats[i].begin();pos!=mvContextObjStats[i].end();++pos)
1911  {
1912  cout << pos->first->GetName()
1913  << "(LLK="
1914  << pos->second.mLastLogLikelihood
1915  //<< "(<LLK>="
1916  //<< pos->second.mTotalLogLikelihood/nbTrialsReport
1917  //<< ", <delta(LLK)^2>="
1918  //<< pos->second.mTotalLogLikelihoodDeltaSq/nbTrialsReport
1919  << ", w="<<mvObjWeight[pos->first].mWeight
1920  <<") ";
1921  pos->second.mTotalLogLikelihood=0;
1922  pos->second.mTotalLogLikelihoodDeltaSq=0;
1923  }
1924  cout << endl;
1925  }
1926  #endif
1927  for(int i=0;i<nbWorld;i++)
1928  {
1929  //mRefParList.RestoreParamSet(worldCurrentSetIndex(i));
1930  cout <<" World :" << worldSwapIndex(i)
1931  <<" Temp.: " << simAnnealTemp(i)
1932  <<" Mutation Ampl.: " << mutationAmplitude(i)
1933  <<" Current Cost=" << currentCost(i)
1934  <<" Accepting "
1935  << (int)((REAL)worldNbAcceptedMoves(i)/nbTrialsReport*100)
1936  <<"% moves " <<endl;
1937  // <<"% moves " << mRefParList.GetPar("Pboccup").GetValue()<<endl;
1938  }
1939  }
1940  if(!silent) cout <<"Trial :" << mNbTrial << " Best Cost=" << runBestCost<< " ";
1941  if(!silent) chrono.print();
1942  //Change the mutation rate if necessary for each world
1943  if(ANNEALING_SMART==mAnnealingScheduleMutation.GetChoice())
1944  {
1945  for(int i=0;i<nbWorld;i++)
1946  {
1947  if((worldNbAcceptedMoves(i)/(REAL)nbTrialsReport)>0.30)
1948  mutationAmplitude(i)*=2.;
1949  if((worldNbAcceptedMoves(i)/(REAL)nbTrialsReport)<0.10)
1950  mutationAmplitude(i)/=2.;
1951  if(mutationAmplitude(i)>mMutationAmplitudeMax)
1952  mutationAmplitude(i)=mMutationAmplitudeMax;
1953  if(mutationAmplitude(i)<mMutationAmplitudeMin)
1954  mutationAmplitude(i)=mMutationAmplitudeMin;
1955  }
1956  }
1957  if(ANNEALING_SMART==mAnnealingScheduleTemp.GetChoice())
1958  {
1959  for(int i=0;i<nbWorld;i++)
1960  {
1961  if((worldNbAcceptedMoves(i)/(REAL)nbTrialsReport)>0.30)
1962  simAnnealTemp(i)/=1.5;
1963  if((worldNbAcceptedMoves(i)/(REAL)nbTrialsReport)>0.80)
1964  simAnnealTemp(i)/=1.5;
1965  if((worldNbAcceptedMoves(i)/(REAL)nbTrialsReport)>0.95)
1966  simAnnealTemp(i)/=1.5;
1967 
1968  if((worldNbAcceptedMoves(i)/(REAL)nbTrialsReport)<0.10)
1969  simAnnealTemp(i)*=1.5;
1970  if((worldNbAcceptedMoves(i)/(REAL)nbTrialsReport)<0.04)
1971  simAnnealTemp(i)*=1.5;
1972  //if((worldNbAcceptedMoves(i)/(REAL)nbTrialsReport)<0.01)
1973  // simAnnealTemp(i)*=1.5;
1974  //cout<<"World#"<<i<<":"<<worldNbAcceptedMoves(i)<<":"<<nbTrialsReport<<endl;
1975  //if(simAnnealTemp(i)>mTemperatureMax) simAnnealTemp(i)=mTemperatureMax;
1976  //if(simAnnealTemp(i)<mTemperatureMin) simAnnealTemp(i)=mTemperatureMin;
1977  }
1978  }
1979  worldNbAcceptedMoves=0;
1980  //this->DisplayReport();
1981 
1982  #ifdef __WX__CRYST__
1983  if(0!=mpWXCrystObj) mpWXCrystObj->UpdateDisplayNbTrial();
1984  #endif
1985  }
1986  if( (needUpdateDisplay&&(lastUpdateDisplayTime<(chrono.seconds()-1)))||(lastUpdateDisplayTime<(chrono.seconds()-10)))
1987  {
1988  mRefParList.RestoreParamSet(runBestIndex);
1989  this->UpdateDisplay();
1990  needUpdateDisplay=false;
1991  lastUpdateDisplayTime=chrono.seconds();
1992  }
1993  #ifdef __WX__CRYST__
1994  mMutexStopAfterCycle.Lock();
1995  #endif
1996  if((runBestCost<finalcost) || mStopAfterCycle ||( (maxTime>0)&&(chrono.seconds()>maxTime)))
1997  {
1998  #ifdef __WX__CRYST__
1999  mMutexStopAfterCycle.Unlock();
2000  #endif
2001  if(!silent) cout << endl <<endl << "Refinement Stopped:"<<mBestCost<<endl;
2002  break;
2003  }
2004  #ifdef __WX__CRYST__
2005  mMutexStopAfterCycle.Unlock();
2006  #endif
2007  }//Trials
2008 
2009  TAU_PROFILE_START(timerN);
2010  if(mAutoLSQ.GetChoice()>0)
2011  {// LSQ
2012  if(!silent) cout<<"Beginning final LSQ refinement"<<endl;
2013  for(int i=0;i<mRefinedObjList.GetNb();i++) mRefinedObjList.GetObj(i).SetApproximationFlag(false);
2014  mRefParList.RestoreParamSet(runBestIndex);
2016  try {mLSQ.Refine(-50,true,true,false,0.001);}
2017  catch(const ObjCrystException &except){};
2018  if(!silent) cout<<"LSQ cost: "<<mCurrentCost<<" -> "<<this->GetLogLikelihood()<<endl;
2019 
2020  // Need to go back to optimization with approximations allowed (they are not during LSQ)
2021  for(int i=0;i<mRefinedObjList.GetNb();i++) mRefinedObjList.GetObj(i).SetApproximationFlag(true);
2022 
2023  REAL cost=this->GetLogLikelihood();
2024  if(cost<mCurrentCost)
2025  {
2026  mCurrentCost=cost;
2027  mRefParList.SaveParamSet(lastParSavedSetIndex);
2028  if(mCurrentCost<runBestCost)
2029  {
2030  runBestCost=mCurrentCost;
2031  mRefParList.SaveParamSet(runBestIndex);
2032  if(runBestCost<mBestCost)
2033  {
2036  if(!silent) cout << "LSQ : NEW OVERALL Best Cost="<<runBestCost<< endl;
2037  }
2038  else if(!silent) cout << " LSQ : NEW Run Best Cost="<<runBestCost<< endl;
2039  }
2040  }
2041  if(!silent) cout<<"Finished LSQ refinement"<<endl;
2042  }
2043 
2044  mLastOptimTime=chrono.seconds();
2045  //Restore Best values
2046  //mRefParList.Print();
2047  if(!silent) this->DisplayReport();
2048  mRefParList.RestoreParamSet(runBestIndex);
2049  //for(int i=0;i<mRefinedObjList.GetNb();i++) mRefinedObjList.GetObj(i).Print();
2051  if(!silent) cout<<"Run Best Cost:"<<mCurrentCost<<endl;
2052  if(!silent) chrono.print();
2053  //Save density of states
2054  //ofstream out("densityOfStates.txt");
2055  //out << trialsDensity<<endl;
2056  //out.close();
2057  // Clear temporary param set
2058  for(int i=0;i<nbWorld;i++)
2059  {
2060  mRefParList.ClearParamSet(worldCurrentSetIndex(i));
2061  //mvSavedParamSet.push_back(make_pair(worldCurrentSetIndex(i),currentCost(i)));
2062  }
2063  mRefParList.ClearParamSet(lastParSavedSetIndex);
2064  mRefParList.ClearParamSet(runBestIndex);
2065  TAU_PROFILE_STOP(timerN);
2066 }
2067 
2068 void MonteCarloObj::XMLOutput(ostream &os,int indent)const
2069 {
2070  VFN_DEBUG_ENTRY("MonteCarloObj::XMLOutput():"<<this->GetName(),5)
2071  for(int i=0;i<indent;i++) os << " " ;
2072  XMLCrystTag tag("GlobalOptimObj");
2073  tag.AddAttribute("Name",this->GetName());
2074  tag.AddAttribute("NbTrialPerRun",(boost::format("%d")%(this->NbTrialPerRun())).str());
2075 
2076  os <<tag<<endl;
2077  indent++;
2078 
2079  mGlobalOptimType.XMLOutput(os,indent);
2080  os<<endl;
2081 
2082  mAnnealingScheduleTemp.XMLOutput(os,indent);
2083  os<<endl;
2084 
2085  mXMLAutoSave.XMLOutput(os,indent);
2086  os<<endl;
2087 
2088  mAutoLSQ.XMLOutput(os,indent);
2089  os<<endl;
2090 
2091  {
2092  XMLCrystTag tag2("TempMaxMin");
2093  for(int i=0;i<indent;i++) os << " " ;
2094  os<<tag2<<mTemperatureMax << " "<< mTemperatureMin;
2095  tag2.SetIsEndTag(true);
2096  os<<tag2<<endl;
2097  }
2098 
2100  os<<endl;
2101 
2102  mSaveTrackedData.XMLOutput(os,indent);
2103  os<<endl;
2104 
2105  {
2106  XMLCrystTag tag2("MutationMaxMin");
2107  for(int i=0;i<indent;i++) os << " " ;
2108  os<<tag2<<mMutationAmplitudeMax << " "<< mMutationAmplitudeMin;
2109  tag2.SetIsEndTag(true);
2110  os<<tag2<<endl;
2111  }
2112 
2113  for(int j=0;j<mRefinedObjList.GetNb();j++)
2114  {
2115  XMLCrystTag tag2("RefinedObject",false,true);
2116  tag2.AddAttribute("ObjectType",mRefinedObjList.GetObj(j).GetClassName());
2117  tag2.AddAttribute("ObjectName",mRefinedObjList.GetObj(j).GetName());
2118  for(int i=0;i<indent;i++) os << " " ;
2119  os<<tag2<<endl;
2120  }
2121 
2122  indent--;
2123  tag.SetIsEndTag(true);
2124  for(int i=0;i<indent;i++) os << " " ;
2125  os <<tag<<endl;
2126  VFN_DEBUG_EXIT("MonteCarloObj::XMLOutput():"<<this->GetName(),5)
2127 }
2128 
2129 void MonteCarloObj::XMLInput(istream &is,const XMLCrystTag &tagg)
2130 {
2131  VFN_DEBUG_ENTRY("MonteCarloObj::XMLInput():"<<this->GetName(),5)
2132  for(unsigned int i=0;i<tagg.GetNbAttribute();i++)
2133  {
2134  if("Name"==tagg.GetAttributeName(i)) this->SetName(tagg.GetAttributeValue(i));
2135  if("NbTrialPerRun"==tagg.GetAttributeName(i))
2136  {
2137  stringstream ss(tagg.GetAttributeValue(i));
2138  long v;
2139  ss>>v;
2140  this->NbTrialPerRun()=v;
2141  }
2142  }
2143  while(true)
2144  {
2145  XMLCrystTag tag(is);
2146  if(("GlobalOptimObj"==tag.GetName())&&tag.IsEndTag())
2147  {
2148  VFN_DEBUG_EXIT("MonteCarloObj::Exit():"<<this->GetName(),5)
2149  this->UpdateDisplay();
2150  return;
2151  }
2152  if("Option"==tag.GetName())
2153  {
2154  for(unsigned int i=0;i<tag.GetNbAttribute();i++)
2155  if("Name"==tag.GetAttributeName(i))
2156  {
2157  if("Algorithm"==tag.GetAttributeValue(i))
2158  {
2159  mGlobalOptimType.XMLInput(is,tag);
2160  break;
2161  }
2162  if("Temperature Schedule"==tag.GetAttributeValue(i))
2163  {
2165  break;
2166  }
2167  if("Displacement Amplitude Schedule"==tag.GetAttributeValue(i))
2168  {
2170  break;
2171  }
2172  if("Save Best Config Regularly"==tag.GetAttributeValue(i))
2173  {
2174  mXMLAutoSave.XMLInput(is,tag);
2175  break;
2176  }
2177  if("Save Tracked Data"==tag.GetAttributeValue(i))
2178  {
2179  mSaveTrackedData.XMLInput(is,tag);
2180  break;
2181  }
2182  if("Automatic Least Squares Refinement"==tag.GetAttributeValue(i))
2183  {
2184  mAutoLSQ.XMLInput(is,tag);
2185  break;
2186  }
2187  }
2188  continue;
2189  }
2190  if("TempMaxMin"==tag.GetName())
2191  {
2193  if(false==tag.IsEmptyTag()) XMLCrystTag junk(is);//:KLUDGE: for first release
2194  continue;
2195  }
2196  if("MutationMaxMin"==tag.GetName())
2197  {
2199  if(false==tag.IsEmptyTag()) XMLCrystTag junk(is);//:KLUDGE: for first release
2200  continue;
2201  }
2202  if("RefinedObject"==tag.GetName())
2203  {
2204  string name,type;
2205  for(unsigned int i=0;i<tag.GetNbAttribute();i++)
2206  {
2207  if("ObjectName"==tag.GetAttributeName(i)) name=tag.GetAttributeValue(i);
2208  if("ObjectType"==tag.GetAttributeName(i)) type=tag.GetAttributeValue(i);
2209  }
2210  RefinableObj* obj=& (gRefinableObjRegistry.GetObj(name,type));
2211  this->AddRefinableObj(*obj);
2212  continue;
2213  }
2214  }
2215 }
2216 
2217 const string MonteCarloObj::GetClassName()const { return "MonteCarloObj";}
2218 
2220 
2221 const LSQNumObj& MonteCarloObj::GetLSQObj() const{return mLSQ;}
2222 
2224 {
2225  TAU_PROFILE("MonteCarloObj::NewConfiguration()","void ()",TAU_DEFAULT);
2226  VFN_DEBUG_ENTRY("MonteCarloObj::NewConfiguration()",4)
2227  for(int i=0;i<mRefinedObjList.GetNb();i++)
2228  mRefinedObjList.GetObj(i).BeginGlobalOptRandomMove();
2229  for(int i=0;i<mRefinedObjList.GetNb();i++)
2230  mRefinedObjList.GetObj(i).GlobalOptRandomMove(mMutationAmplitude,type);
2231  VFN_DEBUG_EXIT("MonteCarloObj::NewConfiguration()",4)
2232 }
2233 
2235 {
2236  VFN_DEBUG_MESSAGE("MonteCarloObj::InitOptions()",5)
2238  static string GlobalOptimTypeName;
2239  static string GlobalOptimTypeChoices[2];//:TODO: Add Genetic Algorithm
2240 
2241  static string AnnealingScheduleChoices[6];
2242 
2243  static string AnnealingScheduleTempName;
2244  static string AnnealingScheduleMutationName;
2245 
2246  static string runAutoLSQName;
2247  static string runAutoLSQChoices[3];
2248 
2249  static string saveTrackedDataName;
2250  static string saveTrackedDataChoices[2];
2251 
2252  static bool needInitNames=true;
2253  if(true==needInitNames)
2254  {
2255  GlobalOptimTypeName="Algorithm";
2256  GlobalOptimTypeChoices[0]="Simulated Annealing";
2257  GlobalOptimTypeChoices[1]="Parallel Tempering";
2258  //GlobalOptimTypeChoices[2]="Random-LSQ";
2259 
2260  AnnealingScheduleTempName="Temperature Schedule";
2261  AnnealingScheduleMutationName="Displacement Amplitude Schedule";
2262  AnnealingScheduleChoices[0]="Constant";
2263  AnnealingScheduleChoices[1]="Boltzmann";
2264  AnnealingScheduleChoices[2]="Cauchy";
2265  AnnealingScheduleChoices[3]="Exponential";
2266  AnnealingScheduleChoices[4]="Smart";
2267  AnnealingScheduleChoices[5]="Gamma";
2268 
2269  runAutoLSQName="Automatic Least Squares Refinement";
2270  runAutoLSQChoices[0]="Never";
2271  runAutoLSQChoices[1]="At the end of each run";
2272  runAutoLSQChoices[2]="Every 150000 trials, and at the end of each run";
2273 
2274  saveTrackedDataName="Save Tracked Data";
2275  saveTrackedDataChoices[0]="No (recommended!)";
2276  saveTrackedDataChoices[1]="Yes (for tests ONLY)";
2277 
2278  needInitNames=false;//Only once for the class
2279  }
2280  mGlobalOptimType.Init(2,&GlobalOptimTypeName,GlobalOptimTypeChoices);
2281  mAnnealingScheduleTemp.Init(6,&AnnealingScheduleTempName,AnnealingScheduleChoices);
2282  mAnnealingScheduleMutation.Init(6,&AnnealingScheduleMutationName,AnnealingScheduleChoices);
2283  mSaveTrackedData.Init(2,&saveTrackedDataName,saveTrackedDataChoices);
2284  mAutoLSQ.Init(3,&runAutoLSQName,runAutoLSQChoices);
2285  this->AddOption(&mGlobalOptimType);
2288  this->AddOption(&mSaveTrackedData);
2289  this->AddOption(&mAutoLSQ);
2290  VFN_DEBUG_MESSAGE("MonteCarloObj::InitOptions():End",5)
2291 }
2292 
2293 void MonteCarloObj::InitLSQ(const bool useFullPowderPatternProfile)
2294 {
2295  mLSQ.SetRefinedObj(mRecursiveRefinedObjList.GetObj(0),0,true,true);
2296  for(unsigned int i=1;i<mRefinedObjList.GetNb();++i)
2297  mLSQ.SetRefinedObj(mRefinedObjList.GetObj(i),0,false,true);
2298 
2299  if(!useFullPowderPatternProfile)
2300  {// Use LSQ function #1 for powder patterns (integrated patterns - faster !)
2301  for(map<RefinableObj*,unsigned int>::iterator pos=mLSQ.GetRefinedObjMap().begin();pos!=mLSQ.GetRefinedObjMap().end();++pos)
2302  if(pos->first->GetClassName()=="PowderPattern") pos->second=1;
2303  }
2304  // Only refine structural parameters (excepting parameters already fixed) and scale factor
2305  mLSQ.PrepareRefParList(true);
2306 
2307  // Intensity corrections can be refined
2308  std::list<RefinablePar*> vIntCorrPar;
2309  for(int i=0; i<mLSQ.GetCompiledRefinedObj().GetNbPar();i++)
2311  vIntCorrPar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar(i));
2312 
2315 
2316  for(std::list<RefinablePar*>::iterator pos=vIntCorrPar.begin();pos!=vIntCorrPar.end();pos++)
2317  (*pos)->SetIsFixed(false);
2318  mLSQ.SetParIsFixed(gpRefParTypeUnitCell,true);
2319  mLSQ.SetParIsFixed(gpRefParTypeScattPow,true);
2320  mLSQ.SetParIsFixed(gpRefParTypeRadiation,true);
2321 }
2322 
2324 {
2325  Chronometer chrono;
2326  #ifdef __WX__CRYST__
2327  if(0!=mpWXCrystObj) mpWXCrystObj->CrystUpdate(true,true);
2328  #endif
2330 }
2331 
2332 #ifdef __WX__CRYST__
2333 WXCrystObjBasic* MonteCarloObj::WXCreate(wxWindow *parent)
2334 {
2335  mpWXCrystObj=new WXMonteCarloObj (parent,this);
2336  return mpWXCrystObj;
2337 }
2338 WXOptimizationObj* MonteCarloObj::WXGet()
2339 {
2340  return mpWXCrystObj;
2341 }
2342 void MonteCarloObj::WXDelete()
2343 {
2344  if(0!=mpWXCrystObj) delete mpWXCrystObj;
2345  mpWXCrystObj=0;
2346 }
2347 void MonteCarloObj::WXNotifyDelete()
2348 {
2349  mpWXCrystObj=0;
2350 }
2351 #endif
2352 
2353 }//namespace
The namespace which includes all objects (crystallographic and algorithmic) in ObjCryst++.
Definition: doc-main.h:25
void RefObjRegisterRecursive(T &obj, ObjRegistry< T > &reg)
Register a new object in a registry, and recursively include all included (sub)objects.
const RefParType * gpRefParTypeScattDataScale
Type for scattering data scale factors.
ObjRegistry< OptimizationObj > gOptimizationObjRegistry("List of all Optimization objects")
Global Registry for all OptimizationObj.
void(* fpObjCrystInformUser)(const string &)
Pointer to a function for passing info to the user during or after long/important processes (use scar...
Definition: Exception.cpp:76
AnnealingSchedule
Annealing schedule type.
const RefParType * gpRefParTypeObjCryst
Top RefParType for the ObjCryst++ library.
void GetSubRefObjListClockRecursive(ObjRegistry< RefinableObj > &reg, RefinableObjClock &clock)
Get the last time any object was added in the recursive list of objects.
ObjRegistry< RefinableObj > gRefinableObjRegistry("Global RefinableObj registry")
Global Registry for all RefinableObj.
const RefParType * gpRefParTypeScattDataCorrInt
Generic type for correction to calculated intensities.
void GetRefParListClockRecursive(ObjRegistry< RefinableObj > &reg, RefinableObjClock &clock)
Get the last time any RefinablePar was added in a recursive list of objects.
const RefParType * gpRefParTypeScattData
Generic type for scattering data.
void XMLCrystFileSaveGlobal(const string &filename)
Save all Objcryst++ objects.
Crystal class: Unit cell, spacegroup, scatterers.
Definition: Crystal.h:98
REAL GetBondValenceCost() const
Get the Bond-Valence cost function, which compares the expected valence to the one computed from Bond...
Definition: Crystal.cpp:1531
ObjRegistry< Scatterer > & GetScattererRegistry()
Get the registry of scatterers.
Definition: Crystal.cpp:232
REAL GetBumpMergeCost() const
Get the Anti-bumping/pro-Merging cost function.
Definition: Crystal.cpp:938
Scatterer & GetScatt(const string &scattName)
Provides an access to the scatterers.
Definition: Crystal.cpp:212
Exception class for ObjCryst++ library.
Definition: General.h:122
Molecule : class for complex scatterer descriptions using cartesian coordinates with bond length/angl...
Definition: Molecule.h:760
Base object for Optimization methods.
virtual const string GetClassName() const
Get the name for this class type.
void AddRefinableObj(RefinableObj &)
Add a refined object. All sub-objects are also added.
void SetName(const string &)
Set the name for this object.
ObjRegistry< RefinableObj > mRecursiveRefinedObjList
The refined objects, recursively including all sub-objects.
REAL GetLastOptimElapsedTime() const
Get the elapsed time (in seconds) during the last optimization.
virtual void UpdateDisplay() const
Update Display (if any display is available), when a new 'relevant' configuration is reached.
unsigned int GetNbParamSet() const
Get the number of saved parameters set.
map< unsigned long, map< const RefinableObj *, LogLikelihoodStats > > mvContextObjStats
Statistics for each context (mutable for dynamic update during optimization)
void RestoreParamSet(const unsigned int i, const bool update_display=true)
Restore a given saved parameter set.
ObjRegistry< RefObjOpt > mOptionRegistry
List of options for this object.
bool IsOptimizing() const
Are we busy optimizing ?
void RestoreBestConfiguration()
Restore the Best configuration.
void StopAfterCycle()
Stop after the current cycle. USed for interactive refinement.
virtual void Print() const
Print some information about this object.
RefinableObj & GetFullRefinableObj(const bool rebuild=true)
Get the RefinableObj with all the parameters from all refined objects.
virtual REAL GetLogLikelihood() const
The optimized (minimized, actually) function.
virtual void EndOptimization()
End optimization for all objects.
REAL mBestCost
Best value of the cost function so far.
void AddOption(RefObjOpt *opt)
map< const RefinableObj *, DynamicObjWeight > mvObjWeight
Weights for each objects in each context (mutable for dynamic update during optimization)
OptimizationObj()
Default constructor.
virtual void RandomizeStartingConfig()
Randomize starting configuration.
virtual void DisplayReport()
Show report to the user during refinement. Used for GUI update.
long GetParamSetCost(const unsigned int i) const
Get the cost (log-likelihood) of a saved parameters set.
ObjRegistry< RefObjOpt > & GetOptionList()
Access to the options registry.
virtual void XMLOutput(ostream &os, int indent=0) const =0
Output a description of the object in XML format to a stream.
long GetParamSetIndex(const unsigned int i) const
Get the index of a saved parameters set in the compiled RefinableObj.
bool mIsOptimizing
True if a refinement is being done. For multi-threaded environment.
unsigned long mContext
The current 'context', in the case the optimization is run in different parallel contexts.
ObjRegistry< RefinableObj > mRefinedObjList
The refined objects.
RefObjOpt & GetOption(const unsigned int i)
Access to the options.
void SetLimitsRelative(const string &parName, const REAL min, const REAL max)
Change the relative limits for a parameter from its name.
void BuildRecursiveRefObjList()
(Re)build OptimizationObj::mRecursiveRefinedObjList, if an object has been added or modified.
long mRun
Current run number (during multiple runs)
virtual void InitOptions()
Initialization of options.
std::vector< pair< long, REAL > > mvSavedParamSet
List of saved parameter sets.
long GetRun() const
Current run number (updated during a run)
long GetTrial() const
Current trial number (updated during a run)
RefObjOpt mXMLAutoSave
Periodic save of complete environment as an xml file.
void TagNewBestConfig()
During a global optimization, tell all objects that the current config is the latest "best" config.
RefinableObj mRefParList
The refinable par list used during refinement.
string mName
Name of the GlobalOptimization object.
long mNbTrialPerRun
Number of trial per run, to be saved/restored in XML output.
long mBestParSavedSetIndex
Index of the 'best' saved parameter set.
void SetParIsUsed(const string &parName, const bool use)
Set a parameter to be used.
virtual long & NbTrialPerRun()
Number of trial per run.
MainTracker mMainTracker
MainTracker object to track the evolution of cost functions, likelihood, and individual parameters.
bool mStopAfterCycle
If true, then stop at the end of the cycle. Used in multi-threaded environment.
REAL mLastOptimTime
The time elapsed after the last optimization, in seconds.
const REAL & GetBestCost() const
Access to current best cost.
void SetParIsFixed(const string &parName, const bool fix)
Fix one parameter.
unsigned int GetNbOption() const
Number of Options for this object.
void SetLimitsAbsolute(const string &parName, const REAL min, const REAL max)
Change the absolute limits for a parameter from its name.
virtual void BeginOptimization(const bool allowApproximations=false, const bool enableRestraints=false)
Begin optimization for all objects.
const string & GetName() const
Get the name for this object.
void UnFixAllPar()
UnFix All parameters.
virtual ~OptimizationObj()
Destructor.
const ObjRegistry< RefinableObj > & GetRefinedObjList() const
Access the list of refined object.
long mNbTrial
Current trial number.
void FixAllPar()
Fix all parameters.
MainTracker & GetMainTracker()
Get the MainTracker.
Statistics about each object contributing to the overall Log(likelihood)
REAL mTotalLogLikelihoodDeltaSq
total of (Delta(Log(Likelihood)))^2 between successive trials
REAL mTotalLogLikelihood
Total Log(Likelihood), to compute the average.
REAL mLastLogLikelihood
Previous log(likelihood)
Base object for Monte-Carlo Global Optimization methods.
REAL mTemperatureMax
Beginning temperature for annealing.
REAL mTemperature
Current temperature for annealing.
virtual void XMLInput(istream &is, const XMLCrystTag &tag)
Input in XML format from a stream, restoring the set of refined objects and the associated cost funct...
REAL mMutationAmplitudeGamma
Gamma for the 'gamma' Mutation amplitude schedule.
long mNbTrialRetry
Number of trials before testing if we are below the given minimum cost.
LSQNumObj mLSQ
Least squares object.
RefObjOpt mAutoLSQ
Option to run automatic least-squares refinements.
virtual ~MonteCarloObj()
Destructor.
virtual void InitOptions()
Initialization of options.
virtual const string GetClassName() const
Get the name for this class type.
virtual void XMLOutput(ostream &os, int indent=0) const
Output a description of the object in XML format to a stream.
void SetAlgorithmParallTempering(const AnnealingSchedule scheduleTemp, const REAL tMax, const REAL tMin, const AnnealingSchedule scheduleMutation=ANNEALING_CONSTANT, const REAL mutMax=16., const REAL mutMin=.125)
Set the refinement method to Parallel Tempering.
RefObjOpt mAnnealingScheduleMutation
Schedule for the annealing.
virtual void NewConfiguration(const RefParType *type=gpRefParTypeObjCryst)
Make a random change in the configuration.
MonteCarloObj()
Default Constructor.
virtual void UpdateDisplay() const
Update Display (if any display is available), when a new 'relevant' configuration is reached.
REAL mMutationAmplitudeMin
Mutation amplitude at the end of the optimization.
void RunParallelTempering(long &nbSteps, const bool silent=false, const REAL finalcost=0, const REAL maxTime=-1)
void RunSimulatedAnnealing(long &nbSteps, const bool silent=false, const REAL finalcost=0, const REAL maxTime=-1)
virtual void MultiRunOptimize(long &nbCycle, long &nbSteps, const bool silent=false, const REAL finalcost=0, const REAL maxTime=-1)
Launch optimization for multiple runs of N steps.
REAL mTemperatureMin
Lower temperature.
REAL mCurrentCost
Current value of the cost function.
REAL mMinCostRetry
Cost to reach unless an automatic randomization and retry is done.
void SetAlgorithmSimulAnnealing(const AnnealingSchedule scheduleTemp, const REAL tMax, const REAL tMin, const AnnealingSchedule scheduleMutation=ANNEALING_CONSTANT, const REAL mutMax=16., const REAL mutMin=.125, const long nbTrialRetry=0, const REAL minCostRetry=0.)
Set the refinement method to simulated Annealing.
RefObjOpt mSaveTrackedData
Option to save the evolution of tracked data (cost functions, likelihhod, individual parameters,...
virtual void InitLSQ(const bool useFullPowderPatternProfile=true)
Prepare mLSQ for least-squares refinement during the global optimization.
virtual void Optimize(long &nbSteps, const bool silent=false, const REAL finalcost=0, const REAL maxTime=-1)
Launch optimization (a single run) for N steps.
LSQNumObj & GetLSQObj()
Access to the builtin LSQ optimization object.
REAL mMutationAmplitudeMax
Mutation amplitude at the beginning of the optimization.
RefObjOpt mAnnealingScheduleTemp
Schedule for the annealing.
REAL mTemperatureGamma
Gamma for the 'gamma' temperature schedule.
RefObjOpt mGlobalOptimType
Method used for the global optimization.
REAL mMutationAmplitude
Mutation amplitude.
class to input or output a well-formatted xml beginning or ending tag.
(Quick & dirty) Least-Squares Refinement Object with Numerical derivatives
Definition: LSQNumObj.h:39
void SetParIsFixed(const std::string &parName, const bool fix)
Fix one parameter.
const std::map< RefinableObj *, unsigned int > & GetRefinedObjMap() const
Get the map of refined objects - this is a recursive list of all the objects that are taken into acco...
Definition: LSQNumObj.cpp:837
void Refine(int nbCycle=1, bool useLevenbergMarquardt=false, const bool silent=false, const bool callBeginEndOptimization=true, const float minChi2var=0.01)
Do the refinement.
Definition: LSQNumObj.cpp:106
void SetRefinedObj(RefinableObj &obj, const unsigned int LSQFuncIndex=0, const bool init=true, const bool recursive=false)
Choose the object to refine.
Definition: LSQNumObj.cpp:824
RefinableObj & GetCompiledRefinedObj()
Access to the RefinableObj which is the compilation of all parameters from the object supplied for op...
Definition: LSQNumObj.cpp:848
void PrepareRefParList(const bool copy_param=false)
Prepare the full parameter list for the refinement.
Definition: LSQNumObj.cpp:913
class of refinable parameter types.
Definition: RefinableObj.h:80
bool IsDescendantFromOrSameAs(const RefParType *type) const
Returns true if the parameter is a descendant of 'type'.
We need to record exactly when refinable objects have been modified for the last time (to avoid re-co...
Definition: RefinableObj.h:140
REAL GetMin() const
Minimum value allowed (if limited or periodic)
void MutateTo(const REAL newValue)
Change the current value to the given one.
REAL GetMax() const
Get the maximum value allowed (if limited)
REAL GetPeriod() const
Get the period (if periodic)
Base class for options.
Definition: RefinableObj.h:552
void XMLInput(istream &is, const XMLCrystTag &tag)
XMLInput From stream.
void XMLOutput(ostream &os, int indent=0) const
XMLOutput to stream in well-formed XML.
Object Registry.
Definition: RefinableObj.h:645
Generic Refinable Object.
Definition: RefinableObj.h:784
void RestoreParamSet(const unsigned long id)
Restore a saved set of values.
void AddPar(const RefinablePar &newRefPar)
Add a refinable parameter.
RefinablePar & GetPar(const long i)
Access all parameters in the order they were inputted.
virtual const string & GetName() const
Name of the object.
void SetDeleteRefParInDestructor(const bool b)
Set this object not to delete its list of parameters when destroyed.
long GetNbPar() const
Total number of refinable parameter in the object.
void ResetParList()
Re-init the list of refinable parameters, removing all parameters.
void SaveParamSet(const unsigned long id) const
Save the current set of refined values over a previously-created set of saved values.
void PrepareForRefinement() const
Find which parameters are used and not fixed, for a refinement /optimization.
RefinablePar & GetParNotFixed(const long i)
Access all parameters in the order they were inputted, skipping fixed parameters.
const RefinableObjClock & GetRefParListClock() const
What was the last time a RefinablePar was added/removed ?
const CrystVector_REAL & GetParamSet(const unsigned long setId) const
Access one save refpar set.
void ClearParamSet(const unsigned long id) const
Erase the param set with the given id, releasing memory.
unsigned long CreateParamSet(const string name="") const
Save the current set of refined values in a new set.
const void EraseAllParamSet()
Erase all saved refpar sets.
virtual REAL GetLogLikelihood() const
Get -log(likelihood) of the current configuration for the object.
long GetNbParNotFixed() const
Total number of non-fixed parameters. Is initialized by PrepareForRefinement()
A class to hold all trackers.
Definition: Tracker.h:69
void SaveAll(std::ostream &out) const
Will save to a single file if all recorded trial numbers are the same Otherwise ?
Definition: Tracker.cpp:105
void ClearTrackers()
Removes all Trackers.
Definition: Tracker.cpp:88
void ClearValues()
Removes all stored values.
Definition: Tracker.cpp:97
void UpdateDisplay() const
Update display, if any.
Definition: Tracker.cpp:133
Tracker for objects (RefinableObj, Crystal, PowderPattern, RefPar,...)
Definition: Tracker.h:110
Simple chronometer class, with microsecond precision.
Definition: Chronometer.h:35
Abstract base class for all objects in wxCryst.
Definition: wxCryst.h:128
Class for Graphical interface to Monte-Carlo objects (Simulated Annealing, Parallel Tempering)