libcsim.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. /*Copyright (C) 2005, 2006, 2007 Frank Michler, Philipps-University Marburg, Germany
  2. This program is free software; you can redistribute it and/or
  3. modify it under the terms of the GNU General Public License
  4. as published by the Free Software Foundation; either version 2
  5. of the License, or (at your option) any later version.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. GNU General Public License for more details.
  10. You should have received a copy of the GNU General Public License
  11. along with this program; if not, write to the Free Software
  12. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  13. */
  14. // c++ simulation library
  15. // layers and connection matrices as objects
  16. // goal: structured and expandable but still fast (avoid too much function calls)
  17. // Created by Frank Michler, September 2005, Marburg, Germany
  18. //
  19. // chunks of code were taken from SPNET (Eugene Izhikevich)
  20. // http://vesicle.nsi.edu/users/izhikevich/publications/spnet.cpp
  21. // 5.10.2005: Idee: ein Objekt (oder structure) mit globalen Einstellungen
  22. // (dt, MacroTimeStep, ...), und jedes SimElement hat eine Referenz
  23. // oder einen Pointer darauf [done]
  24. // 13.10.2005: gsl_rng * r; /* global generator */ sollte auch darin enthalten sein
  25. // --> k�nnte alles in SimLoop integriert werden [done]
  26. // 02.11.2005
  27. // ToDo: check existence of directory before saving files
  28. // use assertions [done]
  29. // 03.11.2005
  30. // ToDo: MySimLoop: save sim info with all layer and connection names
  31. // an idl program could then automatically show all layers [done]
  32. // 15.11.2005
  33. // ToDo: ask and create directory if it doesn't exist [done]
  34. // 16.11.2005
  35. // ToDo: bug: bei Delay-Differenz == 0 tritt Gleitkomma-Fehler auf (wahrscheinlich Division durch Null) --> abfangen!! (wahrscheinlich modulo 0 bei Zufalls-Generierung der Delays: getrandom(DelayDiff))
  36. // 18.11.2005 [done]
  37. // 17.11.2005
  38. // ToDo: Idee: Zeiger auf MainSimLoop global machen??
  39. // so dass er nicht mehr mit jedem Konstruktor �bergeben werden muss [done]
  40. // 29.11.2005
  41. // Fehlermeldungen nach cerr ausgeben!!
  42. // 09.12.2005
  43. // ToDo: input-Klassen: TestMode abschaffen und durch enum mode ersetzen
  44. // 21.12.2005
  45. // ToDo: Gewichts-Matritzen: im Moment ns*M-Matritzen, Problem: wenn wenige Source-Neuronen auf alle Target-Neuronen konvergieren: M==nt und die Matrix wird sehr gro�
  46. // L�sung: Die Gewichts-Arrays nur so gro� machen wie n�tig, und zus�tzlich die Gr��e speichern
  47. // 22.12.2005
  48. // ToDo: Handling der Delays: MaxDelay muss Connection-spezifisch gesetzt werden (und evtl. minDelay/maxDelay ber�cksichtigen)
  49. // 08.01.2006
  50. // ToDo: Ber�cksichtigung des individuellen maximumDelay [done]
  51. // ToDo: Ber�cksichtigung des individuellen minimumDelay
  52. // 22.02.2006
  53. // ToDo: Format der Gewichtsstrukturen:
  54. // delays[ns][maximumDelay][M] --> zu gro�, muss nicht bis M in der dritten Dim gehen
  55. // Problem: Format muss an vielen Stellen ber�cksichtigt werden (Einlesen, Speichern, IDL, Tcl/Tk)
  56. // 24.02.2006
  57. // ToDo: AnyOptionWrapper::SaveDefaultConfigFile
  58. // aus den gesetzten Parametern ein Default-Config-File generieren [done]
  59. // 19.06.2006
  60. // ToDo: automatically save configuration file to data directory
  61. #include "sys.hpp"
  62. #include "debug.hpp"
  63. #include "objsimlibrary.hpp"
  64. // #include "anyoptionwrapper.cpp"
  65. // #include "simmodules.cpp"
  66. // float gauss(float x, float sigma=1, float x0=0)
  67. // {
  68. // return exp(-(x-x0)*(x-x0)/(2*sigma*sigma));
  69. // }
  70. double gauss(double x, double sigma, double x0)
  71. {
  72. return exp(-(x-x0)*(x-x0)/(2*sigma*sigma));
  73. }
  74. /////////////////
  75. LookUpTable::LookUpTable(): value(0), tmpvalue(0), N(0), xRange0(0), xRange1(0), RDiff(0), IndexFactor(0)
  76. {
  77. }
  78. LookUpTable::~LookUpTable()
  79. {
  80. if (tmpvalue != 0) delete [] tmpvalue;
  81. }
  82. void LookUpTable::Reset()
  83. {
  84. if (tmpvalue != 0) delete [] tmpvalue;
  85. tmpvalue=0;
  86. value=0;
  87. N=0;
  88. xRange0=0;
  89. xRange1=0;
  90. RDiff=0;
  91. }
  92. void LookUpTable::InitExp(int _N, float Tau, float v0, float Range0, float Range1)
  93. {
  94. Reset();
  95. xRange0=Range0;
  96. xRange1=Range1;
  97. RDiff = xRange1-xRange0;
  98. N=_N;
  99. IndexFactor = N/RDiff;
  100. LBound = int(xRange0*IndexFactor);
  101. UBound = int(xRange1*IndexFactor);
  102. float coef=RDiff/N;
  103. if (N > 0) {
  104. if (RDiff >0) {
  105. tmpvalue = new float [N+1];
  106. value = tmpvalue-LBound;
  107. for (int t=LBound;t<=UBound;++t) {
  108. value[t] = v0*exp(-coef*t/Tau);
  109. }
  110. } else {
  111. tmpvalue = new float [N];
  112. value = tmpvalue;
  113. for (int t=0;t<N;++t) value[t] = v0*exp(-t/Tau);
  114. }
  115. }
  116. }
  117. float LookUpTable::GetValue(int index)
  118. {
  119. if (index > 0) {
  120. if (index <N) {
  121. return value[index];
  122. } else return value[N-1];
  123. } else return value[0];
  124. }
  125. double LookUpTable::GetValue(double X)
  126. {
  127. int index = int(IndexFactor*X);
  128. // cout << "(X-xRange0)/RDiff=" << N*(X-xRange0)/RDiff << " index=" << index << "\n";
  129. if (index > LBound) {
  130. if (index <UBound) {
  131. return value[index];
  132. } else return value[UBound];
  133. } else return value[LBound];
  134. }
  135. /////////////////////
  136. DistanceProfile::DistanceProfile(int _N): N(_N)
  137. {
  138. }
  139. DistanceProfile::DistanceProfile(const vector<float> &Profile)
  140. {
  141. cout << "DistanceProfile::DistanceProfile, inizialize with vector" << "\n";
  142. N=Profile.size();
  143. profile = new float [N];
  144. for (int i=0;i<N;++i)
  145. {
  146. profile[i]=Profile[i];
  147. }
  148. }
  149. DistanceProfile::DistanceProfile(int _N, float Sigma1, float Sigma2): N(_N)
  150. {
  151. cout << "DistanceProfile::DistanceProfile, N=" << N << "\n";
  152. float MaxX=1;
  153. profile = new float [N];
  154. int i;
  155. double x;
  156. double s1, s2;
  157. for (i=0;i<N;++i)
  158. {
  159. x = i*MaxX/N;
  160. s2= gauss(x, Sigma2);
  161. s1=gauss(x, Sigma1);
  162. profile[i] = float(s2-s1);
  163. // if (i<20) cout << "x=" << x << " s2=" << s2 << " s1=" << s1 << " profile[i]=" << profile[i] << "\n";
  164. }
  165. // find maximum
  166. float gmax =0;
  167. for (i=0;i<N;++i)
  168. {
  169. if (profile[i] > gmax) gmax=profile[i];
  170. }
  171. float factor=1.0/gmax;
  172. cout << "gmax=" << gmax << " factor=" << factor << "\n";
  173. // scale to [0,1]
  174. for (i=0;i<N;++i)
  175. {
  176. profile[i] *= factor;
  177. }
  178. }
  179. DistanceProfile::~DistanceProfile()
  180. {
  181. cout << "DistanceProfile::destructor\n";fflush(stdout);
  182. delete profile;
  183. }
  184. float DistanceProfile::GetValue(float dist)
  185. {
  186. int i = int(dist*N);
  187. if (i>=N) i=N-1;
  188. return profile[i];
  189. }
  190. float DistanceProfile::GetMaxConDistance(float minweight)
  191. {
  192. int i=N-1;
  193. while((i>0) && (profile[i--]<minweight));
  194. return float(i)/N;
  195. }
  196. void DistanceProfile::print()
  197. {
  198. cout << "DistanceProfile::print() N=" << N << "\n";
  199. int i;
  200. for(i=0;i<N;++i) cout << profile[i] << " ";
  201. cout << "\n";
  202. }
  203. CircleDistanceProfile::CircleDistanceProfile(int _N, float Radius, bool invers): DistanceProfile(_N)
  204. {
  205. cout << "CircleDistanceProfile::CircleDistanceProfile, N=" << N << "\n";
  206. float MaxX=1;
  207. profile = new float [N];
  208. int i;
  209. double x;
  210. for (i=0;i<N;++i)
  211. {
  212. x = i*MaxX/N;
  213. if (invers) {
  214. if (x>=Radius) profile[i]=1; else profile[i]=0;
  215. } else {
  216. if (x<=Radius) profile[i]=1; else profile[i]=0;
  217. }
  218. }
  219. }
  220. ///////////////////////////////////////////////
  221. Recorder::Recorder(char* _FileName): FileName(_FileName)
  222. {
  223. fs = fopen(FileName.c_str(),"w");
  224. }
  225. Recorder::~Recorder()
  226. {
  227. cout << "Recorder Destructor, FileName=" << FileName << "\n";
  228. fclose(fs);
  229. }
  230. int Recorder::record(float time, float value)
  231. {
  232. fprintf(fs, "%f %f\n", time, value);
  233. }
  234. int Recorder::record(float time, float value, float value2)
  235. {
  236. fprintf(fs, "%f %f %f\n", time, value, value2);
  237. }
  238. ////////////////////////////////////////////////
  239. BinRecorder::BinRecorder(int _MacroTimeStep, int _N, int _M, float** _PBuffer, float _dt, const char* _FileName): MacroTimeStep(_MacroTimeStep), N(_N), M(_M), PBuffer(_PBuffer), BaseFileName(_FileName), SimTag("")
  240. {
  241. int i;
  242. const char* tmpinfo = "BinRec\n";
  243. const char* tmpversion = "0.02\n";
  244. strcpy(Header.finfo, tmpinfo);
  245. strcpy(Header.version, tmpversion);
  246. Header.N=N;
  247. Header.M=M;
  248. Header.ValueSize=sizeof(**PBuffer);
  249. Header.FrameSize = Header.N*Header.ValueSize;
  250. Header.dt = _dt;
  251. FileName = BaseFileName + SimTag;
  252. fs = fopen(FileName.c_str(),"w");
  253. // Write Header Infos
  254. fwrite(&Header, sizeof(Header), 1, fs);
  255. fclose(fs);
  256. cout << "BinRecorder; MacroTimeStep =" << MacroTimeStep << " N=" << N << "\n";
  257. RecBuffer = new float [N*MacroTimeStep];
  258. RecBuffPointer = RecBuffer;
  259. RecBuffMax = RecBuffPointer + N*(MacroTimeStep-1)+1; //??
  260. }
  261. BinRecorder::~BinRecorder()
  262. {
  263. // fclose(fs);
  264. delete [] RecBuffer;
  265. }
  266. int BinRecorder::record()
  267. {
  268. int i;
  269. // fs = fopen(FileName.c_str(),"a");
  270. // for (i=0; i<N;++i) fwrite(PBuffer[i], sizeof(**PBuffer), 1, fs);
  271. // fclose(fs);
  272. // cout << "a"; fflush(stdout);
  273. float test;
  274. if (RecBuffPointer < RecBuffMax)
  275. for (i=0; i<N;++i) *(RecBuffPointer++) = *PBuffer[i];
  276. // for (i=0; i<N;++i) test = *PBuffer[i];
  277. else cout << "ERROR: BinRecorder: RecBuffer overflow\n";
  278. // cout << "g"; fflush(stdout);
  279. }
  280. int BinRecorder::restart()
  281. {
  282. fs = fopen(FileName.c_str(),"w");
  283. fwrite(&Header, sizeof(Header), 1, fs);
  284. fclose(fs);
  285. }
  286. int BinRecorder::restart(string _SimTag)
  287. {
  288. FileName = BaseFileName + _SimTag;
  289. fs = fopen(FileName.c_str(),"w");
  290. fwrite(&Header, sizeof(Header), 1, fs);
  291. fclose(fs);
  292. }
  293. int BinRecorder::WriteToFile()
  294. {
  295. fs = fopen(FileName.c_str(),"a");
  296. fwrite(RecBuffer, N*MacroTimeStep*sizeof(*RecBuffer), 1, fs);
  297. fclose(fs);
  298. RecBuffPointer = RecBuffer;
  299. }
  300. ////////////////////////////////////////////////////////
  301. ////////////////////////
  302. SimpleTextProgressBar::SimpleTextProgressBar(int MaxSteps): Final(MaxSteps), Status(0), StepSize(0.1)
  303. {
  304. }
  305. int SimpleTextProgressBar::Next(int StepNr)
  306. {
  307. while ((Status*Final) <= StepNr)
  308. {
  309. cout << "."; fflush(stdout);
  310. Status += StepSize;
  311. }
  312. }
  313. int SimpleTextProgressBar::Reset(int MaxSteps)
  314. {
  315. Final=MaxSteps;
  316. Status=0;
  317. }
  318. ////////////////
  319. CSimStandardOptions::CSimStandardOptions(AnyOptionWrapper* _aowrap)
  320. : myAnyWrap(_aowrap), NTrials(1), NSteps(10), TestNSteps(10), LoadWeights(false), InputStrength(1),
  321. DataDirectory("."), SimFinishButton(false), SaveInitialWeights(true)
  322. {
  323. if (myAnyWrap) {
  324. std::string HomeDir(getenv("HOME"));
  325. std::string DefaultDataDir(HomeDir+"/data/tmp/");
  326. myAnyWrap->setOption("DataDirectory", 'a', &DataDirectory, DefaultDataDir.c_str());
  327. myAnyWrap->setOption("NTrials", 'a', &NTrials, 1);
  328. myAnyWrap->setOption("NSteps", 'a', &NSteps, 1);
  329. myAnyWrap->setOption("TestNSteps", 'a', &TestNSteps, 1);
  330. myAnyWrap->setFlag ( "LoadWeights", 'L', &LoadWeights);
  331. myAnyWrap->setOption( "InputStrength", 'i', &InputStrength, 1);
  332. myAnyWrap->setFlag ( "SimFinishButton", 'a', &SimFinishButton);
  333. myAnyWrap->setFlag("SaveInitialWeights", 'S', &SaveInitialWeights);
  334. }
  335. }
  336. //////////////////////////////
  337. ////////////////////////
  338. // IDLrpc::IDLrpc()
  339. // {
  340. // CLIENT *pClient;
  341. // char cmdBuffer[512];
  342. // int result;
  343. // /* Modification by jimu 9-jan-2006 */
  344. // char *startupstr;
  345. // char startupcmd[100] = "@/home/frank/idl/test_startup";
  346. // /*
  347. // * Connect to the server.
  348. // */
  349. // if((pClient = IDL_RPCInit(0, (char*)NULL)) == (CLIENT*)NULL){
  350. // fprintf(stderr, "Can't register with IDL server\n");
  351. // exit(1);
  352. // }
  353. // printf("Get Environment Variable");fflush(stdout);
  354. // startupstr = getenv("IDL_STARTUP");
  355. // printf("%s\n",startupstr);fflush(stdout);
  356. // strcat(startupcmd, startupstr);
  357. // printf("IDL startup command: %s\n",startupcmd);fflush(stdout);
  358. // result = IDL_RPCExecuteStr(pClient, startupcmd);
  359. // result = IDL_RPCExecuteStr(pClient, "print, 'The value of !MyTestVar is: '");
  360. // result = IDL_RPCExecuteStr(pClient, "help, !MyTestVar");
  361. // }
  362. // IDLrpc::~IDLrpc()
  363. // {
  364. // }
  365. /////////////////////////////