00001
00036 const bool test_applier = false;
00037
00038 #include <stdlib.h>
00039 #include <sstream>
00040 #include <fstream>
00041 #include <iomanip>
00042 #include <sys/types.h>
00043 #include <sys/wait.h>
00044 #include <unistd.h>
00045 #include <math.h>
00046 #include <string>
00047 #ifdef HAVE_HASH_MAP
00048 #include <hash_map>
00049 #endif
00050 #ifdef HAVE_EXT_HASH_MAP
00051 #include <ext/hash_map>
00052 #endif
00053 #include <mak/hash_string.h>
00054
00055 #include "punnets.h"
00056
00057 using namespace __gnu_cxx;
00058 using namespace std;
00059 using namespace mak;
00060 using namespace punnets;
00061
00062 const real a1_offset = 1.0;
00063 const real weight_scale = 1.0;
00064 const ntime_t coindet_duration_period = 0.002;
00065 const real coindet_offset = 0.0015;
00066
00067 const ntime_t inhibitor_delay = 0.00001;
00068 const ntime_t gates_delay = 0.00001;
00069 const real synchro_gate_delay = 0.001;
00070 const real delayed_gate_delay = 0.1;
00071 const real delayed_gate_gap = 0.009;
00072 const real synchro_hidden_offset = 0.0002;
00073 const real delayed_hidden_offset = 0.03;
00074 const ntime_t suppress_delay = -0.0001;
00075 const ntime_t coindet_delay = 0.00003;
00076 const ntime_t incoindet_delay = 0.003 - inhibitor_delay;
00077 const ntime_t sgate_sig_hv_period = 0.003;
00078 const ntime_t sgate_thr_hv_period = 0.003;
00079 const ntime_t dgate_sig_hv_period = 0.0045;
00080 const ntime_t dgate_thr_hv_period = 0.01;
00081 const real sgate_hidden_thr_raise = 16;
00082 const real dgate_hidden_thr_raise = 32;
00083 const real coindet_suppress_weight = 15.0;
00084 const real delay_weight_decrease = 0.5;
00085 const real synch_weight_decrease = 0.0;
00086 const real inhibitor_suppress_weight = 30.0;
00087 const ntime_t synch_minus_preceding = 0.00001;
00088 const ntime_t delay_minus_preceding = 0.00045;
00089
00090 const ntime_t test_until = 3.25;
00091
00092 enum pos_t {
00093 pos_n1,
00094 pos_n3,
00095 pos_n,
00096 pos_pn3,
00097 pos_vi,
00098 pos_vt,
00099 pos_vt_subj,
00100 pos_det,
00101 pos_max
00102 };
00103
00104 const string posstrs[] = { "pronoun 1st", "pronoun 3rd", "noun", "proper noun",
00105 "vi", "vt", "vt_subj", "det" };
00106
00107 enum flg_t
00108 {
00109 flg_none = 0,
00110 flg_nom = 1,
00111 flg_acc = 2,
00112
00113 flg_plu = 8,
00114 flg_male = 16,
00115 flg_female = 32,
00116 flg_food = 64,
00117 flg_reading = 128,
00118 flg_countable = 128,
00119 flg_love = 256,
00120 };
00121
00122 struct word_t {
00123 string word;
00124 pos_t pos;
00125 int flag;
00126 };
00127
00128 const word_t words[] =
00129 { { "I", pos_n1, flg_nom },
00130 { "me", pos_n1, flg_acc },
00131 { "he", pos_n3, flg_nom | flg_male},
00132 { "him", pos_n3, flg_acc | flg_male },
00133 { "she", pos_n3, flg_nom | flg_female },
00134 { "her", pos_n3, flg_acc | flg_female },
00135
00136
00137 { "Mary", pos_pn3, flg_female },
00138 { "John", pos_pn3, flg_male },
00139 { "Susan", pos_pn3, flg_female },
00140 { "Mike", pos_pn3, flg_male },
00141 { "man", pos_n, flg_male | flg_countable },
00142 { "lady", pos_n, flg_female | flg_countable },
00143 { "boy", pos_n, flg_male | flg_countable },
00144 { "girl", pos_n, flg_female | flg_countable },
00145 { "book", pos_n, flg_reading | flg_countable },
00146 { "paper", pos_n, flg_reading },
00147 { "mail", pos_n, flg_reading | flg_countable },
00148 { "bread", pos_n, flg_food },
00149 { "lemon", pos_n, flg_food | flg_countable },
00150 { "banana", pos_n, flg_food | flg_countable },
00151 { "runs", pos_vi, 0 },
00152 { "sleeps", pos_vi, 0 },
00153 { "smiles", pos_vi, 0 },
00154 { "likes", pos_vt, flg_love | flg_reading | flg_food },
00155 { "(liker)", pos_vt_subj, flg_love | flg_reading | flg_food },
00156 { "has", pos_vt, flg_reading | flg_food },
00157 { "(owner)", pos_vt_subj, flg_reading | flg_food },
00158 { "loves", pos_vt, flg_love },
00159 { "(lover)", pos_vt_subj, flg_love },
00160 { "reads", pos_vt, flg_reading },
00161 { "(reader)", pos_vt_subj, flg_reading },
00162 { "eats", pos_vt, flg_food },
00163 { "(eater)", pos_vt_subj, flg_food },
00164 { "a", pos_det, flg_countable },
00165 { "the", pos_det, 0 }
00166 };
00167
00168 hash_map<string, unsigned int> str_to_wordid;
00169
00170 const unsigned int NWORDS = sizeof(words) / sizeof(word_t);
00171 const unsigned int NELEMS = (int)pos_max;
00172
00173
00174
00175 struct neuinfo {
00176 string layername;
00177 unsigned int nneuron;
00178 tneuron_base *ref;
00179 neuinfo() { }
00180 neuinfo(string il, unsigned int in, tneuron_base *ir) : layername(il), nneuron(in), ref(ir) { }
00181 };
00182
00183
00184 void read_file(vector<tneuron_ext *> &neuin, vector<tneuron *> &neuhid, vector<tneuron *> &neuout, tneuron &inhibitor, tneuron &coindet, string fname, ntime_t delay1, ntime_t delay_input_gap, real decay_level, real hidden_offset, bool synch)
00185 {
00186 tneuron &incoindet = inhibitor;
00187 cout << "Read file " << fname << ", decay_level=" << decay_level << endl;
00188 const bool debug_readfile = false;
00189
00190 ifstream ifs(fname.c_str());
00191
00192 string s;
00193 ifs >> s;
00194
00195 hash_map<string, neuinfo, hash_string> nmap;
00196
00197 while(ifs.good())
00198 {
00199 if( s != "layer" ) { cout << "input file bad <" << s << ">" << endl; abort();}
00200
00201 string layername;
00202 int layersize;
00203 ifs >> layername;
00204 if( debug_readfile ) cout << "layer " << layername << endl;
00205
00206 ifs >> s;
00207 while( ifs.good() )
00208 {
00209 if( s == "size" )
00210 {
00211 ifs >> layersize;
00212 if( debug_readfile ) cout << "size " << layersize << endl;
00213 ifs >> s;
00214 }
00215 else if( s == "neurons" )
00216 {
00217 if( debug_readfile ) cout << "neurons " << layersize << endl;
00218 for( int i=0; i<layersize; i++ )
00219 {
00220 ifs >> s;
00221 if( layername == "a1_layer" )
00222 nmap[s] = neuinfo(layername, i, &inhibitor);
00223 else if( layername == "input_layer" )
00224 nmap[s] = neuinfo(layername, i, (neuin[i % neuin.size()]));
00225 else if( layername == "output_layer" )
00226 nmap[s] = neuinfo(layername, i, (neuout[i % neuout.size()]));
00227 else if( layername == "hidden_layer" )
00228 {
00229 ostringstream oss; oss << i;
00230 tneuron *neu = new tneuron((synch ? "shidden(" : "dhidden(") + oss.str() + ")",
00231 synch ? sgate_sig_hv_period : dgate_sig_hv_period,
00232 synch ? sgate_thr_hv_period : dgate_thr_hv_period,
00233 a1_offset, a1_offset+(synch ? sgate_hidden_thr_raise : dgate_hidden_thr_raise) );
00234 nmap[s] = neuinfo(layername, i, neu);
00235 neuhid.push_back(neu);
00236 }
00237 else
00238 {
00239 cout << "Unknown layer name " << layername << endl;
00240 abort();
00241 }
00242 }
00243 ifs >> s;
00244 }
00245 else if( s == "connection" )
00246 {
00247 string dstname;
00248 int nconn;
00249 ifs >> dstname >> nconn;
00250 if( nmap.find(dstname) == nmap.end() ) { cout << "unknown neuron " << dstname << endl; abort();}
00251 if( debug_readfile ) cout << "connection " << nconn << endl;
00252 tneuron_base *dest = nmap[dstname].ref;
00253 for( int i=0; i<nconn; i++ )
00254 {
00255 string srcname;
00256 real weight;
00257 int idelay;
00258 ifs >> srcname >> weight >> idelay;
00259 if( nmap.find(srcname)== nmap.end() ) { cout << "unknown neuron " << srcname << endl; abort();}
00260 tneuron_base *src = nmap[srcname].ref;
00261 weight *= weight_scale;
00262 if( nmap[srcname].layername == "a1_layer" )
00263 {
00264 tsynapse *p1, *p2, *p3 = NULL;
00265 real delay = delay1 - inhibitor_delay;
00266 if( nmap[dstname].layername == "hidden_layer" )
00267 delay += -hidden_offset;
00268 weight += a1_offset;
00269
00270 real inhibitor_fix = 0.0;
00271 if( ! synch )
00272 {
00273 weight -= a1_offset;
00274 incoindet.addSynapse(p3 = new tsynapse(*dest, delay - 0.00002 - incoindet_delay - coindet_offset, ((weight < 0 ? weight : 0) - inhibitor_suppress_weight)) );
00275
00276
00277 inhibitor_fix = ((weight < 0 ? weight : 0) - inhibitor_suppress_weight) * pow(decay_level, (delayed_gate_gap + coindet_offset) / coindet_duration_period );
00278
00279 weight += a1_offset;
00280 }
00281 coindet.addSynapse(p1 = new tsynapse(*dest,
00282 delay + (! synch ? -coindet_duration_period : - 0.00001),
00283 ((weight < 0 ? weight : 0) - coindet_suppress_weight)/sqrt(decay_level)));
00284 coindet.addSynapse(p2 = new tsynapse(*dest,
00285 delay,
00286 ((weight > 0 ? weight : 0) + coindet_suppress_weight)*sqrt(decay_level) - inhibitor_fix - (!synch ? delay_weight_decrease : synch_weight_decrease)));
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297 }
00298 else
00299 {
00300 real delay = (nmap[srcname].layername == "input_layer" && nmap[srcname].nneuron >= neuin.size()) ? delay1 + delay_input_gap : delay1;
00301 if( nmap[srcname].layername == "hidden_layer" )
00302 delay = hidden_offset;
00303 else if( nmap[dstname].layername == "hidden_layer" )
00304 delay -= hidden_offset;
00305 tsynapse *p;
00306 if( weight < 0.0 )
00307 {
00308 delay -= synch ? synch_minus_preceding : delay_minus_preceding;
00309 if( !synch )
00310 weight /= pow(decay_level, delay_minus_preceding / coindet_duration_period );
00311 }
00312 src->addSynapse(p = new tsynapse(*dest, delay - (! synch ? coindet_offset : 0), weight));
00313
00314
00315
00316
00317
00318
00319 }
00320 }
00321 ifs >> s;
00322 }
00323 else
00324 break;
00325 }
00326 }
00327 }
00328
00329
00330 int main(int argc, char **argv)
00331 {
00332 cout << "Punnets language simulation program (c) 2003 Makino Takaki." << endl;
00333 cout << "Punnets is free software, covered by the GNU General Public License." << endl;
00334 cout << endl;
00335
00336 const char *datafilename = "lang.dat";
00337 const char *plotfilename = "lang.plt";
00338
00339 const unsigned int nexts = NWORDS + NELEMS;
00340 vector<tneuron_ext *> exts(nexts);
00341 vector<tneuron *> hidden;
00342 vector<tneuron *> sgates(nexts);
00343 vector<tneuron *> dgates(nexts);
00344 tneuron inhibitor("inhibitor", 0.0005, 0.0005, 1.0, 128.0);
00345 tneuron coindet("coindet", 0.003, 0.05, 1.0, 5.0);
00346 tneuron incoindet("incoindet", 0.003, 0.003, 1.0, 2.0);
00347
00348 inhibitor.addSynapse(new tsynapse(coindet, inhibitor_delay, 0.67));
00349 inhibitor.addSynapse(new tsynapse(coindet, inhibitor_delay + delayed_gate_gap, 0.67));
00350 inhibitor.addSynapse(new tsynapse(incoindet, incoindet_delay, 1.2));
00351 inhibitor.addSynapse(new tsynapse(incoindet, incoindet_delay + delayed_gate_gap, 1.2));
00352 coindet.addSynapse(new tsynapse(incoindet, incoindet_delay - inhibitor_delay - 0.0015, -4));
00353
00354 for( unsigned int i=0; i<NWORDS; i++ )
00355 str_to_wordid[ words[i].word ] = i;
00356
00357
00358 tscheduler scheduler;
00359
00360 ofstream ofs(datafilename);
00361 cout << "Produce simulation log file '" << datafilename << "'." << endl;
00362 tlogger logger(ofs, 0.001, 0.01, test_until);
00363
00364
00365 for( unsigned int i=0; i<nexts; i++ )
00366 {
00367 ostringstream oss;
00368 exts[i] = new tneuron_ext("repre'" + (i < NWORDS ? words[i].word : posstrs[i-NWORDS]) + "'", 0.0045);
00369 sgates[i] = new tneuron("sgate'" + (i < NWORDS ? words[i].word : posstrs[i-NWORDS]) + "'",
00370 sgate_sig_hv_period, sgate_thr_hv_period, a1_offset, a1_offset+64 );
00371 dgates[i] = new tneuron("dgate'" + (i < NWORDS ? words[i].word : posstrs[i-NWORDS]) + "'",
00372 dgate_sig_hv_period, dgate_thr_hv_period, a1_offset, a1_offset+64 );
00373
00374
00375
00376
00377
00378
00379
00380
00381 exts[i]->addExt(new func_const(-1.4));
00382 if( ! test_applier ) {
00383 exts[i]->addExt(new func_sine(1.0 , 8 * 2*M_PI , 0.0 ));
00384 exts[i]->addExt(new func_sineshot_int(1.27 , 1.59 * 2*M_PI ));
00385 inhibitor.addSynapse(new tsynapse_addfunc(*exts[i], 0.0001, new func_sineshot(-0.7, (1/0.021) * 2*M_PI, -1.0), new func_sineshot::message_set_t0, -0.25));
00386 }
00387 exts[i]->addSynapse(new tsynapse(inhibitor, inhibitor_delay, 1.5));
00388 exts[i]->addSynapse(new tsynapse(*exts[i], inhibitor_delay, -4.0));
00389 exts[i]->setLoopBack(scheduler, 0.0);
00390 if( ! test_applier ) {
00391 sgates[i]->addSynapse(new tsynapse(*exts[i], gates_delay, 4.0));
00392 dgates[i]->addSynapse(new tsynapse(*exts[i], gates_delay, 5.5));
00393 }
00394
00395 if(
00396 i == str_to_wordid["the"] || i == NWORDS + pos_det
00397 || i == str_to_wordid["Mary"] || i == NWORDS + pos_pn3
00398 || i == str_to_wordid["girl"] || i == NWORDS + pos_n
00399 || i == str_to_wordid["loves"] || i == NWORDS + pos_vt
00400 || i == str_to_wordid["(lover)"] || i == NWORDS + pos_vt_subj
00401 )
00402 {
00403 real off =
00404 (i == str_to_wordid["Mary"] || i == NWORDS + pos_pn3) ? 40 :
00405 (i == str_to_wordid["(lover)"] || i == NWORDS + pos_vt_subj) ? 30 :
00406 (i == str_to_wordid["loves"] || i == NWORDS + pos_vt) ? 20 :
00407 (i == str_to_wordid["the"] || i == NWORDS + pos_det) ? 10 : 0;
00408 off += (i >= NWORDS) ? 4 : 0;
00409 logger.add(*exts[i], 0, false, false, off * 3.5 / 5);
00410
00411
00412
00413
00414
00415 }
00416 }
00417
00418
00419
00420 read_file(exts, hidden, sgates, inhibitor, inhibitor, "synch.dat", synchro_gate_delay, 0.0 ,
00421 1.0 , synchro_hidden_offset, true);
00422 read_file(exts, hidden, dgates, incoindet, coindet , "delay.dat", delayed_gate_delay, delayed_gate_gap,
00423 exp(-(M_LN2 / dgate_sig_hv_period)*(coindet_duration_period)) , delayed_hidden_offset, false );
00424
00425 ofstream ofs2(plotfilename);
00426 cout << "Produce GNUPLOT plotting file '" << plotfilename << "'." << endl;
00427 logger.gnuplot_def(ofs2, datafilename);
00428
00429 logger.schedule(scheduler);
00430
00431 scheduler.scheduleEvent( 0.61, makePulse( * exts[ str_to_wordid[ "Mary" ] ], 5.0 ) );
00432 scheduler.scheduleEvent( 0.975, makePulse( * exts[ str_to_wordid[ "loves" ] ], 5.0 ) );
00433 scheduler.scheduleEvent( 1.725, makePulse( * exts[ str_to_wordid[ "the" ] ], 5.0 ) );
00434 scheduler.scheduleEvent( 2.225, makePulse( * exts[ str_to_wordid[ "girl" ] ], 5.0 ) );
00435
00436 scheduler.run(test_until);
00437
00438 cout << "Simulation finished." << endl;
00439 return 0;
00440 }