FOX/ObjCryst++  2022
wxGlobalOptimObj.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 //#include <sstream> //for stringstream
20 #include <fstream>
21 
22 // wx headers, with or without precompilation
23 #include "wx/wxprec.h"
24 #ifdef __BORLANDC__
25  #pragma hdrstop
26 #endif
27 #ifndef WX_PRECOMP
28  #include "wx/wx.h"
29 #endif
30 
31 #include "wx/progdlg.h"
32 
33 #include "ObjCryst/wxCryst/wxGlobalOptimObj.h"
34 
35 #include "ObjCryst/ObjCryst/IO.h"
36 // Next two just to fix some parameters during global optimization
37 #include "ObjCryst/ObjCryst/Crystal.h"
38 #include "ObjCryst/ObjCryst/ScatteringData.h"
39 
40 //Fixes for Cygwin; where do those stupid macros come from ? Somewhere in wxMSW headers
41 #ifdef max
42 #undef max
43 #endif
44 #ifdef min
45 #undef min
46 #endif
47 #ifdef DrawText
48 #undef DrawText
49 #endif
50 
51 namespace ObjCryst
52 {
53 
55 //
56 // WXOptimizationObj
57 //
59 static long ID_GLOBALOPT_MENU_OBJECTS= WXCRYST_ID();
60 static long ID_GLOBALOPT_MENU_OBJECTS_ADDOBJ= WXCRYST_ID();
61 static long ID_GLOBALOPT_MENU_OBJECTS_REMOVEOBJ= WXCRYST_ID();
62 static long ID_GLOBALOPT_MENU_OBJECTS_ADDCOSTFUNC= WXCRYST_ID();
63 static long ID_GLOBALOPT_MENU_OBJECTS_REMOVECOSTFUNC=WXCRYST_ID();
64 static long ID_GLOBALOPT_MENU_OPT= WXCRYST_ID();
65 static long ID_GLOBALOPT_MENU_OPT_RUN= WXCRYST_ID();
66 static long ID_GLOBALOPT_MENU_OPT_RUN_MULTIPLE= WXCRYST_ID();
67 static long ID_GLOBALOPT_MENU_OPT_STOP= WXCRYST_ID();
68 static long ID_GLOBALOPT_MENU_OPT_LSQ= WXCRYST_ID();
69 static long ID_GLOBALOPT_MENU_SOLUTIONS= WXCRYST_ID();
70 static long ID_GLOBALOPT_MENU_SOLUTIONS_BROWSE= WXCRYST_ID();
71 static long ID_BROWSE_WIN= WXCRYST_ID();
72 
73 WXOptimizationObj::WXOptimizationObj(wxWindow* parent, OptimizationObj *obj):
74 WXCrystObj(parent),mpGlobalOptimRunThread(0)
75 {
76  VFN_DEBUG_ENTRY("WXOptimizationObj::WXOptimizationObj(wxWindow*,GlobalOptimObj*,)",7)
77  #ifdef VFN_CRYST_MUTEX
78  cout <<"new CrystMutex("<<&mMutex<<")for WXOptimizationObj:"<<obj->GetName()<<endl;
79  #endif
80  mpWXTitle->SetForegroundColour(wxColour(255,0,0));
81  mpWXTitle->SetLabel("Global Optimization:");
82  mpWXTitle->SetSize(400,-1);
83  // Menu
84  mpMenuBar=new WXCrystMenuBar(this,this);
85  mpSizer->Add(mpMenuBar);
86  mList.Add(mpMenuBar);
87 
88  //mpMenuBar->AddMenu("Object",ID_REFOBJ_MENU_OBJ);
89  //mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_REFOBJ_MENU_OBJ_SAVE,"Save");
90  //mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_REFOBJ_MENU_OBJ_LOAD,"Load");
91  mpMenuBar->AddMenu("Optimized Objects",ID_GLOBALOPT_MENU_OBJECTS);
92  mpMenuBar->AddMenuItem(ID_GLOBALOPT_MENU_OBJECTS,ID_GLOBALOPT_MENU_OBJECTS_ADDOBJ,
93  "Add object to optimize");
94  mpMenuBar->AddMenu("Run/Stop",ID_GLOBALOPT_MENU_OPT);
95  mpMenuBar->AddMenuItem(ID_GLOBALOPT_MENU_OPT,
96  ID_GLOBALOPT_MENU_OPT_RUN_MULTIPLE,"Multiple Runs");
97  mpMenuBar->AddMenuItem(ID_GLOBALOPT_MENU_OPT,
98  ID_GLOBALOPT_MENU_OPT_RUN,"Single Run");
99  mpMenuBar->AddMenuItem(ID_GLOBALOPT_MENU_OPT,
100  ID_GLOBALOPT_MENU_OPT_STOP,"Stop Optimization");
101  mpMenuBar->GetMenu(ID_GLOBALOPT_MENU_OPT).AppendSeparator();
102  mpMenuBar->AddMenuItem(ID_GLOBALOPT_MENU_OPT,
103  ID_GLOBALOPT_MENU_OPT_LSQ,"Least Squares Fit");
104  mpMenuBar->AddMenu("Solutions",ID_GLOBALOPT_MENU_SOLUTIONS);
105  mpMenuBar->AddMenuItem(ID_GLOBALOPT_MENU_SOLUTIONS,
106  ID_GLOBALOPT_MENU_SOLUTIONS_BROWSE,"Browse Solutions");
107  mpMenuBar->Layout();
108  //mpSizer->SetItemMinSize(mpMenuBar,
109  // mpMenuBar->GetSize().GetWidth(),
110  // mpMenuBar->GetSize().GetHeight());
111  //Refined Objects
112  for(int i=0;i<obj->mRefinedObjList.GetNb();i++)
113  {
114  WXFieldName *refobj=new WXFieldName(this,"Optimized object:",this,-1,300,false);
115  refobj->SetValue(obj->mRefinedObjList.GetObj(i).GetClassName()
116  +":"+obj->mRefinedObjList.GetObj(i).GetName());
117  mpSizer->Add(refobj);
118  mList.Add(refobj);
119  }
120 
121  // This will be done later
122  //this->CrystUpdate();
123  VFN_DEBUG_EXIT("WXOptimizationObj::WXOptimizationObj(wxWindow*,GlobalOptimObj*,)",7)
124 }
125 
126 void WXOptimizationObj::CrystUpdate(const bool uui,const bool lock)
127 {
128  VFN_DEBUG_ENTRY("WXOptimizationObj::CrystUpdate("<<uui<<lock<<")",7)
129  this->WXCrystObj::CrystUpdate(uui,lock);
130  if(uui)
131  {
132  if(true==wxThread::IsMain()) this->UpdateUI(lock);
133  else
134  {
135  wxUpdateUIEvent event(ID_CRYST_UPDATEUI);
136  wxPostEvent(this,event);
137  }
138  }
139  VFN_DEBUG_EXIT("WXOptimizationObj::CrystUpdate("<<uui<<lock<<")",7)
140 }
141 
142 bool WXOptimizationObj::OnChangeName(const int id)
143 {
144  VFN_DEBUG_MESSAGE("WXOptimizationObj::OnChangeName()",6)
145  if(id==ID_WXOBJ_NAME)
146  {
147  VFN_DEBUG_MESSAGE("WXOptimizationObj::OnChangeName():Changing GlobalOptimObj Name",6)
148  this->GetOptimizationObj().SetName(mpWXTitle->GetValue());
149  return true;
150  }
151  return false;
152 }
153 void WXOptimizationObj::OnSave(){}
154 
155 void WXOptimizationObj::OnLoad(){}
156 
157 void WXOptimizationObj::OnAddRefinedObject(wxCommandEvent & WXUNUSED(event))
158 {
160  int choice;
161  RefinableObj *obj=
163  "Choose object to optimize:",choice);
164  if(0==obj) return;
165  this->GetOptimizationObj().AddRefinableObj(*obj);
166 }
167 
168 void WXOptimizationObj::AddRefinedObject(RefinableObj &obj)
169 {
171  WXFieldName *refobj=new WXFieldName(this,"Optimized object:",this,-1,300,false);
172  refobj->SetValue(obj.GetClassName()+":"+obj.GetName());
173  mpSizer->Add(refobj);
174  mList.Add(refobj);
175  wxTheApp->GetTopWindow()->Layout();
176  wxTheApp->GetTopWindow()->SendSizeEvent();
177  refobj->UpdateUI(true);
178 }
179 
180 void WXOptimizationObj::OnRemoveRefinedObject(wxCommandEvent & WXUNUSED(event))
181 {
182 }
183 
184 void WXOptimizationObj::OnStopOptimization(wxCommandEvent & WXUNUSED(event))
185 {
186  if(0!=mpGlobalOptimRunThread)
187  {
188  if(mpGlobalOptimRunThread->IsAlive())
189  {
190  (*fpObjCrystInformUser)("Waiting for global optimization to stop...");
191  this->GetOptimizationObj().StopAfterCycle();
192  mpGlobalOptimRunThread->Wait(wxTHREAD_WAIT_YIELD);
193  this->GetOptimizationObj().UpdateDisplay();
194  (*fpObjCrystInformUser)("Global optimization halted...");
195  }
196  delete mpGlobalOptimRunThread;
197  mpGlobalOptimRunThread=0;
198  }
199 }
200 void WXOptimizationObj::OnUpdateUI(wxUpdateUIEvent& event)
201 {
202  VFN_DEBUG_ENTRY("WXOptimizationObj::OnUpdateUI()",5)
203  this->UpdateUI(true);
204  event.Skip();
205  VFN_DEBUG_EXIT("WXOptimizationObj::OnUpdateUI()",5)
206 }
207 
208 void WXOptimizationObj::UpdateUI(const bool lock)
209 {
210  VFN_DEBUG_ENTRY("WXOptimizationObj::UpdateUI()",5)
211  if(lock) mMutex.Lock();
212  mpWXTitle->SetValue(this->GetOptimizationObj().GetName());
213  mpWXTitle->UpdateUI(false);
214  this->WXCrystObj::UpdateUI(false);
215  if(lock) mMutex.Unlock();
216  VFN_DEBUG_EXIT("WXOptimizationObj::UpdateUI()",5)
217 }
218 
219 void WXOptimizationObj::OnBrowseParamSet(wxCommandEvent & WXUNUSED(event))
220 {
221  if(this->GetOptimizationObj().IsOptimizing())
222  {
223  wxMessageDialog dumbUser(this,_T("Cannot browse during Optimisation !"),
224  _T("Cannot browse during Optimisation!"),wxOK|wxICON_EXCLAMATION);
225  dumbUser.ShowModal();
226  return;
227  }
228  wxFrame *frame= new wxFrame(this,-1,_T("Stored Configurations"),
229  wxDefaultPosition,wxSize(250,200));
230  const long nb=this->GetOptimizationObj().mvSavedParamSet.size();
231  wxArrayString choices;
232  mpwxParamSetList=new wxListBox(frame, ID_BROWSE_WIN, wxDefaultPosition,
233  wxDefaultSize, choices,
234  wxLB_SINGLE|wxLB_NEEDED_SB, wxDefaultValidator,
235  _T("listBox"));
236  for(int i=0;i<nb;i++)
237  {
238  wxString tmpname=wxString::FromAscii(this->GetOptimizationObj().mRefParList.GetParamSetName
239  (this->GetOptimizationObj().mvSavedParamSet[i].first).c_str());
240  mpwxParamSetList->Append(wxString::Format(_T("%d, cost= %f, %s"),i,
241  this->GetOptimizationObj().mvSavedParamSet[i].second,tmpname.c_str()));
242  }
243  //mpwxParamSetList->SetEventHandler(this);
244  mClockParamSetWindow.Click();
245  frame->Show(true);
246 }
247 
248 void WXOptimizationObj::OnSelectParamSet(wxCommandEvent &event)
249 {
250 
251  if(this->GetOptimizationObj().IsOptimizing())
252  {
253  wxMessageDialog dumbUser(this,_T("Cannot browse during Optimisation !"),
254  _T("Cannot browse during Optimisation!"),wxOK|wxICON_EXCLAMATION);
255  dumbUser.ShowModal();
256  return;
257  }
258  const long n=event.GetSelection();
259  if(n>=0)
260  {// n=-1 when window is closed ?
261  // Window is alive, check the number of browsable parameters is unchanged
262  if(mpwxParamSetList->GetCount()!=this->GetOptimizationObj().mvSavedParamSet.size())
263  {
264  const long nb=this->GetOptimizationObj().mvSavedParamSet.size();
265  wxArrayString choices;
266  for(int i=0;i<nb;i++)
267  {
268  wxString tmpname=wxString::FromAscii(this->GetOptimizationObj().mRefParList.GetParamSetName
269  (this->GetOptimizationObj().mvSavedParamSet[i].first).c_str());
270  choices.Add(wxString::Format(_T("%d, cost= %f, %s"),i,
271  this->GetOptimizationObj().mvSavedParamSet[i].second,tmpname.c_str()));
272  }
273  mpwxParamSetList->Set(choices);
274  mClockParamSetWindow.Click();
275  //wxMessageDialog bad(mpwxParamSetList,_T("The list has changed. Updating"),
276  // _T("The list has changed. Updating"),wxOK|wxSTAY_ON_TOP);
277  //bad.ShowModal();
278  return;
279  }
280  if(mClockParamSetWindow>this->GetOptimizationObj().mRefParList.GetRefParListClock())
281  {
282  try
283  {
284  this->GetOptimizationObj().mRefParList
285  .RestoreParamSet(this->GetOptimizationObj().mvSavedParamSet[n].first);
286  }
287  catch(const ObjCrystException &except)
288  {
289  wxMessageDialog bad(this,_T("Impossible ! Model has been altered !"),
290  _T("Impossible ! Model has been altered !"),wxOK|wxICON_EXCLAMATION);
291  mpwxParamSetList->GetParent()->Close();
292  mpwxParamSetList=0;
293  }
294  this->GetOptimizationObj().UpdateDisplay();
295  cout <<"Param set #"<<this->GetOptimizationObj().mvSavedParamSet[n].first<<", cost="
296  <<this->GetOptimizationObj().mvSavedParamSet[n].second
297  <<", now cost="<<this->GetOptimizationObj().GetLogLikelihood()<<endl;
298  }
299  else
300  {
301  wxMessageDialog bad(this,_T("Impossible ! The list of parameters has been changed !"),
302  _T("Impossible ! The list of parameters has been changed !"),wxOK|wxICON_EXCLAMATION);
303  bad.ShowModal();
304  }
305  }
306 }
307 
308 #if 0
309 void WXOptimizationObj::OnClose(wxCloseEvent& event)
310 {
311  if(event.GetId()==ID_BROWSE_WIN)
312  {
313  cout<<"Closing browse window..."<<endl;
314  mpwxParamSetList=0;
315  }
316  else cout<<event.GetId()<<"?"<<endl;
317  event.Skip();
318 }
319 #endif
320 
322 //
323 // WXGlobalOptimRunThread
324 //
326 WXGlobalOptimRunThread::WXGlobalOptimRunThread(OptimizationObj &globalOptObj,long &nbTrial,
327  const REAL finalCost,long &nbRun,const bool multiple):
328 wxThread(wxTHREAD_JOINABLE),mpGlobalOptObj(&globalOptObj),mpNbTrial(&nbTrial),mpNbRun(&nbRun),
329 mFinalCost(finalCost),mDoMultiple(multiple)
330 {
331 }
332 
333 void *WXGlobalOptimRunThread::Entry()
334 {
335  (*fpObjCrystInformUser)("Entering refinement thread");
336  try{
337  if(mDoMultiple) mpGlobalOptObj->MultiRunOptimize(*mpNbRun,*mpNbTrial,false,mFinalCost);
338  else mpGlobalOptObj->Optimize(*mpNbTrial,false,mFinalCost);
339  (*fpObjCrystInformUser)("Finished global optimization");
340  }
341  catch(...){cout<<"Unhandled exception in WXGlobalOptimRunThread::Entry() ?"<<endl;}
342  return NULL;
343 }
344 
345 void WXGlobalOptimRunThread::OnExit()
346 {
347  (*fpObjCrystInformUser)("Exiting refinement thread");
348  XMLCrystFileSaveGlobal("Fox-LastOptimizationStop.xml");
349  (*fpObjCrystInformUser)("Optimization result saved to Fox-LastOptimizationStop.xml");
350 }
352 //
353 // WXMonteCarloObj
354 //
356 BEGIN_EVENT_TABLE(WXMonteCarloObj, wxWindow)
357  EVT_BUTTON(ID_WXOBJ_COLLAPSE, WXCrystObj::OnToggleCollapse)
358  //EVT_MENU(ID_REFOBJ_MENU_OBJ_SAVE, WXOptimizationObj::OnSave)
359  //EVT_MENU(ID_REFOBJ_MENU_OBJ_LOAD, WXOptimizationObj::OnLoad)
360  EVT_MENU(ID_GLOBALOPT_MENU_OBJECTS_ADDOBJ, WXOptimizationObj::OnAddRefinedObject)
361  EVT_MENU(ID_GLOBALOPT_MENU_OPT_RUN, WXOptimizationObj::OnRunOptimization)
362  EVT_MENU(ID_GLOBALOPT_MENU_OPT_RUN_MULTIPLE, WXOptimizationObj::OnRunOptimization)
363  EVT_MENU(ID_GLOBALOPT_MENU_OPT_STOP, WXOptimizationObj::OnStopOptimization)
364  EVT_MENU(ID_GLOBALOPT_MENU_OPT_LSQ, WXMonteCarloObj::OnLSQRefine)
365  EVT_MENU(ID_GLOBALOPT_MENU_SOLUTIONS_BROWSE, WXOptimizationObj::OnBrowseParamSet)
366  EVT_UPDATE_UI(ID_CRYST_UPDATEUI, WXOptimizationObj::OnUpdateUI)
367  EVT_LISTBOX(ID_BROWSE_WIN, WXOptimizationObj::OnSelectParamSet)
368  EVT_LISTBOX_DCLICK(ID_BROWSE_WIN, WXOptimizationObj::OnSelectParamSet)
369  //EVT_CLOSE( WXOptimizationObj::OnClose)
370 END_EVENT_TABLE()
371 
372 WXMonteCarloObj::WXMonteCarloObj(wxWindow *parent, MonteCarloObj* obj):
373 WXOptimizationObj(parent,obj),mpMonteCarloObj(obj),mNbRun(-1)
374 {
375  VFN_DEBUG_ENTRY("WXMonteCarloObj::WXMonteCarloObj()",7)
376  //options
377  WXFieldOption *opt;
378 
379  opt=new WXFieldOption(this,-1,&(mpMonteCarloObj->mGlobalOptimType));
380  mpSizer->Add(opt,0,wxALIGN_LEFT);
381  mList.Add(opt);
382 
383  opt=new WXFieldOption(this,-1,&(mpMonteCarloObj->mAnnealingScheduleTemp));
384  mpSizer->Add(opt,0,wxALIGN_LEFT);
385  mList.Add(opt);
386 
387  wxBoxSizer *sizerTemp=new wxBoxSizer(wxHORIZONTAL);
388  WXFieldPar<REAL> *tempMax=
389  new WXFieldPar<REAL>(this,"Temperature Max:",-1,&(mpMonteCarloObj->mTemperatureMax));
390  WXFieldPar<REAL> *tempMin=
391  new WXFieldPar<REAL>(this,"Temperature Min:",-1,&(mpMonteCarloObj->mTemperatureMin));
392  WXFieldPar<REAL> *tempGamma=
393  new WXFieldPar<REAL>(this,"Gamma:",-1,&(mpMonteCarloObj->mTemperatureGamma));
394  sizerTemp->Add(tempMax);
395  sizerTemp->Add(tempMin);
396  sizerTemp->Add(tempGamma);
397  mpSizer->Add(sizerTemp);
398  mList.Add(tempMax);
399  mList.Add(tempMin);
400  mList.Add(tempGamma);
401  tempMax->SetFormat(_T("%8f"));
402  tempMin->SetFormat(_T("%8f"));
403  tempGamma->SetFormat(_T("%8f"));
404 
405  opt=new WXFieldOption(this,-1,&(mpMonteCarloObj->mAnnealingScheduleMutation));
406  mpSizer->Add(opt,0,wxALIGN_LEFT);
407  mList.Add(opt);
408 
409  wxBoxSizer *sizerAmp=new wxBoxSizer(wxHORIZONTAL);
410  WXFieldPar<REAL> *ampMax=
411  new WXFieldPar<REAL>(this,"Amplitude Max:",-1,&(mpMonteCarloObj->mMutationAmplitudeMax));
412  WXFieldPar<REAL> *ampMin=
413  new WXFieldPar<REAL>(this,"Amplitude Min:",-1,&(mpMonteCarloObj->mMutationAmplitudeMin));
414  WXFieldPar<REAL> *ampGamma=
415  new WXFieldPar<REAL>(this,"Gamma:",-1,&(mpMonteCarloObj->mMutationAmplitudeGamma));
416  sizerAmp->Add(ampMax);
417  sizerAmp->Add(ampMin);
418  sizerAmp->Add(ampGamma);
419  mpSizer->Add(sizerAmp);
420  mList.Add(ampMax);
421  mList.Add(ampMin);
422  mList.Add(ampGamma);
423  ampMax->SetFormat(_T("%8f"));
424  ampMin->SetFormat(_T("%8f"));
425  ampGamma->SetFormat(_T("%8f"));
426 
427  opt=new WXFieldOption(this,-1,&(mpMonteCarloObj->mSaveTrackedData));
428  mpSizer->Add(opt,0,wxALIGN_LEFT);
429  mList.Add(opt);
430  opt->SetToolTip(_T("Saved Tracked values (costs, Chi^2, parameters...)\n\n")
431  _T("This is only useful for Test purposes.\n")
432  _T("Data is saved in the file (Name)-Tracker(-Run#).dat"));
433 
434  opt=new WXFieldOption(this,-1,&(mpMonteCarloObj->mXMLAutoSave));
435  mpSizer->Add(opt,0,wxALIGN_LEFT);
436  mList.Add(opt);
437  opt->SetToolTip(_T("Periodically save the best configuration\n\n")
438  _T("Recommended choice is : After Each Run\n")
439  _T("File name is: (name)-(date)-(Run#)-cost.xml\n\n")
440  _T("For Multiple Runs, Note that all choices\n")
441  _T("save the *best* configuration overall, except for\n")
442  _T("'After Each Run', for which the configuration\n")
443  _T("saved are the best for each run."));
444 
445  opt=new WXFieldOption(this,-1,&(mpMonteCarloObj->mAutoLSQ));
446  mpSizer->Add(opt,0,wxALIGN_LEFT);
447  mList.Add(opt);
448  opt->SetToolTip(_T("Least squares refinement can be run:\n\n")
449  _T(" - at the end of each run\n")
450  _T(" - perdiodically during the optimization\n\n")
451  _T(" This allows to find the global minimum\n")
452  _T("much faster\n")
453  _T(" Note that if a LSQ refinement is run but does\n")
454  _T("not reach the real global minimum, the returned\n")
455  _T("structure can be very distorted, but this is\n")
456  _T("harmless (restraints will bring back a correct \n")
457  _T("conformation after a few thousand tests)"));
458 
459  // Number of trials to go
460  mpWXFieldNbTrial=new WXFieldPar<long>(this,"Number of trials per run:",-1,&(mpMonteCarloObj->NbTrialPerRun()),70);
461  mpSizer->Add(mpWXFieldNbTrial);
462  mList.Add(mpWXFieldNbTrial);
463  mpWXFieldNbTrial->SetFormat(_T("%ld"));
464  mpWXFieldNbTrial->SetToolTip(_T("Number of triels per run.\n")
465  _T("This number will be updated during the optimization.\n\n")
466  _T("Using Multiple Runs:\n")
467  _T(" For simple problems (e.g. PbSO4), use 200 000\n")
468  _T(" For larger problems (e.g. Cimetidine), use 2 000 000\n")
469  _T(" For much larger problems, use 10 000 000\n\n")
470  _T("For a single run using Parallel Tempering, use a large number (100 000 000:\n"));
471  // Number of cycles (-1=run indefinitely)
472  WXFieldPar<long> *pWXFieldNbRun=new WXFieldPar<long>(this,"Number of Runs to perform:",-1,&mNbRun,40);
473  mpSizer->Add(pWXFieldNbRun);
474  mList.Add(pWXFieldNbRun);
475  pWXFieldNbRun->SetFormat(_T("%ld"));
476  pWXFieldNbRun->SetToolTip(_T("Number of runs to perform (for Multiple Runs).\n")
477  _T("Use -1 (the default) to run an infinite number of Runs.\n\n")
478  _T("The model will be randomized at the beginning of each run.\n"));
479  // Best cost so far
480  WXFieldPar<REAL> *pWXFieldBestCost=new WXFieldPar<REAL>(this,"Overall Best Cost:",-1,&(mpMonteCarloObj->GetBestCost()),130);
481  mpSizer->Add(pWXFieldBestCost);
482  mList.Add(pWXFieldBestCost);
483  pWXFieldBestCost->SetFormat(_T("%12.2f"));
484  pWXFieldBestCost->SetToolTip(_T("Overall (all runs) Best Cost"));
485  this->CrystUpdate(true);
486  VFN_DEBUG_EXIT("WXMonteCarloObj::WXMonteCarloObj()",7)
487 }
488 
489 WXMonteCarloObj::~WXMonteCarloObj()
490 {
491  if(0!=mpGlobalOptimRunThread)
492  {
493  if(mpGlobalOptimRunThread->IsAlive())
494  {
495  (*fpObjCrystInformUser)("Waiting for global optimization to stop...");
496  this->GetOptimizationObj().StopAfterCycle();
497  mpGlobalOptimRunThread->Wait(wxTHREAD_WAIT_BLOCK);
498  (*fpObjCrystInformUser)("Global optimization halted...");
499  }
500  delete mpGlobalOptimRunThread;
501  mpGlobalOptimRunThread=0;
502  }
503 }
504 
505 
506 void WXMonteCarloObj::OnRunOptimization(wxCommandEvent & event)
507 {
508  VFN_DEBUG_ENTRY("WXMonteCarloObj::OnRunOptimization()",6)
509  WXCrystValidateAllUserInput();
510  if(true==this->GetOptimizationObj().IsOptimizing())
511  {
512  wxMessageDialog dumbUser(this,_T("The optimization is already running !"),_T("Huh ?"),
513  wxOK|wxICON_EXCLAMATION);
514  dumbUser.ShowModal();
515  VFN_DEBUG_EXIT("WXMonteCarloObj::OnRunOptimization()",6)
516  return;
517  }
518  (*fpObjCrystInformUser)("Beginning global optimization");
519 
520  //Fix parameters than really should not be global-optimized
521  mpMonteCarloObj->SetParIsFixed(gpRefParTypeUnitCell,true);
522  mpMonteCarloObj->SetParIsFixed(gpRefParTypeScattDataScale,true);
523  mpMonteCarloObj->SetParIsFixed(gpRefParTypeScattDataProfile,true);
524  mpMonteCarloObj->SetParIsFixed(gpRefParTypeScattDataCorrIntAbsorp,true);
525  mpMonteCarloObj->SetParIsFixed(gpRefParTypeScattDataCorrIntPolar,true);
526  mpMonteCarloObj->SetParIsFixed(gpRefParTypeScattDataCorrIntExtinc,true);
527  mpMonteCarloObj->SetParIsFixed(gpRefParTypeScattDataCorrPos,true);
528  mpMonteCarloObj->SetParIsFixed(gpRefParTypeScattDataBackground,true);
529  mpMonteCarloObj->SetParIsFixed(gpRefParTypeRadiation,true);
530  mpMonteCarloObj->UpdateDisplay();
531 
532  double finalCost=0;
533  if(mpMonteCarloObj->NbTrialPerRun()<0)
534  {
535  mpMonteCarloObj->NbTrialPerRun() = - mpMonteCarloObj->NbTrialPerRun();
536  wxTextEntryDialog costDialog(this,_T("Enter desired cost for the optimization to stop"),
537  _T("Goal Cost"),_T(".20"),wxOK | wxCANCEL);
538  costDialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC));
539  if(wxID_OK==costDialog.ShowModal()) costDialog.GetValue().ToDouble(&finalCost);
540  }
541  if(0!=mpGlobalOptimRunThread)
542  delete mpGlobalOptimRunThread;
543 
544  if(event.GetId()==ID_GLOBALOPT_MENU_OPT_RUN_MULTIPLE)
545  mpGlobalOptimRunThread = new WXGlobalOptimRunThread(this->GetOptimizationObj(),
546  mpMonteCarloObj->NbTrialPerRun(),finalCost,mNbRun,true);
547  else
548  mpGlobalOptimRunThread = new WXGlobalOptimRunThread(this->GetOptimizationObj(),
549  mpMonteCarloObj->NbTrialPerRun(),finalCost,mNbRun,false);
550  // Tracker window
551  if(this->GetOptimizationObj().GetMainTracker().WXGet()==0)
552  {
553  wxFrame *frame= new wxFrame(this,-1,_T("Tracked data"),
554  wxDefaultPosition,wxSize(300,200));
555  wxWindow* pwxTrackerGraph = this->GetOptimizationObj().GetMainTracker().WXCreate(frame);
556 
557  wxSizer *ps=new wxBoxSizer(wxHORIZONTAL);
558  ps->Add(pwxTrackerGraph,1,wxEXPAND);
559  frame->CreateStatusBar(2);
560  frame->SetSizer(ps);
561  frame->SetAutoLayout(true);
562  frame->Show(true);
563  }
564  if(mpGlobalOptimRunThread->Create() != wxTHREAD_NO_ERROR)
565  wxLogError(_T("Can't create optimization thread"));
566  else mpGlobalOptimRunThread->Run();
567 
568  VFN_DEBUG_EXIT("WXMonteCarloObj::OnRunOptimization()",6)
569 }
570 
571 void WXMonteCarloObj::OnLSQRefine(wxCommandEvent &event)
572 {
573  WXCrystValidateAllUserInput();
574  if(true==this->GetOptimizationObj().IsOptimizing())
575  {
576  wxMessageDialog dumbUser(this,_T("An optimization is already running !"),_T("Huh ?"),
577  wxOK|wxICON_EXCLAMATION);
578  dumbUser.ShowModal();
579  return;
580  }
581  char buf[200];
582  mpMonteCarloObj->BeginOptimization();
583  mpMonteCarloObj->PrepareRefParList();
584  mpMonteCarloObj->InitLSQ(true);
585 
586  sprintf(buf,"LSQ: start");
587  REAL cost=mpMonteCarloObj->GetLogLikelihood();
588  mpMonteCarloObj->mvSavedParamSet.push_back(make_pair(mpMonteCarloObj->mRefParList.CreateParamSet(buf),cost));
589  wxProgressDialog dlgProgress(_T("Least Squares refinement"),wxString::Format(_T("Least Squares refinement, cycle #%02d/20, Chi^2=%012.2f"),0,cost),
590  19,this,wxPD_AUTO_HIDE|wxPD_ELAPSED_TIME|wxPD_CAN_ABORT);
591  (*fpObjCrystInformUser)(std::string(wxString::Format(_T("Least Squares refinement, cycle #%02d/20, Chi^2=%012.2f"),0,cost)));
592  for(unsigned i=0;i<20;++i)
593  {
594  try {mpMonteCarloObj->GetLSQObj().Refine(1,true,false,false);}
595  catch(const ObjCrystException &except){};
596  mpMonteCarloObj->UpdateDisplay();
597  sprintf(buf,"LSQ: cycle #%02d",i);
598  cost=mpMonteCarloObj->GetLogLikelihood();
599  mpMonteCarloObj->mvSavedParamSet.push_back(make_pair(mpMonteCarloObj->mRefParList.CreateParamSet(buf),cost));
600  (*fpObjCrystInformUser)(std::string(wxString::Format(_T("Least Squares refinement, cycle #%02d/20, Chi^2=%012.2f"),i,cost)));
601  if(dlgProgress.Update(i,wxString::Format(_T("Least Squares refinement, cycle #%02d/20, Chi^2=%012.2f"),i,cost))==false) break;
602  }
603  mpMonteCarloObj->EndOptimization();
604 }
605 
606 void WXMonteCarloObj::UpdateDisplayNbTrial()
607 {
608  VFN_DEBUG_MESSAGE("WXMonteCarloObj::UpdateDisplayNbTrial()",5)
609  mMutex.Lock();
610  mList.CrystUpdate(false);
611  mMutex.Unlock();
612  wxUpdateUIEvent event(ID_CRYST_UPDATEUI);
613  wxPostEvent(this,event);
614 }
615 
616 OptimizationObj & WXMonteCarloObj::GetOptimizationObj()
617 {
618  VFN_DEBUG_MESSAGE("WXMonteCarloObj::GetOptimizationObj()",2)
619  return *mpMonteCarloObj;
620 }
621 const OptimizationObj & WXMonteCarloObj::GetOptimizationObj()const
622 {
623  VFN_DEBUG_MESSAGE("WXMonteCarloObj::GetOptimizationObj() const",2)
624  return *mpMonteCarloObj;
625 }
626 
627 
628 }// namespace
The namespace which includes all objects (crystallographic and algorithmic) in ObjCryst++.
Definition: doc-main.h:25
void WXCrystValidateAllUserInput()
This function validates all user input (in a WXField) not yet taken into account, if needs be.
Definition: wxCryst.cpp:258
ObjRegistry< RefinableObj > gTopRefinableObjRegistry("Global Top RefinableObj registry")
This is a special registry for 'top' object for an optimization.
T * WXDialogChooseFromRegistry(ObjRegistry< T > &reg, wxWindow *parent, const string &message, int &choice)
This function allows to pick up one object in a registry.
void XMLCrystFileSaveGlobal(const string &filename)
Save all Objcryst++ objects.
Exception class for ObjCryst++ library.
Definition: General.h:122
virtual void Optimize(long &nbSteps, const bool silent=false, const REAL finalcost=0, const REAL maxTime=-1)=0
Launch optimization (a single run) for N steps.
virtual void MultiRunOptimize(long &nbCycle, long &nbSteps, const bool silent=false, const REAL finalcost=0, const REAL maxTime=-1)=0
Launch optimization for multiple runs of N steps.
Generic Refinable Object.
Definition: RefinableObj.h:784
virtual const string & GetClassName() const
Name for this class ("RefinableObj", "Crystal",...).
virtual const string & GetName() const
Name of the object.
void OnToggleCollapse(wxCommandEvent &WXUNUSED(event))
Only display the title, and collapse everything else.
Definition: wxCryst.cpp:818
A field with the name of a WXCrystObj.
Definition: wxCryst.h:372
void SetValue(const string &)
This actually posts an UpdateUI event, so that it is safe to call it from a non-graphic thread.
Definition: wxCryst.cpp:472
virtual void UpdateUI(const bool mutexlock=false)
Update the User Interface, if necessary.
Definition: wxCryst.cpp:496
WX Class for a Global Optimization objects.
virtual void OnRunOptimization(wxCommandEvent &WXUNUSED(event))=0
Launches the optimization run.
virtual void OnAddRefinedObject(wxCommandEvent &WXUNUSED(event))
From the menu.
virtual void OnBrowseParamSet(wxCommandEvent &WXUNUSED(event))
Opens a window where the stored parameter set can be selected.
virtual void OnSelectParamSet(wxCommandEvent &WXUNUSED(event))
Restore one parameter set.
const REAL mFinalCost
The value of the cost below which the optimization should stop (0 by default) even if the desired num...
const bool mDoMultiple
Use multiple Runs ?
long * mpNbRun
This points to the mNbRun member in WXOptimizationObj.
long * mpNbTrial
This points to OptimizationObj::mNbTrialPerRun.