Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

inputs.c

Go to the documentation of this file.
00001 
00009 #include <vector>
00010 #include <functional>
00011 #include <string>
00012 using std::string;
00013 #include <time.h>
00014 
00015 #include "inputs.h"
00016 #include "ipc.h"
00017 #include "cmdparam.h"
00018 #include "kernelfactory.h"
00019 #include "fixedwtregion.h"
00020 #include "retina.h"
00021 #include "pointermap.h"
00022 #include "kernelwrapper.h"
00023 #include "stringutils.h"
00024 #include "worldviews.h"
00025 #include "shuffledrand.h"
00026 #include "valuegencontainer.h"
00027 #include "generic_stdlib.h"
00028 #include "matrix.h"
00029 #include "tnt_gnuplot.h"
00030 #include "robj.h"
00031 #include "neuralregion.h"
00032 #include "neuralregionmap.h"
00033 #include "neuralregionmanager.h"
00034 #include "mathconstants.h"
00035 
00036 
00037 #ifdef EXPLICIT_INSTANTIATION_FOR_STATICS
00038 template class Msg::LevelHandler<Msg::MessageLevel,Msg::NumMessageLevels>;
00039 template class ShuffledRandom<double>;
00040 template class ValueGenerator_Increment<double>;
00041 template class ValueGenerator_Expression<double>;
00042 template class ValueGenerator_Correlate<double,synchronized_distribution<Distributions::uniform>,true>;
00043 template class ValueGenerator_Random<double,synchronized_distribution<Distributions::uniform> >;
00044 template class ValueGenerator_Random<double,synchronized_distribution<Distributions::normal> >;
00045 #endif 
00046 
00047 
00048 /******************************************************************************/
00049 /* NamedValueGenerators class                                                 */
00050 /******************************************************************************/
00051 
00053 class NamedValueGenerators : public ValueGenContainer {
00054 public:
00055   virtual cmdstat create(StringArgs args);
00056 };
00057 
00058 
00060 cmdstat NamedValueGenerators::create(StringArgs args)
00061 {
00062   DistributedValueGeneratorFactory<double> vgf;
00063   
00064   const string name         = args.next(string(""));
00065   ValueGenerator<>* valgen  = vgf.create(args.recursiveparser());
00066   const string helpstring   = args.next(string(""));
00067 
00068   
00069   if (blackboard.define_param(DECLARE_PARAM(PARAM_DOUBLE,name.c_str(),false,
00070                                             valgen->valueptr())) == 1) {
00071     if (helpstring != "") params_define_doc(name.c_str(),cmdparam_dupstr(helpstring.c_str()));
00072     push_back(valgen);
00073     ipc_notify(IPC_ONE,IPC_STD,"Defined ValueGenerator %s",name.c_str());
00074   }
00075   else {
00076     delete valgen;
00077     ipc_notify(IPC_ONE,IPC_STD,"Could not define ValueGenerator %s; perhaps already defined",name.c_str());
00078   }
00079   return CMD_NO_ERROR;
00080 }
00081 
00082 
00083 
00084 /******************************************************************************/
00085 /* Eyes class                                                                 */
00086 /******************************************************************************/
00087 
00088 
00094 class Eyes : public Inputs {
00095 public:
00096   Eyes() : last_object_drawn(&permanent_contents),
00097            neuralregions("Region",blackboard),
00098            default_region_command("define_region height=BaseN*area_scale width=BaseN*area_scale"),
00099            initialize_weights(true), size_scale_override(-1),
00100            input_define_convolution_in_use(false) {  }
00101   
00102   virtual ~Eyes() { }
00103 
00104   virtual void uninit();
00105   virtual void init();
00106 
00109   virtual void reset() {
00110     permanent_contents.reset();
00111     namedgenerators.reset();
00112   }
00115   virtual void reset(long int seed) {
00116     permanent_contents.reset(seed);
00117     namedgenerators.reset();
00118   }
00119 
00120   virtual bool next();
00121 
00122   virtual void activate(const WorldViews& views, const ParamMap& argparams) {
00123     activate(views,
00124              argparams.get_with_default("learning",False),
00125              argparams.get_with_default("settle",True),
00126              argparams.get_with_default("activate",True),
00127              argparams.get_with_default("verbose",False));
00128   }
00129 
00130   virtual void activate(bool learn, bool settle_, bool activatefn=true)
00131     {  activate(permanent_contents,learn,settle_,activatefn);  };
00132 
00134   virtual void activate(const WorldViews& views,bool learn, bool settle_, bool activatefn=true, bool verbose=false);
00135 
00137   virtual bool   is_active(int objnumber, int eye) const
00138     {  return last_object_drawn->is_active(objnumber,eye);  }
00139   virtual double angle_of_object(int objnumber, int eye) const
00140     {  return last_object_drawn->angle_of_object(objnumber,eye);  }
00141   virtual double angle_of_object_at_location(int i, int j, int eye) const
00142     {  return last_object_drawn->angle_of_object_at_location(i,j,eye);  }
00143 
00144 private:
00145   static void message(Msg::MessageLevel m, const string& s)
00146     {  NeuralRegionMap::message(m,s);  }
00147   
00148   CMDOBJ_DECLARE(Eyes,define_region);
00149   CMDOBJ_DECLARE(Eyes,connect_region);
00150 
00151   bool   has_default_region() {  return default_region!="";  }
00152   string ensure_default_region();
00153 
00154   void update_default_values();
00155   void register_params_and_commands( void );
00156   void select_worldview(const WorldViews& views);
00157 
00158   void define_input_pathway(const string& region_downstream, const string& eyename,
00159                             StringArgs& arglist, const double size_scale, const int layers_pereye );
00160   cmdstat training(StringArgs& arglist, const ParamMap& argparams);
00161     
00162   CMDOBJ_DECLARE(Eyes,input_undefine);
00163   CMDOBJ_DECLARE(Eyes,input_define);
00164   CMDOBJ_DECLARE(Eyes,input_define_generator);
00165   CMDOBJ_DECLARE(Eyes,input_print);
00166   CMDOBJ_DECLARE(Eyes,input_reset);
00167   CMDOBJ_DECLARE(Eyes,input_clear);
00168   CMDOBJ_DECLARE(Eyes,input_draw);
00169   CMDOBJ_DECLARE(Eyes,input_present);
00170   CMDOBJ_DECLARE(Eyes,input_present_object);
00171 
00172   CMDOBJ_DECLARE(Eyes,input_define_convolution);
00173 
00174   CMDOBJ_DECLARE(Eyes,load_snapshot);
00175 
00176   CMDOBJ_DECLARE(Eyes,step);
00177   CMDOBJ_DECLARE(Eyes,testing);
00178   CMDOBJ_DECLARE(Eyes,training);
00179     
00180   CMDOBJ_DECLARE(Eyes,uninit_network);
00181   CMDOBJ_DECLARE(Eyes,init_network);
00182 
00183   
00184   SETFNOBJ_DECLARE2(Eyes,inputs_pereye_setfn2);
00185   SETFNOBJ_DECLARE2(Eyes,blur_type_setfn2);
00186   SETFNOBJ_DECLARE2(Eyes,double_blur_setfn2);
00187   SETFNOBJ_DECLARE2(Eyes,exc_rad_setfn2);
00188   
00189   /* Obsolete */
00190   SETFNOBJ_DECLARE2(Eyes,distribution_setfn2);
00191 
00193   NamedValueGenerators namedgenerators;
00194 
00196   const WorldViews* last_object_drawn;
00197   WorldViews permanent_contents;
00198   WorldViews temporary_contents;
00199 
00201   typedef Retina        retina_type;
00202   
00204   typedef NeuralRegionMap neuralregions_type;
00205   neuralregions_type      neuralregions;
00206   
00207   KernelFactory kernel_factory;
00208 
00212   string default_region;
00213   
00214   string default_region_command;
00215   
00220   bool   initialize_weights;
00221   
00227   string default_input_target;
00228   
00229   static int    current_object_angle;
00230   static double world_size_scale;
00231 
00232   static Tristate progress_reports;
00233   static int    progress_report_interval;
00234   static int    startt;
00235 
00239   double size_scale_override;
00240   
00243   bool input_define_convolution_in_use;
00244 
00245   HooklistNum before_input;               
00246 //HooklistNum after_presentation;         /**< Hook set for hooklists_run_list() */
00247   HooklistNum after_learning;             
00249   void advance_iteration_counter(int old_t, int new_t);
00250 };
00251 
00252 
00253 
00254 /* Static variables in Eyes */
00255 int    Eyes::current_object_angle=0;
00256 double Eyes::world_size_scale=1.0;
00257 
00258 Tristate Eyes::progress_reports=Uninitialized;
00259 int      Eyes::progress_report_interval=10;
00260 int      Eyes::startt=0;
00261 
00264 void Eyes::init()
00265 {
00266   startt=0;
00267 
00268   /* Define toplevel area, if none already */
00269   ensure_default_region();
00270   
00271   /* Define inputs and optional convolution, if none already */
00272   if (!permanent_contents.has_been_defined())
00273     cmd_input_define_convolution();
00274 
00275   /* Define contents of each input area, if none already */
00276   if (permanent_contents.is_empty())
00277     permanent_contents.generate_default_contents();
00278 
00279   ipc_notify(IPC_ONE,IPC_SUMMARY,"Defined %d-connection network; %.1fMB%s total required for weight storage",
00280              int(neuralregions.size_unique_connections()),
00281              neuralregions.size_connection_bytes()/1024.0/1024.0,
00282              (NPEs>1 ? " on each PE" : ""));
00283 }
00284 
00285 
00288 string Eyes::ensure_default_region()
00289 {
00290   if (default_region=="") cmddefs_exec_str(default_region_command);
00291   assert (default_region!="");
00292   return default_region;
00293 }
00294 
00295 
00296 
00297 void Eyes::uninit( void )
00298 {
00299   cmddefs_declare_prereq_status( "init_network", CMD_NEVER_CALLED );
00300   iteration=0;
00301   presentation=0;
00302 
00303   permanent_contents.uninit();
00304   neuralregions.erase();
00305   default_region="";
00306   default_input_target="";
00307   ::network_initialized=false;
00308   startt=0;
00309   input_define_convolution_in_use=false;
00310   
00311   /* Clear out all training hooks defined */
00312   hooklists_empty_list(before_input);
00313 //hooklists_empty_list(after_presentation);
00314   hooklists_empty_list(after_learning);
00315 }
00316 
00317 
00318 
00319 bool Eyes::next(void)
00320 {
00321   /* Update parameters for this presentation */
00322   /* This barrier is superfluous (isn't it?) since the next() fns use
00323      the barrier-ed random distributions */
00324   ipc_barrier();
00325   bool status1 = namedgenerators.next();
00326   bool status2 = permanent_contents.next();
00327   return status1 && status2;
00328 }
00329 
00330 
00331 
00332 void Eyes::activate(const WorldViews& views,bool learn, bool settle_, bool activatefn, bool verbose)
00333 {
00334   static int iteration_of_last_presentation=Uninitialized;
00335   if (iteration!=iteration_of_last_presentation) {
00336     iteration_of_last_presentation=iteration;
00337     presentation=0;
00338   }
00339   else
00340     presentation++;
00341   
00342   select_worldview(views);
00343   neuralregions.activate(learn,settle_,activatefn,verbose);
00344 }
00345 
00346 
00348 void Eyes::select_worldview(const WorldViews& views)
00349 {
00350   for (WorldViews::const_iterator eye=views.begin(); eye!= views.end(); eye++) {
00351     retina_type* retina = dynamic_cast<retina_type*>(neuralregions.getptr((*eye)->get_name())->region());
00352     if (retina)
00353       retina->set_input(*eye);
00354   }
00355   
00356   /* Update globals for use in e.g. filename format strings */
00357   last_object_drawn = &views;
00358   current_object_angle = (int)floor(RADIANS_TO_DEGREES(CONSTRAIN_ANGLE(angle_of_object(0,0)))+0.5);
00359 }
00360 
00361 
00369 void Eyes::define_input_pathway(const string& region_downstream, const string& eyename,
00370                                 StringArgs& arglist, const double size_scale, const int layers_pereye )
00371 {
00372   const string eyenum = String::numeric_extension<string>(eyename);
00373     
00374   /* Save the user's default_region, to be restored before we finish */
00375   string default_reg    = default_region;
00376   
00377   /* True if input region has already been defined. */
00378   bool retina_defined = false;
00379 
00380   /* True if we will be defining ganglia layers between the input region and the
00381      target */
00382   const bool has_ganglia = (layers_pereye>0);
00383 
00384   
00385   /* Add each pathway to this input layer */
00386   for (int layer=0; layer<std::max(1,layers_pereye); layer++) {
00387     double sscale=size_scale;
00388       
00389     /* These are used for the first region defined, whatever it is */
00390     string target         = region_downstream;
00391     string connectionspec = "Blur_CircularRandom ::Region::"+default_region+"::rf_radius"; // Should honor various parameters instead
00392 
00393     /* Insert new Ganglia layer, if not connecting directly */
00394     if (has_ganglia) {
00395       const string convolvenum  = eyenum + String::stringrep(layer);
00396       const string convolvename = "Ganglia" + convolvenum;
00397       size_scale_override=sscale;
00398       const string ssoverride = String::stringrep(size_scale_override,String::StreamFormat(-1,'0',16,false));
00399       const string command = string("connect_region")
00400         + " name=Afferent" + convolvenum
00401         + " target="       + target
00402         + " source="       + convolvename
00403         // This copy of the size_scale is usually ignored, but it's
00404         // helpful if user is seeing the command execute:
00405         + " size_scale="   + ssoverride 
00406         + " sourcespec='type=Convolution'"
00407         + " " + connectionspec;
00408       cmddefs_exec_str(command);
00409       size_scale_override=-1;
00410       
00411       target=convolvename;
00412       sscale=1.0;
00413       connectionspec=arglist.stringrep();
00414     }
00415 
00416     /* Connect ganglia layer to retina layer, creating or overwriting it if need be */
00417     size_scale_override=(has_ganglia? world_size_scale : 1.0)*sscale;
00418     const string ssoverride = String::stringrep(size_scale_override,String::StreamFormat(-1,'0',16,false));
00419     const string command = string("connect_region")
00420       + " name=Afferent" + eyenum
00421       + " target="       + target
00422       + " source="       + eyename
00423       + (retina_defined? "" : " sourcespec='type=Retina" +
00424          string(!has_ganglia ? "" : " size_scale=" + ssoverride) + "'")
00425       + " " + connectionspec;
00426     cmddefs_exec_str(command);
00427     size_scale_override=-1;
00428     retina_defined=true;
00429   }
00430   
00431   /* Restore the value of default_region; we assume that none of the
00432      automatically-constructed ones defined here are of enough
00433      interest to be worthy of being the default.  Uses the public set
00434      command so that user can see that it has been changed when trying
00435      to recreate this process by hand, but sets the value first so
00436      that messages will not be printed unless requested. */
00437   default_region=default_reg;
00438   cmddefs_exec_str("set default_region=" + default_reg);
00439 }
00440 
00441 
00442 
00444 #define CMDARGP_DOC "Default value for the corresponding parameter for commands."
00445 #define CMDARGP(name,initial_value,options,doc) PARAM_A(blackboard.lookup_map("::cmd"),name,initial_value,options,doc);
00446 
00447 
00448 
00449 void  Eyes::register_params_and_commands( void )
00450 {
00451   /* Define hook sets for cmd_training */
00452   before_input       = hooklists_define_list("before_input",   "iteration");
00453 //after_presentation = hooklists_define_list("after_presentation", "iteration");
00454   after_learning     = hooklists_define_list("after_learning", "iteration");
00455 
00456 
00459   PARAM_A(blackboard,"display",0,.add_lower_bound(0),
00460           "Plot network activation, etc. every (display)th training or testing\n"
00461           "iteration.  If display==0, never do it; if display==1, do it every\n"
00462           "iteration, if display==2, do it every other iteration, etc.");
00463 
00464   PARAM_A(blackboard,"learning",True,.add_lower_bound(False),
00465           "Whether learning (as controlled by the various alpha_ parameters)\n"
00466           "is enabled.");
00467 
00468   PARAM_A(blackboard.lookup_map("::cmd"),"activate",True,.add_lower_bound(False),
00469           "Whether to pass a neuron's initial response through an activation function.\n"
00470           "Usually true, but this can be set to False for some commands to examine the\n"
00471           "initial response, or for commands like measure_stimulus_map which can work\n"
00472           "better with the smooth, continuous initial response than with the more patchy\n"
00473           "activated response.\n");
00474   
00475   PARAM_A(blackboard.lookup_map("::cmd"),"settle",True,.add_lower_bound(False),
00476           "Whether settling (as controlled by the tsettle parameter) is enabled or\n"
00477           "disabled.");
00478   
00479   PARAM_A(blackboard,"tend",50000,.add_lower_bound(0),
00480           "Upper bound for training iterations.");
00481 
00482 
00483   CMDOBJ_DOC(step,"init_network",this,0,"%s [<named_arguments>]* [<training_iterations>]",
00484           "Supported <named_arguments> include: <display>,<learning>,<settle>,<activate>.\n\n"
00485 
00486           "Same as training except that it interprets the parameter as a value relative\n"
00487           "relative to the current iteration (1 by default), rather than an\n"
00488           "absolute iteration number, and defaults to display==1. Example: \"step\"\n"
00489           "just trains for one iteration and calls plot.  Typically used at the\n"
00490           "command prompt for debugging or exploration, rather than in a command file.");
00491   blackboard.lookup_map("::cmd::step") /* Default arguments, overriding globals */
00492     .set_local("display",1);
00493   
00494   CMDOBJ_DOC(testing,"init_network",this,0,"%s [<named_arguments>]* [<tend>]",
00495           "Supported <named_arguments> include: <display>,<learning>,<settle>,<activate>.\n\n"
00496              
00497           "Same as training except that learning defaults to False.  The iteration counter\n"
00498           "is still advanced.");
00499   blackboard.lookup_map("::cmd::testing") /* Default arguments, overriding globals */
00500     .set_local("learning",False);
00501   
00502   CMDOBJ_DOC(training,"init_network",this,0,"%s [<named_arguments>]* [<tend>]",
00503           "Supported <named_arguments> include: <display>,<learning>,<settle>,<activate>.\n\n"
00504 
00505           "Trains the network for the current iteration, then repeats training until\n"
00506           "the iteration counter 'iteration' has reached the <tend>.  Sometimes it is\n"
00507           "appropriate to supply a specific tend iteration (e.g. `training 1000' trains\n"
00508           "until iteration 1000); other times it's more useful to supply an offset\n"
00509           "relative to the current iteration (e.g. `training iteration+1000' trains for\n"
00510           "1000 iterations more).  After training, the global parameter 'iteration' is\n"
00511           "equal to the specified tend.");
00512 
00513   CMDOBJ_DOC(uninit_network,NULL,this,0,"%s",
00514           "Marks network uninitialized so that network architecture parameters\n"
00515           "can be changed.  All weight values and training iteration hook\n"
00516           "definitions will be lost, and the iteration counter will be reset to\n"
00517           "zero.  However, other parameters keep their existing values, which can\n"
00518           "have surprising consequences.  When in doubt, it may be safest to quit\n"
00519           "the program and restart if changing the underlying architecture.");
00520   
00521   CMDOBJ_DOC(init_network,"uninit_network",this,0,"%s [<named_arguments>]*",
00522           "Supported <named_arguments> include:\n"
00523           "<initialize>,<essential_training_hooks_only>.\n\n"
00524 
00525           "Initializes network with the current parameters, suitable for\n"
00526           "beginning training anew.  A command file <filebase>.<iteration>.params\n"
00527           "is created with the current values of parameters, suitable for\n"
00528           "recreating the starting state later.  A single cycle of testing\n"
00529           "is done, iterating t to 1, in order to verify that everything is\n"
00530           "working properly.  This command is a prerequisite for most other\n"
00531           "commands, and will be called automatically the first time one of\n"
00532           "those commands is executed.");
00533   
00534 
00535   
00536   PARAM_I(PARAM_3BOOL,  progress_reports,False,True,
00537           "Whether or not to print messages during very long computations; defaults to\n"  
00538           "True for interactive sessions and False otherwise.");
00539   params_define_default_expr("progress_reports","interactive");
00540   
00541   PARAM_L(PARAM_INT,   progress_report_interval,0,
00542           "The minimum number of seconds between messages printed during very long\n"  
00543           "computations, such as training.  Only used if progress_reports is True.");
00544   
00545   PARAM_L(PARAM_INT,   startt,0,
00546           "Starting iteration to be used the next time training or testing begins.\n"  
00547           "This should not ordinarily be changed, but it can be used for debugging.");
00548   
00549   PARAM_A(blackboard,"essential_training_hooks_only",False,.add_lower_bound(False).add_upper_bound(True),
00550           "If this is true, inessential hooks such as plotting and analysis will be\n"
00551           "ignored during training and initialization.  (Whether or not a given command\n"
00552           "is ignored depends upon whether it was defined as a `catchup' command or not;\n"
00553           "see cmdparam.c.)  This defaults to true for an interactive session to\n"
00554           "facilitate exploration using a saved batch session; this avoids having too\n"
00555           "many images displayed automatically.");
00556   params_define_default_expr("essential_training_hooks_only","interactive");
00557   
00558   PARAM_A(blackboard,"rf_radius",6.0,.add_lower_bound(0.0),
00559           "Default radius (centered about the neuron) of an afferent receptive field.\n"  
00560           "Must not be larger than half the width of the input region (usually RN/2).\n\n"
00561 
00562           "For square radii, the floating-point value of the radius is rounded to the\n"
00563           "nearest integer.  For circular radii, the digits after the decimal point\n"
00564           "determine the shape of the blocky circular outline.  For small values of the\n"
00565           "radius you may want to set the decimal value precisely to achieve the most\n"
00566           "circular-looking outline; generally .5 works well.");
00567   
00568   PARAM_A(blackboard,"inh_rad",9.0,.add_lower_bound(0.0),
00569           "Default connection radius for lateral inhibitory weights.  See rf_radius\n"
00570           "for more information about using floating-point values.");
00571   
00572   PARAM_A(blackboard,"exc_rad",4.0,.add_lower_bound(0.0),
00573           "Default connection radius for lateral excitatory weights.  When the global\n"  
00574           "value of this parameter is changed after a LISSOM map has been defined, each\n"  
00575           "such map is converted into one with the smaller excitatory radius.  To change\n"  
00576           "only a particular map, change that region's value of this parameter instead.\n"  
00577           "See rf_radius for more information about using floating-point values.");
00578 
00579 
00580 
00581   /* Register default values for command arguments.  Eventually should
00582   probably add more documentation than this */
00583   CMDARGP("name",              string(""),  , CMDARGP_DOC);
00584   CMDARGP("objtype",           string(""),  , CMDARGP_DOC);
00585   CMDARGP("plotgroup",         string(""),  , CMDARGP_DOC);
00586   CMDARGP("parent",            string(""),  , CMDARGP_DOC);
00587   CMDARGP("child",             string(""),  , CMDARGP_DOC);
00588   CMDARGP("source",            string(""),  , CMDARGP_DOC);
00589   CMDARGP("target",            string(""),  , CMDARGP_DOC);
00590   CMDARGP("region",            string(""),  , CMDARGP_DOC);
00591   CMDARGP("type",              string(""),  , CMDARGP_DOC);
00592   CMDARGP("filename",          string(""),  , CMDARGP_DOC);
00593 
00594   CMDARGP("height",            1,.add_lower_bound(1), CMDARGP_DOC);
00595   CMDARGP("width",             1,.add_lower_bound(1), CMDARGP_DOC);
00596 
00597   CMDARGP("save_matrices",     False,       .add_lower_bound(False).add_upper_bound(True),
00598           "When using a plot routine, whether to save the matrices as ASCII in addition\n"
00599           "to any other plot format generated.");
00600   
00601   CMDARGP("gnuplot_plots",     False,       .add_lower_bound(False).add_upper_bound(True),
00602           "When using a plot routine, whether to generate gnuplot PostScript plots\n"
00603           "and save them to disk.");
00604   
00605   CMDARGP("ppm_plots",         True,        .add_lower_bound(False).add_upper_bound(True),
00606           "When using a plot routine, whether to generate .ppm bitmap images and\n"
00607           "save them to disk.");
00608   
00609   CMDARGP("weight_situate",    True,        .add_lower_bound(False).add_upper_bound(True),
00610           "Whether to situate weight plots in their location on the network.  If\n"
00611           "false, weights are shown in their own coordinate systems instead, which\n"
00612           "gives less information but requires less plot area.");
00613 
00614   CMDARGP("weight_bare",       False,       .add_lower_bound(False).add_upper_bound(True),
00615           "If true, suppresses extraneous details from weight plots, such as borders\n"
00616           "outlines, etc., without having to turn off the various other parameters.");
00617 
00618   CMDARGP("weight_fill_background",False,   .add_lower_bound(False).add_upper_bound(True),
00619           "If true, weight plots fill in all area not containing weights with the\n"
00620           "ppm_page color so that the weight outlines are visible.  At present,\n"
00621           "killed connections are not filled in with the background color, instead\n"
00622           "appearing as zero-strength connections, but at some point making\n"
00623           "them into the background color may be implemented.");
00624 
00625   /* Register parameters in subobjects */ 
00626   WorldViews::register_params_and_commands();
00627   kernel_factory.register_params_and_commands();
00628   neuralregions.register_params_and_commands();
00629 
00630   /*
00631     Strange but (currently) legal: Changes the setfn for a few
00632     parameters we do not own so that we will know when they change and
00633     can update our own structures; this should be ok as long as no one
00634     else has installed a special setfn for them (which should probably
00635     be checked).
00636   */
00637   SETFNOBJ_DEFINE2(this,inputs_pereye,inputs_pereye_setfn2);
00638   SETFNOBJ_DEFINE2(this,distribution,distribution_setfn2);
00639   SETFNOBJ_DEFINE2(this,blur_radius,double_blur_setfn2);
00640   SETFNOBJ_DEFINE2(this,blur_type,blur_type_setfn2);
00641   SETFNOBJ_DEFINE2(this,blur_radius_surround_multiplier,double_blur_setfn2);
00642   SETFNOBJ_DEFINE2(this,blur_range_multiplier,double_blur_setfn2);
00643   SETFNOBJ_DEFINE2(this,blur_scale,double_blur_setfn2);
00644   SETFNOBJ_DEFINE2(this,exc_rad,exc_rad_setfn2);
00645   
00646   CMDOBJ_DEFINE_CATCHUP(this,0,define_region,
00647           "%s [<named_arguments>]* [<name> [<named_region_arguments>*]]",
00648 
00649           "Supported <named_arguments> include: <name>,<type>,<initialize>,\n"
00650           "<height>,<width>,<xoffset>,<yoffset>.\n\n"
00651 
00652           "Supported <type>s include: LISSOM (default), Convolution, Retina\n"
00653           "(At present only LISSOM accepts any <named_region_arguments>.)\n\n"
00654 
00655           "Define a new neural region with the given <name>, which defaults to\n"
00656           "'Primary'.  After definition, the value of default_region is set to\n"
00657           "this <name>, e.g. for plot_unit and plot_unit_range.  (Often this\n"
00658           "command will only need to be called explicitly once, for a top-level\n"
00659           "region, and then the rest of the input pathway can be constructed to\n"
00660           "match it by connect_region using default_region.)\n\n"
00661 
00662           "After the default_region is set, the command (if any) specified in\n"
00663           "'Region::.defaults::<type>::default_command' is executed.");
00664   blackboard.lookup_map("::cmd::define_region") /* Default arguments, overriding globals */
00665     .set_local("type",string("LISSOM"))
00666     .set_local("name",string("Primary"));
00667   PARAM_A(blackboard.lookup_map("::Region"),"num_aff_inputs",1,.add_lower_bound(0)
00668           .add_default_expr("num_eyes*(layers_pereye>?1)"),
00669           "Parameter for a LISSOM map specifying the number of afferent inputs that\n"
00670           "you will eventually connect.  Most region types do not need this information,\n"
00671           "since it is implicit in the calls to connect_region, but LISSOM maps currently\n"
00672           "must know num_aff_inputs when they are created because they initialize all\n"
00673           "weights at that time.  Warnings will be generated if the number of actual\n"
00674           "calls to connect_region before the first iteration does not match this\n"
00675           "parameter's value.\n");
00676   
00677   PARAM_A(blackboard.lookup_map("::cmd"),"initialize",True,.add_lower_bound(False),  
00678           "Whether to initialize the internal state of a region or a set of connections\n"
00679           "when creating it.  Not usually changed to false by users, but some commands\n"
00680           "(e.g. load_snapshot) specify false because they will be initializing the\n"
00681           "objects themselves.");
00682   PARAM_A(blackboard.lookup_map("::cmd::define_region"),"xoffset",0.5,,
00683           "When creating a new region, where to place the horizontal (x) axis of the\n"
00684           "coordinate system origin.  At present many region types ignore this parameter\n"
00685           "and always place the origin at (0.5,0.5).");
00686   PARAM_A(blackboard.lookup_map("::cmd::define_region"),"yoffset",0.5,,
00687           "When creating a new region, where to place the vertical (y) axis of the\n"
00688           "coordinate system origin.  At present many region types ignore this parameter\n"
00689           "and instead always place the origin at (0.5,0.5).");
00690   
00691   CMDOBJ_DEFINE_CATCHUP(this,0,connect_region,
00692           "%s [<named_arguments>]* [<connection_arguments>*]",
00693 
00694           "Supported <named_arguments> include: <name>,<target>,<source>,<sourcespec>,\n"
00695           "<size_scale>.\n\n"
00696 
00697           "Define a new set of connections from the neural region <target> to the\n"
00698           "region <source>.  The <connection_arguments> are as for\n"
00699           "input_define_convolution, which see.  (Exception: named arguments cannot\n"
00700           "be used in the <connection_arguments>, because they will be processed in\n"
00701           "this command instead, and will thus have no effect.)\n\n"
00702 
00703           "The connection <name> defaults to 'Afferent'.  All connections to a given\n"
00704           "<target> MUST have a unique <name>.  In addition, it is usually a good idea\n"
00705           "to keep all connection <names> for a given <source> unique, since e.g. plotting\n"
00706           "parameters are stored with the <source> and not the target.\n\n"
00707                         
00708           "If a <sourcespec> is given, the <source> region will be created\n"
00709           "(or recreated) with a size that provides full connectivity (by default)\n"
00710           "for the target region with this size, connection radius, etc.");
00711   blackboard.lookup_map("::cmd::connect_region") /* Default arguments, overriding globals */
00712     .set_local("name",string("Afferent"));
00713   PARAM_A(blackboard.lookup_map("::cmd::connect_region"),"sourcespec",string(),,
00714           "If this argument is non-empty (even a quoted space will do), a new source\n"
00715           "region will be created (and will replace any old one by that name, if present.)\n"
00716           "Default sizes for the source are computed from the <target>, <size_scale>, and\n"
00717           "<connection_arguments>, and these values are combined with the value of this\n"
00718           "parameter and then passed to the define_region command to define the region.");
00719 
00720 
00721   CMDOBJ_DEFINE_CATCHUP(this,0,input_define,
00722           "%s [<name> [<parent> [<objtype> [<input_object_arguments>*]]]]",
00723           
00724           "Define a new persistent input object with the given <name>.\n\n"
00725 
00726           "The <parent> may be the name of one input region, e.g. EyeX, where\n"
00727           "X is a numeric digit representing a single eye, \"\", \'\', or 'All'\n"
00728           "for all input regions, or the name of a previously defined\n"
00729           "Input_Composite object. (To keep yourself from getting confused about\n"
00730           "which regions are included in `all input regions', you should probably\n"
00731           "not change num_eyes after you call this command.)\n\n"
00732 
00733           "The <objtype> may be any of the following (prefixed with `Input_'):\n\n"
00734           
00735           "  Composite,UniformRandomNoise,Gaussian,CircularGaussian,\n"
00736           "  SineGrating,Gabor,PGM,Clone,Rectangle\n"
00737           "  FuzzyLine,FuzzyDisc,FuzzyRing\n\n"
00738           
00739           "See the documentation for the corresponding constants for more\n"
00740           "information on that particular object type.\n\n"
00741           
00742           "The remaining parameters are determined by the <objtype>.  They\n"
00743           "can generally be specified either by position, i.e. by listing\n"
00744           "them in order, or by name, e.g. by specifying xsigma=5.  All\n"
00745           "named arguments must follow any positional arguments.\n\n"
00746 
00747           "Most or all floating-point parameters may be a ValueGenerator, i.e.\n"
00748           "any <valuegenerator> accepted by the input_define_generator command.\n"
00749           "If the object is being defined in more than one input region, the\n"
00750           "specified <valuegenerator>s apply only to the first region.  Objects\n"
00751           "in the remaining regions are created with references to the\n"
00752           "corresponding parameters in the first, so that e.g. random values are\n"
00753           "fully correlated between the input regions.\n\n"
00754           
00755           "If you wish to introduce some degree of uncorrelation between\n"
00756           "objects defined in more than one region, you may substitute for any\n"
00757           "ValueGenerator parameter the extended syntax:\n\n"
00758 
00759           "  \"Uncorrelate <uncorrelation-ratio> <lower-bound> <upper-bound> <valuegenerator>\"\n\n"
00760 
00761           "This will add or subtract a random value to the value generated\n"
00762           "in the first region, scaled by the difference between the bounds times\n"
00763           "the uncorrelation-ratio, and cropped by the bounds.  For instance,\n\n"
00764           
00765           "  \"Uncorrelate &uncorrelation 0 RN  Random RN/2 RN/2\"\n\n"
00766 
00767           "when uncorrelation=1.0 will create a random number generator\n"
00768           "in the range 0..RN in the first region, and will effectively\n"
00769           "uncorrelate the value entirely within that range in all the\n"
00770           "other input regions.  (This is the default for <cx> and <cy>\n"
00771           "parameters, except that uncorrelation is not necessarily 1.0.)\n\n"
00772 
00773           "Since ValueGenerators and input objects are extremely flexible, be\n"
00774           "sure to look at images of the inputs for a number of sample iterations\n"
00775           "so that you can verify that the inputs are being generated as you expect.\n"
00776           "You can also look at the logfile (when input_log is true) to verify\n"
00777           "the average and range for some of the generated values.");
00778  
00779   CMDOBJ_DEFINE_CATCHUP(this,2,input_define_generator,
00780           "%s <name> <valuegenerator> [<helpstring>]",
00781 
00782           "Define a new ValueGenerator whose value is updated before every input\n"
00783           "presentation.  A ValueGenerator is like a generalization of a parameter\n"
00784           "of type PARAM_DOUBLE which supports automatic updating from e.g. a\n"
00785           "random distribution.  This command allows you to define a named\n"
00786           "ValueGenerator which can be referred to when later defining input\n"
00787           "objects; this enables you to e.g. define a single random number\n"
00788           "which controls multiple objects in unison.  The value also\n"
00789           "becomes a parameter, so it will henceforth show up in documentation,\n"
00790           "online help, etc., and can be set or queried like any parameter.\n\n"
00791           
00792           "Possible values for a <valuegenerator>:\n\n"
00793           
00794           "  <expr>               A floating-point expression.  (Ex: 2*PI)\n\n"
00795           
00796           "  &<param>             A reference to a parameter.  (Ex: &xsigma)\n"
00797           "                       Future changes to the parameter will be\n"
00798           "                       reflected in the ValueGenerator, so this\n"
00799           "                       form provides a means for controlling a\n"
00800           "                       ValueGenerator after creation and linking\n"
00801           "                       multiple ValueGenerators together.  This form\n"
00802           "                       is also accepted for the numeric arguments of\n"
00803           "                       all the other ValueGenerators defined below.\n\n"
00804 
00805           "  \"Random <m> <r>\"     A random number from the uniform distribution\n"
00806           "                       centered at mean <m> and extending radius <r>\n"
00807           "                       in either direction (inclusively on the lower\n"
00808           "                       side, exclusively on the higher).\n"
00809           "                       (Ex: \"Random PI/2 PI/2\" or \"Random &mean &radius\"\n\n"
00810 
00811           "  \"Normal <m> <r>\"     A random number from the normal distribution\n"
00812           "                       centered at mean <m> with sigma (approx. half-width at\n"
00813           "                       half-height) <r>.\n"
00814           "                       (Ex: \"Normal PI/2 PI/2\" or \"Normal &mean &radius\")\n\n"
00815 
00816           "  \"Increment <s> <i>\"  Starts at value <s>; before each presentation, it\n"
00817           "                       is incremented by <i> (which may be negative or\n"
00818           "                       non-integer).  Note that increment occurs *before*\n"
00819           "                       each presentation, so decrement the starting\n"
00820           "                       value if needed.\n"
00821           "                       (Ex: \"Increment -1 1\" to count from 0 by 1)\n\n"
00822 
00823           "  \"Correlate <m> <u> <lb> <ub> \"     Generate a value correlated with\n"
00824           "                       the given master variable <m> within a correlation\n"
00825           "                       constant of <u>.  Optionally crops to the given\n"
00826           "                       range [<lb>..<ub>].  This description may be\n"
00827           "                       seriously incomplete, so study the code a bit first.\n\n"
00828 
00829           "  \"Expression <e>\"     Before each presentation, the given expression <e>\n"
00830           "                       is evaluated to get a value.\n"
00831           "                       (Ex: \"Expression theta+PI/2\" to get the current\n"
00832           "                       value of theta, plus PI/2, each time)\n\n"
00833 
00834           "Single or double quotes are required for any form that has an embedded space,\n"
00835           "and are optional for the others.\n\n"
00836           
00837           "Calling this command multiple times for the same name is not an error,\n"
00838           "but subsequent calls are ignored.");
00839 
00840   CMDOBJ_DEFINE_CATCHUP(this,0,input_define_convolution,
00841           "%s [<named_arguments>]* [<parent> [<blur_type> [<blur_type_arguments>*]]]",
00842 
00843           "Supported <named_arguments> include: <default_afferent_size_scale>,\n"
00844           "<num_eyes>,<layers_pereye>.\n\n"
00845 
00846           "Defines a convolution kernel for the given input region(s) (specified as\n"
00847           "in input_define) to perform input blurring, smoothing, edge detection or\n"
00848           "(in general) convolution.  This command is called automatically at network\n"
00849           "initialization and when any of the parameters blur_type, blur_radius,\n"
00850           "blur_scale, or blur_range_multiplier are changed.  It can also be called\n"
00851           "explicitly for more precise control.  Note that this command clears the\n"
00852           "the current activity values of the input regions, since some may be\n"
00853           "regenerated, so e.g. activity plots will show blank values until new\n"
00854           "activity is computed.\n\n"
00855 
00856           "See the documentation for each type for more information.  Convolution\n"
00857           "radii should be specified in terms of the retinal output; any scaling\n"
00858           "with respect to world_size_scale is handled automatically.  Available\n"
00859           "types include the following (prefixed with 'Blur_'):\n"
00860           "  CircularAverage,SquareAverage,Gaussian,DoG,LoG,GoD,DoGGoD");
00861   PARAM_A(blackboard,"default_afferent_size_scale",0.0,,
00862           "Default size ratio between a target region and a region connected to\n"
00863           "an input.  This is the ratio between the areas mapped directly between\n"
00864           "the regions.  For any given region, such an area can be less than the\n"
00865           "full area because other regions may be expanded to provide full receptive\n"
00866           "fields for this region.  At present, see retina_edge_buffer for more\n"
00867           "details, although that parameter is likely to be replaced with one\n"
00868           "that does not depend on connection radii.");
00869   params_define_default_expr("default_afferent_size_scale","BaseN/BaseRN");
00870   
00871 
00872   CMDOBJ_DOC(input_draw,"init_network",this,0,
00873           "%s [<named_arguments>]* [<parent> [<objtype> [<input_object_arguments>*]]]",
00874           "Supported <named_arguments> include: <name>.\n\n"
00875 
00876           "Same as input_define, but adds the unnamed object to a collection of\n"
00877           "temporary objects (e.g. for testing) to be presented using input_present.\n\n"
00878 
00879           "The arguments are like those in input_define. If no arguments are supplied,\n"
00880           "the object specified by parameter input_default_object is created in all\n"
00881           "input regions, with default arguments.\n\n"
00882           
00883           "The input_clear command can be called before this command to ensure\n"
00884           "that the object list is empty.  This command may be called multiple times\n"
00885           "to define more than one object, either in the same or different input regions.\n"
00886           " The object is not seen by the network until input_present is called.\n\n"
00887 
00888           "Objects created by this command are named 'input_draw' by default, but\n"
00889           "another can be supplied, e.g. if you are constructing composite objects.");
00890 
00891   CMDOBJ_DOC(input_clear,"init_network",this,0,"%s [<named_arguments>]* [<parent>]",
00892           "Supported <named_arguments> include: <name>,<parent>.\n\n"
00893 
00894           "Clears the specifed temporary objects (all objects, by default) defined\n"
00895           "for the given parent (all input regions, by default) in preparation for\n"
00896           "e.g. input_draw.");
00897 
00898   CMDOBJ_DOC(input_present,"init_network",this,0,"%s [<named_arguments>]*",
00899           "Supported <named_arguments> include: <display>,<learning>,<settle>,<activate>,<reset>.\n\n"
00900 
00901           "If <reset> is False (the default), presents the temporary objects currently\n"
00902           "defined by input_draw and activates the network, without advancing the\n"
00903           "iteration counter.  By default, learning is disabled for this test pattern,\n"
00904           "but it can be enabled by setting <learning> to True.  By default,\n"
00905           "pictures are saved using plot when the command completes; <display> can be\n"
00906           "set to zero to prevent this or to some integer higher than one to display only\n"
00907           "every <display>th presentation.  Unless <settle> is set to False, the network\n"
00908           "is allowed to settle after the initial activity calculation (for region types\n"
00909           "for which settling is defined).  Unless <activate> is False, the activation of\n"
00910           "each neuron is computed from using its activation function; if it's True then\n"
00911           "only the initial response is used.\n\n"
00912              
00913           "If <reset> is True, then this command restores the permanent contents of the\n"
00914           "eye and presents that instead of the temporary patterns defined with input_draw.");
00915   blackboard.lookup_map("::cmd::input_present") /* Default arguments, overriding globals */
00916     .set_local("learning",False)
00917     .set_local("display",1);
00918 
00919   CMDOBJ_DOC(input_present_object,"init_network",this,0,
00920           "%s [<named_arguments>] [<parent> [<objtype> [<input_object_arguments>*]]]",
00921           "Supported <named_arguments> include: <name>,<display>,<learning>,<settle>,\n"
00922           "<activate>.\n\n"
00923              
00924           "Convenience macro for looking at the response to a single object.\n"
00925           "Calls input_clear, then passes all the arguments to input_draw and\n"
00926           "then input_present.  (input_present ignores the <input_object_arguments>,\n"
00927           "if any).");
00928 
00929   CMDOBJ_DOC(input_print,NULL,this,0,"%s [<name> [<parent>]]",
00930           "Print a textual representation of the specified input object in the specified\n"
00931           "parent.  Parent defaults to all inputs, and name defaults to all persistent\n"
00932           "objects.");
00933 
00934   CMDOBJ_DEFINE_CATCHUP(this,0,input_reset,
00935           "%s [input_seed]",
00936           "Reset all persistent retinal objects and the input random number generator to\n"
00937           "their starting states.  For instance, if any Increment ValueGenerators have\n"
00938           "been defined (see input_define_generator), their values will be reset to the\n"
00939           "start value supplied initially.\n\n"
00940 
00941           "The random number generator is reset to the specified seed (or the value of\n"
00942           "input_seed if none is given), so the same series of pseudo-random numbers will\n"
00943           "be seen as the last time this command was called.  This means that the\n"
00944           "same sequence of input values will be generated unless other input settings\n"
00945           "have changed, which makes it possible to independently test the effect of\n"
00946           "unrelated changes such as to the network architecture.\n\n"
00947 
00948           "This command is called automatically by init_network, so (in general) changes\n"
00949           "in architecture parameters or the number of PEs should not usually affect the\n"
00950           "input sequence generated.  (Known exception: when Input_UniformRandom inputs\n"
00951           "are used, each processor computes the values independently instead of copying\n"
00952           "from a single master PE, so in that case the sequence will differ when the\n"
00953           "number of PEs changes.)");
00954 
00955   CMDOBJ_DEFINE_CATCHUP(this,0,input_undefine,"%s [<name> [<parent>]]",
00956           "Remove specified input object from specified parent.  Parent defaults to\n"
00957           "all input regions, and name defaults to all persistent objects.");
00958 
00959   CMDOBJ_DOC(load_snapshot,NULL,this,0,"%s [<named_arguments>]* [<tend> [<filename>]]",
00960           "Supported <named_arguments> include: <tend>,<filename>,<verbose>,\n"
00961           "<regions>,<plastic>,<internal>.\n\n"
00962 
00963           "Load weight files saved earlier at the specified iteration <tend>, in order to\n"
00964           "test it or continue training.  If no filename is specified, one is constructed\n"
00965           "as for save_snapshot at the specified iteration.  The load will fail if the\n"
00966           "architecture parameters do not match the current values.\n\n"
00967 
00968           "Specific regions can be given in the regions parameter, in which case only\n"
00969           "those regions are restored.  If using this option, you should ensure that\n"
00970           "the network has first been initialized (via init_network, called\n"
00971           "automatically by most commands), since otherwise regions whose state\n"
00972           "is not restored will have undefined (uninitialized) weight values.");
00973   blackboard.lookup_map("::cmd::load_snapshot")
00974     .set_local("essential_training_hooks_only",True)
00975     .set_local("plastic",True);
00976 
00977   PARAM_A(blackboard.lookup_map("::Region"),"activity_threshold",-1.0,,
00978           "Threshold below which activation is set to zero, usually to save computation\n"
00979           "time.  For an input region, judicious use of this parameter can reduce the\n"
00980           "amount of computation performed in later recurrent regions, since those often\n"
00981           "compute final activations only when a neuron has some initial activation.\n"
00982           "The values should be set high enough so that activations below it would rarely\n"
00983           "exceed the thresholds of subsequent states.  For a recurrent region, an\n"
00984           "activation reaching this lower value is eliminated from future calculations,\n"
00985           "with similar results.  Ignored if < 0.0.\n");
00986   PARAM_A(blackboard.lookup_map("::Region"),"activity_lbound",2.0,,
00987           "Activations below this value are set to it, e.g. to prevent overwhelming later\n"
00988           "regions.  Ignored if > 1.0 (negative values are allowed).\n");
00989   PARAM_A(blackboard.lookup_map("::Region"),"activity_ubound",-1.0,,
00990           "Activations above this value are set to it, e.g. to prevent overwhelming later\n"
00991           "regions.  Ignored if < 0.0.\n");
00992   
00993   blackboard.define_param(DECLARE_PARAM(PARAM_INT,"current_object_angle",true,&current_object_angle));  
00994   params_define_doc("current_object_angle",
00995          "Read-only parameter which reports the top-level (nominal) angle of the object\n"
00996           "last drawn on an input surface, in degrees.  This can be useful for\n"
00997           "constructing filenames for a series of images differing primarily by their\n"
00998           "orientations.  The value is only guaranteed to be current during a call\n"
00999           "to the plot command.\n\n"
01000 
01001           "Obviously, one might also wish to include positions, disparities, etc., in\n"
01002           "filenames, but rather than adding new parameters for each such possibility,\n"
01003           "the command language should probably be extended to be able to access all\n"
01004           "such quantities directly.  Such support has not yet been provided because\n"
01005           "the command language is not yet sufficient to convert the angle in radians\n"
01006           "to a clean integer value in degrees.");
01007   SETFN_DEFINE2(current_object_angle,read_only_param_setfn2);
01008  
01009   PARAM_LL(PARAM_DOUBLE,world_size_scale,&world_size_scale,0,
01010           "Scale of world model relative to the size of the retinal ganglia.  Only\n"
01011           "used when layers_pereye>0.  In such cases, it can be useful for the world\n"
01012           "to have a higher resolution than the network input in order to avoid aliasing\n"
01013           "effects for operations like rotation of image input.");
01014   SETFNOBJ_DEFINE2(this,world_size_scale,double_blur_setfn2);
01015 
01016   PARAM_NN(PARAM_STRING,default_region,&default_region,
01017           "The name of a region to use as the default for commands expecting\n"
01018           "a single region, like plot_unit, plot_unit_range, and define_region.\n"
01019           "This default is used as the <region> for such commands when no non-empty\n"
01020           "<region> is specified in their arguments.  Also used as the default\n"
01021           "<target> for commands expecting <source> and <target> regions, such as\n"
01022           "connect_region.  Every time define_region is called, it changes the\n"
01023           "value of this parameter to be the <name> of the newly-defined region.");
01024 
01025   PARAM_NN(PARAM_STRING,default_region_command,&default_region_command,
01026           "Command that will be used to construct a default region, if not has yet\n"
01027           "been defined when init_network is called.  Usually this will be\n"
01028           "one or more define_region calls with options.");
01029 
01030   PARAM_A(blackboard.lookup_map("::Region"),"default_command",string(""),,
01031           "Default command to be executed after a region of this type is created.");
01032 
01033 
01034   
01035   /*       Region-type-specific defaults      */
01036   
01037   BlackboardType* typedefaults = blackboard.lookup_map("::Region").new_child(".defaults",true);
01038   
01039   /* Automatically define the lateral weights for LISSOM maps.  The
01040      weight specifications here should also take the various
01041      parameters like preset_lat_wts into account, or provide
01042      alternatives to them. */
01043   (* typedefaults->new_child("LISSOM",true))
01044     .set_local("default_command",
01045                string("exec 'connect_region name=LateralExcitatory target=${default_region} source=${default_region}"
01046                       "        size_scale=1.0 Blur_CircularRandom ::Region::${default_region}::exc_rad' "
01047                       "     'connect_region name=LateralInhibitory target=${default_region} source=${default_region}"
01048                       "        size_scale=1.0 Blur_CircularRandom ::Region::${default_region}::inh_rad' "))
01049     .set_local("activity_threshold",1.0E-09);
01050   
01051   (* typedefaults->new_child("Retina",true))
01052     .set_local("activity_threshold",1.0/(Math::e*Math::e));
01053   
01054   (* typedefaults->new_child("Convolution",true))
01055     .set_local("activity_threshold",1.0/(Math::e*Math::e));
01056 }
01057 
01058 
01059 
01061 void Eyes::advance_iteration_counter(int old_t, int new_t)
01062 {
01063   int i;
01064   for (i=old_t; i<new_t; i++) {
01065     hooklists_run_list(before_input,i,True);
01066 //  hooklists_run_list(after_presentation,i,True);
01067     hooklists_run_list(after_learning,i,True);
01068   }
01069 }
01070 
01071 
01072 
01073 /******************************************************************************/
01074 /* Commands                                                                   */
01075 /******************************************************************************/
01076 
01077 
01079 template <class InContainer, class OutContainer>
01080 class ParameterizedThreshold : public SequenceTransform::OneD<InContainer,OutContainer> {
01081 public:
01082   typedef typename InContainer::value_type value_type;
01083 
01087   ParameterizedThreshold(const ParamMap& params_) : params(params_) { }
01088   
01089   virtual void operator() (const InContainer& in, OutContainer& out) const {
01090     const double threshold        = params.get_with_default("activity_threshold", -1.0);
01091     const double low_bound        = params.get_with_default("activity_lbound",     2.0);
01092     const double upp_bound        = params.get_with_default("activity_ubound",    -1.0);
01093     
01094     if (threshold>=0.0) Generic::lower_threshold(MSEQ(in),MBEGIN(out),threshold,0.0);
01095     if (low_bound<=1.0) Generic::lower_threshold(MSEQ(in),MBEGIN(out),low_bound,low_bound);
01096     if (upp_bound>=0.0) Generic::upper_threshold(MSEQ(in),MBEGIN(out),upp_bound,upp_bound);
01097   }
01098 
01099 private:
01100   const ParamMap& params;
01101 };
01102 
01103 
01104 cmdstat Eyes::cmd_define_region( CMD_ARGS )
01105 {
01106   CMD_ARG_PARAMS(define_region);
01107   
01108   if (!has_default_region()) update_default_values();
01109 
01110   const string name             = arglist.next(argparams.get_with_default("name",string("")));
01111   const string type             = argparams.get_with_default("type",string(""));
01112   const int    height           = argparams.get_with_default("height",1);
01113   const int    width            = argparams.get_with_default("width",1);
01114   const double xoffset          = argparams.get_with_default("xoffset",0.5);
01115   const double yoffset          = argparams.get_with_default("yoffset",0.5);
01116   typedef ParameterizedThreshold<NeuralRegion::ActivityMatrix,NeuralRegion::ActivityMatrix> ThresholdActfn;
01117     
01118   const NeuralRegion::Dimensions dims =
01119     NeuralRegion::Dimensions(height,width,xoffset,yoffset);
01120 
01121   
01122   if (name=="") {
01123     message(Msg::Error,"A <name> is required; no region defined");
01124     return CMD_PARAMETER_ERROR;
01125   }
01126 
01127   /* Use remaining arguments to set region-specific parameters */
01128   BlackboardType&  region_params = blackboard.lookup_map("::Region");
01129   BlackboardType*  new_params    = &(region_params.lookup_map(name,false));
01130   if (new_params==&region_params) /* If no parameters yet defined, make a new set */
01131     new_params = region_params.new_child(name,true);
01132   new_params->merge(blackboard.lookup_map("::Region::.defaults::"+type),false);
01133   new_params->set_local("type",type)
01134     .set_local("height",height).set_local("width", width)
01135     .set_local("xoffset",xoffset).set_local("yoffset",yoffset);
01136   cmdparams_set(*new_params,arglist,true,false,false);
01137   
01138 
01140   if (type=="LISSOM") 
01141     /* Note that this call depends on the value of the member variable initialize_weights */
01142     neuralregions.new_manager(*LissomMap_create(name,dims,initialize_weights,new_params),
01143                               new_params);
01144 #if 0
01145   else if (type=="OBJ-LISSOM") 
01146     /* Note that this call depends on the value of the member variable initialize_weights */
01147     neuralregions.new_manager(*ObjLissomMap_create(name,dims,initialize_weights,new_params),
01148                               new_params);
01149 #endif
01150   else if (type=="Retina") {
01151     const double size_scale = argparams.get_with_default("size_scale",1.0);
01152     neuralregions.new_manager(*new retina_type(name,dims,new ThresholdActfn(*new_params),
01153                                                size_scale),
01154                               new_params);
01155     /* The nominal_width is not the same as the actual width, because
01156        ganglion-centered coordinates are used.  That way coordinates
01157        will be the same regardless of whether a Convolution layer
01158        (ganglion) is used or not.
01159 
01160        This code should probably be replaced with something making
01161        fewer assumptions about the network configuration, i.e.,
01162        assuming that the following formulas will always be correct.
01163        Meanwhile, the nominal_width and height should only be used in
01164        other parts of the code for constructing defaults, because in
01165        some configurations it will not be meaningful.
01166     */
01167     const double nominal_width  = (dims.width +2*(dims.xoffset-0.5))/world_size_scale;
01168     const double nominal_height = (dims.height+2*(dims.yoffset-0.5))/world_size_scale;
01169     permanent_contents.define(name,nominal_height,nominal_width);
01170     temporary_contents.define(name,nominal_height,nominal_width);
01171   }
01172   else if (type=="Convolution")
01173     neuralregions.new_manager(*new FixedWtRegion(name,dims,new ThresholdActfn(*new_params)),
01174                               new_params);
01175   else {
01176     message(Msg::Error,"Unknown <type>: "+type+"; no region defined");
01177     return CMD_PARAMETER_ERROR;
01178   }
01179 
01180   /* Set this region as the new default and call any default_command needed */
01181   default_region = name;
01182   const string default_command=new_params->get_with_default("default_command",string());
01183   if (!default_command.empty()) cmddefs_exec_str(default_command);
01184 
01185   
01186   CMD_ARG_ASSERT_EMPTY;
01187   return CMD_NO_ERROR;
01188 }
01189 
01190 
01192 std::ostream& operator<<(std::ostream &s, const NeuralRegion::Dimensions& d)
01193 {
01194   s << "height="   << d.height
01195     << " width="   << d.width
01196     << " xoffset=" << d.xoffset
01197     << " yoffset=" << d.yoffset;
01198   return s;
01199 }
01200 
01201 
01202 // Needs to be extended to connect a NeuralRegion with a RetinalObject (i.e. a WorldView);
01203 // right now that connection is implicit and very shaky.
01204 cmdstat Eyes::cmd_connect_region( CMD_ARGS )
01205 {
01206   CMD_ARG_PARAMS(connect_region);
01207 
01208   if (!has_default_region()) update_default_values();
01209 
01210   const string default_name     = "Afferent";
01211   const string specified_name   = argparams.get_with_default("name",string(""));
01212   const string name             = (specified_name!=""? specified_name : default_name);
01213   
01214   const string specified_target = argparams.get_with_default("target",string(""));
01215   const string targetstr        = (specified_target!=""? specified_target : default_region);
01216   NeuralRegionManager* target   = neuralregions.getptr(targetstr);
01217   
01218   const string sourcestr        = argparams.get_with_default("source",string(""));
01219   NeuralRegionManager* source   = neuralregions.getptr(sourcestr);
01220 
01221   const string sourcespec       = argparams.get_with_default("sourcespec",string(""));
01223   const double size_scale       = (size_scale_override>=0? size_scale_override :
01224                                    argparams.get_with_default("size_scale",1.0));
01225 
01228   const int    connectionnum    = String::numeric_extension<int>(targetstr);
01229   
01230   if (!target) {
01231     ipc_notify(IPC_ONE,IPC_ERROR, "Could not locate <target> region %s; no connection defined",targetstr.c_str());
01232     return CMD_PARAMETER_ERROR;
01233   }
01234   else if (!target->internalregion()) {
01235     ipc_notify(IPC_ONE,IPC_ERROR, "The <target> region %s cannot accept incoming connections",targetstr.c_str());
01236     return CMD_PARAMETER_ERROR;
01237   }
01238 
01239   /* Creates each set of initial weights */
01240   KernelFactoryWrapper kfw(kernel_factory,arglist,connectionnum);
01241 
01242   /* Abort if connection matrix is empty */
01243   if (!mat::size(kfw(size_scale))) {
01244     message(Msg::Error,"Empty connection matrix; no connection defined");
01245     return CMD_PARAMETER_ERROR;
01246   }
01247     
01248   /* Create source region */
01249   if (sourcespec!="") {
01250     const NeuralRegion::Dimensions dims = target->internalregion()->input_dimensions(kfw,size_scale);
01251     const string command = "define_region name="+sourcestr+" "+String::stringrep(dims)+" "+sourcespec;
01252     cmddefs_exec_str(command);
01253     source = neuralregions.getptr(sourcestr);
01254   }
01255   
01256   if (!source) {
01257     ipc_notify(IPC_ONE,IPC_ERROR, "The <source> region %s does not exist; no connection defined",sourcestr.c_str());
01258     return CMD_PARAMETER_ERROR;
01259   }
01260 
01261   /* Create this set of connections */
01262   target->add_input(name,*source,kfw,size_scale);
01263   
01264   return CMD_NO_ERROR;
01265 }
01266 
01267 
01268 
01270 cmdstat Eyes::cmd_uninit_network( CMD_UNUSED_ARGS )
01271 {  uninit();  return CMD_NO_ERROR;  }
01272 
01273 
01275 void Eyes::update_default_values()
01276 {
01277   int oldval=cmdparam_changes_verbose;
01278   cmdparam_changes_verbose=False;
01279   params_update_all_default_values();
01280   cmdparam_changes_verbose=oldval;
01281 }
01282 
01283 
01284 
01285 cmdstat Eyes::cmd_init_network( CMD_ARGS )
01286 {
01287   CMD_ARG_PARAMS(init_network);
01288   cmdparam_changes_verbose = False;
01289 
01290   /* Since this command can be called automatically in different contexts,
01291      ensure that we always use the root set of parameters */
01292   cmddefs_exec_str("select_param_set ::");
01293   
01294   /* Sets member variable for use in define_region */
01295   initialize_weights = argparams.get_with_default("initialize",True);
01296 
01297   /* Reset master defaults for parameters and variables */
01298   iteration=0;
01299 
01300   update_default_values();
01301   
01302   /* Check parameters against compilation limits, etc. */
01303   if (params_check_all() != 0) {
01304     const Tristate interactive = blackboard.get_with_default("interactive",True);
01305     if (interactive) {
01306       ipc_notify(IPC_ONE,IPC_WARNING, "init_network failed due to parameter problem; fix message(s) above and try again");
01307       return CMD_PARAMETER_ERROR;
01308     }
01309     else
01310       ipc_exit(IPC_EXIT_PARAM_VALUE_ERROR, "Parameter problem (see message(s) above)");
01311   }
01312 
01313   /* Exercise random number generator differently on each PE to help
01314      ensure that noise is uncorrelated */
01315   shuffled_rand_reset();
01316   for(int i=0; i < 500+MyPE; i++)
01317     ShuffledRandom<double>::plain_rand();
01318 
01319   init();
01320 
01321   /* Declare initialization officially complete */
01322   ::network_initialized = True;
01323   cmddefs_declare_prereq_status( "init_network", CMD_NO_ERROR );
01324  
01325   /* Iteration 0 is used to make sure everything is initialized properly */
01326   argparams.set_local("tend",0).set_local("learning",False);
01327   training(arglist,argparams);
01328 
01329   /* Erase effect of running the test iteration */
01330   reset();
01331   
01332   /* One PE prints out final values of starting params, for reference */
01333   if (AMPARENTPE) cmddefs_exec_str("save_params");
01334   ipc_notify(IPC_ONE,IPC_STD, "Current parameters saved to .params file; future changes will be reported");
01335   /* Now that a listing is on file, report changes to params */
01336   cmdparam_changes_verbose = True; 
01337 
01338   cmddefs_exec_str("select_param_set");
01339   
01340   return CMD_NO_ERROR;
01341 }
01342 
01343 
01344 
01345 #define PROGRESS_REPORT_NEEDED(last_msg_time)                                  \
01346 (progress_reports && (time(NULL)-(last_msg_time) >= progress_report_interval))
01347 
01348 
01349 
01351 cmdstat Eyes::cmd_training( CMD_ARGS )
01352 {
01353   CMD_ARG_PARAMS(training);
01354   return training(arglist,argparams);
01355 }
01356 
01357 cmdstat Eyes::training(StringArgs& arglist, const ParamMap& argparams)
01358 {
01359   const bool incremental = (arglist.top(string(""))[0] == '+');
01360   const int  tend        = arglist.next(argparams.get_with_default("tend",1))
01361                            + (incremental? iteration : 0);
01362   const bool learning    = argparams.get_with_default("learning",True);
01363   const int  display     = argparams.get_with_default("display",1);
01364   const bool ess_h_only  = argparams.get_with_default("essential_training_hooks_only",False);
01365                            
01366   time_t last_msg_time = time(NULL);
01367   
01368   if (tend-startt>1) {
01369     if (learning)
01370       ipc_notify(IPC_ONE,IPC_STD,"Training until iteration %d", tend);
01371     else if (iteration!=0) /* Zeroth iteration is for housekeeping */
01372       ipc_notify(IPC_ONE,IPC_STD,"Testing until iteration %d", tend);
01373   }
01374 
01375   /* Main iteration loop */
01376   for(iteration=startt; iteration <= tend; iteration++) {
01377     ipc_barrier(); 
01378 
01379     if (PROGRESS_REPORT_NEEDED(last_msg_time)) {
01380       last_msg_time = time(NULL);
01381       ipc_notify(IPC_ONE,IPC_STD,"%s has reached iteration %06d, %.24s",
01382                  (learning ? "Training" : "Testing"),iteration,ctime(&last_msg_time));
01383     }
01384 
01385     /* Run any hooks needed before input is presented. */
01386     hooklists_run_list(before_input,iteration,ess_h_only);
01387     
01388 
01389     next();
01390 #ifdef PRINT_TIME_PER_ITERATION
01391     clock_t time_before_iteration = clock();
01392 #endif
01393     
01394     activate(permanent_contents,argparams);
01395     
01396 #ifdef PRINT_TIME_PER_ITERATION
01397     ipc_log(IPC_ONE,"Iteration %06d took %04d milliseconds",
01398             iteration,(int)((clock()-time_before_iteration)*1000.0/CLOCKS_PER_SEC));
01399 #endif
01400  
01401     hooklists_run_list(after_learning,iteration,ess_h_only);
01402     if (display && iteration%display==0)
01403       cmddefs_exec_str("plot");
01404   }
01405   startt = iteration; /* Set the startt to the last iteration. */
01406   iteration--; /* Make the declared iteration be the one last finished */
01407 
01408   CMD_ARG_ASSERT_EMPTY;  
01409 
01410   return CMD_NO_ERROR;
01411 }
01412 
01413 
01414 
01415 cmdstat Eyes::cmd_testing( CMD_ARGS )
01416 {
01417   CMD_ARG_PARAMS(testing);
01418   return training(arglist,argparams);
01419 }
01420 
01421 
01422 
01423 cmdstat Eyes::cmd_step( CMD_ARGS )
01424 {
01425   /* Converts specified increment into a tend specification for cmd_training */
01426   CMD_ARG_PARAMS(step);
01427   argparams.set_local("tend", iteration+arglist.next(1));
01428   return training(arglist,argparams);
01429 }
01430 
01431 
01432 
01433 cmdstat Eyes::cmd_input_define_generator( CMD_ARGS )
01434 {
01435   CMD_ARG_LIST;
01436   // Should pass arglist by reference all the way down, to detect unused args
01437   return namedgenerators.create(arglist);
01438 }
01439 
01440 
01441 cmdstat Eyes::cmd_input_define_convolution( CMD_ARGS )
01442 {
01443   CMD_ARG_PARAMS(input_define_convolution);
01444 
01445   if (default_input_target=="")
01446     default_input_target=ensure_default_region();
01447 
01448   const string parent     = arglist.next(argparams.get_with_default("parent",string("")));
01449   const double size_scale = argparams.get_with_default("default_afferent_size_scale",1.0);
01450   const int    number     = argparams.get_with_default("num_eyes",1);
01451   const int    numlayers  = argparams.get_with_default("layers_pereye",1);
01452 
01453   if (parent!="" && parent!="All")
01454     define_input_pathway( default_input_target, parent, arglist, size_scale, numlayers );
01455   else for (int e=0; e<number; e++)
01456     define_input_pathway( default_input_target, "Eye"+String::stringrep(e), arglist, size_scale, numlayers );
01457 
01458   input_define_convolution_in_use=true;
01459   
01460   CMD_ARG_ASSERT_EMPTY;
01461   return CMD_NO_ERROR;
01462 }
01463 
01464 
01465 
01466 cmdstat Eyes::cmd_input_clear( CMD_ARGS )
01467 {
01468   CMD_ARG_PARAMS(input_clear);
01469   const string parent = arglist.next(argparams.get_with_default("parent",string("")));
01470   const string name   = argparams.get_with_default("name",string(""));
01471   temporary_contents.remove_object(parent,name);
01472   ipc_notify(IPC_ONE,IPC_VERBOSE,"Cleared temporary objects");
01473   CMD_ARG_ASSERT_EMPTY;
01474   return CMD_NO_ERROR;
01475 }
01476 
01477 
01478 
01479 cmdstat Eyes::cmd_input_draw( CMD_ARGS )
01480 {
01481   CMD_ARG_PARAMS(input_draw);
01482   const string spec_name = argparams.get_with_default("name",string(""));
01483   const string name      = (spec_name != "") ? spec_name : "input_draw";
01484   
01485   // Should pass arglist by reference all the way down, to detect unused args
01486   if (temporary_contents.create_object(arglist,name,permanent_contents, false) != 0) {
01487     ipc_notify(IPC_ONE,IPC_ERROR,"Could not draw input object");
01488     return CMD_PARAMETER_ERROR;
01489   }
01490 
01491   return CMD_NO_ERROR;
01492 }
01493 
01494 
01495 
01496 cmdstat Eyes::cmd_input_define( CMD_ARGS )
01497 {
01498   CMD_ARG_PARAMS(input_define);
01499 
01500   if (!permanent_contents.has_been_defined())
01501     cmd_input_define_convolution();
01502   
01503   const string name = arglist.next(argparams.get_with_default("name",string("")));
01504   
01505   if (permanent_contents.create_object(arglist,name,permanent_contents) != 0)
01506     ipc_notify(IPC_ONE,IPC_ERROR,"Could not define input object");
01507   
01508   return CMD_NO_ERROR;
01509 }
01510 
01511 
01512 
01513 cmdstat Eyes::cmd_input_present( CMD_ARGS )
01514 {
01515   CMD_ARG_PARAMS(input_present);
01516   const int  plot   = argparams.get_with_default("display",1);
01517   const bool reset  = argparams.get_with_default("reset",False);
01518 
01519   if (reset) {
01520     Eyes::activate(permanent_contents,argparams);
01521     ipc_notify(IPC_ONE,IPC_VERBOSE,"Reset contents of retina");
01522   }
01523   else {
01524     Eyes::activate(temporary_contents,argparams);
01525     if (plot && presentation%plot==0) cmddefs_exec_str("plot");
01526     ipc_notify(IPC_ONE,IPC_VERBOSE,"Presented currently-defined temp input");
01527   }
01528   
01529   // Currently ignores extra arguments, so same arguments
01530   // can be passed to both input_draw and input_present
01531   //   CMD_ARG_ASSERT_EMPTY;
01532 
01533   return CMD_NO_ERROR;
01534 }
01535 
01536 
01537 
01539 cmdstat Eyes::cmd_input_present_object( CMD_ARGS )
01540 {
01541   cmdstat status=CMD_NO_ERROR;
01542 
01543   cmd_input_clear();
01544   status = cmd_input_draw(CMD_CALL_ARGS);
01545   if (status >= 0) cmd_input_present(CMD_CALL_ARGS); // Hack?  (Arguments are shared with two commands)
01546 
01547   return status;
01548 }
01549 
01550 
01551 
01552 cmdstat Eyes::cmd_input_print( CMD_ARGS )
01553 {
01554   CMD_ARG_PARAMS(input_print);
01555 
01556   const string name   = arglist.next(argparams.get_with_default("name",string("")));  
01557   const string parent = arglist.next(argparams.get_with_default("parent",string("")));  
01558 
01559   /* This may not stay here, but is useful for now */
01560   if (name == "" && parent == "")
01561     for (neuralregions_type::const_iterator e=neuralregions.begin(); e!=neuralregions.end(); e++) {
01562       const string ename = (*e).first;
01563       ipc_notify(IPC_ONE,IPC_REQUESTED,ename.c_str());
01564     }
01565 
01566   permanent_contents.print_object(parent,name);
01567   temporary_contents.print_object(parent,name);
01568   CMD_ARG_ASSERT_EMPTY;
01569   return CMD_NO_ERROR;
01570 }
01571 
01572 
01573 
01574 cmdstat Eyes::cmd_input_reset( CMD_ARGS )
01575 {
01576   CMD_ARG_PARAMS(input_reset);
01577   const int seed = arglist.next(argparams.get_with_default("input_seed",0));
01578   Eyes::reset(seed);
01579   CMD_ARG_ASSERT_EMPTY;
01580   return CMD_NO_ERROR;
01581 }
01582 
01583 
01584 
01585 cmdstat Eyes::cmd_input_undefine( CMD_ARGS )
01586 {
01587   CMD_ARG_PARAMS(input_undefine);
01588   const string name   = arglist.next(argparams.get_with_default("name",string("")));  
01589   const string parent = arglist.next(argparams.get_with_default("parent",string("")));
01590   
01591   permanent_contents.remove_object(parent,name);
01592   CMD_ARG_ASSERT_EMPTY;
01593   return CMD_NO_ERROR;
01594 }
01595 
01596 
01597 cmdstat Eyes::cmd_load_snapshot( CMD_ARGS )
01598 {  
01599   CMD_ARG_PARAMS(load_snapshot);
01600   const int    load_snap = arglist.next(argparams.get_with_default("tend",0));
01601   const string filename  = arglist.next(argparams.get_with_default("filename",string()));
01602   const bool   verbose   = arglist.next(argparams.get_with_default("verbose",True));
01603 
01604   const int    oldipcverbosity = ipc_msg_level;
01605   const int    newipcverbosity = IPC_SUMMARY;
01606   const bool   setverbosity    = (!verbose && (ipc_msg_level > newipcverbosity));
01607 
01608   if (setverbosity)
01609     ipc_msg_level = newipcverbosity;
01610 
01611   /* Call init_network with non-essential hooks disabled and weight init skipped */
01612   if (!has_default_region())
01613     cmddefs_exec_str("init_network essential_training_hooks_only=True initialize=False");
01614   
01615   /* Make sure parameters have advanced to this iteration */
01616   ipc_notify(IPC_ONE,IPC_STD,"Advancing to iteration %d", load_snap);
01617   advance_iteration_counter(iteration,load_snap);
01618   iteration=load_snap;
01619   startt=iteration;
01620   if (!AMPARENTPE) ipc_get(&iteration, IPC_INT, 1, PARENTPE);
01621   
01622   /* Ask each region to restore its enduring state */
01623   bool restored = neuralregions.restore_state(argparams,load_snap,filename);
01624 
01625   if (restored) {
01626     /* Recreate the dynamic state (activation levels, etc.) */
01627     hooklists_run_list(before_input,load_snap,True);
01628     next(); /* Is this call necessary and/or desirable? */
01629   
01630     /* Recreate the last input */
01631     activate(permanent_contents,argparams);
01632   }
01633   
01634   ipc_barrier();  /* Synchronize all PEs */
01635 
01636   if (restored) {
01637     iteration=load_snap;
01638     ipc_notify(IPC_ONE,IPC_STD,"Changing iteration to %d",iteration);
01639     startt=iteration+1;
01640     
01641     hooklists_run_list(after_learning,load_snap,True);
01642   }
01643 
01644   if (setverbosity)
01645     ipc_msg_level=oldipcverbosity;
01646   
01647   return (restored? CMD_NO_ERROR : CMD_FILE_ERROR);
01648 }
01649 
01650 
01651 /******************************************************************************/
01652 /* Parameter changing functions                                               */
01653 /******************************************************************************/
01654 
01655 
01656 cmdstat Eyes::distribution_setfn2(const string&, Typeless&, const Typeless& requested)
01657 {
01658   int  dist = (int)requested.numericvalue();
01659   bool changed=false;
01660 
01661   cmdstat status = WorldViews::set_distribution(dist,changed);
01662 
01663   /*
01664     If objects have already been defined, overwrite them now, otherwise delay
01665     object creation until runtime to ensure that all relevant parameters
01666     have been defined.
01667   */
01668   if (changed && !permanent_contents.is_empty()) {
01669     message(Msg::Notify,"Regenerating input contents");
01670     permanent_contents.remove_object();
01671     permanent_contents.generate_default_contents();
01672   }
01673   
01674   return status;
01675 }
01676 
01677 
01678 
01679 cmdstat Eyes::blur_type_setfn2(const string& name, Typeless& existing, const Typeless& requested)
01680 {
01681   const bool differs = (existing != requested);
01682   int newvalue = (int)requested.numericvalue();
01683   
01684   if (newvalue<0 || newvalue>kernel_factory.max_blur_type) {
01685     ipc_notify(IPC_ONE,IPC_WARNING,"No %s of %d is defined",name.c_str(),newvalue);
01686     return CMD_PARAMETER_ERROR;
01687   }
01688 
01689   existing.set(requested);
01690   if (input_define_convolution_in_use &&
01691       permanent_contents.has_been_defined() && differs) {
01692     message(Msg::Notify,"Regenerating input pathways");
01693     cmd_input_define_convolution();
01694   }
01695   
01696   return CMD_NO_ERROR;
01697 }
01698 
01699 
01700 
01701 cmdstat Eyes::double_blur_setfn2(const string&, Typeless& existing, const Typeless& requested)
01702 {
01703   const bool differs = (existing != requested);
01704   existing.set(requested);
01705   if (input_define_convolution_in_use &&
01706       permanent_contents.has_been_defined() && differs) {
01707     message(Msg::Notify,"Regenerating input pathways");
01708     cmd_input_define_convolution();
01709   }
01710 
01711   return CMD_NO_ERROR;
01712 }
01713 
01714 
01715 
01716 cmdstat Eyes::inputs_pereye_setfn2(const string&, Typeless& existing, const Typeless& requested)
01717 {
01718   const bool differs = (existing != requested);
01719   existing.set(requested);
01720 
01721   if (permanent_contents.has_been_defined() && differs) {
01722     message(Msg::Notify,"Regenerating input contents");
01723     permanent_contents.remove_object();
01724     permanent_contents.generate_default_contents();
01725   }
01726 
01727   return CMD_NO_ERROR;
01728 }
01729 
01730 
01732 cmdstat Eyes::exc_rad_setfn2(const string&, Typeless& existing, const Typeless& requested)
01733 {
01734   const CmdParamStringParser sp(blackboard);
01735   if (::network_initialized)
01736     blackboard.set_matching(sp,"::Region::*::exc_rad", requested.stringrep(),true,true,true);
01737   existing.set(requested);
01738   return CMD_NO_ERROR;
01739 }
01740 
01741 
01742 
01743 /******************************************************************************/
01744 /* Global points of entry                                                     */
01745 /******************************************************************************/
01746 
01748 Inputs& Inputs::global_entry()
01749 {
01750   static Eyes eyes;
01751   return eyes;
01752 }
01753 
01754 

Generated on Mon Jan 20 02:35:44 2003 for RF-LISSOM by doxygen1.3-rc2