Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow input and output parameters to be specified with PARAM_* macros #723

Merged
merged 22 commits into from Jul 20, 2016
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
3fc0fbf
Refactor to support input and output parameters.
rcurtin Jul 12, 2016
6ff92c9
Refactor programs to support input and output parameters.
rcurtin Jul 12, 2016
7bed982
Merge branch 'master' into bindings
rcurtin Jul 13, 2016
7afd99c
Fix duplicate options.
rcurtin Jul 13, 2016
2e740c5
Don't print extra lines.
rcurtin Jul 13, 2016
aac0b7f
Warn when the user does not specify a file to test but asks for output.
rcurtin Jul 13, 2016
4cec0a3
Fix misspelled parameter name.
rcurtin Jul 13, 2016
fe6ad34
Fix parameter name issues.
rcurtin Jul 13, 2016
d665abe
Better warnings when --output_file is not specified.
rcurtin Jul 13, 2016
280feb5
Correct warning for no output.
rcurtin Jul 13, 2016
5506cbc
There is no such thing as a required output option.
rcurtin Jul 13, 2016
156c92e
Update to --output_predictions_file, but keep old version for reverse…
rcurtin Jul 13, 2016
511596d
Only print output parameters that are strings and end with "_file".
rcurtin Jul 13, 2016
52ffd75
Print any output options at the end of the run.
rcurtin Jul 13, 2016
e11fbbb
Fix wrong conditional for printing warning.
rcurtin Jul 13, 2016
bbc0efc
Add warning for kernel_pca when --output_file is not specified.
rcurtin Jul 13, 2016
846af86
Add reverse compatibility for some incorrectly-named parameters.
rcurtin Jul 15, 2016
95ee836
Fix incorrect conditionals. Thanks to Sergiu Deitsch for pointing th…
rcurtin Jul 16, 2016
7a34fe3
Update documentation; 'parent' is very outdated; that parameter is ac…
rcurtin Jul 18, 2016
c852746
Fix --test_file: it is an input parameter.
rcurtin Jul 18, 2016
b36b3df
Too much Java lately: no 'd' suffix necessary.
rcurtin Jul 18, 2016
5853b8a
Don't add unknown options for Visual Studio.
rcurtin Jul 18, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
126 changes: 105 additions & 21 deletions src/mlpack/core/util/cli.cpp
Expand Up @@ -50,6 +50,9 @@ CLI::CLI(const CLI& other) : desc(other.desc),

CLI::~CLI()
{
// We need to print any output options.
PrintOutput();

// Terminate the program timers.
std::map<std::string, std::chrono::microseconds>::iterator it;
for (it = timer.GetAllTimers().begin(); it != timer.GetAllTimers().end();
Expand Down Expand Up @@ -95,11 +98,14 @@ CLI::~CLI()
* @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.
* @param input If true, the parameter is an input parameter (not an output
* parameter).
*/
void CLI::Add(const std::string& identifier,
const std::string& description,
const std::string& alias,
bool required)
const bool required,
const bool input)
{
po::options_description& desc = CLI::GetSingleton().desc;

Expand Down Expand Up @@ -129,6 +135,13 @@ void CLI::Add(const std::string& identifier,
if (required)
GetSingleton().requiredOptions.push_front(identifier);

// Depending on whether the option is input or output, add it to the list of
// input or output options.
if (input)
GetSingleton().inputOptions.push_front(identifier);
else
GetSingleton().outputOptions.push_front(identifier);

return;
}

Expand Down Expand Up @@ -450,6 +463,60 @@ void CLI::RemoveDuplicateFlags(po::basic_parsed_options<char>& bpo)
}
}

