diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5641c5b437..ad6bf23d88 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -17,7 +17,6 @@ option(BUILD_TESTS "Build tests." ON)
option(BUILD_CLI_EXECUTABLES "Build command-line executables." ON)
option(DOWNLOAD_DEPENDENCIES "Automatically download dependencies if not available." OFF)
option(BUILD_GO_SHLIB "Build Go shared library." OFF)
-option(BUILD_DOCS "Build doxygen documentation (if doxygen is available)." ON)
# Set minimum library versions required by mlpack.
#
@@ -484,48 +483,6 @@ set(MLPACK_LIBRARIES ${MLPACK_LIBRARIES} ${CROSS_COMPILE_SUPPORT_LIBRARIES})
# Recurse into the rest of the project.
add_subdirectory(src/mlpack)
-# Make a target to generate the documentation. If Doxygen isn't installed, then
-# I guess this option will just be unavailable.
-if (BUILD_DOCS)
- find_package(Doxygen)
- if (DOXYGEN_FOUND)
- if (MATHJAX)
- find_package(MathJax)
- if (NOT MATHJAX_FOUND)
- message(STATUS "Using MathJax at the MathJax Content Delivery Network. "
- "Be careful, formulas will not be shown without the internet.")
- endif ()
- endif ()
- # Preprocess the Doxyfile. This is done before 'make doc'.
- add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/Doxyfile
- PRE_BUILD
- COMMAND ${CMAKE_COMMAND}
- -D DESTDIR=${CMAKE_BINARY_DIR}
- -D MATHJAX="${MATHJAX}"
- -D MATHJAX_FOUND="${MATHJAX_FOUND}"
- -D MATHJAX_PATH="${MATHJAX_PATH}"
- -P "${CMAKE_CURRENT_SOURCE_DIR}/CMake/GenerateDoxyfile.cmake"
- WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
- DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile"
- COMMENT "Creating Doxyfile to generate Doxygen documentation"
- )
-
- # Generate documentation.
- add_custom_target(doc
- COMMAND "${DOXYGEN_EXECUTABLE}" "${CMAKE_BINARY_DIR}/Doxyfile"
- DEPENDS "${CMAKE_BINARY_DIR}/Doxyfile"
- WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
- COMMENT "Generating API documentation with Doxygen"
- )
-
- install(DIRECTORY "${CMAKE_BINARY_DIR}/doc/html"
- DESTINATION "${CMAKE_INSTALL_DOCDIR}"
- COMPONENT doc
- OPTIONAL
- )
- endif ()
-endif()
-
# Create the pkg-config file, if we have pkg-config.
find_package(PkgConfig)
if (PKG_CONFIG_FOUND)
diff --git a/Doxyfile b/Doxyfile
deleted file mode 100644
index b7afc561b9..0000000000
--- a/Doxyfile
+++ /dev/null
@@ -1,262 +0,0 @@
-# Doxyfile 1.4.7
-
-#---------------------------------------------------------------------------
-# Project related configuration options
-#---------------------------------------------------------------------------
-PROJECT_NAME = mlpack
-PROJECT_NUMBER = 3.4.2
-OUTPUT_DIRECTORY = ./doc
-CREATE_SUBDIRS = NO
-OUTPUT_LANGUAGE = English
-USE_WINDOWS_ENCODING = NO
-BRIEF_MEMBER_DESC = YES
-REPEAT_BRIEF = YES
-ABBREVIATE_BRIEF = "The $name class" \
- "The $name widget" \
- "The $name file" \
- is \
- provides \
- specifies \
- contains \
- represents \
- a \
- an \
- the
-ALWAYS_DETAILED_SEC = YES
-INLINE_INHERITED_MEMB = NO
-FULL_PATH_NAMES = YES
-STRIP_FROM_PATH = ./
-STRIP_FROM_INC_PATH =
-SHORT_NAMES = NO
-JAVADOC_AUTOBRIEF = YES
-MULTILINE_CPP_IS_BRIEF = NO
-DETAILS_AT_TOP = YES
-INHERIT_DOCS = YES
-SEPARATE_MEMBER_PAGES = NO
-TAB_SIZE = 2
-ALIASES =
-OPTIMIZE_OUTPUT_FOR_C = NO
-OPTIMIZE_OUTPUT_JAVA = NO
-BUILTIN_STL_SUPPORT = NO
-DISTRIBUTE_GROUP_DOC = NO
-SUBGROUPING = YES
-#---------------------------------------------------------------------------
-# Build related configuration options
-#---------------------------------------------------------------------------
-EXTRACT_ALL = YES
-EXTRACT_PRIVATE = NO
-EXTRACT_STATIC = YES
-EXTRACT_LOCAL_CLASSES = NO
-EXTRACT_LOCAL_METHODS = NO
-HIDE_UNDOC_MEMBERS = NO
-HIDE_UNDOC_CLASSES = NO
-HIDE_FRIEND_COMPOUNDS = YES
-HIDE_IN_BODY_DOCS = NO
-INTERNAL_DOCS = YES
-CASE_SENSE_NAMES = YES
-HIDE_SCOPE_NAMES = YES
-SHOW_INCLUDE_FILES = NO
-INLINE_INFO = YES
-SORT_MEMBER_DOCS = YES
-SORT_BRIEF_DOCS = YES
-SORT_BY_SCOPE_NAME = YES
-SORT_MEMBERS_CTORS_1ST = YES
-GENERATE_TODOLIST = NO
-GENERATE_TESTLIST = NO
-GENERATE_BUGLIST = YES
-GENERATE_DEPRECATEDLIST= NO
-ENABLED_SECTIONS =
-MAX_INITIALIZER_LINES = 30
-SHOW_USED_FILES = YES
-SHOW_DIRECTORIES = YES
-FILE_VERSION_FILTER =
-#---------------------------------------------------------------------------
-# configuration options related to warning and progress messages
-#---------------------------------------------------------------------------
-QUIET = NO
-WARNINGS = YES
-# This will be set to YES for the Jenkins doxygen check build.
-WARN_AS_ERROR = NO
-WARN_IF_UNDOCUMENTED = YES
-WARN_IF_DOC_ERROR = YES
-WARN_NO_PARAMDOC = YES
-WARN_FORMAT = "$file:$line: $text"
-WARN_LOGFILE =
-#---------------------------------------------------------------------------
-# configuration options related to the input files
-#---------------------------------------------------------------------------
-INPUT = ./src/mlpack \
- ./doc/guide \
- ./doc/tutorials \
- ./doc/policies
-FILE_PATTERNS = *.hpp \
- *.cpp \
- *.txt
-RECURSIVE = YES
-EXCLUDE =
-EXCLUDE_SYMLINKS = YES
-EXCLUDE_PATTERNS = */build/* \
- */test/* \
- */arma_extend/* \
- */boost_backport/* \
- */.svn/* \
- *_impl.cc \
- *_impl.h \
- *_impl.hpp \
- *.cpp \
- *.cc \
- *_test.cpp \
- *CLI11.hpp \
- */tests/catch.hpp \
- */boost/serialization/*
-EXAMPLE_PATH =
-EXAMPLE_PATTERNS = *
-EXAMPLE_RECURSIVE = NO
-IMAGE_PATH =
-INPUT_FILTER =
-FILTER_PATTERNS =
-FILTER_SOURCE_FILES = NO
-#---------------------------------------------------------------------------
-# configuration options related to source browsing
-#---------------------------------------------------------------------------
-SOURCE_BROWSER = YES
-INLINE_SOURCES = NO
-STRIP_CODE_COMMENTS = YES
-REFERENCED_BY_RELATION = YES
-REFERENCES_RELATION = YES
-REFERENCES_LINK_SOURCE = YES
-USE_HTAGS = NO
-VERBATIM_HEADERS = YES
-#---------------------------------------------------------------------------
-# configuration options related to the alphabetical class index
-#---------------------------------------------------------------------------
-ALPHABETICAL_INDEX = YES
-COLS_IN_ALPHA_INDEX = 1
-IGNORE_PREFIX =
-#---------------------------------------------------------------------------
-# configuration options related to the HTML output
-#---------------------------------------------------------------------------
-GENERATE_HTML = YES
-HTML_OUTPUT = html
-HTML_FILE_EXTENSION = .html
-HTML_HEADER =
-HTML_FOOTER = ./doc/doxygen/footer.html
-HTML_STYLESHEET =
-HTML_EXTRA_STYLESHEET = ./doc/doxygen/extra-stylesheet.css
-HTML_ALIGN_MEMBERS = YES
-GENERATE_HTMLHELP = NO
-CHM_FILE =
-HHC_LOCATION =
-GENERATE_CHI = NO
-BINARY_TOC = NO
-TOC_EXPAND = NO
-DISABLE_INDEX = NO
-ENUM_VALUES_PER_LINE = 1
-GENERATE_TREEVIEW = NO
-TREEVIEW_WIDTH = 250
-USE_MATHJAX = NO
-MATHJAX_FORMAT = SVG
-MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
-#---------------------------------------------------------------------------
-# configuration options related to the LaTeX output
-#---------------------------------------------------------------------------
-GENERATE_LATEX = YES
-LATEX_OUTPUT = latex
-LATEX_CMD_NAME = latex
-MAKEINDEX_CMD_NAME = makeindex
-COMPACT_LATEX = NO
-PAPER_TYPE = letter
-EXTRA_PACKAGES = amsmath amssymb mathrsfs
-LATEX_HEADER =
-PDF_HYPERLINKS = NO
-USE_PDFLATEX = NO
-LATEX_BATCHMODE = NO
-LATEX_HIDE_INDICES = NO
-FORMULA_FONTSIZE = 50
-#---------------------------------------------------------------------------
-# configuration options related to the RTF output
-#---------------------------------------------------------------------------
-GENERATE_RTF = NO
-RTF_OUTPUT = rtf
-COMPACT_RTF = NO
-RTF_HYPERLINKS = NO
-RTF_STYLESHEET_FILE =
-RTF_EXTENSIONS_FILE =
-#---------------------------------------------------------------------------
-# configuration options related to the man page output
-#---------------------------------------------------------------------------
-GENERATE_MAN = YES
-MAN_OUTPUT = man
-MAN_EXTENSION = .3
-MAN_LINKS = NO
-#---------------------------------------------------------------------------
-# configuration options related to the XML output
-#---------------------------------------------------------------------------
-GENERATE_XML = NO
-XML_OUTPUT = xml
-XML_SCHEMA =
-XML_DTD =
-XML_PROGRAMLISTING = YES
-#---------------------------------------------------------------------------
-# configuration options for the AutoGen Definitions output
-#---------------------------------------------------------------------------
-GENERATE_AUTOGEN_DEF = NO
-#---------------------------------------------------------------------------
-# configuration options related to the Perl module output
-#---------------------------------------------------------------------------
-GENERATE_PERLMOD = NO
-PERLMOD_LATEX = NO
-PERLMOD_PRETTY = YES
-PERLMOD_MAKEVAR_PREFIX =
-#---------------------------------------------------------------------------
-# Configuration options related to the preprocessor
-#---------------------------------------------------------------------------
-ENABLE_PREPROCESSING = YES
-MACRO_EXPANSION = YES
-EXPAND_ONLY_PREDEF = NO
-SEARCH_INCLUDES = YES
-INCLUDE_PATH =
-INCLUDE_FILE_PATTERNS =
-PREDEFINED =
-EXPAND_AS_DEFINED =
-SKIP_FUNCTION_MACROS = YES
-#---------------------------------------------------------------------------
-# Configuration::additions related to external references
-#---------------------------------------------------------------------------
-TAGFILES =
-GENERATE_TAGFILE =
-ALLEXTERNALS = NO
-EXTERNAL_GROUPS = YES
-PERL_PATH = /usr/bin/perl
-#---------------------------------------------------------------------------
-# Configuration options related to the dot tool
-#---------------------------------------------------------------------------
-CLASS_DIAGRAMS = YES
-HIDE_UNDOC_RELATIONS = YES
-HAVE_DOT = YES
-CLASS_GRAPH = YES
-COLLABORATION_GRAPH = NO
-GROUP_GRAPHS = YES
-UML_LOOK = NO
-TEMPLATE_RELATIONS = YES
-INCLUDE_GRAPH = YES
-INCLUDED_BY_GRAPH = YES
-CALL_GRAPH = NO
-CALLER_GRAPH = NO
-GRAPHICAL_HIERARCHY = YES
-DIRECTORY_GRAPH = YES
-DOT_IMAGE_FORMAT = png
-# Hack dark color support in through the dot path. Kind of cheating...
-DOT_PATH = dot -Gbgcolor=black
-DOTFILE_DIRS =
-MAX_DOT_GRAPH_WIDTH = 800
-MAX_DOT_GRAPH_HEIGHT = 600
-MAX_DOT_GRAPH_DEPTH = 1000
-DOT_TRANSPARENT = NO
-DOT_MULTI_TARGETS = NO
-GENERATE_LEGEND = YES
-DOT_CLEANUP = YES
-#---------------------------------------------------------------------------
-# Configuration::additions related to the search engine
-#---------------------------------------------------------------------------
-SEARCHENGINE = YES
diff --git a/README.md b/README.md
index f3472f52b3..2b21ee2c7d 100644
--- a/README.md
+++ b/README.md
@@ -29,10 +29,27 @@ src="https://cdn.rawgit.com/mlpack/mlpack.org/e7d36ed8/mlpack-black.svg" style="
**mlpack** is an intuitive, fast, and flexible header-only C++ machine learning
library with bindings to other languages. It is meant to be a machine learning
analog to LAPACK, and aims to implement a wide array of machine learning methods
-and functions as a "swiss army knife" for machine learning researchers. In
-addition to its powerful C++ interface, mlpack also provides command-line
+and functions as a "swiss army knife" for machine learning researchers.
+
+mlpack's lightweight C++ implementation makes it ideal for deployment, and it
+can also be used for interactive prototyping via C++ notebooks (these can be
+seen in action on mlpack's [homepage](https://www.mlpack.org/)).
+
+In addition to its powerful C++ interface, mlpack also provides command-line
programs, Python bindings, Julia bindings, Go bindings and R bindings.
+***Quick links:***
+
+ - Quickstart guides: [C++](doc/quickstart/cpp.md),
+ [CLI](doc/quickstart/cli.md), [Python](doc/quickstart/python.md),
+ [R](doc/quickstart/R.md), [Julia](doc/quickstart/julia.md),
+ [Go](doc/quickstart/go.md)
+ - [mlpack homepage](https://www.mlpack.org/)
+ - [mlpack documentation](https://www.mlpack.org/docs.html)
+ - [Examples repository](https://github.com/mlpack/examples/)
+ - [Tutorials](https://www.mlpack.org/doc/mlpack-git/doxygen/tutorials.html)
+ - [Development Site (Github)](https://www.github.com/mlpack/mlpack/)
+
[//]: # (numfocus-fiscal-sponsor-attribution)
mlpack uses an [open governance model](./GOVERNANCE.md) and is fiscally
@@ -50,32 +67,21 @@ variety of other needs.
-### 0. Contents
+## 0. Contents and Quick Links
- 1. [Introduction](#1-introduction)
- 2. [Citation details](#2-citation-details)
- 3. [Dependencies](#3-dependencies)
- 4. [Building mlpack from source](#4-building-mlpack-from-source)
- 5. [Running mlpack programs](#5-running-mlpack-programs)
- 6. [Using mlpack from Python](#6-using-mlpack-from-python)
- 7. [Further documentation](#7-further-documentation)
- 8. [Bug reporting](#8-bug-reporting)
- 9. [Building mlpack from vcpkg](#9-building-mlpack-from-vcpkg)
+ 1. [Citation details](#1-citation-details)
+ 2. [Dependencies](#2-dependencies)
+ 3. [Installing and using mlpack in C++](#4-installing-and-using-mlpack-in-c++)
+ 4. [Building mlpack bindings to other languages](#5-building-mlpack-bindings-to-other-languages)
+ 1. [Command-line programs](#4i-command-line-programs)
+ 2. [Python bindings](#4ii-python-bindings)
+ 3. [R bindings](#4iii-r-bindings)
+ 4. [Julia bindings](#4iv-julia-bindings)
+ 5. [Go bindings](#4v-go-bindings)
+ 5. [Building mlpack's test suite](#5-building-mlpacks-test-suite)
+ 6. [Further resources](#6-further-resources)
-### 1. Introduction
-
-The mlpack website can be found at https://www.mlpack.org and it contains
-numerous tutorials and extensive documentation. This README serves as a guide
-for what mlpack is, how to install it, how to run it, and where to find more
-documentation. The website should be consulted for further information:
-
- - [mlpack homepage](https://www.mlpack.org/)
- - [mlpack documentation](https://www.mlpack.org/docs.html)
- - [Tutorials](https://www.mlpack.org/doc/mlpack-git/doxygen/tutorials.html)
- - [Development Site (Github)](https://www.github.com/mlpack/mlpack/)
- - [API documentation (Doxygen)](https://www.mlpack.org/doc/mlpack-git/doxygen/index.html)
-
-### 2. Citation details
+## 1. Citation details
If you use mlpack in your research or software, please cite mlpack using the
citation below (given in BibTeX format):
@@ -96,266 +102,322 @@ citation below (given in BibTeX format):
Citations are beneficial for the growth and improvement of mlpack.
-### 3. Dependencies
+## 2. Dependencies
-mlpack has the following dependencies:
+mlpack requires a C++14 compiler and has the following additional dependencies:
- Armadillo >= 9.800
- CMake >= 3.6
- ensmallen >= 2.10.0
- cereal >= 1.1.2
-
-All of those should be available in your distribution's package manager. If
-not, you will have to compile each of them by hand. See the documentation for
-each of those packages for more information.
-
-If you would like to use or build the mlpack Python bindings, make sure that the
-following Python packages are installed:
-
- setuptools
- cython >= 0.24
- numpy
- pandas >= 0.15.0
-
-If you would like to build the Julia bindings, make sure that Julia >= 1.3.0 is
-installed.
-
-If you would like to build the Go bindings, make sure that Go >= 1.11.0 is
-installed with this package:
-
- Gonum
-
-If you would like to build the R bindings, make sure that R >= 4.0 is
-installed with these R packages.
-
- Rcpp >= 0.12.12
- RcppArmadillo >= 0.8.400.0
- RcppEnsmallen >= 0.2.10.0
- BH >= 1.58
- roxygen2
+ - Armadillo >= 9.800
+ - ensmallen >= 2.10.0
+ - cereal >= 1.1.2
If the STB library headers are available, image loading support will be
-compiled.
+available.
If you are compiling Armadillo by hand, ensure that LAPACK and BLAS are enabled.
-### 4. Building mlpack from source
+## 3. Installing and using mlpack in C++
-This document discusses how to build mlpack from source. These build directions
-will work for any Linux-like shell environment (for example Ubuntu, macOS,
-FreeBSD etc). However, mlpack is in the repositories of many Linux distributions
-and so it may be easier to use the package manager for your system. For example,
-on Ubuntu, you can install the mlpack library and command-line executables (e.g.
-mlpack_pca, mlpack_kmeans etc.) with the following command:
+*See also the [C++ quickstart](doc/quickstart/cpp.md).*
- $ sudo apt-get install libmlpack-dev mlpack-bin
+Since mlpack is a header-only library, installing just the headers for use in a
+C++ application is trivial. From the root of the sources, configure and install
+in the standard CMake way:
-On Fedora or Red Hat (EPEL):
-
- $ sudo dnf install mlpack-devel mlpack-bin
-
-*Note*: Older Ubuntu versions may not have the most recent version of mlpack
-available---for instance, at the time of this writing, Ubuntu 16.04 only has
-mlpack 3.4.2 available. Options include upgrading your Ubuntu version, finding
-a PPA or other non-official sources, or installing with a manual build.
-
-*Note*: If you are using RHEL7/CentOS 7, gcc 4.8 is too old to compile mlpack.
-One option is to use `devtoolset-8`; see
-[here](https://www.softwarecollections.org/en/scls/rhscl/devtoolset-8/) for more
-information.
-
-There are some useful pages to consult in addition to this section:
-
- - [Building mlpack From Source](https://www.mlpack.org/doc/mlpack-git/doxygen/build.html)
- - [Building mlpack From Source on Windows](https://www.mlpack.org/doc/mlpack-git/doxygen/build_windows.html)
-
-mlpack uses CMake as a build system and allows several flexible build
-configuration options. You can consult any of the CMake tutorials for
-further documentation, but this tutorial should be enough to get mlpack built
-and installed.
-
-First, unpack the mlpack source and change into the unpacked directory. Here we
-use mlpack-x.y.z where x.y.z is the version.
-
- $ tar -xzf mlpack-x.y.z.tar.gz
- $ cd mlpack-x.y.z
-
-Then, make a build directory. The directory can have any name, but 'build' is
-sufficient.
-
- $ mkdir build
- $ cd build
-
-The next step is to run CMake to configure the project. Running CMake is the
-equivalent to running `./configure` with autotools. If you run CMake with no
-options, it will configure the project to build with no debugging symbols and
-no profiling information:
-
- $ cmake ../
-
-Options can be specified to compile with debugging information and profiling information:
-
- $ cmake -D DEBUG=ON -D PROFILE=ON ../
-
-Options are specified with the -D flag. The allowed options include:
-
- DEBUG=(ON/OFF): compile with debugging symbols
- PROFILE=(ON/OFF): compile with profiling symbols
- ARMA_EXTRA_DEBUG=(ON/OFF): compile with extra Armadillo debugging symbols
- ARMADILLO_INCLUDE_DIR=(/path/to/armadillo/include/): path to Armadillo headers
- ARMADILLO_LIBRARY=(/path/to/armadillo/libarmadillo.so): Armadillo library
- BUILD_CLI_EXECUTABLES=(ON/OFF): whether or not to build command-line programs
- BUILD_PYTHON_BINDINGS=(ON/OFF): whether or not to build Python bindings
- PYTHON_EXECUTABLE=(/path/to/python_version): Path to specific Python executable
- PYTHON_INSTALL_PREFIX=(/path/to/python/): Path to root of Python installation
- BUILD_JULIA_BINDINGS=(ON/OFF): whether or not to build Julia bindings
- JULIA_EXECUTABLE=(/path/to/julia): Path to specific Julia executable
- BUILD_GO_BINDINGS=(ON/OFF): whether or not to build Go bindings
- GO_EXECUTABLE=(/path/to/go): Path to specific Go executable
- BUILD_GO_SHLIB=(ON/OFF): whether or not to build shared libraries required by Go bindings
- BUILD_R_BINDINGS=(ON/OFF): whether or not to build R bindings
- R_EXECUTABLE=(/path/to/R): Path to specific R executable
- BUILD_TESTS=(ON/OFF): whether or not to build tests
- BUILD_SHARED_LIBS=(ON/OFF): compile shared libraries and executables as
- opposed to static libraries
- DISABLE_DOWNLOADS=(ON/OFF): whether to disable all downloads during build
- ENSMALLEN_INCLUDE_DIR=(/path/to/ensmallen/include): path to include directory
- for ensmallen
- STB_IMAGE_INCLUDE_DIR=(/path/to/stb/include): path to include directory for
- STB image library
- USE_OPENMP=(ON/OFF): whether or not to use OpenMP if available
- BUILD_DOCS=(ON/OFF): build Doxygen documentation, if Doxygen is available
- (default ON)
-
-For example, to build mlpack's CLI bindings statically the following command can
-be used:
-
- $ cmake -D BUILD_SHARED_LIBS=OFF ../
-
-Other tools can also be used to configure CMake, but those are not documented
-here. See [this section of the build guide](https://www.mlpack.org/doc/mlpack-git/doxygen/build.html#build_config)
-for more details, including a full list of options, and their default values.
-
-By default, command-line programs will be built, and if the Python dependencies
-(Cython, setuptools, numpy, pandas) are available, then Python bindings will
-also be built. OpenMP will be used for parallelization when possible by
-default.
-
-Once CMake is configured, building the library is as simple as typing 'make'.
-This will build all library components and bindings.
-
- $ make
-
-If you do not want to build everything in the library, individual components
-of the build can be specified:
-
- $ make mlpack_pca mlpack_knn mlpack_kfn
-
-If you want to build the tests, just make the `mlpack_test` target, and use
-`ctest` to run the tests:
-
- $ make mlpack_test
- $ ctest .
-
-If the build fails and you cannot figure out why, register an account on Github
-and submit an issue. The mlpack developers will quickly help you figure it out:
-
-[mlpack on Github](https://www.github.com/mlpack/mlpack/)
-
-Alternately, mlpack help can be found in IRC at `#mlpack` on chat.freenode.net.
-
-If you wish to install mlpack to `/usr/local/include/mlpack/`, `/usr/local/lib/`,
-and `/usr/local/bin/`, make sure you have root privileges (or write permissions
-to those three directories), and simply type
-
- $ make install
-
-You can now run the executables by name; the mlpack headers are found in
- `/usr/local/include/mlpack/`
-and if Python bindings were built, you can access them with the `mlpack`
-package in Python.
-
-### 5. Running mlpack programs
-
-After building mlpack, the executables will reside in `build/bin/`. You can
-call them from there, or you can install the library and (depending on system
-settings) they should be added to your PATH and you can call them directly. The
-documentation below assumes the executables are in your PATH.
-
-Consider the 'mlpack_knn' program, which finds the k nearest neighbors in a
-reference dataset of all the points in a query set. That is, we have a query
-and a reference dataset. For each point in the query dataset, we wish to know
-the k points in the reference dataset which are closest to the given query
-point.
-
-Alternately, if the query and reference datasets are the same, the problem can
-be stated more simply: for each point in the dataset, we wish to know the k
-nearest points to that point.
-
-Each mlpack program has extensive help documentation which details what the
-method does, what each of the parameters is, and how to use them:
-
-```shell
-$ mlpack_knn --help
+```sh
+mkdir build && cd build/
+cmake ../
+sudo make install
```
-Running `mlpack_knn` on one dataset (that is, the query and reference
-datasets are the same) and finding the 5 nearest neighbors is very simple:
+You can add a few arguments to the `cmake` command to control the behavior of
+the configuration and build process. Simply add these to the `cmake` command.
+Some options are given below:
-```shell
-$ mlpack_knn -r dataset.csv -n neighbors_out.csv -d distances_out.csv -k 5 -v
+ - `-DCMAKE_INSTALL_PREFIX=/install/root/` will set the root of the install
+ directory to `/install/root` when `make install` is run.
+ - `-DDOWNLOAD_DEPENDENCIES=ON` will automatically download mlpack's
+ dependencies (ensmallen, Armadillo, and cereal).
+ - `-DDEBUG=ON` will enable debugging symbols in any compiled bindings or tests.
+
+There are also options to enable building bindings to each language that mlpack
+supports; those are detailed in the following sections.
+
+Once headers are installed with `make install`, using mlpack in an application
+consists only of including it. So, your program should include mlpack:
+
+```c++
+#include
```
-The `-v (--verbose)` flag is optional; it gives informational output. It is not
-unique to `mlpack_knn` but is available in all mlpack programs. Verbose
-output also gives timing output at the end of the program, which can be very
-useful.
+and when you link, be sure to link against Armadillo. If your example program
+is `my_program.cpp`, your compiler is GCC, and you would like to compile with
+OpenMP support (recommended) and optimizations, compile like this:
-### 6. Using mlpack from Python
-
-If mlpack is installed to the system, then the mlpack Python bindings should be
-automatically in your PYTHONPATH, and importing mlpack functionality into Python
-should be very simple:
-
-```python
->>> from mlpack import knn
+```sh
+g++ -O3 -std=c++14 -o my_program my_program.cpp -larmadillo -fopenmp
```
-Accessing help is easy:
+Note that if you want to serialize (save or load) neural networks, you should
+add `#define MLPACK_ENABLE_ANN_SERIALIZATION` before including ``.
-```python
->>> help(knn)
+See the [C++ quickstart](doc/quickstart/cpp.md) and the
+[examples](https://github.com/mlpack/examples) repository for some examples of
+mlpack applications in C++, with corresponding `Makefile`s.
+
+### 3.1. Including mlpack and improving compile time
+
+mlpack is a template-heavy library, and if care is not used, compilation time of
+a project can be increased greatly. Fortunately, there are a number of ways to
+reduce compilation time:
+
+ * Include individual headers, like ``, if you
+ are only using one component, instead of ``. This reduces the
+ amount of work the compiler has to do.
+
+ * Only use the `MLPACK_ENABLE_ANN_SERIALIZATION` definition if you are
+ serializing neural networks in your code. When this define is enabled,
+ compilation time will increase significantly, as the compiler must generate
+ code for every possible type of layer.
+
+ * If you are using mlpack in multiple .cpp files, consider using [`extern
+ templates`](https://isocpp.org/wiki/faq/cpp11-language-templates) so that the
+ compiler only instantiates each template once; add an explicit template
+ instantiation for each mlpack template type you want to use in a .cpp file,
+ and then use `extern` definitions elsewhere to let the compiler know it
+ exists in a different file.
+
+Other strategies exist too, such as precompiled headers, compiler options,
+[`ccache`](https://ccache.dev), and others.
+
+## 4. Building mlpack bindings to other languages
+
+mlpack is not just a header-only library: it also comes with bindings to a
+number of other languages, this allows flexible use of mlpack's efficient
+implementations from languages that aren't C++.
+
+In general, you should *not* need to build these by hand---they should be
+provided by either your system package manager or your language's package
+manager.
+
+Building the bindings for a particular language is done by calling `cmake` with
+different options; each example below shows how to configure an individual set
+of bindings, but it is of course possible to combine the options and build
+bindings for many languages at once.
+
+### 4.i. Command-line programs
+
+*See also the [command-line quickstart](doc/quickstart/cli.md).*
+
+The command-line programs have no extra dependencies. The set of programs that
+will be compiled is detailed and documented on the [command-line program
+documentation page](https://www.mlpack.org/doc/stable/cli_documentation.html).
+
+From the root of the mlpack sources, run the following commands to build and
+install the command-line bindings:
+
+```sh
+mkdir build && cd build/
+cmake -DBUILD_CLI_PROGRAMS=ON ../
+make
+sudo make install
```
-The API is similar to the command-line programs. So, running `knn()`
-(k-nearest-neighbor search) on the numpy matrix `dataset` and finding the 5
-nearest neighbors is very simple:
+You can use `make -j`, where `N` is the number of cores on your machine, to
+build in parallel; e.g., `make -j4` will use 4 cores to build.
-```python
->>> output = knn(reference=dataset, k=5, verbose=True)
+### 4.ii. Python bindings
+
+*See also the [Python quickstart](doc/quickstart/python.md).*
+
+mlpack's Python bindings are available on
+[PyPI](https://pypi.org/project/mlpack) and
+[conda-forge](https://conda-forge.org/packages/mlpack), and can be installed
+with either `pip install mlpack` or `conda install -c conda-forge mlpack`.
+These sources are recommended, as building the Python bindings by hand can be
+complex.
+
+With that in mind, if you would still like to manually build the mlpack Python
+bindings, first make sure that the following Python packages are installed:
+
+ - setuptools
+ - cython >= 0.24
+ - numpy
+ - pandas >= 0.15.0
+
+Now, from the root of the mlpack sources, run the following commands to build
+and install the Python bindings:
+
+```sh
+mkdir build && cd build/
+cmake -DBUILD_PYTHON_BINDINGS=ON ../
+make
+sudo make install
```
-This will store the output neighbors in `output['neighbors']` and the output
-distances in `output['distances']`. Other mlpack bindings function similarly,
-and the input/output parameters exactly match those of the command-line
-programs.
+You can use `make -j`, where `N` is the number of cores on your machine, to
+build in parallel; e.g., `make -j4` will use 4 cores to build. You can also
+specify a custom Python interpreter with the CMake option
+`-DPYTHON_EXECUTABLE=/path/to/python`.
-### 7. Further documentation
+### 4.iii. R bindings
-The documentation given here is only a fraction of the available documentation
-for mlpack. If doxygen is installed, you can type `make doc` to build the
-documentation locally. Alternately, up-to-date documentation is available for
-older versions of mlpack:
+*See also the [R quickstart](doc/quickstart/R.md).*
- - [mlpack homepage](https://www.mlpack.org/)
- - [mlpack documentation](https://www.mlpack.org/docs.html)
- - [Tutorials](https://www.mlpack.org/doc/mlpack-git/doxygen/tutorials.html)
- - [Development Site (Github)](https://www.github.com/mlpack/mlpack/)
- - [API documentation (Doxygen)](https://www.mlpack.org/doc/mlpack-git/doxygen/index.html)
+mlpack's R bindings are available as the R package
+[mlpack](https://cran.r-project.org/web/packages/mlpack/index.html) on CRAN.
+You can install the package by running `install.packages('mlpack')`, and this is
+the recommended way of getting mlpack in R.
+
+If you still wish to build the R bindings by hand, first make sure the following
+dependencies are installed:
+
+ - R >= 4.0
+ - Rcpp >= 0.12.12
+ - RcppArmadillo >= 0.9.800.0
+ - RcppEnsmallen >= 0.2.10.0
+ - roxygen2
+ - testthat
+ - pkgbuild
+
+These can be installed with `install.packages()` inside of your R environment.
+Once the dependencies are available, you can configure mlpack and build the R
+bindings by running the following commands from the root of the mlpack sources:
+
+```sh
+mkdir build && cd build/
+cmake -DBUILD_R_BINDINGS=ON ../
+make
+sudo make install
+```
+
+You may need to specify the location of the R program in the `cmake` command
+with the option `-DR_EXECUTABLE=/path/to/R`.
+
+Once the build is complete, a tarball can be found under the build directory in
+`src/mlpack/bindings/R/`, and then that can be installed into your R environment
+with a command like `install.packages(mlpack_3.4.3.tar.gz, repos=NULL,
+type='source')`.
+
+### 4.iv. Julia bindings
+
+*See also the [Julia quickstart](doc/quickstart/julia.md).*
+
+mlpack's Julia bindings are available by installing the
+[mlpack.jl](https://github.com/mlpack/mlpack.jl) package using
+`Pkg.add("mlpack.jl")`. The process of building, packaging, and distributing
+mlpack's Julia bindings is very nontrivial, so it is recommended to simply use
+the version available in `Pkg`, but if you want to build the bindings by hand
+anyway, you can configure and build them by running the following commands from
+the root of the mlpack sources:
+
+```sh
+mkdir build && cd build/
+cmake -DBUILD_JULIA_BINDINGS=ON ../
+make
+```
+
+If CMake cannot find your Julia installation, you can add
+`-DJULIA_EXECUTABLE=/path/to/julia` to the CMake configuration step.
+
+Note that the `make install` step is not done above, since the Julia binding
+build system was not meant to be installed directly. Instead, to use handbuilt
+bindings (for instance, to test them), one option is to start Julia with
+`JULIA_PROJECT` set as an environment variable:
+
+```sh
+cd build/src/mlpack/bindings/julia/mlpack/
+JULIA_PROJECT=$PWD julia
+```
+
+and then `using mlpack` should work.
+
+### 4.v. Go bindings
+
+*See also the [Go quickstart](doc/quickstart/go.md).*
+
+To build mlpack's Go bindings, ensure that Go >= 1.11.0 is installed, and that
+the Gonum package is available. You can use `go get` to install mlpack for Go:
+
+```sh
+go get -u -d mlpack.org/v1/mlpack
+cd ${GOPATH}/src/mlpack.org/v1/mlpack
+make install
+```
+
+The process of building the Go bindings by hand is a little tedious, so
+following the steps above is recommended. However, if you wish to build the Go
+bindings by hand anyway, you can do this by running the following commands from
+the root of the mlpack sources:
+
+```sh
+mkdir build && cd build/
+cmake -DBUILD_GO_BINDINGS=ON ../
+make
+sudo make install
+```
+
+## 5. Building mlpack's test suite
+
+mlpack contains an extensive test suite that exercises every part of the
+codebase. It is easy to build and run the tests with CMake and CTest, as below:
+
+```sh
+mkdir build && cd build/
+cmake -DBUILD_TESTS=ON ../
+make
+ctest .
+```
+
+If you want to test the bindings, too, you will have to adapt the CMake
+configuration command to turn on the language bindings that you want to
+test---see the previous sections for details.
+
+## 6. Further Resources
+
+More documentation is available for both users and developers.
+
+***User documentation***:
+
+ - [File formats and loading data in mlpack](doc/user/formats.md)
+ - [Matrices in mlpack](doc/user/matrices.md)
+ - [Cross-Validation](doc/user/cv.md)
+ - [Hyper-parameter Tuning](doc/user/hpt.md)
+ - [Building mlpack from source on Windows](doc/user/build_windows.md)
+ - [Sample C++ ML App for Windows](doc/user/sample_ml_app.md)
+ - [Examples repository](https://github.com/mlpack/examples/)
+
+***Tutorials:***
+
+ - [Alternating Matrix Factorization (AMF)](doc/tutorials/amf.md)
+ - [Artificial Neural Networks (ANN)](doc/tutorials/ann.md)
+ - [Approximate k-Furthest Neighbor Search (`approx_kfn`)](doc/tutorials/approx_kfn.md)
+ - [Collaborative Filtering (CF)](doc/tutorials/cf.md)
+ - [DatasetMapper](doc/tutorials/datasetmapper.md)
+ - [Density Estimation Trees (DET)](doc/tutorials/det.md)
+ - [Euclidean Minimum Spanning Trees (EMST)](doc/tutorials/emst.md)
+ - [Fast Max-Kernel Search (FastMKS)](doc/tutorials/fastmks.md)
+ - [Image Utilities](doc/tutorials/image.md)
+ - [k-Means Clustering](doc/tutorials/kmeans.md)
+ - [Linear Regression](doc/tutorials/linear_regression.md)
+ - [Neighbor Search (k-Nearest-Neighbors)](doc/tutorials/neighbor_search.md)
+ - [Range Search](doc/tutorials/range_search.md)
+ - [Reinforcement Learning](doc/tutorials/reinforcement_learning.md)
+
+***Developer documentation***:
+
+ - [mlpack versions in code](doc/developer/version.md)
+ - [Writing an mlpack binding](doc/developer/iodoc.md)
+ - [mlpack Timers](doc/developer/timer.md)
+ - [mlpack automatic bindings to other languages](doc/developer/bindings.md)
+ - [The ElemType policy in mlpack](doc/developer/elemtype.md)
+ - [The KernelType policy in mlpack](doc/developer/kernels.md)
+ - [The MetricType policy in mlpack](doc/developer/metrics.md)
+ - [The TreeType policy in mlpack](doc/developer/trees.md)
To learn about the development goals of mlpack in the short- and medium-term
future, see the [vision document](https://www.mlpack.org/papers/vision.pdf).
+<<<<<<< HEAD
### 8. Bug reporting
(see also [mlpack help](https://www.mlpack.org/questions.html))
@@ -379,16 +441,8 @@ and the git commit list is available at
Lastly, the IRC channel `#mlpack` on Freenode can be used to get help.
-### 9. Building mlpack from vcpkg
-
-The mlpack port in vcpkg is kept up to date by Microsoft team members and community contributors. The url of vcpkg is: https://github.com/Microsoft/vcpkg . You can download and install mlpack using the vcpkg dependency manager:
-
-```shell
-git clone https://github.com/Microsoft/vcpkg.git
-cd vcpkg
-./bootstrap-vcpkg.sh # ./bootstrap-vcpkg.bat for Windows
-./vcpkg integrate install
-./vcpkg install mlpack
-```
-
-If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
+If you have problems, find a bug, or need help, you can try visiting
+the [mlpack help](https://www.mlpack.org/questions.html) page, or [mlpack on
+Github](https://www.github.com/mlpack/mlpack/). Alternately, mlpack help can be
+found on Matrix at `#mlpack`; see also the
+[community](https://www.mlpack.org/community.html) page.
diff --git a/doc/guide/bindings.hpp b/doc/developer/bindings.md
similarity index 56%
rename from doc/guide/bindings.hpp
rename to doc/developer/bindings.md
index b6b93e67c7..9b3d2e92b2 100644
--- a/doc/guide/bindings.hpp
+++ b/doc/developer/bindings.md
@@ -1,6 +1,4 @@
-/*! @page bindings mlpack automatic bindings to other languages
-
-@section bindings_overview Overview
+# mlpack automatic bindings to other languages
mlpack has a system to automatically generate bindings to other languages, such
as Python and command-line programs, and it is extensible to other languages
@@ -16,27 +14,15 @@ curious enough to see how the sausage is made.
The document is split into several sections:
- - @ref bindings_intro
- - @ref bindings_code
- - @ref bindings_general
- - @ref bindings_general_program_doc
- - @ref bindings_general_define_params
- - @ref bindings_general_functions
- - @ref bindings_general_more
- - @ref bindings_structure
- - @ref bindings_cli
- - @ref bindings_cli_mlpack_main
- - @ref bindings_cli_matrix
- - @ref bindings_cli_parsing
- - @ref bindings_python
- - @ref bindings_python_matrix
- - @ref bindings_python_model
- - @ref bindings_python_setup_py
- - @ref bindings_python_build_pyx
- - @ref bindings_python_testing
- - @ref bindings_new
+ - [Introduction](#introduction)
+ - [Writing code that can be turned into a binding](#writing-code-that-can-be-turned-into-a-binding)
+ - [How to write mlpack bindings](#how-to-write-mlpack-bindings)
+ - [Structure of IO module and associated macros](#structure-of-io-module-and-associated-macros)
+ - [Command-line program bindings](#command-line-program-bindings)
+ - [Python bindings](#python-bindings)
+ - [Adding new binding types](#adding-new-binding-types)
-@section bindings_intro Introduction
+## Introduction
C++ is not the most popular language on the planet, and it (unfortunately) can
scare many away with its ultra-verbose error messages, confusing template rules,
@@ -44,10 +30,10 @@ and complex metaprogramming techniques. Most practitioners of machine learning
tend to avoid writing native C++ and instead prefer other languages---probably
most notably Python.
-In the case of Python, many projects will use tools like SWIG
-(http://www.swig.org/) to automatically generate bindings, or they might
+In the case of Python, many projects will use tools like
+[SWIG](http://www.swig.org) to automatically generate bindings, or they might
hand-write Cython. The same types of strategies may be used for other
-languages; hand-written MEX files may be used for MATLAB, hand-written RCpp
+languages; hand-written MEX files may be used for MATLAB, hand-written Rcpp
bindings might be used for R bindings, and so forth.
However, these approaches have a fundamental flaw: the hand-written bindings
@@ -59,7 +45,7 @@ workload; therefore an alternate solution is needed.
At the time of the design of this system, mlpack shipped headers for a C++
library as well as many (~40) hand-written command-line programs that used the
-mlpack::IO object to manage command-line arguments. These programs all had
+`mlpack::IO` object to manage command-line arguments. These programs all had
similar structure, and could be logically split into three sections:
- parse the input options supplied by the user
@@ -68,21 +54,21 @@ similar structure, and could be logically split into three sections:
The user might interface with this command-line program like the following:
-@code
+```sh
$ mlpack_knn -r reference.csv -q query.csv -k 3 -d d.csv -n n.csv
-@endcode
+```
That is, they would pass a number of input options---some were numeric values
-(like @c -k @c 3 ); some were filenames (like @c -r @c reference.csv ); and a
-few other types also. Therefore, the first stage of the program---parsing input
+(like `-k 3`); some were filenames (like `-r reference.csv`); and a few other
+types also. Therefore, the first stage of the program---parsing input
options---would be handled by reading the command line and loading any input
matrices. Preparing the output, which usually consists of data matrices (i.e.
-@c -d @c d.csv ) involves saving the matrix returned by the algorithm to the
-user's desired file.
+`-d d.csv`) involves saving the matrix returned by the algorithm to the user's
+desired file.
Ideally, any binding to any language would have this same structure, and the
actual "run the machine learning algorithm" code could be identical. For
-MATLAB, for instance, we would not need to read the file @c reference.csv but
+MATLAB, for instance, we would not need to read the file `reference.csv` but
instead the user would simply pass their data matrix as an argument. So each
input and output parameter would need to be handled differently, but the
algorithm could be run identically across all bindings.
@@ -91,33 +77,30 @@ Therefore, design of an automatically-generated binding system would simply
involve generating the boilerplate code necessary to parse input options for a
given language, and to return output options to a user.
-@section bindings_code Writing code that can be turned into a binding
+## Writing code that can be turned into a binding
This section details what a binding file might actually look like. It is good
to have this API in mind when reading the following sections.
-Each mlpack binding is typically contained in the @c src/mlpack/methods/ folder
+Each mlpack binding is typically contained in the `src/mlpack/methods/` folder
corresponding to a given machine learning algorithm, with the suffix
-@c _main.cpp ; so an example is @c src/mlpack/methods/pca/pca_main.cpp .
+`_main.cpp`; so an example is `src/mlpack/methods/pca/pca_main.cpp`.
These files have roughly two parts:
- - definition of the input and output parameters with @c PARAM macros and
- documentation with @c BINDING macros
- - implementation of @c BINDING_FUNCTION(), which is the actual machine learning
+ - definition of the input and output parameters with `PARAM` macros and
+ documentation with `BINDING` macros
+ - implementation of `BINDING_FUNCTION()`, which is the actual machine learning
code
Here is a simple example file:
-@code
+```c++
// This is a stripped version of mean_shift_main.cpp.
-#include
-#include
+#include
// Define the name of the binding (as seen by the binding generation system).
-#ifdef BINDING_NAME
- #undef BINDING_NAME
-#endif
+#undef BINDING_NAME
#define BINDING_NAME mean_shift
#include
@@ -244,104 +227,98 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& timers)
if (params.Has("centroid"))
params.Get("centroid") = std::move(centroids);
}
-@endcode
+```
-We can see that we have defined the name of the binding with the @c BINDING_NAME
-macro, and basic program information in the @c BINDING_USER_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
+We can see that we have defined the name of the binding with the `BINDING_NAME`
+macro, and basic program information in the `BINDING_USER_NAME()`,
+`BINDING_SHORT_DESC()`, `BINDING_LONG_DESC()`, `BINDING_EXAMPLE()` and
+`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
-parameters are defined with the @c PARAM macros, of which there are many. The
+parameters are defined with the `PARAM` macros, of which there are many. The
names of these macros specify the type, whether the parameter is required, and
whether the parameter is input or output. Some examples:
- - @c PARAM_STRING_IN() -- a string-type input parameter
- - @c PARAM_MATRIX_OUT() -- a matrix-type output parameter
- - @c PARAM_DOUBLE_IN_REQ() -- a required double-type input parameter
- - @c PARAM_UMATRIX_IN() -- an unsigned matrix-type input parameter
- - @c PARAM_MODEL_IN() -- a serializable model-type input parameter
+ - `PARAM_STRING_IN()` -- a string-type input parameter
+ - `PARAM_MATRIX_OUT()` -- a matrix-type output parameter
+ - `PARAM_DOUBLE_IN_REQ()` -- a required double-type input parameter
+ - `PARAM_UMATRIX_IN()` -- an unsigned matrix-type input parameter
+ - `PARAM_MODEL_IN()` -- a serializable model-type input parameter
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 define @c BINDING_NAME,
-then write @c BINDING_USER_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 a @c BINDING_FUNCTION() function that actually
-performs the functionality of the binding.
+In order to write a new binding, then, you simply must define `BINDING_NAME`,
+then write `BINDING_USER_NAME()`, `BINDING_SHORT_DESC()`, `BINDING_LONG_DESC()`,
+`BINDING_EXAMPLE()` and `BINDING_SEE_ALSO()` definitions of the program with
+some docuentation, define the input and output parameters as `PARAM` macros, and
+then write a `BINDING_FUNCTION()` function that actually performs the
+functionality of the binding.
-Inside of @c BINDING_FUNCTION(util::Params& params, util::Timers& timers):
+Inside of `BINDING_FUNCTION(util::Params& params, util::Timers& timers)`:
- - All input parameters are accessible through @c params.Get("name").
+ - All input parameters are accessible through `params.Get("name")`.
- All output parameters should be set by the end of the function with the
- @c params.Get("name") method.
- - The @c params.Has("name") function will return @c true if the parameter
- @c "name" was specified.
- - Timers can be started and stopped with @c timers.Start("timer_name") and
- @c timers.Stop("timer_name").
+ `params.Get("name")` method.
+ - The `params.Has("name")` function will return `true` if the parameter
+ `"name"` was specified.
+ - Timers can be started and stopped with `timers.Start("timer_name")` and
+ `timers.Stop("timer_name")`.
-Then, assuming that your program is saved in the file @c program_name_main.cpp,
+Then, assuming that your program is saved in the file `program_name_main.cpp`,
generating bindings for other languages is a simple addition to the
-@c CMakeLists.txt file:
+`CMakeLists.txt` file in `src/mlpack/methods/CMakeLists.txt`:
-@code
-add_cli_executable(program_name)
-add_python_binding(program_name)
-add_markdown_docs(program_name "cli;python" "category")
-@endcode
+```
+add_all_bindings(program_dir program_name "category")
+```
-In this example, @c add_markdown_docs() will generate documentation that is
-typically used to build the website. The "category" parameter should be one of
-the categories in @c src/mlpack/bindings/markdown/MarkdownCategories.cmake.
+In this example, this will also add a Markdown binding, which will generate
+documentation that is typically used to build the website. The `category`
+parameter should be one of the categories in
+`src/mlpack/bindings/markdown/MarkdownCategories.cmake`.
-@section bindings_general How to write mlpack bindings
+## How to write mlpack bindings
This section describes the general structure of the automatic binding system and
how one might write a new binding for mlpack. After reading this section it
should be relatively clear how one could use the provided functionality in the
-@c Params and @c Timers class along with CMake to add a binding for a new mlpack
+`Params` and `Timers` class 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_binding_name Providing a name with @c BINDING_NAME
+### Providing a name with `BINDING_NAME`
-Every binding must have the macro @c BINDING_NAME defined, specifying a name
+Every binding must have the macro `BINDING_NAME` defined, specifying a name
(without spaces, generally all lowercase) that will be used to represent the
-binding. It is suggested to @c #undef any previous setting of @c BINDING_NAME
+binding. It is suggested to `#undef` any previous setting of `BINDING_NAME`
just to prevent any strange error messages in case it is already defined.
Here is an example that can be adapted:
-@code
-#ifdef BINDING_NAME
- #undef BINDING_NAME
-#endif
+```c++
+#undef BINDING_NAME
#define BINDING_NAME my_binding_name
// BINDING_NAME should be defined before including mlpack_main.hpp!
#include
-@endcode
+```
If this macro is not defined, compilation of the binding will fail in many ways
with potentially obscure error messages! (Sorry that they are bad error
messages. The preprocessor doesn't give us too much to work with.)
-@subsection bindings_general_program_doc Documenting a program with
-@c BINDING_USER_NAME(), @c BINDING_SHORT_DESC(), @c BINDING_LONG_DESC(),
-@c BINDING_EXAMPLE() and @c BINDING_SEE_ALSO().
+### Documenting a program with macros
-Any mlpack program should be documented with the @c BINDING_USER_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
+Any mlpack binding should be documented with the `BINDING_USER_NAME()`,
+`BINDING_SHORT_DESC()`, `BINDING_LONG_DESC()`, `BINDING_EXAMPLE()` and
+`BINDING_SEE_ALSO()` macros, which is available from the
+`` header. The macros are of the form
-@code
+```c++
BINDING_USER_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."
@@ -352,17 +329,17 @@ 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
implements and does, and a quick overview of how it can be used and what it
should be used for. When writing new short documentation, it is a good idea to
take a look at the existing documentation to get an idea of the general format.
-For the "see also" section, you can specify as many @c SEE_ALSO() calls as you
+For the "see also" section, you can specify as many `SEE_ALSO()` calls as you
see fit. These are links used at the "see also" section of the website
documentation for each binding, and it's very important that relevant links are
-provided (also to other bindings). See the @c SEE_ALSO() documentation for more
+provided (also to other bindings). See the `SEE_ALSO()` documentation for more
details.
Although it is possible to provide very short documentation, it is certainly
@@ -377,7 +354,7 @@ immediately search for, instead of taking a long time to read and carefully
consider all of the written documentation.
However, it is difficult to write language-agnostic documentation. For
-instance, in a command-line program, an output parameter '\--output_file' would
+instance, in a command-line program, an output parameter `--output_file` would
be specified on the command line as an input parameter, but in Python, the
output parameter 'output' would actually simply be returned from the call to the
Python function. Therefore, we must be careful how our documentation refers to
@@ -388,18 +365,18 @@ input and output parameters. The following general guidelines can help:
like Python and MATLAB and also "arguments given on the command line" for
command line programs.
- - Use the provided @c PRINT_PARAM_STRING() macro to print the names of
- parameters. For instance, PRINT_PARAM_STRING("shuffle") will print
- @c '\--shuffle' for a command line program and @c 'shuffle' for a Python
- binding. The @c PRINT_PARAM_STRING() macro also takes into account the type
+ - Use the provided `PRINT_PARAM_STRING()` macro to print the names of
+ parameters. For instance, `PRINT_PARAM_STRING("shuffle")` will print
+ `--shuffle` for a command line program and `'shuffle'` for a Python
+ binding. The `PRINT_PARAM_STRING()` macro also takes into account the type
of the parameter.
- - Use the provided @c PRINT_DATASET() and @c PRINT_MODEL() macro to introduce
+ - Use the provided `PRINT_DATASET()` and `PRINT_MODEL()` macro to introduce
example datasets or models, which can be useful when introducing an example
- usage of the program. So you could write @c '"to @c run @c with @c a
- @c dataset @c " @c + @c PRINT_DATASET("data") @c + @c "..."'.
+ usage of the program. So you could write `"to run with a dataset " +
+ PRINT_DATASET("data") + "..."`.
- - Use the provided @c PRINT_CALL() macro to print example invocations of the
+ - Use the provided `PRINT_CALL()` macro to print example invocations of the
program. The first argument is the name of the program, and then the
following arguments should be the name of a parameter followed by the value
of that parameter.
@@ -410,95 +387,123 @@ input and output parameters. The following general guidelines can help:
- Remember that some languages give output through return values and some give
output using other input parameters. So the right verbiage to use is, e.g.,
- 'the results may be saved using the PRINT_PARAM_STRING("output")
- parameter', and @b not 'the results are returned through the
- PRINT_PARAM_STRING("output") parameter'.
+ `the results may be saved using the PRINT_PARAM_STRING("output") parameter`,
+ and ***not*** `the results are returned through the
+ PRINT_PARAM_STRING("output") parameter`.
-Each of these macros (@c PRINT_PARAM_STRING(), @c PRINT_DATASET(),
-@c PRINT_MODEL(), and @c PRINT_CALL() ) provides different output depending on
-the language. Below are some example of documentation strings and their outputs
-for different languages. Note that the output might not be *exactly* as written
-or formatted here, but the general gist should be the same.
+Each of these macros (`PRINT_PARAM_STRING()`, `PRINT_DATASET()`,
+`PRINT_MODEL()`, and `PRINT_CALL()`) provides different output depending on the
+language. Below are some example of documentation strings and their outputs for
+different languages. Note that the output might not be *exactly* as written or
+formatted here, but the general gist should be the same.
-@code
-Input C++ (snippet):
+*Input C++ (snippet):*
+```c++
"The parameter " + PRINT_PARAM_STRING("shuffle") + ", if set, will shuffle "
"the data before learning."
+```
-Command-line program output (snippet):
+*Command-line program output (snippet):*
+```
The parameter '--shuffle', if set, will shuffle the data before learning.
+```
-Python binding output (snippet):
+*Python binding output (snippet):*
+```
The parameter 'shuffle', if set, will shuffle the data before learning.
+```
-Julia binding output (snippet):
+*Julia binding output (snippet):*
+```
The parameter `shuffle`, if set, will shuffle the data before learning.
+```
-Go binding output (snippet):
+*Go binding output (snippet):*
+```
The parameter "Shuffle", if set, will shuffle the data before learning.
-@endcode
+```
-@code
-Input C++ (snippet):
+Another example:
+*Input C++ (snippet):*
+
+```c++
"The output matrix can be saved with the " + PRINT_PARAM_STRING("output") +
" output parameter."
+```
-Command-line program output (snippet):
+*Command-line program output (snippet):*
+```
The output matrix can be saved with the '--output_file' output parameter.
+```
-Python binding output (snippet):
+*Python binding output (snippet):*
+```
The output matrix can be saved with the 'output' output parameter.
+```
-Julia binding output (snippet):
+*Julia binding output (snippet):*
+```
The output matrix can be saved with the `output` output parameter.
+```
-Go binding output (snippet):
+*Go binding output (snippet):*
+```
The output matrix can be saved with the "output" output parameter.
-@endcode
+```
-@code
-Input C++ (snippet):
+And another example:
+*Input C++ (snippet):*
+
+```c++
"For example, to train a model on the dataset " + PRINT_DATASET("x") + " and "
"save the output model to " + PRINT_MODEL("model") + ", the following command"
" can be used:"
"\n\n" +
PRINT_CALL("program", "input", "x", "output_model", "model")
+```
-Command-line program output (snippet):
+*Command-line program output (snippet):*
+```
For example, to train a model on the dataset 'x.csv' and save the output model
to 'model.bin', the following command can be used:
$ program --input_file x.csv --output_model_file model.bin
+```
-Python binding output (snippet):
+*Python 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:
>>> output = program(input=x)
>>> model = output['output_model']
+```
-Julia binding output (snippet):
+*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):
+*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:
@@ -507,11 +512,13 @@ Go binding output (snippet):
param.Input = x
model := mlpack.Program(param)
-@endcode
+```
-@code
-Input C++ (full program, 'random_numbers_main.cpp'):
+And finally, a full program example:
+*Input C++ (full program, `random_numbers_main.cpp`):*
+
+```c++
// Program Name.
BINDING_USER_NAME("Random Numbers");
@@ -543,11 +550,11 @@ Input C++ (full program, 'random_numbers_main.cpp'):
"\n\n" +
PRINT_CALL("random_numbers", "num_values", 100, "subtract", 3, "output",
"rand", "output_model", "rand_lr"));
-@endcode
+```
-Command line output:
+*Command line output*:
-@code
+```
Random Numbers
This program generates random numbers with a variety of nonsensical
@@ -567,11 +574,11 @@ Command line output:
$ random_numbers --num_values 100 --subtract 3 --output_file rand.csv
--output_model_file rand_lr.bin
-@endcode
+```
-Python binding output:
+*Python binding output*:
-@code
+```
Random Numbers
This program generates random numbers with a variety of nonsensical
@@ -592,11 +599,11 @@ Python binding output:
>>> output = random_numbers(num_values=100, subtract=3)
>>> rand = output['output']
>>> rand_lr = output['output_model']
-@endcode
+```
-Julia binding output:
+*Julia binding output:*
-@code
+```
Random Numbers
This program generates random numbers with a variety of nonsensical
@@ -617,11 +624,11 @@ Julia binding output:
```julia
julia> rand, rand_lr = random_numbers(num_values=100, subtract=3)
```
-@endcode
+```
-Go binding output:
+*Go binding output:*
-@code
+```
Random Numbers
This program generates random numbers with a variety of nonsensical
@@ -645,128 +652,121 @@ Go binding output:
param.Subtract=3
rand, randLr := mlpack.RandomNumbers(param)
-@endcode
+```
-@subsection bindings_general_define_params Defining parameters for a program
+### Defining parameters for a program
-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
+There exist several macros that can be used after a `BINDING_LONG_DESC()` and
+`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.
+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
-@code
+```c++
PARAM_STRING_IN("algorithm", "The algorithm to use: 'svd' or 'blah'.", "a");
-@endcode
+```
-will define a string input parameter @c algorithm (referenced as
-@c '\--algorithm' from the command-line or @c 'algorithm' from Python) with the
-description The algorithm to use: 'svd' or 'blah'. The
-single-character alias @c '-a' can be used from a command-line program (but
-means nothing in Python).
+will define a string input parameter `algorithm` (referenced as `--algorithm`
+from the command-line or `'algorithm'` from Python) with the description `The
+algorithm to use: 'svd' or 'blah'.` The single-character alias `-a` can be used
+from a command-line program (but means nothing in Python).
There are numerous different macros that can be used:
- - @c PARAM_FLAG() - boolean flag parameter
- - @c PARAM_INT_IN() - integer input parameter
- - @c PARAM_INT_OUT() - integer output parameter
- - @c PARAM_DOUBLE_IN() - double input parameter
- - @c PARAM_DOUBLE_OUT() - double output parameter
- - @c PARAM_STRING_IN() - string input parameter
- - @c PARAM_STRING_OUT() - string output parameter
- - @c PARAM_MATRIX_IN() - double-valued matrix (arma::mat) input
+ - `PARAM_FLAG()` - boolean flag parameter
+ - `PARAM_INT_IN()` - integer input parameter
+ - `PARAM_INT_OUT()` - integer output parameter
+ - `PARAM_DOUBLE_IN()` - double input parameter
+ - `PARAM_DOUBLE_OUT()` - double output parameter
+ - `PARAM_STRING_IN()` - string input parameter
+ - `PARAM_STRING_OUT()` - string output parameter
+ - `PARAM_MATRIX_IN()` - double-valued matrix (`arma::mat`) input parameter
+ - `PARAM_MATRIX_OUT()` - double-valued matrix (`arma::mat`) output parameter
+ - `PARAM_UMATRIX_IN()` - size_t-valued matrix (`arma::Mat`) input
parameter
- - @c PARAM_MATRIX_OUT() - double-valued matrix (arma::mat) output
+ - `PARAM_UMATRIX_OUT()` - size_t-valued matrix (`arma::Mat`) output
parameter
- - @c PARAM_UMATRIX_IN() - size_t-valued matrix (arma::Mat)
- input parameter
- - @c PARAM_UMATRIX_OUT() - size_t-valued matrix (arma::Mat)
- output parameter
- - @c PARAM_TMATRIX_IN() - transposed double-valued matrix (arma::mat)
- input parameter
- - @c PARAM_TMATRIX_OUT() - transposed double-valued matrix (arma::mat)
- output parameter
- - @c PARAM_MATRIX_AND_INFO_IN() - matrix with categoricals input parameter
- (std::tuple)
- - @c PARAM_COL_IN() - double-valued column vector (arma::vec) input
+ - `PARAM_TMATRIX_IN()` - transposed double-valued matrix (`arma::mat`) input
parameter
- - @c PARAM_COL_OUT() - double-valued column vector (arma::vec) output
+ - `PARAM_TMATRIX_OUT()` - transposed double-valued matrix (`arma::mat`) output
parameter
- - @c PARAM_UCOL_IN() - size_t-valued column vector (arma::Col)
- input parameter
- - @c PARAM_UCOL_OUT() - size_t-valued column vector
- (arma::Col) output parameter
- - @c PARAM_ROW_IN() - double-valued row vector (arma::rowvec) input
+ - `PARAM_MATRIX_AND_INFO_IN()` - matrix with categoricals input parameter
+ (`std::tuplearma::rowvec) output
+ - `PARAM_UCOL_IN()` - size_t-valued column vector (`arma::Col`) input
parameter
- - @c PARAM_VECTOR_IN() - std::vector input parameter
- - @c PARAM_VECTOR_OUT() - std::vector output parameter
- - @c PARAM_MODEL_IN() - serializable model input parameter
- - @c PARAM_MODEL_OUT() - serializable model output parameter
+ - `PARAM_UCOL_OUT()` - size_t-valued column vector (`arma::Col`) output
+ parameter
+ - `PARAM_ROW_IN()` - double-valued row vector (`arma::rowvec`) input parameter
+ - `PARAM_ROW_OUT()` - double-valued row vector (`arma::rowvec`) output
+ parameter
+ - `PARAM_VECTOR_IN()` - `std::vector` input parameter
+ - `PARAM_VECTOR_OUT()` - `std::vector` output parameter
+ - `PARAM_MODEL_IN()` - serializable model input parameter
+ - `PARAM_MODEL_OUT()` - serializable model output parameter
And for input parameters, the parameter may also be required:
- - @c PARAM_INT_IN_REQ()
- - @c PARAM_DOUBLE_IN_REQ()
- - @c PARAM_STRING_IN_REQ()
- - @c PARAM_MATRIX_IN_REQ()
- - @c PARAM_UMATRIX_IN_REQ()
- - @c PARAM_TMATRIX_IN_REQ()
- - @c PARAM_VECTOR_IN_REQ()
- - @c PARAM_MODEL_IN_REQ()
+ - `PARAM_INT_IN_REQ()`
+ - `PARAM_DOUBLE_IN_REQ()`
+ - `PARAM_STRING_IN_REQ()`
+ - `PARAM_MATRIX_IN_REQ()`
+ - `PARAM_UMATRIX_IN_REQ()`
+ - `PARAM_TMATRIX_IN_REQ()`
+ - `PARAM_VECTOR_IN_REQ()`
+ - `PARAM_MODEL_IN_REQ()`
-Click the links for each macro to read further documentation. Note also that
-each possible combination of @c IN, @c OUT, and @c REQ is not available---output
-options cannot be required, and some combinations simply have not been added
-because they have not been needed.
+See the source documentation for each macro to read further details. Note also
+that each possible combination of `IN`, `OUT`, and `REQ` is not
+available---output options cannot be required, and some combinations simply have
+not been added because they have not been needed.
-The @c PARAM_MODEL_IN() and @c PARAM_MODEL_OUT() macros are used to serialize
+The `PARAM_MODEL_IN()` and `PARAM_MODEL_OUT()` macros are used to serialize
mlpack models. These could be used, for instance, to allow the user to save a
trained model (like a linear regression model) or load an input model. The
-first parameter to the @c PARAM_MODEL_IN() or @c PARAM_MODEL_OUT() macro should
-be the C++ type of the model to be serialized; this type @b must have a function
-template void serialize(Archive&)
-(i.e. the type must be serializable via cereal).
-For example, to allow a user to specify an input model of type
-`LinearRegression`, the follow definition could be used:
+first parameter to the `PARAM_MODEL_IN()` or `PARAM_MODEL_OUT()` macro should be
+the C++ type of the model to be serialized; this type *must* have a function
+`template void serialize(Archive&)` (i.e. the type must be
+serializable via cereal). For example, to allow a user to specify an input
+model of type `LinearRegression`, the follow definition could be used:
-@code
+```c++
PARAM_MODEL_IN(LinearRegression, "input_model", "The input model to be used.",
"i");
-@endcode
+```
Then, the user will be able to specify their model from the command-line as
-@c \--input_model_file and from Python using the @c input_model option to the
+`--input_model_file` and from Python using the `input_model` option to the
generated binding.
From the command line, matrix-type and model-type options (both input and
-output) are loaded from or saved to the specified file. This means that
-@c _file is appended to the name of the parameter; so if the parameter name is
-@c data and it is of a matrix or model type, then the name that the user will
-specify on the command line will be @c \--data_file. This displayed parameter
-name change @b only occurs with matrix and model type parameters for
-command-line programs.
+output) are loaded from or saved to the specified file. This means that `_file`
+is appended to the name of the parameter; so if the parameter name is `data` and
+it is of a matrix or model type, then the name that the user will specify on the
+command line will be `--data_file`. This displayed parameter name change *only*
+occurs with matrix and model type parameters for command-line programs.
-The @c PARAM_MATRIX_AND_INFO() macro defines a categorical matrix parameter
+The `PARAM_MATRIX_AND_INFO()` macro defines a categorical matrix parameter
(more specifically, a matrix type that can support categorical columns). From
the C++ program side, this means that the parameter type is
-std::tuple. From the user side, for a
+`std::tuple`. From the user side, for a
command-line program, this means that the user will pass the filename of a
dataset that can have categorical features, such as an ARFF dataset. For a
Python program, the user may pass a Pandas matrix with categorical columns.
When the program is run, the input that the user gives will be processed and the
-@c data::DatasetInfo object will be filled with the dimension types and the
-@c arma::mat object will be filled with the data itself.
+`data::DatasetInfo` object will be filled with the dimension types and the
+`arma::mat` object will be filled with the data itself.
To give some examples, the parameter definitions from the example
-"random_numbers" program in the previous section are shown below.
+`random_numbers` program in the previous section are shown below.
-@code
+```c++
PARAM_MATRIX_IN("input", "The input matrix that will be ignored.", "i");
PARAM_DOUBLE_IN("subtract", "The value to subtract from each parameter.", "s",
0.0); // Default value of 0.0.
@@ -775,91 +775,90 @@ PARAM_INT_IN("num_samples", "The number of samples to generate.", "n", 100);
PARAM_MATRIX_OUT("output", "The output matrix of random samples.", "o");
PARAM_MODEL_OUT(LinearRegression, "output_model", "The randomly generated "
"linear regression output model.", "M");
-@endcode
+```
Note that even the parameter documentation strings must be a little be agnostic
to the binding type, because the command-line interface is so different than the
Python interface to the user.
-@subsection bindings_general_functions Using @c Params in a @c BINDING_FUNCTION() function
+### Using `Params` in a `BINDING_FUNCTION()` function
-mlpack's @c util::Params class 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 BINDING_LONG_DESC() and @c BINDING_EXAMPLE() macros
-and the @c PARAM_*() macros have been defined, a language-agnostic void
-BINDING_FUNCTION(util::Params& params, util::Timers& timers) function can
-be written. This function then can perform the actual computation that the
-entire program is meant to.
+mlpack's `util::Params` class 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 `BINDING_LONG_DESC()` and
+`BINDING_EXAMPLE()` macros and the `PARAM_*()` macros have been defined, a
+language-agnostic `void BINDING_FUNCTION(util::Params& params, util::Timers&
+timers)` 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
-for this, plus a utility printing function:
+Inside of a `BINDING_FUNCTION()` function, the given `util::Params` object can
+be used to access input parameters and set output parameters. There are two
+main functions for this, plus a utility printing function:
- - @c params.Get() - get a reference to a parameter
- - @c params.Has() - returns true if the user specified the parameter
- - @c params.GetPrintable() - returns a string representing the value of the
+ - `params.Get()` - get a reference to a parameter
+ - `params.Has()` - returns true if the user specified the parameter
+ - `params.GetPrintable()` - returns a string representing the value of the
parameter
-So, to print "hello" if the user specified the @c print_hello parameter, the
+So, to print `hello` if the user specified the `print_hello` parameter, the
following code could be used:
-@code
+```c++
if (params.Has("print_hello"))
std::cout << "Hello!" << std::endl;
else
std::cout << "No greetings for you!" << std::endl;
-@endcode
+```
-To access a string that a user passed in to the @c string parameter, the
+To access a string that a user passed in to the `string` parameter, the
following code could be used:
-@code
+```c++
const std::string& str = params.Has("string");
-@endcode
+```
Matrix types are accessed in the same way:
-@code
+```c++
arma::mat& matrix = params.Get("matrix");
-@endcode
+```
-Similarly, model types can be accessed. If a @c LinearRegression model was
-specified by the user as the parameter @c model, the following code can access
+Similarly, model types can be accessed. If a `LinearRegression` model was
+specified by the user as the parameter `model`, the following code can access
the model:
-@code
+```c++
LinearRegression& lr = params.Get("model");
-@endcode
+```
Matrices with categoricals are a little trickier to access since the C++
-parameter type is std::tuple. The
-example below creates references to both the @c DatasetInfo and matrix objects,
-assuming the user has passed a matrix with categoricals as the @c matrix
-parameter.
+parameter type is `std::tuple`. The example below
+creates references to both the `DatasetInfo` and matrix objects, assuming the
+user has passed a matrix with categoricals as the `matrix` parameter.
-@code
+```c++
using namespace mlpack;
typename std::tuple TupleType;
data::DatasetInfo& di = std::get<0>(params.Get("matrix"));
arma::mat& matrix = std::get<1>(params.Get("matrix"));
-@endcode
+```
These two functions can be used to write an entire program. The third function,
-@c params.GetPrintable(), can be used to help provide useful output in a
+`params.GetPrintable()`, can be used to help provide useful output in a
program. Typically, this function should be used if you want to provide some
kind of error message about a matrix or model parameter, but want to avoid
printing the matrix itself. For instance, printing a matrix parameter with
-@c params.GetPrintable() will print the filename for a command-line binding or
-the size of a matrix for a Python binding. @c params.GetPrintable() for a model
+`params.GetPrintable()` will print the filename for a command-line binding or
+the size of a matrix for a Python binding. `params.GetPrintable()` for a model
parameter will print the filename for the model for a command-line binding or a
simple string representing the type of the model for a Python binding.
-Putting all of these ideas together, here is the @c BINDING_FUNCTION() function
-that could be created for the "random_numbers" program from earlier sections.
+Putting all of these ideas together, here is the `BINDING_FUNCTION()` function
+that could be created for the `random_numbers` program from earlier sections.
-@code
+```c++
// BINDING_NAME should be defined here: ...
#include
@@ -905,191 +904,192 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& timers)
params.Get("output_model") = std::move(lr);
}
}
-@endcode
+```
-@subsection bindings_general_more More documentation on using @c util::Params
+### More documentation on using `util::Params`
-More documentation for the IO module can either be found on the util::Params
-documentation page, or by reading the existing mlpack bindings. These can be
-found in the @c src/mlpack/methods/ folders, by finding the @c _main.cpp files.
-For instance, @c src/mlpack/methods/neighbor_search/knn_main.cpp is the
-k-nearest-neighbor search program definition.
+More documentation for the `util::Params` class can either be found in the
+source code for `util::Params`, or by reading the existing mlpack bindings.
+These can be found in the `src/mlpack/methods/` folders, by finding the
+`_main.cpp` files. For instance,
+`src/mlpack/methods/neighbor_search/knn_main.cpp` is the k-nearest-neighbor
+search program definition.
-@section bindings_structure Structure of IO module and associated macros
+## Structure of IO module and associated macros
-This section describes the internal functionality of the IO module, which stores
-all known parameter sets, and the associated macros. If you are only interested
-in writing mlpack programs, this section is probably not worth reading.
+This section describes the internal functionality of the `IO` module, which
+stores all known parameter sets, and the associated macros. If you are only
+interested in writing mlpack programs, this section is probably not worth
+reading.
There are eight main components involved with mlpack bindings:
- - the IO module, a thread-safe singleton class that stores parameter
+ - the `IO` module, a thread-safe singleton class that stores parameter
information
- - the BINDING_FUNCTION() function that defines the functionality of the binding
- - 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 `BINDING_FUNCTION()` function that defines the functionality of the
+ binding
+ - 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 @c mlpack::IO module is a singleton class that stores, at runtime, the
+The `mlpack::IO` module is a singleton class that stores, at runtime, the
binding name, the documentation, and the parameter information and values for
any bindings available in the translation unit. When the binding is called, the
-@c mlpack::IO class instantiates a @c util::Params and @c util::Timers object,
+`mlpack::IO` class instantiates a `util::Params` and `util::Timers` object,
populating them with the correct options for the given binding, then calls
-@c BINDING_FUNCTION() with those instantiated objects.
+`BINDING_FUNCTION()` with those instantiated objects.
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
-BINDING_USER_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
+`BINDING_USER_NAME()`, `BINDING_SHORT_DESC()`, `BINDING_LONG_DESC()`,
+`BINDING_EXAMPLE()`, `BINDING_SEE_ALSO()` and `PARAM_*()` macros declare global
+variables that, in their constructors, register themselves with the `IO`
singleton.
- * The @c BINDING_USER_NAME() macro declares an object of type
- @c mlpack::util::BindingName.
- * The @c BINDING_SHORT_DESC() macro declares an object of type
- @c mlpack::util::ShortDescription.
- * The @c BINDING_LONG_DESC() macro declares an object of type
- @c mlpack::util::LongDescription.
- * The @c BINDING_EXAMPLE() macro declares an object of type
- @c mlpack::util::Example.
- * The @c BINDING_SEE_ALSO() macro declares an object of type
- @c mlpack::util::SeeAlso.
- * The @c BindingName class constructor calls @c IO::AddBindingName() in order
+ * The `BINDING_USER_NAME()` macro declares an object of type
+ `mlpack::util::BindingName`.
+ * The `BINDING_SHORT_DESC()` macro declares an object of type
+ `mlpack::util::ShortDescription`.
+ * The `BINDING_LONG_DESC()` macro declares an object of type
+ `mlpack::util::LongDescription`.
+ * The `BINDING_EXAMPLE()` macro declares an object of type
+ `mlpack::util::Example`.
+ * The `BINDING_SEE_ALSO()` macro declares an object of type
+ `mlpack::util::SeeAlso`.
+ * The `BindingName` class constructor calls `IO::AddBindingName()` in order
to register the given program name.
- * The @c ShortDescription class constructor calls @c IO::AddShortDescription()
+ * The `ShortDescription` class constructor calls `IO::AddShortDescription()`
in order to register the given short description.
- * The @c LongDescription class constructor calls @c IO::AddLongDescription() in
+ * The `LongDescription` class constructor calls `IO::AddLongDescription()` in
order to register the given long description.
- * The @c Example class constructor calls @c IO::AddExample() in order to
+ * The `Example` class constructor calls `IO::AddExample()` in order to
register the given example.
- * The @c SeeAlso class constructor calls @c IO::AddSeeAlso() in order to
+ * The `SeeAlso` class constructor calls `IO::AddSeeAlso()` in order to
register the given see-also link.
-All of those macro calls use whatever the value of the @c BINDING_NAME macro is
-at the time of instantiation. This is why it is important that @c BINDING_NAME
-is set properly at the time @c mlpack_main.hpp is included and before any
+All of those macro calls use whatever the value of the `BINDING_NAME` macro is
+at the time of instantiation. This is why it is important that `BINDING_NAME`
+is set properly at the time `mlpack_main.hpp` is included and before any
options are defined.
-The @c PARAM_*() macros declare an object that will, in its constructor, call
-IO::Add() to register that parameter for the current binding (again specified by
-the @c BINDING_NAME macro's value) with the IO singleton. The specific type of
-that object will depend on the binding type being used.
+The `PARAM_*()` macros declare an object that will, in its constructor, call
+`IO::Add()` to register that parameter for the current binding (again specified
+by the `BINDING_NAME` macro's value) with the IO singleton. The specific type
+of that object will depend on the binding type being used.
-The IO::AddParameter() function takes the name of the binding it is for and an
-mlpack::util::ParamData object as its input. This @c ParamData object has a
+The `IO::AddParameter()` function takes the name of the binding it is for and an
+`mlpack::util::ParamData` object as its input. This `ParamData` object has a
number of fields that must be set to properly describe the parameter. Each of
the fields is documented and probably self-explanatory, but three fields deserve
further explanation:
- - the std::string tname member is used to encode the true type of
- the parameter---which is not known by the IO singleton at runtime. This
- should be set to TYPENAME(T) where @c T is the type of the
- parameter.
+ - the `std::string tname` member is used to encode the true type of the
+ parameter---which is not known by the `IO` singleton at runtime. This should
+ be set to `TYPENAME(T)` where `T` is the type of the parameter.
- - the ANY value member (where ANY is whatever type was chosen
- in case std::any is not available) is used to hold the actual value
- of the parameter. Typically this will simply be the parameter held by a
- @c ANY object, but for some types it may be more complex. For instance, for
- a command-line matrix option, the @c value parameter will actually hold a
- tuple containing both the filename and the matrix itself.
+ - the `ANY value` member (where `ANY` is whatever type was chosen in case
+ `std::any` is not available) is used to hold the actual value of the
+ parameter. Typically this will simply be the parameter held by a `ANY`
+ object, but for some types it may be more complex. For instance, for a
+ command-line matrix option, the `value` parameter will actually hold a tuple
+ containing both the filename and the matrix itself.
- - the std::string cppType should be a string containing the type as
- seen in C++ code. Typically this can be encoded by stringifying a
- @c PARAM_*() macro argument.
+ - the `std::string cppType` should be a string containing the type as seen in
+ C++ code. Typically this can be encoded by stringifying a `PARAM_*()` macro
+ argument.
-Thus, the global object defined by the @c PARAM_*() macro must turn its
-arguments into a fully specified @c ParamData object and then call IO::Add()
-with it.
+Thus, the global object defined by the `PARAM_*()` macro must turn its arguments
+into a fully specified `ParamData` object and then call `IO::Add()` with it.
With different binding types, different behavior is often required for the
-@c params.Get(), @c params.Has(), and @c params.GetPrintable() functions.
-In order to handle this, the IO singleton also holds a function pointer map, so
+`params.Get()`, `params.Has()`, and `params.GetPrintable()` functions. In
+order to handle this, the `IO` singleton also holds a function pointer map, so
that a given type of option can call specific functionality for a certain task.
-Given a @c util::Params object (which can be obtained with
-@c IO::Parameters("binding_name") ), this function map is accessible as
-@c params.functionMap, and is not meant to be used by users, but instead by
+Given a `util::Params` object (which can be obtained with
+`IO::Parameters("binding_name")`), this function map is accessible as
+`params.functionMap`, and is not meant to be used by users, but instead by
people writing binding types.
Each function in the map must have signature
-@code
+```c++
void MapFunction(const util::ParamData& d,
const void* input,
void* output);
-@endcode
+```
-The use of void pointers allows any type to be specified as input or output to
-the function without changing the signature for the map. The IO function map
+The use of `void` pointers allows any type to be specified as input or output to
+the function without changing the signature for the map. The `IO` function map
is of type
-@code
+```c++
std::map>
-@endcode
+```
-and the first map key is the typename (tname) of the parameter, and the
-second map key is the string name of the function. For instance, calling
+and the first map key is the typename (`tname`) of the parameter, and the second
+map key is the string name of the function. For instance, calling
-@code
+```c++
const util::ParamData& d = params.Parameters()["param"];
params.functionMap[d.tname]["GetParam"](d, input, output);
-@endcode
+```
-will call the @c GetParam() function for the type of the @c "param" parameter.
+will call the `GetParam()` function for the type of the `"param"` parameter.
Examples are probably easiest to understand how this functionality works; see
-the @c params.Get() source to see how this might be used.
+the `params.Get()` source to see how this might be used.
-The IO singleton expects the following functions to be defined in the function
+The `IO` singleton expects the following functions to be defined in the function
map for each type:
- - @c GetParam -- return a pointer to the parameter in @c output.
- - @c GetPrintableParam -- return a pointer to a string description of the
- parameter in @c output.
+ - `GetParam` -- return a pointer to the parameter in `output`.
+ - `GetPrintableParam` -- return a pointer to a string description of the
+ parameter in `output`.
-If these functions are properly defined, then the IO module will work
+If these functions are properly defined, then the `IO` module will work
correctly. Other functions may also be defined; these may be used by other
parts of the binding infrastructure for different languages.
-@section bindings_cli Command-line program bindings
+## Command-line program bindings
This section describes the internal functionality of the command-line program
binding generator. If you are only interested in writing mlpack programs, this
section probably is not worth reading. This section is worth reading only if
-you want to know the specifics of how the @c BINDING_FUNCTION() function and
+you want to know the specifics of how the `BINDING_FUNCTION()` function and
macros get turned into a fully working command-line program.
-The code for the command-line bindings is found in @c src/mlpack/bindings/cli.
+The code for the command-line bindings is found in `src/mlpack/bindings/cli`.
-@subsection bindings_cli_mlpack_main BINDING_FUNCTION() definition
+### The `BINDING_FUNCTION()` definition
-Any command-line program must be compiled with the @c BINDING_TYPE macro
-set to the value @c BINDING_TYPE_CLI. This is handled by the CMake macro
-@c add_cli_executable().
+Any command-line program must be compiled with the `BINDING_TYPE` macro
+set to the value `BINDING_TYPE_CLI`. This is handled by the CMake macro
+`add_cli_executable()`.
-When @c BINDING_TYPE is set to @c BINDING_TYPE_CLI, the following is set in
-@c src/mlpack/core/util/mlpack_main.hpp, which must be included by every mlpack
+When `BINDING_TYPE` is set to `BINDING_TYPE_CLI`, the following is set in
+`src/mlpack/core/util/mlpack_main.hpp`, which must be included by every mlpack
binding:
- - The options defined by @c PARAM_*() macros are of type
- mlpack::bindings::cli::CLIOption.
+ - The options defined by `PARAM_*()` macros are of type
+ `mlpack::bindings::cli::CLIOption`.
- - 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
- mlpack::bindings::cli::PrintDataset().
- * The @c PRINT_MODEL() macro is defined as
- mlpack::bindings::cli::PrintModel().
- * The @c PRINT_CALL() macro is defined as
- mlpack::bindings::cli::ProgramCall().
+ - The parameter and value printing macros for `BINDING_LONG_DESC()`
+ and `BINDING_EXAMPLE()` are set:
+ * The `PRINT_PARAM_STRING()` macro is defined as
+ `mlpack::bindings::cli::ParamString()`.
+ * The `PRINT_DATASET()` macro is defined as
+ `mlpack::bindings::cli::PrintDataset()`.
+ * The `PRINT_MODEL()` macro is defined as
+ `mlpack::bindings::cli::PrintModel()`.
+ * The `PRINT_CALL()` macro is defined as
+ `mlpack::bindings::cli::ProgramCall()`.
- - The function int main() is defined as:
+ - The function `int main()` is defined as:
-@code
+```c++
int main(int argc, char** argv)
{
// Parse the command-line options; put them into CLI.
@@ -1109,62 +1109,59 @@ int main(int argc, char** argv)
// clean up, and so forth.
mlpack::bindings::cli::EndProgram(params, timers);
}
-@endcode
+```
Thus any mlpack command-line binding first processes the command-line arguments
-with @c mlpack::bindings::cli::ParseCommandLine(), then runs the binding with
-@c BINDING_FUNCTION(), then cleans up with
-@c mlpack::bindings::cli::EndProgram().
+with `mlpack::bindings::cli::ParseCommandLine()`, then runs the binding with
+`BINDING_FUNCTION()`, then cleans up with `mlpack::bindings::cli::EndProgram()`.
-The @c ParseCommandLine() function reads the input parameters and sets the
-values in IO. For matrix-type and model-type parameters, this reads the
+The `ParseCommandLine()` function reads the input parameters and sets the
+values in `IO`. For matrix-type and model-type parameters, this reads the
filenames from the command-line, but does not load the matrix or model. Instead
the matrix or model is loaded the first time it is accessed with
-@c params.Get().
+`params.Get()`.
-The @c \--help parameter is handled by the mlpack::bindings::cli::PrintHelp()
+The `--help` parameter is handled by the `mlpack::bindings::cli::PrintHelp()`
function.
-At the end of program execution, the @c mlpack::bindings::cli::EndProgram()
+At the end of program execution, the `mlpack::bindings::cli::EndProgram()`
function is called. This writes any output matrix or model parameters to disk,
-and prints the program parameters and timers if @c \--verbose was given.
+and prints the program parameters and timers if `--verbose` was given.
-@subsection bindings_cli_matrix Matrix and model parameter handling
+### Matrix and model parameter handling
For command line bindings, the matrix, model, and matrix with categorical type
parameters all require special handling, since it is not possible to pass a
matrix of any reasonable size or a model on the command line directly.
Therefore for a matrix or model parameter, the user specifies the file
containing that matrix or model parameter. If the parameter is an input
-parameter, then the file is loaded when @c params.Get() is called. If the
+parameter, then the file is loaded when `params.Get()` is called. If the
parameter is an output parameter, then the matrix or model is saved to the file
-when @c EndProgram() is called.
+when `EndProgram()` is called.
-The actual implementation of this is that the ANY value member
-of the @c ParamData struct does not hold the model or the matrix, but instead a
-std::tuple containing both the matrix or the model, and the filename
+The actual implementation of this is that the `ANY value` member of the
+`ParamData` struct does not hold the model or the matrix, but instead a
+`std::tuple` containing both the matrix or the model, and the filename
associated with that matrix or model.
-This means that functions like @c params.Get() and
-@c params.GetPrintable() (and all of the other associated functions in the
-function map) must have special handling for matrix or model types. See those
-implementations for more details---the special handling is enforced via SFINAE.
+This means that functions like `params.Get()` and `params.GetPrintable()`
+(and all of the other associated functions in the function map) must have
+special handling for matrix or model types. See those implementations for more
+details---the special handling is enforced via SFINAE.
-@subsection bindings_cli_parsing Parsing the command line
+### Parsing the command line
-The @c ParseCommandLine() function uses CLI11 to read
-the values from the command line into the @c ParamData structs held by the IO
-singleton.
+The `ParseCommandLine()` function uses `CLI11` to read the values from the
+command line into the `ParamData` structs held by the `IO` singleton.
-In order to set up CLI11---and to keep its headers
-from needing to be included by the rest of the library---the code loops over
-each parameter known by the IO singleton and calls the @c "AddToPO" function
-from the function map. This in turn calls the necessary functions to register a
-given parameter with CLI11, and once all parameters
-have been registered, the facilities provided by CLI11
+In order to set up `CLI11`---and to keep its headers from needing to be included
+by the rest of the library---the code loops over each parameter known by the
+`IO` singleton and calls the `AddToPO` function from the function map. This in
+turn calls the necessary functions to register a given parameter with `CLI11`,
+and once all parameters have been registered, the facilities provided by `CLI11`
are used to parse the command line input properly.
-@section bindings_python Python bindings
+## Python bindings
This section describes the internal functionality of the mlpack Python binding
generator. If you are only interested in writing new bindings or building the
@@ -1176,33 +1173,33 @@ The Python bindings are significantly more complex than the command line
bindings because we cannot just compile directly to a finished product. Instead
we need a multi-stage compilation:
- - We must generate a setup.py file that can be used to compile the bindings.
- - We must generate the .pyx (Cython) bindings for each program.
- - Then we must build each .pyx into a .so that is loadable from Python.
+ - We must generate a `setup.py` file that can be used to compile the bindings.
+ - We must generate the `.pyx` (Cython) bindings for each program.
+ - Then we must build each `.pyx` into a `.so` that is loadable from Python.
- We must also test the Python bindings.
-This is done with a combination of C++ code to generate the .pyx bindings, CMake
-to run the actual compilation and generate the setup.py file, some utility
-Python functions, and tests written in both Python and C++. This code is
-primarily contained in @c src/mlpack/bindings/python/.
+This is done with a combination of C++ code to generate the `.pyx` bindings,
+CMake to run the actual compilation and generate the `setup.py` file, some
+utility Python functions, and tests written in both Python and C++. This code
+is primarily contained in `src/mlpack/bindings/python/`.
-@subsection bindings_python_matrix Passing matrices to/from Python
+### Passing matrices to/from Python
The standard Python matrix library is numpy, so mlpack bindings should accept
numpy matrices as input. Fortunately, numpy Cython bindings already exist,
which make it easy to convert from a numpy object to an Armadillo object without
copying any data. This code can be found in
-@c src/mlpack/bindings/python/mlpack/arma_numpy.pyx, and is used by the Python
-@c params.Get() functionality.
+`src/mlpack/bindings/python/mlpack/arma_numpy.pyx`, and is used by the Python
+`params.Get()` functionality.
mlpack also supports categorical matrices; in Python, the typical way of
representing matrices with categorical features is with Pandas. Therefore,
mlpack also accepts Pandas matrices, and if any of the Pandas matrix dimensions
are categorical, these are properly encoded. The function
-@c to_matrix_with_info() from @c mlpack/bindings/python/mlpack/matrix_utils.py
-is used to perform this conversion.
+`to_matrix_with_info()` from `mlpack/bindings/python/mlpack/matrix_utils.py` is
+used to perform this conversion.
-@subsection bindings_python_model Passing model parameter to/from Python
+### Passing model parameters to/from Python
We use (or abuse) Cython functionality in order to give the user a model object
that they can use in their Python code. However, we do not want to (or have the
@@ -1216,7 +1213,7 @@ reuse the model as an input parameter to another binding (or the same binding).
To return a function pointer we have to define a Cython class in the following
way (this example is taken from the perceptron binding):
-@code
+```py
cdef extern from "" nogil:
cdef int mlpack_perceptron(Params, Timers) nogil except +RuntimeError
@@ -1232,36 +1229,36 @@ cdef class PerceptronModelType:
def __dealloc__(self):
del self.modelptr
-@endcode
+```
-This class definition is automatically generated when the .pyx file is
+This class definition is automatically generated when the `.pyx` file is
automatically generated.
-@subsection bindings_python_setup_py CMake generation of setup.py
+### CMake generation of `setup.py`
-A boilerplate setup.py file can be found in
-@c src/mlpack/bindings/python/setup.py.in. This will be configured by CMake to
-produce the final @c setup.py file, but in order to do this, a list of the .pyx
+A boilerplate `setup.py` file can be found in
+`src/mlpack/bindings/python/setup.py.in`. This will be configured by CMake to
+produce the final `setup.py` file, but in order to do this, a list of the `.pyx`
files to be compiled must be gathered.
-Therefore, the @c add_python_binding() macro is defined in
-@c src/mlpack/bindings/python/CMakeLists.txt. This adds the given binding to
-the @c MLPACK_PYXS variable, which is then inserted into @c setup.py as part of
-the @c configure_file() step in @c src/mlpack/CMakeLists.txt.
+Therefore, the `add_python_binding()` macro is defined in
+`src/mlpack/bindings/python/CMakeLists.txt`. This adds the given binding to the
+`MLPACK_PYXS` variable, which is then inserted into `setup.py` as part of the
+`configure_file()` step in `src/mlpack/CMakeLists.txt`.
-@subsection bindings_python_generate_pyx Generation of .pyx files
+### Generation of `.pyx` files
-A binding named @c program is built into a program called
-@c generate_pyx_program (this a CMake target, so you can build these
+A binding named `program` is built into a program called
+`generate_pyx_program` (this a CMake target, so you can build these
individually if you like). The file
-@c src/mlpack/bindings/python/generate_pyx.cpp.in is configured by CMake to set
-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 BINDING_USER_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:
+`src/mlpack/bindings/python/generate_pyx.cpp.in` is configured by CMake to set
+the name of the program and the `*_main.cpp` file to include correctly, then
+the `mlpack::bindings::python::PrintPYX()` function is called by the program.
+The `PrintPYX()` function uses the parameters that have been set in the `IO`
+singleton by the `BINDING_USER_NAME()`, `BINDING_SHORT_DESC()`,
+`BINDING_LONG_DESC()`, `BINDING_EXAMPLE()`, `BINDING_SEE_ALSO()` and `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
@@ -1269,45 +1266,46 @@ can be compiled. The file has several sections:
- Definitions of classes for serializable model types
- The binding function definition
- Documentation: input and output parameters
- - The call to mlpackMain()
+ - The call to `BINDING_FUNCTION()`
- Handling of output functionality
- Return of output parameters
Any output parameters for Python bindings are returned in a dict containing
named elements.
-@subsection bindings_python_build_pyx Building the .pyx files
+### Building the `.pyx` files
-After building the @c generate_pyx_program target, the @c build_pyx_program
-target is built as a dependency of the @c python target. This simply takes the
-generated .pyx file and uses Python setuptools to compile this to a Python
+After building the `generate_pyx_program` target, the `build_pyx_program` target
+is built as a dependency of the `python` target. This simply takes the
+generated `.pyx` file and uses Python setuptools to compile this to a Python
binding.
-@subsection bindings_python_testing Testing the Python bindings
+### Testing the Python bindings
In addition to the C++ tests we have implemented for each binding, we also have
tests from Python that ensure that we can successfully transfer parameter values
from Python to C++ and return output correctly.
-The tests are in @c src/mlpack/bindings/python/tests/ and test both the actual
+The tests are in `src/mlpack/bindings/python/tests/` and test both the actual
bindings and also the auxiliary Python code included in
-@c src/mlpack/bindings/python/mlpack/.
+`src/mlpack/bindings/python/mlpack/`.
-@section bindings_new Adding new binding types
+## Adding new binding types
Adding a new binding type to mlpack is fairly straightforward once the general
-structure of the IO singleton and the function map that IO uses is understood.
-For each different language that bindings are desired for, the route to a
-solution will be particularly different---so it is hard to provide any general
-guidance for how to make new bindings that will be applicable to each language.
+structure of the `IO` singleton and the function map that `IO` uses is
+understood. For each different language that bindings are desired for, the
+route to a solution will be particularly different---so it is hard to provide
+any general guidance for how to make new bindings that will be applicable to
+each language.
In general, the first thing to handle will be how matrices are passed back and
forth between the target language. Typically this might mean getting the memory
-address of an input matrix and wrapping an @c arma::mat object around that
-memory address. This can be handled in the @c GetParam() function that is part
-of the IO singleton function map; see @c get_param.hpp for both the IO and
-Python bindings for an example (in @c src/mlpack/bindings/cli/ and
-@c src/mlpack/bindings/python/).
+address of an input matrix and wrapping an `arma::mat` object around that memory
+address. This can be handled in the `GetParam()` function that is part of the
+`IO` singleton function map; see `get_param.hpp` for both the `IO` and Python
+bindings for an example (in `src/mlpack/bindings/cli/` and
+`src/mlpack/bindings/python/`).
Serialization of models is also a tricky consideration; in some languages you
will be able to pass a pointer to the model itself. This is generally
@@ -1326,11 +1324,9 @@ probably a large amount of adaptation to other languages will be necessary.
Lastly, when adding a new language, be sure to make sure it works with the
Markdown documentation generator. In order to make this happen, you will need
-to modify all of the @c add_markdown_docs() calls in the different
-@c CMakeLists.txt files to contain the name of the language you have written a
-binding for. You will also need to modify every function in
-@c src/mlpack/bindings/markdown/print_doc_functions_impl.hpp to correctly call
+to modify all of the `add_markdown_docs()` calls in
+`src/mlpack/methods/CMakeLists.txt` to contain the name of the language you have
+written a binding for. You will also need to modify every function in
+`src/mlpack/bindings/markdown/print_doc_functions_impl.hpp` to correctly call
out to the corresponding function for the language that you have written
bindings for.
-
-*/
diff --git a/doc/developer/elemtype.md b/doc/developer/elemtype.md
new file mode 100644
index 0000000000..a758414197
--- /dev/null
+++ b/doc/developer/elemtype.md
@@ -0,0 +1,36 @@
+# The ElemType policy in mlpack
+
+mlpack algorithms should be as generic as possible. Often this means
+allowing arbitrary metrics or kernels to be used, but this also means allowing
+any type of data point to be used. This means that mlpack classes should
+support `float`, `double`, and other observation types. Some algorithms
+support this through the use of a `MatType` template parameter; others will
+have their own template parameter, `ElemType`.
+
+The `ElemType` template parameter can take any value that can be used by
+Armadillo (or, specifically, classes like `arma::Mat<>` and others); this
+encompasses the types
+
+ - `double`
+ - `float`
+ - `int`
+ - `unsigned int`
+ - `std::complex`
+ - `std::complex`
+
+and other primitive numeric types. Note that Armadillo does not support some
+integer types for functionality such as matrix decompositions or other more
+advanced linear algebra. This means that when these integer types are used,
+some algorithms may fail with Armadillo error messages indicating that those
+types cannot be used.
+
+*Note*: if the class has a `MatType` template parameter, `ElemType` can be
+easily defined as below:
+
+```c++
+typedef typename MatType::elem_type ElemType;
+```
+
+and otherwise a template parameter with the name `ElemType` can be used. It is
+generally a good idea to expose the element type somehow for use by other
+classes.
diff --git a/doc/guide/iodoc.hpp b/doc/developer/iodoc.md
similarity index 67%
rename from doc/guide/iodoc.hpp
rename to doc/developer/iodoc.md
index b60f6fc937..e55daa9a9c 100644
--- a/doc/guide/iodoc.hpp
+++ b/doc/developer/iodoc.md
@@ -1,6 +1,4 @@
-/*! @page iodoc Writing an mlpack binding
-
-@section iointro Introduction
+# Writing an mlpack binding
This tutorial gives some simple examples of how to write an mlpack binding that
can be compiled for multiple languages. These bindings make up the core of how
@@ -8,37 +6,39 @@ most users will interact with mlpack.
mlpack provides the following:
- - mlpack::Log, for debugging / informational / warning / fatal output
- - mlpack::IO, for parsing command line options or other option
+ - `mlpack::Log`, for debugging / informational / warning / fatal output
+ - a `util::Params` object, for parsing command line options or other option
+ - a `util::Timers` object, for collecting and displaying timing information
-Each of those classes are well-documented, and that documentation should be
-consulted for further reference.
+Each of those classes are well-documented, and that documentation in the source
+code should be consulted for further reference.
First, we'll discuss the logging infrastructure, which is useful for giving
output that users can see.
-@section simplelog Simple Logging Example
+## Simple logging example
mlpack has four logging levels:
- - Log::Debug
- - Log::Info
- - Log::Warn
- - Log::Fatal
+ - `Log::Debug`
+ - `Log::Info`
+ - `Log::Warn`
+ - `Log::Fatal`
-Output to Log::Debug does not show (and has no performance penalty) when mlpack
-is compiled without debugging symbols. Output to Log::Info is only shown when
-the program is run with the \c --verbose (or \c -v) flag. Log::Warn is always
-shown, and Log::Fatal will throw a std::runtime_error exception, after a newline
-is sent to it. If mlpack was compiled with debugging symbols, Log::Fatal will
+Output to `Log::Debug` does not show (and has no performance penalty) when
+mlpack is compiled without debugging symbols. Output to `Log::Info` is only
+shown when the program is run with the `verbose` option (for a command-line
+binding, this is `--verbose` or `-v`). `Log::Warn` is always shown, and
+`Log::Fatal` will throw a `std::runtime_error` exception, after a newline is
+sent to it. If mlpack was compiled with debugging symbols, `Log::Fatal` will
also print a backtrace, if the necessary libraries are available.
Here is a simple example binding, and its output. Note that instead of
-\c int \c main(), we use \c static \c void \c mlpackMain(). This is because the
-automatic binding generator (see \ref bindings) will set up the environment and
-once that is done, it will call \c mlpackMain().
+`int main()`, we use `void BINDING_FUNCTION()`. This is because the
+[automatic binding generator](bindings.md) will set up the environment and
+once that is done, it will call `BINDING_FUNCTION()`.
-@code
+```c++
#include
#include
// This definition below means we will only compile for the command line.
@@ -47,7 +47,7 @@ once that is done, it will call \c mlpackMain().
using namespace mlpack;
-static void mlpackMain()
+void BINDING_FUNCTION(util::Params& params, util::Timers& timers)
{
Log::Debug << "Compiled with debugging symbols." << std::endl;
@@ -59,19 +59,19 @@ static void mlpackMain()
Log::Warn << "Made it!" << std::endl;
}
-@endcode
+```
Assuming mlpack is installed on the system and the code above is saved in
-\c test.cpp, this program can be compiled with the following command:
+`test.cpp`, this program can be compiled with the following command:
-@code
+```sh
$ g++ -o test test.cpp -DDEBUG -g -rdynamic -lmlpack
-@endcode
+```
-Since we compiled with \c -DDEBUG, if we run the program as below, the following
+Since we compiled with `-DDEBUG`, if we run the program as below, the following
output is shown:
-@code
+```sh
$ ./test --verbose
[DEBUG] Compiled with debugging symbols.
[INFO ] Some test informational output.
@@ -81,13 +81,13 @@ $ ./test --verbose
terminate called after throwing an instance of 'std::runtime_error'
what(): fatal error; see Log::Fatal output
Aborted
-@endcode
+```
-The flags \c -g and \c -rdynamic are only necessary for providing a backtrace.
+The flags `-g` and `-rdynamic` are only necessary for providing a backtrace.
If those flags are not given during compilation, the following output would be
shown:
-@code
+```sh
$ ./test --verbose
[DEBUG] Compiled with debugging symbols.
[INFO ] Some test informational output.
@@ -98,36 +98,36 @@ $ ./test --verbose
terminate called after throwing an instance of 'std::runtime_error'
what(): fatal error; see Log::Fatal output
Aborted
-@endcode
+```
-The last warning is not reached, because Log::Fatal terminates the program.
+The last warning is not reached, because `Log::Fatal` terminates the program.
-Without debugging symbols (i.e. without \c -g and \c -DDEBUG) and without
---verbose, the following is shown:
+Without debugging symbols (i.e. without `-g` and `-DDEBUG`) and without
+`--verbose`, the following is shown:
-@code
+```sh
$ ./test
[WARN ] A warning!
[FATAL] Program has crashed.
terminate called after throwing an instance of 'std::runtime_error'
what(): fatal error; see Log::Fatal output
Aborted
-@endcode
+```
These four outputs can be very useful for both providing informational output
and debugging output for your mlpack program.
-@section simpleio Simple IO Example
+## Simple parameter example
-Through the mlpack::IO object, command-line parameters can be easily added
-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.
+Through the `mlpack::util::Params` object, parameters can be easily added to a
+binding 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.
+Here is a sample use of those macros, extracted from `methods/pca/pca_main.cpp`.
(Some details have been omitted from the snippet below.)
-@code
+```c++
#include
#include
#include
@@ -164,25 +164,26 @@ PARAM_INT_IN("new_dimensionality", "Desired dimensionality of output dataset.",
using namespace mlpack;
-static void mlpackMain()
+void BINDING_FUNCTION(util::Params& params, util::Timers& timers)
{
// Load input dataset.
- arma::mat& dataset = IO::GetParam("input");
+ arma::mat& dataset = params.Get("input");
- size_t newDimension = IO::GetParam("new_dimensionality");
+ size_t newDimension = params.Get("new_dimensionality");
...
// Now save the results.
- if (IO::HasParam("output"))
- IO::GetParam("output") = std::move(dataset);
+ if (params.Has("output"))
+ params.Get("output") = std::move(dataset);
}
-@endcode
+```
-Documentation is automatically generated using those macros, and when the
-program is run with --help the following is displayed:
+Documentation is automatically generated using those macros, and if compiled to
+a command-line program, when that program is run with `--help` the following is
+displayed:
-@code
+```
$ mlpack_pca --help
Principal Components Analysis
@@ -206,10 +207,8 @@ Options:
--verbose (-v) Display informational messages and the full list
of parameters and timers at the end of
execution.
-@endcode
+```
-The mlpack::IO documentation can be consulted for further and complete
+The `mlpack::IO` source code can be consulted for further and complete
documentation. Also useful is to look at other example bindings, found in
-\c src/mlpack/methods/.
-
-*/
+`src/mlpack/methods/`.
diff --git a/doc/developer/kernels.md b/doc/developer/kernels.md
new file mode 100644
index 0000000000..0b48bc3770
--- /dev/null
+++ b/doc/developer/kernels.md
@@ -0,0 +1,153 @@
+# The KernelType policy in mlpack
+
+Kernel methods make up a large class of machine learning techniques. Each of
+these methods is characterized by its dependence on a *kernel function*. In
+rough terms, a kernel function is a general notion of similarity between two
+points, with its value large when objects are similar and its value small when
+objects are dissimilar (note that this is not the only interpretation of what a
+kernel is).
+
+A kernel (or 'Mercer kernel') `K(a, b)` takes two objects as input and returns
+some sort of similarity value. The specific details and properties of kernels
+are outside the scope of this documentation; for a better introduction to
+kernels and kernel methods, there are numerous better resources available,
+including
+[Eric Kim's tutorial](http://www.eric-kim.net/eric-kim-net/posts/1/kernel_trick.html).
+
+mlpack implements a number of kernel methods and, accordingly, each of these
+methods allows arbitrary kernels to be used via the `KernelType` template
+parameter. Like the [MetricType policy](metrictype.md), the requirements are
+quite simple: a class implementing the `KernelType` policy must have
+
+ - an `Evaluate()` function
+ - a default constructor
+
+The signature of the `Evaluate()` function is straightforward:
+
+```c++
+template
+double Evaluate(const VecTypeA& a, const VecTypeB& b);
+```
+
+The function takes two vector arguments, `a` and `b`, and returns a `double`
+that is the evaluation of the kernel between the two arguments. So, for a
+particular kernel `K`, the `Evaluate()` function should return `K(a, b)`.
+
+The arguments `a` and `b`, of types `VecTypeA` and `VecTypeB`, respectively,
+will be an Armadillo-like vector type (usually `arma::vec`, `arma::sp_vec`, or
+similar). In general it should be valid to assume that `VecTypeA` is a class
+with the same API as `arma::vec`.
+
+Note that for kernels that do not hold any state, the `Evaluate()` method can be
+marked as `static`.
+
+Overall, the `KernelType` template policy is quite simple (much like the
+[MetricType policy](metrictype.md)). Below is an example kernel class, which
+outputs `1` if the vectors are close and `0` otherwise.
+
+```c++
+class ExampleKernel
+{
+ // Default constructor is required.
+ ExampleKernel() { }
+
+ // The example kernel holds no state, so we can mark Evaluate() as static.
+ template
+ static double Evaluate(const VecTypeA& a, const VecTypeB& b)
+ {
+ // Get how far apart the vectors are (using the Euclidean distance).
+ const double distance = arma::norm(a - b);
+
+ if (distance < 0.05) // Less than 0.05 distance is "close".
+ return 1;
+ else
+ return 0;
+ }
+};
+```
+
+Then, this kernel may be easily used inside of mlpack algorithms. For instance,
+the code below runs kernel PCA (`mlpack::kpca::KernelPCA`) on a random dataset
+using the `ExampleKernel`. The results are saved to a file called
+`results.csv`. (Note that this is simply an example to demonstrate usage, and
+this example kernel isn't actually likely to be useful in practice.)
+
+```c++
+#include
+#include "example_kernel.hpp" // Contains the ExampleKernel class.
+
+using namespace mlpack;
+using namespace mlpack::kpca;
+using namespace arma;
+
+int main()
+{
+ // Generate the random dataset; 10 dimensions, 5000 points.
+ mat dataset = randu(10, 5000);
+
+ // Instantiate the KernelPCA object with the ExampleKernel kernel type.
+ KernelPCA kpca;
+
+ // The dataset will be transformed using kernel PCA with the example kernel to
+ // contain only 2 dimensions.
+ kpca.Apply(dataset, 2);
+
+ // Save the results to 'results.csv'.
+ data::Save(dataset, "results.csv");
+}
+```
+
+## The `KernelTraits` trait class
+
+Some algorithms that use kernels can specialize if the kernel fulfills some
+certain conditions. An example of a condition might be that the kernel is
+shift-invariant or that the kernel is normalized. In the case of fast
+max-kernel search (`mlpack::fastmks::FastMKS`), the computation can be
+accelerated if the kernel is normalized. For this reason, the `KernelTraits`
+trait class exists. This allows a kernel to specify via a `const static bool`
+when these types of conditions are satisfied. *Note that a KernelTraits class
+is not required,* but may be helpful.
+
+The `KernelTraits` trait class is a template class that takes a `KernelType` as
+a parameter, and exposes `const static bool` values that depend on the kernel.
+Setting these values is achieved by specialization. The code below provides an
+example, specializing `KernelTraits` for the `ExampleKernel` from earlier:
+
+```c++
+template<>
+class KernelTraits
+{
+ public:
+ //! The example kernel is normalized (K(x, x) = 1 for all x).
+ const static bool IsNormalized = true;
+};
+```
+
+At this time, there is only one kernel trait that is used in mlpack code:
+
+ - `IsNormalized` (defaults to `false`): if `K(x, x) = 1` for all `x`,
+ then the kernel is normalized and this should be set to `true`.
+
+## List of kernels and classes that use a `KernelType`
+
+mlpack comes with a number of pre-written kernels that satisfy the `KernelType`
+policy:
+
+ - `mlpack::kernel::LinearKernel`
+ - `mlpack::kernel::ExampleKernel` -- an example kernel with more documentation
+ - `mlpack::kernel::GaussianKernel`
+ - `mlpack::kernel::HyperbolicTangentKernel`
+ - `mlpack::kernel::EpanechnikovKernel`
+ - `mlpack::kernel::CosineDistance`
+ - `mlpack::kernel::LaplacianKernel`
+ - `mlpack::kernel::PolynomialKernel`
+ - `mlpack::kernel::TriangularKernel`
+ - `mlpack::kernel::SphericalKernel`
+ - `mlpack::kernel::PSpectrumStringKernel` -- operates on strings, not vectors
+
+These kernels (or a custom kernel) may be used in a variety of mlpack methods:
+
+ - `mlpack::kpca::KernelPCA` - kernel principal components analysis
+ - `mlpack::fastmks::FastMKS` - fast max-kernel search
+ - `mlpack::kernel::NystroemMethod` - the Nystroem method for sampling
+ - `mlpack::metric::IPMetric` - a metric built on a kernel
diff --git a/doc/policies/metrics.hpp b/doc/developer/metrics.md
similarity index 57%
rename from doc/policies/metrics.hpp
rename to doc/developer/metrics.md
index a2f290d01c..772031780e 100644
--- a/doc/policies/metrics.hpp
+++ b/doc/developer/metrics.md
@@ -1,4 +1,4 @@
-/*! @page metrics The MetricType policy in mlpack
+# The MetricType policy in mlpack
Many machine learning methods operate with some sort of metric, and often, this
metric can be any arbitrary metric. For instance, consider the problem of
@@ -8,38 +8,37 @@ distance. The actual search techniques, though, remain the same. And this is
true of many machine learning methods: the specific metric that is used can be
any valid metric.
-mlpack algorithms, when possible, allow the use of an arbitrary metric via the
-use of the \c MetricType template parameter. Any metric passed as a
-\c MetricType template parameter will need to have
+mlpack algorithms, when relevant, allow the use of an arbitrary metric via the
+use of the `MetricType` template parameter. Any metric passed as a `MetricType`
+template parameter will need to have
- - an \c Evaluate function
+ - an `Evaluate()` function
- a default constructor.
-The signature of the \c Evaluate function is straightforward:
+The signature of the `Evaluate()` function is straightforward:
-@code
+```c++
template
double Evaluate(const VecTypeA& a, const VecTypeB& b);
-@endcode
+```
-The function takes two vector arguments, \c a and \c b, and returns a \c double
+The function takes two vector arguments, `a` and `b`, and returns a `double`
that is the evaluation of the metric between the two arguments. So, for a
-particular metric \f$d(\cdot, \cdot)\f$, the \c Evaluate() function should
-return \f$d(a, b)\f$.
+particular metric `d`, the `Evaluate()` function should return `d(a, b)`.
-The arguments \c a and \c b, of types \c VecTypeA and \c VecTypeB, respectively,
-will be an Armadillo-like vector type (usually \c arma::vec, \c arma::sp_vec, or
-similar). In general it should be valid to assume that \c VecTypeA is a class
-with the same API as \c arma::vec.
+The arguments `a` and `b`, of types `VecTypeA` and `VecTypeB`, respectively,
+will be an Armadillo-like vector type (usually `arma::vec`, `arma::sp_vec`, or
+similar). In general it should be valid to assume that `VecTypeA` is a class
+with the same API as `arma::vec`.
-Note that for metrics that do not hold any state, the \c Evaluate() method can
-be marked as \c static.
+Note that for metrics that do not hold any state, the `Evaluate()` method can
+be marked as `static`.
-Overall, the \c MetricType template policy is quite simple (much like the
-\ref kernels KernelType policy). Below is an example metric class, which
+Overall, the `MetricType` template policy is quite simple (much like the
+[KernelType policy](kerneltype.md)). Below is an example metric class, which
implements the L2 distance:
-@code
+```c++
class ExampleMetric
{
// Default constructor is required.
@@ -54,19 +53,18 @@ class ExampleMetric
return arma::norm(a - b);
}
};
-@endcode
+```
Then, this metric can easily be used inside of other mlpack algorithms. For
example, the code below runs range search on a random dataset with the
-\c ExampleKernel, by instantiating a \c mlpack::range::RangeSearch object that
-uses the \c ExampleKernel. Then, the number of results are printed. The \c
-RangeSearch class takes three template parameters: \c MetricType, \c MatType,
-and \c TreeType. (All three have defaults, so we will just leave \c MatType and
-\c TreeType to their defaults.)
+`ExampleKernel`, by instantiating a `mlpack::range::RangeSearch` object that
+uses the `ExampleKernel`. Then, the number of results are printed. The
+`RangeSearch` class takes three template parameters: `MetricType`, `MatType`,
+and `TreeType`. (All three have defaults, so we will just leave `MatType` and
+`TreeType` to their defaults.)
-@code
-#include
-#include
+```c++
+#include
#include "example_metric.hpp" // A file that contains ExampleKernel.
using namespace mlpack;
@@ -98,16 +96,14 @@ int main()
cout << neighbors[0].size() << " points within the range [1.0, 2.0] of the "
<< "query point!" << endl;
}
-@endcode
+```
-mlpack comes with a number of pre-written metrics that satisfy the \c MetricType
+mlpack comes with a number of pre-written metrics that satisfy the `MetricType`
policy:
- - mlpack::metric::ManhattanDistance
- - mlpack::metric::EuclideanDistance
- - mlpack::metric::ChebyshevDistance
- - mlpack::metric::MahalanobisDistance
- - mlpack::metric::LMetric (for arbitrary L-metrics)
- - mlpack::metric::IPMetric (requires a \ref kernels "KernelType" parameter)
-
-*/
+ - `mlpack::metric::ManhattanDistance`
+ - `mlpack::metric::EuclideanDistance`
+ - `mlpack::metric::ChebyshevDistance`
+ - `mlpack::metric::MahalanobisDistance`
+ - `mlpack::metric::LMetric` (for arbitrary L-metrics)
+ - `mlpack::metric::IPMetric` (requires a [KernelType](kerneltype.md) parameter)
diff --git a/doc/developer/timer.md b/doc/developer/timer.md
new file mode 100644
index 0000000000..a8751bad33
--- /dev/null
+++ b/doc/developer/timer.md
@@ -0,0 +1,68 @@
+# mlpack Timers
+
+mlpack provides a simple timer interface for the timing of machine learning
+methods. The results of any timers used during the program are displayed at
+output by any command-line binding, when `--verbose` is given:
+
+```sh
+$ mlpack_knn -r dataset.csv -n neighbors_out.csv -d distances_out.csv -k 5 -v
+<...>
+[INFO ] Program timers:
+[INFO ] computing_neighbors: 0.010650s
+[INFO ] loading_data: 0.002567s
+[INFO ] saving_data: 0.001115s
+[INFO ] total_time: 0.149816s
+[INFO ] tree_building: 0.000534s
+```
+
+## Timer API
+
+In C++, the `mlpack::Timers` class can be used to add timers to a program. The
+`mlpack::Timers` class provides three simple methods:
+
+```c++
+void Timer::Start(const char* name);
+void Timer::Stop(const char* name);
+timeval Timer::Get(const char* name);
+```
+
+Every binding is called with an `mlpack::Timers&`, which can be used in the body
+of that binding. For the sake of this discussion, let us call that object
+`timers`.
+
+Each timer is given a name, and is referenced by that name. You can call
+`timers.Start()` and `timers.Stop()` multiple times for a particular timer name,
+and the result will be the sum of the runs of the timer. Note that
+`timers.Stop()` must be called before `timers.Start()` is called again,
+otherwise a `std::runtime_error` exception will be thrown.
+
+A `"total_time"` timer is run automatically for each mlpack binding.
+
+## Timer Example
+
+Below is a very simple example of timer usage in code.
+
+```c++
+#include
+#include
+#define BINDING_TYPE BINDING_TYPE_CLI
+#include
+
+using namespace mlpack;
+
+void BINDING_FUNCTION(util::Params& params, util::Timers& timers)
+{
+ // Start a timer.
+ timers.Start("some_timer");
+
+ // Do some things.
+ DoSomeStuff();
+
+ // Stop the timer.
+ timers.Stop("some_timer");
+}
+@endcode
+
+If the `verbose` flag was given to this binding, then a command-line binding
+would print the time that `"some_timer"` ran for at the end of the program's
+output.
diff --git a/doc/policies/trees.hpp b/doc/developer/trees.md
similarity index 61%
rename from doc/policies/trees.hpp
rename to doc/developer/trees.md
index 36a03e634a..807c61ed06 100644
--- a/doc/policies/trees.hpp
+++ b/doc/developer/trees.md
@@ -1,6 +1,4 @@
-/*! @page trees The TreeType policy in mlpack
-
-@section treeintro Introduction
+# The TreeType policy in mlpack
Trees are an important data structure in mlpack and are used in a number of the
machine learning algorithms that mlpack implements. Often, the use of trees can
@@ -8,58 +6,42 @@ allow significant acceleration of an algorithm; this is generally done by
pruning away large parts of the tree during computation.
Most mlpack algorithms that use trees are not tied to a specific tree but
-instead allow the user to choose a tree via the \c TreeType template parameter.
-Any tree passed as a \c TreeType template parameter will need to implement a
+instead allow the user to choose a tree via the `TreeType` template parameter.
+Any tree passed as a `TreeType` template parameter will need to implement a
certain set of functions. In addition, a tree may optionally specify some
-traits about itself with the \c TreeTraits trait class.
+traits about itself with the `TreeTraits` trait class.
This document aims to clarify the abstractions underlying mlpack trees, list and
-describe the required functionality of the \c TreeType policy, and point users
-towards existing types of trees. A table of contents is below:
-
- - \ref treeintro
- - \ref whatistree
- - \ref treetype_template_params
- - \ref treetype_api
- - \ref treetype_rigorous
- - \ref treetype_rigorous_template
- - \ref treetype_rigorous_constructor
- - \ref treetype_rigorous_basic
- - \ref treetype_rigorous_complex
- - \ref treetype_rigorous_serialization
- - \ref treetype_traits
- - \ref treetype_more
+describe the required functionality of the `TreeType` policy, and point users
+towards existing types of trees.
Although this document is long, there may still be errors and unclear areas. If
you are having trouble understanding anything, please get in touch on Github or
on the mailing list and someone will help you (and possibly update the
documentation afterwards).
-@section whatistree What is a tree?
+## What is a tree?
In mlpack, we assume that we have some sort of data matrix, which might be
-sparse or dense (that is, it could be of type \c arma::mat or \c arma::sp_mat,
+sparse or dense (that is, it could be of type `arma::mat` or `arma::sp_mat`,
or any variant that implements the Armadillo API). This data matrix corresponds
to a collection of points in some space (usually a Euclidean space). A tree is
a way of organizing this data matrix in a hierarchical manner---so, points that
are nearby should lie in similar nodes.
-We can rigorously define what a tree is, using the definition of **space tree**
+We can rigorously define what a tree is, using the definition of *space tree*
introduced in the following paper:
-@code
-@quote
+```c++
R.R. Curtin, W.B. March, P. Ram, D.V. Anderson, A.G. Gray, and C.L. Isbell Jr.,
"Tree-independent dual-tree algorithms," in Proceedings of the 30th
International Conference on Machine Learning (ICML '13), pp. 1435--1443, 2013.
-@endquote
-@endcode
+```
The definition is:
-A **space tree** on a dataset \f$ S \in \mathcal{R}^{N \times d} \f$ is an
-undirected, connected, acyclic, rooted simple graph with the following
-properties:
+A *space tree* on a dataset `S` in `R^(N x d)` is an undirected, connected,
+acyclic, rooted simple graph with the following properties:
- Each node (or vertex) holds a number of points (possibly zero) and is
connected to one parent node and a number of child nodes (possibly zero).
@@ -67,17 +49,16 @@ connected to one parent node and a number of child nodes (possibly zero).
- There is one node in every space tree with no parent; this is the root node
of the tree.
- - Each point in \f$S\f$ is contained in at least one node.
+ - Each point in `S` is contained in at least one node.
- - Each node corresponds to some subset of \f$\mathcal{R}^d\f$ that contains
-each point in the node and also the subsets that correspond to each child of the
-node.
+ - Each node corresponds to some subset of `R^d` that contains each point in the
+ node and also the subsets that correspond to each child of the node.
This is really a quite straightforward definition: a tree is hierarchical, and
each node corresponds to some region of the input space. Each node may have
some number of children, and may hold some number of points. However, there is
-an important terminology distinction to make: the term **points held by a node**
-has a different meaning than the term **descendant points held by a node**. The
+an important terminology distinction to make: the term *points held by a node*
+has a different meaning than the term *descendant points held by a node*. The
points held in a node are just that---points held only in the node. The
descendant points of a node are the combination of the points held in a node
with the points held in the node's children and the points held in the node's
@@ -89,37 +70,37 @@ Now, it's also important to note that a point does not *need* to hold any
children, and that a node *can* hold the same points as its children (or its
parent). Some types of trees do this. For instance, each node in the cover
tree holds only one point, and may have a child that holds the same point. As
-another example, the \f$kd\f$-tree holds its points only in the leaves (at the
+another example, the `kd`-tree holds its points only in the leaves (at the
bottom of the tree). More information on space trees can be found in either the
"Tree-independent dual-tree algorithms" paper or any of the related literature.
So there is a huge amount of possible variety in the types of trees that can
fall into the class of *space trees*. Therefore, it's important to treat them
-abstractly, and the \c TreeType policy allows us to do just that. All we need
+abstractly, and the `TreeType` policy allows us to do just that. All we need
to remember is that a node in a tree can be represented as the combination of
some points held in the node, some child nodes, and some geometric structure
that represents the space that all of the descendant points fall into (this is a
restatement of the fourth part of the definition).
-@section treetype_template_params Template parameters required by the TreeType policy
+## Template parameters required by the TreeType policy
Most everything in mlpack is decomposed into a series of configurable template
parameters, and trees are no exception. In order to ease usage of high-level
mlpack algorithms, each \c TreeType itself must be a template class taking three
parameters:
- - \c MetricType -- the underlying metric that the tree will be built on (see
-\ref metrics "the MetricType policy documentation")
- - \c StatisticType -- holds any auxiliary information that individual
+ - `MetricType` -- the underlying metric that the tree will be built on (see
+[the MetricType policy documentation](metrictype.md))
+ - `StatisticType` -- holds any auxiliary information that individual
algorithms may need
- - \c MatType -- the type of the matrix used to represent the data
+ - `MatType` -- the type of the matrix used to represent the data
The reason that these three template parameters are necessary is so that each
-\c TreeType can be used as a template template parameter, which can radically
+`TreeType` can be used as a template template parameter, which can radically
simplify the required syntax for instantiating mlpack algorithms. By using
template template parameters, a user needs only to write
-@code
+```c++
// The RangeSearch class takes a MetricType and a TreeType template parameter.
// This code instantiates RangeSearch with the ManhattanDistance and a
@@ -128,20 +109,20 @@ template template parameters, a user needs only to write
// This example ignores the constructor parameters, for the sake of simplicity.
RangeSearch rs(...);
-@endcode
+```
as opposed to the far more complicated alternative, where the user must specify
the values of each template parameter of the tree type:
-@code
+```c++
// This is a much worse alternative, where the user must specify the template
// arguments of their tree.
RangeSearch> rs(...);
-@endcode
+```
Unfortunately, the price to pay for this user convenience is that *every*
-\c TreeType must have three template parameters, and they must be in exactly
+`TreeType` must have three template parameters, and they must be in exactly
that order. Fortunately, there is an additional benefit: we are guaranteed that
the tree is built using the same metric as the method (that is, a user can't
specify different metric types to the algorithm and to the tree, which they can
@@ -149,24 +130,24 @@ without template template parameters).
There are two important notes about this:
- - Not every possible input of MetricType, StatisticType, and/or MatType
-necessarily need to be valid or work correctly for each type of tree. For
-instance, the QuadTree is limited to Euclidean metrics and will not work
-otherwise. Either compile-time static checks or detailed documentation can help
-keep users from using invalid combinations of template arguments.
+ - Not every possible input of `MetricType`, `StatisticType`, and/or `MatType`
+ necessarily need to be valid or work correctly for each type of tree. For
+ instance, the `QuadTree` is limited to Euclidean metrics and will not work
+ otherwise. Either compile-time static checks or detailed documentation can
+ help keep users from using invalid combinations of template arguments.
- Some types of trees have more template parameters than just these three. One
-example is the generalized binary space tree, where the bounding shape of each
-node is easily made into a fourth template parameter (the \c BinarySpaceTree
-class calls this the \c BoundType parameter), and the procedure used to split a
-node is easily made into a fifth template parameter (the \c BinarySpaceTree
-class calls this the \c SplitType parameter). However, the syntax of template
-template parameters *requires* that the class only has the correct number of
-template parameters---no more, no less. Fortunately, C++11 allows template
-typedefs, which can be used to provide partial specialization of template
-classes:
+ example is the generalized binary space tree, where the bounding shape of
+ each node is easily made into a fourth template parameter (the
+ `BinarySpaceTree` class calls this the `BoundType` parameter), and the
+ procedure used to split a node is easily made into a fifth template parameter
+ (the `BinarySpaceTree` class calls this the `SplitType` parameter). However,
+ the syntax of template template parameters *requires* that the class only has
+ the correct number of template parameters---no more, no less. Fortunately,
+ C++11 allows template typedefs, which can be used to provide partial
+ specialization of template classes:
-@code
+```c++
// This is the definition of the BinarySpaceTree class, which has five template
// parameters.
template
MeanSplit>;
-@endcode
+```
-Now, the \c MeanSplitKDTree class has only three template parameters and can be
-used as a \c TreeType policy class in various mlpack algorithms. Many types of
+Now, the `MeanSplitKDTree` class has only three template parameters and can be
+used as a `TreeType` policy class in various mlpack algorithms. Many types of
trees in mlpack have more than three template parameters and rely on template
-typedefs to provide simplified \c TreeType interfaces.
+typedefs to provide simplified `TreeType` interfaces.
-@section treetype_api The TreeType API
+## The TreeType API
As a result of the definition of *space tree* in the previous section, a
simplified API presents itself quite easily. However, more complex
functionality is often necessary in mlpack, so this leads to more functions
-being necessary for a class to satisfy the \c TreeType policy. Combining this
+being necessary for a class to satisfy the `TreeType` policy. Combining this
with the template parameters required for trees given in the previous section
-gives us the complete API required for a class implementing the \c TreeType
-policy. Below is the minimal set of functions required with minor
-documentation for each function. (More extensive documentation and explanation
-is given afterwards.)
+gives us the complete API required for a class implementing the `TreeType`
+policy. Below is the minimal set of functions required with minor documentation
+for each function. (More extensive documentation and explanation is given
+afterwards.)
-@code
+```c++
// The three template parameters will be supplied by the user, and are detailed
// in the previous section.
template
double Evaluate(const VecTypeA& a, const VecTypeB& b);
-@endcode
+```
-Note that this method is not necessarily static, so a \c MetricType object
-should be held internally and its \c Evaluate() method should be called whenever
-the distance between two points is required. **It is generally a bad idea to
-hardcode any distance calculation in your tree.** This will make the tree
-unable to generalize to arbitrary metrics. If your tree must depend on certain
+Note that this method is not necessarily static, so a `MetricType` object should
+be held internally and its `Evaluate()` method should be called whenever the
+distance between two points is required. *It is generally a bad idea to
+hardcode any distance calculation in your tree.* This will make the tree unable
+to generalize to arbitrary metrics. If your tree must depend on certain
assumptions holding about the metric (i.e. the metric is a Euclidean metric),
then make that clear in the documentation of the tree, so users do not try to
use the tree with an inappropriate metric.
-The second template parameter, \c StatisticType, is for auxiliary information
+The second template parameter, `StatisticType`, is for auxiliary information
that is required by certain algorithms. For instance, consider an algorithm
which repeatedly uses the variance of the descendant points of a node. It might
-be tempting to add a \c Variance() method to the required \c TreeType API, but
+be tempting to add a `Variance()` method to the required `TreeType` API, but
this quickly leads to code bloat (after all, the API already has quite enough
-functions as it is). Instead, it is better to create a \c StatisticType class
-which provides the \c Variance() method, and then call \c Stat().Variance() when
+functions as it is). Instead, it is better to create a `StatisticType` class
+which provides the `Variance()` method, and then call `Stat().Variance()` when
the variance is required. This also holds true for cached data members.
-Each node should have its own instance of a \c StatisticType class. The
-\c StatisticType must provide the following constructors:
+Each node should have its own instance of a `StatisticType` class. The
+`StatisticType` must provide the following constructors:
-@code
+```c++
// Default constructor required by the StatisticType policy.
StatisticType();
// This constructor is required by the StatisticType policy.
template
StatisticType(TreeType& node);
-@endcode
+```
-This constructor should be called with \c (*this) after the node is constructed
+This constructor should be called with `(*this)` after the node is constructed
(usually, this ends up being the last line in the constructor of a node).
-The last template parameter is the \c MatType parameter. This is generally
-\c arma::mat or \c arma::sp_mat, but could be any Armadillo type, including
-matrices that hold data points of different precisions (such as \c float or even
-\c int). It generally suffices to write \c MatType assuming that \c arma::mat
+The last template parameter is the `MatType` parameter. This is generally
+`arma::mat` or `arma::sp_mat`, but could be any Armadillo type, including
+matrices that hold data points of different precisions (such as `float` or even
+`int`). It generally suffices to write \c MatType assuming that `arma::mat`
will be used, since the vast majority of the time this will be what is used.
-@subsection treetype_rigorous_constructor Constructors and destructors
+### Constructors and destructors
-The \c TreeType API requires at least three constructors. Technically, it does
+The `TreeType` API requires at least three constructors. Technically, it does
not *require* a destructor, but almost certainly your tree class will be doing
some memory management internally and should have one (though not always).
The first two constructors are variations of the same idea:
-@code
+```c++
// This batch constructor does not modify the dataset, and builds the entire
// tree using a default-constructed MetricType.
ExampleTree(const MatType& data);
@@ -468,19 +443,19 @@ ExampleTree(const MatType& data);
// This batch constructor does not modify the dataset, and builds the entire
// tree using the given MetricType.
ExampleTree(const MatType& data, MetricType& metric);
-@endcode
+```
All that is required here is that a constructor is available that takes a
dataset and optionally an instantiated metric. If no metric is provided, then
-it should be assumed that the \c MetricType class has a default constructor and
+it should be assumed that the `MetricType` class has a default constructor and
a default-constructed metric should be used. The constructor *must* return a
valid, fully-constructed, ready-to-use tree that satisfies the definition
-of *space tree* that was \ref whatistree "given earlier".
+of *space tree* that was given earlier in the document.
-The third constructor requires the tree to be initializable from a \c
-cereal archive:
+The third constructor requires the tree to be initializable from a `cereal`
+archive:
-@code
+```c++
// Initialize the tree from a given cereal archive. SFINAE (the
// second argument) is necessary to ensure that the archive is loading, not
// saving.
@@ -488,81 +463,80 @@ template
ExampleTree(
Archive& ar,
const typename std::enable_if_c::type* = 0);
-@endcode
+```
This has implications on how the tree must be stored. In this case, the dataset
-is *not yet loaded* and therefore the tree **may be required to have
-ownership of the data matrix**. This means that realistically the most
+is *not yet loaded* and therefore the tree ***may be required to have
+ownership of the data matrix***. This means that realistically the most
reasonable way to represent the data matrix internally in a tree class is not
with a reference but instead with a pointer. If this is true, then a destructor
will be required:
-@code
+```c++
// Release any resources held by the tree.
~ExampleTree();
-@endcode
+```
and, if the data matrix is represented internally with a pointer, this
destructor will need to release the memory for the data matrix (in the case that
-the tree was created via \c cereal ).
+the tree was created via `cereal`).
Note that these constructors are not necessarily the only constructors that a
-\c TreeType implementation can provide. One important example of when more
+`TreeType` implementation can provide. One important example of when more
constructors are useful is when the tree rearranges points internally; this
might be desired for the sake of speed or memory optimization. But to do this
with the required constructors would necessarily incur a copy of the data
-matrix, because the user will pass a \c "const MatType&". One alternate
-solution is to provide a constructor which takes an rvalue reference to a
-\c MatType:
+matrix, because the user will pass a `const MatType&`. One alternate solution
+is to provide a constructor which takes an rvalue reference to a `MatType`:
-@code
+```c++
template
ExampleTree(MatType&& data);
-@endcode
+```
(and another overload that takes an instantiated metric), and then the user can
-use \c std::move() to build the tree without copying the data matrix, although
+use `std::move()` to build the tree without copying the data matrix, although
the data matrix will be modified:
-@code
+```c++
ExampleTree exTree(std::move(dataset));
-@endcode
+```
It is, of course, possible to add even more constructors if desired.
-@subsection treetype_rigorous_basic Basic tree functionality
+### Basic tree functionality
-The basic functionality of a class implementing the \c TreeType API is quite
+The basic functionality of a class implementing the `TreeType` API is quite
straightforward and intuitive.
-@code
+```c++
// Get the dataset that the tree is built on.
const MatType& Dataset();
-@endcode
+```
-This should return a \c const reference to the dataset the tree is built on.
-The fact that this function is required essentially means that each node in the
-tree must store a pointer to the dataset (this is not the only option, but it is
-the most obvious option).
+This should return a `const` reference to the dataset the tree is built on. The
+fact that this function is required essentially means that each node in the tree
+must store a pointer to the dataset (this is not the only option, but it is the
+most obvious option).
-@code
+```c++
// Get the metric that the tree is built with.
MetricType& Metric();
-@endcode
+```
Each node must also store an instantiated metric or a pointer to one (note that
-this is required even for metrics that have no state and have a \c static \c
-Evaluate() function).
+this is required even for metrics that have no state and have a `static`
+`Evaluate()` function).
-@code
+```c++
// Get/modify the StatisticType for this node.
StatisticType& Stat();
-@endcode
+```
-As discussed earlier, each node must hold a \c StatisticType; this is accessible
-through the \c Stat() function.
+As discussed earlier, each node must hold a `StatisticType`; this is accessible
+through the `Stat()` function.
-@code
+```c++
// Return the parent of the node, or NULL if this is the root.
ExampleTree* Parent();
@@ -585,63 +559,63 @@ ExampleTree& DescendantNode(const size_t i);
size_t NumDescendants();
// Return the index of the i'th descendant point of this node.
size_t Descendant(const size_t i);
-@endcode
+```
These functions are all fairly self-explanatory. Most algorithms will use the
-\c Parent(), \c Children(), \c NumChildren(), \c Point(), and \c NumPoints()
+`Parent()`, `Children()`, `NumChildren()`, `Point()`, and `NumPoints()`
functions, so care should be taken when implementing those functions to ensure
-they will be efficient. Note that \c Point() and \c Descendant() should return
+they will be efficient. Note that `Point()` and `Descendant()` should return
indices of points, so the actual points can be accessed by calling
-\c "Dataset().col(Point(i))" for some index \c i (or something similar).
+`Dataset().col(Point(i))` for some index `i` (or something similar).
-An important note about the \c Descendant() function is that each descendant
+An important note about the `Descendant()` function is that each descendant
point should be unique. So if a node holds the point with index 6 and it has
-one child that holds the points with indices 6 and 7, then \c NumDescendants()
+one child that holds the points with indices 6 and 7, then `NumDescendants()`
should return 2, not 3. The ordering in which the descendants are returned can
-be arbitrary; so, \c Descendant(0) can return 6 \b or 7, and \c Descendant(1)
+be arbitrary; so, `Descendant(0)` can return 6 *or* 7, and `Descendant(1)`
should return the other index.
-@code
+```c++
// Store the center of the bounding region of the node in the given vector.
void Center(arma::vec& center);
-@endcode
+```
-The last function, \c Center(), should calculate the center of the bounding
-shape and store it in the given vector. So, for instance, if the tree is a ball
-tree, then the center is simply the center of the ball. Algorithm writers would
-be wise to try and avoid the use of \c Center() if possible, since it will
+The last function, `Center()`, should calculate the center of the bounding shape
+and store it in the given vector. So, for instance, if the tree is a ball tree,
+then the center is simply the center of the ball. Algorithm writers would be
+wise to try and avoid the use of `Center()` if possible, since it will
necessarily cost a copy of a vector.
-@subsection treetype_rigorous_complex Complex tree functionality and bounds
+### Complex tree functionality and bounds
A node in a tree should also be able to calculate various distance-related
bounds; these are particularly useful in tree-based algorithms. Note that any
of these bounds does not necessarily need to be maximally tight; generally it is
more important that each bound can be easily calculated.
-Details on each bounding function that the \c TreeType API requires are given
+Details on each bounding function that the `TreeType` API requires are given
below.
-@code
+```c++
// Return the distance between the center of this node and the center of
// its parent.
double ParentDistance();
-@endcode
+```
Remember that each node corresponds to some region in the space that the dataset
lies in. For most tree types this shape is often something geometrically
simple: a ball, a cone, a hyperrectangle, a slice, or something similar. The
-\c ParentDistance() function should return the distance between the center of
+`ParentDistance()` function should return the distance between the center of
this node's region and the center of the parent node's region.
In practice this bound is often used in dual-tree (or single-tree) algorithms to
-place an easy \c MinDistance() (or \c MaxDistance() ) bound for a child node;
-the parent's \c MinDistance() (or \c MaxDistance() ) function is called and then
-adjusted with \c ParentDistance() to provide a possibly loose but efficient
-bound on what the result of \c MinDistance() (or \c MaxDistance() ) would be
-with the child.
+place an easy `MinDistance()` (or `MaxDistance()`) bound for a child node; the
+parent's `MinDistance()` (or `MaxDistance()`) function is called and then
+adjusted with `ParentDistance()` to provide a possibly loose but efficient bound
+on what the result of `MinDistance()` (or `MaxDistance()`) would be with the
+child.
-@code
+```c++
// Return an upper bound on the furthest possible distance between the
// center of the node and any point held in the node.
double FurthestPointDistance();
@@ -649,25 +623,25 @@ double FurthestPointDistance();
// Return an upper bound on the furthest possible distance between the
// center of the node and any descendant point of the node.
double FurthestDescendantDistance();
-@endcode
+```
It is often very useful to be able to bound the radius of a node, which is
-effectively what \c FurthestDescendantDistance() does. Often it is easiest to
+effectively what `FurthestDescendantDistance()` does. Often it is easiest to
simply calculate and cache the furthest descendant distance at tree construction
time. Some trees, such as the cover tree, are able to give guarantees that the
points held in the node will necessarily be closer than the descendant points;
-therefore, the \c FurthestPointDistance() function is also useful.
+therefore, the `FurthestPointDistance()` function is also useful.
-It is permissible to simply have \c FurthestPointDistance() return the result of
-\c FurthestDescendantDistance(), and that will still be a valid bound, but
-depending on the type of tree it may be possible to have \c
-FurthestPointDistance() return a tighter bound.
+It is permissible to simply have `FurthestPointDistance()` return the result of
+`FurthestDescendantDistance()`, and that will still be a valid bound, but
+depending on the type of tree it may be possible to have
+`FurthestPointDistance()` return a tighter bound.
-@code
+```c++
// Return a lower bound on the minimum distance between the center and any
// edge of the node's bounding shape.
double MinimumBoundDistance();
-@endcode
+```
This is, admittedly, a somewhat complex and weird quantity. It is one of the
less important bounding functions, so it is valid to simply return 0...
@@ -675,14 +649,14 @@ less important bounding functions, so it is valid to simply return 0...
The bound is a bound on the minimum distance between the center of the node and
any edge of the shape that bounds all of the descendants of the node. So, if
the bounding shape is a ball (as in a ball tree or a cover tree), then
-\c MinimumBoundDistance() should just return the radius of the ball. If the
+`MinimumBoundDistance()` should just return the radius of the ball. If the
bounding shape is a hypercube (as in a generalized octree), then
-\c MinimumBoundDistance() should return the side length divided by two. If the
+`MinimumBoundDistance()` should return the side length divided by two. If the
bounding shape is a hyperrectangle (as in a kd-tree or a spill tree), then
-\c MinimumBoundDistance() should return half the side length of the
+`MinimumBoundDistance()` should return half the side length of the
hyperrectangle's smallest side.
-@code
+```c++
// Return a lower bound on the minimum distance between the given point and
// the node.
template
@@ -707,7 +681,7 @@ math::Range RangeDistance(VecType& point);
// Return the combined results of MinDistance() and MaxDistance().
math::Range RangeDistance(ExampleTree& otherNode);
-@endcode
+```
These six functions are almost without a doubt the most important functionality
of a tree. Therefore, it is preferable that these methods be implemented as
@@ -718,14 +692,14 @@ work, and tighter bounds mean that more pruning is possible.
Of these six functions, there are only really two bounds that are desired here:
the *minimum distance* between a node and an object, and the *maximum distance*
-between a node and an object. The object may be either a vector (usually \c
-arma::vec ) or another tree node.
+between a node and an object. The object may be either a vector (usually
+`arma::vec`) or another tree node.
Consider the first case, where the object is a vector. The result of
-\c MinDistance() needs to be less than or equal to the true minimum distance,
+`MinDistance()` needs to be less than or equal to the true minimum distance,
which could be calculated as below:
-@code
+```c++
// We assume that we have a vector 'vec', and a tree node 'node'.
double trueMinDist = DBL_MAX;
for (size_t i = 0; i < node.NumDescendants(); ++i)
@@ -737,45 +711,31 @@ for (size_t i = 0; i < node.NumDescendants(); ++i)
}
// At the end of the loop, trueMinDist will hold the true minimum distance
// between 'vec' and any descendant point of 'node'.
-@endcode
+```
Often the bounding shape of a node will allow a quick calculation that will make
a reasonable bound. For instance, if the node's bounding shape is a ball with
-radius \c r and center \c ctr, the calculation is simply
-\c "(node.Metric().Evaluate(vec, ctr) - r)". Usually a good \c MinDistance() or
-\c MaxDistance() function will make only one call to the \c Evaluate() function
-of the metric.
+radius `r` and center `ctr`, the calculation is simply
+`(node.Metric().Evaluate(vec, ctr) - r)`. Usually a good `MinDistance()` or
+`MaxDistance()` function will make only one call to the `Evaluate()` function of
+the metric.
-The \c RangeDistance() function allows a way for both bounds to be calculated at
-once. It is possible to implement this as a call to \c MinDistance() followed
-by a call to \c MaxDistance(), but this may incur more metric \c Evaluate()
-calls than necessary. Often calculating both bounds at once can be more
-efficient and can be done with fewer \c Evaluate() calls than calling both
-\c MinDistance() and \c MaxDistance().
+The `RangeDistance()` function allows a way for both bounds to be calculated at
+once. It is possible to implement this as a call to `MinDistance()` followed by
+a call to `MaxDistance()`, but this may incur more metric `Evaluate()` calls
+than necessary. Often calculating both bounds at once can be more efficient and
+can be done with fewer `Evaluate()` calls than calling both `MinDistance()` and
+`MaxDistance()`.
-@subsection treetype_rigorous_serialization Serialization
+### Serialization
-The last two public functions that the \c TreeType API requires are related to
-serialization and printing.
+The last functions that the `TreeType` API requires are for serialization.
-@code
-// Return a string representation of the tree.
-std::string ToString() const;
-@endcode
-
-There are few restrictions on the precise way that the \c ToString() function
-should operate, but generally it should behave similarly to the \c ToString()
-function in other mlpack methods. Generally, a user will call \c ToString()
-when they want to inspect the object and see what it looks like. For a tree,
-printing the entire tree may be way more information than the user was
-expecting, so it may be a better option to print either only the node itself or
-the node plus one or two levels of children.
-
-@code
+```c++
// Serialize the tree (load from the given archive / save to the given
// archive, depending on its type).
template
-void serialize(Archive& ar);
+void serialize(Archive& ar, const unsigned int version);
protected:
// A default constructor; only meant to be used by cereal. This
@@ -785,38 +745,37 @@ ExampleTree();
// Friend access must be given for the default constructor.
friend class cereal::access;
-@endcode
+```
On the other hand, the specifics of the functionality required for the
-\c Serialize() function are somewhat more difficult. The \c Serialize()
-function will be called either when a tree is being saved to disk or loaded from
-disk. The \c cereal documentation is fairly comprehensive.
+`serialize()` function are somewhat more difficult. The `serialize()` function
+will be called either when a tree is being saved to disk or loaded from disk.
+The `cereal` documentation is fairly comprehensive.
-An important note is that it is very difficult to use references with
-\c cereal, because \c serialize() may be called at any time during
-the object's lifetime, and references cannot be re-seated. In general this will
-require the use of pointers, which then require manual memory management.
-Therefore, be careful that \c serialize() (and the tree's destructor) properly
-handle memory management!
+An important note is that it is very difficult to use references with `cereal`,
+because `serialize()` may be called at any time during the object's lifetime,
+and references cannot be re-seated. In general this will require the use of
+pointers, which then require manual memory management. Therefore, be careful
+that `serialize()` (and the tree's destructor) properly handle memory
+management!
-@section treetype_traits The TreeTraits trait class
+## The TreeTraits trait class
Some tree-based algorithms can specialize if the tree fulfills certain
conditions. For instance, if the regions represented by two sibling nodes
cannot overlap, an algorithm may be able to perform a simpler computation.
-Based on this reasoning, the \c TreeTraits trait class (much like the
-mlpack::kernel::KernelTraits class) exists in order to allow a tree to specify
-(via a \c const \c static \c bool) when these types of conditions are
-satisfied. **Note that a TreeTraits class is not required,** but may be
-helpful.
+Based on this reasoning, the `TreeTraits` trait class (much like the
+`mlpack::kernel::KernelTraits` class) exists in order to allow a tree to specify
+(via a `const static bool`) when these types of conditions are satisfied.
+***Note that a TreeTraits class is not required***, but may be helpful.
-The \c TreeTraits trait class is a template class that takes a \c TreeType as a
-parameter, and exposes \c const \c static \c bool values that depend on the
-tree. Setting these values is achieved by specialization. The code below shows
-the default \c TreeTraits values (these are the values that will be used if no
-specialization is provided for a given \c TreeType).
+The `TreeTraits` trait class is a template class that takes a `TreeType` as a
+parameter, and exposes `const static bool` values that depend on the tree.
+Setting these values is achieved by specialization. The code below shows the
+default `TreeTraits` values (these are the values that will be used if no
+specialization is provided for a given `TreeType`).
-@code
+```c++
template
class TreeTraits
{
@@ -838,14 +797,14 @@ class TreeTraits
// This is true if the tree always has only two children.
static const bool BinaryTree = false;
};
-@endcode
+```
-An example specialization for the \ref mlpack::tree::KDTree class is given
-below. Note that \ref mlpack::tree::KDTree is itself a template class (like
-every class satisfying the \c TreeType policy), so we are specializing to a
-template parameter.
+An example specialization for the `mlpack::tree::KDTree` class is given below.
+Note that `mlpack::tree::KDTree` is itself a template class (like every class
+satisfying the `TreeType` policy), so we are specializing to a template
+parameter.
-@code
+```c++
template
@@ -868,29 +827,28 @@ class TreeTraits>
// The tree is always binary.
static const bool BinaryTree = true;
};
-@endcode
+```
Currently, the traits available are each of the five detailed above. For more
-information, see the \ref mlpack::tree::TreeTraits documentation.
+information, see the `mlpack::tree::TreeTraits` source code for more
+documentation.
-@section treetype_more A list of trees in mlpack and more information
+## A list of trees in mlpack and more information
mlpack contains several ready-to-use implementations of trees that satisfy the
TreeType policy API:
- - mlpack::tree::KDTree
- - mlpack::tree::MeanSplitKDTree
- - mlpack::tree::BallTree
- - mlpack::tree::MeanSplitBallTree
- - mlpack::tree::RTree
- - mlpack::tree::RStarTree
- - mlpack::tree::StandardCoverTree
+ - `mlpack::tree::KDTree`
+ - `mlpack::tree::MeanSplitKDTree`
+ - `mlpack::tree::BallTree`
+ - `mlpack::tree::MeanSplitBallTree`
+ - `mlpack::tree::RTree`
+ - `mlpack::tree::RStarTree`
+ - `mlpack::tree::StandardCoverTree`
Often, these are template typedefs of more flexible tree classes:
- - mlpack::tree::BinarySpaceTree -- binary trees, such as the KD-tree and ball
+ - `mlpack::tree::BinarySpaceTree` -- binary trees, such as the KD-tree and ball
tree
- - mlpack::tree::RectangleTree -- the R tree and variants
- - mlpack::tree::CoverTree -- the cover tree and variants
-
-*/
+ - `mlpack::tree::RectangleTree` -- the R tree and variants
+ - `mlpack::tree::CoverTree` -- the cover tree and variants
diff --git a/doc/developer/version.md b/doc/developer/version.md
new file mode 100644
index 0000000000..c303f2a624
--- /dev/null
+++ b/doc/developer/version.md
@@ -0,0 +1,25 @@
+# mlpack versions in code
+
+mlpack provides a couple of convenience macros and functions to get the version
+of mlpack. More information (and straightforward code) can be found in
+`src/mlpack/core/util/version.hpp`.
+
+The following three macros provide major, minor, and patch versions of mlpack
+(i.e. for `mlpack-x.y.z`, `x` is the major version, `y` is the minor version,
+and `z` is the patch version):
+
+```c++
+MLPACK_VERSION_MAJOR
+MLPACK_VERSION_MINOR
+MLPACK_VERSION_PATCH
+```
+
+In addition, the function `mlpack::util::GetVersion()` returns the mlpack
+version as a string (for instance, `"mlpack 1.0.8"`).
+
+## mlpack command-line program versions
+
+Each mlpack command-line program supports the `--version` (or `-V`) option,
+which will print the version of mlpack used. If the version is not an official
+release but instead from git, the version will be `mlpack git` (and will have a
+git revision SHA appended to `git`).
diff --git a/doc/doxygen/extra-stylesheet.css b/doc/doxygen/extra-stylesheet.css
deleted file mode 100644
index a9f808272f..0000000000
--- a/doc/doxygen/extra-stylesheet.css
+++ /dev/null
@@ -1,7 +0,0 @@
-/* Additional CSS styles for the html output */
-
-/* Fix the size of inline formulas */
-img.formulaInl {
- vertical-align: middle;
- height: 15pt;
-}
diff --git a/doc/doxygen/footer.html b/doc/doxygen/footer.html
deleted file mode 100644
index 730f025aaa..0000000000
--- a/doc/doxygen/footer.html
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-