diff --git a/HISTORY.md b/HISTORY.md
index c0b6a270ce..3837b541c4 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -11,6 +11,9 @@
* Added macro for changing stream of printing and warnings/errors (#2556).
+ * Refactor `ProgramInfo()` to separate out all the different
+ information (#2558).
+
* Added Soft Actor-Critic to RL methods (#2487).
* Added Categorical DQN to q_networks (#2454).
@@ -31,6 +34,8 @@
version of linear regression where the regularization parameter is
automatically tuned (#2030).
+ * Fix incremental training of logistic regression models (#2560).
+
### mlpack 3.3.2
###### 2020-06-18
* Added Noisy DQN to q_networks (#2446).
diff --git a/doc/guide/bindings.hpp b/doc/guide/bindings.hpp
index 13cb7ee12e..2ef5db763b 100644
--- a/doc/guide/bindings.hpp
+++ b/doc/guide/bindings.hpp
@@ -19,7 +19,7 @@ The document is split into several sections:
- @ref bindings_intro
- @ref bindings_code
- @ref bindings_general
- - @ref bindings_general_program_info
+ - @ref bindings_general_program_doc
- @ref bindings_general_define_params
- @ref bindings_general_functions
- @ref bindings_general_more
@@ -128,12 +128,18 @@ using namespace std;
// being used. Note that the macros must have + on either side of them. We
// provide some extra references with the "SEE_ALSO()" macro, which is used to
// generate documentation for the website.
-PROGRAM_INFO("Mean Shift Clustering",
- // Short description.
+
+// Program Name.
+BINDING_NAME("Mean Shift Clustering");
+
+// Short description.
+BINDING_SHORT_DESC(
"A fast implementation of mean-shift clustering using dual-tree range "
"search. Given a dataset, this uses the mean shift algorithm to produce "
- "and return a clustering of the data.",
- // Long description.
+ "and return a clustering of the data.");
+
+// Long description.
+BINDING_LONG_DESC(
"This program performs mean shift clustering on the given dataset, storing "
"the learned cluster assignments either as a column of labels in the input "
"dataset or separately."
@@ -147,21 +153,26 @@ PROGRAM_INFO("Mean Shift Clustering",
"\n\n"
"The output labels may be saved with the " + PRINT_PARAM_STRING("output") +
" output parameter and the centroids of each cluster may be saved with the"
- " " + PRINT_PARAM_STRING("centroid") + " output parameter.",
+ " " + PRINT_PARAM_STRING("centroid") + " output parameter.");
+
+// Example.
+BINDING_EXAMPLE(
"For example, to run mean shift clustering on the dataset " +
PRINT_DATASET("data") + " and store the centroids to " +
PRINT_DATASET("centroids") + ", the following command may be used: "
"\n\n" +
- PRINT_CALL("mean_shift", "input", "data", "centroid", "centroids"),
- SEE_ALSO("@kmeans", "#kmeans"),
- SEE_ALSO("@dbscan", "#dbscan"),
- SEE_ALSO("Mean shift on Wikipedia",
- "https://en.wikipedia.org/wiki/Mean_shift"),
- SEE_ALSO("Mean Shift, Mode Seeking, and Clustering (pdf)",
+ PRINT_CALL("mean_shift", "input", "data", "centroid", "centroids"));
+
+// See also...
+BINDING_SEE_ALSO("@kmeans", "#kmeans");
+BINDING_SEE_ALSO("@dbscan", "#dbscan");
+BINDING_SEE_ALSO("Mean shift on Wikipedia",
+ "https://en.wikipedia.org/wiki/Mean_shift");
+BINDING_SEE_ALSO("Mean Shift, Mode Seeking, and Clustering (pdf)",
"http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.510.1222"
- "&rep=rep1&type=pdf"),
- SEE_ALSO("mlpack::mean_shift::MeanShift C++ class documentation",
- "@doxygen/classmlpack_1_1meanshift_1_1MeanShift.html"));
+ "&rep=rep1&type=pdf");
+BINDING_SEE_ALSO("mlpack::mean_shift::MeanShift C++ class documentation",
+ "@doxygen/classmlpack_1_1meanshift_1_1MeanShift.html");
// Define parameters for the executable.
@@ -227,9 +238,10 @@ void mlpackMain()
@endcode
We can see that we have defined the basic program information in the
-@c PROGRAM_INFO() macro. This is, for instance, what is displayed to describe
-the binding if the user passed the \--help option for a
-command-line program.
+@c BINDING_NAME(), @c BINDING_SHORT_DESC(), @c BINDING_LONG_DESC(),
+@c BINDING_EXAMPLE() and @c BINDING_SEE_ALSO() macros. This is, for instance,
+what is displayed to describe the binding if the user passed the
+\--help option for a command-line program.
Then, we define five parameters, three input and two output, that define the
data and options that the mean shift clustering will function on. These
@@ -246,10 +258,12 @@ whether the parameter is input or output. Some examples:
Note that each of these macros may have slightly different syntax. See the
links above for further documentation.
-In order to write a new binding, then, you simply must write a @c PROGRAM_INFO()
-definition of the program with some docuentation, define the input and output
-parameters as @c PARAM macros, and then write an @c mlpackMain() function that
-actually performs the functionality of the binding. Inside of @c mlpackMain():
+In order to write a new binding, then, you simply must write @c BINDING_NAME(),
+@c BINDING_SHORT_DESC(), @c BINDING_LONG_DESC(), @c BINDING_EXAMPLE() and
+@c BINDING_SEE_ALSO() definitions of the program with some docuentation, define
+the input and output parameters as @c PARAM macros, and then write an
+@c mlpackMain() function that actually performs the functionality of the binding.
+Inside of @c mlpackMain():
- All input parameters are accessible through @c IO::GetParam("name").
- All output parameters should be set by the end of the function with the
@@ -277,15 +291,27 @@ relatively clear how one could use the @c IO functionality along with CMake to
add a binding for a new mlpack machine learning method. If it is not clear,
then the examples in the following sections should clarify.
-@subsection bindings_general_program_info Documenting a program with PROGRAM_INFO()
+@subsection bindings_general_program_doc Documenting a program with
+@c BINDING_NAME(), @c BINDING_SHORT_DESC(), @c BINDING_LONG_DESC(),
+@c BINDING_EXAMPLE() and @c BINDING_SEE_ALSO().
-Any mlpack program should be documented with the @c PROGRAM_INFO() macro, which
-is available from the @c header. The macro
-is of the form
+Any mlpack program should be documented with the @c BINDING_NAME(),
+@c BINDING_SHORT_DESC(), @c BINDING_LONG_DESC() , @c BINDING_EXAMPLE() and
+@c BINDING_SEE_ALSO() macros, which is available from the
+@c header. The macros
+are of the form
@code
-PROGRAM_INFO("program name", "short documentation", "long documentation",
- "examples", SEE_ALSO("link", "description"), ...)
+BINDING_NAME("program name");
+BINDING_SHORT_DESC("This is a short, two-sentence description of what the program does.");
+BINDING_LONG_DESC("This is a long description of what the program does."
+ " It might be many lines long and have lots of details about different options.");
+BINDING_EXAMPLE("This contains one example for this particular binding.\n" +
+ PROGRAM_CALL(...));
+BINDING_EXAMPLE("This contains another example for this particular binding.\n" +
+ PROGRAM_CALL(...));
+// There could be many of these "see alsos".
+BINDING_SEE_ALSO("https://en.wikipedia.org/wiki/Machine_learning");
@endcode
The short documentation should be two sentences indicating what the program
@@ -367,6 +393,14 @@ Command-line program output (snippet):
Python binding output (snippet):
The parameter 'shuffle', if set, will shuffle the data before learning.
+
+Julia binding output (snippet):
+
+ The parameter `shuffle`, if set, will shuffle the data before learning.
+
+Go binding output (snippet):
+
+ The parameter "Shuffle", if set, will shuffle the data before learning.
@endcode
@code
@@ -382,6 +416,14 @@ Command-line program output (snippet):
Python binding output (snippet):
The output matrix can be saved with the 'output' output parameter.
+
+Julia binding output (snippet):
+
+ The output matrix can be saved with the `output` output parameter.
+
+Go binding output (snippet):
+
+ The output matrix can be saved with the "output" output parameter.
@endcode
@code
@@ -407,12 +449,38 @@ Python binding output (snippet):
>>> output = program(input=x)
>>> model = output['output_model']
+
+Julia binding output (snippet):
+
+ For example, to train a model on the dataset `x` and save the output model to
+ `model`, the following command can be used:
+
+ julia> model = program(input=x)
+
+Go binding output (snippet):
+
+ For example, to train a model on the dataset "x" and save the output model to
+ "model", the following command can be used:
+
+ // Initialize optional parameters for Program().
+ param := mlpack.ProgramOptions()
+ param.Input = x
+
+ model := mlpack.Program(param)
@endcode
@code
Input C++ (full program, 'random_numbers_main.cpp'):
- PROGRAM_INFO("Random Numbers", "This program generates random numbers with a "
+ // Program Name.
+ BINDING_NAME("Random Numbers");
+
+ // Short description.
+ BINDING_SHORT_DESC("An implementation of Random Numbers");
+
+ // Long description.
+ BINDING_LONG_DESC(
+ "This program generates random numbers with a "
"variety of nonsensical techniques and example parameters. The input "
"dataset, which will be ignored, can be specified with the " +
PRINT_PARAM_STRING("input") + " parameter. If you would like to subtract"
@@ -424,7 +492,10 @@ Input C++ (full program, 'random_numbers_main.cpp'):
"The output random numbers can be saved with the " +
PRINT_PARAM_STRING("output") + " output parameter. In addition, a "
"randomly generated linear regression model can be saved with the " +
- PRINT_PARAM_STRING("output_model") + " output parameter.",
+ PRINT_PARAM_STRING("output_model") + " output parameter.");
+
+ // Example.
+ BINDING_EXAMPLE(
"For example, to generate 100 random numbers with 3 subtracted from them "
"and save the output to " + PRINT_DATASET("rand") + " and the random "
"model to " + PRINT_MODEL("rand_lr") + ", use the following "
@@ -477,17 +548,66 @@ Python binding output:
>>> output = random_numbers(num_values=100, subtract=3)
>>> rand = output['output']
>>> rand_lr = output['output_model']
+
+Julia binding output:
+
+ Random Numbers
+
+ This program generates random numbers with a variety of nonsensical
+ techniques and example parameters. The input dataset, which will be
+ ignored, can be specified with the `input` parameter. If you would like to
+ subtract values from each number, specify the `subtract` parameter. The
+ number of random numbers to generate is specified with the `num_values`
+ parameter.
+
+ The output random numbers can be saved with the `output` output parameter.
+ In addition, a randomly generated linear regression model can be saved with
+ the `output_model` output parameter.
+
+ For example, to generate 100 random numbers with 3 subtracted from them and
+ save the output to `rand` and the random model to `rand_lr`, use the
+ following command:
+
+ ```julia
+ julia> rand, rand_lr = random_numbers(num_values=100, subtract=3)
+ ```
+
+Go binding output:
+
+ Random Numbers
+
+ This program generates random numbers with a variety of nonsensical
+ techniques and example parameters. The input dataset, which will be
+ ignored, can be specified with the "Input" parameter. If you would like to
+ subtract values from each number, specify the "Subtract" parameter. The
+ number of random numbers to generate is specified with the "NumValues"
+ parameter.
+
+ The output random numbers can be saved with the "output" output parameter.
+ In addition, a randomly generated linear regression model can be saved with
+ the "outputModel" output parameter.
+
+ For example, to generate 100 random numbers with 3 subtracted from them and
+ save the output to "rand" and the random model to "randLr", use the
+ following command:
+
+ // Initialize optional parameters for RandomNumbers().
+ param := mlpack.RandomNumbersOptions()
+ param.NumValues = 100
+ param.Subtract=3
+
+ rand, randLr := mlpack.RandomNumbers(param)
@endcode
@subsection bindings_general_define_params Defining parameters for a program
-There exist several macros that can be used after a @c PROGRAM_INFO() definition
-to define the parameters that can be specified for a given mlpack program.
-These macros all have the same general definition: the name of the macro
-specifies the type of the parameter, whether or not the parameter is required,
-and whether the parameter is an input or output parameter. Then as arguments to
-the macro, the name, description, and sometimes the single-character alias and
-the default value of the parameter.
+There exist several macros that can be used after a @c BINDING_LONG_DESC() and
+@c BINDING_EXAMPLE() definition to define the parameters that can be specified
+for a given mlpack program. These macros all have the same general definition:
+the name of the macro specifies the type of the parameter, whether or not the
+parameter is required, and whether the parameter is an input or output parameter.
+Then as arguments to the macros, the name, description, and sometimes the
+single-character alias and the default value of the parameter.
To give a flavor of how these definitions look, the definition
@@ -618,10 +738,10 @@ Python interface to the user.
mlpack's @c IO module provides a unified abstract interface for getting input
from and providing output to users without needing to consider the language
(command-line, Python, MATLAB, etc.) that the user is running the program from.
-This means that after the @c PROGRAM_INFO() macro and the @c PARAM_*() macros
-have been defined, a language-agnostic @c mlpackMain() function can be written.
-This function then can perform the actual computation that the entire program is
-meant to.
+This means that after the @c BINDING_LONG_DESC() and @c BINDING_EXAMPLE() macros
+and the @c PARAM_*() macros have been defined, a language-agnostic
+@c mlpackMain() function can be written. This function then can perform the
+actual computation that the entire program is meant to.
Inside of an @c mlpackMain() function, the @c mlpack::IO module can be used to
access input parameters and set output parameters. There are two main functions
@@ -701,7 +821,8 @@ could be created for the "random_numbers" program from earlier sections.
@code
#include
-// The PROGRAM_INFO() and PARAM_*() definitions should go here:
+// BINDING_NAME(), BINDING_SHORT_DESC(), BINDING_LONG_DESC() , BINDING_EXAMPLE(),
+// BINDING_SEE_ALSO() and PARAM_*() definitions should go here:
// ...
using namespace mlpack;
@@ -757,23 +878,43 @@ This section describes the internal functionality of the IO module and the
associated macros. If you are only interested in writing mlpack programs, this
section is probably not worth reading.
-There are four main components involved with mlpack bindings:
+There are eight main components involved with mlpack bindings:
- the IO module, a singleton class that stores parameter information
- the mlpackMain() function that defines the functionality of the binding
- - the PROGRAM_INFO() macro that defines the binding name and documentation
+ - the BINDING_NAME() macro that defines the binding name
+ - the BINDING_SHORT_DESC() macro that defines the short description
+ - the BINDING_LONG_DESC() macro that defines the long description
+ - (optional) the BINDING_EXAMPLE() macro that defines example usages
+ - (optional) the BINDING_SEE_ALSO() macro that defines "see also" links
- the PARAM_*() macros that define parameters for the binding
The mlpack::IO module is a singleton class that stores, at runtime, the binding
name, the documentation, and the parameter information and values. In order to
do this, each parameter and the program documentation must make themselves known
-to the IO singleton. This is accomplished by having the @c PROGRAM_INFO() and
-@c PARAM_*() macros declare global variables that, in their constructors,
-register themselves with the IO singleton.
+to the IO singleton. This is accomplished by having the @c BINDING_NAME(),
+@c BINDING_SHORT_DESC(), @c BINDING_LONG_DESC(), @c BINDING_EXAMPLE(),
+@c BINDING_SEE_ALSO() and @c PARAM_*() macros declare global variables that,
+in their constructors, register themselves with the IO singleton.
-The @c PROGRAM_INFO() macro declares an object of type mlpack::util::ProgramDoc.
-The @c ProgramDoc class constructor calls IO::RegisterProgramDoc() in order to
-register the given program name and documentation.
+The @c BINDING_NAME() macro declares an object of type mlpack::util::ProgramName.
+The @c BINDING_SHORT_DESC() macro declares an object of type
+mlpack::util::ShortDescription.
+The @c BINDING_LONG_DESC() macro declares an object of type
+mlpack::util::LongDescription.
+The @c BINDING_EXAMPLE() macro declares an object of type mlpack::util::Example.
+The @c BINDING_SEE_ALSO() macro declares an object of type
+mlpack::util::SeeAlso.
+The @c ProgramName class constructor calls IO::RegisterProgramName() in order to
+register the given program name.
+The @c ShortDescription class constructor calls IO::RegisterShortDescription() in order to
+register the given short description.
+The @c LongDescription class constructor calls IO::RegisterLongDescription() in order to
+register the given long description.
+The @c Example class constructor calls IO::RegisterExample() in order to
+register the given example.
+The @c SeeAlso class constructor calls IO::RegisterSeeAlso() in order to
+register the given see-also link.
The @c PARAM_*() macros declare an object that will, in its constructor, call
IO::Add() to register that parameter with the IO singleton. The specific type
@@ -873,7 +1014,8 @@ binding:
- The options defined by @c PARAM_*() macros are of type
mlpack::bindings::cli::CLIOption.
- - The parameter and value printing macros for @c PROGRAM_INFO() are set:
+ - The parameter and value printing macros for @c BINDING_LONG_DESC()
+ and BINDING_EXAMPLE() are set:
* The @c PRINT_PARAM_STRING() macro is defined as
mlpack::bindings::cli::ParamString().
* The @c PRINT_DATASET() macro is defined as
@@ -1045,9 +1187,10 @@ individually if you like). The file
the name of the program and the @c *_main.cpp file to include correctly, then
the @c mlpack::bindings::python::PrintPYX() function is called by the program.
The @c PrintPYX() function uses the parameters that have been set in the IO
-singleton by the @c PROGRAM_INFO() and @c PARAM_*() macros in order to actually
-print a fully-working .pyx file that can be compiled. The file has several
-sections:
+singleton by the @c BINDING_NAME(), @c BINDING_SHORT_DESC(),
+@c BINDING_LONG_DESC(), @c BINDING_EXAMPLE(), @c BINDING_SEE_ALSO() and
+@c PARAM_*() macros in order to actually print a fully-working .pyx file that
+can be compiled. The file has several sections:
- Python imports (numpy/pandas/cython/etc.)
- Cython imports of C++ utility functions and Armadillo functionality
diff --git a/doc/guide/iodoc.hpp b/doc/guide/iodoc.hpp
index 3282268f88..b60f6fc937 100644
--- a/doc/guide/iodoc.hpp
+++ b/doc/guide/iodoc.hpp
@@ -120,7 +120,8 @@ and debugging output for your mlpack program.
@section simpleio Simple IO Example
Through the mlpack::IO object, command-line parameters can be easily added
-with the PROGRAM_INFO, PARAM_INT, PARAM_DOUBLE, PARAM_STRING, and PARAM_FLAG
+with the BINDING_NAME, BINDING_SHORT_DESC, BINDING_LONG_DESC, BINDING_EXAMPLE,
+BINDING_SEE_ALSO, PARAM_INT, PARAM_DOUBLE, PARAM_STRING, and PARAM_FLAG
macros.
Here is a sample use of those macros, extracted from methods/pca/pca_main.cpp.
@@ -131,23 +132,28 @@ Here is a sample use of those macros, extracted from methods/pca/pca_main.cpp.
#include
#include
-// Document program.
-PROGRAM_INFO("Principal Components Analysis",
- // Short description.
+// Program Name.
+BINDING_NAME("Principal Components Analysis");
+
+// Short description.
+BINDING_SHORT_DESC(
"An implementation of several strategies for principal components analysis "
"(PCA), a common preprocessing step. Given a dataset and a desired new "
"dimensionality, this can reduce the dimensionality of the data using the "
- "linear transformation determined by PCA.",
- // Long description.
+ "linear transformation determined by PCA.");
+
+// Long description.
+BINDING_LONG_DESC(
"This program performs principal components analysis on the given dataset "
"using the exact, randomized, randomized block Krylov, or QUIC SVD method. "
"It will transform the data onto its principal components, optionally "
"performing dimensionality reduction by ignoring the principal components "
- "with the smallest eigenvalues."
- // "See also" section for generated documentation.
- SEE_ALSO("Principal component analysis on Wikipedia",
- "https://en.wikipedia.org/wiki/Principal_component_analysis"),
- SEE_ALSO("mlpack::pca::PCA C++ class documentation",
+ "with the smallest eigenvalues.");
+
+// See also...
+BINDING_SEE_ALSO("Principal component analysis on Wikipedia",
+ "https://en.wikipedia.org/wiki/Principal_component_analysis");
+BINDING_SEE_ALSO("mlpack::pca::PCA C++ class documentation",
"@doxygen/classmlpack_1_1pca_1_1PCA.html"));
// Parameters for program.
diff --git a/src/mlpack/bindings/cli/cli_option.hpp b/src/mlpack/bindings/cli/cli_option.hpp
index f09f324ea0..eeebc2d7cc 100644
--- a/src/mlpack/bindings/cli/cli_option.hpp
+++ b/src/mlpack/bindings/cli/cli_option.hpp
@@ -3,7 +3,7 @@
* @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.
+ * used by CLI.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
@@ -164,35 +164,6 @@ class CLIOption
}
};
-/**
- * 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/util/io.hpp, mlpack::IO
- */
-class ProgramDoc
-{
- public:
- /**
- * Construct a ProgramDoc object. When constructed, it will register itself
- * with IO.
- *
- * @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 IO 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 cli
} // namespace bindings
} // namespace mlpack
diff --git a/src/mlpack/bindings/cli/print_doc_functions.hpp b/src/mlpack/bindings/cli/print_doc_functions.hpp
index 3b027f8720..1f7e9390bb 100644
--- a/src/mlpack/bindings/cli/print_doc_functions.hpp
+++ b/src/mlpack/bindings/cli/print_doc_functions.hpp
@@ -102,8 +102,9 @@ inline std::string ProgramCall(const std::string& programName);
/**
* Print what a user would type to invoke the given option name. Note that the
* name *must* exist in the CLI module. (Note that because of the way
- * ProgramInfo is structured, this doesn't mean that all of the PARAM_*()
- * declarataions need to come before the PROGRAM_INFO() declaration.)
+ * BINDING_LONG_DESC() and BINDING_EXAMPLE() is structured, this doesn't mean
+ * that all of the PARAM_*() declarataions need to come before
+ * BINDING_LONG_DESC() and BINDING_EXAMPLE() declaration.)
*/
inline std::string ParamString(const std::string& paramName);
diff --git a/src/mlpack/bindings/cli/print_doc_functions_impl.hpp b/src/mlpack/bindings/cli/print_doc_functions_impl.hpp
index fbfa22c33b..68339e5912 100644
--- a/src/mlpack/bindings/cli/print_doc_functions_impl.hpp
+++ b/src/mlpack/bindings/cli/print_doc_functions_impl.hpp
@@ -138,8 +138,8 @@ std::string ProcessOptions(const std::string& paramName,
else
{
throw std::runtime_error("Unknown parameter '" + paramName + "' " +
- "encountered while assembling documentation! Check PROGRAM_INFO() " +
- "declaration.");
+ "encountered while assembling documentation! Check BINDING_LONG_DESC()"
+ + " and BINDING_EXAMPLE() declaration.");
}
std::string rest = ProcessOptions(args...);
@@ -229,8 +229,9 @@ inline std::string ProgramCall(const std::string& programName)
/**
* Print what a user would type to invoke the given option name. Note that the
* name *must* exist in the CLI module. (Note that because of the way
- * ProgramInfo is structured, this doesn't mean that all of the PARAM_*()
- * declarataions need to come before the PROGRAM_INFO() declaration.)
+ * BINDING_LONG_DESC() and BINDING_EXAMPLE() is structured, this doesn't mean
+ * that all of the PARAM_*() declarataions need to come before
+ * BINDING_LONG_DESC() and BINDING_EXAMPLE() declaration.)
*/
inline std::string ParamString(const std::string& paramName)
{
@@ -252,7 +253,7 @@ inline std::string ParamString(const std::string& paramName)
else
{
throw std::runtime_error("Parameter '" + paramName + "' not known! Check "
- "PROGRAM_INFO() definition.");
+ "BINDING_LONG_DESC() and BINDING_EXAMPLE() definition.");
}
}
diff --git a/src/mlpack/bindings/cli/print_help.cpp b/src/mlpack/bindings/cli/print_help.cpp
index 5cfa1bf57e..a1cf44089f 100644
--- a/src/mlpack/bindings/cli/print_help.cpp
+++ b/src/mlpack/bindings/cli/print_help.cpp
@@ -25,8 +25,7 @@ void PrintHelp(const std::string& param)
std::string usedParam = param;
std::map& parameters = IO::Parameters();
const std::map& aliases = IO::Aliases();
- util::ProgramDoc& docs = *IO::GetSingleton().doc;
-
+ util::BindingDetails& bindingDetails = IO::GetSingleton().doc;
// If we pass a single param, alias it if necessary.
if (usedParam.length() == 1 && aliases.count(usedParam[0]))
usedParam = aliases.at(usedParam[0]);
@@ -64,11 +63,16 @@ void PrintHelp(const std::string& param)
}
// Print out the descriptions.
- if (docs.programName != "")
+ if (bindingDetails.programName != "")
{
- std::cout << docs.programName << std::endl << std::endl;
- std::cout << " " << util::HyphenateString(docs.documentation(), 2)
- << std::endl << std::endl;
+ std::cout << bindingDetails.programName << std::endl << std::endl;
+ std::cout << " " << util::HyphenateString(bindingDetails.longDescription(),
+ 2) << std::endl << std::endl;
+ for (size_t j = 0; j < bindingDetails.example.size(); ++j)
+ {
+ std::cout << " " << util::HyphenateString(bindingDetails.example[j](), 2)
+ << std::endl << std::endl;
+ }
}
else
std::cout << "[undocumented program]" << std::endl << std::endl;
diff --git a/src/mlpack/bindings/go/generate_go.cpp.in b/src/mlpack/bindings/go/generate_go.cpp.in
index 5a07bc5573..0e75e9c4cd 100644
--- a/src/mlpack/bindings/go/generate_go.cpp.in
+++ b/src/mlpack/bindings/go/generate_go.cpp.in
@@ -45,5 +45,5 @@ int main(int /* argc */, char** /* argv */)
// programName is defined in mlpack_main.hpp.
IO::RestoreSettings(programName);
- PrintGo(*IO::GetSingleton().doc, "${PROGRAM_NAME}");
+ PrintGo(IO::GetSingleton().doc, "${PROGRAM_NAME}");
}
diff --git a/src/mlpack/bindings/go/print_doc_functions_impl.hpp b/src/mlpack/bindings/go/print_doc_functions_impl.hpp
index 10aedec1be..8d478c9576 100644
--- a/src/mlpack/bindings/go/print_doc_functions_impl.hpp
+++ b/src/mlpack/bindings/go/print_doc_functions_impl.hpp
@@ -154,8 +154,8 @@ std::string PrintOptionalInputs(const std::string& paramName,
{
// Unknown parameter!
throw std::runtime_error("Unknown parameter '" + paramName + "' " +
- "encountered while assembling documentation! Check PROGRAM_INFO() " +
- "declaration.");
+ "encountered while assembling documentation! Check BINDING_LONG_DESC()"
+ + " and BINDING_EXAMPLE() declaration.");
}
// Continue recursion.
@@ -211,8 +211,8 @@ std::string PrintInputOptions(const std::string& paramName,
{
// Unknown parameter!
throw std::runtime_error("Unknown parameter '" + paramName + "' " +
- "encountered while assembling documentation! Check PROGRAM_INFO() " +
- "declaration.");
+ "encountered while assembling documentation! Check BINDING_LONG_DESC()"
+ + " and BINDING_EXAMPLE() declaration.");
}
// Continue recursion.
@@ -256,8 +256,8 @@ void GetOptions(
{
// Unknown parameter!
throw std::runtime_error("Unknown parameter '" + paramName + "' " +
- "encountered while assembling documentation! Check PROGRAM_INFO() " +
- "declaration.");
+ "encountered while assembling documentation! Check BINDING_LONG_DESC()"
+ + " and BINDING_EXAMPLE() declaration.");
}
}
diff --git a/src/mlpack/bindings/go/print_go.cpp b/src/mlpack/bindings/go/print_go.cpp
index ba84fd598a..1774e202b7 100644
--- a/src/mlpack/bindings/go/print_go.cpp
+++ b/src/mlpack/bindings/go/print_go.cpp
@@ -27,14 +27,14 @@ namespace go {
* Given a list of parameter definition and program documentation, print a
* generated .go file to stdout.
*
- * @param programInfo Documentation for the program.
+ * @param doc Documentation for the program.
* @param functionName Name of the function (i.e. "pca").
*/
-void PrintGo(const util::ProgramDoc& programInfo,
- const std::string& functionName)
+void PrintGo(const util::BindingDetails& doc,
+ const std::string& functionName)
{
// Restore parameters.
- IO::RestoreSettings(programInfo.programName);
+ IO::RestoreSettings(doc.programName);
std::map& parameters = IO::Parameters();
typedef std::map::iterator ParamIter;
@@ -124,8 +124,15 @@ void PrintGo(const util::ProgramDoc& programInfo,
// Print the comment describing the function and its parameters.
cout << "/*" << endl;
- cout << " " << HyphenateString(programInfo.documentation(), 2) << endl;
- cout << endl << endl;
+ cout << " " << HyphenateString(doc.longDescription(), 2) << endl << endl;
+
+ // Print the examples.
+ for (size_t j = 0; j < doc.example.size(); ++j)
+ {
+ cout << " " << util::HyphenateString(doc.example[j](), 2) << endl << endl;
+ }
+
+ // Next, print information on the input options.
cout << " Input parameters:" << endl;
cout << endl;
for (size_t i = 0; i < inputOptions.size(); ++i)
@@ -216,8 +223,7 @@ void PrintGo(const util::ProgramDoc& programInfo,
cout << " " << "disableVerbose()" << endl;
// Restore the parameters.
- cout << " " << "restoreSettings(\"" << programInfo.programName
- << "\")" << endl;
+ cout << " " << "restoreSettings(\"" << doc.programName << "\")" << endl;
cout << endl;
// Do any input processing.
diff --git a/src/mlpack/bindings/go/print_go.hpp b/src/mlpack/bindings/go/print_go.hpp
index 4b6bfdbed6..d2ce7161de 100644
--- a/src/mlpack/bindings/go/print_go.hpp
+++ b/src/mlpack/bindings/go/print_go.hpp
@@ -22,11 +22,10 @@ namespace go {
/**
* Given a list of parameter definition and program documentation, print a
* generated .go file to stdout.
- *
- * @param programInfo Documentation for the program.
+ * @param doc Documentation for the program.
* @param functionName Name of the function (i.e. "pca").
*/
-void PrintGo(const util::ProgramDoc& programInfo,
+void PrintGo(const util::BindingDetails& doc,
const std::string& functionName);
diff --git a/src/mlpack/bindings/go/tests/test_go_binding_main.cpp b/src/mlpack/bindings/go/tests/test_go_binding_main.cpp
index 08a5e09b35..69e78af4d0 100644
--- a/src/mlpack/bindings/go/tests/test_go_binding_main.cpp
+++ b/src/mlpack/bindings/go/tests/test_go_binding_main.cpp
@@ -18,9 +18,16 @@ using namespace std;
using namespace mlpack;
using namespace mlpack::kernel;
-PROGRAM_INFO("Golang binding test",
- "A simple program to test Golang binding functionality.",
- "A simple program to test Golang binding functionality. You can build "
+// Program Name.
+BINDING_NAME("Golang binding test");
+
+// Short description.
+BINDING_SHORT_DESC(
+ "A simple program to test Go binding functionality.");
+
+// Long description.
+BINDING_LONG_DESC(
+ "A simple program to test Go binding functionality. You can build "
"mlpack with the BUILD_TESTS option set to off, and this binding will "
"no longer be built.", "");
diff --git a/src/mlpack/bindings/julia/generate_jl.cpp.in b/src/mlpack/bindings/julia/generate_jl.cpp.in
index 289342f7a7..8dbd38470c 100644
--- a/src/mlpack/bindings/julia/generate_jl.cpp.in
+++ b/src/mlpack/bindings/julia/generate_jl.cpp.in
@@ -35,5 +35,5 @@ int main(int /* argc */, char** /* argv */)
// programName is defined in mlpack_main.hpp.
IO::RestoreSettings(programName);
- PrintJL(*IO::GetSingleton().doc, "${NAME}", "${MLPACK_JL_LIB_SUFFIX}");
+ PrintJL(IO::GetSingleton().doc, "${NAME}", "${MLPACK_JL_LIB_SUFFIX}");
}
diff --git a/src/mlpack/bindings/julia/print_doc_functions_impl.hpp b/src/mlpack/bindings/julia/print_doc_functions_impl.hpp
index 2c1ef7fe9f..3e8b69b845 100644
--- a/src/mlpack/bindings/julia/print_doc_functions_impl.hpp
+++ b/src/mlpack/bindings/julia/print_doc_functions_impl.hpp
@@ -144,8 +144,8 @@ inline std::string CreateInputArguments(const std::string& paramName,
{
// Unknown parameter!
throw std::runtime_error("Unknown parameter '" + paramName + "' " +
- "encountered while assembling documentation! Check PROGRAM_INFO() " +
- "declaration.");
+ "encountered while assembling documentation! Check BINDING_LONG_DESC()"
+ + " and BINDING_EXAMPLE() declaration.");
}
}
@@ -223,8 +223,8 @@ inline void GetOptions(
{
// Unknown parameter!
throw std::runtime_error("Unknown parameter '" + paramName + "' " +
- "encountered while assembling documentation! Check PROGRAM_INFO() " +
- "declaration.");
+ "encountered while assembling documentation! Check BINDING_LONG_DESC()"
+ + " and BINDING_EXAMPLE() declaration.");
}
}
diff --git a/src/mlpack/bindings/julia/print_jl.cpp b/src/mlpack/bindings/julia/print_jl.cpp
index 9b0a853bd5..ac1f7d8b60 100644
--- a/src/mlpack/bindings/julia/print_jl.cpp
+++ b/src/mlpack/bindings/julia/print_jl.cpp
@@ -14,7 +14,7 @@
#include
-using namespace mlpack;
+using namespace mlpack::util;
using namespace std;
namespace mlpack {
@@ -26,12 +26,12 @@ extern std::string programName;
/**
* Print the code for a .jl binding for an mlpack program to stdout.
*/
-void PrintJL(const util::ProgramDoc& programInfo,
+void PrintJL(const util::BindingDetails& doc,
const string& functionName,
const std::string& mlpackJuliaLibSuffix)
{
// Restore parameters.
- IO::RestoreSettings(programInfo.programName);
+ IO::RestoreSettings(doc.programName);
map& parameters = IO::Parameters();
typedef map::iterator ParamIter;
@@ -167,10 +167,15 @@ void PrintJL(const util::ProgramDoc& programInfo,
cout << endl;
// Next print the description.
- cout << util::HyphenateString(programInfo.documentation(), 0) << endl;
+ cout << HyphenateString(doc.longDescription(), 0) << endl << endl;
+
+ // Next print the examples.
+ for (size_t j = 0; j < doc.example.size(); ++j)
+ {
+ cout << util::HyphenateString(doc.example[j](), 0) << endl << endl;
+ }
// Next, print information on the input options.
- cout << endl;
cout << "# Arguments" << endl;
cout << endl;
diff --git a/src/mlpack/bindings/julia/print_jl.hpp b/src/mlpack/bindings/julia/print_jl.hpp
index 39b84295d2..5e73f590ff 100644
--- a/src/mlpack/bindings/julia/print_jl.hpp
+++ b/src/mlpack/bindings/julia/print_jl.hpp
@@ -21,7 +21,7 @@ namespace julia {
/**
* Print the code for a .jl binding for an mlpack program to stdout.
*/
-void PrintJL(const util::ProgramDoc& programInfo,
+void PrintJL(const util::BindingDetails& doc,
const std::string& functionName,
const std::string& mlpackJuliaLibSuffix);
diff --git a/src/mlpack/bindings/julia/tests/test_julia_binding_main.cpp b/src/mlpack/bindings/julia/tests/test_julia_binding_main.cpp
index a0aca51e56..d5ea842684 100644
--- a/src/mlpack/bindings/julia/tests/test_julia_binding_main.cpp
+++ b/src/mlpack/bindings/julia/tests/test_julia_binding_main.cpp
@@ -18,8 +18,15 @@ using namespace std;
using namespace mlpack;
using namespace mlpack::kernel;
-PROGRAM_INFO("Julia binding test",
- "A simple program to test Julia binding functionality.",
+// Program Name.
+BINDING_NAME("Julia binding test");
+
+// Short description.
+BINDING_SHORT_DESC(
+ "A simple program to test Julia binding functionality.");
+
+// Long description.
+BINDING_LONG_DESC(
"A simple program to test Julia binding functionality. You can build "
"mlpack with the BUILD_TESTS option set to off, and this binding will "
"no longer be built.", "");
diff --git a/src/mlpack/bindings/markdown/binding_info.cpp b/src/mlpack/bindings/markdown/binding_info.cpp
index e76ee2eb39..eed8e2098a 100644
--- a/src/mlpack/bindings/markdown/binding_info.cpp
+++ b/src/mlpack/bindings/markdown/binding_info.cpp
@@ -17,7 +17,8 @@ namespace mlpack {
namespace bindings {
namespace markdown {
-util::ProgramDoc& BindingInfo::GetProgramDoc(const std::string& bindingName)
+util::BindingDetails& BindingInfo::GetBindingDetails(
+ const std::string& bindingName)
{
if (GetSingleton().map.count(bindingName) == 0)
{
@@ -28,14 +29,6 @@ util::ProgramDoc& BindingInfo::GetProgramDoc(const std::string& bindingName)
return GetSingleton().map.at(bindingName);
}
-
-//! Register a ProgramDoc object with the given bindingName.
-void BindingInfo::RegisterProgramDoc(const std::string& bindingName,
- const util::ProgramDoc& programDoc)
-{
- GetSingleton().map[bindingName] = programDoc;
-}
-
//! Get or modify the current language (don't set it to something invalid!).
std::string& BindingInfo::Language()
{
diff --git a/src/mlpack/bindings/markdown/binding_info.hpp b/src/mlpack/bindings/markdown/binding_info.hpp
index b93738b26e..319bb0bcac 100644
--- a/src/mlpack/bindings/markdown/binding_info.hpp
+++ b/src/mlpack/bindings/markdown/binding_info.hpp
@@ -4,7 +4,7 @@
*
* This file defines the BindingInfo singleton class that is used specifically
* for the Markdown bindings to map from a binding name (i.e. "knn") to
- * multiple ProgramDoc objects, which are then used to generate the
+ * multiple documentation objects, which are then used to generate the
* documentation.
*
* mlpack is free software; you may redistribute it and/or modify it under the
@@ -16,7 +16,7 @@
#define MLPACK_BINDINGS_MARKDOWN_BINDING_NAME_HPP
#include
-#include
+#include
namespace mlpack {
namespace bindings {
@@ -24,31 +24,28 @@ namespace markdown {
/**
* The BindingInfo class is used by the Markdown documentation generator to
- * store multiple ProgramDoc objects, indexed by both the binding name (i.e.
+ * store multiple documentation objects, indexed by both the binding name (i.e.
* "knn") and the language (i.e. "cli").
*/
class BindingInfo
{
public:
- //! Return a ProgramDoc object for a given bindingName.
- static util::ProgramDoc& GetProgramDoc(const std::string& bindingName);
-
- //! Register a ProgramDoc object with the given bindingName.
- static void RegisterProgramDoc(const std::string& bindingName,
- const util::ProgramDoc& programDoc);
+ //! Return a BindingDetails object for a given bindingName.
+ static util::BindingDetails& GetBindingDetails(
+ const std::string& bindingName);
//! Get or modify the current language (don't set it to something invalid!).
static std::string& Language();
- private:
- //! Private constructor, so that only one instance can be created.
- BindingInfo() { }
-
//! Get the singleton.
static BindingInfo& GetSingleton();
- //! Internally-held map for mapping a binding name to a ProgramDoc name.
- std::unordered_map map;
+ //! Internally-held map for mapping a binding name to a BindingDetails.
+ std::unordered_map map;
+
+ private:
+ //! Private constructor, so that only one instance can be created.
+ BindingInfo() { }
//! Holds the name of the language that we are currently printing. This is
//! modified before printing the documentation, and then used by
diff --git a/src/mlpack/bindings/markdown/generate_markdown.binding.cpp.in b/src/mlpack/bindings/markdown/generate_markdown.binding.cpp.in
index b6ac08952a..a6286faeab 100644
--- a/src/mlpack/bindings/markdown/generate_markdown.binding.cpp.in
+++ b/src/mlpack/bindings/markdown/generate_markdown.binding.cpp.in
@@ -12,7 +12,7 @@
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
-#define BINDING_NAME "${BINDING}"
+#define MARKDOWN_BINDING_NAME "${BINDING}"
#include
#include "generate_markdown.${BINDING}.hpp"
diff --git a/src/mlpack/bindings/markdown/print_doc_functions.hpp b/src/mlpack/bindings/markdown/print_doc_functions.hpp
index 35e60e0934..c122339b95 100644
--- a/src/mlpack/bindings/markdown/print_doc_functions.hpp
+++ b/src/mlpack/bindings/markdown/print_doc_functions.hpp
@@ -88,8 +88,9 @@ inline std::string ProgramCall(const std::string& programName);
/**
* Print what a user would type to invoke the given option name. Note that the
* name *must* exist in the IO module. (Note that because of the way
- * ProgramInfo is structured, this doesn't mean that all of the PARAM_*()
- * declarataions need to come before the PROGRAM_INFO() declaration.)
+ * BINDING_LONG_DESC() and BINDING_EXAMPLE() is structured, this doesn't mean
+ * that all of the PARAM_*() declarataions need to come before
+ * BINDING_LONG_DESC() and BINDING_EXAMPLE() declaration.)
*/
inline std::string ParamString(const std::string& paramName);
diff --git a/src/mlpack/bindings/markdown/print_doc_functions_impl.hpp b/src/mlpack/bindings/markdown/print_doc_functions_impl.hpp
index 2d1c0ff457..3fb46e9d63 100644
--- a/src/mlpack/bindings/markdown/print_doc_functions_impl.hpp
+++ b/src/mlpack/bindings/markdown/print_doc_functions_impl.hpp
@@ -646,8 +646,9 @@ inline std::string ProgramCall(const std::string& programName)
/**
* Print what a user would type to invoke the given option name. Note that the
* name *must* exist in the CLI module. (Note that because of the way
- * ProgramInfo is structured, this doesn't mean that all of the PARAM_*()
- * declarataions need to come before the PROGRAM_INFO() declaration.)
+ * BINDING_LONG_DESC() and BINDING_EXAMPLE() is structured, this doesn't mean
+ * that all of the PARAM_*() declarataions need to come before
+ * BINDING_LONG_DESC() and BINDING_EXAMPLE() declaration.)
*/
inline std::string ParamString(const std::string& paramName)
{
diff --git a/src/mlpack/bindings/markdown/print_docs.cpp b/src/mlpack/bindings/markdown/print_docs.cpp
index 2ffacfd6cb..5d8a55e140 100644
--- a/src/mlpack/bindings/markdown/print_docs.cpp
+++ b/src/mlpack/bindings/markdown/print_docs.cpp
@@ -12,7 +12,7 @@
#include "print_docs.hpp"
#include
-#include
+#include
#include "binding_info.hpp"
#include "print_doc_functions.hpp"
@@ -45,7 +45,7 @@ void PrintHeaders(const std::string& bindingName,
void PrintDocs(const std::string& bindingName,
const vector& languages)
{
- ProgramDoc& programDoc = BindingInfo::GetProgramDoc(bindingName);
+ BindingDetails& doc = BindingInfo::GetBindingDetails(bindingName);
IO::RestoreSettings(bindingName);
@@ -64,7 +64,7 @@ void PrintDocs(const std::string& bindingName,
// Next, print the logical name of the binding (that's known by
// ProgramInfo).
- cout << "#### " << programDoc.programName << endl;
+ cout << "#### " << doc.programName << endl;
cout << endl;
for (size_t i = 0; i < languages.size(); ++i)
@@ -78,7 +78,7 @@ void PrintDocs(const std::string& bindingName,
}
cout << endl;
- cout << programDoc.shortDocumentation << " ";
+ cout << doc.shortDescription << " ";
for (size_t i = 0; i < languages.size(); ++i)
{
cout << "[Detailed documentation](#" << languages[i] << "_"
@@ -213,37 +213,44 @@ void PrintDocs(const std::string& bindingName,
cout << "{: #" << languages[i] << "_" << bindingName
<< "_detailed-documentation }" << endl;
cout << endl;
- string doc = boost::replace_all_copy(programDoc.documentation(),
- "|", "\\|");
- cout << doc << endl;
- cout << endl;
+ string desc = boost::replace_all_copy(doc.longDescription(),
+ "|", "\\|");
+ cout << desc << endl << endl;
+ if (doc.example.size() > 0)
+ cout << "### Example" << endl;
+ for (size_t j = 0; j < doc.example.size(); ++j)
+ {
+ string eg = boost::replace_all_copy(doc.example[j](),
+ "|", "\\|");
+ cout << eg << endl << endl;
+ }
cout << "### See also" << endl;
cout << endl;
- for (size_t j = 0; j < programDoc.seeAlso.size(); ++j)
+ for (size_t j = 0; j < doc.seeAlso.size(); ++j)
{
cout << " - " << "[";
// We need special processing if the user has specified a binding name
// starting with @ (i.e., '@kfn' or similar).
- if (programDoc.seeAlso[j].first[0] == '@')
- cout << GetBindingName(programDoc.seeAlso[j].first.substr(1));
+ if (doc.seeAlso[j].first[0] == '@')
+ cout << GetBindingName(doc.seeAlso[j].first.substr(1));
else
- cout << programDoc.seeAlso[j].first;
+ cout << doc.seeAlso[j].first;
cout << "](";
// We need special handling of Doxygen information.
- if (programDoc.seeAlso[j].second.substr(0, 8) == "@doxygen")
+ if (doc.seeAlso[j].second.substr(0, 8) == "@doxygen")
{
- cout << DOXYGEN_PREFIX << programDoc.seeAlso[j].second.substr(9);
+ cout << DOXYGEN_PREFIX << doc.seeAlso[j].second.substr(9);
}
- else if (programDoc.seeAlso[j].second[0] == '#')
+ else if (doc.seeAlso[j].second[0] == '#')
{
cout << "#" << languages[i] << "_"
- << programDoc.seeAlso[j].second.substr(1);
+ << doc.seeAlso[j].second.substr(1);
}
else
{
- cout << programDoc.seeAlso[j].second;
+ cout << doc.seeAlso[j].second;
}
cout << ")" << endl;
diff --git a/src/mlpack/bindings/markdown/program_doc_wrapper.hpp b/src/mlpack/bindings/markdown/program_doc_wrapper.hpp
index 6e4854081f..9cc333bdd6 100644
--- a/src/mlpack/bindings/markdown/program_doc_wrapper.hpp
+++ b/src/mlpack/bindings/markdown/program_doc_wrapper.hpp
@@ -2,8 +2,9 @@
* @file bindings/markdown/program_doc_wrapper.hpp
* @author Ryan Curtin
*
- * A simple wrapper around ProgramDoc that also calls
- * BindingInfo::RegisterProgramDoc() upon construction.
+ * A simple wrapper around programName, shortDescription, longDescription,
+ * example and seeAlso that also respectively register all the macros upon
+ * construction.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
@@ -19,24 +20,73 @@ namespace mlpack {
namespace bindings {
namespace markdown {
-class ProgramDocWrapper
+class ProgramNameWrapper
{
public:
/**
- * Construct a ProgramDoc object and register it with
- * BindingInfo::RegisterProgramDoc().
+ * Register programName.
*/
- ProgramDocWrapper(const std::string& bindingName,
- const std::string& programName,
- const std::string& shortDocumentation,
- const std::function& documentation,
- const std::function& example,
- const std::vector>&
- seeAlso)
+ ProgramNameWrapper(const std::string& bindingName,
+ const std::string& programName)
{
- util::ProgramDoc pd(programName, shortDocumentation, documentation,
- example, seeAlso);
- BindingInfo::RegisterProgramDoc(bindingName, pd);
+ BindingInfo::GetSingleton().map[bindingName].programName =
+ std::move(programName);
+ }
+};
+
+class ShortDescriptionWrapper
+{
+ public:
+ /**
+ * Register shortDescription.
+ */
+ ShortDescriptionWrapper(const std::string& bindingName,
+ const std::string& shortDescription)
+ {
+ BindingInfo::GetSingleton().map[bindingName].shortDescription =
+ std::move(shortDescription);
+ }
+};
+
+class LongDescriptionWrapper
+{
+ public:
+ /**
+ * Register longDescription.
+ */
+ LongDescriptionWrapper(const std::string& bindingName,
+ const std::function& longDescription)
+ {
+ BindingInfo::GetSingleton().map[bindingName].longDescription =
+ std::move(longDescription);
+ }
+};
+
+class ExampleWrapper
+{
+ public:
+ /**
+ * Register example.
+ */
+ ExampleWrapper(const std::string& bindingName,
+ const std::function& example)
+ {
+ BindingInfo::GetSingleton().map[bindingName].example.push_back(
+ std::move(example));
+ }
+};
+
+class SeeAlsoWrapper
+{
+ public:
+ /**
+ * Register seeAlso.
+ */
+ SeeAlsoWrapper(const std::string& bindingName,
+ const std::string& description, const std::string& link)
+ {
+ BindingInfo::GetSingleton().map[bindingName].seeAlso.push_back(
+ std::move(std::make_pair(description, link)));
}
};
diff --git a/src/mlpack/bindings/python/generate_pyx.cpp.in b/src/mlpack/bindings/python/generate_pyx.cpp.in
index 7eb2824969..09905be574 100644
--- a/src/mlpack/bindings/python/generate_pyx.cpp.in
+++ b/src/mlpack/bindings/python/generate_pyx.cpp.in
@@ -45,6 +45,5 @@ int main(int /* argc */, char** /* argv */)
// programName is defined in mlpack_main.hpp.
IO::RestoreSettings(programName);
- PrintPYX(*IO::GetSingleton().doc, "${PROGRAM_MAIN_FILE}",
- "${PROGRAM_NAME}");
+ PrintPYX(IO::GetSingleton().doc, "${PROGRAM_MAIN_FILE}", "${PROGRAM_NAME}");
}
diff --git a/src/mlpack/bindings/python/print_doc_functions_impl.hpp b/src/mlpack/bindings/python/print_doc_functions_impl.hpp
index 9e6bebd987..4f282e2a68 100644
--- a/src/mlpack/bindings/python/print_doc_functions_impl.hpp
+++ b/src/mlpack/bindings/python/print_doc_functions_impl.hpp
@@ -133,8 +133,8 @@ std::string PrintInputOptions(const std::string& paramName,
{
// Unknown parameter!
throw std::runtime_error("Unknown parameter '" + paramName + "' " +
- "encountered while assembling documentation! Check PROGRAM_INFO() " +
- "declaration.");
+ "encountered while assembling documentation! Check BINDING_LONG_DESC()"
+ + " and BINDING_EXAMPLE() declaration.");
}
// Continue recursion.
@@ -172,8 +172,8 @@ std::string PrintOutputOptions(const std::string& paramName,
{
// Unknown parameter!
throw std::runtime_error("Unknown parameter '" + paramName + "' " +
- "encountered while assembling documentation! Check PROGRAM_INFO() " +
- "declaration.");
+ "encountered while assembling documentation! Check BINDING_LONG_DESC()"
+ + " and BINDING_EXAMPLE() declaration.");
}
// Continue recursion.
diff --git a/src/mlpack/bindings/python/print_pyx.cpp b/src/mlpack/bindings/python/print_pyx.cpp
index 72b895697b..87a412346b 100644
--- a/src/mlpack/bindings/python/print_pyx.cpp
+++ b/src/mlpack/bindings/python/print_pyx.cpp
@@ -26,18 +26,17 @@ namespace python {
* Given a list of parameter definition and program documentation, print a
* generated .pyx file to stdout.
*
- * @param parameters List of parameters the program will use (from IO).
- * @param programInfo Documentation for the program.
+ * @param doc Documentation for the program.
* @param mainFilename Filename of the main program (i.e.
* "/path/to/pca_main.cpp").
* @param functionName Name of the function (i.e. "pca").
*/
-void PrintPYX(const ProgramDoc& programInfo,
+void PrintPYX(const util::BindingDetails& doc,
const string& mainFilename,
const string& functionName)
{
// Restore parameters.
- IO::RestoreSettings(programInfo.programName);
+ IO::RestoreSettings(doc.programName);
std::map& parameters = IO::Parameters();
typedef std::map::iterator ParamIter;
@@ -143,10 +142,19 @@ void PrintPYX(const ProgramDoc& programInfo,
// Print the comment describing the function and its parameters.
cout << " \"\"\"" << endl;
- cout << " " << programInfo.programName << endl;
+ cout << " " << doc.programName << endl;
cout << endl;
- cout << " " << HyphenateString(programInfo.documentation(), 2) << endl;
- cout << endl << endl;
+
+ // Print the description.
+ cout << " " << HyphenateString(doc.longDescription(), 2) << endl << endl;
+
+ // Next print the examples.
+ for (size_t j = 0; j < doc.example.size(); ++j)
+ {
+ cout << " " << util::HyphenateString(doc.example[j](), 2) << endl << endl;
+ }
+
+ // Next, print information on the input options.
cout << " Input parameters:" << endl;
cout << endl;
for (size_t i = 0; i < inputOptions.size(); ++i)
@@ -184,7 +192,7 @@ void PrintPYX(const ProgramDoc& programInfo,
cout << " DisableVerbose()" << endl;
// Restore the parameters.
- cout << " IO.RestoreSettings(\"" << programInfo.programName << "\")"
+ cout << " IO.RestoreSettings(\"" << doc.programName << "\")"
<< endl;
// Determine whether or not we need to copy parameters.
diff --git a/src/mlpack/bindings/python/print_pyx.hpp b/src/mlpack/bindings/python/print_pyx.hpp
index 896840e3c8..999fd3153b 100644
--- a/src/mlpack/bindings/python/print_pyx.hpp
+++ b/src/mlpack/bindings/python/print_pyx.hpp
@@ -23,12 +23,12 @@ namespace python {
* Given a list of parameter definition and program documentation, print a
* generated .pyx file to stdout.
*
- * @param programInfo Documentation for the program.
+ * @param doc Documentation for the program.
* @param mainFilename Filename of the main program (i.e.
* "/path/to/pca_main.cpp").
* @param functionName Name of the function (i.e. "pca").
*/
-void PrintPYX(const util::ProgramDoc& programInfo,
+void PrintPYX(const util::BindingDetails& doc,
const std::string& mainFilename,
const std::string& functionName);
diff --git a/src/mlpack/bindings/python/tests/test_python_binding_main.cpp b/src/mlpack/bindings/python/tests/test_python_binding_main.cpp
index e46c392fa2..c0f1ba61be 100644
--- a/src/mlpack/bindings/python/tests/test_python_binding_main.cpp
+++ b/src/mlpack/bindings/python/tests/test_python_binding_main.cpp
@@ -18,8 +18,15 @@ using namespace std;
using namespace mlpack;
using namespace mlpack::kernel;
-PROGRAM_INFO("Python binding test",
- "A simple program to test Python binding functionality.",
+// Program Name.
+BINDING_NAME("Python binding test");
+
+// Short description.
+BINDING_SHORT_DESC(
+ "A simple program to test Python binding functionality.");
+
+// Long description.
+BINDING_LONG_DESC(
"A simple program to test Python binding functionality. You can build "
"mlpack with the BUILD_TESTS option set to off, and this binding will "
"no longer be built.", "");
diff --git a/src/mlpack/bindings/tests/test_option.hpp b/src/mlpack/bindings/tests/test_option.hpp
index 95332019f3..206126f958 100644
--- a/src/mlpack/bindings/tests/test_option.hpp
+++ b/src/mlpack/bindings/tests/test_option.hpp
@@ -108,35 +108,6 @@ class TestOption
}
};
-/**
- * A static object whose constructor registers program documentation with the
- * IO class. This should not be used outside of IO itself, and you should use
- * the PROGRAM_INFO() macro to declare these objects. Only one ProgramDoc
- * object should ever exist.
- *
- * @see core/util/io.hpp, mlpack::IO
- */
-class ProgramDoc
-{
- public:
- /**
- * Construct a ProgramDoc object. When constructed, it will register itself
- * with IO.
- *
- * @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 IO 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 tests
} // namespace bindings
} // namespace mlpack
diff --git a/src/mlpack/core/util/CMakeLists.txt b/src/mlpack/core/util/CMakeLists.txt
index 17a565ef87..19ddff3293 100644
--- a/src/mlpack/core/util/CMakeLists.txt
+++ b/src/mlpack/core/util/CMakeLists.txt
@@ -6,6 +6,7 @@ set(SOURCES
arma_config_check.hpp
backtrace.hpp
backtrace.cpp
+ binding_details.hpp
io.hpp
io.cpp
io_impl.hpp
diff --git a/src/mlpack/core/util/binding_details.hpp b/src/mlpack/core/util/binding_details.hpp
new file mode 100644
index 0000000000..34fabe6627
--- /dev/null
+++ b/src/mlpack/core/util/binding_details.hpp
@@ -0,0 +1,44 @@
+/**
+ * @file core/util/binding_details.hpp
+ * @author Yashwant Singh Parihar
+ *
+ * This defines the structure that holds documentation details for bindings.
+ *
+ * mlpack is free software; you may redistribute it and/or modify it under the
+ * terms of the 3-clause BSD license. You should have received a copy of the
+ * 3-clause BSD license along with mlpack. If not, see
+ * http://www.opensource.org/licenses/BSD-3-Clause for more information.
+ */
+#ifndef MLPACK_CORE_UTIL_BINDING_DETAILS_HPP
+#define MLPACK_CORE_UTIL_BINDING_DETAILS_HPP
+
+#include
+#include "program_doc.hpp"
+
+namespace mlpack {
+namespace util {
+
+/**
+ * This structure holds all of the information about bindings documentation.
+ */
+struct BindingDetails
+{
+ //! Name of the binding.
+ std::string programName;
+ //! A short two-sentence description of the binding, what it does, and what
+ //! it is useful for.
+ std::string shortDescription;
+ //! Long string containing documentation on what it is. No newline characters
+ //! are necessary; this is taken care of by IO later.
+ std::function longDescription;
+ //! Documentation on how to use the binding.
+ std::vector> example;
+ //! A set of pairs of strings with useful "see also" information; each pair
+ //! is .
+ std::vector> seeAlso;
+};
+
+} // namespace util
+} // namespace mlpack
+
+#endif
diff --git a/src/mlpack/core/util/io.cpp b/src/mlpack/core/util/io.cpp
index 2c357dac60..0c8703c406 100644
--- a/src/mlpack/core/util/io.cpp
+++ b/src/mlpack/core/util/io.cpp
@@ -17,19 +17,15 @@
using namespace mlpack;
using namespace mlpack::util;
-// Fake ProgramDoc in case none is supplied.
-static ProgramDoc emptyProgramDoc = ProgramDoc("", "", []() { return ""; },
- []() { return ""; }, {});
-
/* Constructors, Destructors, Copy */
/* Make the constructor private, to preclude unauthorized instances */
-IO::IO() : didParse(false), doc(&emptyProgramDoc)
+IO::IO() : didParse(false)
{
return;
}
// Private copy constructor; don't want copies floating around.
-IO::IO(const IO& /* other */) : didParse(false), doc(&emptyProgramDoc)
+IO::IO(const IO& /* other */) : didParse(false)
{
return;
}
@@ -154,20 +150,6 @@ IO& IO::GetSingleton()
return singleton;
}
-/**
- * Registers a ProgramDoc object, which contains documentation about the
- * program.
- *
- * @param doc Pointer to the ProgramDoc object.
- */
-void IO::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 != &emptyProgramDoc)
- GetSingleton().doc = doc;
-}
-
// Get the parameters that the IO object knows about.
std::map& IO::Parameters()
{
@@ -180,10 +162,10 @@ std::map& IO::Aliases()
return GetSingleton().aliases;
}
-// Get the program name as set by PROGRAM_INFO().
+// Get the program name as set by BINDING_NAME().
std::string IO::ProgramName()
{
- return GetSingleton().doc->programName;
+ return GetSingleton().doc.programName;
}
// Set a particular parameter as passed.
diff --git a/src/mlpack/core/util/io.hpp b/src/mlpack/core/util/io.hpp
index c0da36f8ae..427142c897 100644
--- a/src/mlpack/core/util/io.hpp
+++ b/src/mlpack/core/util/io.hpp
@@ -23,6 +23,7 @@
#include
#include "timers.hpp"
+#include "binding_details.hpp"
#include "program_doc.hpp"
#include "version.hpp"
@@ -32,13 +33,6 @@
#include
namespace mlpack {
-namespace util {
-
-// Externally defined in option.hpp, this class holds information about the
-// program being run.
-class ProgramDoc;
-
-} // namespace util
/**
* @brief Parses the command line for parameters and holds user-specified
@@ -76,7 +70,7 @@ class ProgramDoc;
* 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 KNN
- * executable (methods/neighbor_search/knn_main.cpp):
+ * binding (methods/neighbor_search/knn_main.cpp):
*
* @code
* PARAM_STRING_REQ("reference_file", "File containing the reference dataset.",
@@ -99,14 +93,24 @@ class ProgramDoc;
* @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.
+ * module, the BINDING_NAME() macro provides support for documenting the
+ * programName, BINDING_SHORT_DESC() macro provides support for documenting the
+ * shortDescription, BINDING_LONG_DESC() macro provides support for documenting
+ * the longDescription, the BINDING_EXAMPLE() macro provides support for
+ * documenting the example and the BINDING_SEE_ALSO() macro provides support for
+ * documenting the seeAlso. There should only be one instance of the
+ * BINDING_NAME(), BINDING_SHORT_DESC() and BINDING_LONG_DESC() macros and there
+ * can be multiple instance of BINDING_EXAMPLE() and BINDING_SEE_ALSO() macro.
* Below is an example:
*
* @code
- * PROGRAM_INFO("Maximum Variance Unfolding", "This program performs maximum "
+ * BINDING_NAME("Maximum Variance Unfolding");
+ * BINDING_SHORT_DESC("An implementation of Maximum Variance Unfolding");
+ * BINDING_LONG_DESC( "This program performs maximum "
* "variance unfolding on the given dataset, writing a lower-dimensional "
* "unfolded dataset to the given output file.");
+ * BINDING_EXAMPLE("mvu", "input", "dataset", "new_dim", 5, "output", "output");
+ * BINDING_SEE_ALSO("Perceptron", "#perceptron");
* @endcode
*
* This description should be verbose, and explain to a non-expert user what the
@@ -152,10 +156,10 @@ class ProgramDoc;
*
* @note
* Options should only be defined in files which define `main()` (that is, main
- * executables). If options are defined elsewhere, they may be spuriously
- * included into other executables and confuse users. Similarly, if your
- * executable has options which you did not define, it is probably because the
- * option is defined somewhere else and included in your executable.
+ * bindings). If options are defined elsewhere, they may be spuriously
+ * included into other bindings and confuse users. Similarly, if your
+ * binding has options which you did not define, it is probably because the
+ * option is defined somewhere else and included in your binding.
*
* @bug
* The __COUNTER__ variable is used in most cases to guarantee a unique global
@@ -240,21 +244,12 @@ class IO
*/
static IO& GetSingleton();
- /**
- * 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(util::ProgramDoc* doc);
-
//! Return a modifiable list of parameters that IO knows about.
static std::map& Parameters();
//! Return a modifiable list of aliases that IO knows about.
static std::map& Aliases();
- //! Get the program name as set by the PROGRAM_INFO() macro.
+ //! Get the program name as set by the BINDING_NAME() macro.
static std::string ProgramName();
/**
@@ -313,7 +308,7 @@ class IO
bool didParse;
//! Holds the name of the program for --version. This is the true program
- //! name (argv[0]) not what is given in ProgramDoc.
+ //! name (argv[0]) not what is given in BindingDetails.
std::string programName;
//! Holds the timer objects.
@@ -322,9 +317,8 @@ class IO
//! So that Timer::Start() and Timer::Stop() can access the timer variable.
friend class Timer;
- //! Pointer to the ProgramDoc object.
- util::ProgramDoc* doc;
-
+ //! Holds the bindingDetails objects.
+ util::BindingDetails doc;
private:
/**
* Make the constructor private, to preclude unauthorized instances.
diff --git a/src/mlpack/core/util/mlpack_main.hpp b/src/mlpack/core/util/mlpack_main.hpp
index 8c0b2613c7..26fab564de 100644
--- a/src/mlpack/core/util/mlpack_main.hpp
+++ b/src/mlpack/core/util/mlpack_main.hpp
@@ -153,13 +153,6 @@ using Option = mlpack::bindings::tests::TestOption;
// testName symbol should be defined in each binding test file
#include
-#undef PROGRAM_INFO
-#define PROGRAM_INFO(NAME, SHORT_DESC, DESC, EXAMPLE, ...) static \
- mlpack::util::ProgramDoc \
- io_programdoc_dummy_object = mlpack::util::ProgramDoc(NAME, SHORT_DESC, \
- []() { return std::string(DESC) + "\n\n" + std::string(EXAMPLE); }, []() \
- { return ""; }, { __VA_ARGS__ })
-
#elif(BINDING_TYPE == BINDING_TYPE_PYX) // This is a Python binding.
// Matrices are transposed on load/save.
@@ -219,12 +212,10 @@ using Option = mlpack::bindings::python::PyOption;
static const std::string testName = "";
#include
-#undef PROGRAM_INFO
-#define PROGRAM_INFO(NAME, SHORT_DESC, DESC, EXAMPLE, ...) static \
- mlpack::util::ProgramDoc \
- io_programdoc_dummy_object = mlpack::util::ProgramDoc(NAME, SHORT_DESC, \
- []() { return std::string(DESC) + "\n\n" + std::string(EXAMPLE); }, []() \
- { return ""; }, { __VA_ARGS__ }); \
+#undef BINDING_NAME
+#define BINDING_NAME(NAME) static \
+ mlpack::util::ProgramName \
+ io_programname_dummy_object = mlpack::util::ProgramName(NAME); \
namespace mlpack { \
namespace bindings { \
namespace python { \
@@ -269,12 +260,10 @@ using Option = mlpack::bindings::julia::JuliaOption;
static const std::string testName = "";
#include
-#undef PROGRAM_INFO
-#define PROGRAM_INFO(NAME, SHORT_DESC, DESC, EXAMPLE, ...) static \
- mlpack::util::ProgramDoc \
- io_programdoc_dummy_object = mlpack::util::ProgramDoc(NAME, SHORT_DESC, \
- []() { return std::string(DESC) + "\n\n" + std::string(EXAMPLE); }, []() \
- { return ""; }, { __VA_ARGS__ }); \
+#undef BINDING_NAME
+#define BINDING_NAME(NAME) static \
+ mlpack::util::ProgramName \
+ io_programname_dummy_object = mlpack::util::ProgramName(NAME); \
namespace mlpack { \
namespace bindings { \
namespace julia { \
@@ -315,12 +304,10 @@ using Option = mlpack::bindings::go::GoOption;
static const std::string testName = "";
#include
-#undef PROGRAM_INFO
-#define PROGRAM_INFO(NAME, SHORT_DESC, DESC, EXAMPLE, ...) static \
- mlpack::util::ProgramDoc \
- io_programdoc_dummy_object = mlpack::util::ProgramDoc(NAME, SHORT_DESC, \
- []() { return std::string(DESC) + "\n\n" + std::string(EXAMPLE); }, []() \
- { return ""; }, { __VA_ARGS__ }); \
+#undef BINDING_NAME
+#define BINDING_NAME(NAME) static \
+ mlpack::util::ProgramName \
+ io_programname_dummy_object = mlpack::util::ProgramName(NAME); \
namespace mlpack { \
namespace bindings { \
namespace go { \
@@ -374,9 +361,11 @@ PARAM_FLAG("verbose", "Display informational messages and the full list of "
#elif BINDING_TYPE == BINDING_TYPE_MARKDOWN
-// We use BINDING_NAME in PROGRAM_INFO() so it needs to be defined.
-#ifndef BINDING_NAME
- #error "BINDING_NAME must be defined when BINDING_TYPE is Markdown!"
+// We use MARKDOWN_BINDING_NAME in BINDING_NAME(), BINDING_SHORT_DESC(),
+// BINDING_LONG_DESC(), BINDING_EXAMPLE() and BINDING_SEE_ALSO()
+// so it needs to be defined.
+#ifndef MARKDOWN_BINDING_NAME
+ #error "MARKDOWN_BINDING_NAME must be defined when BINDING_TYPE is Markdown!"
#endif
// This value doesn't actually matter, but it needs to be defined as something.
@@ -439,13 +428,55 @@ using Option = mlpack::bindings::markdown::MDOption;
#include
#include
-#undef PROGRAM_INFO
-#define PROGRAM_INFO(NAME, SHORT_DESC, DESC, EXAMPLE, ...) static \
- mlpack::bindings::markdown::ProgramDocWrapper \
- io_programdoc_dummy_object = \
- mlpack::bindings::markdown::ProgramDocWrapper(BINDING_NAME, NAME, \
- SHORT_DESC, []() { return std::string(DESC) + "\n\n" + std::string( \
- EXAMPLE); }, []() { return ""; }, { __VA_ARGS__ }); \
+#undef BINDING_NAME
+#undef BINDING_SHORT_DESC
+#undef BINDING_LONG_DESC
+#undef BINDING_EXAMPLE
+#undef BINDING_SEE_ALSO
+
+#define BINDING_NAME(NAME) static \
+ mlpack::bindings::markdown::ProgramNameWrapper \
+ io_programname_dummy_object = \
+ mlpack::bindings::markdown::ProgramNameWrapper( \
+ MARKDOWN_BINDING_NAME, NAME);
+
+#define BINDING_SHORT_DESC(SHORT_DESC) static \
+ mlpack::bindings::markdown::ShortDescriptionWrapper \
+ io_programshort_desc_dummy_object = \
+ mlpack::bindings::markdown::ShortDescriptionWrapper( \
+ MARKDOWN_BINDING_NAME, SHORT_DESC);
+
+#define BINDING_LONG_DESC(LONG_DESC) static \
+ mlpack::bindings::markdown::LongDescriptionWrapper \
+ io_programlong_desc_dummy_object = \
+ mlpack::bindings::markdown::LongDescriptionWrapper( \
+ MARKDOWN_BINDING_NAME, []() { return std::string(LONG_DESC); });
+
+#ifdef __COUNTER__
+ #define BINDING_EXAMPLE(EXAMPLE) static \
+ mlpack::bindings::markdown::ExampleWrapper \
+ JOIN(io_programexample_dummy_object_, __COUNTER__) = \
+ mlpack::bindings::markdown::ExampleWrapper(MARKDOWN_BINDING_NAME, \
+ []() { return(std::string(EXAMPLE)); });
+
+ #define BINDING_SEE_ALSO(DESCRIPTION, LINK) static \
+ mlpack::bindings::markdown::SeeAlsoWrapper \
+ JOIN(io_programsee_also_dummy_object_, __COUNTER__) = \
+ mlpack::bindings::markdown::SeeAlsoWrapper(MARKDOWN_BINDING_NAME, \
+ DESCRIPTION, LINK);
+#else
+ #define BINDING_EXAMPLE(EXAMPLE) static \
+ mlpack::bindings::markdown::ExampleWrapper \
+ JOIN(JOIN(io_programexample_dummy_object_, __LINE__), opt) = \
+ mlpack::bindings::markdown::ExampleWrapper(MARKDOWN_BINDING_NAME, \
+ []() { return(std::string(EXAMPLE)); });
+
+ #define BINDING_SEE_ALSO(DESCRIPTION, LINK) static \
+ mlpack::bindings::markdown::SeeAlsoWrapper \
+ JOIN(JOIN(io_programsee_also_dummy_object_, __LINE__), opt) = \
+ mlpack::bindings::markdown::SeeAlsoWrapper(MARKDOWN_BINDING_NAME, \
+ DESCRIPTION, LINK);
+#endif
PARAM_FLAG("verbose", "Display informational messages and the full list of "
"parameters and timers at the end of execution.", "v");
diff --git a/src/mlpack/core/util/param.hpp b/src/mlpack/core/util/param.hpp
index 272093d092..ab679a2f00 100644
--- a/src/mlpack/core/util/param.hpp
+++ b/src/mlpack/core/util/param.hpp
@@ -4,8 +4,8 @@
* @author Ryan Curtin
*
* Definition of PARAM_*_IN() and PARAM_*_OUT() macros, as well as the
- * PROGRAM_INFO() macro, which are used to define input and output parameters of
- * command-line programs and bindings to other languages.
+ * Documentation related macro, which are used to define input and output
+ * parameters of command-line programs and bindings to other languages.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
@@ -30,6 +30,118 @@ using DatasetInfo = DatasetMapper;
} // namespace mlpack
/**
+ * @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 */
+
+/**
+ * Specify the program name of a binding. Only one instance of this macro
+ * should be present in your program! Therefore, use it in the main.cpp
+ * (or corresponding binding) in your program.
+ *
+ * @see mlpack::IO, PARAM_FLAG(), PARAM_INT_IN(), PARAM_DOUBLE_IN(),
+ * PARAM_STRING_IN(), PARAM_VECTOR_IN(), PARAM_INT_OUT(), PARAM_DOUBLE_OUT(),
+ * PARAM_VECTOR_OUT(), PARAM_INT_IN_REQ(), PARAM_DOUBLE_IN_REQ(),
+ * PARAM_STRING_IN_REQ(), PARAM_VECTOR_IN_REQ(), PARAM_INT_OUT_REQ(),
+ * PARAM_DOUBLE_OUT_REQ(), PARAM_VECTOR_OUT_REQ(), PARAM_STRING_OUT_REQ().
+ *
+ * @param NAME Short string representing the name of the program.
+ */
+#define BINDING_NAME(NAME) static \
+ mlpack::util::ProgramName \
+ io_programname_dummy_object = mlpack::util::ProgramName(NAME);
+
+/**
+ * Specify the short description of a binding. Only one instance of this macro
+ * should be present in your program! Therefore, use it in the main.cpp
+ * (or corresponding binding) in your program.
+ *
+ * @see mlpack::IO, PARAM_FLAG(), PARAM_INT_IN(), PARAM_DOUBLE_IN(),
+ * PARAM_STRING_IN(), PARAM_VECTOR_IN(), PARAM_INT_OUT(), PARAM_DOUBLE_OUT(),
+ * PARAM_VECTOR_OUT(), PARAM_INT_IN_REQ(), PARAM_DOUBLE_IN_REQ(),
+ * PARAM_STRING_IN_REQ(), PARAM_VECTOR_IN_REQ(), PARAM_INT_OUT_REQ(),
+ * PARAM_DOUBLE_OUT_REQ(), PARAM_VECTOR_OUT_REQ(), PARAM_STRING_OUT_REQ().
+ *
+ * @param SHORT_DESC Short two-sentence description of the program; it should
+ * describe what the program implements and does, and a quick overview of
+ * how it can be used and what it should be used for.
+ */
+#define BINDING_SHORT_DESC(SHORT_DESC) static \
+ mlpack::util::ShortDescription \
+ io_programshort_desc_dummy_object = mlpack::util::ShortDescription( \
+ SHORT_DESC);
+
+/**
+ * Specify the long description of a binding. Only one instance of this macro
+ * present in your program! Therefore, use it in the main.cpp
+ * (or corresponding binding) in your program.
+ *
+ * @see mlpack::IO, PARAM_FLAG(), PARAM_INT_IN(), PARAM_DOUBLE_IN(),
+ * PARAM_STRING_IN(), PARAM_VECTOR_IN(), PARAM_INT_OUT(), PARAM_DOUBLE_OUT(),
+ * PARAM_VECTOR_OUT(), PARAM_INT_IN_REQ(), PARAM_DOUBLE_IN_REQ(),
+ * PARAM_STRING_IN_REQ(), PARAM_VECTOR_IN_REQ(), PARAM_INT_OUT_REQ(),
+ * PARAM_DOUBLE_OUT_REQ(), PARAM_VECTOR_OUT_REQ(), PARAM_STRING_OUT_REQ().
+ *
+ * @param LONG_DESC Long string describing what the program does. Newlines
+ * should not be used here; this is taken care of by IO (however, you
+ * can explicitly specify newlines to denote new paragraphs). You can
+ * also use printing macros like PRINT_PARAM_STRING(), PRINT_DATASET(),
+ * and others.
+ */
+#define BINDING_LONG_DESC(LONG_DESC) static \
+ mlpack::util::LongDescription \
+ io_programlong_desc_dummy_object = mlpack::util::LongDescription( \
+ []() { return std::string(LONG_DESC); });
+
+/**
+ * Specify the example of a binding. Mutiple instance of this macro can be
+ * present in your program! Therefore, use it in the main.cpp
+ * (or corresponding binding) in your program.
+ *
+ * @see mlpack::IO, PARAM_FLAG(), PARAM_INT_IN(), PARAM_DOUBLE_IN(),
+ * PARAM_STRING_IN(), PARAM_VECTOR_IN(), PARAM_INT_OUT(), PARAM_DOUBLE_OUT(),
+ * PARAM_VECTOR_OUT(), PARAM_INT_IN_REQ(), PARAM_DOUBLE_IN_REQ(),
+ * PARAM_STRING_IN_REQ(), PARAM_VECTOR_IN_REQ(), PARAM_INT_OUT_REQ(),
+ * PARAM_DOUBLE_OUT_REQ(), PARAM_VECTOR_OUT_REQ(), PARAM_STRING_OUT_REQ().
+ *
+ * @param EXAMPLE Long string describing a simple usage example.. Newlines
+ * should not be used here; this is taken care of by IO (however, you
+ * can explicitly specify newlines to denote new paragraphs). You can
+ * also use printing macros like PRINT_CALL(), PRINT_DATASET(),
+ * and others.
+ */
+#ifdef __COUNTER__
+ #define BINDING_EXAMPLE(EXAMPLE) static \
+ mlpack::util::Example \
+ JOIN(io_programexample_dummy_object_, __COUNTER__) = \
+ mlpack::util::Example( \
+ []() { return(std::string(EXAMPLE)); });
+#else
+ #define BINDING_EXAMPLE(EXAMPLE) static \
+ mlpack::util::Example \
+ JOIN(JOIN(io_programexample_dummy_object_, __LINE__), opt) = \
+ mlpack::util::Example( \
+ []() { return(std::string(EXAMPLE)); });
+#endif
+
+/**
+ * Specify the see-also of a binding. Mutiple instance of this macro can be
+ * present in your program! Therefore, use it in the main.cpp
+ * (or corresponding binding) in your program.
+ *
+ * @see mlpack::IO, PARAM_FLAG(), PARAM_INT_IN(), PARAM_DOUBLE_IN(),
+ * PARAM_STRING_IN(), PARAM_VECTOR_IN(), PARAM_INT_OUT(), PARAM_DOUBLE_OUT(),
+ * PARAM_VECTOR_OUT(), PARAM_INT_IN_REQ(), PARAM_DOUBLE_IN_REQ(),
+ * PARAM_STRING_IN_REQ(), PARAM_VECTOR_IN_REQ(), PARAM_INT_OUT_REQ(),
+ * PARAM_DOUBLE_OUT_REQ(), PARAM_VECTOR_OUT_REQ(), PARAM_STRING_OUT_REQ().
+ *
* Provide a link for a binding's "see also" documentation section, which is
* primarily (but not necessarily exclusively) used by the Markdown bindings
* This link can be specified by calling SEE_ALSO("description", "link"), where
@@ -42,39 +154,17 @@ using DatasetInfo = DatasetMapper;
* - A link to a Doxygen page, using the mangled Doxygen name after a
* '\@doxygen/', i.e., "@doxygen/mlpack1_1_adaboost1_1_AdaBoost".
*/
-#define SEE_ALSO(DESCRIPTION, LINK) {DESCRIPTION, LINK}
-
-/**
- * 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::IO, PARAM_FLAG(), PARAM_INT_IN(), PARAM_DOUBLE_IN(),
- * PARAM_STRING_IN(), PARAM_VECTOR_IN(), PARAM_INT_OUT(), PARAM_DOUBLE_OUT(),
- * PARAM_VECTOR_OUT(), PARAM_INT_IN_REQ(), PARAM_DOUBLE_IN_REQ(),
- * PARAM_STRING_IN_REQ(), PARAM_VECTOR_IN_REQ(), PARAM_INT_OUT_REQ(),
- * PARAM_DOUBLE_OUT_REQ(), PARAM_VECTOR_OUT_REQ(), PARAM_STRING_OUT_REQ().
- *
- * @param NAME Short string representing the name of the program.
- * @param SHORT_DESC Short two-sentence description of the program; it should
- * describe what the program implements and does, and a quick overview of
- * how it can be used and what it should be used for.
- * @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 IO (however, you can explicitly specify newlines to denote
- * new paragraphs). You can also use printing macros like
- * PRINT_PARAM_STRING(), PRINT_DATASET(), and others.
- * @param EXAMPLE A simple usage example. You can also use printing macros like
- * PRINT_PARAM_STRING(), PRINT_CALL(), and others.
- * @param ... A set of SEE_ALSO() macros that are used for generating
- * documentation. See the SEE_ALSO() macro. This is a varargs argument, so
- * you can add as many SEE_ALSO()s as you like.
- */
-#define PROGRAM_INFO(NAME, SHORT_DESC, DESC, EXAMPLE, ...) \
- static mlpack::util::ProgramDoc \
- io_programdoc_dummy_object = mlpack::util::ProgramDoc(NAME, SHORT_DESC, \
- []() { return std::string(DESC) + std::string(EXAMPLE); }, []() \
- { return ""; }, { __VA_ARGS__ })
+#ifdef __COUNTER__
+ #define BINDING_SEE_ALSO(DESCRIPTION, LINK) static \
+ mlpack::util::SeeAlso \
+ JOIN(io_programsee_also_dummy_object_, __COUNTER__) = \
+ mlpack::util::SeeAlso(DESCRIPTION, LINK);
+#else
+ #define BINDING_SEE_ALSO(DESCRIPTION, LINK) static \
+ mlpack::util::SeeAlso \
+ JOIN(JOIN(io_programsee_also_dummy_object_, __LINE__), opt) = \
+ mlpack::util::SeeAlso(DESCRIPTION, LINK);
+#endif
/**
* Define a flag parameter.
@@ -85,7 +175,8 @@ using DatasetInfo = DatasetMapper;
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
*
- * @see mlpack::IO, PROGRAM_INFO()
+ * @see mlpack::IO, BINDING_NAME(), BINDING_SHORT_DESC(), BINDING_LONG_DESC(),
+ * BINDING_EXAMPLE() and BINDING_SEE_ALSO().
*
* @bug
* The __COUNTER__ variable is used in most cases to guarantee a unique global
@@ -111,7 +202,8 @@ using DatasetInfo = DatasetMapper;
* @param ALIAS An alias for the parameter (one letter).
* @param DEF Default value of the parameter.
*
- * @see mlpack::IO, PROGRAM_INFO()
+ * @see mlpack::IO, BINDING_NAME(), BINDING_SHORT_DESC(), BINDING_LONG_DESC(),
+ * BINDING_EXAMPLE() and BINDING_SEE_ALSO().
*
* @bug
// Use a forward declaration of the class.
@@ -142,7 +234,8 @@ using DatasetInfo = DatasetMapper;
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
*
- * @see mlpack::IO, PROGRAM_INFO()
+ * @see mlpack::IO, BINDING_NAME(), BINDING_SHORT_DESC(), BINDING_LONG_DESC(),
+ * BINDING_EXAMPLE() and BINDING_SEE_ALSO().
*
* @bug
* The __COUNTER__ variable is used in most cases to guarantee a unique global
@@ -168,7 +261,8 @@ using DatasetInfo = DatasetMapper;
* @param ALIAS An alias for the parameter (one letter).
* @param DEF Default value of the parameter.
*
- * @see mlpack::IO, PROGRAM_INFO()
+ * @see mlpack::IO, BINDING_NAME(), BINDING_SHORT_DESC(), BINDING_LONG_DESC(),
+ * BINDING_EXAMPLE() and BINDING_SEE_ALSO().
*
* @bug
* The __COUNTER__ variable is used in most cases to guarantee a unique global
@@ -198,7 +292,8 @@ using DatasetInfo = DatasetMapper;
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
*
- * @see mlpack::IO, PROGRAM_INFO()
+ * @see mlpack::IO, BINDING_NAME(), BINDING_SHORT_DESC(), BINDING_LONG_DESC(),
+ * BINDING_EXAMPLE() and BINDING_SEE_ALSO().
*
* @bug
* The __COUNTER__ variable is used in most cases to guarantee a unique global
@@ -216,7 +311,8 @@ using DatasetInfo = DatasetMapper;
*
* 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.
+ * BINDING_LONG_DESC() 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). Don't use
@@ -225,7 +321,8 @@ using DatasetInfo = DatasetMapper;
* @param ALIAS An alias for the parameter (one letter).
* @param DEF Default value of the parameter.
*
- * @see mlpack::IO, PROGRAM_INFO()
+ * @see mlpack::IO, BINDING_NAME(), BINDING_SHORT_DESC(), BINDING_LONG_DESC(),
+ * BINDING_EXAMPLE() and BINDING_SEE_ALSO().
*
* @bug
* The __COUNTER__ variable is used in most cases to guarantee a unique global
@@ -256,7 +353,8 @@ using DatasetInfo = DatasetMapper;
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
*
- * @see mlpack::IO, PROGRAM_INFO()
+ * @see mlpack::IO, BINDING_NAME(), BINDING_SHORT_DESC(), BINDING_LONG_DESC(),
+ * BINDING_EXAMPLE() and BINDING_SEE_ALSO().
*
* @bug
* The __COUNTER__ variable is used in most cases to guarantee a unique global
@@ -830,7 +928,8 @@ using DatasetInfo = DatasetMapper;
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
*
- * @see mlpack::IO, PROGRAM_INFO()
+ * @see mlpack::IO, BINDING_NAME(), BINDING_SHORT_DESC(), BINDING_LONG_DESC(),
+ * BINDING_EXAMPLE() and BINDING_SEE_ALSO().
*
* @bug
* The __COUNTER__ variable is used in most cases to guarantee a unique global
@@ -863,7 +962,8 @@ using DatasetInfo = DatasetMapper;
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
*
- * @see mlpack::IO, PROGRAM_INFO()
+ * @see mlpack::IO, BINDING_NAME(), BINDING_SHORT_DESC(), BINDING_LONG_DESC(),
+ * BINDING_EXAMPLE() and BINDING_SEE_ALSO().
*
* @bug
* The __COUNTER__ variable is used in most cases to guarantee a unique global
@@ -902,7 +1002,8 @@ using DatasetInfo = DatasetMapper;
* here---it will cause problems.
* @param ALIAS One-character string representing the alias of the parameter.
*
- * @see mlpack::IO, PROGRAM_INFO()
+ * @see mlpack::IO, BINDING_NAME(), BINDING_SHORT_DESC(), BINDING_LONG_DESC(),
+ * BINDING_EXAMPLE() and BINDING_SEE_ALSO().
*
* @bug
* The __COUNTER__ variable is used in most cases to guarantee a unique global
@@ -1014,7 +1115,8 @@ using DatasetInfo = DatasetMapper;
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
*
- * @see mlpack::IO, PROGRAM_INFO()
+ * @see mlpack::IO, BINDING_NAME(), BINDING_SHORT_DESC(), BINDING_LONG_DESC(),
+ * BINDING_EXAMPLE() and BINDING_SEE_ALSO().
*
* @bug
* The __COUNTER__ variable is used in most cases to guarantee a unique global
@@ -1038,7 +1140,8 @@ using DatasetInfo = DatasetMapper;
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
*
- * @see mlpack::IO, PROGRAM_INFO()
+ * @see mlpack::IO, BINDING_NAME(), BINDING_SHORT_DESC(), BINDING_LONG_DESC(),
+ * BINDING_EXAMPLE() and BINDING_SEE_ALSO().
*
* @bug
* The __COUNTER__ variable is used in most cases to guarantee a unique global
@@ -1062,7 +1165,8 @@ using DatasetInfo = DatasetMapper;
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
*
- * @see mlpack::IO, PROGRAM_INFO()
+ * @see mlpack::IO, BINDING_NAME(), BINDING_SHORT_DESC(), BINDING_LONG_DESC(),
+ * BINDING_EXAMPLE() and BINDING_SEE_ALSO().
*
* @bug
* The __COUNTER__ variable is used in most cases to guarantee a unique global
@@ -1088,7 +1192,8 @@ using DatasetInfo = DatasetMapper;
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
*
- * @see mlpack::IO, PROGRAM_INFO()
+ * @see mlpack::IO, BINDING_NAME(), BINDING_SHORT_DESC(), BINDING_LONG_DESC(),
+ * BINDING_EXAMPLE() and BINDING_SEE_ALSO().
*
* @bug
* The __COUNTER__ variable is used in most cases to guarantee a unique global
@@ -1101,18 +1206,6 @@ using DatasetInfo = DatasetMapper;
#define PARAM_VECTOR_IN_REQ(T, ID, DESC, ALIAS) \
PARAM_IN(std::vector, ID, DESC, ALIAS, std::vector(), 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
diff --git a/src/mlpack/core/util/program_doc.cpp b/src/mlpack/core/util/program_doc.cpp
index 269b93c237..a5c623df72 100644
--- a/src/mlpack/core/util/program_doc.cpp
+++ b/src/mlpack/core/util/program_doc.cpp
@@ -1,9 +1,10 @@
/**
* @file core/util/program_doc.cpp
+ * @author Yashwant Singh Parihar
* @author Ryan Curtin
*
- * Implementation of the ProgramDoc class. The class registers itself with IO
- * when constructed.
+ * Implementation of mutiple classes that store information related to a binding.
+ * The classes register themselves with IO when constructed.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
@@ -20,39 +21,70 @@ using namespace mlpack::util;
using namespace std;
/**
- * Construct a ProgramDoc object. When constructed, it will register itself
+ * Construct a ProgramName object. When constructed, it will register itself
* with IO. A fatal error will be thrown if more than one is constructed.
*
- * @param defaultModule Name of the default module.
- * @param shortDocumentation A short two-sentence description of the program,
- * what it does, and what it is useful for.
- * @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 IO later.
- * @param example Documentation on how to use the program.
- * @param seeAlso A set of pairs of strings with useful "see also"
- * information; each pair is .
+ * @param programName Name of the binding.
*/
-ProgramDoc::ProgramDoc(
- const std::string programName,
- const std::string shortDocumentation,
- const std::function documentation,
- const std::function example,
- const std::vector> seeAlso) :
- programName(std::move(programName)),
- shortDocumentation(std::move(shortDocumentation)),
- documentation(std::move(documentation)),
- example(std::move(example)),
- seeAlso(std::move(seeAlso))
+ProgramName::ProgramName(const std::string& programName)
{
// Register this with IO.
- IO::RegisterProgramDoc(this);
+ IO::GetSingleton().doc.programName = std::move(programName);
}
/**
- * Construct an empty ProgramDoc object.
+ * Construct a ShortDescription object. When constructed, it will register
+ * itself with IO. A fatal error will be thrown if more than one is
+ * constructed.
+ *
+ * @param shortDescription A short two-sentence description of the binding,
+ * what it does, and what it is useful for.
*/
-ProgramDoc::ProgramDoc()
+ShortDescription::ShortDescription(const std::string& shortDescription)
{
- IO::RegisterProgramDoc(this);
+ // Register this with IO.
+ IO::GetSingleton().doc.shortDescription = std::move(shortDescription);
+}
+
+/**
+ * Construct a LongDescription object. When constructed, it will register itself
+ * with IO. A fatal error will be thrown if more than one is constructed.
+ *
+ * @param longDescription Long string containing documentation on
+ * what it is. No newline characters are necessary; this is
+ * taken care of by IO later.
+ */
+LongDescription::LongDescription(
+ const std::function& longDescription)
+{
+ // Register this with IO.
+ IO::GetSingleton().doc.longDescription = std::move(longDescription);
+}
+
+/**
+ * Construct a Example object. When constructed, it will register itself
+ * with IO.
+ *
+ * @param example Documentation on how to use the binding.
+ */
+Example::Example(
+ const std::function& example)
+{
+ // Register this with IO.
+ IO::GetSingleton().doc.example.push_back(std::move(example));
+}
+
+/**
+ * Construct a SeeAlso object. When constructed, it will register itself
+ * with IO.
+ *
+ * @param description Description of SeeAlso.
+ * @param link Link of SeeAlso.
+ */
+SeeAlso::SeeAlso(
+ const std::string& description, const std::string& link)
+{
+ // Register this with IO.
+ IO::GetSingleton().doc.seeAlso.push_back(std::move(
+ make_pair(description, link)));
}
diff --git a/src/mlpack/core/util/program_doc.hpp b/src/mlpack/core/util/program_doc.hpp
index 1b61249160..0d71d93fe5 100644
--- a/src/mlpack/core/util/program_doc.hpp
+++ b/src/mlpack/core/util/program_doc.hpp
@@ -1,8 +1,10 @@
/**
* @file core/util/program_doc.hpp
+ * @author Yashwant Singh Parihar
* @author Matthew Amidon
*
- * The structure used to store a program's name and documentation.
+ * Implementation of mutiple classes that store information related to a binding.
+ * The classes register themselves with IO when constructed.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
@@ -15,54 +17,69 @@
namespace mlpack {
namespace util {
-/**
- * A static object whose constructor registers program documentation with the
- * IO class. This should not be used outside of IO itself, and you should use
- * the PROGRAM_INFO() macro to declare these objects. Only one ProgramDoc
- * object should ever exist.
- *
- * @see core/util/io.hpp, mlpack::IO
- */
-class ProgramDoc
+class ProgramName
{
public:
/**
- * Construct a ProgramDoc object. When constructed, it will register itself
- * with IO, and when the user calls --help (or whatever the option is named
- * for the given binding type), the given function that returns a std::string
- * will be returned.
+ * Construct a ProgramName object. When constructed, it will register itself
+ * with IO. A fatal error will be thrown if more than one is constructed.
*
- * @param programName Short string representing the name of the program.
- * @param shortDocumentation A short two-sentence description of the program,
- * what it does, and what it is useful for.
- * @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 IO later.
- * @param example Documentation on how to use the program.
- * @param seeAlso A set of pairs of strings with useful "see also"
- * information; each pair is .
+ * @param programName Name of the binding.
*/
- ProgramDoc(const std::string programName,
- const std::string shortDocumentation,
- const std::function documentation,
- const std::function example,
- const std::vector> seeAlso);
+ ProgramName(const std::string& programName);
+};
+class ShortDescription
+{
+ public:
/**
- * Construct an empty ProgramDoc object. (This is not meant to be used!)
+ * Construct a ShortDescription object. When constructed, it will register
+ * itself with IO. A fatal error will be thrown if more than one is
+ * constructed.
+ *
+ * @param shortDescription A short two-sentence description of the binding,
+ * what it does, and what it is useful for.
*/
- ProgramDoc();
+ ShortDescription(const std::string& shortDescription);
+};
- //! The name of the program.
- std::string programName;
- //! The short documentation for the program.
- std::string shortDocumentation;
- //! Documentation for what the program does.
- std::function documentation;
- //! Example for the program.
- std::function example;
- //! Set of see also information.
- std::vector> seeAlso;
+class LongDescription
+{
+ public:
+ /**
+ * Construct a LongDescription object. When constructed, it will register itself
+ * with IO. A fatal error will be thrown if more than one is constructed.
+ *
+ * @param longDescription Long string containing documentation on
+ * what it is. No newline characters are necessary; this is
+ * taken care of by IO later.
+ */
+ LongDescription(const std::function& longDescription);
+};
+
+class Example
+{
+ public:
+ /**
+ * Construct a Example object. When constructed, it will register itself
+ * with IO.
+ *
+ * @param example Documentation on how to use the binding.
+ */
+ Example(const std::function& example);
+};
+
+class SeeAlso
+{
+ public:
+ /**
+ * Construct a SeeAlso object. When constructed, it will register itself
+ * with IO.
+ *
+ * @param description Description of SeeAlso.
+ * @param link Link of SeeAlso.
+ */
+ SeeAlso(const std::string& description, const std::string& link);
};
} // namespace util
diff --git a/src/mlpack/methods/adaboost/adaboost_main.cpp b/src/mlpack/methods/adaboost/adaboost_main.cpp
index c0acc86103..4635d438f6 100644
--- a/src/mlpack/methods/adaboost/adaboost_main.cpp
+++ b/src/mlpack/methods/adaboost/adaboost_main.cpp
@@ -46,13 +46,18 @@ using namespace mlpack::tree;
using namespace mlpack::perceptron;
using namespace mlpack::util;
-PROGRAM_INFO("AdaBoost",
- // Short description.
+// Program Name.
+BINDING_NAME("AdaBoost");
+
+// Short description.
+BINDING_SHORT_DESC(
"An implementation of the AdaBoost.MH (Adaptive Boosting) algorithm for "
"classification. This can be used to train an AdaBoost model on labeled "
"data or use an existing AdaBoost model to predict the classes of new "
- "points.",
- // Long description.
+ "points.");
+
+// Long description.
+BINDING_LONG_DESC(
"This program implements the AdaBoost (or Adaptive "
"Boosting) algorithm. The variant of AdaBoost implemented here is "
"AdaBoost.MH. It uses a weak learner, either decision stumps or "
@@ -86,8 +91,10 @@ PROGRAM_INFO("AdaBoost",
"."
"\n"
"Use " + PRINT_PARAM_STRING("predictions") + " instead of " +
- PRINT_PARAM_STRING("output") + '.',
- // Example.
+ PRINT_PARAM_STRING("output") + '.');
+
+// Example.
+BINDING_EXAMPLE(
"For example, to run AdaBoost on an input dataset " +
PRINT_DATASET("data") + " with labels " + PRINT_DATASET("labels") +
"and perceptrons as the weak learner type, storing the trained model in " +
@@ -102,15 +109,17 @@ PROGRAM_INFO("AdaBoost",
PRINT_DATASET("predictions") + " with the following command: "
"\n\n" +
PRINT_CALL("adaboost", "input_model", "model", "test", "test_data",
- "predictions", "predictions"),
- // See also...
- SEE_ALSO("AdaBoost on Wikipedia", "https://en.wikipedia.org/wiki/AdaBoost"),
- SEE_ALSO("Improved boosting algorithms using confidence-rated predictions "
- "(pdf)", "http://rob.schapire.net/papers/SchapireSi98.pdf"),
- SEE_ALSO("Perceptron", "#perceptron"),
- SEE_ALSO("Decision Stump", "#decision_stump"),
- SEE_ALSO("mlpack::adaboost::AdaBoost C++ class documentation",
- "@doxygen/classmlpack_1_1adaboost_1_1AdaBoost.html"));
+ "predictions", "predictions"));
+
+// See also...
+BINDING_SEE_ALSO("AdaBoost on Wikipedia", "https://en.wikipedia.org/wiki/"
+ "AdaBoost");
+BINDING_SEE_ALSO("Improved boosting algorithms using confidence-rated "
+ "predictions (pdf)", "http://rob.schapire.net/papers/SchapireSi98.pdf");
+BINDING_SEE_ALSO("Perceptron", "#perceptron");
+BINDING_SEE_ALSO("Decision Stump", "#decision_stump");
+BINDING_SEE_ALSO("mlpack::adaboost::AdaBoost C++ class documentation",
+ "@doxygen/classmlpack_1_1adaboost_1_1AdaBoost.html");
// Input for training.
PARAM_MATRIX_IN("training", "Dataset for training AdaBoost.", "t");
diff --git a/src/mlpack/methods/ann/rbm/rbm.hpp b/src/mlpack/methods/ann/rbm/rbm.hpp
index 51faa83eaa..be8d939169 100644
--- a/src/mlpack/methods/ann/rbm/rbm.hpp
+++ b/src/mlpack/methods/ann/rbm/rbm.hpp
@@ -70,12 +70,12 @@ class RBM
const bool persistence = false);
// Reset the network.
- template
+ template
typename std::enable_if::value, void>::type
Reset();
// Reset the network.
- template
+ template
typename std::enable_if::value, void>::type
Reset();
@@ -116,9 +116,9 @@ class RBM
*
* @param input The visible neurons.
*/
- template
+ template
typename std::enable_if::value, double>::type
- FreeEnergy(arma::Mat&& input);
+ FreeEnergy(const arma::Mat& input);
/**
* This function calculates the free energy of the SpikeSlabRBM.
@@ -130,10 +130,10 @@ class RBM
*
* @param input The visible layer neurons.
*/
- template
+ template
typename std::enable_if::value,
double>::type
- FreeEnergy(arma::Mat&& input);
+ FreeEnergy(const arma::Mat& input);
/**
* Calculates the gradient of the RBM network on the provided input.
@@ -141,9 +141,9 @@ class RBM
* @param input The provided input data.
* @param gradient Stores the gradient of the RBM network.
*/
- template
+ template
typename std::enable_if::value, void>::type
- Phase(DataType&& input, DataType&& gradient);
+ Phase(const InputType& input, DataType& gradient);
/**
* Calculates the gradient of the RBM network on the provided input.
@@ -151,9 +151,9 @@ class RBM
* @param input The provided input data.
* @param gradient Stores the gradient of the RBM network.
*/
- template
+ template
typename std::enable_if::value, void>::type
- Phase(DataType&& input, DataType&& gradient);
+ Phase(const InputType& input, DataType& gradient);
/**
* This function samples the hidden layer given the visible layer using
@@ -162,9 +162,9 @@ class RBM
* @param input Visible layer input.
* @param output The sampled hidden layer.
*/
- template
+ template
typename std::enable_if::value, void>::type
- SampleHidden(arma::Mat&& input, arma::Mat&& output);
+ SampleHidden(const arma::Mat& input, arma::Mat& output);
/**
* This function samples the slab outputs from the Normal distribution with
@@ -176,9 +176,9 @@ class RBM
* @param input Consists of both visible and spike variables.
* @param output Sampled slab neurons.
*/
- template
+ template
typename std::enable_if::value, void>::type
- SampleHidden(arma::Mat&& input, arma::Mat&& output);
+ SampleHidden(const arma::Mat& input, arma::Mat& output);
/**
* This function samples the visible layer given the hidden layer using
@@ -187,9 +187,9 @@ class RBM
* @param input Hidden layer of the network.
* @param output The sampled visible layer.
*/
- template
+ template
typename std::enable_if::value, void>::type
- SampleVisible(arma::Mat&& input, arma::Mat&& output);
+ SampleVisible(arma::Mat& input, arma::Mat& output);
/**
* Sample Hidden function samples the slab outputs from the Normal
@@ -201,9 +201,9 @@ class RBM
* @param input Hidden layer of the network.
* @param output The sampled visible layer.
*/
- template
+ template
typename std::enable_if::value, void>::type
- SampleVisible(arma::Mat&& input, arma::Mat&& output);
+ SampleVisible(arma::Mat& input, arma::Mat& output);
/**
* The function calculates the mean for the visible layer.
@@ -211,9 +211,9 @@ class RBM
* @param input Hidden neurons from the hidden layer of the network.
* @param output Visible neuron activations.
*/
- template
+ template
typename std::enable_if::value, void>::type
- VisibleMean(DataType&& input, DataType&& output);
+ VisibleMean(InputType& input, DataType& output);
/**
* The function calculates the mean of the Normal distribution of P(v|s, h).
@@ -223,9 +223,9 @@ class RBM
* @param input Consists of both the spike and slab variables.
* @param output Mean of the of the Normal distribution.
*/
- template
+ template
typename std::enable_if::value, void>::type
- VisibleMean(DataType&& input, DataType&& output);
+ VisibleMean(InputType& input, DataType& output);
/**
* The function calculates the mean for the hidden layer.
@@ -233,9 +233,9 @@ class RBM
* @param input Visible neurons.
* @param output Hidden neuron activations.
*/
- template
+ template
typename std::enable_if::value, void>::type
- HiddenMean(DataType&& input, DataType&& output);
+ HiddenMean(const InputType& input, DataType& output);
/**
* The function calculates the mean of the Normal distribution of P(s|v, h).
@@ -247,9 +247,9 @@ class RBM
* @param input Visible layer neurons.
* @param output Consists of both the spike samples and slab samples.
*/
- template
+ template
typename std::enable_if::value, void>::type
- HiddenMean(DataType&& input, DataType&& output);
+ HiddenMean(const InputType& input, DataType& output);
/**
* The function calculates the mean of the distribution P(h|v),
@@ -259,18 +259,18 @@ class RBM
* @param visible The visible layer neurons.
* @param spikeMean Indicates P(h|v).
*/
- template
+ template
typename std::enable_if::value, void>::type
- SpikeMean(DataType&& visible, DataType&& spikeMean);
+ SpikeMean(const InputType& visible, DataType& spikeMean);
/**
* The function samples the spike function using Bernoulli distribution.
* @param spikeMean Indicates P(h|v).
* @param spike Sampled binary spike variables.
*/
- template
+ template
typename std::enable_if::value, void>::type
- SampleSpike(DataType&& spikeMean, DataType&& spike);
+ SampleSpike(InputType& spikeMean, DataType& spike);
/**
* The function calculates the mean of Normal distribution of P(s|v, h),
@@ -281,9 +281,9 @@ class RBM
* @param spike The spike variables from hidden layer.
* @param slabMean The mean of the Normal distribution of slab neurons.
*/
- template
+ template
typename std::enable_if::value, void>::type
- SlabMean(DataType&& visible, DataType&& spike, DataType&& slabMean);
+ SlabMean(const DataType& visible, DataType& spike, DataType& slabMean);
/**
* The function samples from the Normal distribution of P(s|v, h),
@@ -295,9 +295,9 @@ class RBM
* @param slabMean Mean of the Normal distribution of the slab neurons.
* @param slab Sampled slab variable from the Normal distribution.
*/
- template
+ template
typename std::enable_if::value, void>::type
- SampleSlab(DataType&& slabMean, DataType&& slab);
+ SampleSlab(InputType& slabMean, DataType& slab);
/**
* This function does the k-step Gibbs Sampling.
@@ -306,8 +306,8 @@ class RBM
* @param output Used for storing the negative sample.
* @param steps Number of Gibbs Sampling steps taken.
*/
- void Gibbs(arma::Mat&& input,
- arma::Mat&& output,
+ void Gibbs(const arma::Mat& input,
+ arma::Mat& output,
const size_t steps = SIZE_MAX);
/**
diff --git a/src/mlpack/methods/ann/rbm/rbm_impl.hpp b/src/mlpack/methods/ann/rbm/rbm_impl.hpp
index 79122b12d0..76014848b0 100644
--- a/src/mlpack/methods/ann/rbm/rbm_impl.hpp
+++ b/src/mlpack/methods/ann/rbm/rbm_impl.hpp
@@ -58,7 +58,7 @@ template<
typename DataType,
typename PolicyType
>
-template
+template
typename std::enable_if::value, void>::type
RBM::Reset()
{
@@ -108,10 +108,10 @@ template<
typename DataType,
typename PolicyType
>
-template
+template
typename std::enable_if::value, double>::type
RBM::FreeEnergy(
- arma::Mat&& input)
+ const arma::Mat& input)
{
preActivation = (weight.slice(0) * input);
preActivation.each_col() += hiddenBias;
@@ -124,11 +124,11 @@ template<
typename DataType,
typename PolicyType
>
-template
+template
typename std::enable_if::value, void>::type
RBM::Phase(
- DataType&& input,
- DataType&& gradient)
+ const InputType& input,
+ DataType& gradient)
{
arma::Cube weightGrad = arma::Cube(gradient.memptr(),
hiddenSize, visibleSize, 1, false, false);
@@ -136,7 +136,7 @@ RBM::Phase(
DataType hiddenBiasGrad = DataType(gradient.memptr() + weightGrad.n_elem,
hiddenSize, 1, false, false);
- HiddenMean(std::move(input), std::move(hiddenBiasGrad));
+ HiddenMean(input, hiddenBiasGrad);
weightGrad.slice(0) = hiddenBiasGrad * input.t();
}
@@ -150,10 +150,10 @@ double RBM::Evaluate(
const size_t i,
const size_t batchSize)
{
- Gibbs(std::move(predictors.cols(i, i + batchSize - 1)),
- std::move(negativeSamples));
- return std::fabs(FreeEnergy(std::move(predictors.cols(i,
- i + batchSize - 1))) - FreeEnergy(std::move(negativeSamples)));
+ Gibbs(predictors.cols(i, i + batchSize - 1),
+ negativeSamples);
+ return std::fabs(FreeEnergy(predictors.cols(i,
+ i + batchSize - 1)) - FreeEnergy(negativeSamples));
}
template<
@@ -161,13 +161,13 @@ template<
typename DataType,
typename PolicyType
>
-template
+template
typename std::enable_if::value, void>::type
RBM::SampleHidden(
- arma::Mat&& input,
- arma::Mat&& output)
+ const arma::Mat& input,
+ arma::Mat& output)
{
- HiddenMean(std::move(input), std::move(output));
+ HiddenMean(input, output);
for (size_t i = 0; i < output.n_elem; ++i)
{
@@ -180,13 +180,13 @@ template<
typename DataType,
typename PolicyType
>
-template
+template
typename std::enable_if::value, void>::type
RBM::SampleVisible(
- arma::Mat&& input,
- arma::Mat&& output)
+ arma::Mat& input,
+ arma::Mat& output)
{
- VisibleMean(std::move(input), std::move(output));
+ VisibleMean(input, output);
for (size_t i = 0; i < output.n_elem; ++i)
{
@@ -199,10 +199,11 @@ template<
typename DataType,
typename PolicyType
>
-template
+template
typename std::enable_if::value, void>::type
-RBM::VisibleMean(DataType&& input,
- DataType&& output)
+RBM::VisibleMean(
+ InputType& input,
+ DataType& output)
{
output = weight.slice(0).t() * input;
output.each_col() += visibleBias;
@@ -214,10 +215,11 @@ template<
typename DataType,
typename PolicyType
>
-template
+template
typename std::enable_if::value, void>::type
-RBM::HiddenMean(DataType&& input,
- DataType&& output)
+RBM::HiddenMean(
+ const InputType& input,
+ DataType& output)
{
output = weight.slice(0) * input;
output.each_col() += hiddenBias;
@@ -230,27 +232,27 @@ template<
typename PolicyType
>
void RBM::Gibbs(
- arma::Mat&& input,
- arma::Mat&& output,
+ const arma::Mat& input,
+ arma::Mat& output,
const size_t steps)
{
this->steps = (steps == SIZE_MAX) ? this->numSteps : steps;
if (persistence && !state.is_empty())
{
- SampleHidden(std::move(state), std::move(gibbsTemporary));
- SampleVisible(std::move(gibbsTemporary), std::move(output));
+ SampleHidden(state, gibbsTemporary);
+ SampleVisible(gibbsTemporary, output);
}
else
{
- SampleHidden(std::move(input), std::move(gibbsTemporary));
- SampleVisible(std::move(gibbsTemporary), std::move(output));
+ SampleHidden(input, gibbsTemporary);
+ SampleVisible(gibbsTemporary, output);
}
for (size_t j = 1; j < this->steps; ++j)
{
- SampleHidden(std::move(output), std::move(gibbsTemporary));
- SampleVisible(std::move(gibbsTemporary), std::move(output));
+ SampleHidden(output, gibbsTemporary);
+ SampleVisible(gibbsTemporary, output);
}
if (persistence)
{
@@ -272,14 +274,14 @@ void RBM::Gradient(
positiveGradient.zeros();
negativeGradient.zeros();
- Phase(std::move(predictors.cols(i, i + batchSize - 1)),
- std::move(positiveGradient));
+ Phase(predictors.cols(i, i + batchSize - 1),
+ positiveGradient);
for (size_t i = 0; i < negSteps; ++i)
{
- Gibbs(std::move(predictors.cols(i, i + batchSize - 1)),
- std::move(negativeSamples));
- Phase(std::move(negativeSamples), std::move(tempNegativeGradient));
+ Gibbs(predictors.cols(i, i + batchSize - 1),
+ negativeSamples);
+ Phase(negativeSamples, tempNegativeGradient);
negativeGradient += tempNegativeGradient;
}
diff --git a/src/mlpack/methods/ann/rbm/spike_slab_rbm_impl.hpp b/src/mlpack/methods/ann/rbm/spike_slab_rbm_impl.hpp
index a116e813fc..125c828310 100644
--- a/src/mlpack/methods/ann/rbm/spike_slab_rbm_impl.hpp
+++ b/src/mlpack/methods/ann/rbm/spike_slab_rbm_impl.hpp
@@ -25,7 +25,7 @@ template<
typename DataType,
typename PolicyType
>
-template
+template
typename std::enable_if::value, void>::type
RBM::Reset()
{
@@ -65,10 +65,10 @@ template<
typename DataType,
typename PolicyType
>
-template
+template
typename std::enable_if::value, double>::type
RBM::FreeEnergy(
- arma::Mat&& input)
+ const arma::Mat& input)
{
ElemType freeEnergy = 0.5 * visiblePenalty(0) * arma::dot(input, input);
@@ -90,11 +90,11 @@ template<
typename DataType,
typename PolicyType
>
-template
+template
typename std::enable_if::value, void>::type
RBM::Phase(
- DataType&& input,
- DataType&& gradient)
+ const InputType& input,
+ DataType& gradient)
{
arma::Cube weightGrad = arma::Cube
(gradient.memptr(), visibleSize, poolSize, hiddenSize, false, false);
@@ -102,12 +102,9 @@ RBM::Phase(
DataType spikeBiasGrad = DataType(gradient.memptr() + weightGrad.n_elem,
hiddenSize, 1, false, false);
- DataType visiblePenaltyGrad = DataType(gradient.memptr() +
- weightGrad.n_elem + spikeBiasGrad.n_elem, 1, 1, false, false);
-
- SpikeMean(std::move(input), std::move(spikeMean));
- SampleSpike(std::move(spikeMean), std::move(spikeSamples));
- SlabMean(std::move(input), std::move(spikeSamples), std::move(slabMean));
+ SpikeMean(input, spikeMean);
+ SampleSpike(spikeMean, spikeSamples);
+ SlabMean(input, spikeSamples, slabMean);
for (size_t i = 0 ; i < hiddenSize; ++i)
{
@@ -116,9 +113,9 @@ RBM::Phase(
}
spikeBiasGrad = spikeMean;
-
- visiblePenaltyGrad = -0.5 * arma::dot(input, input)
- / std::pow(input.n_cols, 2);
+ // Setting visiblePenaltyGrad.
+ gradient.row(weightGrad.n_elem + spikeBiasGrad.n_elem) = -0.5 * arma::dot(
+ input, input) / std::pow(input.n_cols, 2);
}
template<
@@ -126,11 +123,11 @@ template<
typename DataType,
typename PolicyType
>
-template
+template
typename std::enable_if::value, void>::type
RBM::SampleHidden(
- arma::Mat&& input,
- arma::Mat&& output)
+ const arma::Mat& input,
+ arma::Mat& output)
{
output.set_size(hiddenSize + poolSize * hiddenSize, 1);
@@ -138,10 +135,10 @@ RBM::SampleHidden(
DataType slab(output.memptr() + hiddenSize, poolSize, hiddenSize, false,
false);
- SpikeMean(std::move(input), std::move(spike));
- SampleSpike(std::move(spike), std::move(spike));
- SlabMean(std::move(input), std::move(spike), std::move(slab));
- SampleSlab(std::move(slab), std::move(slab));
+ SpikeMean(input, spike);
+ SampleSpike(spike, spike);
+ SlabMean(input, spike, slab);
+ SampleSlab(slab, slab);
}
template<
@@ -149,16 +146,16 @@ template<
typename DataType,
typename PolicyType
>
-template
+template
typename std::enable_if::value, void>::type
RBM::SampleVisible(
- arma::Mat&& input,
- arma::Mat&& output)
+ arma::Mat& input,
+ arma::Mat& output)
{
const size_t numMaxTrials = 10;
size_t k = 0;
- VisibleMean(std::move(input), std::move(visibleMean));
+ VisibleMean(input, visibleMean);
output.set_size(visibleSize, 1);
for (k = 0; k < numMaxTrials; ++k)
@@ -187,11 +184,11 @@ template<
typename DataType,
typename PolicyType
>
-template
+template
typename std::enable_if::value, void>::type
RBM::VisibleMean(
- DataType&& input,
- DataType&& output)
+ InputType& input,
+ DataType& output)
{
output.zeros(visibleSize, 1);
@@ -212,11 +209,11 @@ template<
typename DataType,
typename PolicyType
>
-template