[mlpack-svn] r10788 - mlpack/trunk/src/mlpack/core/util

fastlab-svn at coffeetalk-1.cc.gatech.edu fastlab-svn at coffeetalk-1.cc.gatech.edu
Wed Dec 14 12:37:53 EST 2011


Author: mamidon
Date: 2011-12-14 12:37:52 -0500 (Wed, 14 Dec 2011)
New Revision: 10788

Modified:
   mlpack/trunk/src/mlpack/core/util/cli.cpp
   mlpack/trunk/src/mlpack/core/util/cli.hpp
   mlpack/trunk/src/mlpack/core/util/cli_impl.hpp
Log:
Did some refactoring on CLI, fixed a potential bug.  
Also removed some references to PARAM_MODULE.



Modified: mlpack/trunk/src/mlpack/core/util/cli.cpp
===================================================================
--- mlpack/trunk/src/mlpack/core/util/cli.cpp	2011-12-14 17:23:59 UTC (rev 10787)
+++ mlpack/trunk/src/mlpack/core/util/cli.cpp	2011-12-14 17:37:52 UTC (rev 10788)
@@ -119,20 +119,18 @@
   std::string tmp = TYPENAME(bool);
   std::string path = identifier;
   std::string stringAlias = alias;
-  std::string prog_opt_id = path; // Use boost's syntax for aliasing.
+  // Must make use of boost option name syntax.
+  std::string prog_opt_id = stringAlias.length() ? path + "," + alias : path;
 
   // Deal with a required alias.
-  if (stringAlias.length()) {
-    amap_t& amap = GetSingleton().aliasValues;
-    amap[stringAlias] = path;
-    prog_opt_id = path + "," + alias;
-  }
+  AddAlias(stringAlias, path);
 
   // Add the option to boost::program_options.
   desc.add_options()(prog_opt_id.c_str(), description);
 
   // Make sure the description, etc. ends up in gmap.
   gmap_t& gmap = GetSingleton().globalValues;
+  
   ParamData data;
   data.desc = description;
   data.tname = "";
@@ -150,42 +148,113 @@
 }
 
 /*
+ * Adds an alias mapping for a given parameter.
+ *
+ * @param alias The alias we will use for the parameter.
+ * @param original The name of the actual parameter we will be mapping to.
+ */
+void CLI::AddAlias(std::string alias, std::string original) {
+  //Conduct the mapping
+  if (alias.length()) {
+    amap_t& amap = GetSingleton().aliasValues;
+    amap[alias] = original;
+  }
+}
+
+/*
  * @brief Adds a flag parameter to CLI.
  */
 void CLI::AddFlag(const char* identifier,
                  const char* description,
                  const char* alias)
 {
-  po::options_description& desc = CLI::GetSingleton().desc;
+  // Reuse functionality from add
+  Add(identifier, description, alias, false); 
 
-  std::string path = identifier;
-  std::string stringAlias = alias;
-  std::string prog_opt_id = path;
-
-  //Deal with a required alias
-  if (stringAlias.length()) {
-    amap_t& amap = GetSingleton().aliasValues;
-    amap[stringAlias] = path;
-    prog_opt_id = path + "," + alias;
-  }
-
-  // Add the option to boost::program_options.
-  desc.add_options()
-    (prog_opt_id.c_str(), po::value<bool>()->implicit_value(true), description);
-
-  // Add the proper metadata in gmap.
+  // Insert the proper metadata in gmap.
   gmap_t& gmap = GetSingleton().globalValues;
+
   ParamData data;
   data.desc = description;
   data.tname = TYPENAME(bool);
-  data.name = path;
+  data.name = std::string(identifier);
   data.isFlag = true;
   data.wasPassed = false;
 
-  gmap[path] = data;
+  gmap[data.name] = data;
 }
 