// Prints any output options.
void CLI::PrintOutput()
{
gmap_t& gmap = GetSingleton().globalValues;
gmap_t::iterator iter;

for (iter = gmap.begin(); iter != gmap.end(); ++iter)
{
std::string key = iter->first;
ParamData data = iter->second;

const std::list<std::string>& inputOptions = GetSingleton().inputOptions;
const bool input = (std::find(std::begin(inputOptions),
std::end(inputOptions), key) != std::end(inputOptions));

// Ignore input options.
if (input)
continue;

// Ignore string output options that end in _file.
if ((data.tname == TYPENAME(std::string)) &&
(data.name.substr(data.name.size() - 5, 5) == "_file"))
continue;

// Reverse compatibility; should be removed for mlpack 3.0.0. Don't print
// some options that have only been kept for reverse compatibility.
if (data.name == "output_predictions" ||
data.name == "output_ic" ||
data.name == "output_unmixing")
continue;

// Now, we must print it, so figure out what the type is.
if (data.tname == TYPENAME(std::string))
{
std::string value = GetParam<std::string>(key);
std::cout << key << ": " << value << std::endl;
}
else if (data.tname == TYPENAME(int))
{
int value = GetParam<int>(key);
std::cout << key << ": " << value << std::endl;
}
else if (data.tname == TYPENAME(double))
{
double value = GetParam<double>(key);
std::cout << key << ": " << value << std::endl;
}
else
{
std::cout << key << ": unknown data type" << std::endl;
}
}
}

/* Prints out the current hierarchy. */
void CLI::Print()
{
Expand Down Expand Up @@ -567,7 +634,7 @@ void CLI::PrintHelp(const std::string& param)
else
std::cout << "[undocumented program]" << std::endl << std::endl;

for (size_t pass = 0; pass < 2; ++pass)
for (size_t pass = 0; pass < 3; ++pass)
{
bool printedHeader = false;

Expand All @@ -580,29 +647,46 @@ void CLI::PrintHelp(const std::string& param)
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.
// Is the option required or not? And is it an input option or not?
const std::list<std::string>& requiredOptions =
GetSingleton().requiredOptions;
const std::list<std::string>& inputOptions = GetSingleton().inputOptions;

const bool required = (std::find(std::begin(requiredOptions),
std::end(requiredOptions), key) != std::end(requiredOptions));
const bool input = (std::find(std::begin(inputOptions),
std::end(inputOptions), key) != std::end(inputOptions));

// Filter un-printed options.
if ((pass == 0) && !(required && input)) // Required input options only.
continue;
if ((pass == 1) && !(!required && input)) // Optional input options only.
continue;
if ((pass == 2) && input) // Output options only (always optional).
continue;

// Only print string output options that end in "_file".
if ((pass == 2) && ((data.tname != TYPENAME(std::string)) ||
(data.name.substr(data.name.size() - 5, 5) != "_file")))
continue;

// For reverse compatibility: this can be removed when these options are
// gone in mlpack 3.0.0. We don't want to print the deprecated options.
if (data.name == "inputFile")
continue;

if (!printedHeader)
{
printedHeader = true;
if (pass == 0)
std::cout << "Required options:" << std::endl << std::endl;
else
std::cout << "Options: " << std::endl << std::endl;
std::cout << "Required input options:" << std::endl << std::endl;
else if (pass == 1)
std::cout << "Optional input options: " << std::endl << std::endl;
else if (pass == 2)
std::cout << "Optional output options: " << std::endl << std::endl;
}

if (pass == 1) // Append default value to description.
if (pass >= 1) // Append default value to description.
{
desc += " Default value ";
std::stringstream tmp;
Expand Down Expand Up @@ -645,8 +729,8 @@ void CLI::PrintHelp(const std::string& param)
std::cout << HyphenateString(desc, 32) << std::endl;
}

std::cout << std::endl;

if (printedHeader)
std::cout << std::endl;
}

// Helpful information at the bottom of the help output, to point the user to
Expand Down Expand Up @@ -718,7 +802,7 @@ void CLI::UpdateGmap()

// Add help parameter.
PARAM_FLAG("help", "Default help info.", "h");
PARAM_STRING("info", "Get help on a specific module or option.", "", "");
PARAM_STRING_IN("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.", "v");
PARAM_FLAG("version", "Display the version of mlpack.", "V");