[mlpack-svn] r10774 - in mlpack/trunk/src/mlpack: . core core/data core/math core/tree core/util methods/gmm tests
fastlab-svn at coffeetalk-1.cc.gatech.edu
fastlab-svn at coffeetalk-1.cc.gatech.edu
Wed Dec 14 07:44:53 EST 2011
Author: rcurtin
Date: 2011-12-14 07:44:53 -0500 (Wed, 14 Dec 2011)
New Revision: 10774
Added:
mlpack/trunk/src/mlpack/core/util/
mlpack/trunk/src/mlpack/core/util/CMakeLists.txt
mlpack/trunk/src/mlpack/core/util/cli.cpp
mlpack/trunk/src/mlpack/core/util/cli.hpp
mlpack/trunk/src/mlpack/core/util/cli_deleter.cpp
mlpack/trunk/src/mlpack/core/util/cli_deleter.hpp
mlpack/trunk/src/mlpack/core/util/cli_impl.hpp
mlpack/trunk/src/mlpack/core/util/log.cpp
mlpack/trunk/src/mlpack/core/util/log.hpp
mlpack/trunk/src/mlpack/core/util/nulloutstream.hpp
mlpack/trunk/src/mlpack/core/util/option.cpp
mlpack/trunk/src/mlpack/core/util/option.hpp
mlpack/trunk/src/mlpack/core/util/option_impl.hpp
mlpack/trunk/src/mlpack/core/util/prefixedoutstream.cpp
mlpack/trunk/src/mlpack/core/util/prefixedoutstream.hpp
mlpack/trunk/src/mlpack/core/util/prefixedoutstream_impl.hpp
mlpack/trunk/src/mlpack/core/util/timers.cpp
mlpack/trunk/src/mlpack/core/util/timers.hpp
Removed:
mlpack/trunk/src/mlpack/core/io/
mlpack/trunk/src/mlpack/core/util/CMakeLists.txt
mlpack/trunk/src/mlpack/core/util/timers.cpp
mlpack/trunk/src/mlpack/core/util/timers.hpp
mlpack/trunk/src/mlpack/core/utilities/
Modified:
mlpack/trunk/src/mlpack/core.hpp
mlpack/trunk/src/mlpack/core/CMakeLists.txt
mlpack/trunk/src/mlpack/core/data/load.hpp
mlpack/trunk/src/mlpack/core/data/save.hpp
mlpack/trunk/src/mlpack/core/math/math_misc.hpp
mlpack/trunk/src/mlpack/core/tree/binary_space_tree_impl.hpp
mlpack/trunk/src/mlpack/core/tree/periodichrectbound_impl.hpp
mlpack/trunk/src/mlpack/core/util/save_restore_utility.hpp
mlpack/trunk/src/mlpack/methods/gmm/gmm_main.cpp
mlpack/trunk/src/mlpack/tests/save_restore_utility_test.cpp
Log:
Move io/* to utilities/* then utilities to util (shorter, simpler name) and
update all references thereto.
Modified: mlpack/trunk/src/mlpack/core/CMakeLists.txt
===================================================================
--- mlpack/trunk/src/mlpack/core/CMakeLists.txt 2011-12-14 12:41:57 UTC (rev 10773)
+++ mlpack/trunk/src/mlpack/core/CMakeLists.txt 2011-12-14 12:44:53 UTC (rev 10774)
@@ -2,13 +2,12 @@
set(DIRS
arma_extend
data
- io
kernels
math
metrics
optimizers
tree
- utilities
+ util
)
foreach(dir ${DIRS})
Modified: mlpack/trunk/src/mlpack/core/data/load.hpp
===================================================================
--- mlpack/trunk/src/mlpack/core/data/load.hpp 2011-12-14 12:41:57 UTC (rev 10773)
+++ mlpack/trunk/src/mlpack/core/data/load.hpp 2011-12-14 12:44:53 UTC (rev 10774)
@@ -9,7 +9,7 @@
#ifndef __MLPACK_CORE_DATA_LOAD_HPP
#define __MLPACK_CORE_DATA_LOAD_HPP
-#include <mlpack/core/io/log.hpp>
+#include <mlpack/core/util/log.hpp>
#include <mlpack/core/arma_extend/arma_extend.hpp> // Includes Armadillo.
#include <string>
Modified: mlpack/trunk/src/mlpack/core/data/save.hpp
===================================================================
--- mlpack/trunk/src/mlpack/core/data/save.hpp 2011-12-14 12:41:57 UTC (rev 10773)
+++ mlpack/trunk/src/mlpack/core/data/save.hpp 2011-12-14 12:44:53 UTC (rev 10774)
@@ -9,7 +9,7 @@
#ifndef __MLPACK_CORE_DATA_SAVE_HPP
#define __MLPACK_CORE_DATA_SAVE_HPP
-#include <mlpack/core/io/log.hpp>
+#include <mlpack/core/util/log.hpp>
#include <mlpack/core/arma_extend/arma_extend.hpp> // Includes Armadillo.
#include <string>
Modified: mlpack/trunk/src/mlpack/core/math/math_misc.hpp
===================================================================
--- mlpack/trunk/src/mlpack/core/math/math_misc.hpp 2011-12-14 12:41:57 UTC (rev 10773)
+++ mlpack/trunk/src/mlpack/core/math/math_misc.hpp 2011-12-14 12:44:53 UTC (rev 10774)
@@ -3,13 +3,10 @@
*
* Miscellaneous math routines.
*/
+#ifndef __MLPACK_CORE_MATH_MATH_MISC_HPP
+#define __MLPACK_CORE_MATH_MATH_MISC_HPP
-#ifndef __MLPACK_CORE_MATH_MATH_LIB_HPP
-#define __MLPACK_CORE_MATH_MATH_LIB_HPP
-
-#include "../io/cli.hpp"
-#include "../io/log.hpp"
-
+#include <stdlib.h>
#include <math.h>
#include <float.h>
Modified: mlpack/trunk/src/mlpack/core/tree/binary_space_tree_impl.hpp
===================================================================
--- mlpack/trunk/src/mlpack/core/tree/binary_space_tree_impl.hpp 2011-12-14 12:41:57 UTC (rev 10773)
+++ mlpack/trunk/src/mlpack/core/tree/binary_space_tree_impl.hpp 2011-12-14 12:44:53 UTC (rev 10774)
@@ -9,8 +9,8 @@
// In case it wasn't included already for some reason.
#include "binary_space_tree.hpp"
-#include <mlpack/core/io/cli.hpp>
-#include <mlpack/core/io/log.hpp>
+#include <mlpack/core/util/cli.hpp>
+#include <mlpack/core/util/log.hpp>
namespace mlpack {
namespace tree {
Modified: mlpack/trunk/src/mlpack/core/tree/periodichrectbound_impl.hpp
===================================================================
--- mlpack/trunk/src/mlpack/core/tree/periodichrectbound_impl.hpp 2011-12-14 12:41:57 UTC (rev 10773)
+++ mlpack/trunk/src/mlpack/core/tree/periodichrectbound_impl.hpp 2011-12-14 12:44:53 UTC (rev 10774)
@@ -13,7 +13,6 @@
#include <math.h>
#include "../math/math_misc.hpp"
-#include "../io/log.hpp"
namespace mlpack {
namespace bound {
Deleted: mlpack/trunk/src/mlpack/core/util/CMakeLists.txt
===================================================================
--- mlpack/trunk/src/mlpack/core/utilities/CMakeLists.txt 2011-12-13 07:23:09 UTC (rev 10737)
+++ mlpack/trunk/src/mlpack/core/util/CMakeLists.txt 2011-12-14 12:44:53 UTC (rev 10774)
@@ -1,19 +0,0 @@
-cmake_minimum_required(VERSION 2.8)
-
-# Define the files we need to compile.
-# Anything not in this list will not be compiled into MLPACK.
-set(SOURCES
- save_restore_utility.cpp
- save_restore_utility.hpp
- timers.hpp
- timers.cpp
-)
-
-# add directory name to sources
-set(DIR_SRCS)
-foreach(file ${SOURCES})
- set(DIR_SRCS ${DIR_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/${file})
-endforeach()
-# Append sources (with directory name) to list of all MLPACK sources (used at
-# the parent scope).
-set(MLPACK_SRCS ${MLPACK_SRCS} ${DIR_SRCS} PARENT_SCOPE)
Copied: mlpack/trunk/src/mlpack/core/util/CMakeLists.txt (from rev 10767, mlpack/trunk/src/mlpack/core/utilities/CMakeLists.txt)
===================================================================
--- mlpack/trunk/src/mlpack/core/util/CMakeLists.txt (rev 0)
+++ mlpack/trunk/src/mlpack/core/util/CMakeLists.txt 2011-12-14 12:44:53 UTC (rev 10774)
@@ -0,0 +1,34 @@
+cmake_minimum_required(VERSION 2.8)
+
+# Define the files we need to compile.
+# Anything not in this list will not be compiled into MLPACK.
+set(SOURCES
+ cli.hpp
+ cli.cpp
+ cli_deleter.hpp
+ cli_deleter.cpp
+ cli_impl.hpp
+ log.hpp
+ log.cpp
+ nulloutstream.hpp
+ option.hpp
+ option.cpp
+ option_impl.hpp
+ prefixedoutstream.hpp
+ prefixedoutstream.cpp
+ prefixedoutstream_impl.hpp
+ save_restore_utility.hpp
+ save_restore_utility.cpp
+ save_restore_utility_impl.hpp
+ timers.hpp
+ timers.cpp
+)
+
+# add directory name to sources
+set(DIR_SRCS)
+foreach(file ${SOURCES})
+ set(DIR_SRCS ${DIR_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/${file})
+endforeach()
+# Append sources (with directory name) to list of all MLPACK sources (used at
+# the parent scope).
+set(MLPACK_SRCS ${MLPACK_SRCS} ${DIR_SRCS} PARENT_SCOPE)
Copied: mlpack/trunk/src/mlpack/core/util/cli.cpp (from rev 10768, mlpack/trunk/src/mlpack/core/io/cli.cpp)
===================================================================
--- mlpack/trunk/src/mlpack/core/util/cli.cpp (rev 0)
+++ mlpack/trunk/src/mlpack/core/util/cli.cpp 2011-12-14 12:44:53 UTC (rev 10774)
@@ -0,0 +1,683 @@
+/**
+ * @file cli.cpp
+ * @author Matthew Amidon
+ *
+ * Implementation of the CLI module for parsing parameters.
+ */
+#include <list>
+#include <boost/program_options.hpp>
+#include <boost/any.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <iostream>
+#include <string>
+#include <execinfo.h>
+
+#ifndef _WIN32
+ #include <sys/time.h> // For Linux.
+#else
+ #include <winsock.h> // timeval on Windows.
+ #include <windows.h> // GetSystemTimeAsFileTime() on Windows.
+// gettimeofday() has no equivalent; we will need to write extra code for that.
+ #if defined(_MSC_VER) || defined(_MSC_EXTENSCLINS)
+ #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
+ #else
+ #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
+ #endif
+#endif // _WIN32
+
+#include "cli.hpp"
+#include "log.hpp"
+
+#include "option.hpp"
+
+using namespace mlpack;
+using namespace mlpack::io;
+
+CLI* CLI::singleton = NULL;
+
+/* For clarity, we will alias boost's namespace. */
+namespace po = boost::program_options;
+
+// Fake ProgramDoc in case none is supplied.
+static ProgramDoc empty_program_doc = ProgramDoc("", "");
+
+/* Constructors, Destructors, Copy */
+/* Make the constructor private, to preclude unauthorized instances */
+CLI::CLI() : desc("Allowed Options") , did_parse(false), doc(&empty_program_doc)
+{
+ return;
+}
+
+/**
+ * Initialize desc with a particular name.
+ *
+ * @param optionsName Name of the module, as far as boost is concerned.
+ */
+CLI::CLI(std::string& optionsName) :
+ desc(optionsName.c_str()), did_parse(false), doc(&empty_program_doc)
+{
+ return;
+}
+
+// Private copy constructor; don't want copies floating around.
+CLI::CLI(const CLI& other) : desc(other.desc),
+ did_parse(false), doc(&empty_program_doc)
+{
+ return;
+}
+
+CLI::~CLI()
+{
+ // Terminate the program timer.
+ Timer::Stop("total_time");
+
+ // Did the user ask for verbose output? If so we need to print everything.
+ // But only if the user did not ask for help or info.
+ if (HasParam("verbose") && !HasParam("help") && !HasParam("info"))
+ {
+ Log::Info << std::endl << "Execution parameters:" << std::endl;
+ Print();
+
+ Log::Info << "Program timers:" << std::endl;
+ std::map<std::string, timeval>::iterator it;
+ for (it = timer.GetAllTimers().begin(); it != timer.GetAllTimers().end();
+ ++it)
+ {
+ std::string i = (*it).first;
+ Log::Info << " " << i << ": ";
+ timer.PrintTimer((*it).first.c_str());
+ }
+ }
+
+ // Notify the user if we are debugging, but only if we actually parsed the
+ // options. This way this output doesn't show up inexplicably for someone who
+ // may not have wanted it there (i.e. in Boost unit tests).
+ if (did_parse)
+ Log::Debug << "Compiled with debugging symbols." << std::endl;
+
+ return;
+}
+
+/* Methods */
+
+/**
+ * Adds a parameter to the hierarchy. Use char* and not std::string since the
+ * vast majority of use cases will be literal strings.
+ *
+ * @param identifier The name of the parameter.
+ * @param description Short string description of the parameter.
+ * @param alias An alias for the parameter.
+ * @param required Indicates if parameter must be set on command line.
+ */
+void CLI::Add(const char* identifier,
+ const char* description,
+ const char* alias,
+ bool required)
+{
+ po::options_description& desc = CLI::GetSingleton().desc;
+
+ 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.
+
+ // 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(), description);
+
+ // Make sure the description, etc. ends up in gmap.
+ gmap_t& gmap = GetSingleton().globalValues;
+ ParamData data;
+ data.desc = description;
+ data.tname = "";
+ data.name = path;
+ data.isFlag = false;
+ data.wasPassed = false;
+
+ gmap[path] = data;
+
+ // If the option is required, add it to the required options list.
+ if (required)
+ GetSingleton().requiredOptions.push_front(path);
+
+ return;
+}
+
+/*
+ * @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;
+
+ 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.
+ gmap_t& gmap = GetSingleton().globalValues;
+ ParamData data;
+ data.desc = description;
+ data.tname = TYPENAME(bool);
+ data.name = path;
+ data.isFlag = true;
+ data.wasPassed = false;
+
+ gmap[path] = data;
+}
+
+/**
+ * See if the specified flag was found while parsing.
+ *
+ * @param identifier The name of the parameter in question.
+ */
+bool CLI::HasParam(const char* identifier)
+{
+ po::variables_map vmap = GetSingleton().vmap;
+ gmap_t& gmap = GetSingleton().globalValues;
+ std::string key = identifier;
+
+ // Take any possible alias into account.
+ amap_t& amap = GetSingleton().aliasValues;
+ if (amap.count(key))
+ key = amap[key];
+
+ // Does the parameter exist at all?
+ int isInGmap = gmap.count(key);
+
+ // Check if the parameter is boolean; if it is, we just want to see if it was
+ // passed.
+ if(isInGmap)
+ return gmap[key].wasPassed;
+
+ // The parameter was not passed in; return false.
+ return false;
+}
+
+/**
+ * Grab the description of the specified node.
+ *
+ * @param identifier Name of the node in question.
+ * @return Description of the node in question.
+ */
+std::string CLI::GetDescription(const char* identifier)
+{
+ gmap_t& gmap = GetSingleton().globalValues;
+ std::string name = std::string(identifier);
+
+ //Take any possible alias into account
+ amap_t& amap = GetSingleton().aliasValues;
+ if (amap.count(name))
+ name = amap[name];
+
+
+ if(gmap.count(name))
+ return gmap[name].desc;
+ else
+ return "";
+
+}
+
+// Returns the sole instance of this class.
+CLI& CLI::GetSingleton()
+{
+ if (singleton == NULL)
+ singleton = new CLI();
+
+ return *singleton;
+}
+
+/**
+ * Parses the commandline for arguments.
+ *
+ * @param argc The number of arguments on the commandline.
+ * @param argv The array of arguments as strings
+ */
+void CLI::ParseCommandLine(int argc, char** line)
+{
+ Timer::Start("total_time");
+
+ po::variables_map& vmap = GetSingleton().vmap;
+ po::options_description& desc = GetSingleton().desc;
+
+ // Parse the command line, place the options & values into vmap
+ try
+ {
+ po::store(po::parse_command_line(argc, line, desc), vmap);
+ }
+ catch (std::exception& ex)
+ {
+ Log::Fatal << ex.what() << std::endl;
+ }
+
+ // Flush the buffer, make sure changes are propagated to vmap
+ po::notify(vmap);
+ UpdateGmap();
+ DefaultMessages();
+ RequiredOptions();
+}
+
+/**
+ * Parses a stream for arguments
+ *
+ * @param stream The stream to be parsed.
+ */
+void CLI::ParseStream(std::istream& stream)
+{
+ po::variables_map& vmap = GetSingleton().vmap;
+ po::options_description& desc = GetSingleton().desc;
+
+ // Parse the stream; place options & values into vmap.
+ try
+ {
+ po::store(po::parse_config_file(stream, desc), vmap);
+ }
+ catch (std::exception& ex)
+ {
+ Log::Fatal << ex.what() << std::endl;
+ }
+
+ // Flush the buffer; make sure changes are propagated to vmap.
+ po::notify(vmap);
+
+ UpdateGmap();
+ DefaultMessages();
+ RequiredOptions();
+
+ 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()
+{
+ gmap_t& gmap = GetSingleton().globalValues;
+ gmap_t::iterator iter;
+
+ // Print out all the values.
+ for (iter = gmap.begin(); iter != gmap.end(); iter++)
+ {
+ std::string key = iter->first;
+
+ Log::Info << " " << key << ": ";
+
+ // Now, figure out what type it is, and print it.
+ // We can handle strings, ints, bools, floats, doubles.
+ ParamData data = iter->second;
+ if (data.tname == TYPENAME(std::string))
+ {
+ std::string value = GetParam<std::string>(key.c_str());
+ if(value == "")
+ Log::Info << "\"\"";
+ Log::Info << value;
+ }
+ else if (data.tname == TYPENAME(int))
+ {
+ int value = GetParam<int>(key.c_str());
+ Log::Info << value;
+ }
+ else if (data.tname == TYPENAME(bool))
+ {
+ bool value = HasParam(key.c_str());
+ Log::Info << (value ? "true" : "false");
+ }
+ else if (data.tname == TYPENAME(float))
+ {
+ float value = GetParam<float>(key.c_str());
+ Log::Info << value;
+ }
+ else if (data.tname == TYPENAME(double))
+ {
+ double value = GetParam<double>(key.c_str());
+ Log::Info << value;
+ }
+ else
+ {
+ // We don't know how to print this, or it's a timeval which is printed
+ // later.
+ Log::Info << "(unknown data type)";
+ }
+
+ Log::Info << std::endl;
+ }
+ Log::Info << std::endl;
+}
+
+
+/* Prints the descriptions of the current hierarchy. */
+void CLI::PrintHelp(std::string param)
+{
+ gmap_t& gmap = GetSingleton().globalValues;
+ amap_t& amap = GetSingleton().aliasValues;
+ gmap_t::iterator iter;
+ ProgramDoc docs = *GetSingleton().doc;
+
+ // If we pass a single param, alias it if necessary.
+ if (param != "" && amap.count(param))
+ param = amap[param];
+
+ // Do we only want to print out one value?
+ if (param != "" && gmap.count(param))
+ {
+ ParamData data = gmap[param];
+ std::string alias = AliasReverseLookup(param);
+ alias = alias.length() ? " (-" + alias + ")" : alias;
+
+ // Figure out the name of the type.
+ std::string type = "";
+ if (data.tname == TYPENAME(std::string))
+ type = " [string]";
+ else if (data.tname == TYPENAME(int))
+ type = " [int]";
+ else if (data.tname == TYPENAME(bool))
+ type = ""; // Nothing to pass for a flag.
+ else if (data.tname == TYPENAME(float))
+ type = " [float]";
+ else if (data.tname == TYPENAME(double))
+ type = " [double]";
+
+ // Now, print the descriptions.
+ std::string fullDesc = " --" + param + alias + type + " ";
+
+ if (fullDesc.length() <= 32) // It all fits on one line.
+ std::cout << fullDesc << std::string(32 - fullDesc.length(), ' ');
+ else // We need multiple lines.
+ std::cout << fullDesc << std::endl << std::string(32, ' ');
+
+ std::cout << HyphenateString(data.desc, 32) << std::endl;
+ return;
+ }
+ else if (param != "")
+ {
+ // User passed a single variable, but it doesn't exist.
+ std::cerr << "Parameter --" << param << " does not exist." << std::endl;
+ exit(1); // Nothing left to do.
+ }
+
+ // Print out the descriptions.
+ if(docs.programName != "")
+ {
+ std::cout << docs.programName << std::endl << std::endl;
+ std::cout << " " << HyphenateString(docs.documentation, 2) << std::endl
+ << std::endl;
+ }
+ else
+ std::cout << "[undocumented program]" << std::endl << std::endl;
+
+ for (size_t pass = 0; pass < 2; ++pass)
+ {
+ if (pass == 0)
+ std::cout << "Required options:" << std::endl << std::endl;
+ else
+ std::cout << "Options: " << std::endl << std::endl;
+
+ // Print out the descriptions of everything else.
+ for (iter = gmap.begin(); iter != gmap.end(); iter++)
+ {
+ std::string key = iter->first;
+ ParamData data = iter->second;
+ std::string desc = data.desc;
+ std::string alias = AliasReverseLookup(key);
+ alias = alias.length() ? " (-" + alias + ")" : alias;
+
+ // Is the option required or not?
+ bool required = false;
+ std::list<std::string>::iterator iter;
+ std::list<std::string>& rOpt = GetSingleton().requiredOptions;
+ for (iter = rOpt.begin(); iter != rOpt.end(); ++iter)
+ if ((*iter) == key)
+ required = true;
+
+ if ((pass == 0) && !required)
+ continue; // Don't print this one.
+ if ((pass == 1) && required)
+ continue; // Don't print this one.
+
+ if (pass == 1) // Append default value to description.
+ {
+ desc += " Default value ";
+ std::stringstream tmp;
+
+ if (data.tname == TYPENAME(std::string))
+ tmp << "'" << boost::any_cast<std::string>(data.value) << "'.";
+ else if (data.tname == TYPENAME(int))
+ tmp << boost::any_cast<int>(data.value) << '.';
+ else if (data.tname == TYPENAME(bool))
+ desc = data.desc; // No extra output for that.
+ else if (data.tname == TYPENAME(float))
+ tmp << boost::any_cast<float>(data.value) << '.';
+ else if (data.tname == TYPENAME(double))
+ tmp << boost::any_cast<double>(data.value) << '.';
+
+ desc += tmp.str();
+ }
+
+ // Figure out the name of the type.
+ std::string type = "";
+ if (data.tname == TYPENAME(std::string))
+ type = " [string]";
+ else if (data.tname == TYPENAME(int))
+ type = " [int]";
+ else if (data.tname == TYPENAME(bool))
+ type = ""; // Nothing to pass for a flag.
+ else if (data.tname == TYPENAME(float))
+ type = " [float]";
+ else if (data.tname == TYPENAME(double))
+ type = " [double]";
+
+ // Now, print the descriptions.
+ std::string fullDesc = " --" + key + alias + type + " ";
+
+ if (fullDesc.length() <= 32) // It all fits on one line.
+ std::cout << fullDesc << std::string(32 - fullDesc.length(), ' ');
+ else // We need multiple lines.
+ std::cout << fullDesc << std::endl << std::string(32, ' ');
+
+ std::cout << HyphenateString(desc, 32) << std::endl;
+ }
+
+ std::cout << std::endl;
+
+ }
+}
+
+/**
+ * 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;
+}
+
+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.
+}
+
+// Add help parameter.
+PARAM_FLAG("help", "Default help info.", "h");
+PARAM_STRING("info", "Get help on a specific module or option.", "", "");
+PARAM_FLAG("verbose", "Display informational messages and the full list of "
+ "parameters and timers at the end of execution.", "");
Copied: mlpack/trunk/src/mlpack/core/util/cli.hpp (from rev 10767, mlpack/trunk/src/mlpack/core/io/cli.hpp)
===================================================================
--- mlpack/trunk/src/mlpack/core/util/cli.hpp (rev 0)
+++ mlpack/trunk/src/mlpack/core/util/cli.hpp 2011-12-14 12:44:53 UTC (rev 10774)
@@ -0,0 +1,780 @@
+/**
+ * @file cli.hpp
+ * @author Matthew Amidon
+ *
+ * This file implements the CLI subsystem which is intended to replace FX.
+ * This can be used more or less regardless of context. In the future,
+ * it might be expanded to include file I/O.
+ */
+#ifndef __MLPACK_CORE_IO_CLI_HPP
+#define __MLPACK_CORE_IO_CLI_HPP
+
+#include <list>
+#include <iostream>
+#include <map>
+#include <string>
+
+#include <boost/any.hpp>
+#include <boost/program_options.hpp>
+
+#include "timers.hpp"
+#include "cli_deleter.hpp" // To make sure we can delete the singleton.
+
+/**
+ * Document an executable. Only one instance of this macro should be
+ * present in your program! Therefore, use it in the main.cpp
+ * (or corresponding executable) in your program.
+ *
+ * @see mlpack::CLI, PARAM_FLAG(), PARAM_INT(), PARAM_DOUBLE(), PARAM_STRING(),
+ * PARAM_VECTOR(), PARAM_INT_REQ(), PARAM_DOUBLE_REQ(), PARAM_STRING_REQ(),
+ * PARAM_VECTOR_REQ().
+ *
+ * @param NAME Short string representing the name of the program.
+ * @param DESC Long string describing what the program does and possibly a
+ * simple usage example. Newlines should not be used here; this is taken
+ * care of by CLI.
+ */
+#define PROGRAM_INFO(NAME, DESC) static mlpack::io::ProgramDoc \
+ io_programdoc_dummy_object = mlpack::io::ProgramDoc(NAME, DESC);
+
+/**
+ * Define a flag parameter.
+ *
+ * @param ID Name of the parameter.
+ * @param DESC Quick description of the parameter (1-2 sentences).
+ * @param ALIAS An alias for the parameter
+ *
+ * @see mlpack::CLI, PROGRAM_INFO()
+ *
+ * @bug
+ * The __COUNTER__ variable is used in most cases to guarantee a unique global
+ * identifier for options declared using the PARAM_*() macros. However, not all
+ * compilers have this support--most notably, gcc < 4.3. In that case, the
+ * __LINE__ macro is used as an attempt to get a unique global identifier, but
+ * collisions are still possible, and they produce bizarre error messages. See
+ * http://mlpack.org/ticket/74 for more information.
+ */
+#define PARAM_FLAG(ID, DESC, ALIAS) \
+ PARAM_FLAG_INTERNAL(ID, DESC, ALIAS);
+
+/**
+ * Define an integer parameter.
+ *
+ * The parameter can then be specified on the command line with
+ * --ID=value.
+ *
+ * @param ID Name of the parameter.
+ * @param DESC Quick description of the parameter (1-2 sentences).
+ * @param ALIAS An alias for the parameter.
+ * @param DEF Default value of the parameter.
+ *
+ * @see mlpack::CLI, PROGRAM_INFO()
+ *
+ * @bug
+ * The __COUNTER__ variable is used in most cases to guarantee a unique global
+ * identifier for options declared using the PARAM_*() macros. However, not all
+ * compilers have this support--most notably, gcc < 4.3. In that case, the
+ * __LINE__ macro is used as an attempt to get a unique global identifier, but
+ * collisions are still possible, and they produce bizarre error messages. See
+ * http://mlpack.org/ticket/74 for more information.
+ */
+#define PARAM_INT(ID, DESC, ALIAS, DEF) \
+ PARAM(int, ID, DESC, ALIAS, DEF, false)
+
+/**
+ * Define a floating-point parameter. You should use PARAM_DOUBLE instead.
+ *
+ * The parameter can then be specified on the command line with
+ * --ID=value.
+ *
+ * @param ID Name of the parameter.
+ * @param DESC Quick description of the parameter (1-2 sentences).
+ * @param ALIAS An alias for the parameter.
+ * @param DEF Default value of the parameter.
+ *
+ * @see mlpack::CLI, PROGRAM_INFO()
+ *
+ * @bug
+ * The __COUNTER__ variable is used in most cases to guarantee a unique global
+ * identifier for options declared using the PARAM_*() macros. However, not all
+ * compilers have this support--most notably, gcc < 4.3. In that case, the
+ * __LINE__ macro is used as an attempt to get a unique global identifier, but
+ * collisions are still possible, and they produce bizarre error messages. See
+ * http://mlpack.org/ticket/74 for more information.
+ */
+#define PARAM_FLOAT(ID, DESC, ALIAS, DEF) \
+ PARAM(float, ID, DESC, ALIAS, DEF, false)
+
+/**
+ * Define a double parameter.
+ *
+ * The parameter can then be specified on the command line with
+ * --ID=value.
+ *
+ * @param ID Name of the parameter.
+ * @param DESC Quick description of the parameter (1-2 sentences).
+ * @param ALIAS An alias for the parameter.
+ * @param DEF Default value of the parameter.
+ *
+ * @see mlpack::CLI, PROGRAM_INFO()
+ *
+ * @bug
+ * The __COUNTER__ variable is used in most cases to guarantee a unique global
+ * identifier for options declared using the PARAM_*() macros. However, not all
+ * compilers have this support--most notably, gcc < 4.3. In that case, the
+ * __LINE__ macro is used as an attempt to get a unique global identifier, but
+ * collisions are still possible, and they produce bizarre error messages. See
+ * http://mlpack.org/ticket/74 for more information.
+ */
+#define PARAM_DOUBLE(ID, DESC, ALIAS, DEF) \
+ PARAM(double, ID, DESC, ALIAS, DEF, false)
+
+/**
+ * Define a string parameter.
+ *
+ * The parameter can then be specified on the command line with
+ * --ID=value. If ALIAS is equal to DEF_MOD (which is set using the
+ * PROGRAM_INFO() macro), the parameter can be specified with just --ID=value.
+ *
+ * @param ID Name of the parameter.
+ * @param DESC Quick description of the parameter (1-2 sentences).
+ * @param ALIAS An alias for the parameter.
+ * @param DEF Default value of the parameter.
+ *
+ * @see mlpack::CLI, PROGRAM_INFO()
+ *
+ * @bug
+ * The __COUNTER__ variable is used in most cases to guarantee a unique global
+ * identifier for options declared using the PARAM_*() macros. However, not all
+ * compilers have this support--most notably, gcc < 4.3. In that case, the
+ * __LINE__ macro is used as an attempt to get a unique global identifier, but
+ * collisions are still possible, and they produce bizarre error messages. See
+ * http://mlpack.org/ticket/74 for more information.
+ */
+#define PARAM_STRING(ID, DESC, ALIAS, DEF) \
+ PARAM(std::string, ID, DESC, ALIAS, DEF, false)
+
+/**
+ * Define a vector parameter.
+ *
+ * The parameter can then be specified on the command line with
+ * --ID=value.
+ *
+ * @param ID Name of the parameter.
+ * @param DESC Quick description of the parameter (1-2 sentences).
+ * @param ALIAS An alias for the parameter.
+ * @param DEF Default value of the parameter.
+ *
+ * @see mlpack::CLI, PROGRAM_INFO()
+ *
+ * @bug
+ * The __COUNTER__ variable is used in most cases to guarantee a unique global
+ * identifier for options declared using the PARAM_*() macros. However, not all
+ * compilers have this support--most notably, gcc < 4.3. In that case, the
+ * __LINE__ macro is used as an attempt to get a unique global identifier, but
+ * collisions are still possible, and they produce bizarre error messages. See
+ * http://mlpack.org/ticket/74 for more information.
+ */
+#define PARAM_VECTOR(T, ID, DESC, ALIAS) \
+ PARAM(std::vector<T>, ID, DESC, ALIAS, std::vector<T>(), false)
+
+// A required flag doesn't make sense and isn't given here.
+
+/**
+ * Define a required integer parameter.
+ *
+ * The parameter must then be specified on the command line with
+ * --ID=value.
+ *
+ * @param ID Name of the parameter.
+ * @param DESC Quick description of the parameter (1-2 sentences).
+ * @param ALIAS An alias for the parameter.
+ *
+ * @see mlpack::CLI, PROGRAM_INFO()
+ *
+ * @bug
+ * The __COUNTER__ variable is used in most cases to guarantee a unique global
+ * identifier for options declared using the PARAM_*() macros. However, not all
+ * compilers have this support--most notably, gcc < 4.3. In that case, the
+ * __LINE__ macro is used as an attempt to get a unique global identifier, but
+ * collisions are still possible, and they produce bizarre error messages. See
+ * http://mlpack.org/ticket/74 for more information.
+ */
+#define PARAM_INT_REQ(ID, DESC, ALIAS) PARAM(int, ID, DESC, ALIAS, 0, true)
+
+/**
+ * Define a required floating-point parameter. You should probably use a double
+ * instead.
+ *
+ * The parameter must then be specified on the command line with
+ * --ID=value. If ALIAS is equal to DEF_MOD (which is set using the
+ * PROGRAM_INFO() macro), the parameter can be specified with just --ID=value.
+ *
+ * @param ID Name of the parameter.
+ * @param DESC Quick description of the parameter (1-2 sentences).
+ * @param ALIAS An alias for the parameter.
+ *
+ * @see mlpack::CLI, PROGRAM_INFO()
+ *
+ * @bug
+ * The __COUNTER__ variable is used in most cases to guarantee a unique global
+ * identifier for options declared using the PARAM_*() macros. However, not all
+ * compilers have this support--most notably, gcc < 4.3. In that case, the
+ * __LINE__ macro is used as an attempt to get a unique global identifier, but
+ * collisions are still possible, and they produce bizarre error messages. See
+ * http://mlpack.org/ticket/74 for more information.
+ */
+#define PARAM_FLOAT_REQ(ID, DESC, ALIAS) PARAM(float, ID, DESC, ALIAS, 0.0f, \
+ true)
+
+/**
+ * Define a required double parameter.
+ *
+ * The parameter must then be specified on the command line with
+ * --ID=value.
+ *
+ * @param ID Name of the parameter.
+ * @param DESC Quick description of the parameter (1-2 sentences).
+ * @param ALIAS An alias for the parameter.
+ *
+ * @see mlpack::CLI, PROGRAM_INFO()
+ *
+ * @bug
+ * The __COUNTER__ variable is used in most cases to guarantee a unique global
+ * identifier for options declared using the PARAM_*() macros. However, not all
+ * compilers have this support--most notably, gcc < 4.3. In that case, the
+ * __LINE__ macro is used as an attempt to get a unique global identifier, but
+ * collisions are still possible, and they produce bizarre error messages. See
+ * http://mlpack.org/ticket/74 for more information.
+ */
+#define PARAM_DOUBLE_REQ(ID, DESC, ALIAS) PARAM(double, ID, DESC, ALIAS, \
+ 0.0f, true)
+
+/**
+ * Define a required string parameter.
+ *
+ * The parameter must then be specified on the command line with
+ * --ID=value.
+ *
+ * @param ID Name of the parameter.
+ * @param DESC Quick description of the parameter (1-2 sentences).
+ * @param ALIAS An alias for the parameter.
+ *
+ * @see mlpack::CLI, PROGRAM_INFO()
+ *
+ * @bug
+ * The __COUNTER__ variable is used in most cases to guarantee a unique global
+ * identifier for options declared using the PARAM_*() macros. However, not all
+ * compilers have this support--most notably, gcc < 4.3. In that case, the
+ * __LINE__ macro is used as an attempt to get a unique global identifier, but
+ * collisions are still possible, and they produce bizarre error messages. See
+ * http://mlpack.org/ticket/74 for more information.
+ */
+#define PARAM_STRING_REQ(ID, DESC, ALIAS) PARAM(std::string, ID, DESC, \
+ ALIAS, "", true);
+
+/**
+ * Define a required vector parameter.
+ *
+ * The parameter must then be specified on the command line with
+ * --ID=value.
+ *
+ * @param ID Name of the parameter.
+ * @param DESC Quick description of the parameter (1-2 sentences).
+ * @param ALIAS An alias for the parameter.
+ *
+ * @see mlpack::CLI, PROGRAM_INFO()
+ *
+ * @bug
+ * The __COUNTER__ variable is used in most cases to guarantee a unique global
+ * identifier for options declared using the PARAM_*() macros. However, not all
+ * compilers have this support--most notably, gcc < 4.3. In that case, the
+ * __LINE__ macro is used as an attempt to get a unique global identifier, but
+ * collisions are still possible, and they produce bizarre error messages. See
+ * http://mlpack.org/ticket/74 for more information.
+ */
+#define PARAM_VECTOR_REQ(T, ID, DESC, ALIAS) PARAM(std::vector<T>, ID, DESC, \
+ ALIAS, std::vector<T>(), true);
+
+/**
+ * @cond
+ * Don't document internal macros.
+ */
+
+// These are ugly, but necessary utility functions we must use to generate a
+// unique identifier inside of the PARAM() module.
+#define JOIN(x, y) JOIN_AGAIN(x, y)
+#define JOIN_AGAIN(x, y) x ## y
+/** @endcond */
+
+/**
+ * Define an input parameter. Don't use this function; use the other ones above
+ * that call it. Note that we are using the __LINE__ macro for naming these
+ * actual parameters when __COUNTER__ does not exist, which is a bit of an ugly
+ * hack... but this is the preprocessor, after all. We don't have much choice
+ * other than ugliness.
+ *
+ * @param T Type of the parameter.
+ * @param ID Name of the parameter.
+ * @param DESC Description of the parameter (1-2 sentences).
+ * @param ALIAS Alias for this parameter.
+ * @param DEF Default value of the parameter.
+ * @param REQ Whether or not parameter is required (boolean value).
+ */
+#ifdef __COUNTER__
+ #define PARAM(T, ID, DESC, ALIAS, DEF, REQ) static mlpack::io::Option<T> \
+ JOIN(io_option_dummy_object_, __COUNTER__) \
+ (false, DEF, ID, DESC, ALIAS, REQ);
+
+ /** @cond Don't document internal macros. */
+ #define PARAM_FLAG_INTERNAL(ID, DESC, ALIAS) static mlpack::io::Option<bool>\
+ 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
+ // enough". We use the __LINE__ macro and the type of the parameter to try
+ // and get a good guess at something unique.
+ #define PARAM(T, ID, DESC, ALIAS, DEF, REQ) static mlpack::io::Option<T> \
+ JOIN(JOIN(io_option_dummy_object_, __LINE__), opt) (false, DEF, ID, \
+ DESC, ALIAS, REQ);
+
+ /** @cond Don't document internal macros. */
+ #define PARAM_FLAG_INTERNAL(ID, DESC, ALIAS) static mlpack::io::Option<bool>\
+ 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
+
+/**
+ * The TYPENAME macro is used internally to convert a type into a string.
+ */
+#define TYPENAME(x) (std::string(typeid(x).name()))
+
+namespace po = boost::program_options;
+
+namespace mlpack {
+
+namespace io {
+
+// Externally defined in option.hpp, this class holds information about the
+// program being run.
+class ProgramDoc;
+
+}; // namespace io
+
+/**
+ * Aids in the extensibility of OptionsHierarchy by focusing the potential
+ * changes into one structure.
+ */
+struct ParamData
+{
+ //! Name of this parameter.
+ std::string name;
+ //! Description of this parameter, if any.
+ std::string desc;
+ //! Type information of this parameter.
+ std::string tname;
+ //! The actual value of this parameter.
+ boost::any value;
+ //! True if this parameter was passed in via command line or file.
+ bool wasPassed;
+ //! True if the wasPassed value should not be ignored
+ bool isFlag;
+};
+
+/**
+ * @brief Parses the command line for parameters and holds user-specified
+ * parameters.
+ *
+ * The CLI class is a subsystem by which parameters for machine learning methods
+ * can be specified and accessed. In conjunction with the macros PARAM_DOUBLE,
+ * PARAM_INT, PARAM_STRING, PARAM_FLAG, and others, this class aims to make user
+ * configurability of MLPACK methods very easy.
+ *
+ * @section addparam Adding parameters to a program
+ *
+ * @code
+ * $ ./executable --foo/bar=5
+ * @endcode
+ *
+ * @note The = is optional; a space can also be used.
+ *
+ * A parameter is specified by using one of the following macros (this is not a
+ * complete list; see core/io/cli.hpp):
+ *
+ * - PARAM_FLAG(ID, DESC, ALIAS)
+ * - PARAM_DOUBLE(ID, DESC, ALIAS, DEF)
+ * - PARAM_INT(ID, DESC, ALIAS, DEF)
+ * - PARAM_STRING(ID, DESC, ALIAS, DEF)
+ *
+ * @param ID Name of the parameter.
+ * @param DESC Short description of the parameter (one/two sentences).
+ * @param ALIAS An alias for the parameter.
+ * @param DEF Default value of the parameter.
+ *
+ * The flag (boolean) type automatically defaults to false; it is specified
+ * merely as a flag on the command line (no '=true' is required).
+ *
+ * Here is an example of a few parameters being defined; this is for the L-BFGS
+ * 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",
+ * 1e-20);
+ * PARAM_DOUBLE("max_step", "The maximum step of the line search.", "lbfgs",
+ * 1e20);
+ * PARAM_INT("max_line_search_trials", "The maximum number of trials for the "
+ * "line search.", "lbfgs", 50);
+ * PARAM_DOUBLE("wolfe", "Parameter for detecting the Wolfe condition.",
+ * "lbfgs", 0.9);
+ * PARAM_DOUBLE("min_gradient_norm", "Minimum gradient norm required to "
+ * "continue the optimization.", "lbfgs", 1e-10);
+ * @endcode
+ *
+ * More documentation is available on the PARAM_*() macros in the documentation
+ * for core/io/cli.hpp.
+ *
+ * @section programinfo Documenting the program itself
+ *
+ * In addition to allowing documentation for each individual parameter and
+ * module, the PROGRAM_INFO() macro provides support for documenting the program
+ * itself. There should only be one instance of the PROGRAM_INFO() macro.
+ * Below is an example:
+ *
+ * @code
+ * PROGRAM_INFO("Maximum Variance Unfolding", "This program performs maximum "
+ * "variance unfolding on the given dataset, writing a lower-dimensional "
+ * "unfolded dataset to the given output file.", "mvu");
+ * @endcode
+ *
+ * The last parameter, the default module (DEF_MOD), is discussed in detail in
+ * the PROGRAM_INFO() documentation.
+ *
+ * @section parsecli Parsing the command line with CLI
+ *
+ * To have CLI parse the command line at the beginning of code execution, only a
+ * call to ParseCommandLine() is necessary:
+ *
+ * @code
+ * int main(int argc, char** argv) {
+ * CLI::ParseCommandLine(argc, argv);
+ *
+ * ...
+ * }
+ * @endcode
+ *
+ * CLI provides --help and --info options which give nicely formatted
+ * documentation of each option; the documentation is generated from the DESC
+ * arguments in the PARAM_*() macros.
+ *
+ * @section getparam Getting/setting parameters with CLI
+ *
+ * When the parameters have been defined, the next important thing is how to
+ * access and modify them. For this, the HasParam() and GetParam() methods are
+ * used. For instance, the option "neighbor_search/k" could be
+ * modified like this (it could also be merely accessed with the same call as an
+ * r-value).
+ *
+ * @code
+ * CLI::GetParam<index_t>("neighbor_search/k") = 50;
+ * @endcode
+ *
+ * @note
+ * Care is needed when defining options. Because the PARAM_*() macros expand to
+ * a global object definition (of type mlpack::io::Option) whose constructor
+ * adds the parameter to the hierarchy, the parameters defined in any included
+ * file will be added to the program--and the documentation for those options
+ * will appear when --help is given. For this reason, mlpack/core.h does not
+ * include more than the core components necessary to write MLPACK code. Care
+ * is required so that only the files which are absolutely necessary are
+ * included, so as to avoid cluttering the documentation with irrelevant
+ * options.
+ *
+ * @bug
+ * The __COUNTER__ variable is used in most cases to guarantee a unique global
+ * identifier for options declared using the PARAM_*() macros. However, not all
+ * compilers have this support--most notably, gcc < 4.3. In that case, the
+ * __LINE__ macro is used as an attempt to get a unique global identifier, but
+ * collisions are still possible, and they produce bizarre error messages. See
+ * http://mlpack.org/ticket/74 for more information.
+ */
+class CLI
+{
+ public:
+ /**
+ * Adds a parameter to the hierarchy; use the PARAM_*() macros instead of this
+ * (i.e. PARAM_INT()). Uses char* and not std::string since the vast majority
+ * of use cases will be literal strings.
+ *
+ * @param identifier The name of the parameter.
+ * @param description Short string description of the parameter.
+ * @param alias An alias for the parameter, defaults to "" which is no alias.
+ * ("").
+ * @param required Indicates if parameter must be set on command line.
+ */
+ static void Add(const char* identifier,
+ const char* description,
+ const char* alias = "",
+ bool required = false);
+
+ /**
+ * Adds a parameter to the hierarchy; use the PARAM_*() macros instead of this
+ * (i.e. PARAM_INT()). Uses char* and not std::string since the vast majority
+ * of use cases will be literal strings. If the argument requires a
+ * parameter, you must specify a type.
+ *
+ * @param identifier The name of the parameter.
+ * @param description Short string description of the parameter.
+ * @param alias An alias for the parameter, defaults to "" which is no alias.
+ * @param required Indicates if parameter must be set on command line.
+ */
+ template<class T>
+ static void Add(const char* identifier,
+ const char* description,
+ const char* alias = "",
+ bool required = false);
+
+ /**
+ * Adds a flag parameter to the hierarchy; use PARAM_FLAG() instead of this.
+ *
+ * @param identifier The name of the paramater.
+ * @param description Short string description of the parameter.
+ * @param alias An alias for the parameter, defaults to "" which is no alias.
+ */
+ 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();
+
+ /**
+ * Grab the value of type T found while parsing. You can set the value using
+ * this reference safely.
+ *
+ * @param identifier The name of the parameter in question.
+ */
+ template<typename T>
+ static T& GetParam(const char* identifier);
+
+ /**
+ * Get the description of the specified node.
+ *
+ * @param identifier Name of the node in question.
+ * @return Description of the node in question.
+ */
+ static std::string GetDescription(const char* identifier);
+
+ /**
+ * Searches for unqualified paramters; when one is found, the default module
+ * is prepended onto it (if necessary).
+ *
+ * @param argc The number of parameters.
+ * @param argv 2D array of the parameter strings.
+ * @return Valid modified strings.
+ */
+ static std::vector<std::string> InsertDefaultModule(int argc, char** argv);
+
+ /**
+ * Parses the commandline for arguments.
+ *
+ * @param argc The number of arguments on the commandline.
+ * @param argv The array of arguments as strings.
+ */
+ static void ParseCommandLine(int argc, char** argv);
+
+ /**
+ * Parses a stream for arguments.
+ *
+ * @param stream The stream to be parsed.
+ */
+ static void ParseStream(std::istream& stream);
+
+ /**
+ * Print out the current hierarchy.
+ */
+ static void Print();
+
+ /**
+ * Print out the help info of the hierarchy.
+ */
+ 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.
+ *
+ * @param doc Pointer to the ProgramDoc object.
+ */
+ 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();
+
+ private:
+ //! The documentation and names of options.
+ po::options_description desc;
+
+ //! Values of the options given by user.
+ po::variables_map vmap;
+
+ //! Pathnames of required options.
+ std::list<std::string> requiredOptions;
+
+ //! Map of global values.
+ typedef std::map<std::string, ParamData> gmap_t;
+ gmap_t globalValues;
+
+ //! Map for aliases, from alias to actual name.
+ typedef std::map<std::string, std::string> amap_t;
+ amap_t aliasValues;
+
+ //! The singleton itself.
+ static CLI* singleton;
+
+ //! True, if CLI was used to parse command line options.
+ bool did_parse;
+
+ //! Holds the timer objects.
+ Timers timer;
+
+ //! So that Timer::Start() and Timer::Stop() can access the timer variable.
+ friend class Timer;
+
+ public:
+ //! Pointer to the ProgramDoc object.
+ io::ProgramDoc *doc;
+
+ private:
+
+ /**
+ * Returns an alias, if given the name of the original.
+ *
+ * @param value The value in a key:value pair where the key
+ * is an alias.
+ * @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.
+ * Only necessary on windows platforms.
+ * @param tv Valid timeval structure.
+ */
+ void FileTimeToTimeVal(timeval* tv);
+#endif
+
+ /**
+ * Make the constructor private, to preclude unauthorized instances.
+ */
+ CLI();
+
+ /**
+ * Initialize desc with a particular name.
+ *
+ * @param optionsName Name of the module, as far as boost is concerned.
+ */
+ CLI(std::string& optionsName);
+
+ //! Private copy constructor; we don't want copies floating around.
+ CLI(const CLI& other);
+};
+
+}; // namespace mlpack
+
+// Include the actual definitions of templated methods
+#include "cli_impl.hpp"
+
+#endif
Copied: mlpack/trunk/src/mlpack/core/util/cli_deleter.cpp (from rev 10737, mlpack/trunk/src/mlpack/core/io/cli_deleter.cpp)
===================================================================
--- mlpack/trunk/src/mlpack/core/util/cli_deleter.cpp (rev 0)
+++ mlpack/trunk/src/mlpack/core/util/cli_deleter.cpp 2011-12-14 12:44:53 UTC (rev 10774)
@@ -0,0 +1,32 @@
+/**
+ * @file io_deleter.cc
+ * @author Ryan Curtin
+ *
+ * Extremely simple class whose only job is to delete the existing CLI object at
+ * the end of execution. This is meant to allow the user to avoid typing
+ * 'CLI::Destroy()' at the end of their program. The file also defines a static
+ * CLIDeleter class, which will be initialized at the beginning of the program
+ * and deleted at the end. The destructor destroys the CLI singleton.
+ */
+#include "cli_deleter.hpp"
+#include "cli.hpp"
+
+using namespace mlpack;
+using namespace mlpack::io;
+
+/***
+ * Empty constructor that does nothing.
+ */
+CLIDeleter::CLIDeleter()
+{
+ /* nothing to do */
+}
+
+/***
+ * This destructor deletes the CLI singleton.
+ */
+CLIDeleter::~CLIDeleter()
+{
+ // Delete the singleton!
+ CLI::Destroy();
+}
Copied: mlpack/trunk/src/mlpack/core/util/cli_deleter.hpp (from rev 10737, mlpack/trunk/src/mlpack/core/io/cli_deleter.hpp)
===================================================================
--- mlpack/trunk/src/mlpack/core/util/cli_deleter.hpp (rev 0)
+++ mlpack/trunk/src/mlpack/core/util/cli_deleter.hpp 2011-12-14 12:44:53 UTC (rev 10774)
@@ -0,0 +1,33 @@
+/**
+ * @file cli_deleter.hpp
+ * @author Ryan Curtin
+ *
+ * Definition of the CLIDeleter() class.
+ */
+#ifndef __MLPACK_CORE_IO_CLI_DELETER_HPP
+#define __MLPACK_CORE_IO_CLI_DELETER_HPP
+
+namespace mlpack {
+namespace io {
+
+/**
+ * Extremely simple class whose only job is to delete the existing CLI object at
+ * the end of execution. This is meant to allow the user to avoid typing
+ * 'CLI::Destroy()' at the end of their program. The file also defines a static
+ * CLIDeleter class, which will be initialized at the beginning of the program
+ * and deleted at the end. The destructor destroys the CLI singleton.
+ */
+class CLIDeleter
+{
+ public:
+ CLIDeleter();
+ ~CLIDeleter();
+};
+
+//! Declare the deleter.
+static CLIDeleter cli_deleter;
+
+}; // namespace io
+}; // namespace mlpack
+
+#endif
Copied: mlpack/trunk/src/mlpack/core/util/cli_impl.hpp (from rev 10767, mlpack/trunk/src/mlpack/core/io/cli_impl.hpp)
===================================================================
--- mlpack/trunk/src/mlpack/core/util/cli_impl.hpp (rev 0)
+++ mlpack/trunk/src/mlpack/core/util/cli_impl.hpp 2011-12-14 12:44:53 UTC (rev 10774)
@@ -0,0 +1,118 @@
+/**
+ * @file cli_impl.hpp
+ * @author Matthew Amidon
+ *
+ * Implementation of templated functions of the CLI class.
+ */
+#ifndef __MLPACK_CORE_IO_CLI_HPP
+#error "Do not include this file directly."
+#endif
+
+#ifndef __MLPACK_CORE_IO_CLI_IMPL_HPP
+#define __MLPACK_CORE_IO_CLI_IMPL_HPP
+
+// Include option.hpp here because it requires CLI but is also templated.
+#include "option.hpp"
+
+namespace mlpack {
+
+/**
+ * @brief Adds a parameter to CLI, making it accessibile via GetParam &
+ * CheckValue.
+ *
+ * @tparam T The type of the parameter.
+ * @param identifier The name of the parameter, eg foo in bar/foo.
+ * @param description A string description of the parameter.
+ * @param parent The name of the parent of the parameter,
+ * eg bar/foo in bar/foo/buzz.
+ * @param required If required, the program will refuse to run
+ * unless the parameter is specified.
+ */
+template<typename T>
+void CLI::Add(const char* identifier,
+ const char* description,
+ const char* alias,
+ bool required)
+{
+
+ po::options_description& desc = CLI::GetSingleton().desc;
+ std::string path = identifier;
+ std::string stringAlias = alias;
+ std::string prog_opt_id = path;
+
+ // Add the alias, if necessary
+ 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<T>(), description);
+
+ // Make sure the appropriate metadata is inserted into gmap.
+ gmap_t& gmap = GetSingleton().globalValues;
+
+ ParamData data;
+ T tmp = T();
+
+ data.desc = description;
+ data.name = path;
+ 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.
+ if (required)
+ GetSingleton().requiredOptions.push_front(path);
+}
+
+
+/**
+ * @brief Returns the value of the specified parameter.
+ * If the parameter is unspecified, an undefined but
+ * more or less valid value is returned.
+ *
+ * @tparam T The type of the parameter.
+ * @param identifier The full pathname of the parameter.
+ *
+ * @return The value of the parameter. Use CLI::CheckValue to determine if it's
+ * valid.
+ */
+template<typename T>
+T& CLI::GetParam(const char* identifier)
+{
+ // Used to ensure we have a valid value.
+ T tmp = T();
+
+ // Used to index into the globalValues map.
+ std::string key = std::string(identifier);
+ gmap_t& gmap = GetSingleton().globalValues;
+
+ // Now check if we have an alias.
+ amap_t& amap = GetSingleton().aliasValues;
+ if (amap.count(key))
+ key = amap[key];
+
+ //What if we don't actually have any value?
+ if (!gmap.count(key))
+ {
+ gmap[key] = ParamData();
+ gmap[key].value = boost::any(tmp);
+ *boost::any_cast<T>(&gmap[key].value) = tmp;
+ }
+
+ //What if we have meta-data, but no data?
+ boost::any val = gmap[key].value;
+ if(val.empty())
+ gmap[key].value = boost::any(tmp);
+
+
+ return *boost::any_cast<T>(&gmap[key].value);
+}
+
+}; // namespace mlpack
+
+#endif
Copied: mlpack/trunk/src/mlpack/core/util/log.cpp (from rev 10737, mlpack/trunk/src/mlpack/core/io/log.cpp)
===================================================================
--- mlpack/trunk/src/mlpack/core/util/log.cpp (rev 0)
+++ mlpack/trunk/src/mlpack/core/util/log.cpp 2011-12-14 12:44:53 UTC (rev 10774)
@@ -0,0 +1,116 @@
+/**
+ * @file log.cpp
+ * @author Matthew Amidon
+ *
+ * Implementation of the Log class.
+ */
+#include <cxxabi.h>
+#include <execinfo.h>
+
+#include "log.hpp"
+
+// Color code escape sequences.
+#define BASH_RED "\033[0;31m"
+#define BASH_GREEN "\033[0;32m"
+#define BASH_YELLOW "\033[0;33m"
+#define BASH_CYAN "\033[0;36m"
+#define BASH_CLEAR "\033[0m"
+
+using namespace mlpack;
+using namespace mlpack::io;
+
+// Only output debugging output if in debug mode.
+#ifdef DEBUG
+PrefixedOutStream Log::Debug = PrefixedOutStream(std::cout,
+ BASH_CYAN "[DEBUG] " BASH_CLEAR);
+#else
+NullOutStream Log::Debug = NullOutStream();
+#endif
+
+PrefixedOutStream Log::Info = PrefixedOutStream(std::cout,
+ BASH_GREEN "[INFO ] " BASH_CLEAR, true /* unless --verbose */, false);
+PrefixedOutStream Log::Warn = PrefixedOutStream(std::cout,
+ BASH_YELLOW "[WARN ] " BASH_CLEAR, false, false);
+PrefixedOutStream Log::Fatal = PrefixedOutStream(std::cerr,
+ BASH_RED "[FATAL] " BASH_CLEAR, false, true /* fatal */);
+
+std::ostream& Log::cout = std::cout;
+
+// Only do anything for Assert() if in debugging mode.
+#ifdef DEBUG
+void Log::Assert(bool condition, const char* message)
+{
+ if(!condition)
+ {
+ void* array[25];
+ size_t size = backtrace (array, sizeof(array)/sizeof(void*));
+ char** messages = backtrace_symbols(array, size);
+
+ // skip first stack frame (points here)
+ for (size_t i = 1; i < size && messages != NULL; ++i)
+ {
+ char *mangled_name = 0, *offset_begin = 0, *offset_end = 0;
+
+ // find parantheses and +address offset surrounding mangled name
+ for (char *p = messages[i]; *p; ++p)
+ {
+ if (*p == '(')
+ {
+ mangled_name = p;
+ }
+ else if (*p == '+')
+ {
+ offset_begin = p;
+ }
+ else if (*p == ')')
+ {
+ offset_end = p;
+ break;
+ }
+ }
+
+ // if the line could be processed, attempt to demangle the symbol
+ if (mangled_name && offset_begin && offset_end &&
+ mangled_name < offset_begin)
+ {
+ *mangled_name++ = '\0';
+ *offset_begin++ = '\0';
+ *offset_end++ = '\0';
+
+ int status;
+ char* real_name = abi::__cxa_demangle(mangled_name, 0, 0, &status);
+
+ // if demangling is successful, output the demangled function name
+ if (status == 0)
+ {
+ Log::Debug << "[bt]: (" << i << ") " << messages[i] << " : "
+ << real_name << "+" << offset_begin << offset_end
+ << std::endl;
+
+ }
+ // otherwise, output the mangled function name
+ else
+ {
+ Log::Debug << "[bt]: (" << i << ") " << messages[i] << " : "
+ << mangled_name << "+" << offset_begin << offset_end
+ << std::endl;
+ }
+ free(real_name);
+ }
+ // otherwise, print the whole line
+ else
+ {
+ Log::Debug << "[bt]: (" << i << ") " << messages[i] << std::endl;
+ }
+ }
+ Log::Debug << message << std::endl;
+ free(messages);
+
+ //backtrace_symbols_fd (array, size, 2);
+ exit(1);
+ }
+}
+#else
+void Log::Assert(bool condition, const char* message)
+{ }
+#endif
Copied: mlpack/trunk/src/mlpack/core/util/log.hpp (from rev 10737, mlpack/trunk/src/mlpack/core/io/log.hpp)
===================================================================
--- mlpack/trunk/src/mlpack/core/util/log.hpp (rev 0)
+++ mlpack/trunk/src/mlpack/core/util/log.hpp 2011-12-14 12:44:53 UTC (rev 10774)
@@ -0,0 +1,84 @@
+/**
+ * @file log.hpp
+ * @author Matthew Amidon
+ *
+ * Definition of the Log class.
+ */
+#ifndef __MLPACK_CORE_IO_LOG_HPP
+#define __MLPACK_CORE_IO_LOG_HPP
+
+#include "prefixedoutstream.hpp"
+#include "nulloutstream.hpp"
+
+namespace mlpack {
+
+/**
+ * Provides a convenient way to give formatted output.
+ *
+ * The Log class has four members which can be used in the same way ostreams can
+ * be used:
+ *
+ * - Log::Debug
+ * - Log::Info
+ * - Log::Warn
+ * - Log::Fatal
+ *
+ * Each of these will prefix a tag to the output (for easy filtering), and the
+ * fatal output will terminate the program when a newline is encountered. An
+ * example is given below.
+ *
+ * @code
+ * Log::Info << "Checking a condition." << std::endl;
+ * if (!someCondition())
+ * Log::Warn << "someCondition() is not satisfied!" << std::endl;
+ * Log::Info << "Checking an important condition." << std::endl;
+ * if (!someImportantCondition()) {
+ * Log::Fatal << "someImportantCondition() is not satisfied! Terminating.";
+ * Log::Fatal << std::endl;
+ * }
+ * @endcode
+ *
+ * Any messages sent to Log::Debug will not be shown when compiling in non-debug
+ * mode. Messages to Log::Info will only be shown when the --verbose flag is
+ * given to the program (or rather, the CLI class).
+ *
+ * @see PrefixedOutStream, NullOutStream, CLI
+ */
+class Log
+{
+ public:
+ /**
+ * Checks if the specified condition is true.
+ * If not, halts program execution and prints a custom error message.
+ * Does nothing in non-debug mode.
+ */
+ static void Assert(bool condition, const char* message = "Assert Failed.");
+
+
+ // We only use PrefixedOutStream if the program is compiled with debug
+ // symbols.
+#ifdef DEBUG
+ //! Prints debug output with the appropriate tag: [DEBUG].
+ static io::PrefixedOutStream Debug;
+#else
+ //! Dumps debug output into the bit nether regions.
+ static io::NullOutStream Debug;
+#endif
+
+ //! Prints informational messages if --verbose is specified, prefixed with
+ //! [INFO ].
+ static io::PrefixedOutStream Info;
+
+ //! Prints warning messages prefixed with [WARN ].
+ static io::PrefixedOutStream Warn;
+
+ //! Prints fatal messages prefixed with [FATAL], then terminates the program.
+ static io::PrefixedOutStream Fatal;
+
+ //! Reference to cout, if necessary.
+ static std::ostream& cout;
+};
+
+}; //namespace mlpack
+
+#endif
Copied: mlpack/trunk/src/mlpack/core/util/nulloutstream.hpp (from rev 10737, mlpack/trunk/src/mlpack/core/io/nulloutstream.hpp)
===================================================================
--- mlpack/trunk/src/mlpack/core/util/nulloutstream.hpp (rev 0)
+++ mlpack/trunk/src/mlpack/core/util/nulloutstream.hpp 2011-12-14 12:44:53 UTC (rev 10774)
@@ -0,0 +1,80 @@
+/**
+ * @file nulloutstream.hpp
+ * @author Ryan Curtin
+ * @author Matthew Amidon
+ *
+ * Definition of the NullOutStream class.
+ */
+#ifndef __MLPACK_CORE_IO_NULLOUTSTREAM_HPP
+#define __MLPACK_CORE_IO_NULLOUTSTREAM_HPP
+
+#include <iostream>
+#include <streambuf>
+#include <string>
+
+namespace mlpack {
+namespace io {
+
+/**
+ * Used for Log::Debug when not compiled with debugging symbols. This class
+ * does nothing and should be optimized out entirely by the compiler.
+ */
+class NullOutStream {
+ public:
+ /**
+ * Does nothing.
+ */
+ NullOutStream() { }
+
+ /**
+ * Does nothing.
+ */
+ NullOutStream(const NullOutStream& other) { }
+
+ //! Does nothing.
+ NullOutStream& operator<<(bool val) { return *this; }
+ //! Does nothing.
+ NullOutStream& operator<<(short val) { return *this; }
+ //! Does nothing.
+ NullOutStream& operator<<(unsigned short val) { return *this; }
+ //! Does nothing.
+ NullOutStream& operator<<(int val) { return *this; }
+ //! Does nothing.
+ NullOutStream& operator<<(unsigned int val) { return *this; }
+ //! Does nothing.
+ NullOutStream& operator<<(long val) { return *this; }
+ //! Does nothing.
+ NullOutStream& operator<<(unsigned long val) { return *this; }
+ //! Does nothing.
+ NullOutStream& operator<<(float val) { return *this; }
+ //! Does nothing.
+ NullOutStream& operator<<(double val) { return *this; }
+ //! Does nothing.
+ NullOutStream& operator<<(long double val) { return *this; }
+ //! Does nothing.
+ NullOutStream& operator<<(void* val) { return *this; }
+ //! Does nothing.
+ NullOutStream& operator<<(const char* str) { return *this; }
+ //! Does nothing.
+ NullOutStream& operator<<(std::string& str) { return *this; }
+ //! Does nothing.
+ NullOutStream& operator<<(std::streambuf* sb) { return *this; }
+ //! Does nothing.
+ NullOutStream& operator<<(std::ostream& (*pf) (std::ostream&))
+ { return *this; }
+ //! Does nothing.
+ NullOutStream& operator<<(std::ios& (*pf) (std::ios&)) { return *this; }
+ //! Does nothing.
+ NullOutStream& operator<<(std::ios_base& (*pf) (std::ios_base&))
+ { return *this; }
+
+ //! Does nothing.
+ template<typename T>
+ NullOutStream& operator<<(T s)
+ { return *this; }
+};
+
+} // namespace io
+} // namespace mlpack
+
+#endif
Copied: mlpack/trunk/src/mlpack/core/util/option.cpp (from rev 10737, mlpack/trunk/src/mlpack/core/io/option.cpp)
===================================================================
--- mlpack/trunk/src/mlpack/core/util/option.cpp (rev 0)
+++ mlpack/trunk/src/mlpack/core/util/option.cpp 2011-12-14 12:44:53 UTC (rev 10774)
@@ -0,0 +1,34 @@
+/**
+ * @file option.cpp
+ * @author Ryan Curtin
+ *
+ * Implementation of the ProgramDoc class. The class registers itself with CLI
+ * when constructed.
+ */
+#include "cli.hpp"
+#include "option.hpp"
+
+#include <string>
+
+using namespace mlpack;
+using namespace mlpack::io;
+using namespace std;
+
+/**
+ * Construct a ProgramDoc object. When constructed, it will register itself
+ * with CLI. A fatal error will be thrown if more than one is constructed.
+ *
+ * @param programName Short string representing the name of the program.
+ * @param documentation Long string containing documentation on how to use the
+ * program and what it is. No newline characters are necessary; this is
+ * taken care of by CLI later.
+ * @param defaultModule Name of the default module.
+ */
+ProgramDoc::ProgramDoc(const std::string programName,
+ const std::string documentation) :
+ programName(programName),
+ documentation(documentation)
+{
+ // Register this with CLI.
+ CLI::RegisterProgramDoc(this);
+}
Copied: mlpack/trunk/src/mlpack/core/util/option.hpp (from rev 10737, mlpack/trunk/src/mlpack/core/io/option.hpp)
===================================================================
--- mlpack/trunk/src/mlpack/core/util/option.hpp (rev 0)
+++ mlpack/trunk/src/mlpack/core/util/option.hpp 2011-12-14 12:44:53 UTC (rev 10774)
@@ -0,0 +1,102 @@
+/**
+ * @file option.hpp
+ * @author Matthew Amidon
+ *
+ * Definition of the Option class, which is used to define parameters which are
+ * used by CLI. The ProgramDoc class also resides here.
+ */
+#ifndef __MLPACK_CORE_IO_OPTION_HPP
+#define __MLPACK_CORE_IO_OPTION_HPP
+
+#include <string>
+
+#include "cli.hpp"
+
+namespace mlpack {
+namespace io {
+
+/**
+ * A static object whose constructor registers a parameter with the CLI class.
+ * This should not be used outside of CLI itself, and you should use the
+ * PARAM_FLAG(), PARAM_DOUBLE(), PARAM_INT(), PARAM_STRING(), or other similar
+ * macros to declare these objects instead of declaring them directly.
+ *
+ * @see core/io/cli.hpp, mlpack::CLI
+ */
+template<typename N>
+class Option
+{
+ public:
+ /**
+ * Construct an Option object. When constructed, it will register
+ * itself with CLI.
+ *
+ * @param ignoreTemplate Whether or not the template type matters for this
+ * option. Essentially differs options with no value (flags) from those
+ * that do, and thus require a type.
+ * @param defaultValue Default value this parameter will be initialized to.
+ * @param identifier The name of the option (no dashes in front; for --help,
+ * we would pass "help").
+ * @param description A short string describing the option.
+ * @param parent Full pathname of the parent module that "owns" this option.
+ * The default is the root node (an empty string).
+ * @param required Whether or not the option is required at runtime.
+ */
+ Option(bool ignoreTemplate,
+ N defaultValue,
+ const char* identifier,
+ const char* description,
+ const char* parent = NULL,
+ bool required = false);
+
+ /**
+ * Constructs an Option object. When constructed, it will register a flag
+ * with CLI.
+ *
+ * @param identifier The name of the option (no dashes in front); for --help
+ * we would pass "help".
+ * @param description A short string describing the option.
+ * @param parent Full pathname of the parent module that "owns" this option.
+ * The default is the root node (an empty string).
+ */
+ Option(const char* identifier,
+ const char* description,
+ const char* parent = NULL);
+};
+
+/**
+ * A static object whose constructor registers program documentation with the
+ * CLI class. This should not be used outside of CLI itself, and you should use
+ * the PROGRAM_INFO() macro to declare these objects. Only one ProgramDoc
+ * object should ever exist.
+ *
+ * @see core/io/cli.hpp, mlpack::CLI
+ */
+class ProgramDoc
+{
+ public:
+ /**
+ * Construct a ProgramDoc object. When constructed, it will register itself
+ * with CLI.
+ *
+ * @param programName Short string representing the name of the program.
+ * @param documentation Long string containing documentation on how to use the
+ * program and what it is. No newline characters are necessary; this is
+ * taken care of by CLI later.
+ */
+ ProgramDoc(const std::string programName,
+ const std::string documentation);
+
+ //! The name of the program.
+ std::string programName;
+ //! Documentation for what the program does.
+ std::string documentation;
+};
+
+}; // namespace io
+}; // namespace mlpack
+
+// For implementations of templated functions
+#include "option_impl.hpp"
+
+#endif
Copied: mlpack/trunk/src/mlpack/core/util/option_impl.hpp (from rev 10737, mlpack/trunk/src/mlpack/core/io/option_impl.hpp)
===================================================================
--- mlpack/trunk/src/mlpack/core/util/option_impl.hpp (rev 0)
+++ mlpack/trunk/src/mlpack/core/util/option_impl.hpp 2011-12-14 12:44:53 UTC (rev 10774)
@@ -0,0 +1,63 @@
+/**
+ * @file option_impl.hpp
+ * @author Matthew Amidon
+ *
+ * Implementation of template functions for the Option class.
+ */
+#ifndef __MLPACK_CORE_IO_OPTION_IMPL_HPP
+#define __MLPACK_CORE_IO_OPTION_IMPL_HPP
+
+// Just in case it has not been included.
+#include "option.hpp"
+
+namespace mlpack {
+namespace io {
+
+/**
+ * Registers a parameter with CLI.
+ */
+template<typename N>
+Option<N>::Option(bool ignoreTemplate,
+ N defaultValue,
+ const char* identifier,
+ const char* description,
+ const char* alias,
+ bool required)
+{
+ if (ignoreTemplate)
+ {
+ if(alias == NULL)
+ alias = "";
+
+ CLI::Add(identifier, description, alias, required);
+ }
+ else
+ {
+ if(alias == NULL)
+ alias = "";
+
+ CLI::Add<N>(identifier, description, alias, required);
+
+ CLI::GetParam<N>(identifier) = defaultValue;
+ }
+}
+
+
+/**
+ * Registers a flag parameter with CLI.
+ */
+template<typename N>
+Option<N>::Option(const char* identifier,
+ const char* description,
+ const char* alias)
+{
+ if(alias == NULL)
+ alias = "";
+
+ CLI::AddFlag(identifier, description, alias);
+}
+
+}; // namespace io
+}; // namespace mlpack
+
+#endif
Copied: mlpack/trunk/src/mlpack/core/util/prefixedoutstream.cpp (from rev 10737, mlpack/trunk/src/mlpack/core/io/prefixedoutstream.cpp)
===================================================================
--- mlpack/trunk/src/mlpack/core/util/prefixedoutstream.cpp (rev 0)
+++ mlpack/trunk/src/mlpack/core/util/prefixedoutstream.cpp 2011-12-14 12:44:53 UTC (rev 10774)
@@ -0,0 +1,127 @@
+/**
+ * @file prefixedoutstream.cpp
+ * @author Ryan Curtin
+ * @author Matthew Amidon
+ *
+ * Implementation of PrefixedOutStream methods.
+ */
+#include <string>
+#include <iostream>
+#include <streambuf>
+#include <string.h>
+#include <stdlib.h>
+
+#include "prefixedoutstream.hpp"
+
+using namespace mlpack::io;
+
+/**
+ * These are all necessary because gcc's template mechanism does not seem smart
+ * enough to figure out what I want to pass into operator<< without these. That
+ * may not be the actual case, but it works when these is here.
+ */
+
+PrefixedOutStream& PrefixedOutStream::operator<<(bool val)
+{
+ BaseLogic<bool>(val);
+ return *this;
+}
+
+PrefixedOutStream& PrefixedOutStream::operator<<(short val)
+{
+ BaseLogic<short>(val);
+ return *this;
+}
+
+PrefixedOutStream& PrefixedOutStream::operator<<(unsigned short val)
+{
+ BaseLogic<unsigned short>(val);
+ return *this;
+}
+
+PrefixedOutStream& PrefixedOutStream::operator<<(int val)
+{
+ BaseLogic<int>(val);
+ return *this;
+}
+
+PrefixedOutStream& PrefixedOutStream::operator<<(unsigned int val)
+{
+ BaseLogic<unsigned int>(val);
+ return *this;
+}
+
+PrefixedOutStream& PrefixedOutStream::operator<<(long val)
+{
+ BaseLogic<long>(val);
+ return *this;
+}
+
+PrefixedOutStream& PrefixedOutStream::operator<<(unsigned long val)
+{
+ BaseLogic<unsigned long>(val);
+ return *this;
+}
+
+PrefixedOutStream& PrefixedOutStream::operator<<(float val)
+{
+ BaseLogic<float>(val);
+ return *this;
+}
+
+PrefixedOutStream& PrefixedOutStream::operator<<(double val)
+{
+ BaseLogic<double>(val);
+ return *this;
+}
+
+PrefixedOutStream& PrefixedOutStream::operator<<(long double val)
+{
+ BaseLogic<long double>(val);
+ return *this;
+}
+
+PrefixedOutStream& PrefixedOutStream::operator<<(void* val)
+{
+ BaseLogic<void*>(val);
+ return *this;
+}
+
+PrefixedOutStream& PrefixedOutStream::operator<<(const char* str)
+{
+ BaseLogic<const char*>(str);
+ return *this;
+}
+
+
+PrefixedOutStream& PrefixedOutStream::operator<<(std::string& str)
+{
+ BaseLogic<std::string&>(str);
+ return *this;
+}
+
+PrefixedOutStream& PrefixedOutStream::operator<<(std::streambuf* sb)
+{
+ BaseLogic<std::streambuf*>(sb);
+ return *this;
+}
+
+PrefixedOutStream& PrefixedOutStream::operator<<(
+ std::ostream& (*pf)(std::ostream&))
+{
+ BaseLogic<std::ostream& (*)(std::ostream&)>(pf);
+ return *this;
+}
+
+PrefixedOutStream& PrefixedOutStream::operator<<(std::ios& (*pf)(std::ios&))
+{
+ BaseLogic<std::ios& (*)(std::ios&)>(pf);
+ return *this;
+}
+
+PrefixedOutStream& PrefixedOutStream::operator<<(
+ std::ios_base& (*pf) (std::ios_base&))
+{
+ BaseLogic<std::ios_base& (*)(std::ios_base&)>(pf);
+ return *this;
+}
Copied: mlpack/trunk/src/mlpack/core/util/prefixedoutstream.hpp (from rev 10737, mlpack/trunk/src/mlpack/core/io/prefixedoutstream.hpp)
===================================================================
--- mlpack/trunk/src/mlpack/core/util/prefixedoutstream.hpp (rev 0)
+++ mlpack/trunk/src/mlpack/core/util/prefixedoutstream.hpp 2011-12-14 12:44:53 UTC (rev 10774)
@@ -0,0 +1,147 @@
+/**
+ * @file prefixedoutstream.hpp
+ * @author Ryan Curtin
+ * @author Matthew Amidon
+ *
+ * Declaration of the PrefixedOutStream class.
+ */
+#ifndef __MLPACK_CORE_IO_PREFIXEDOUTSTREAM_HPP
+#define __MLPACK_CORE_IO_PREFIXEDOUTSTREAM_HPP
+
+#include <iostream>
+#include <iomanip>
+#include <string>
+#include <streambuf>
+
+#include <boost/lexical_cast.hpp>
+
+namespace mlpack {
+namespace io {
+
+/**
+ * Allows us to output to an ostream with a prefix at the beginning of each
+ * line, in the same way we would output to cout or cerr. The prefix is
+ * specified in the constructor (as well as the destination ostream). A newline
+ * must be passed to the stream, and then the prefix will be prepended to the
+ * next line. For example,
+ *
+ * @code
+ * PrefixedOutStream outstr(std::cout, "[TEST] ");
+ * outstr << "Hello world I like " << 7.5;
+ * outstr << "...Continue" << std::endl;
+ * outstr << "After the CR\n" << std::endl;
+ * @endcode
+ *
+ * would give, on std::cout,
+ *
+ * @code
+ * [TEST] Hello world I like 7.5...Continue
+ * [TEST] After the CR
+ * [TEST]
+ * @endcode
+ *
+ * These objects are used for the mlpack::Log levels (DEBUG, INFO, WARN, and
+ * FATAL).
+ */
+class PrefixedOutStream
+{
+ public:
+ /**
+ * Set up the PrefixedOutStream.
+ *
+ * @param destination ostream which receives output from this object.
+ * @param prefix The prefix to prepend to each line.
+ */
+ PrefixedOutStream(std::ostream& destination,
+ const char* prefix,
+ bool ignoreInput = false,
+ bool fatal = false) :
+ destination(destination),
+ ignoreInput(ignoreInput),
+ prefix(prefix),
+ // We want the first call to operator<< to prefix the prefix so we set
+ // carriageReturned to true.
+ carriageReturned(true),
+ fatal(fatal)
+ { /* nothing to do */ }
+
+ //! Write a bool to the stream.
+ PrefixedOutStream& operator<<(bool val);
+ //! Write a short to the stream.
+ PrefixedOutStream& operator<<(short val);
+ //! Write an unsigned short to the stream.
+ PrefixedOutStream& operator<<(unsigned short val);
+ //! Write an int to the stream.
+ PrefixedOutStream& operator<<(int val);
+ //! Write an unsigned int to the stream.
+ PrefixedOutStream& operator<<(unsigned int val);
+ //! Write a long to the stream.
+ PrefixedOutStream& operator<<(long val);
+ //! Write an unsigned long to the stream.
+ PrefixedOutStream& operator<<(unsigned long val);
+ //! Write a float to the stream.
+ PrefixedOutStream& operator<<(float val);
+ //! Write a double to the stream.
+ PrefixedOutStream& operator<<(double val);
+ //! Write a long double to the stream.
+ PrefixedOutStream& operator<<(long double val);
+ //! Write a void pointer to the stream.
+ PrefixedOutStream& operator<<(void* val);
+ //! Write a character array to the stream.
+ PrefixedOutStream& operator<<(const char* str);
+ //! Write a string to the stream.
+ PrefixedOutStream& operator<<(std::string& str);
+ //! Write a streambuf to the stream.
+ PrefixedOutStream& operator<<(std::streambuf* sb);
+ //! Write an ostream manipulator function to the stream.
+ PrefixedOutStream& operator<<(std::ostream& (*pf)(std::ostream&));
+ //! Write an ios manipulator function to the stream.
+ PrefixedOutStream& operator<<(std::ios& (*pf)(std::ios&));
+ //! Write an ios_base manipulator function to the stream.
+ PrefixedOutStream& operator<<(std::ios_base& (*pf)(std::ios_base&));
+
+ //! Write anything else to the stream.
+ template<typename T>
+ PrefixedOutStream& operator<<(T s);
+
+ //! The output stream that all data is to be sent too; example: std::cout.
+ std::ostream& destination;
+
+ //! Discards input, prints nothing if true.
+ bool ignoreInput;
+
+ private:
+ /**
+ * @brief Conducts the base logic required in all the operator << overloads.
+ * Mostly just a good idea to reduce copy-pasta.
+ *
+ * @tparam T The type of the data to output.
+ * @param val The The data to be output.
+ */
+ template<typename T>
+ void BaseLogic(T val);
+
+ /**
+ * Output the prefix, but only if we need to and if we are allowed to.
+ */
+ inline void PrefixIfNeeded();
+
+ //! Contains the prefix we must prepend to each line.
+ std::string prefix;
+
+ //! If true, the previous call to operator<< encountered a CR, and a prefix
+ //! will be necessary.
+ bool carriageReturned;
+
+ //! If true, the application will terminate with an error code when a CR is
+ //! encountered.
+ bool fatal;
+};
+
+// Template definitions
+#include "prefixedoutstream_impl.hpp"
+
+} // namespace io
+} // namespace mlpack
+
+#endif
Copied: mlpack/trunk/src/mlpack/core/util/prefixedoutstream_impl.hpp (from rev 10737, mlpack/trunk/src/mlpack/core/io/prefixedoutstream_impl.hpp)
===================================================================
--- mlpack/trunk/src/mlpack/core/util/prefixedoutstream_impl.hpp (rev 0)
+++ mlpack/trunk/src/mlpack/core/util/prefixedoutstream_impl.hpp 2011-12-14 12:44:53 UTC (rev 10774)
@@ -0,0 +1,107 @@
+/**
+ * @file prefixedoutstream.hpp
+ * @author Ryan Curtin
+ * @author Matthew Amidon
+ *
+ * Implementation of templated PrefixedOutStream member functions.
+ */
+#ifndef __MLPACK_CORE_IO_PREFIXEDOUTSTREAM_IMPL_HPP
+#define __MLPACK_CORE_IO_PREFIXEDOUTSTREAM_IMPL_HPP
+
+// Just in case it hasn't been included.
+#include "prefixedoutstream.hpp"
+
+template<typename T>
+PrefixedOutStream& PrefixedOutStream::operator<<(T s)
+{
+ BaseLogic<T>(s);
+
+ return *this;
+}
+
+template<typename T>
+void PrefixedOutStream::BaseLogic(T val)
+{
+ // We will use this to track whether or not we need to terminate at the end of
+ // this call (only for streams which terminate after a newline).
+ bool newlined = false;
+
+ // If we need to, output the prefix.
+ PrefixIfNeeded();
+
+ // Now we try to output the T (whatever it is).
+ try
+ {
+ std::string line = boost::lexical_cast<std::string>(val);
+
+ // If the length of the casted thing was 0, it may have been a stream
+ // manipulator, so send it directly to the stream and don't ask questions.
+ if (line.length() == 0)
+ {
+ // The prefix cannot be necessary at this point.
+ if (!ignoreInput) // Only if the user wants it.
+ destination << val;
+
+ return;
+ }
+
+ // Now, we need to check for newlines in this line. If we find one, output
+ // up until the newline, then output the newline and the prefix and continue
+ // looking.
+ size_t nl;
+ size_t pos = 0;
+ while ((nl = line.find('\n', pos)) != std::string::npos)
+ {
+ PrefixIfNeeded();
+
+ // Only output if the user wants it.
+ if (!ignoreInput)
+ {
+ destination << line.substr(pos, nl - pos);
+ destination << std::endl;
+ newlined = true;
+ }
+
+ carriageReturned = true; // Regardless of whether or not we display it.
+
+ pos = nl + 1;
+ }
+
+ if (pos != line.length()) // We need to display the rest.
+ {
+ PrefixIfNeeded();
+ if (!ignoreInput)
+ destination << line.substr(pos);
+ }
+ }
+ catch (boost::bad_lexical_cast &e)
+ {
+ // Warn the user that there was a failure.
+ PrefixIfNeeded();
+ if (!ignoreInput)
+ {
+ destination << "Failed lexical_cast<std::string>(T) for output; output"
+ " not shown." << std::endl;
+ newlined = true;
+ }
+ }
+
+ // If we displayed a newline and we need to terminate afterwards, do that.
+ if (fatal && newlined)
+ exit(1);
+}
+
+// This is an inline function (that is why it is here and not in .cc).
+void PrefixedOutStream::PrefixIfNeeded()
+{
+ // If we need to, output a prefix.
+ if (carriageReturned)
+ {
+ if (!ignoreInput) // But only if we are allowed to.
+ destination << prefix;
+
+ carriageReturned = false; // Denote that the prefix has been displayed.
+ }
+}
+
+#endif // MLPACK_CLI_PREFIXEDOUTSTREAM_IMPL_H
Modified: mlpack/trunk/src/mlpack/core/util/save_restore_utility.hpp
===================================================================
--- mlpack/trunk/src/mlpack/core/utilities/save_restore_utility.hpp 2011-12-13 07:23:09 UTC (rev 10737)
+++ mlpack/trunk/src/mlpack/core/util/save_restore_utility.hpp 2011-12-14 12:44:53 UTC (rev 10774)
@@ -32,62 +32,76 @@
* parameters contains a list of names and parameters in string form.
*/
std::map<std::string, std::string> parameters;
+
/**
* RecurseOnNodes performs a depth first search of the XML tree.
*/
void RecurseOnNodes(xmlNode* n);
+
public:
SaveRestoreUtility() {}
~SaveRestoreUtility() { parameters.clear(); }
+
/**
* ReadFile reads an XML tree from a file.
*/
bool ReadFile(std::string filename);
+
/**
* WriteFile writes the XML tree to a file.
*/
bool WriteFile(std::string filename);
+
/**
* LoadParameter loads a parameter from the parameters map.
*/
template<typename T>
T& LoadParameter(T& t, std::string name);
+
/**
* LoadParameter loads a parameter from the parameters map.
*/
template<typename T>
std::vector<T>& LoadParameter(std::vector<T>& v, std::string name);
+
/**
* LoadParameter loads a character from the parameters map.
*/
char LoadParameter(char c, std::string name);
+
/**
* LoadParameter loads a string from the parameters map.
*/
std::string LoadParameter(std::string str, std::string name);
+
/**
* LoadParameter loads an arma::mat from the parameters map.
*/
arma::mat& LoadParameter(arma::mat& matrix, std::string name);
+
/**
* SaveParameter saves a parameter to the parameters map.
*/
template<typename T>
void SaveParameter(T& t, std::string name);
+
/**
* SaveParameter saves a parameter to the parameters map.
*/
template<typename T>
void SaveParameter(std::vector<T>& v, std::string name);
+
/**
* SaveParameter saves a character to the parameters map.
*/
void SaveParameter(char c, std::string name);
+
/**
* SaveParameter saves an arma::mat to the parameters map.
*/
void SaveParameter(arma::mat& mat, std::string name);
};
+
} /* namespace utilities */
} /* namespace mlpack */
Deleted: mlpack/trunk/src/mlpack/core/util/timers.cpp
===================================================================
--- mlpack/trunk/src/mlpack/core/utilities/timers.cpp 2011-12-13 07:23:09 UTC (rev 10737)
+++ mlpack/trunk/src/mlpack/core/util/timers.cpp 2011-12-14 12:44:53 UTC (rev 10774)
@@ -1,134 +0,0 @@
-/**
- * @file timers.cpp
- * @author Matthew Amidon
- *
- * Implementation of timers.
- */
-#include "timers.hpp"
-#include "../io/cli.hpp"
-#include "../io/log.hpp"
-
-#include <map>
-#include <string>
-
-using namespace mlpack;
-
-std::map<std::string, timeval> Timers::timers;
-
-std::map<std::string, timeval> Timers::GetAllTimers()
-{
- return timers;
-}
-
-timeval Timers::GetTimer(const char* timerName)
-{
- std::string name(timerName);
- return timers[name];
-}
-
-void Timers::PrintTimer(const char* timerName)
-{
- std::string name=timerName;
- timeval& t = timers[name];
- Log::Info << t.tv_sec << "." << std::setw(6) << std::setfill('0')
- << t.tv_usec << "s";
-
- // Also output convenient day/hr/min/sec.
- int days = t.tv_sec / 86400; // Integer division rounds down.
- int hours = (t.tv_sec % 86400) / 3600;
- int minutes = (t.tv_sec % 3600) / 60;
- int seconds = (t.tv_sec % 60);
- // No output if it didn't even take a minute.
- if (!(days == 0 && hours == 0 && minutes == 0))
- {
- bool output = false; // Denotes if we have output anything yet.
- Log::Info << " (";
-
- // Only output units if they have nonzero values (yes, a bit tedious).
- if (days > 0)
- {
- Log::Info << days << " days";
- output = true;
- }
-
- if (hours > 0)
- {
- if (output)
- Log::Info << ", ";
- Log::Info << hours << " hrs";
- output = true;
- }
-
- if (minutes > 0)
- {
- if (output)
- Log::Info << ", ";
- Log::Info << minutes << " mins";
- output = true;
- }
-
- if (seconds > 0)
- {
- if (output)
- Log::Info << ",";
- Log::Info << seconds << "." << std::setw(1) << (t.tv_usec / 100000) <<
- "secs";
- output = true;
- }
-
- Log::Info << ")";
- }
-
- Log::Info << std::endl;
-}
-
-void Timers::StartTimer(const char* timerName)
-{
- // Convert the name to std::string.
- std::string name(timerName);
- timeval tmp;
-
- tmp.tv_sec = 0;
- tmp.tv_usec = 0;
-
-#ifndef _WIN32
- gettimeofday(&tmp, NULL);
-#else
- FileTimeToTimeVal(&tmp);
-#endif
- timers[name] = tmp;
-}
-
-void Timers::StopTimer(const char* timerName)
-{
- std::string name(timerName);
- timeval delta, b, a = timers[name];
-
-#ifndef _WIN32
- gettimeofday(&b, NULL);
-#else
- FileTimeToTimeVal(&b);
-#endif
- // Calculate the delta time.
- timersub(&b, &a, &delta);
- timers[name] = delta;
-}
-
-#ifdef _WIN32
-void Timers::FileTimeToTimeVal(timeval* tv)
-{
- FILETIME ftime;
- uint64_t ptime = 0;
- // Acquire the file time.
- GetSystemTimeAsFileTime(&ftime);
- // Now convert FILETIME to timeval.
- ptime |= ftime.dwHighDateTime;
- ptime = ptime << 32;
- ptime |= ftime.dwLowDateTime;
- ptime /= 10;
- ptime -= DELTA_EPOC_IN_MICROSECONDS;
-
- tv.tv_sec = (long) (ptime / 1000000UL);
- tv.tv_usec = (long) (ptime % 1000000UL);
-}
-#endif // _WIN32
Copied: mlpack/trunk/src/mlpack/core/util/timers.cpp (from rev 10767, mlpack/trunk/src/mlpack/core/io/timers.cpp)
===================================================================
--- mlpack/trunk/src/mlpack/core/util/timers.cpp (rev 0)
+++ mlpack/trunk/src/mlpack/core/util/timers.cpp 2011-12-14 12:44:53 UTC (rev 10774)
@@ -0,0 +1,153 @@
+/**
+ * @file timers.cpp
+ * @author Matthew Amidon
+ *
+ * Implementation of timers.
+ */
+#include "timers.hpp"
+#include "cli.hpp"
+#include "log.hpp"
+
+#include <map>
+#include <string>
+
+using namespace mlpack;
+
+/**
+ * Start the given timer.
+ */
+void Timer::Start(const std::string name)
+{
+ CLI::GetSingleton().timer.StartTimer(name);
+}
+
+/**
+ * Stop the given timer.
+ */
+void Timer::Stop(const std::string name)
+{
+ CLI::GetSingleton().timer.StopTimer(name);
+}
+
+/**
+ * Get the given timer.
+ */
+timeval Timer::Get(const std::string name)
+{
+ return CLI::GetSingleton().timer.GetTimer(name);
+}
+
+std::map<std::string, timeval>& Timers::GetAllTimers()
+{
+ return timers;
+}
+
+timeval Timers::GetTimer(const std::string timerName)
+{
+ std::string name(timerName);
+ return timers[name];
+}
+
+void Timers::PrintTimer(const std::string timerName)
+{
+ timeval& t = timers[timerName];
+ Log::Info << t.tv_sec << "." << std::setw(6) << std::setfill('0')
+ << t.tv_usec << "s";
+
+ // Also output convenient day/hr/min/sec.
+ int days = t.tv_sec / 86400; // Integer division rounds down.
+ int hours = (t.tv_sec % 86400) / 3600;
+ int minutes = (t.tv_sec % 3600) / 60;
+ int seconds = (t.tv_sec % 60);
+ // No output if it didn't even take a minute.
+ if (!(days == 0 && hours == 0 && minutes == 0))
+ {
+ bool output = false; // Denotes if we have output anything yet.
+ Log::Info << " (";
+
+ // Only output units if they have nonzero values (yes, a bit tedious).
+ if (days > 0)
+ {
+ Log::Info << days << " days";
+ output = true;
+ }
+
+ if (hours > 0)
+ {
+ if (output)
+ Log::Info << ", ";
+ Log::Info << hours << " hrs";
+ output = true;
+ }
+
+ if (minutes > 0)
+ {
+ if (output)
+ Log::Info << ", ";
+ Log::Info << minutes << " mins";
+ output = true;
+ }
+
+ if (seconds > 0)
+ {
+ if (output)
+ Log::Info << ",";
+ Log::Info << seconds << "." << std::setw(1) << (t.tv_usec / 100000) <<
+ "secs";
+ output = true;
+ }
+
+ Log::Info << ")";
+ }
+
+ Log::Info << std::endl;
+}
+
+void Timers::StartTimer(const std::string timerName)
+{
+ timeval tmp;
+
+ tmp.tv_sec = 0;
+ tmp.tv_usec = 0;
+
+#ifndef _WIN32
+ gettimeofday(&tmp, NULL);
+#else
+ FileTimeToTimeVal(&tmp);
+#endif
+ timers[timerName] = tmp;
+}
+
+void Timers::StopTimer(const std::string timerName)
+{
+ timeval delta, b, a = timers[timerName];
+
+#ifndef _WIN32
+ gettimeofday(&b, NULL);
+#else
+ FileTimeToTimeVal(&b);
+#endif
+ // Calculate the delta time.
+ timersub(&b, &a, &delta);
+ timers[timerName] = delta;
+}
+
+#ifdef _WIN32
+void Timers::FileTimeToTimeVal(timeval* tv)
+{
+ FILETIME ftime;
+ uint64_t ptime = 0;
+ // Acquire the file time.
+ GetSystemTimeAsFileTime(&ftime);
+ // Now convert FILETIME to timeval.
+ ptime |= ftime.dwHighDateTime;
+ ptime = ptime << 32;
+ ptime |= ftime.dwLowDateTime;
+ ptime /= 10;
+ ptime -= DELTA_EPOC_IN_MICROSECONDS;
+
+ tv.tv_sec = (long) (ptime / 1000000UL);
+ tv.tv_usec = (long) (ptime % 1000000UL);
+}
+
+#endif // _WIN32
Deleted: mlpack/trunk/src/mlpack/core/util/timers.hpp
===================================================================
--- mlpack/trunk/src/mlpack/core/utilities/timers.hpp 2011-12-13 07:23:09 UTC (rev 10737)
+++ mlpack/trunk/src/mlpack/core/util/timers.hpp 2011-12-14 12:44:53 UTC (rev 10774)
@@ -1,79 +0,0 @@
-/**
- * @file timers.hpp
- * @author Matthew Amidon
- *
- * Timers for MLPACK.
- */
-#ifndef __MLPACK_CORE_UTILITIES_TIMERS_HPP
-#define __MLPACK_CORE_UTILITIES_TIMERS_HPP
-
-#include <map>
-#include <string>
-
-#ifndef _WIN32
- #include <sys/time.h> //linux
-#else
- #include <winsock.h> //timeval on windows
- #include <windows.h> //GetSystemTimeAsFileTime on windows
-//gettimeofday has no equivalent will need to write extra code for that.
- #if defined(_MSC_VER) || defined(_MSC_EXTENSCLINS)
- #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
- #else
- #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
- #endif
-#endif //_WIN32
-
-namespace mlpack {
-
-class Timers
-{
- public:
- /**
- * Returns a copy of all the timers used via this interface.
- */
- static std::map<std::string, timeval> GetAllTimers();
-
- /**
- * Returns a copy of the timer specified.
- *
- * @param timerName The name of the timer in question.
- */
- static timeval GetTimer(const char* timerName);
-
- /**
- * Prints the specified timer. If it took longer than a minute to complete
- * the timer will be displayed in days, hours, and minutes as well.
- *
- * @param timerName The name of the timer in question.
- */
- static void PrintTimer(const char* timerName);
-
- /**
- * Initializes a timer, available like a normal value specified on
- * the command line. Timers are of type timval
- *
- * @param timerName The name of the timer in question.
- */
- static void StartTimer(const char* timerName);
-
- /**
- * Halts the timer, and replaces it's value with
- * the delta time from it's start
- *
- * @param timerName The name of the timer in question.
- */
- static void StopTimer(const char* timerName);
-
- private:
- static std::map<std::string, timeval> timers;
-
- void FileTimeToTimeVal(timeval* tv);
-
- // Don't want any instances floating around.
- Timers();
- ~Timers();
-};
-
-}; // namespace mlpack
-
-#endif // __MLPACK_CORE_UTILITIES_TIMERS_HPP
Copied: mlpack/trunk/src/mlpack/core/util/timers.hpp (from rev 10767, mlpack/trunk/src/mlpack/core/io/timers.hpp)
===================================================================
--- mlpack/trunk/src/mlpack/core/util/timers.hpp (rev 0)
+++ mlpack/trunk/src/mlpack/core/util/timers.hpp 2011-12-14 12:44:53 UTC (rev 10774)
@@ -0,0 +1,104 @@
+/**
+ * @file timers.hpp
+ * @author Matthew Amidon
+ *
+ * Timers for MLPACK.
+ */
+#ifndef __MLPACK_CORE_UTILITIES_TIMERS_HPP
+#define __MLPACK_CORE_UTILITIES_TIMERS_HPP
+
+#include <map>
+#include <string>
+
+#ifndef _WIN32
+ #include <sys/time.h> //linux
+#else
+ #include <winsock.h> //timeval on windows
+ #include <windows.h> //GetSystemTimeAsFileTime on windows
+//gettimeofday has no equivalent will need to write extra code for that.
+ #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
+ #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
+ #else
+ #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
+ #endif
+#endif //_WIN32
+
+namespace mlpack {
+
+class Timers
+{
+ public:
+ //! Nothing to do for the constructor.
+ Timers() { }
+
+ /**
+ * Returns a copy of all the timers used via this interface.
+ */
+ std::map<std::string, timeval>& GetAllTimers();
+
+ /**
+ * Returns a copy of the timer specified.
+ *
+ * @param timerName The name of the timer in question.
+ */
+ timeval GetTimer(const std::string timerName);
+
+ /**
+ * Prints the specified timer. If it took longer than a minute to complete
+ * the timer will be displayed in days, hours, and minutes as well.
+ *
+ * @param timerName The name of the timer in question.
+ */
+ void PrintTimer(const std::string timerName);
+
+ /**
+ * Initializes a timer, available like a normal value specified on
+ * the command line. Timers are of type timval
+ *
+ * @param timerName The name of the timer in question.
+ */
+ void StartTimer(const std::string timerName);
+
+ /**
+ * Halts the timer, and replaces it's value with
+ * the delta time from it's start
+ *
+ * @param timerName The name of the timer in question.
+ */
+ void StopTimer(const std::string timerName);
+
+ private:
+ std::map<std::string, timeval> timers;
+
+ void FileTimeToTimeVal(timeval* tv);
+};
+
+// Static access methods.
+class Timer
+{
+ public:
+ /**
+ * Start the given timer.
+ *
+ * @param name Name of timer to be started.
+ */
+ static void Start(const std::string name);
+
+ /**
+ * Stop the given timer.
+ *
+ * @param name Name of timer to be stopped.
+ */
+ static void Stop(const std::string name);
+
+ /**
+ * Get the value of the given timer.
+ *
+ * @param name Name of timer to return value of.
+ */
+ static timeval Get(const std::string name);
+};
+
+}; // namespace mlpack
+
+#endif // __MLPACK_CORE_UTILITIES_TIMERS_HPP
Modified: mlpack/trunk/src/mlpack/core.hpp
===================================================================
--- mlpack/trunk/src/mlpack/core.hpp 2011-12-14 12:41:57 UTC (rev 10773)
+++ mlpack/trunk/src/mlpack/core.hpp 2011-12-14 12:44:53 UTC (rev 10774)
@@ -88,12 +88,12 @@
// Now MLPACK-specific includes.
#include <mlpack/core/arma_extend/arma_extend.hpp> // Includes Armadillo.
-#include <mlpack/core/io/log.hpp>
-#include <mlpack/core/io/cli.hpp>
+#include <mlpack/core/util/log.hpp>
+#include <mlpack/core/util/cli.hpp>
#include <mlpack/core/data/load.hpp>
#include <mlpack/core/data/save.hpp>
#include <mlpack/core/math/math_misc.hpp>
#include <mlpack/core/math/range.hpp>
-#include <mlpack/core/utilities/save_restore_utility.hpp>
+#include <mlpack/core/util/save_restore_utility.hpp>
#endif
Modified: mlpack/trunk/src/mlpack/methods/gmm/gmm_main.cpp
===================================================================
--- mlpack/trunk/src/mlpack/methods/gmm/gmm_main.cpp 2011-12-14 12:41:57 UTC (rev 10773)
+++ mlpack/trunk/src/mlpack/methods/gmm/gmm_main.cpp 2011-12-14 12:44:53 UTC (rev 10774)
@@ -13,6 +13,8 @@
PARAM_STRING_REQ("data", "A file containing the data on which the model has to "
"be fit.", "D");
PARAM_INT("gaussians", "g", "G", 1);
+PARAM_STRING("output_file", "The file to write the trained GMM parameters into "
+ "(as XML).", "gmm.xml");
using namespace mlpack;
using namespace mlpack::gmm;
@@ -33,6 +35,8 @@
Timer::Stop("em");
////// OUTPUT RESULTS //////
+
+
// We need a better solution for this. So, currently, we do nothing.
// XML is probably the right tool for the job.
}
Modified: mlpack/trunk/src/mlpack/tests/save_restore_utility_test.cpp
===================================================================
--- mlpack/trunk/src/mlpack/tests/save_restore_utility_test.cpp 2011-12-14 12:41:57 UTC (rev 10773)
+++ mlpack/trunk/src/mlpack/tests/save_restore_utility_test.cpp 2011-12-14 12:44:53 UTC (rev 10774)
@@ -4,7 +4,7 @@
*
* Here we have tests for the SaveRestoreModel class.
*/
-#include <mlpack/core/utilities/save_restore_utility.hpp>
+#include <mlpack/core/util/save_restore_utility.hpp>
#include <boost/test/unit_test.hpp>
More information about the mlpack-svn
mailing list