+std::string CLI::AliasReverseLookup(std::string value)
+{
+  amap_t& amap = GetSingleton().aliasValues;
+  amap_t::iterator iter;
+  for (iter = amap.begin(); iter != amap.end(); iter++)
+    if (iter->second == value) // Found our match.
+      return iter->first;
+
+  return ""; // Nothing found.
+}
+
 /**
+ * Parses the parameters for 'help' and 'info'
+ * If found, will print out the appropriate information
+ * and kill the program.
+ */
+void CLI::DefaultMessages()
+{
+  // Default help message
+  if (HasParam("help"))
+  {
+    Log::Info.ignoreInput = false;
+    PrintHelp();
+    exit(0); // The user doesn't want to run the program, he wants help.
+  }
+
+  if (HasParam("info"))
+  {
+    Log::Info.ignoreInput = false;
+    std::string str = GetParam<std::string>("info");
+
+    // The info node should always be there, but the user may not have specified
+    // anything.
+    if (str != "")
+    {
+      PrintHelp(str);
+      exit(0);
+    }
+
+    // Otherwise just print the generalized help.
+    PrintHelp();
+    exit(0);
+  }
+
+  if (GetParam<bool>("verbose"))
+  {
+    // Give [INFO ] output.
+    Log::Info.ignoreInput = false;
+  }
+
+  // Notify the user if we are debugging.  This is not done in the constructor
+  // because the output streams may not be set up yet.  We also don't want this
+  // message twice if the user just asked for help or information.
+  Log::Debug << "Compiled with debugging symbols." << std::endl;
+}
+
+/**
+ * Destroy the CLI object.  This resets the pointer to the singleton, so in case
+ * someone tries to access it after destruction, a new one will be made (the
+ * program will not fail).
+ */
+void CLI::Destroy()
+{
+  if (singleton != NULL)
+  {
+    delete singleton;
+    singleton = NULL; // Reset pointer.
+  }
+}
+
+/**
  * See if the specified flag was found while parsing.
  *
  * @param identifier The name of the parameter in question.
@@ -214,6 +283,54 @@
 }
 
 /**
+ * Hyphenate a string or split it onto multiple 80-character lines, with some
+ * amount of padding on each line.  This is used for option output.
+ *
+ * @param str String to hyphenate (splits are on ' ').
+ * @param padding Amount of padding on the left for each new line.
+ */
+std::string CLI::HyphenateString(std::string str, int padding)
+{
+  size_t margin = 80 - padding;
+  if (str.length() < margin)
+    return str;
+  std::string out("");
+  unsigned int pos = 0;
+  // First try to look as far as possible.
+  while (pos < str.length() - 1)
+  {
+    size_t splitpos;
+    // Check that we don't have a newline first.
+    splitpos = str.find('\n', pos);
+    if (splitpos == std::string::npos || splitpos > (pos + margin))
+    {
+      // We did not find a newline.
+      if (str.length() - pos < margin)
+      {
+        splitpos = str.length(); // The rest fits on one line.
+      }
+      else
+      {
+        splitpos = str.rfind(' ', margin + pos); // Find nearest space.
+        if (splitpos <= pos || splitpos == std::string::npos) // Not found.
+          splitpos = pos + margin;
+      }
+    }
+    out += str.substr(pos, (splitpos - pos));
+    if (splitpos < str.length())
+    {
+      out += '\n';
+      out += std::string(padding, ' ');
+    }
+
+    pos = splitpos;
+    if (str[pos] == ' ' || str[pos] == '\n')
+      pos++;
+  }
+  return out;
+}
+
+/**
  * Grab the description of the specified node.
  *
  * @param identifier Name of the node in question.
@@ -306,124 +423,6 @@
   Timer::Start("total_time");
 }
 
-/**
- * Parses the values given on the command line, overriding any default values.
- */
-void CLI::UpdateGmap()
-{
-  gmap_t& gmap = GetSingleton().globalValues;
-  po::variables_map& vmap = GetSingleton().vmap;
-
-  // Iterate through vmap, and overwrite default values with anything found on
-  // command line.
-  po::variables_map::iterator i;
-  for (i = vmap.begin(); i != vmap.end(); i++)
-  {
-    ParamData param;
-    if (gmap.count(i->first)) // We need to preserve certain data
-      param = gmap[i->first];
-
-    param.value = vmap[i->first].value();
-    param.wasPassed = true;
-    gmap[i->first] = param;
-  }
-}
-
-/**
- * Registers a ProgramDoc object, which contains documentation about the
- * program.
- *
- * @param doc Pointer to the ProgramDoc object.
- */
-void CLI::RegisterProgramDoc(ProgramDoc* doc)
-{
-  // Only register the doc if it is not the dummy object we created at the
-  // beginning of the file (as a default value in case this is never called).
-  if (doc != &empty_program_doc)
-    GetSingleton().doc = doc;
-}
-
-/**
- * Destroy the CLI object.  This resets the pointer to the singleton, so in case
- * someone tries to access it after destruction, a new one will be made (the
- * program will not fail).
- */
-void CLI::Destroy()
-{
-  if (singleton != NULL)
-  {
-    delete singleton;
-    singleton = NULL; // Reset pointer.
-  }
-}
-
-/**
- * Parses the parameters for 'help' and 'info'
- * If found, will print out the appropriate information
- * and kill the program.
- */
-void CLI::DefaultMessages()
-{
-  // Default help message
-  if (GetParam<bool>("help"))
-  {
-    Log::Info.ignoreInput = false;
-    PrintHelp();
-    exit(0); // The user doesn't want to run the program, he wants help.
-  }
-
-  if (HasParam("info"))
-  {
-    Log::Info.ignoreInput = false;
-    std::string str = GetParam<std::string>("info");
-
-    // The info node should always be there, but the user may not have specified
-    // anything.
-    if (str != "")
-    {
-      PrintHelp(str);
-      exit(0);
-    }
-
-    // Otherwise just print the generalized help.
-    PrintHelp();
-    exit(0);
-  }
-
-  if (GetParam<bool>("verbose"))
-  {
-    // Give [INFO ] output.
-    Log::Info.ignoreInput = false;
-  }
-
-  // Notify the user if we are debugging.  This is not done in the constructor
-  // because the output streams may not be set up yet.  We also don't want this
-  // message twice if the user just asked for help or information.
-  Log::Debug << "Compiled with debugging symbols." << std::endl;
-}
-
-/**
- * Checks that all parameters specified as required have been specified on the
- * command line.  If they havent, prints an error message and kills the program.
- */
-void CLI::RequiredOptions()
-{
-  po::variables_map& vmap = GetSingleton().vmap;
-  std::list<std::string> rOpt = GetSingleton().requiredOptions;
-
-  // Now, warn the user if they missed any required options.
-  std::list<std::string>::iterator iter;
-  for (iter = rOpt.begin(); iter != rOpt.end(); iter++)
-  {
-    std::string str = *iter;
-    if (!vmap.count(str))
-    { // If a required option isn't there...
-      Log::Fatal << "Required option --" << str.c_str() << " is undefined."
-          << std::endl;
-    }
-  }
-}
-
 /* Prints out the current hierarchy. */
 void CLI::Print()
 {
@@ -479,7 +478,6 @@
   Log::Info << std::endl;
 }
 
