00001
00207 #include <math.h>
00208 #include <time.h>
00209
00210 #include "ind_types.h"
00211 #include "ipc.h"
00212 #include "cmdparam.h"
00213 #include "binarysave.h"
00214 #include "vgen.h"
00215 #ifndef NO_INPUTS
00216 #include "inputs.h"
00217 #endif
00218 #ifndef NO_IO
00219 #include "file_io.h"
00220 #endif
00221 #include "globals.h"
00222 #include "kernel.h"
00223 #include "kernelwrapper.h"
00224 #include "stringutils.h"
00225 #include "lissom.h"
00226
00227
00228
00229
00230
00231
00232
00245 #define ACTLIST_START(actlist) 1
00246 #define ACTLIST_COUNT(actlist) ((actlist)[0])
00247 typedef int actlist[NMAX+1];
00248
00250 #ifndef NO_BINARY
00251 #define BINARY_WEIGHTS_FILE
00252 #endif
00253
00254 00255 00256 00257
00258
00259
00271
00273 #define VERIFY_WEIGHT_SAVES_ERROR_LIMIT 10
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283 double alpha_exc=0.002;
00284 double alpha_inh=0.0002;
00285 double alpha_input=0.0007;
00286 double beta=0.7;
00287 double delta=0.1;
00288 int display=0;
00289 int dynamics=0;
00290 double exc_death=0;
00291 double inh_death=0.00001;
00292 double lat_exc_randomness=1.0;
00293 double lat_inh_randomness=1.0;
00294 double noise=0.0;
00295 int preset_aff_wts=True;
00296 double preset_sigma_aff=Uninitialized;
00297 double preset_sigma_lat=Uninitialized;
00298 double preset_sigma_exc=Uninitialized;
00299 double preset_sigma_inh=Uninitialized;
00300 double randomness=0;
00301 int seed=87654321;
00302 int smooth_circular_outlines=False;
00303 double smooth_circular_radius_trim=-0.25;
00304 int tend=MAXITERATION;
00305 int essential_training_hooks_only=False;
00309 double accumulate_sum[NMAX];
00310 actlist activity_list[NROWS];
00311 int activity_marker[NMAX][NMAX];
00312 double aff_norm_sum[MAX_NUM_EYES*RNMAX*RNMAX];
00313 double afferent_sum[MAX_NUM_EYES*RNMAX*RNMAX];
00314 int exc_connections_killed=False;
00315 int inh_connections_killed=False;
00316 double gather_activity[NMAX][NMAX+1];
00317 double map_activity[NMAX][NMAX];
00318 actlist prev_activity_list[NMAX];
00319 double resp_to_inp[NMAX][NMAX];
00320 int RN_sq;
00321 double temp_sum[MAX_NUM_EYES*RNMAX*RNMAX];
00324
00325 #ifndef NO_WEIGHTS
00326 Wts wts[NROWS][NMAX];
00327 #endif
00328
00330 #ifdef VERIFY_WEIGHT_SAVES
00331 Wts Orig_wts[NROWS][NMAX];
00332 Neuron Orig_map[NMAX][NMAX];
00333 #endif
00334
00335
00336
00337
00338
00339
00340
00341 int binary_search(const int list[], int lower, int upper, int value);
00342 void clear_weights(void);
00343 void crop_actlist(const actlist, int lowval, int highval, int *lowidx, int *highidx);
00344 double dist_lat_wt(double value, double amt_of_randomness);
00345 double lat_resp(int ui, int uj, int radius, int array_width, l_weight *weights, int weight_idx_bound);
00346 double lat_resp_rad1(int ui, int uj, int radius, int array_width, int array_width_2, l_weight *weights, int weight_idx_bound);
00347 void modify_lat_wts(void);
00348 void modify_latwt_loop(int i, int j, int radius, int array_width, l_weight *weights, int weight_idx_bound, double alpha);
00349 void modify_latwt_loop_killed(int i, int j, int radius, int array_width, l_weight *weights, int weight_idx_bound, double alpha);
00350 void modify_latwt_loop_rad1(int ui, int uj, int radius, int array_width, int array_width_2, l_weight *weights, int weight_idx_bound, double alpha);
00351 void modify_weights(void);
00352 void normalize_afferent_wts(int lowk, int highk, int lowl, int highl, int row, int j, double length);
00353 void normalize_lat_wts(int i, int j, int radius, int array_width, l_weight *weights);
00354 double prune_circular_aff_weights(int ui, int uj, int radius,
00355 a_weight weights[MAX_NUM_EYES][WTMAX][WTMAX],
00356 double length);
00357 void prune_circular_lat_weights(int ui, int uj, int radius_sq, int array_width, l_weight *weights);
00358 void receptor_normalize(void);
00359 void reduce_lateral_radius(int ui, int uj, int old_radius, int new_radius, int array_width, l_weight *weights);
00360 void set_markers(int radius);
00361 void setup_lateral_weights(int ui, int uj, int radius,
00362 int array_width, l_weight *weights,
00363 int preset, double sigma, double randomness_scale,
00364 int* con_killed_flag);
00365 double sigmoid(double activity, double sigdelta, double sigbeta);
00366 void verify_actlist(actlist list);
00367 void verify_actlist_array(actlist lists[],int num);
00368 void verify_saved_lateral_weights( int i, int j, int radius, int array_width, l_weight *old_weights, l_weight *new_weights, double tolerance, const char *description);
00369 void verify_saved_weights( double tolerance );
00370
00371 CMD_DECLARE(init_network);
00372 CMD_DECLARE(kill_connections);
00373 CMD_DECLARE(step);
00374 CMD_DECLARE(testing);
00375 CMD_DECLARE(training);
00376 CMD_DECLARE(uninit_network);
00377
00378
00379
00380
00381
00382
00383 void kernel_init_hook( void )
00384 {
00385 CMD_DOC(kill_connections,"init_network",0, "%s [<inh_death> [<exc_death>]]",
00386 "Prunes lateral connections at or below below the specified levels.\n"
00387 "The levels default to the global values of those parameters.");
00388
00389 CMD_DOC(init_network,"uninit_network",0,"%s [<skip_weight_init>]",
00390 "Initializes network with the current parameters, suitable for\n"
00391 "beginning training anew. A command file <filebase>.init.param\n"
00392 "is created with the current values of parameters, suitable for\n"
00393 "recreating the starting state later. A single cycle of testing\n"
00394 "is done, iterating t to 1, in order to verify that everything is\n"
00395 "working properly. This command is a prerequisite for most other\n"
00396 "commands, and will be called automatically the first time one of\n"
00397 "those commands is executed. For debugging and internal purposes,\n"
00398 "a True argument may be supplied to skip the weight initialization.");
00399
00400 CMD_DOC(step,"init_network",0,"%s [<training_iterations>]",
00401 "Same as training except that it interprets the parameter as a\n"
00402 "value relative to the current iteration (default==1), rather\n"
00403 "than an absolute iteration number, and always displays result (as\n"
00404 "if display==1). Example: \"step\" just trains for one iteration\n"
00405 "and calls plot_activity. Typically used at the command prompt for\n"
00406 "debugging or exploration, rather than in a command file.");
00407
00408 CMD_DOC(testing,"init_network",0,"%s [<stop_iteration>]",
00409 "Same as training except that learning is turned off temporarily.\n"
00410 "The iteration counter is still advanced.");
00411
00412 CMD_DOC(training,"init_network",0,"%s [<stop_iteration>]",
00413 "Trains the network for the current iteration, then repeats training\n"
00414 "until the iteration counter (t) has reached the <stop_iteration>\n"
00415 "(which defaults to tend). Sometimes it is appropriate to supply a\n"
00416 "specific iteration (e.g. `training 1000' trains until iteration 1000);\n"
00417 "other times it's more useful to supply an offset relative to the current\n"
00418 "iteration (e.g. `training t+1000' trains for 1001 iterations more). After\n"
00419 "training, the global parameter t is one greater than the iteration\n"
00420 "specified.");
00421
00422 CMD_DOC(uninit_network,NULL,0,"%s",
00423 "Marks network uninitialized so that network architecture parameters\n"
00424 "can be changed. All weight values and training iteration hook\n"
00425 "definitions will be lost, and the iteration counter will be reset to\n"
00426 "zero. However, other parameters keep their existing values, which can\n"
00427 "have surprising consequences. When in doubt, it may be safest to quit\n"
00428 "the program and restart if changing the underlying architecture.");
00429
00430
00431
00432 PARAM_L(PARAM_DOUBLE,alpha_exc,0,
00433 "Learning rate for excitatory lateral connections.");
00434
00435 PARAM_L(PARAM_DOUBLE,alpha_inh,0,
00436 "Learning rate for inhibitory lateral connections.");
00437
00438 PARAM_L(PARAM_DOUBLE,alpha_input,0,
00439 "Learning rate for afferent connections.");
00440
00441 PARAM_N(PARAM_DOUBLE,beta,
00442 "Upper threshold of sigmoid-like activation function.");
00443
00444 PARAM_N(PARAM_DOUBLE,delta,
00445 "Lower threshold of sigmoid-like activation function.");
00446
00447 PARAM_L(PARAM_INT,display,0,
00448 "Plot network activation, etc. every (display)th training or testing\n"
00449 "iteration. If display==0, never do it; if display==1, do it every\n"
00450 "iteration, if display==2, do it every other iteration, etc.");
00451
00452 PARAM_I(PARAM_INT, dynamics,0,1,
00453 "Learning dynamics:\n"
00454 " 0 = discrete (learn after each presentation, i.e. when settling completes),\n"
00455 " 1 = continuous (learn after each settling step.)");
00456
00457 PARAM_I(PARAM_BOOL, essential_training_hooks_only,False,True,
00458 "If this is true, inessential hooks such as plotting and analysis will be\n"
00459 "ignored during training and initialization. (Whether or not a given command\n"
00460 "is ignored depends upon whether it was defined as a `catchup' command or not;\n"
00461 "see cmdparam.c.) This defaults to true for an interactive session to\n"
00462 "facilitate exploration using a saved batch session; this avoids having too\n"
00463 "many images displayed automatically.");
00464 params_define_default_expr("essential_training_hooks_only","interactive");
00465
00466 PARAM_L(PARAM_DOUBLE,exc_death,0,
00467 "Maximum value of excitatory lateral connection weights to kill when pruning.");
00468
00469 PARAM_L(PARAM_DOUBLE,inh_death,0,
00470 "Maximum value of inhibitory lateral connection weights to kill when pruning. ");
00471
00472 PARAM_L(PARAM_DOUBLE,lat_exc_randomness,0,
00473 "Randomness radius of lateral excitatory connections.");
00474
00475 PARAM_L(PARAM_DOUBLE,lat_inh_randomness,0,
00476 "Randomness radius of lateral inhibitory connections.");
00477
00478 PARAM_I(PARAM_DOUBLE,noise,0,1,
00479 "Intrinsic noise factor of the neuron.");
00480
00481 PARAM_I(PARAM_BOOL, preset_aff_wts,False,True,
00482 "Whether or not to use preset afferent weights.");
00483 SETFN_DEFINE(preset_aff_wts,fixed_arch_param_setfn);
00484
00485 PARAM_L(PARAM_DOUBLE,preset_sigma_aff,0,
00486 "Variance (sigma) of gaussian to preset afferent weights. It defaults to\n"
00487 "0.9*rf_radius, which makes it nearly fill up the available weight area.");
00488 params_define_default_expr("preset_sigma_aff","0.9*rf_radius");
00489
00490 PARAM_L(PARAM_DOUBLE,preset_sigma_lat,Uninitialized,
00491 "If this parameter is set, the default values for preset_sigma_exc and\n"
00492 "preset_sigma_inh are calculated from it as follows:\n\n"
00493
00494 " preset_sigma_exc = preset_sigma_lat\n"
00495 " preset_sigma_inh = preset_sigma_lat*MIN(1,sqrt(inh_rad))\n\n"
00496
00497 "This formula and the preset_sigma_lat parameter are used for backwards\n"
00498 "compatibility with old parameter files. The normal default values for\n"
00499 "the two parameters listed are probably more appropriate, so it is better\n"
00500 "to avoid setting this parameter.");
00501
00502 PARAM_L(PARAM_DOUBLE,preset_sigma_exc,Uninitialized,
00503 "Variance (sigma) of gaussian to preset lateral excitatory weights. Unless\n"
00504 "preset_sigma_lat is set, it defaults to 0.9*exc_rad, which makes it nearly\n"
00505 "fill up the available weight area.");
00506
00507 PARAM_L(PARAM_DOUBLE,preset_sigma_inh,Uninitialized,
00508 "Variance (sigma) of gaussian to preset lateral inhibitory weights. Unless\n"
00509 "preset_sigma_lat is set, it defaults to 0.9*inh_rad, which makes it nearly\n"
00510 "fill up the available weight area.");
00511
00512 PARAM_I(PARAM_DOUBLE,randomness,0,1,
00513 "Amount of randomness of placement of receptive field centers for each neuron:\n"
00514 "0 = no randomness, 1 = offset by RN/2 max. The code hasn't been verified for\n"
00515 "cases where the randomness is set high enough to have centers chosen more than\n"
00516 "rf_radius units off the retina, and init_weights() will probably need\n"
00517 "modification to handle that case properly.");
00518
00519 PARAM_N(PARAM_INT, seed,
00520 "Seed for random number generator used to generate initial weights, etc. See\n"
00521 "also inputs_seed if applicable.");
00522 SETFN_DEFINE(seed,fixed_arch_param_setfn);
00523
00524 PARAM_I(PARAM_BOOL, smooth_circular_outlines,False,True,
00525 "If true, smoothes the edges of circular weights when they are initialized or\n"
00526 "when a radius is reduced by multiplying them by a Gaussian which starts at\n"
00527 "radius+smooth_circular_radius_trim and has a sigma of (circular_radius_trim-\n"
00528 "smooth_circular_radius_trim)/2.");
00529 SETFN_DEFINE(smooth_circular_outlines,fixed_arch_param_setfn);
00530
00531 PARAM_N(PARAM_DOUBLE,smooth_circular_radius_trim,
00532 "When smooth_circular_outlines is True, this quantity is added to the\n"
00533 "appropriate radius (rf_radius, inh_rad, or exc_rad) to create a\n"
00534 "floating-point radius at which to start smoothing the outline. It\n"
00535 "should presumably be smaller than circular_radius_trim, and may be slightly\n"
00536 "negative.");
00537
00538 PARAM_I(PARAM_INT, tend,0,MAXITERATION,
00539 "Upper bound for training iterations. If no command file is specified,\n"
00540 "the last iteration trained will be tend. If a command file is specified,\n"
00541 "the last iteration trained will be the smaller of tend or the last\n"
00542 "training iteration requested in the command file.");
00543 }
00544
00545
00546
00547
00548
00549
00550
00551
00553 cmdstat cmd_training( CMD_ARGS )
00554 {
00555 int training_stop=MAXITERATION;
00556 time_t last_msg_time = time(NULL);
00557
00558
00559 if (argc>0){
00560 if (argv[0][0] == '+')
00561 training_stop = iteration + cmdi(&(argv[0][1]));
00562 else
00563 training_stop = cmdi(argv[0]);
00564 }
00565 if (training_stop > tend) training_stop = tend;
00566
00567 if (learning)
00568 ipc_notify(IPC_ONE,IPC_STD,"Training until iteration %d", training_stop);
00569 else if (iteration!=0)
00570 ipc_notify(IPC_ONE,IPC_STD,"Testing until iteration %d", training_stop);
00571
00572
00573
00574 for(iteration=startt; iteration <= training_stop; iteration++) {
00575 ipc_barrier();
00576
00577 if (PROGRESS_REPORT_NEEDED(last_msg_time)) {
00578 last_msg_time = time(NULL);
00579 ipc_notify(IPC_ONE,IPC_STD,"%s has reached iteration %06d, %.24s",
00580 (learning ? "Training" : "Testing"),iteration,ctime(&last_msg_time));
00581 }
00582
00583
00584 hooklists_run_list(before_input,iteration,essential_training_hooks_only);
00585
00586 #ifndef NO_INPUTS
00587
00588 inputs->next();
00589 #ifdef PRINT_TIME_PER_ITERATION
00590 clock_t time_before_iteration = clock();
00591 #endif
00592 inputs->activate(learning);
00593
00594 #ifdef PRINT_TIME_PER_ITERATION
00595 ipc_log(IPC_ONE,"Iteration %06d took %04d milliseconds",
00596 iteration,(int)((clock()-time_before_iteration)*1000.0/CLOCKS_PER_SEC));
00597 #endif
00598
00599 #endif
00600
00601 hooklists_run_list(after_learning,iteration,essential_training_hooks_only);
00602 #ifndef NO_IO
00603 if (display && iteration%display==0)
00604 cmd_plot_activity(0,NULL);
00605 #endif
00606 }
00607 startt = iteration;
00608 iteration--;
00609
00610 return CMD_NO_ERROR;
00611 }
00612
00613
00614
00615 cmdstat cmd_testing( CMD_ARGS )
00616 {
00617 const int orig_learning = learning;
00618 cmdstat status;
00619
00620 learning = False;
00621 status = cmd_training(argc,argv);
00622 learning = orig_learning;
00623
00624 return status;
00625 }
00626
00627
00628
00629 cmdstat cmd_step( CMD_ARGS )
00630 {
00631 const int orig_display = display;
00632 const int iterations = ((argc>0)? cmdi(argv[0]) : 1);
00633 char argstring[CMD_MAX_LINE_LENGTH];
00634 const char *args[1];
00635 cmdstat status;
00636
00637 snprintf(argstring, CMD_MAX_LINE_LENGTH-1, "%d", iteration+iterations);
00638 args[0]=argstring;
00639
00640 display=1;
00641 status = cmd_training(1,args);
00642 display=orig_display;
00643
00644 return status;
00645 }
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655 InputVectorWrapper::InputVectorWrapper(string name_i, int e)
00656 : InternalNeuralRegion(name_i,RN,RN), eye(e), input(0) { }
00657
00658
00659 void InputVectorWrapper::add_input(const string&,const ActivityMatrix& input_region, WeightFunction&, Length size_scale)
00660 {
00661 assert(input==0);
00662 assert(int(input_region.nrows())==RN);
00663 assert(int(input_region.ncols())==RN);
00664 (void)size_scale;
00665 assert(size_scale==1.0);
00666 input=&input_region;
00667 }
00668
00669
00670 InputVectorWrapper::Dimensions InputVectorWrapper::input_dimensions(WeightFunction&, Length size_scale)
00671 {
00672 (void)size_scale;
00673 assert (size_scale==1.0);
00674 return Dimensions(Subscript(RN),Subscript(RN));
00675 }
00676
00677
00678 const InputVectorWrapper::WeightMatrix InputVectorWrapper::get_weights(const string& name, int, int) const
00679 {
00680
00681 if (name=="Afferent") {
00682 WeightMatrix w(1,1); w[0][0] = 1;
00683 return w;
00684 }
00685
00686 return WeightMatrix();
00687 }
00688
00689
00690 void InputVectorWrapper::activate(bool, bool)
00691 {
00692
00693 assert (input->nrows() == output.nrows() && input->ncols() == output.ncols());
00694 for (Subscript i=0; i<input->nrows(); i++)
00695 for (Subscript j=0; j<input->ncols(); j++)
00696 input_vectors[INP_INDEX(eye,j,i)]=(*input)[i][j];
00697 }
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708 CortexMapWrapper::CortexMapWrapper(string name_i)
00709 : InternalNeuralRegion(name_i,N,N) { }
00710
00711
00712 void CortexMapWrapper::activate(bool learn, bool)
00713 {
00714 present_inputs(learn);
00715
00716
00717
00718 for (Subscript i=0; i<output.nrows(); i++)
00719 for (Subscript j=0; j<output.ncols(); j++)
00720 output[i][j] = ::prev_map_activity[j][i];
00721
00722 }
00723
00724
00725
00726 void CortexMapWrapper::add_input(const string&,const ActivityMatrix& input_region, WeightFunction&, Length size_scale)
00727 {
00728 assert(int(input_region.nrows())==RN);
00729 assert(int(input_region.ncols())==RN);
00730 (void)input_region;
00731 (void)size_scale;
00732 assert(int(size_scale*RN)==N);
00733 }
00734
00735
00736 CortexMapWrapper::Dimensions CortexMapWrapper::input_dimensions(WeightFunction&, Length size_scale)
00737 {
00738 (void)size_scale;
00739 assert (size_scale==1.0);
00740 return Dimensions(Subscript(RN),Subscript(RN));
00741 }
00742
00743
00744 const CortexMapWrapper::WeightMatrix CortexMapWrapper::get_weights(const string& name, int ui, int uj) const
00745 {
00746 assert (ROWISLOCAL(ui));
00747
00748
00749 if (String::non_numeric_basename_matches<string>(name,"Afferent")) {
00750 const string s = String::numeric_extension<string>(name);
00751 const int eye = (s == "" ? 0 : String::numeric_extension<int>(name));
00752
00753 assert (eye<num_eyes);
00754
00755 const int lowk = MAX(cortex_map[ui][uj].centerx-rf_radius,0 );
00756 const int highk = MIN(cortex_map[ui][uj].centerx+rf_radius,RN-1);
00757 const int lowl = MAX(cortex_map[ui][uj].centery-rf_radius,0 );
00758 const int highl = MIN(cortex_map[ui][uj].centery+rf_radius,RN-1);
00759
00760 WeightMatrix w(highl-lowl+1,highk-lowk+1);
00761
00762 for (int k=lowk; k <=highk; k++)
00763 for (int l=lowl; l<=highl; l++)
00764 w[l-lowl][k-lowk] = cortex_map[ui][uj].weights[eye][k-lowk][l-lowl];
00765
00766 return w;
00767 }
00768 else if (name == "LateralExcitatory") {
00769 const int lowi = MAX(ui-exc_rad,0);
00770 const int highi = MIN(ui+exc_rad,N-1);
00771 const int lowj = MAX(uj-exc_rad,0);
00772 const int highj = MIN(uj+exc_rad,N-1);
00773
00774 WeightMatrix w(highj-lowj+1,highi-lowi+1);
00775
00776 for (int i=lowi; i<=highi; i++)
00777 for (int j=lowj; j<=highj; j++)
00778 w[j-lowj][i-lowi] = cortex_map[ui][uj].lat_exc_wts[LAT_INDEX(ui,uj,i,j,exc_rad,exc_array_width)];
00779
00780 return w;
00781 }
00782 else if (name == "LateralInhibitory") {
00783 const int lowi = MAX(ui-inh_rad,0);
00784 const int highi = MIN(ui+inh_rad,N-1);
00785 const int lowj = MAX(uj-inh_rad,0);
00786 const int highj = MIN(uj+inh_rad,N-1);
00787
00788 WeightMatrix w(highj-lowj+1,highi-lowi+1);
00789
00790 for (int i=lowi; i<=highi; i++)
00791 for (int j=lowj; j<=highj; j++)
00792 w[j-lowj][i-lowi] = cortex_map[ui][uj].lat_inh_wts[LAT_INDEX(ui,uj,i,j,inh_rad,inh_array_width)];
00793
00794 return w;
00795 }
00796
00797
00798 return WeightMatrix();
00799 }
00800
00801
00802
00803
00804
00805
00806
00827 void present_inputs(int learn)
00828 {
00829 int i,pe,j,count;
00830 static int iteration_of_last_presentation=Uninitialized;
00831
00832 if (iteration!=iteration_of_last_presentation) {
00833 iteration_of_last_presentation=iteration;
00834 presentation=0;
00835 }
00836 else
00837 presentation++;
00838
00839 settle_responses(learn);
00840
00841 for(pe=0; pe< NPEs; pe++)
00842 for(i=0; i<nrows; i++)
00843 ipc_get_to(prev_map_activity[ARBITRARY_MAPROW(i,pe)],
00844 map_activity[ARBITRARY_MAPROW(i,pe)],IPC_DOUBLE,N,pe);
00845
00846
00847 for (i=0; i<N; i++)
00848 if ((count=ACTLIST_COUNT(prev_activity_list[i])) > 0)
00849 for (j=ACTLIST_START(prev_activity_list); j<=count; j++)
00850 gather_activity[i][j]=prev_map_activity[i][prev_activity_list[i][j]];
00851
00852
00853 if (learn && dynamics==0){
00854 if (alpha_input!=0)
00855 modify_weights();
00856 if (alpha_exc!=0 || alpha_inh!=0)
00857 modify_lat_wts();
00858 }
00859
00860 if (presentation>0)
00861 hooklists_run_list(after_presentation,iteration,essential_training_hooks_only);
00862 }
00863
00864
00865
00867 void settle_responses(int learn)
00868 {
00869 int ts;
00870
00871 response_to_input();
00872 initialize_markers();
00873 initialize_actlists();
00874
00875 ipc_barrier();
00876
00877 for(ts=1; ts<=tsettle; ts++){
00878 compute_responses(ts);
00879 ipc_barrier();
00880
00881 if (learn && dynamics==1) {
00882 if (alpha_input!=0)
00883 modify_weights();
00884
00885 if (alpha_exc!=0 || alpha_inh!=0){
00886 modify_lat_wts();
00887 ipc_barrier();
00888 }
00889 }
00890 }
00891 }
00892
00893
00894
00896 void response_to_input(void)
00897 {
00898 int i,j,k,l,index0,index1=0;
00899
00900 for(i=0; i<nrows; i++){
00901 const int row = MAPROW(i);
00902 for(j=0; j<N; j++)
00903 {
00904 const int lowk = MAX(cortex_map[row][j].centerx-rf_radius,0 );
00905 const int highk = MIN(cortex_map[row][j].centerx+rf_radius,RN-1);
00906 const int lowl = MAX(cortex_map[row][j].centery-rf_radius,0 );
00907 const int highl = MIN(cortex_map[row][j].centery+rf_radius,RN-1);
00908 double resp =0;
00909 double resp1=0;
00910
00911
00912 if (dynamics==0) prev_map_activity[row][j] = map_activity[row][j] =0.0;
00913
00914
00915 for (k=lowk; k <=highk; k++){
00916 index0 = INP_INDEX(0,k,lowl);
00917 assert (index0 >= INP_INDEX(0,0,0));
00918 assert (index0 < INP_INDEX(1,0,0));
00919
00920 #ifndef NUM_EYES_IS_CONSTANT
00921
00922 for (l=lowl; l<=highl; l++,index0++,index1++){
00923 int eye;
00924 for (eye=0; eye<num_eyes; eye++)
00925 resp += input_vectors[INP_INDEX_OTHER_EYE(eye,index0)] *
00926 cortex_map[row][j].weights[eye][k-lowk][l-lowl];
00927 }
00928
00929
00930 #else
00931 #if (num_eyes>1)
00932 index1 = INP_INDEX_OTHER_EYE(1,index0);
00933 assert (index1 >= INP_INDEX(1,0,0));
00934 assert (index1 < INP_INDEX(2,0,0));
00935 #endif
00936 00937 00938 00939 00940
00941 for (l=lowl; l<=highl; l++,index0++,index1++){
00942 resp += input_vectors[index0] * cortex_map[row][j].weights[0][k-lowk][l-lowl];
00943 #if (num_eyes>1)
00944 resp1 += input_vectors[index1] * cortex_map[row][j].weights[1][k-lowk][l-lowl];
00945 #endif
00946 #if (num_eyes>2)
00947 {
00948 int eye;
00949 for (eye=2; eye<num_eyes; eye++)
00950 resp += input_vectors[INP_INDEX_OTHER_EYE(eye,index0)] *
00951 cortex_map[row][j].weights[eye][k-lowk][l-lowl];
00952 }
00953 #endif
00954 }
00955 #endif
00956 }
00957 resp_to_inp[row][j] = resp + resp1;
00958 }
00959 }
00960 }
00961
00962
00963
00965 void compute_responses(int ts)
00966 {
00967 int i,pe,j,row,count; double resp;
00968
00969 if ((ts==1) && (dynamics==0)){
00970 for(i=0; i<nrows; i++){
00971 row = MAPROW(i);
00972 for(j=0; j<N; j++)
00973 {
00974 resp = resp_to_inp[row][j];
00975 if (noise > 0.0)
00976 resp += noise * (shuffled_rand()-0.5);
00977 map_activity[row][j] = init_activity[row][j] = sigmoid(resp,delta,beta);
00978 if (map_activity[row][j] > 0.0)
00979 activity_list[i][++ACTLIST_COUNT(activity_list[i])] = j;
00980 }
00981 assert(ACTLIST_COUNT(activity_list[i]) >= 0); assert(ACTLIST_COUNT(activity_list[i]) <= N);
00982 }
00983 ipc_barrier();
00984 for(i=0; i<nrows; i++){
00985 row = MAPROW(i);
00986 for (pe=0; pe < NPEs; pe++)
00987 ipc_put_to(&(prev_activity_list[row][0]), &(activity_list[i][0]),
00988 IPC_INT,ACTLIST_COUNT(activity_list[i])+1,pe);
00989 ACTLIST_COUNT(activity_list[i]) = 0;
00990 }
00991 return;
00992 }
00993
00994 00995 00996
00997 for(pe=0; pe< NPEs; pe++)
00998 for (i=0; i<nrows; i++){
00999 row = ARBITRARY_MAPROW(i,pe);
01000 ipc_get_to(prev_map_activity[row],map_activity[row],IPC_DOUBLE,N,pe);
01001 }
01002
01003
01004 if (ts==3){
01005 if (exc_rad > 1) set_markers(exc_rad);
01006 else set_markers(2);
01007 }
01008 01009 01010 01011
01012 for (i=0; i<N; i++)
01013 if ((count=ACTLIST_COUNT(prev_activity_list[i])) > 0)
01014 for (j=ACTLIST_START(prev_activity_list); j<=count; j++)
01015 gather_activity[i][j]=prev_map_activity[i][prev_activity_list[i][j]];
01016
01017 for(i=0; i<nrows; i++){
01018 row = MAPROW(i);
01019 for(j=0; j<N; j++){
01020
01021 if (activity_marker[row][j]){
01022 resp = resp_to_inp[row][j];
01023
01024 if (noise > 0.0)
01025 resp += noise * (shuffled_rand()-0.5);
01026
01027 if (exc_rad <= 1)
01028 resp += gammaexc * lat_resp_rad1(row, j, exc_rad, exc_array_width, exc_array_width_2,
01029 cortex_map[row][j].lat_exc_wts, lat_exc_dimension);
01030
01031 else
01032 resp += gammaexc * lat_resp(row, j, exc_rad, exc_array_width,
01033 cortex_map[row][j].lat_exc_wts, lat_exc_dimension);
01034
01035
01036 if ( sigmoid(resp, delta, beta) >0.0 )
01037 map_activity[row][j] = sigmoid((resp-gammainh*lat_resp(row,j,inh_rad,
01038 inh_array_width,cortex_map[row][j].lat_inh_wts, lat_inh_dimension)),
01039 delta, beta);
01040 if (map_activity[row][j] > 0.0)
01041 activity_list[i][++ACTLIST_COUNT(activity_list[i])] = j;
01042
01043 }
01044 else map_activity[row][j]=0.0;
01045 }
01046 }
01047
01048 ipc_barrier();
01049 for(i=0; i<nrows; i++){
01050 row = MAPROW(i);
01051 for (pe=0; pe < NPEs; pe++)
01052 ipc_put_to(&(prev_activity_list[row][0]), &(activity_list[i][0]),
01053 IPC_INT,ACTLIST_COUNT(activity_list[i])+1,pe);
01054 ACTLIST_COUNT(activity_list[i]) = 0;
01055 }
01056 }
01057
01058
01059
01065 int binary_search(const int list[], int lower, int upper, int value)
01066 {
01067
01068 if (value <= list[lower]) return lower;
01069 if (value > list[upper]) return upper+1;
01070
01071
01072 while(lower < upper) {
01073 const int middle = (lower+upper) >> 1;
01074 const int compare_to = list[middle];
01075 if (value > compare_to) lower = middle + 1;
01076 else if (value < compare_to) upper = middle;
01077 else return(middle);
01078 }
01079 return(lower);
01080 }
01081
01082
01083
01090 void crop_actlist(const actlist list, int lowval, int highval, int *lowidx, int *highidx)
01091 {
01092 (*lowidx )=ACTLIST_START(list);
01093 (*highidx)=ACTLIST_COUNT(list);
01094
01095 if (lowval == 0)
01096 (*lowidx) = 1;
01097 else
01098 (*lowidx) = binary_search(list,(*lowidx),(*highidx),lowval);
01099
01100 if (highval==(N-1))
01101 (*highidx) = ACTLIST_COUNT(list);
01102 else {
01103 (*highidx) = binary_search(list,(*lowidx),(*highidx),highval);
01104
01105 if ((*highidx) > ACTLIST_COUNT(list) || (list[(*highidx)]> highval))
01106 (*highidx)--;
01107 }
01108 }
01109
01110
01111
01116 01117 01118 01119 01120 01121 01122 01123 01124 01125
01126
01127
01128
01130 void verify_actlist(actlist list)
01131 {
01132 int i;
01133 int count=ACTLIST_COUNT(list);
01134
01135 if (count <0 || count > NMAX) {
01136 ipc_notify(IPC_ALL,IPC_ERROR,"List has invalid count (%d)",count);
01137 return;
01138 }
01139 for (i=ACTLIST_START(list); i<count; i++)
01140 if (list[i]>= list[i+1]) {
01141 ipc_notify(IPC_ALL,IPC_ERROR,"List is not in proper order -- for %d elements, list[%d]=%d > list[%d]=%d",
01142 count,i,list[i],i+1,list[i+1]);
01143 return;
01144 }
01145 return;
01146 }
01147
01148
01150 void verify_actlist_array(actlist lists[],int num)
01151 {
01152 int i;
01153 for (i=0; i<num; i++)
01154 verify_actlist(lists[i]);
01155 }
01156
01157
01158
01160 void initialize_actlists( void )
01161 {
01162 int i;
01163 for(i=0; i<nrows; i++) {
01164 ACTLIST_COUNT(prev_activity_list[MAPROW(i)]) = 0;
01165 ACTLIST_COUNT(activity_list[i]) = 0;
01166 }
01167 }
01168
01169
01170
01173 void initialize_markers( void )
01174 {
01175 int i,j;
01176
01177 for(i=0; i<nrows; i++){
01178 const int row = MAPROW(i);
01179 for(j=0; j<N; j++)
01180 activity_marker[row][j] = True;
01181 }
01182 }
01183
01184
01185
01191 void set_markers(int radius)
01192 {
01193 int i,j,k,l;
01194
01195 for(i=0; i<nrows; i++){
01196 const int row = MAPROW(i);
01197 const int lowk = MAX(row-radius,0);
01198 const int highk = MIN(row+radius,N-1);
01199
01200 for(j=0; j<N; j++){
01201 const int lowl = MAX(j-radius,0);
01202 const int highl = MIN(j+radius,N-1);
01203 double marker_resp = 0.0;
01204
01205 for(k=lowk; k<= highk; k++)
01206 for(l=lowl; l<=highl; l++)
01207 marker_resp += prev_map_activity[k][l];
01208
01209 if (marker_resp > ALIVE_MINIMUM) activity_marker[row][j] = True;
01210 else activity_marker[row][j] = False;
01211 }
01212 }
01213 }
01214
01215
01216
01221 double lat_resp(int ui, int uj, int radius, int array_width, l_weight *weights, int weight_idx_bound)
01222 {
01223 int i, j;
01224 double resp=0;
01225
01226 const int lowi = MAX(ui-radius,0);
01227 const int highi = MIN(ui+radius,N-1);
01228
01229 (void)weight_idx_bound;
01230
01231 for(i=lowi; i<=highi; i++)
01232 if (ACTLIST_COUNT(prev_activity_list[i]) > 0){
01233 const int lowj = MAX(uj-radius,0);
01234 const int highj = MIN(uj+radius,N-1);
01235 const int partial_idx = PARTIAL_LAT_INDEX(ui,uj,i,radius,array_width);
01236 int high_idx, low_idx;
01237
01238 crop_actlist(prev_activity_list[i],lowj,highj,&low_idx,&high_idx);
01239 assert (high_idx <= ACTLIST_COUNT(prev_activity_list[i]));
01240
01241
01242 for(j=low_idx; j <= high_idx; j++){
01243 const int idx = FULL_LAT_INDEX(partial_idx,prev_activity_list[i][j]);
01244 assert (prev_activity_list[i][j] >= lowj);
01245 assert (prev_activity_list[i][j] <= highj);
01246 assert (idx >= 0); assert (idx <= weight_idx_bound);
01247
01248 resp += gather_activity[i][j] * weights[idx];
01249 }
01250 }
01251 return(resp);
01252 }
01253
01254
01255
01257 double lat_resp_rad1(int ui, int uj, int radius, int array_width, int array_width_2, l_weight *weights, int weight_idx_bound)
01258 {
01259 double resp, resp1, resp2;
01260
01261 01262
01263 (void)weight_idx_bound;
01264
01265 if (radius==0){
01266 resp = prev_map_activity[ui][uj];
01267 return(resp);
01268 }
01269 resp = resp1 = resp2=0.0;
01270 if ((ui > 0) && (ui < N-1))
01271 {
01272 if ((uj >0) && (uj < N-1))
01273 {
01274
01275 resp = prev_map_activity[ui-1][uj-1] * weights[ 0 ];
01276 resp1 = prev_map_activity[ui-1][uj ] * weights[ 1 ];
01277 resp2 = prev_map_activity[ui-1][uj+1] * weights[ 2 ];
01278
01279 resp += prev_map_activity[ui ][uj-1] * weights[ array_width ];
01280 resp1 += prev_map_activity[ui ][uj ] * weights[FULL_LAT_INDEX(array_width, 1)];
01281 resp2 += prev_map_activity[ui ][uj+1] * weights[FULL_LAT_INDEX(array_width, 2)];
01282
01283 resp += prev_map_activity[ui+1][uj-1] * weights[ array_width_2 ];
01284 resp1 += prev_map_activity[ui+1][uj ] * weights[FULL_LAT_INDEX(array_width_2,1)];
01285 resp2 += prev_map_activity[ui+1][uj+1] * weights[FULL_LAT_INDEX(array_width_2,2)];
01286 }
01287 else{
01288 const int lowj = MAX(uj-1,0);
01289 const int highj = MIN(uj+1,N-1);
01290 const int partial_index0 = - uj + 1;
01291 const int partial_index1 = array_width - uj + 1;
01292 const int partial_index2 = array_width_2 - uj + 1;
01293 int j;
01294
01295 for(j=lowj; j<=highj; j++){
01296 resp += prev_map_activity[ui-1][j] * weights[FULL_LAT_INDEX(partial_index0,j)];
01297 resp1 += prev_map_activity[ui ][j] * weights[FULL_LAT_INDEX(partial_index1,j)];
01298 resp2 += prev_map_activity[ui+1][j] * weights[FULL_LAT_INDEX(partial_index2,j)];
01299 }
01300 }
01301 resp += resp1 + resp2;
01302 }
01303 else if (ui > 0){
01304 const int lowj = MAX(uj-1,0);
01305 const int highj = MIN(uj+1,N-1);
01306 const int partial_index0 = -uj + 1;
01307 const int partial_index1 = array_width - uj + 1;
01308 int j;
01309
01310 for(j=lowj; j<=highj; j++){
01311 resp += prev_map_activity[ui-1][j] * weights[FULL_LAT_INDEX(partial_index0,j)];
01312 resp1+= prev_map_activity[ui ][j] * weights[FULL_LAT_INDEX(partial_index1,j)];
01313 }
01314 resp += resp1;
01315 }
01316 else{
01317 const int lowj = MAX(uj-1,0);
01318 const int highj = MIN(uj+1,N-1);
01319 const int partial_index0 = array_width - uj + 1;
01320 const int partial_index1 = array_width_2 - uj + 1;
01321 int j;
01322
01323 for(j=lowj; j<=highj; j++){
01324 resp += prev_map_activity[ui ][j] * weights[FULL_LAT_INDEX(partial_index0,j)];
01325 resp1+= prev_map_activity[ui+1][j] * weights[FULL_LAT_INDEX(partial_index1,j)];
01326 }
01327 resp += resp1;
01328 }
01329 return(resp);
01330 }
01331
01332
01333
01338 void modify_weights(void)
01339 {
01340 int i,j,k,l,eye;
01341
01342 if (normalize_aff)
01343 for(i=0; i<RN; i++)
01344 for(j=0; j<RN; j++)
01345 for (eye=0; eye<num_eyes; eye++)
01346 afferent_sum[INP_INDEX(eye,i,j)] = 0.0;
01347
01348 for(i=0; i<nrows; i++){
01349 const int row = MAPROW(i);
01350
01351 for(j=0; j<N; j++)
01352 if (normalize_aff || (prev_map_activity[row][j] > 0.0)){
01353
01354
01355 const int lowk = MAX(cortex_map[row][j].centerx-rf_radius,0 );
01356 const int highk = MIN(cortex_map[row][j].centerx+rf_radius,RN-1);
01357 const int lowl = MAX(cortex_map[row][j].centery-rf_radius,0 );
01358 const int highl = MIN(cortex_map[row][j].centery+rf_radius,RN-1);
01359
01360 if (prev_map_activity[row][j] > 0.0){
01361
01362 double deltaw = alpha_input * prev_map_activity[row][j];
01363 double length = 0.0;
01364
01365 for (eye=0; eye<num_eyes; eye++)
01366 for (k=lowk; k<=highk; k++){
01367 int idx = INP_INDEX(eye,k,lowl);
01368 assert (idx >= INP_INDEX(eye,0,0));
01369
01370 for (l=lowl; l<=highl; l++,idx++) {
01371 a_weight* const wtptr = &(cortex_map[row][j].weights[eye][k-lowk][l-lowl]);
01372 assert (idx < INP_INDEX(eye+1,0,0));
01373
01374 if (*wtptr > -DEATH_FLAG) {
01375 const double load = input_vectors[idx];
01376
01377 if ( load > 0.0){
01378 const double delt = load * deltaw;
01379 *wtptr += delt;
01380 length += delt;
01381 }
01382 }
01383 }
01384 }
01385
01386 if (! normalize_aff)
01387 normalize_afferent_wts(lowk,highk,lowl,highl,row,j,1.0/(1.0+length));
01388 }
01389
01390 if (normalize_aff)
01391 for (k=lowk; k<=highk; k++)
01392 for (l=lowl; l<=highl; l++)
01393 for (eye=0; eye<num_eyes; eye++) {
01394 assert (INP_INDEX(eye,k,l) >= INP_INDEX(eye, 0,0));
01395 assert (INP_INDEX(eye,k,l) < INP_INDEX(eye+1,0,0));
01396
01397 afferent_sum[INP_INDEX(eye,k,l)] += cortex_map[row][j].weights[eye][k-lowk][l-lowl];
01398 }
01399 }
01400 }
01401
01402 if (normalize_aff) receptor_normalize();
01403 }
01404
01405
01406
01408 void receptor_normalize(void)
01409 {
01410 double result;
01411 int i,j,k,l,pe,eye;
01412
01413 for(k=0; k<RN; k++)
01414 for(l=0; l<RN; l++)
01415 for (eye=0; eye<num_eyes; eye++)
01416 temp_sum[INP_INDEX(eye,k,l)] = afferent_sum[INP_INDEX(eye,k,l)];
01417
01418 ipc_barrier();
01419
01420 for(pe=0; pe<NPEs; pe++)
01421 if (!PEISME(pe)){
01422 ipc_get_to(aff_norm_sum, afferent_sum, IPC_DOUBLE,num_eyes*RN*RN,pe);
01423
01424 for(k=0; k<RN; k++)
01425 for(l=0; l<RN; l++)
01426 for (eye=0; eye<num_eyes; eye++)
01427 temp_sum[INP_INDEX(eye,k,l)] += aff_norm_sum[INP_INDEX(eye,k,l)];
01428 }
01429
01430 ipc_barrier();
01431
01432 for(k=0; k<RN; k++)
01433 for (l=0; l<RN; l++)
01434 for (eye=0; eye<num_eyes; eye++)
01435 afferent_sum[INP_INDEX(eye,k,l)] = 1.0/temp_sum[INP_INDEX(eye,k,l)];
01436
01437 for(i=0; i<nrows; i++){
01438 const int row = MAPROW(i);
01439 for(j=0; j<N; j++){
01440 const int lowk = MAX(cortex_map[row][j].centerx-rf_radius,0 );
01441 const int highk = MIN(cortex_map[row][j].centerx+rf_radius,RN-1);
01442 const int lowl = MAX(cortex_map[row][j].centery-rf_radius,0 );
01443 const int highl = MIN(cortex_map[row][j].centery+rf_radius,RN-1);
01444 double length = 0.0;
01445
01446
01447 for (k=lowk; k<=highk; k++)
01448 for (l=lowl; l<=highl; l++)
01449 for (eye=0; eye<num_eyes; eye++){
01450 a_weight* const wtptr = &(cortex_map[row][j].weights[eye][k-lowk][l-lowl]);
01451 assert (INP_INDEX(eye,k,l) >= INP_INDEX(eye, 0,0));
01452 assert (INP_INDEX(eye,k,l) < INP_INDEX(eye+1,0,0));
01453
01454 result = (*wtptr) * afferent_sum[INP_INDEX(eye,k,l)];
01455 length += result;
01456
01457 *wtptr = result;
01458 }
01459
01460 normalize_afferent_wts(lowk,highk,lowl,highl,row,j,1.0/length);
01461 }
01462 }
01463 }
01464
01465
01466
01467 void normalize_afferent_wts(int lowk, int highk, int lowl, int highl, int row, int j, double length)
01468 {
01469 int k,l,eye;
01470
01471
01472 for (k=lowk; k<=highk; k++)
01473 for (l=lowl; l<=highl; l++)
01474 for (eye=0; eye<num_eyes; eye++) {
01475 a_weight* const wtptr = &(cortex_map[row][j].weights[eye][k-lowk][l-lowl]);
01476 if (*wtptr > -DEATH_FLAG)
01477 *wtptr *= length;
01478 }
01479 }
01480
01481
01482
01488 void modify_lat_wts(void)
01489 {
01490 int i,j;
01491
01492 for(i=0; i<nrows; i++){
01493 const int row = MAPROW(i);
01494
01495 for(j=0; j<N; j++)
01496 if (prev_map_activity[row][j] > 0.0){
01497
01498 if (exc_rad==1 && !exc_connections_killed)
01499 modify_latwt_loop_rad1(row,j,exc_rad, exc_array_width, exc_array_width_2,
01500 cortex_map[row][j].lat_exc_wts, lat_exc_dimension, alpha_exc);
01501 else
01502 modify_latwt_loop( row,j, exc_rad, exc_array_width,
01503 cortex_map[row][j].lat_exc_wts, lat_exc_dimension, alpha_exc);
01504
01505 modify_latwt_loop( row,j, inh_rad, inh_array_width,
01506 cortex_map[row][j].lat_inh_wts, lat_inh_dimension, alpha_inh);
01507 }
01508 }
01509 }
01510
01511
01512
01514 void modify_latwt_loop(int i, int j, int radius, int array_width, l_weight *weights, int weight_idx_bound, double alpha)
01515 {
01516 int k,m;
01517 const int lowk = MAX(i-radius,0 );
01518 const int highk = MIN(i+radius,N-1);
01519 const int lowl = MAX(j-radius,0 );
01520 const int highl = MIN(j+radius,N-1);
01521 const double loop_const=alpha * prev_map_activity[i][j];
01522 double new_length=0;
01523
01524 (void)weight_idx_bound;
01525
01526 for (k=lowk; k<=highk; k++)
01527 if ( ACTLIST_COUNT(prev_activity_list[k]) > 0) {
01528 const int partial_idx = PARTIAL_LAT_INDEX(i,j,k,radius,array_width);
01529 int low_idx, high_idx;
01530 crop_actlist(prev_activity_list[k],lowl,highl,&low_idx,&high_idx);
01531
01532
01533 for (m=low_idx; m <= high_idx; m++) {
01534 const int l = prev_activity_list[k][m];
01535 const int idx = FULL_LAT_INDEX(partial_idx,l);
01536 assert (l >= lowl); assert (l <= highl);
01537 assert (idx >= 0); assert (idx <= weight_idx_bound);
01538
01539 if ( (weights[idx]) > -DEATH_FLAG){
01540 const double delt = gather_activity[k][m] * loop_const;
01541 new_length += delt;
01542 weights[idx] += delt;
01543 }
01544 }
01545 }
01546 new_length = 1.0/(1.0+new_length);
01547
01548 for (k=lowk; k<=highk; k++) {
01549 int idx = LAT_INDEX(i,j,k,lowl,radius,array_width);
01550 int l;
01551 assert (idx >= 0);
01552
01553
01554 for (l=lowl; l<=highl; l++,idx++) {
01555 assert (idx <= weight_idx_bound);
01556 if (weights[idx] > -DEATH_FLAG)
01557 weights[idx] *= new_length;
01558 }
01559 }
01560 }
01561
01562
01563
01567 void modify_latwt_loop_rad1(int ui, int uj, int radius, int array_width, int array_width_2, l_weight *weights, int weight_idx_bound, double alpha)
01568 {
01569 int j;
01570 double length=0;
01571 double delta0=0;
01572 double delta1=0;
01573 double delta2=0;
01574 double delta3=0;
01575 const double loop_constant = alpha * prev_map_activity[ui][uj];
01576
01577 01578
01579 (void)radius;
01580 (void)weight_idx_bound;
01581
01582 if ((ui > 0) && (ui < N-1))
01583 {
01584 if ((uj >0) && (uj < N-1))
01585 {
01586
01587 delta0 = prev_map_activity[ui-1][uj-1] * loop_constant; weights[ 0 ] += delta0;
01588 delta1 = prev_map_activity[ui-1][uj ] * loop_constant; weights[ 1 ] += delta1;
01589 delta2 = prev_map_activity[ui-1][uj+1] * loop_constant; weights[ 2 ] += delta2;
01590 length = delta0 + delta1 + delta2;
01591
01592 delta3 = prev_map_activity[ui ][uj-1] * loop_constant; weights[ array_width ]+= delta3;
01593 delta0 = prev_map_activity[ui ][uj ] * loop_constant; weights[FULL_LAT_INDEX(array_width,1) ]+= delta0;
01594 delta1 = prev_map_activity[ui ][uj+1] * loop_constant; weights[FULL_LAT_INDEX(array_width,2) ]+= delta1;
01595 length += delta3 + delta0 + delta1;
01596
01597 delta2 = prev_map_activity[ui+1][uj-1] * loop_constant; weights[ array_width_2 ]+= delta2;
01598 delta3 = prev_map_activity[ui+1][uj ] * loop_constant; weights[FULL_LAT_INDEX(array_width_2,1)]+= delta3;
01599 delta0 = prev_map_activity[ui+1][uj+1] * loop_constant; weights[FULL_LAT_INDEX(array_width_2,2)]+= delta0;
01600 length = 1.0/(1.0+length + delta2 + delta3 + delta0);
01601
01602 for(j=0; j<3; j++){
01603 weights[ j ] *= length;
01604 weights[FULL_LAT_INDEX(array_width ,j)] *= length;
01605 weights[FULL_LAT_INDEX(array_width_2,j)] *= length;
01606 }
01607 }
01608 else{
01609 const int lowj = MAX(uj-1,0);
01610 const int highj = MIN(uj+1,N-1);
01611 const int index0 = -uj+1;
01612 const int index1 = array_width -uj+1;
01613 const int index2 = array_width_2 -uj+1;
01614
01615 for(j=lowj; j<=highj; j++){
01616 delta0 = prev_map_activity[ui-1][j] * loop_constant; weights[FULL_LAT_INDEX(index0,j)] += delta0;
01617 delta1 = prev_map_activity[ui ][j] * loop_constant; weights[FULL_LAT_INDEX(index1,j)] += delta1;
01618 delta2 = prev_map_activity[ui+1][j] * loop_constant; weights[FULL_LAT_INDEX(index2,j)] += delta2;
01619 length += delta0 + delta1 + delta2;
01620 }
01621 length = 1.0/(1.0+length);
01622 for(j=lowj; j<=highj; j++){
01623 weights[FULL_LAT_INDEX(index0,j)] *= length;
01624 weights[FULL_LAT_INDEX(index1,j)] *= length;
01625 weights[FULL_LAT_INDEX(index2,j)] *= length;
01626 }
01627 }
01628 }
01629 else if (ui > 0){
01630 const int lowj = MAX(uj-1,0);
01631 const int highj = MIN(uj+1,N-1);
01632 const int index0 = -uj + 1;
01633 const int index1 = array_width - uj + 1;
01634
01635 for(j=lowj; j<=highj; j++){
01636 delta0 = prev_map_activity[ui-1][j] * loop_constant; weights[FULL_LAT_INDEX(index0,j)] += delta0; length += delta0;
01637 delta1 = prev_map_activity[ui ][j] * loop_constant; weights[FULL_LAT_INDEX(index1,j)] += delta1; length += delta1;
01638 }
01639 length = 1.0/(1.0+length);
01640 for(j=lowj; j<=highj; j++){
01641 weights[FULL_LAT_INDEX(index0,j)] *= length;
01642 weights[FULL_LAT_INDEX(index1,j)] *= length;
01643 }
01644 }
01645 else{
01646 const int lowj = MAX(uj-1,0);
01647 const int highj = MIN(uj+1,N-1);
01648 const int index1 = array_width -uj+1;
01649 const int index2 = array_width_2 -uj+1;
01650
01651 for(j=lowj; j<=highj; j++){
01652 delta0 = prev_map_activity[ui ][j] * loop_constant; weights[FULL_LAT_INDEX(index1,j)] += delta0; length += delta0;
01653 delta1+= prev_map_activity[ui+1][j] * loop_constant; weights[FULL_LAT_INDEX(index2,j)] += delta1; length += delta1;
01654 }
01655 length = 1.0/(1.0+length);
01656 for(j=lowj; j<=highj; j++){
01657 weights[FULL_LAT_INDEX(index1,j)] *= length;
01658 weights[FULL_LAT_INDEX(index2,j)] *= length;
01659 }
01660 }
01661 }
01662
01663
01664
01669 void normalize_lat_wts(int i, int j, int radius, int array_width, l_weight *weights)
01670 {
01671 int k,l;
01672 const int lowk = MAX(i-radius,0 );
01673 const int highk = MIN(i+radius,N-1);
01674 const int lowl = MAX(j-radius,0 );
01675 const int highl = MIN(j+radius,N-1);
01676 double length = 0;
01677
01678 for(k=lowk; k<= highk; k++){
01679 int idx = LAT_INDEX(i,j,k,lowl,radius,array_width);
01680 assert (idx >= 0);
01681
01682
01683 for (l=lowl; l <=highl; l++,idx++) {
01684
01685 length += weights[idx];
01686 }
01687 }
01688 length = 1.0/length;
01689
01690 for(k=lowk; k<= highk; k++){
01691 int idx = LAT_INDEX(i,j,k,lowl,radius,array_width);
01692 assert (idx >= 0);
01693
01694
01695 for (l=lowl; l <=highl; l++,idx++){
01696
01697 weights[idx] *= length;
01698 }
01699 }
01700 }
01701
01702
01703
01708 double sigmoid(double activity, double sigdelta, double sigbeta)
01709
01710 {
01711 #ifdef DEBUG_SIGMOID
01712 ipc_notify(IPC_ALL,IPC_VERBOSE,"activity=%.6f; sigdelta=%.6f, sigbeta=%.6f",
01713 (double)activity,(double)sigdelta,(double)sigbeta);
01714 #endif
01715 if (activity < sigdelta) return(0.0);
01716 else if (activity > sigbeta) return(1.0);
01717 else return( (activity-sigdelta)/(sigbeta-sigdelta) );
01718 }
01719
01720
01721
01722
01723
01724
01725
01727 double network_size_megabytes( void )
01728 {
01729 int memsize = (N*N * ( (2*rf_radius +1)*(2*rf_radius +1)*sizeof(a_weight)*num_eyes +
01730 (2*exc_rad +1)*(2*exc_rad +1)*sizeof(l_weight) +
01731 (2*inh_rad +1)*(2*inh_rad +1)*sizeof(l_weight) ))/NPEs;
01732
01733 return memsize/1024.0/1024.0;
01734 }
01735
01736
01738 int network_size_connections( void )
01739 {
01740 return N*N * ( (2*rf_radius +1)*(2*rf_radius +1)*num_eyes +
01741 (2*exc_rad +1)*(2*exc_rad +1) +
01742 (2*inh_rad +1)*(2*inh_rad +1) );
01743 }
01744
01745
01746
01747 cmdstat cmd_init_network( CMD_ARGS )
01748 {
01749 const int skip_weight_init = (argc>0 ? cmdi(argv[0]) : False);
01750 int i,j;
01751
01752
01753 exc_connections_killed = False;
01754 inh_connections_killed = False;
01755 startt=0;
01756 iteration=0;
01757 nrows=N/NPEs;
01758
01759
01760 {
01761 int oldval=cmdparam_changes_verbose;
01762 cmdparam_changes_verbose=False;
01763 params_update_all_default_values();
01764 cmdparam_changes_verbose=oldval;
01765 }
01766
01767
01768 if (params_check_all() != 0) {
01769 if (interactive) {
01770 ipc_notify(IPC_ONE,IPC_WARNING, "init_network failed due to parameter problem; fix message(s) above and try again");
01771 return CMD_PARAMETER_ERROR;
01772 }
01773 else
01774 ipc_exit(IPC_EXIT_PARAM_VALUE_ERROR, "Parameter problem (see message(s) above)");
01775 }
01776
01777 ipc_notify(IPC_ONE,IPC_STD,
01778 "Initializing %d-connection (%dMB%s) network (see %s.init.param for parameters)",
01779 network_size_connections(),(int)network_size_megabytes()+1,
01780 (NPEs>1 ? "/PE" : ""),filebase);
01781
01782
01783 for(i=0; i< N; i++)
01784 for(j=0; j< N; j++)
01785 prev_map_activity[i][j]=map_activity[i][j]=0.0;
01786
01787
01788 rf_radius_sq = (rf_radius+circular_radius_trim)*(rf_radius+circular_radius_trim);
01789 exc_array_width = 2*exc_rad + 1;
01790 exc_array_width_2 = 2*exc_array_width;
01791 lat_exc_dimension = exc_array_width * exc_array_width;
01792 inh_array_width = 2*inh_rad + 1;
01793 lat_inh_dimension = inh_array_width * inh_array_width;
01794 input_dimension = num_eyes*(2*rf_radius+1)*(2*rf_radius+1);
01795 RN_sq = RN*RN;
01796
01797 if (!skip_weight_init)
01798 init_weights();
01799
01800 01801
01802 shuffled_rand_reset(seed);
01803 for(i=0; i < 500+MyPE; i++)
01804 drand48();
01805
01806 #ifndef NO_INPUTS
01807 inputs->init();
01808 #endif
01809
01810
01811 if (AMPARENTPE) {
01812 char buf[MAXFILENAMELENGTH];
01813 sprintf( buf,"%s.init.param",filebase);
01814 cmdparam_save_current_state(buf);
01815 }
01816
01817 cmdparam_changes_verbose = True;
01818
01819
01820 network_initialized = True;
01821 cmddefs_declare_prereq_status( "init_network", CMD_NO_ERROR );
01822
01823
01824 cmddefs_exec_str("testing 0");
01825
01826
01827 #ifndef NO_INPUTS
01828 inputs->reset();
01829 #endif
01830
01831 return CMD_NO_ERROR;
01832 }
01833
01834
01835
01837 cmdstat cmd_uninit_network( CMD_ARGS )
01838 {
01839 (void)argc;
01840 (void)argv;
01841
01842 network_initialized = False;
01843 cmddefs_declare_prereq_status( "init_network", CMD_NEVER_CALLED );
01844 iteration=startt=0;
01845 presentation=0;
01846 nrows=N/NPEs;
01847
01848
01849 hooklists_empty_list(before_input);
01850 hooklists_empty_list(after_presentation);
01851 hooklists_empty_list(after_learning);
01852
01853
01854 if (NROWS*NPES != NMAX)
01855 ipc_notify(IPC_ONE,IPC_WARNING,"Maximum cortex size is NOT square: N(%d) x NROWS*NPES(%d)",
01856 (int)N, (int)(NROWS*NPES));
01857
01858 #ifndef NO_INPUTS
01859 inputs->uninit();
01860 #endif
01861
01862 #ifndef NO_WEIGHTS
01863 {
01864 int i,j;
01865
01866
01867 for (i=0; i<nrows; i++)
01868 for (j=0; j<N; j++){
01869
01870 cortex_map[MAPROW(i)][j].lat_exc_wts = wts[i][j].lat_exc_wts;
01871 cortex_map[MAPROW(i)][j].lat_inh_wts = wts[i][j].lat_inh_wts;
01872 cortex_map[MAPROW(i)][j].weights = wts[i][j].weights ;
01873
01874 #ifdef VERIFY_WEIGHT_SAVES
01875
01876 Orig_map[MAPROW(i)][j].lat_exc_wts = Orig_wts[i][j].lat_exc_wts;
01877 Orig_map[MAPROW(i)][j].lat_inh_wts = Orig_wts[i][j].lat_inh_wts;
01878 Orig_map[MAPROW(i)][j].weights = Orig_wts[i][j].weights ;
01879 #endif
01880 }
01881 }
01882 #endif
01883
01884 return CMD_NO_ERROR;
01885 }
01886
01887
01888
01890 void clear_weights(void)
01891 {
01892 int local_row, j, k, eye, x, y;
01893
01894 for(local_row=0; local_row<nrows; local_row++){
01895 const int map_row = MAPROW(local_row);
01896
01897 for(j=0; j<N; j++) {
01898 cortex_map[map_row][j].centerx = 0;
01899 cortex_map[map_row][j].centery = 0;
01900 for(k=0; k<lat_exc_dimension; k++)
01901 cortex_map[map_row][j].lat_exc_wts[k] = -DEATH_FLAG;
01902 for(k=0; k<lat_inh_dimension; k++)
01903 cortex_map[map_row][j].lat_inh_wts[k] = -DEATH_FLAG;
01904 for(eye=0; eye<num_eyes; eye++)
01905 for(x=0; x<WTMAX; x++)
01906 for(y=0; y<WTMAX; y++)
01907 cortex_map[map_row][j].weights[eye][x][y] = -DEATH_FLAG;
01908 }
01909 }
01910 }
01911
01912
01913
01924 void init_weights(void)
01925 {
01926 int i,j,k,l, eye;
01927 double length=0.0;
01928 int lowk, highk, lowl, highl;
01929
01930 const double preset_sigma_e =
01931 (preset_sigma_exc != Uninitialized ? preset_sigma_exc :
01932 (preset_sigma_lat != Uninitialized ? preset_sigma_lat :
01933 0.9*exc_rad));
01934
01935 const double preset_sigma_i =
01936 (preset_sigma_inh != Uninitialized ? preset_sigma_inh :
01937 (preset_sigma_lat != Uninitialized ? preset_sigma_lat*MIN(1,sqrt(inh_rad)) :
01938 0.9*inh_rad));
01939
01940
01941 clear_weights();
01942
01943 for(i=0; i<nrows; i++){
01944 const int row = MAPROW(i);
01945
01946 shuffled_rand_reset(seed+123456+row);
01947 for(j=0; j<N; j++) {
01948
01949 01950 01951 01952 01953 01954 01955 01956 01957 01958
01959 const double cortical_image_width = RN - 2*retina_edge_buffer;
01960 double row_offset = (N>=cortical_image_width ? 0.9999 : 0.5);
01961
01962 const double cx = retina_edge_buffer + cortical_image_width *
01963 ((row+row_offset)/(double)N + randomness*(2.0*shuffled_rand()-1.0));
01964
01965 const double cy = retina_edge_buffer + cortical_image_width *
01966 (( j+row_offset)/(double)N + randomness*(2.0*shuffled_rand()-1.0));
01967
01968 cortex_map[row][j].centerx = (int)floor(cx);
01969 cortex_map[row][j].centery = (int)floor(cy);
01970
01971 lowk = MAX(cortex_map[row][j].centerx-rf_radius,0 );
01972 highk = MIN(cortex_map[row][j].centerx+rf_radius,RN-1);
01973 lowl = MAX(cortex_map[row][j].centery-rf_radius,0 );
01974 highl = MIN(cortex_map[row][j].centery+rf_radius,RN-1);
01975
01976 01977 01978 01979 01980 01981
01982 length = 0.0;
01983 if (preset_aff_wts){
01984 for (k=lowk; k <=highk; k++)
01985 for (l=lowl; l<=highl; l++){
01986 double value;
01987 double xsq = 0.5+abs(cortex_map[row][j].centerx-k);
01988 double ysq = 0.5+abs(cortex_map[row][j].centery-l);
01989 xsq *= xsq;
01990 ysq *= ysq;
01991 value = exp(-((xsq+ysq)/(preset_sigma_aff * preset_sigma_aff)));
01992 for (eye=0; eye<num_eyes; eye++)
01993 cortex_map[row][j].weights[eye][k-lowk][l-lowl] = value;
01994 length += num_eyes * value;
01995 }
01996 }
01997
01998 else{
01999 for (k=lowk; k <=highk; k++)
02000 for (l=lowl; l<=highl; l++){
02001 double value = shuffled_rand();
02002 for (eye=0; eye<num_eyes; eye++)
02003 cortex_map[row][j].weights[eye][k-lowk][l-lowl] = value;
02004 length += num_eyes * value;
02005 }
02006 }
02007
02008
02009 if (circular_aff_wts)
02010 length = prune_circular_aff_weights(cortex_map[row][j].centerx,cortex_map[row][j].centery,
02011 rf_radius, cortex_map[row][j].weights, length);
02012
02013
02014 length = 1.0/length;
02015 for (k=lowk; k <=highk; k++)
02016 for (l=lowl; l<=highl; l++)
02017 if (!circular_aff_wts || WITHIN_RADIUS(k-cortex_map[row][j].centerx,l-cortex_map[row][j].centery,rf_radius_sq))
02018 for (eye=0; eye<num_eyes; eye++)
02019 cortex_map[row][j].weights[eye][k-lowk][l-lowl] *= length;
02020
02021
02022 setup_lateral_weights(row,j, exc_rad, exc_array_width,cortex_map[row][j].lat_exc_wts,
02023 preset_lat_wts, preset_sigma_e, lat_exc_randomness,
02024 &exc_connections_killed);
02025 setup_lateral_weights(row,j, inh_rad, inh_array_width,cortex_map[row][j].lat_inh_wts,
02026 preset_lat_wts, preset_sigma_i, lat_inh_randomness,
02027 &inh_connections_killed);
02028 }
02029 }
02030 }
02031
02032
02033
02035 void setup_latw(void)
02036 {
02037 int i,j;
02038
02039 if (preset_sigma_exc==Uninitialized || preset_sigma_inh==Uninitialized) {
02040 ipc_notify(IPC_ONE,IPC_ERROR,
02041 "Must set preset_sigma_exc and preset_sigma_inh to use setup_latw()");
02042 return;
02043 }
02044
02045 for(i=0; i<nrows; i++) {
02046 const int row = MAPROW(i);
02047 for(j=0; j<N; j++) {
02048 setup_lateral_weights(row,j, exc_rad, exc_array_width,cortex_map[row][j].lat_exc_wts,
02049 preset_lat_wts, preset_sigma_exc, lat_exc_randomness,
02050 &exc_connections_killed);
02051 setup_lateral_weights(row,j, inh_rad, inh_array_width,cortex_map[row][j].lat_inh_wts,
02052 preset_lat_wts, preset_sigma_inh, lat_inh_randomness,
02053 &inh_connections_killed);
02054 }
02055 }
02056 }
02057
02058
02059
02068 void setup_lateral_weights(int ui, int uj, int radius,
02069 int array_width, l_weight *weights,
02070 int preset, double sigma, double amt_of_randomness,
02071 int* con_killed_flag)
02072 {
02073 int k,l;
02074
02075 const int lowk = MAX(ui-radius,0);
02076 const int highk = MIN(ui+radius,N);
02077 const int lowl = MAX(uj-radius,0);
02078 const int highl = MIN(uj+radius,N);
02079
02080 const int max_num_connections = (highk-lowk+1)*(highl-lowl+1);
02081 const double mean_wt = 1.0/max_num_connections;
02082
02083 if (preset)
02084 for(k=lowk; k<=highk; k++)
02085 for(l=lowl; l<=highl; l++){
02086 double xsq = (double)(k-ui);
02087 double ysq = (double)(l-uj);
02088 xsq *= xsq;
02089 ysq *= ysq;
02090 weights[LAT_INDEX(ui,uj,k,l,radius,array_width)] =
02091 mean_wt * exp( -((xsq+ysq)/(sigma*sigma)));
02092 }
02093 else
02094 for(k=lowk; k<=highk; k++)
02095 for(l=lowl; l<=highl; l++)
02096 weights[LAT_INDEX(ui,uj,k,l,radius,array_width)] =
02097 dist_lat_wt(mean_wt,amt_of_randomness);
02098
02099 if (circular_lat_wts) {
02100 prune_circular_lat_weights(ui,uj,radius, array_width, weights);
02101 *con_killed_flag=True;
02102 }
02103
02104 normalize_lat_wts(ui,uj,radius,array_width,weights);
02105 }
02106
02107
02108
02110 void prune_circular_lat_weights(int ui, int uj, int radius,
02111 int array_width, l_weight *weights)
02112 {
02113 const double radius_float = radius+circular_radius_trim;
02114 const double radius_sq = radius_float*radius_float;
02115 const double smooth_start = radius+smooth_circular_radius_trim;
02116 const double smooth_start_sq = smooth_start*smooth_start;
02117 const double smooth_rad = (radius_float-smooth_start)/2;
02118 const double smooth_rad_sq = smooth_rad*smooth_rad;
02119
02120 const int lowk = MAX(ui-radius,0);
02121 const int highk = MIN(ui+radius,N);
02122 const int lowl = MAX(uj-radius,0);
02123 const int highl = MIN(uj+radius,N);
02124
02125 int k,l;
02126
02127 for (k=lowk; k <=highk; k++)
02128 for (l=lowl; l<=highl; l++) {
02129 const double xdist = k-ui;
02130 const double ydist = l-uj;
02131 const double xdist_sq = xdist*xdist;
02132 const double ydist_sq = ydist*ydist;
02133 const double rdist_sq = xdist_sq+ydist_sq;
02134
02135 if (radius>1 && !WITHIN_RADIUS_SQ(xdist_sq,ydist_sq,radius_sq))
02136 weights[LAT_INDEX(ui,uj,k,l,radius,array_width)] = -DEATH_FLAG;
02137
02138 else if (smooth_circular_outlines && (rdist_sq >= smooth_start_sq)) {
02139 double dist_sq = sqrt(rdist_sq)-smooth_start;
02140 dist_sq*=dist_sq;
02141
02142 weights[LAT_INDEX(ui,uj,k,l,radius,array_width)] =
02143 weights[LAT_INDEX(ui,uj,k,l,radius,array_width)] *
02144 exp( -(dist_sq/smooth_rad_sq) );
02145 }
02146 }
02147 }
02148
02149
02150
02152 double prune_circular_aff_weights(int ui, int uj, int radius,
02153 a_weight weights[MAX_NUM_EYES][WTMAX][WTMAX],
02154 double length)
02155 {
02156 const double radius_float = radius+circular_radius_trim;
02157 const double radius_sq = radius_float*radius_float;
02158 const double smooth_start = radius+smooth_circular_radius_trim;
02159 const double smooth_start_sq = smooth_start*smooth_start;
02160 const double smooth_rad = (radius_float-smooth_start)/2;
02161 const double smooth_rad_sq = smooth_rad*smooth_rad;
02162
02163 const int lowk = MAX(ui-radius,0);
02164 const int highk = MIN(ui+radius,RN);
02165 const int lowl = MAX(uj-radius,0);
02166 const int highl = MIN(uj+radius,RN);
02167
02168 int k,l;
02169
02170 for (k=lowk; k <=highk; k++)
02171 for (l=lowl; l<=highl; l++) {
02172 const double xdist = k-ui;
02173 const double ydist = l-uj;
02174 const double xdist_sq = xdist*xdist;
02175 const double ydist_sq = ydist*ydist;
02176 const double rdist_sq = xdist_sq+ydist_sq;
02177
02178 int eye;
02179
02180 if (radius>1 && !WITHIN_RADIUS_SQ(xdist_sq,ydist_sq,radius_sq))
02181 for (eye=0; eye<num_eyes; eye++) {
02182
02183 length -= weights[eye][k-lowk][l-lowl];
02184 weights[eye][k-lowk][l-lowl] = -DEATH_FLAG;
02185 }
02186
02187 else if (smooth_circular_outlines && (rdist_sq >= smooth_start_sq)) {
02188 for (eye=0; eye<num_eyes; eye++) {
02189 double dist_sq = sqrt(rdist_sq)-smooth_start;
02190 a_weight init_weight = weights[eye][k-lowk][l-lowl];
02191 dist_sq*=dist_sq;
02192
02193 weights[eye][k-lowk][l-lowl] =
02194 init_weight * exp( -(dist_sq/smooth_rad_sq) );
02195 length += weights[eye][k-lowk][l-lowl]-init_weight;
02196 }
02197 }
02198 }
02199
02200 return length;
02201 }
02202
02203
02204
02209 double dist_lat_wt(double value, double amt_of_randomness)
02210
02211 {
02212 double low, add;
02213
02214 low = value * (1.0 - amt_of_randomness) ;
02215 add = 2*value*amt_of_randomness*drand48();
02216
02217 return(low+add);
02218 }
02219
02220
02221
02227 cmdstat cmd_kill_connections( CMD_ARGS )
02228 {
02229 int i,j,k;
02230 int living_inh_connections = 0;
02231 int dead_inh_connections = 0;
02232 int killed_inh_connections = 0;
02233
02234
02235 double i_death = (argc>0 ? cmdf(argv[0]) : inh_death);
02236 double e_death = (argc>1 ? cmdf(argv[1]) : exc_death);
02237
02238 if (e_death > 0) exc_connections_killed = True;
02239 if (i_death > 0) inh_connections_killed = True;
02240
02241 for (i=0; i<nrows; i++){
02242 const int row = MAPROW(i);
02243 for(j=0;j<N; j++)
02244 {
02245 for(k=0; k<lat_exc_dimension; k++)
02246 if (cortex_map[row][j].lat_exc_wts[k] < e_death)
02247 cortex_map[row][j].lat_exc_wts[k] = -DEATH_FLAG;
02248
02249 for(k=0; k<lat_inh_dimension; k++)
02250 if (cortex_map[row][j].lat_inh_wts[k] < i_death) {
02251 dead_inh_connections++;
02252
02253 if (cortex_map[row][j].lat_inh_wts[k] > 0) killed_inh_connections++;
02254
02255 cortex_map[row][j].lat_inh_wts[k] = -DEATH_FLAG;
02256 }
02257 else living_inh_connections++;
02258 }
02259 }
02260 ipc_pe_msg_delay(1.0);
02261 int total_inh_connections = living_inh_connections + dead_inh_connections;
02262 ipc_notify(IPC_ALL,IPC_STD,"Killed %g%% (%d/%d) of the inhibitory connections, leaving %d",
02263 (double)(100*((float)killed_inh_connections)/total_inh_connections),
02264 killed_inh_connections, total_inh_connections, living_inh_connections);
02265
02266 return CMD_NO_ERROR;
02267 }
02268
02269
02270
02272 int change_lateral_exc_radius(int old_radius, int new_radius)
02273 {
02274 int i,j;
02275
02276
02277 if (new_radius > old_radius) {
02278 ipc_notify(IPC_ONE,IPC_ERROR,"Increasing excitatory radius is not supported");
02279 new_radius=old_radius;
02280 }
02281
02282 else if (new_radius < old_radius)
02283 for (i=0; i<nrows; i++) {
02284 const int row = MAPROW(i);
02285 for (j=0; j<N; j++)
02286 reduce_lateral_radius(row,j,old_radius,new_radius,exc_array_width,cortex_map[row][j].lat_exc_wts);
02287 }
02288
02289 return new_radius;
02290 }
02291
02292
02302 void reduce_lateral_radius(int ui, int uj, int old_radius, int new_radius, int array_width, l_weight *weights)
02303 {
02304 int k,l;
02305 const int lowk = MAX(ui-new_radius,0 );
02306 const int highk = MIN(ui+new_radius,N-1);
02307 const int lowl = MAX(uj-new_radius,0 );
02308 const int highl = MIN(uj+new_radius,N-1);
02309
02310 for(k=lowk; k<= highk; k++){
02311 const int partial_index_new = PARTIAL_LAT_INDEX(ui,uj,k,new_radius,array_width);
02312 const int partial_index_old = PARTIAL_LAT_INDEX(ui,uj,k,old_radius,array_width);
02313
02314 for(l=lowl; l<=highl; l++)
02315 weights[FULL_LAT_INDEX(partial_index_new,l)] =
02316 weights[FULL_LAT_INDEX(partial_index_old,l)];
02317 }
02318
02319 if (circular_lat_wts)
02320 prune_circular_lat_weights(ui,uj,new_radius, array_width, weights);
02321
02322
02323 normalize_lat_wts(ui,uj,new_radius,array_width,weights);
02324 }
02325
02326
02327
02336 void collect_activation_data(int dest_pe)
02337 {
02338 int i,pe;
02339 ipc_barrier();
02340
02341
02342
02343 if (dest_pe==Uninitialized)
02344 for(pe=0; pe<NPEs; pe++) {
02345 if (!PEISME(pe))
02346 for(i=0; i<nrows; i++) {
02347 ipc_put(init_activity[MAPROW(i)], IPC_DOUBLE, N, pe);
02348 02349
02350 }
02351 }
02352
02353 else if (!PEISME(dest_pe))
02354 for(i=0; i<nrows; i++)
02355 ipc_put(init_activity[MAPROW(i)], IPC_DOUBLE, N, dest_pe);
02356
02357 ipc_barrier();
02358 }
02359
02360
02361
02367 int save_current(const char *filename)
02368 {
02369 #ifdef NO_IO
02370 (void)filename;
02371 #else
02372
02373 FILE *fp=NULL;
02374 char buf[50];
02375
02376 #ifdef VERIFY_WEIGHT_SAVES
02377 {
02378 int row, i, j, k;
02379 for(i=0; i<nrows; i++){
02380 row = MAPROW(i);
02381 for(j=0; j<N; j++) {
02382
02383
02384 Orig_map[row][j].centerx = cortex_map[row][j].centerx;
02385 Orig_map[row][j].centery = cortex_map[row][j].centery;
02386 for(k=0; k<lat_exc_dimension; k++)
02387 Orig_map[row][j].lat_exc_wts[k] = cortex_map[row][j].lat_exc_wts[k];
02388 for(k=0; k<lat_inh_dimension; k++)
02389 Orig_map[row][j].lat_inh_wts[k] = cortex_map[row][j].lat_inh_wts[k];
02390 for(k=0; k<input_dimension; k++)
02391 Orig_map[row][j].weights[0][0][k] = cortex_map[row][j].weights[0][0][k];
02392 }
02393 }
02394 }
02395 verify_saved_weights(0.0);
02396 #endif
02397
02398
02399 if (AMYOUNGESTPE) {
02400 if (!filename) {
02401
02402 sprintf( buf, "%s.%06d.wts", filebase, iteration );
02403 filename=buf;
02404 }
02405
02406 if ((fp=fopen(filename, "w+"))==NULL){
02407 ipc_abort(IPC_EXIT_FILE_PROBLEM,"Weights file %s couldn't be opened for saving", buf);
02408 }
02409
02410 ipc_notify(IPC_ALL,IPC_STD,"Saving weights to file %s",filename);
02411 }
02412
02413
02414 #ifdef BINARY_WEIGHTS_FILE
02415
02416
02417 binaryWeightsFileWrite(fp);
02418
02419 #else
02420
02421
02422 if (AMYOUNGESTPE && fp!=NULL){
02423 if (fprintf(fp,"%d %d\n", t, N)==EOF)
02424 ipc_notify(IPC_ALL,IPC_ERROR,"Error appending to file");
02425 weights_IO(WRITE,fp);
02426 }
02427
02428 #endif
02429
02430 if (fp!=NULL)
02431 fclose(fp);
02432
02433
02434 #ifdef RELOAD_AFTER_WEIGHT_SAVE
02435 ipc_barrier();
02436 clear_weights();
02437 if ( load_current(t,NULL) != CMD_NO_ERROR && !interactive)
02438 ipc_exit(IPC_EXIT_FILE_PROBLEM,"Problem with weights file");
02439 #endif
02440
02441 #endif
02442
02443 return(1);
02444 }
02445
02446
02447
02453 int load_current(int load_snap, const char *filename)
02454
02455 {
02456 int status=CMD_NO_ERROR;
02457 #ifdef NO_IO
02458 (void)load_snap;
02459 (void)filename;
02460 #else
02461 char buf[50];
02462 FILE *fp=NULL;
02463
02464 if (AMPARENTPE){
02465 if (!filename) {
02466
02467 sprintf(buf, "%s.%06d.wts", filebase, load_snap);
02468 filename=buf;
02469 }
02470
02471 if ((fp=fopen(filename, "r" ))==NULL) {
02472
02473 if (!interactive || NPEs>1)
02474 ipc_abort(IPC_EXIT_FILE_PROBLEM,"Wt file %s couldn't be opened", buf);
02475 else {
02476 ipc_notify(IPC_ONE,IPC_ERROR,"Wt file %s couldn't be opened", buf);
02477 return CMD_FILE_ERROR;
02478 }
02479 }
02480 }
02481
02482
02483 if (!network_initialized) {
02484 int global_essential_training_hooks_only=essential_training_hooks_only;
02485 essential_training_hooks_only=True;
02486 cmddefs_exec_str("init_network True");
02487 essential_training_hooks_only=global_essential_training_hooks_only;
02488 }
02489
02490 if (AMPARENTPE)
02491 ipc_notify(IPC_ALL,IPC_STD,"Advancing to iteration %d", load_snap);
02492
02493
02494
02495 advance_iteration_counter(iteration,load_snap);
02496
02497 02498 02499
02500 clear_weights();
02501
02502
02503 #ifdef BINARY_WEIGHTS_FILE
02504 if(binaryWeightsFileRead(fp))
02505 status=CMD_FILE_ERROR;
02506 #else
02507
02508
02509 if (AMPARENTPE) {
02510 int anint,junk;
02511
02512 fscanf(fp,"%d %d",&anint, &junk) ;
02513 t = anint;
02514 if (t != load_snap) {
02515 ipc_notify(IPC_ALL,IPC_ERROR,"Wt file %s doesn't have proper t", buf);
02516 status=CMD_FILE_ERROR;
02517 }
02518 }
02519 weights_IO(READ,fp);
02520
02521 #endif
02522
02523 if (AMPARENTPE) fclose(fp);
02524
02525 02526 02527 02528 02529 02530
02531 exc_connections_killed=True;
02532 inh_connections_killed=True;
02533
02534
02535
02536 #ifdef VERIFY_WEIGHT_SAVES
02537 verify_saved_weights(0.0000001);
02538 #endif
02539
02540 hooklists_run_list(before_input,load_snap,True);
02541 #ifndef NO_INPUTS
02542 inputs->next();
02543 inputs->activate();
02544 #endif
02545 ipc_barrier();
02546
02547 if (!AMPARENTPE) ipc_get(&iteration, IPC_INT, 1, PARENTPE);
02548 iteration++;
02549
02550 ipc_notify(IPC_ONE,IPC_STD,"Changing iteration to %d",iteration);
02551 startt=iteration;
02552
02553 if (iteration > tend) {
02554
02555 const int new_tend = (int)(tend*1.5);
02556 ipc_notify(IPC_ONE,IPC_STD,"Changing tend from %d to %d to allow use of network",tend,new_tend);
02557 tend = new_tend;
02558 }
02559
02560 present_inputs(False);
02561 hooklists_run_list(after_learning,iteration,True);
02562 #endif
02563
02564 return status;
02565 }
02566
02567
02568
02569 #ifdef VERIFY_WEIGHT_SAVES
02570 void verify_saved_weights( double tolerance )
02571 {
02572 int row, i, j, eye, x, y;
02573 int aff_errors_found=0;
02574
02575 for(i=0; i<nrows; i++){
02576 row = MAPROW(i);
02577 for(j=0; j<N; j++) {
02578
02579 if (Orig_map[row][j].centerx - cortex_map[row][j].centerx > tolerance)
02580 ipc_notify(IPC_ALL,IPC_ERROR,"row:%d j:%d -- Centerx changed: %d -> %d",
02581 row,j,(int)Orig_map[row][j].centerx,(int)cortex_map[row][j].centerx);
02582 if (Orig_map[row][j].centery - cortex_map[row][j].centery > tolerance)
02583 ipc_notify(IPC_ALL,IPC_ERROR,"row:%d j:%d -- Centery changed: %d -> %d",
02584 row,j,(int)Orig_map[row][j].centery,(int)cortex_map[row][j].centery);
02585
02586 for(eye=0; eye<num_eyes; eye++)
02587 for(x=0; x<WTMAX; x++)
02588 for(y=0; y<WTMAX; y++)
02589 if (Orig_map[row][j].weights[eye][x][y] - cortex_map[row][j].weights[eye][x][y] >tolerance) {
02590 if (++aff_errors_found < VERIFY_WEIGHT_SAVES_ERROR_LIMIT)
02591 ipc_notify(IPC_ALL,IPC_ERROR,"row:%d j:%d eye:%d x:%d y:%d -- Afferent weights differ: %e -> %e",
02592 row,j,eye,x,y,
02593 (double)Orig_map[row][j].weights[eye][x][y],
02594 (double)cortex_map[row][j].weights[eye][x][y]);
02595 else if (aff_errors_found == VERIFY_WEIGHT_SAVES_ERROR_LIMIT)
02596 ipc_notify(IPC_ALL,IPC_ERROR,"Reached limit for VERIFY_WEIGHT_SAVES error reporting; rest will be discarded");
02597 }
02598
02599 verify_saved_lateral_weights(row,j, exc_rad, exc_array_width,
02600 Orig_map[row][j].lat_exc_wts,
02601 cortex_map[row][j].lat_exc_wts,
02602 tolerance,"lat_exc_wts");
02603
02604 verify_saved_lateral_weights(row,j, inh_rad, inh_array_width,
02605 Orig_map[row][j].lat_inh_wts,
02606 cortex_map[row][j].lat_inh_wts,
02607 tolerance,"lat_inh_wts");
02608
02609 }
02610 }
02611 }
02612 #endif
02613
02614
02615
02616 #ifdef VERIFY_WEIGHT_SAVES
02617 void verify_saved_lateral_weights( int i, int j, int radius, int array_width,
02618 l_weight *old_weights, l_weight *new_weights,
02619 double tolerance, const char *description)
02620 {
02621 const int lowk = MAX(i-radius,0 );
02622 const int highk = MIN(i+radius,N-1);
02623 const int lowl = MAX(j-radius,0 );
02624 const int highl = MIN(j+radius,N-1);
02625
02626 static int errors_found=0;
02627 int k,l;
02628
02629 for(k=lowk; k<= highk; k++) {
02630 const int partial_idx = PARTIAL_LAT_INDEX(i,j,k,radius,array_width);
02631 for (l=lowl; l<=highl; l++) {
02632 const int idx = FULL_LAT_INDEX(partial_idx,l);
02633
02634 if (old_weights[idx] - new_weights[idx] > tolerance) {
02635 if (++errors_found < VERIFY_WEIGHT_SAVES_ERROR_LIMIT)
02636 ipc_notify(IPC_ALL,IPC_ERROR,"i:%d j:%d k:%d l:%d -- %s differ: %e -> %e",
02637 i,j,k,l,description,
02638 (double)old_weights[idx],
02639 (double)new_weights[idx]);
02640 else if (errors_found == VERIFY_WEIGHT_SAVES_ERROR_LIMIT)
02641 ipc_notify(IPC_ALL,IPC_ERROR,"Reached limit for VERIFY_WEIGHT_SAVES error reporting; rest will be discarded");
02642 }
02643
02644 }
02645 }
02646 }
02647 #endif