00001
00012 #include <string.h>
00013 #include <math.h>
00014
00015 #include "ipc.h"
00016 #include "cmdparam.h"
00017 #include "lissom.h"
00018 #include "globals.h"
00019 #include "kernel.h"
00020
00021
00022
00023 int circular_aff_wts=True;
00024 int circular_lat_wts=True;
00025 double circular_radius_trim=0.5;
00026 double uncorrelation=0.0;
00027 int exc_rad=MAX_EXC_RADIUS;
00028 char filebase[MAXFILENAMELENGTH]="lissom";
00029 double gammaexc=1.0;
00030 double gammainh=1.0;
00031 int inh_rad=MAX_INH_RADIUS;
00032 int interactive=False;
00033 int iteration=0;
00034 int learning=True;
00035 int N=NMAX;
00036 int normalize_aff=False;
00037 #ifndef NUM_EYES_IS_CONSTANT
00038 int num_eyes=MAX_NUM_EYES;
00039 #endif
00040 int or_num_angles=MAX_NUM_ANGLES;
00041 int presentation=0;
00042 int preset_lat_wts=True;
00043 int progress_reports=Uninitialized;
00044 int progress_report_interval=10;
00045 int retina_edge_buffer=0;
00046 int rf_radius=MAX_RF_RADIUS;
00047 int RN=RNMAX-MAX_RF_RADIUS*2;
00048 int startt=0;
00049 int spawn_viewer=Uninitialized;
00050 int running_remotely=False;
00051 int tsettle=10;
00052
00053 #ifdef CRAY
00054 #pragma _CRI cache_align RN
00055 #endif
00056
00057
00058 int exc_array_width;
00059 int exc_array_width_2;
00060 int inh_array_width;
00061 double init_activity[NMAX][NMAX];
00062 int input_dimension;
00063 double input_vectors[RNMAX*RNMAX*MAX_NUM_EYES];
00064 int lat_exc_dimension;
00065 int lat_inh_dimension;
00066 Neuron cortex_map[NMAX][NMAX];
00067 int MyPE=0;
00068 int network_initialized=False;
00069 int NPEs=1;
00070 int nrows;
00071 double prev_map_activity[NMAX][NMAX];
00072 double rf_radius_sq;
00074 HooklistNum before_input;
00075 HooklistNum after_presentation;
00076 HooklistNum after_learning;
00079
00080
00081
00082
00083 SETFN_DECLARE(exc_rad_setfn);
00084
00085
00086
00087
00088
00089
00090 void globals_init_hook( void )
00091 {
00092
00093 before_input = hooklists_define_list("before_input", "iteration");
00094 after_presentation = hooklists_define_list("after_presentation", "iteration");
00095 after_learning = hooklists_define_list("after_learning", "iteration");
00096
00097
00098 MyPE = ipc_my_process();
00099 NPEs = ipc_num_processes();
00100
00101
00102
00103
00104 PARAM_I(PARAM_BOOL, circular_aff_wts,False,True,
00105 "If this is true, all afferent weights outside a circular radius\n"
00106 "rf_radius will be killed before training begins. Otherwise a \n"
00107 "square radius is used.");
00108 SETFN_DEFINE(circular_aff_wts,fixed_arch_param_setfn);
00109
00110 PARAM_I(PARAM_BOOL, circular_lat_wts,False,True,
00111 "If this is true, all lateral weights outside a circular radius\n"
00112 "exc_rad or inh_rad (for the excitatory and inhibitory weights,\n"
00113 "respectively) will be killed before training begins. Otherwise\n"
00114 "a square radius is used.");
00115 SETFN_DEFINE(circular_lat_wts,fixed_arch_param_setfn);
00116
00117 PARAM_I(PARAM_DOUBLE,circular_radius_trim,0,1,
00118 "When circular weight radii are in use, this quantity is added to an integer\n"
00119 "radius (rf_radius, inh_rad, or exc_rad) to create a floating-point radius.\n"
00120 "Because they were originally thought of as square radii, the weight radii\n"
00121 "are specified as integers starting one unit away from a center unit.\n"
00122 "However, when circular receptive fields are used, the non-zero width of\n"
00123 "each unit makes it important to decide exactly where the real-valued\n"
00124 "rf_radius lies. This is because the distance between units differs\n"
00125 "slightly in every direction, and thus a precise boundary needs to be\n"
00126 "defined in order to decide which units are within the radius.\n\n"
00127
00128 "One valid interpretation is that the real-valued radius is the\n"
00129 "distance between the center of the central unit and the far edge of the\n"
00130 "unit `radius' units away (set circular_radius_trim=0.5). This accounts\n"
00131 "for the non-zero width of the central unit, and also produces fairly smooth\n"
00132 "outlines.\n\n"
00133
00134 "Another valid interpretation is that the real-valued radius is the distance\n"
00135 "between the center of the central unit and the center of the unit `radius'\n"
00136 "units away (set circular_radius_trim=0.0). However, for small radii this\n"
00137 "setting produces a fairly jagged outline, with peaks at the ends of the\n"
00138 "vertical and horizontal axes due to the rectangular coordinate system.\n\n"
00139
00140 "Older simulations used an implicit setting of 1.0, which caused clipping\n"
00141 "against the integer boundaries determined by the radius; this cannot be a\n"
00142 "good idea. To avoid this use a value under 1.0. One will generally want\n"
00143 "to choose a value in the range 0.0-0.5 that makes the most circular-looking\n"
00144 "outline for the smallest radius in use (particularly important for radii\n"
00145 "smaller than 6.0 or so).");
00146
00147 PARAM_I(PARAM_INT, exc_rad,0,MAX_EXC_RADIUS,
00148 "Connection radius for lateral excitatory weights.");
00149 SETFN_DEFINE(exc_rad,exc_rad_setfn);
00150
00151 PARAM_I(PARAM_STRING,filebase,1,MAXFILENAMELENGTH,
00152 "Basename to use for files to be created during this run.");
00153
00154 PARAM_N(PARAM_DOUBLE,gammaexc,
00155 "Scaling factor for excitatory lateral interactions.");
00156
00157 PARAM_N(PARAM_DOUBLE,gammainh,
00158 "Scaling factor for inhibitory lateral interactions.");
00159
00160 PARAM_I(PARAM_INT, inh_rad,0,MAX_INH_RADIUS,
00161 "Connection radius for lateral inhibitory weights.");
00162 SETFN_DEFINE(inh_rad,fixed_arch_param_setfn);
00163
00164 PARAM_I(PARAM_BOOL, interactive,False,True,
00165 "Whether this run is considered an interactive or a batch run;\n"
00166 "affects certain behaviors such as how often progress messages\n"
00167 "are printed, what level of severity is required to exit the\n"
00168 "program, etc. Should not usually need to be changed by the\n"
00169 "user.");
00170
00171 PARAM_I(PARAM_BOOL, learning,False,True,
00172 "Whether learning (as controlled by the various alpha_ parameters\n"
00173 "is enabled.");
00174
00175 PARAM_I(PARAM_INT, N,0,NMAX,
00176 "The (square) size of the cortical map, i.e. NxN.");
00177 SETFN_DEFINE(N,fixed_arch_param_setfn);
00178
00179 PARAM_I(PARAM_BOOL, normalize_aff,False,True,
00180 "Whether or not to normalize afferent inputs.");
00181
00182
00183
00184 CONST_I(NPEs,NPES,True,
00185 "The number of processing elements (PEs) assigned to this job. This is\n"
00186 "determined by the compile-time constant NPES. With more PEs, more\n"
00187 "memory and processing power are available, but because the LISSOM\n"
00188 "algorithm requires an enormous amount of interprocessor communication,\n"
00189 "the speedup is not linear in the number of processors. In fact, with\n"
00190 "most ordinary communications methods such as Ethernet, going from\n"
00191 "NPEs=1 to NPEs=2 could actually slow down the computation. Still,\n"
00192 "for large problems there is usually no other way to get all the memory\n"
00193 "and processing power needed.\n\n"
00194
00195 "Note that when NPEs changes, the result changes as if a different random\n"
00196 "seed was chosen. This occurs because each processor computes random numbers\n"
00197 "independently, and so a different sequence of random numbers is chosen than\n"
00198 "if a single processor had computed them all. This could be alleviated by\n"
00199 "having a single processor compute all random numbers, but that (and the\n"
00200 "communication it would involve) would probably slow things down considerably.");
00201
00202 #ifdef NUM_EYES_IS_CONSTANT
00203 CONST_I(num_eyes,num_eyes,True,
00204 "The number of eyes used is controlled by MAX_NUM_EYES and num_eyes,\n"
00205 "which are both currently compilation constants equal to each other\n"
00206 "because that allows much better compiler optimizations. If flexibility\n"
00207 "is more important than speed, undefine NUM_EYES_IS_CONSTANT to make this\n"
00208 "parameter writable, and define MAX_NUM_EYES to be greater than one.\n\n"
00209
00210 "At the moment, num_eyes==2 has received the most testing. num_eyes==1 has\n"
00211 "had basic testing, but not as much; num_eyes>2 has just been checked out\n"
00212 "cursorily but may be interesting to look at. (See e.g. Reh & Constantine-\n"
00213 "Paton, J. Neurosci 5:5 1985, \"... Three-Eyed Rana pipiens\".)");
00214 #else
00215 PARAM_I(PARAM_INT, num_eyes,1,MAX_NUM_EYES,
00216 "The number of retinal surfaces (eyes) to attach to the network.\n\n"
00217
00218 "At the moment, num_eyes==2 has received the most testing. num_eyes==1 has\n"
00219 "had basic testing, but not as much; num_eyes>2 has just been checked out\n"
00220 "cursorily but may be interesting to look at. (See e.g. Reh & Constantine-\n"
00221 "Paton, J. Neurosci 5:5 1985, \"... Three-Eyed Rana pipiens\".)");
00222 SETFN_DEFINE(num_eyes,fixed_arch_param_setfn);
00223 #endif
00224
00225 PARAM_I(PARAM_INT, or_num_angles,0,MAX_NUM_ANGLES,
00226 "The number of angles to use during testing of the response of the network\n"
00227 "to various patterns, e.g. for measure_or_pref. The angles are chosen at\n"
00228 "regular intervals in the range [0,180] degrees.");
00229
00230 PARAM_L(PARAM_INT, presentation,0,
00231 "Counter for inputs presented at a single training iteration t. It will\n"
00232 "usually remain at zero, but if extra inputs are presented for testing or\n"
00233 "other purposes, this counter will advance each time. The concatenation\n"
00234 "of t with this counter will then be sufficient to label that input\n"
00235 "presentation uniquely, e.g. for the purposes of creating a unique filename.");
00236
00237 PARAM_I(PARAM_BOOL, preset_lat_wts,False,True,
00238 "Whether or not to preset the lateral weights.");
00239 SETFN_DEFINE(preset_lat_wts,fixed_arch_param_setfn);
00240
00241 PARAM_I(PARAM_BOOL, progress_reports,False,True,
00242 "Whether or not to print messages during very long computations; defaults to\n"
00243 "True for interactive sessions and False otherwise.");
00244 params_define_default_expr("progress_reports","interactive");
00245
00246 PARAM_L(PARAM_INT, progress_report_interval,0,
00247 "The minimum number of seconds between messages printed during very long\n"
00248 "computations, such as training. Only used if progress_reports is True.");
00249
00250 PARAM_I(PARAM_INT, retina_edge_buffer,0,RNMAX/2,
00251 "Number of retinal units to leave on all sides when determining the center\n"
00252 "of the afferent receptive field of each neuron. If it is zero, then the\n"
00253 "entire cortex is scaled to the entire retina, but then the neurons near\n"
00254 "the border will have only partial receptive fields. An effectively\n"
00255 "infinite retina, where each neuron will have a complete receptive field,\n"
00256 "can be obtained by setting this parameter to rf_radius+randomness*RN/2.\n"
00257 "This maps the cortex to a smaller square region (width and length\n"
00258 "RN-2*retina_edge_buffer) in the center of the retina. If you wish to\n"
00259 "keep the same cortical magnification factor as if there were no buffer,\n"
00260 "also increase RN by 2*retina_edge_buffer.");
00261 SETFN_DEFINE(retina_edge_buffer,fixed_arch_param_setfn);
00262
00263 PARAM_I(PARAM_INT, rf_radius,0,MAX_RF_RADIUS,
00264 "Square radius (centered about the neuron) of the receptive field. Must not\n"
00265 "be larger than RN/2.");
00266 SETFN_DEFINE(rf_radius,fixed_arch_param_setfn);
00267
00268 PARAM_I(PARAM_INT, RN,0,RNMAX,
00269 "The size of the (square) input retina matrix, i.e. RNxRN.");
00270 SETFN_DEFINE(RN,fixed_arch_param_setfn);
00271
00272 PARAM_I(PARAM_BOOL, running_remotely,False,True,
00273 "Allows the user to declare that the program is being run in a remote shell,\n"
00274 "which affects default values for whether image viewers are spawned, etc.");
00275
00276 PARAM_I(PARAM_BOOL, spawn_viewer,Uninitialized,True,
00277 "Whether to spawn external programs to view images when they are\n"
00278 "created.");
00279
00280 PARAM_I(PARAM_INT, startt,0,MAXITERATION,
00281 "Starting iteration to be used the next time training or testing begins.\n"
00282 "This should not ordinarily be changed, but it can be used for debugging.");
00283
00284 PARAM_I(PARAM_INT, iteration,0,MAXITERATION,
00285 "The current training iteration. Iteration 0 is used for init_network to\n"
00286 "make sure everything is initialized properly, without doing any learning.");
00287
00288 params_define_param("t",PARAM_INT,False,(char*)&iteration);
00289 params_add_lower_bound_int("t",0);
00290 params_add_upper_bound_int("t",MAXITERATION);
00291 params_define_doc("t","Alias for the `iteration' parameter.");
00292
00293 PARAM_L(PARAM_INT, tsettle,1,
00294 "Iterations for activity to settle at each input presentation. The total\n"
00295 "duration of these is only the equivalent of a few seconds in real time,\n"
00296 "as opposed to the LISSOM training iterations, which total to the equivalent\n"
00297 "of days or weeks.");
00298
00299 PARAM_I(PARAM_DOUBLE,uncorrelation,0,1,
00300 "Amount of uncorrelation between the input to different eyes. A value of\n"
00301 "0.0 means that the inputs are entirely correlated, i.e. identical, while\n"
00302 "1.0 means that they are entirely uncorrelated.");
00303
00304 {
00305 static int i;
00306 static double f;
00307
00308 PARAM_N(PARAM_INT,i,
00309 "Integer register predefined for convenience; suitable for use as\n"
00310 "e.g. a loop index. Since many different user routines can use\n"
00311 "this parameter, don't expect its value to remain unchanged.");
00312
00313 PARAM_N(PARAM_DOUBLE,f,
00314 "Floating-point register predefined for convenience; suitable for use\n"
00315 "as a temporary value e.g. in a loop. Since many different user routines\n"
00316 "can use this parameter, don't expect its value to remain unchanged.");
00317 }
00318 }
00319
00320
00321
00322
00323
00324
00325
00330 void advance_iteration_counter(int old_t, int new_t)
00331 {
00332 int i;
00333 for (i=old_t; i<new_t; i++) {
00334 hooklists_run_list(before_input,i,True);
00335 hooklists_run_list(after_presentation,i,True);
00336 hooklists_run_list(after_learning,i,True);
00337 }
00338 }
00339
00340
00341
00343 cmdstat exc_rad_setfn( const char* name, void* param, const void* newval)
00344 {
00345 #ifdef NO_WEIGHTS
00346 (void)name;
00347 *(int *)param = *(const int *)newval;
00348
00349 #else
00350 int oldvalue= *(int *)param;
00351 int newvalue= *(const int *)newval;
00352
00353 if (!network_initialized)
00354 *(int *)param = newvalue;
00355 else if (oldvalue != newvalue) {
00356 ipc_notify(IPC_ONE,IPC_STD,"Renormalizing weights to change %s from %d to %d",
00357 name,oldvalue,newvalue);
00358 *(int *)param = change_lateral_exc_radius(oldvalue, newvalue);
00359 }
00360 #endif
00361
00362 return CMD_NO_ERROR;
00363 }
00364
00365
00368 cmdstat fixed_arch_param_setfn( const char* name, void* param, const void* newval)
00369 {
00370 int oldvalue= *(int *)param;
00371 int newvalue= *(const int *)newval;
00372
00373 if (!network_initialized)
00374 *(int *)param = newvalue;
00375 else if (oldvalue != newvalue) {
00376 ipc_notify(IPC_ONE,IPC_ERROR,"Can't change %s once the network has been initialized; call uninit_network first",
00377 name);
00378 return CMD_PARAMETER_ERROR;
00379 }
00380
00381 return CMD_NO_ERROR;
00382 }
00383
00384
00385
00386 00387
00388 cmdstat read_only_param_setfn( const char* name, void* param, const void* newval)
00389 {
00390 (void)param;
00391 (void)newval;
00392
00393 ipc_notify(IPC_ONE,IPC_ERROR,"Read-only parameter; can't change %s",name);
00394 return CMD_PARAMETER_ERROR;
00395 }
00396
00397
00398
00399