-
 /* Prints the descriptions of the current hierarchy. */
 void CLI::PrintHelp(std::string param)
 {
@@ -618,62 +616,62 @@
 }
 
 /**
- * Hyphenate a string or split it onto multiple 80-character lines, with some
- * amount of padding on each line.  This is used for option output.
- *
- * @param str String to hyphenate (splits are on ' ').
- * @param padding Amount of padding on the left for each new line.
- */
-std::string CLI::HyphenateString(std::string str, int padding)
+ * Registers a ProgramDoc object, which contains documentation about the
+ * program.
+ *
+ * @param doc Pointer to the ProgramDoc object.
+ */
+void CLI::RegisterProgramDoc(ProgramDoc* doc)
 {
-  size_t margin = 80 - padding;
-  if (str.length() < margin)
-    return str;
-  std::string out("");
-  unsigned int pos = 0;
-  // First try to look as far as possible.
-  while (pos < str.length() - 1)
+  // Only register the doc if it is not the dummy object we created at the
+  // beginning of the file (as a default value in case this is never called).
+  if (doc != &empty_program_doc)
+    GetSingleton().doc = doc;
+}
+
+/**
+ * Checks that all parameters specified as required have been specified on the
+ * command line.  If they havent, prints an error message and kills the program.
+ */
+void CLI::RequiredOptions()
+{
+  po::variables_map& vmap = GetSingleton().vmap;
+  std::list<std::string> rOpt = GetSingleton().requiredOptions;
+
+  // Now, warn the user if they missed any required options.
+  std::list<std::string>::iterator iter;
+  for (iter = rOpt.begin(); iter != rOpt.end(); iter++)
   {
-    size_t splitpos;
-    // Check that we don't have a newline first.
-    splitpos = str.find('\n', pos);
-    if (splitpos == std::string::npos || splitpos > (pos + margin))
-    {
-      // We did not find a newline.
-      if (str.length() - pos < margin)
-      {
-        splitpos = str.length(); // The rest fits on one line.
-      }
-      else
-      {
-        splitpos = str.rfind(' ', margin + pos); // Find nearest space.
-        if (splitpos <= pos || splitpos == std::string::npos) // Not found.
-          splitpos = pos + margin;
-      }
+    std::string str = *iter;
+    if (!vmap.count(str))
+    { // If a required option isn't there...
+      Log::Fatal << "Required option --" << str.c_str() << " is undefined."
+          << std::endl;
     }
-    out += str.substr(pos, (splitpos - pos));
-    if (splitpos < str.length())
-    {
-      out += '\n';
-      out += std::string(padding, ' ');
-    }
-
-    pos = splitpos;
-    if (str[pos] == ' ' || str[pos] == '\n')
-      pos++;
   }
-  return out;
 }
 
-std::string CLI::AliasReverseLookup(std::string value)
+/**
+ * Parses the values given on the command line, overriding any default values.
+ */
+void CLI::UpdateGmap()
 {
-  amap_t& amap = GetSingleton().aliasValues;
-  amap_t::iterator iter;
-  for (iter = amap.begin(); iter != amap.end(); iter++)
-    if (iter->second == value) // Found our match.
-      return iter->first;
+  gmap_t& gmap = GetSingleton().globalValues;
+  po::variables_map& vmap = GetSingleton().vmap;
 
-  return ""; // Nothing found.
+  // Iterate through vmap, and overwrite default values with anything found on
+  // command line.
+  po::variables_map::iterator i;
+  for (i = vmap.begin(); i != vmap.end(); i++)
+  {
+    ParamData param;
+    if (gmap.count(i->first)) // We need to preserve certain data
+      param = gmap[i->first];
+
+    param.value = vmap[i->first].value();
+    param.wasPassed = true;
+    gmap[i->first] = param;
+  }
 }
 
 // Add help parameter.

Modified: mlpack/trunk/src/mlpack/core/util/cli.hpp
===================================================================
--- mlpack/trunk/src/mlpack/core/util/cli.hpp	2011-12-14 17:23:59 UTC (rev 10787)
+++ mlpack/trunk/src/mlpack/core/util/cli.hpp	2011-12-14 17:37:52 UTC (rev 10788)
@@ -331,15 +331,6 @@
   JOIN(__io_option_flag_object_, __COUNTER__) (ID, DESC, ALIAS);
   /** @endcond */
 
-  /**
-   * Define a module.
-   *
-   * @param ID Name of the module.
-   * @param DESC Description of the module (1-2 sentences).
-   */
-  #define PARAM_MODULE(ID, DESC) static mlpack::io::Option<int> \
-      JOIN(io_option_module_dummy_object_, __COUNTER__) (true, 0, ID, DESC, \
-      NULL);
 #else
   // We have to do some really bizarre stuff since __COUNTER__ isn't defined.  I
   // don't think we can absolutely guarantee success, but it should be "good
@@ -354,16 +345,6 @@
       JOIN(__io_option_flag_object_, __LINE__) (ID, DESC, ALIAS);
   /** @endcond */
 
-  /**
-   * Define a module.
-   *
-   * @param ID Name of the module.
-   * @param DESC Description of the module (1-2 sentences).
-   */
-  #define PARAM_MODULE(ID, DESC) static mlpack::io::Option<int> \
-      JOIN(JOIN(io_option_dummy_object_, __LINE__), mod) (true, 0, ID, DESC, \
-      NULL);
-
 #endif
 
 /**
@@ -384,7 +365,7 @@
 }; // namespace io
 
 /**
- * Aids in the extensibility of OptionsHierarchy by focusing the potential
+ * Aids in the extensibility of CLI by focusing potential
  * changes into one structure.
  */
 struct ParamData
@@ -440,9 +421,6 @@
  * optimizer (mlpack::optimizers::L_BFGS):
  *
  * @code
- * PARAM_MODULE("lbfgs", "Options for the L-BFGS optimizer, which uses a "
- *    "back-tracing line search to determine the step size to take.");
- *
  * PARAM_DOUBLE("armijo_constant", "Controls the accuracy of the line search "
  *    "routine for determining the Armijo condition.", "lbfgs", 1e-4);
  * PARAM_DOUBLE("min_step", "The minimum step of the line search.", "lbfgs",
@@ -570,22 +548,21 @@
   static void AddFlag(const char* identifier,
                       const char* description,
                       const char* alias = "");
-
+  
   /**
-   * See if the specified flag was found while parsing.
-   *
-   * @param identifier The name of the parameter in question.
-   */
-  static bool HasParam(const char* identifier);
-
-
-  /**
    * Parses the parameters for 'help' and 'info'.
    * If found, will print out the appropriate information and kill the program.
    */
   static void DefaultMessages();
 
   /**
+   * Destroy the CLI object.  This resets the pointer to the singleton, so in
+   * case someone tries to access it after destruction, a new one will be made
+   * (the program will not fail).
+   */
+  static void Destroy();
+
+  /**
    * Grab the value of type T found while parsing.  You can set the value using
    * this reference safely.
    *
@@ -603,16 +580,36 @@
   static std::string GetDescription(const char* identifier);
 
   /**
-   * Searches for unqualified paramters; when one is found, the default module
-   * is prepended onto it (if necessary).
+   * Retrieve the singleton.
    *
-   * @param argc The number of parameters.
-   * @param argv 2D array of the parameter strings.
-   * @return Valid modified strings.
+   * Not exposed to the outside, so as to spare users some ungainly
+   * x.GetSingleton().foo() syntax.
+   *
+   * In this case, the singleton is used to store data for the static methods,
+   * as there is no point in defining static methods only to have users call
+   * private instance methods
+   *
+   * @return The singleton instance for use in the static methods.
    */
-  static std::vector<std::string> InsertDefaultModule(int argc, char** argv);
+  static CLI& GetSingleton();
+  
+  /**
+   * See if the specified flag was found while parsing.
+   *
+   * @param identifier The name of the parameter in question.
+   */
+  static bool HasParam(const char* identifier);
 
   /**
+   * Hyphenate a string or split it onto multiple 80-character lines, with some
+   * amount of padding on each line.  This is ued for option output.
+   *
+   * @param str String to hyphenate (splits are on ' ').
+   * @param padding Amount of padding on the left for each new line.
+   */
+  static std::string HyphenateString(std::string str, int padding);
+
+  /**
    * Parses the commandline for arguments.
    *
    * @param argc The number of arguments on the commandline.
@@ -638,36 +635,6 @@
   static void PrintHelp(std::string param="");
 
   /**
-   * Checks that all required parameters have been specified on the command
-   * line.  If any have not been specified, an error message is printed and the
-   * program is terminated.
-   */
-  static void RequiredOptions();
-
-  /**
-   * Cleans up input pathnames, rendering strings such as /foo/bar
-   * and foo/bar/ equivalent inputs.
-   *
-   * @param str Input string.
-   * @return Sanitized string.
-   */
-  static std::string SanitizeString(const char* str);
-
-  /**
-   * Hyphenate a string or split it onto multiple 80-character lines, with some
-   * amount of padding on each line.  This is ued for option output.
-   *
-   * @param str String to hyphenate (splits are on ' ').
-   * @param padding Amount of padding on the left for each new line.
-   */
-  static std::string HyphenateString(std::string str, int padding);
-
-  /**
-   * Parses the values given on the command line, overriding any default values.
-   */
-  static void UpdateGmap();
-
-  /**
    * Registers a ProgramDoc object, which contains documentation about the
    * program.  If this method has been called before (that is, if two
    * ProgramDocs are instantiated in the program), a fatal error will occur.
@@ -677,13 +644,6 @@
   static void RegisterProgramDoc(io::ProgramDoc* doc);
 
   /**
-   * Destroy the CLI object.  This resets the pointer to the singleton, so in
-   * case someone tries to access it after destruction, a new one will be made
-   * (the program will not fail).
-   */
-  static void Destroy();
-
-  /**
    * Destructor.
    */
   ~CLI();
@@ -724,6 +684,14 @@
 
  private:
 
+  /*
+   * Maps a given alias to a given parameter.
+   *
+   * @param alias The name of the alias to be mapped.
+   * @param original The name of the parameter to be mapped.
+   */
+  static void AddAlias(std::string alias, std::string original);
+
   /**
    * Returns an alias, if given the name of the original.
    *
@@ -732,21 +700,7 @@
    * @return The alias associated with value.
    */
   static std::string AliasReverseLookup(std::string value);
-
-  /**
-   * Retrieve the singleton.
-   *
-   * Not exposed to the outside, so as to spare users some ungainly
-   * x.GetSingleton().foo() syntax.
-   *
-   * In this case, the singleton is used to store data for the static methods,
-   * as there is no point in defining static methods only to have users call
-   * private instance methods
-   *
-   * @return The singleton instance for use in the static methods.
-   */
-  static CLI& GetSingleton();
-
+ 
 #ifdef _WIN32
   /**
    * Converts a FILETIME structure to an equivalent timeval structure.
@@ -757,6 +711,27 @@
 #endif
 
   /**
+   * Checks that all required parameters have been specified on the command
+   * line.  If any have not been specified, an error message is printed and the
+   * program is terminated.
+   */
+  static void RequiredOptions();
+
+  /**
+   * Cleans up input pathnames, rendering strings such as /foo/bar
+   * and foo/bar/ equivalent inputs.
+   *
+   * @param str Input string.
+   * @return Sanitized string.
+   */
+  static std::string SanitizeString(const char* str);
+
+  /**
+   * Parses the values given on the command line, overriding any default values.
+   */
+  static void UpdateGmap();
+
+  /**
    * Make the constructor private, to preclude unauthorized instances.
    */
   CLI();

Modified: mlpack/trunk/src/mlpack/core/util/cli_impl.hpp
===================================================================
--- mlpack/trunk/src/mlpack/core/util/cli_impl.hpp	2011-12-14 17:23:59 UTC (rev 10787)
+++ mlpack/trunk/src/mlpack/core/util/cli_impl.hpp	2011-12-14 17:37:52 UTC (rev 10788)
@@ -38,14 +38,11 @@
   po::options_description& desc = CLI::GetSingleton().desc;
   std::string path = identifier;
   std::string stringAlias = alias;
-  std::string prog_opt_id = path;
+  // Must make use of boost syntax here.
+  std::string prog_opt_id = stringAlias.length() ? path + "," + alias : path;
 
   // Add the alias, if necessary
-  if (stringAlias.length()) {
-    amap_t& amap = GetSingleton().aliasValues;
-    amap[stringAlias] = path;
-    prog_opt_id = path + "," + alias;
-  }
+  AddAlias(stringAlias, path);
 
   // Add the option to boost program_options.
   desc.add_options()
@@ -62,6 +59,7 @@
   data.tname = TYPENAME(T);
   data.value = boost::any(tmp);
   data.wasPassed = false;
+  
   gmap[path] = data;
 
   // If the option is required, add it to the required options list.




More information about the mlpack-svn mailing list