Merge remote-tracking branch 'origin/master' into negative-log-likelihood-numclasses

This commit is contained in:
Ryan Curtin
2020-12-15 20:38:56 -05:00
917 changed files with 41487 additions and 23332 deletions
+13 -51
View File
@@ -1,16 +1,10 @@
clone_depth: 10
environment:
BOOST_PROG_OPTION : "C:/projects/mlpack/\
boost_program_options-vc140.1.60.0.0/lib/native/address-model-64/lib/*.*"
BOOST_MATH : "C:/projects/mlpack/\
boost_math_c99-vc140.1.60.0.0/lib/native/address-model-64/lib/*.*"
BOOST_RANDOM : "C:/projects/mlpack/\
boost_random-vc140.1.60.0.0/lib/native/address-model-64/lib/*.*"
BOOST_SERIALIZATION : "C:/projects/mlpack/\
boost_serialization-vc140.1.60.0.0/lib/native/address-model-64/lib/*.*"
BOOST_UNIT_TEST : "C:/projects/mlpack/\
boost_unit_test_framework-vc140.1.60.0.0/lib/native/address-model-64/lib/*.*"
ARMADILLO_DOWNLOAD : "https://data.kurg.org/armadillo-8.400.0.tar.xz"
ARMADILLO_LIBRARY : "C:/projects/mlpack/armadillo-8.400.0/\
build/Debug/armadillo.lib"
@@ -22,50 +16,36 @@ environment:
JENKINS_DOC : "C:/projects/mlpack/dist/win-installer/jenkinsdoc.zip"
GIT_VERSION_FILE : "C:/projects/mlpack/src/mlpack/core/util/gitversion.hpp"
matrix:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
VSVER: Visual Studio 14 2015 Win64
MSBUILD: C:\Program Files (x86)\MSBuild\14.0\bin\MSBuild.exe
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
VSVER: Visual Studio 15 2017 Win64
MSBUILD: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\MSBuild.exe
# Currently, the VS2019 build seems to always time out. This seems to be an
# AppVeyor issue.
# - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
# VSVER: Visual Studio 16 2019
# MSBUILD: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\MSBuild.exe
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
VSVER: Visual Studio 16 2019
MSBUILD: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\MSBuild.exe
# We have removed the VS studio 15 2017 build since it is not possible to complete
# or finish the build due to the `compiler out of heap space issues`.
# Therefore, in the meanwhile, we are only doing the installation for VS 16 2019.
configuration: Release
os: Visual Studio 2015
os: Visual Studio 2019
install:
- ps: nuget install boost -o "${env:APPVEYOR_BUILD_FOLDER}" -Version 1.60.0
- ps: >
nuget install boost_unit_test_framework-vc140
-o "${env:APPVEYOR_BUILD_FOLDER}" -Version 1.60.0
- ps: >
nuget install boost_program_options-vc140
-o "${env:APPVEYOR_BUILD_FOLDER}" -Version 1.60.0
- ps: >
nuget install boost_random-vc140
-o "${env:APPVEYOR_BUILD_FOLDER}" -Version 1.60.0
- ps: >
nuget install boost_serialization-vc140
-o "${env:APPVEYOR_BUILD_FOLDER}" -Version 1.60.0
- ps: >
nuget install boost_math_c99-vc140
-o "${env:APPVEYOR_BUILD_FOLDER}" -Version 1.60.0
- ps: >
nuget install unofficial-flayan-cereal
-o "${env:APPVEYOR_BUILD_FOLDER}"
- ps: nuget install OpenBLAS -o "${env:APPVEYOR_BUILD_FOLDER}"
- set path=C:\Program Files (x86)\WiX Toolset v3.11\bin;%path%
build_script:
- mkdir boost_libs
- ps: cp ${env:BOOST_PROG_OPTION} C:\projects\mlpack\boost_libs\
- ps: cp ${env:BOOST_MATH} C:\projects\mlpack\boost_libs\
- ps: cp ${env:BOOST_RANDOM} C:\projects\mlpack\boost_libs\
- ps: cp ${env:BOOST_SERIALIZATION} C:\projects\mlpack\boost_libs\
- ps: cp ${env:BOOST_UNIT_TEST} C:\projects\mlpack\boost_libs\
- echo TEST_ARMA is %ARMADILLO_DOWNLOAD%
- >
appveyor DownloadFile %ARMADILLO_DOWNLOAD%
@@ -89,12 +69,14 @@ build_script:
-DLAPACK_LIBRARIES:FILEPATH=%BLAS_LIBRARY%
-DARMADILLO_INCLUDE_DIR="C:/projects/mlpack/armadillo-8.400.0/include"
-DARMADILLO_LIBRARY:FILEPATH=%ARMADILLO_LIBRARY%
-DCEREAL_INCLUDE_DIR="C:/projects/mlpack/unofficial-flayan-cereal.1.2.2/build/native/include"
-DBOOST_INCLUDEDIR:PATH=%BOOST_INCLUDE%
-DBOOST_LIBRARYDIR:PATH="C:/projects/mlpack/boost_libs"
-DDEBUG=OFF
-DPROFILE=OFF
-DBUILD_PYTHON_BINDINGS=OFF
-DBUILD_GO_BINDINGS=OFF
-DBUILD_R_BINDINGS=OFF
-DBUILD_TESTS=OFF
-DCMAKE_BUILD_TYPE=Release ..
- >
"%MSBUILD%" "C:\projects\mlpack\build\mlpack.sln"
@@ -138,9 +120,6 @@ build_script:
- ps: >
cp C:\projects\mlpack\OpenBLAS.0.2.14.1\lib\native\bin\x64\*.dll
C:\projects\mlpack\dist\win-installer\staging\
- ps: >
cp C:\projects\mlpack\boost_libs\boost_unit_test_framework-vc*.dll
C:\projects\mlpack\dist\win-installer\staging\
- ps: >
cp C:\projects\mlpack\build\include\mlpack
C:\projects\mlpack\dist\win-installer\staging -recurse
@@ -238,20 +217,3 @@ cache:
- packages -> **\packages.config
- armadillo.tar.xz -> appveyor.yaml
test_script:
# Copy all DLLs into the right place before running the test.
- ps: cp C:\projects\mlpack\boost_libs\*.* C:\projects\mlpack\build\
- ps: >
cp C:\projects\mlpack\OpenBLAS.0.2.14.1\lib\native\bin\x64\*.*
C:\projects\mlpack\build\
- cd "%APPVEYOR_BUILD_FOLDER%/build/"
- >
Release\mlpack_test.exe
--report_level=detailed
--log_level=test_suite --log_format=XML > mlpack_test.xml & exit 0
# Attempt to upload results to AppVeyor.
- ps: >
$wc = New-Object 'System.Net.WebClient';
$wc.UploadFile(
"https://ci.appveyor.com/api/testresults/xunit/$($env:APPVEYOR_JOB_ID)",
(Resolve-Path .\mlpack_test.xml));
+15 -31
View File
@@ -15,18 +15,20 @@ jobs:
strategy:
matrix:
Plain:
CMakeArgs: '-DDEBUG=ON -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=OFF -DBUILD_GO_BINDINGS=OFF'
CMakeArgs: '-DDEBUG=ON -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=OFF -DBUILD_GO_BINDINGS=OFF -DBUILD_R_BINDINGS=OFF'
Python:
binding: 'python'
python.version: '3.7'
CMakeArgs: '-DDEBUG=OFF -DPROFILE=OFF -DPYTHON_EXECUTABLE=/opt/hostedtoolcache/Python/3.7.7/x64/bin/python3 -DBUILD_GO_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=OFF'
CMakeArgs: '-DDEBUG=OFF -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=ON -DPYTHON_EXECUTABLE=/usr/bin/python3 -DBUILD_GO_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=OFF -DBUILD_R_BINDINGS=OFF'
Julia:
julia.version: '1.3.0'
CMakeArgs: '-DDEBUG=OFF -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=ON -DBUILD_GO_BINDINGS=OFF -DJULIA_EXECUTABLE=/opt/julia-1.3.0/bin/julia'
CMakeArgs: '-DDEBUG=OFF -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=ON -DBUILD_GO_BINDINGS=OFF -DJULIA_EXECUTABLE=/opt/julia-1.3.0/bin/julia -DBUILD_R_BINDINGS=OFF'
Go:
binding: 'go'
go.version: '1.11.0'
CMakeArgs: '-DDEBUG=OFF -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=OFF -DBUILD_GO_BINDINGS=ON'
CMakeArgs: '-DDEBUG=OFF -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=OFF -DBUILD_GO_BINDINGS=ON -DBUILD_R_BINDINGS=OFF'
Markdown:
CMakeArgs: '-DDEBUG=OFF -DPROFILE=OFF -DBUILD_MARKDOWN_BINDINGS=ON -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_GO_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=OFF'
CMakeArgs: '-DDEBUG=OFF -DPROFILE=OFF -DBUILD_MARKDOWN_BINDINGS=ON -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_GO_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=OFF -DBUILD_R_BINDINGS=OFF'
steps:
- template: linux-steps.yaml
@@ -34,47 +36,29 @@ jobs:
- job: macOS
timeoutInMinutes: 360
pool:
vmImage: macOS-10.14
vmImage: macOS-latest
strategy:
matrix:
Plain:
CMakeArgs: '-DDEBUG=ON -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=OFF -DBUILD_GO_BINDINGS=OFF'
CMakeArgs: '-DDEBUG=ON -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=OFF -DBUILD_GO_BINDINGS=OFF -DBUILD_R_BINDINGS=OFF'
python.version: '2.7'
Python:
binding: 'python'
python.version: '3.7'
CMakeArgs: '-DDEBUG=OFF -DPROFILE=OFF -DBUILD_JULIA_BINDINGS=OFF -DBUILD_GO_BINDINGS=OFF'
CMakeArgs: '-DDEBUG=ON -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=ON -DBUILD_JULIA_BINDINGS=OFF -DBUILD_GO_BINDINGS=OFF -DBUILD_R_BINDINGS=OFF'
Julia:
python.version: '2.7'
julia.version: '1.3.0'
CMakeArgs: '-DDEBUG=OFF -DPROFILE=OFF -DBUILD_JULIA_BINDINGS=ON -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_GO_BINDINGS=OFF'
CMakeArgs: '-DDEBUG=ON -DPROFILE=OFF -DBUILD_JULIA_BINDINGS=ON -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_GO_BINDINGS=OFF -DBUILD_R_BINDINGS=OFF'
Go:
binding: 'go'
python.version: '2.7'
go.version: '1.11.0'
CMakeArgs: '-DDEBUG=OFF -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=OFF -DBUILD_GO_BINDINGS=ON'
CMakeArgs: '-DDEBUG=ON -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=OFF -DBUILD_GO_BINDINGS=ON -DBUILD_R_BINDINGS=OFF'
steps:
- template: macos-steps.yaml
- job: WindowsVS15
timeoutInMinutes: 360
displayName: Windows VS15
pool:
vmImage: vs2017-win2016
strategy:
matrix:
Plain:
CMakeArgs: '-DDEBUG=ON -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_GO_BINDINGS=OFF'
python.version: '2.7'
CMakeGenerator: '-G "Visual Studio 15 2017 Win64"'
MSBuildVersion: '15.0'
ArchiveNoLibs: 'mlpack-windows-vs15-no-libs.zip'
ArchiveLibs: 'mlpack-windows-vs15.zip'
ArchiveTests: 'mlpack_test-vs15.xml'
steps:
- template: windows-steps.yaml
- job: WindowsVS16
timeoutInMinutes: 360
displayName: Windows VS16
@@ -83,7 +67,7 @@ jobs:
strategy:
matrix:
Plain:
CMakeArgs: '-DDEBUG=ON -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_GO_BINDINGS=OFF'
CMakeArgs: '-DDEBUG=ON -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_GO_BINDINGS=OFF -DBUILD_R_BINDINGS=OFF'
python.version: '2.7'
CMakeGenerator: '-G "Visual Studio 16 2019"'
MSBuildVersion: '16.0'
+18 -11
View File
@@ -22,14 +22,14 @@ steps:
echo "##vso[task.setvariable variable=BOOST_ROOT]"$BOOST_ROOT
sudo apt-get install -y --allow-unauthenticated libopenblas-dev liblapack-dev g++ libboost1.70-dev libarmadillo-dev xz-utils
sudo apt-get install -y --allow-unauthenticated python3-pip python3-numpy
if [ "$(binding)" == "python" ]; then
export PYBIN=$(which python)
$PYBIN -m pip install --upgrade pip
$PYBIN -m pip install --upgrade --ignore-installed setuptools cython pandas
fi
sudo /opt/hostedtoolcache/Python/3.7.7/x64/bin/python3 -m pip install "Cython>0.24"
sudo /opt/hostedtoolcache/Python/3.7.7/x64/bin/python3 -m pip install --upgrade --ignore-installed setuptools
sudo /opt/hostedtoolcache/Python/3.7.7/x64/bin/python3 -m pip install pandas
if [ 'a$(julia.version)' != 'a' ]; then
if [ "a$(julia.version)" != "a" ]; then
wget https://julialang-s3.julialang.org/bin/linux/x64/1.3/julia-1.3.0-linux-x86_64.tar.gz
sudo tar -C /opt/ -xvpf julia-1.3.0-linux-x86_64.tar.gz
fi
@@ -37,25 +37,32 @@ steps:
# Install armadillo.
curl https://data.kurg.org/armadillo-8.400.0.tar.xz | tar -xvJ && cd armadillo*
cmake . && make && sudo make install && cd ..
# Install cereal.
wget https://github.com/USCiLab/cereal/archive/v1.3.0.tar.gz
tar -xvzpf v1.3.0.tar.gz # Unpack into cereal-1.3.0/.
cd cereal-1.3.0/
displayName: 'Install Build Dependencies'
# Configure mlpack (CMake)
- script: |
unset BOOST_ROOT
mkdir build && cd build
export GOPATH=$PWD/src/mlpack/bindings/go
go get -u -t gonum.org/v1/gonum/...
cmake $(CMakeArgs) ..
if [ "$(binding)" == "go" ]; then
export GOPATH=$PWD/src/mlpack/bindings/go
go get -u -t gonum.org/v1/gonum/...
fi
cmake $(CMakeArgs) -DPYTHON_EXECUTABLE=`which python` -DCEREAL_INCLUDE_DIR=../cereal-1.3.0/include/ ..
displayName: 'CMake'
# Build mlpack
- script: cd build && make
condition: eq(variables['CMakeArgs'], '-DDEBUG=ON -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=OFF -DBUILD_GO_BINDINGS=OFF')
condition: eq(variables['CMakeArgs'], '-DDEBUG=ON -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=OFF -DBUILD_GO_BINDINGS=OFF -DBUILD_R_BINDINGS=OFF')
displayName: 'Build'
# Build mlpack
- script: cd build && make -j2
condition: ne(variables['CMakeArgs'], '-DDEBUG=ON -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=OFF -DBUILD_GO_BINDINGS=OFF')
condition: ne(variables['CMakeArgs'], '-DDEBUG=ON -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=OFF -DBUILD_GO_BINDINGS=OFF -DBUILD_R_BINDINGS=OFF')
displayName: 'Build'
# Run tests via ctest.
+17 -7
View File
@@ -12,10 +12,14 @@ steps:
# Install Build Dependencies
- script: |
set -e
sudo xcode-select --switch /Applications/Xcode_10.1.app/Contents/Developer
sudo xcode-select --switch /Applications/Xcode_12.2.app/Contents/Developer
unset BOOST_ROOT
pip install cython numpy pandas zipp configparser
brew install openblas armadillo boost
brew install openblas armadillo boost cereal
if [ "$(binding)" == "python" ]; then
pip install --upgrade pip
pip install cython numpy pandas zipp configparser
fi
if [ "a$(julia.version)" != "a" ]; then
brew cask install julia
@@ -28,10 +32,16 @@ steps:
- script: |
unset BOOST_ROOT
mkdir build && cd build
export GOPATH=$PWD/src/mlpack/bindings/go
go get -u -t gonum.org/v1/gonum/...
export PYPATH=$(which python)
cmake $(CMakeArgs) -DPYTHON_EXECUTABLE=$PYPATH ..
if [ "$(binding)" == "go" ]; then
export GOPATH=$PWD/src/mlpack/bindings/go
go get -u -t gonum.org/v1/gonum/...
fi
if [ "$(binding)" == "python" ]; then
export PYPATH=$(which python)
cmake $(CMakeArgs) -DPYTHON_EXECUTABLE=$PYPATH ..
else
cmake $(CMakeArgs) ..
fi
displayName: 'CMake'
# Build mlpack
+58 -8
View File
@@ -10,19 +10,14 @@ steps:
- powershell: |
nuget install OpenBLAS -o $(Agent.ToolsDirectory)
nuget install boost -o $(Agent.ToolsDirectory) -Version 1.60.0
nuget install boost_unit_test_framework-vc140 -o $(Agent.ToolsDirectory) -Version 1.60.0
nuget install boost_program_options-vc140 -o $(Agent.ToolsDirectory) -Version 1.60.0
nuget install boost_random-vc140 -o $(Agent.ToolsDirectory) -Version 1.60.0
nuget install boost_serialization-vc140 -o $(Agent.ToolsDirectory) -Version 1.60.0
nuget install boost_math_c99-vc140 -o $(Agent.ToolsDirectory) -Version 1.60.0
nuget install OpenBLAS -o $(Agent.ToolsDirectory)
nuget install unofficial-flayan-cereal -o $(Agent.ToolsDirectory)
mkdir -p $(Agent.ToolsDirectory)/boost_libs
cp $(Agent.ToolsDirectory)/boost_program_options-vc140.1.60.0.0/lib/native/address-model-64/lib/*.* $(Agent.ToolsDirectory)/boost_libs
cp $(Agent.ToolsDirectory)/boost_math_c99-vc140.1.60.0.0/lib/native/address-model-64/lib/*.* $(Agent.ToolsDirectory)/boost_libs
cp $(Agent.ToolsDirectory)/boost_random-vc140.1.60.0.0/lib/native/address-model-64/lib/*.* $(Agent.ToolsDirectory)/boost_libs
cp $(Agent.ToolsDirectory)/boost_serialization-vc140.1.60.0.0/lib/native/address-model-64/lib/*.* $(Agent.ToolsDirectory)/boost_libs
cp $(Agent.ToolsDirectory)/boost_unit_test_framework-vc140.1.60.0.0/lib/native/address-model-64/lib/*.* $(Agent.ToolsDirectory)/boost_libs
displayName: 'Fetch build dependencies'
# Configure armadillo
@@ -66,6 +61,7 @@ steps:
-DARMADILLO_LIBRARY="..\armadillo-8.400.0\Release\armadillo.lib" `
-DBOOST_INCLUDEDIR=$(Agent.ToolsDirectory)\boost.1.60.0.0\lib\native\include `
-DBOOST_LIBRARYDIR=$(Agent.ToolsDirectory)\boost_libs `
-DCEREAL_INCLUDE_DIR=$(Agent.ToolsDirectory)\unofficial-flayan-cereal.1.2.2\build\native\include `
-DBUILD_JULIA_BINDINGS=OFF `
-DCMAKE_BUILD_TYPE=Release ..
displayName: 'Configure mlpack'
@@ -78,7 +74,6 @@ steps:
msbuildVersion: $(MSBuildVersion)
configuration: 'Release'
msbuildArchitecture: 'x64'
msbuildArguments: /m /p:BuildInParallel=true
maximumCpuCount: false
clean: false
displayName: 'Build mlpack'
@@ -93,7 +88,7 @@ steps:
# Run tests via ctest.
- bash: |
cd build
CTEST_OUTPUT_ON_FAILURE=1 ctest -T Test -C Release .
CTEST_OUTPUT_ON_FAILURE=1 ctest -T Test -C Release . -j1
displayName: 'Run tests via ctest'
# Copy artifacts
@@ -121,6 +116,56 @@ steps:
replaceExistingArchive: true
displayName: 'Build artifacts'
# Build MSI installer.
- powershell: |
# Pull the documentation for the installer.
try {
$url = "http://ci.mlpack.org/job/mlpack%20-%20doxygen%20build/lastSuccessfulBuild/artifact/build/doc/html/*zip*/html.zip"
(new-object net.webclient).DownloadFile($url, 'dist\win-installer\jenkinsdoc.zip')
}
catch {
Write-Output "Unable to download precompiled Doxygen documentation from Jenkins!"
}
try {
(Add-Type -AssemblyName System.IO.Compression.FileSystem);
[System.IO.Compression.ZipFile]::ExtractToDirectory('dist\win-installer\jenkinsdoc.zip', 'dist\win-installer\mlpack-win-installer\Sources\doc')
}
catch{Write-Output "Unable to add doc to installer, skipping!"}
# Preparing installer staging.
mkdir dist\win-installer\mlpack-win-installer\Sources\lib
cp build\Release\*.lib dist\win-installer\mlpack-win-installer\Sources\lib\
cp build\Release\*.exp dist\win-installer\mlpack-win-installer\Sources\lib\
cp build\Release\*.dll dist\win-installer\mlpack-win-installer\Sources\
cp build\Release\*.exe dist\win-installer\mlpack-win-installer\Sources\
cp $(Agent.ToolsDirectory)\OpenBLAS.0.2.14.1\lib\native\bin\x64\*.dll dist\win-installer\mlpack-win-installer\Sources\
cp build\include\mlpack dist\win-installer\mlpack-win-installer\Sources -recurse
cp doc\examples dist\win-installer\mlpack-win-installer\Sources -recurse
cp src\mlpack\tests\data\german.csv dist\win-installer\mlpack-win-installer\Sources\examples\sample-ml-app\sample-ml-app\data\
# Check current git version or mlpack version.
$ver = (Get-Content "src\mlpack\core\util\version.hpp" | where {$_ -like "*MLPACK_VERSION*"});
$env:MLPACK_VERSION += $ver[0].substring($ver[0].length - 1, 1) + '.';
$env:MLPACK_VERSION += $ver[1].substring($ver[1].length - 1, 1) + '.';
$env:MLPACK_VERSION += $ver[2].substring($ver[2].length - 1, 1);
if (Test-Path "src/mlpack/core/util/gitversion.hpp")
{
$ver = (Get-Content "src/mlpack/core/util/gitversion.hpp");
$env:INSTALL_VERSION = $ver.Split('"')[1].Split(' ')[1];
}
else
{
$env:INSTALL_VERSION = $env:MLPACK_VERSION;
}
# Build the MSI installer.
cd dist\win-installer\mlpack-win-installer
& 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\MSBuild.exe' `
-t:rebuild `
-p:Configuration=Release `
-p:TreatWarningsAsErrors=True `
mlpack-win-installer.wixproj
displayName: 'Build MSI Windows installer'
# Publish artifacts to Azure Pipelines
- task: PublishBuildArtifacts@1
inputs:
@@ -137,6 +182,11 @@ steps:
pathtoPublish: 'build/Testing/'
artifactName: 'Tests'
displayName: 'Publish artifacts test results'
- task: PublishBuildArtifacts@1
inputs:
pathtoPublish: 'dist\win-installer\mlpack-win-installer\bin\Release\mlpack-windows.msi'
artifactName: mlpack-windows-installer
displayName: 'Publish Windows MSI installer'
# Publish test results to Azure Pipelines
- task: PublishTestResults@2
+146
View File
@@ -0,0 +1,146 @@
on:
workflow_dispatch:
push:
branches:
- master
pull_request:
branches:
- master
release:
types: [published, created, edited]
name: mlpack.mlpack
jobs:
jobR:
name: mlpack R tarball
if: ${{ github.repository == 'mlpack/mlpack' }}
runs-on: ubuntu-20.04
outputs:
r_bindings: ${{ steps.mlpack_version.outputs.mlpack_r_package }}
steps:
- uses: actions/checkout@v2
- name: Extract mlpack version
id: mlpack_version
run: |
MLPACK_VERSION_MAJOR=$(grep -i ".*#define MLPACK_VERSION_MAJOR.*" src/mlpack/core/util/version.hpp | grep -o "[0-9]*")
MLPACK_VERSION_MINOR=$(grep -i ".*#define MLPACK_VERSION_MINOR.*" src/mlpack/core/util/version.hpp | grep -o "[0-9]*")
MLPACK_VERSION_PATCH=$(grep -i ".*#define MLPACK_VERSION_PATCH.*" src/mlpack/core/util/version.hpp | grep -o "[0-9]*")
MLPACK_VERSION_VALUE=${MLPACK_VERSION_MAJOR}.${MLPACK_VERSION_MINOR}.${MLPACK_VERSION_PATCH}
echo ::set-output name=mlpack_r_package::$(echo mlpack_"$MLPACK_VERSION_VALUE".tar.gz)
- uses: r-lib/actions/setup-r@master
with:
r-version: release
- name: Query dependencies
run: |
cp src/mlpack/bindings/R/mlpack/DESCRIPTION.in DESCRIPTION
Rscript -e "install.packages('remotes')" -e "saveRDS(remotes::dev_package_deps(dependencies = TRUE), 'depends.Rds')"
- name: Cache R packages
if: runner.os != 'Windows'
uses: actions/cache@v1
with:
path: ${{ env.R_LIBS_USER }}
key: ${{ runner.os }}-r-release-${{ hashFiles('depends.Rds') }}
restore-keys: ${{ runner.os }}-r-release-
- name: Install Build Dependencies
run: |
sudo apt-get update
sudo apt-get install -y --allow-unauthenticated libopenblas-dev liblapack-dev g++ libboost-all-dev libcereal-dev
curl https://data.kurg.org/armadillo-8.400.0.tar.xz | tar -xvJ && cd armadillo*
cmake . && make && sudo make install && cd ..
- name: Install R-bindings dependencies
run: |
remotes::install_deps(dependencies = TRUE)
remotes::install_cran("roxygen2")
shell: Rscript {0}
- name: CMake
run: |
mkdir build
cd build && cmake -DDEBUG=OFF -DPROFILE=OFF -DBUILD_CLI_EXECUTABLES=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=OFF -DBUILD_GO_BINDINGS=OFF -DBUILD_R_BINDINGS=ON ..
- name: Build
run: |
cd build && make -j2
- name: Run tests via ctest
run: |
cd build && CTEST_OUTPUT_ON_FAILURE=1 ctest -T Test .
- name: Upload R packages
uses: actions/upload-artifact@v2
with:
name: mlpack_r_tarball
path: build/src/mlpack/bindings/R/${{ steps.mlpack_version.outputs.mlpack_r_package }}
R-CMD-check:
needs: jobR
runs-on: ${{ matrix.config.os }}
name: ${{ matrix.config.name }}
if: ${{ github.repository == 'mlpack/mlpack' }}
strategy:
fail-fast: false
matrix:
config:
- {os: windows-latest, r: '4.0', name: 'Windows R'}
- {os: macOS-latest, r: 'release', name: 'macOS R'}
- {os: ubuntu-20.04, r: 'devel', rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest", name: 'Linux R'}
env:
MAKEFLAGS: "-j 2"
R_BUILD_ARGS: "--no-build-vignettes"
R_CHECK_ARGS: "--no-build-vignettes"
_R_CHECK_FORCE_SUGGESTS: 0
R_REMOTES_NO_ERRORS_FROM_WARNINGS: true
RSPM: ${{ matrix.config.rspm }}
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/download-artifact@v2
with:
name: mlpack_r_tarball
- uses: r-lib/actions/setup-r@master
with:
r-version: ${{ matrix.config.r }}
- uses: r-lib/actions/setup-pandoc@master
- name: Query dependencies
run: Rscript -e "install.packages('remotes')" -e "saveRDS(remotes::dev_package_deps('${{ needs.jobR.outputs.r_bindings }}', dependencies = TRUE), 'depends.Rds')"
- name: Cache R packages
if: runner.os != 'Windows'
uses: actions/cache@v1
with:
path: ${{ env.R_LIBS_USER }}
key: ${{ runner.os }}-r-${{ matrix.config.r }}-${{ hashFiles('depends.Rds') }}
restore-keys: ${{ runner.os }}-r-${{ matrix.config.r }}-
- name: Install dependencies
run: |
remotes::install_deps('${{ needs.jobR.outputs.r_bindings }}', dependencies = TRUE)
remotes::install_cran("rcmdcheck")
shell: Rscript {0}
- name: Check
run: Rscript -e "rcmdcheck::rcmdcheck('${{ needs.jobR.outputs.r_bindings }}', args = c('--no-manual','--as-cran'), error_on = 'warning', check_dir = 'check')"
- name: Upload check results
if: failure()
uses: actions/upload-artifact@master
with:
name: ${{ runner.os }}-r${{ matrix.config.r }}-results
path: |
check/mlpack.Rcheck/00check.log
check/mlpack.Rcheck/00install.out
+49
View File
@@ -0,0 +1,49 @@
name: Update Catch
on:
workflow_dispatch:
schedule:
- cron: '0 10 1/16 * *'
jobs:
updateCatch:
if: ${{ github.repository == 'mlpack/mlpack' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Get Latest Catch Tagged Release
id: catch-header
run: |
# Ping version information upstream.
CATCH_RELEASE_JSON=$(curl -sL https://api.github.com/repos/catchorg/Catch2/releases/latest)
CATCH_RELEASE_VERSION=$(jq -r ".tag_name" <<< "$CATCH_RELEASE_JSON" | tr -d v)
echo ::set-output name=release_tag::$(echo $CATCH_RELEASE_VERSION)
# Extract out version information from git repository.
CATCH_VERSION_MAJOR=$(grep -i ".*#define CATCH_VERSION_MAJOR.*" src/mlpack/tests/catch.hpp | grep -o "[0-9]*")
CATCH_VERSION_MINOR=$(grep -i ".*#define CATCH_VERSION_MINOR.*" src/mlpack/tests/catch.hpp | grep -o "[0-9]*")
CATCH_VERSION_PATCH=$(grep -i ".*#define CATCH_VERSION_PATCH.*" src/mlpack/tests/catch.hpp | grep -o "[0-9]*")
# Combine values to match release tag information.
CATCH_VERSION_VALUE=${CATCH_VERSION_MAJOR}.${CATCH_VERSION_MINOR}.${CATCH_VERSION_PATCH}
# Set the current release tag.
echo ::set-output name=current_tag::$(echo $CATCH_VERSION_VALUE)
- name: Update Catch
if: steps.catch-header.outputs.current_tag != steps.catch-header.outputs.release_tag
env:
CURRENT_TAG: ${{ steps.catch-header.outputs.current_tag }}
RELEASE_TAG: ${{ steps.catch-header.outputs.release_tag }}
run: |
# Delete the catch.hpp.
rm -f src/mlpack/tests/catch.hpp
# Download the release.
curl -sL https://github.com/catchorg/Catch2/releases/latest/download/catch.hpp -o src/mlpack/tests/catch.hpp
- name: Create Pull Request For Catch
if: steps.catch-header.outputs.current_tag != steps.catch-header.outputs.release_tag
uses: peter-evans/create-pull-request@v3
with:
commit-message: Upgrade Catch to ${{ steps.catch-header.outputs.release_tag }}
title: Upgrade Catch to ${{ steps.catch-header.outputs.release_tag }}
body: |
Updates [catchorg/Catch2](https://github.com/catchorg/Catch2) to ${{ steps.catch-header.outputs.release_tag }}.
Auto-generated by [create-pull-request](https://github.com/peter-evans/create-pull-request).
labels: update dependencies, automated PR
branch: catch-header-updates-${{ steps.catch-header.outputs.release_tag }}
+45
View File
@@ -0,0 +1,45 @@
name: Update CLI11
on:
workflow_dispatch:
schedule:
- cron: '0 10 1/16 * *'
jobs:
updateCLI11:
if: ${{ github.repository == 'mlpack/mlpack' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Get Latest CLI11 Tagged Release
id: cli11-header
run: |
# Ping version information upstream.
CLI11_RELEASE_JSON=$(curl -sL https://api.github.com/repos/CLIUtils/CLI11/releases/latest)
CLI11_RELEASE_VERSION=$(jq -r ".tag_name" <<< "$CLI11_RELEASE_JSON" | tr -d v)
echo ::set-output name=release_tag::$(echo $CLI11_RELEASE_VERSION)
# Extract out version information from git repository.
CLI11_VERSION_VALUE=$(grep -i ".*#define CLI11_VERSION.*" src/mlpack/bindings/cli/third_party/CLI/CLI11.hpp | grep -Po "(\d+\.)+\d+")
# Set the current release tag.
echo ::set-output name=current_tag::$(echo $CLI11_VERSION_VALUE)
- name: Update CLI11
if: steps.cli11-header.outputs.current_tag != steps.cli11-header.outputs.release_tag
env:
CURRENT_TAG: ${{ steps.cli11-header.outputs.current_tag }}
RELEASE_TAG: ${{ steps.cli11-header.outputs.release_tag }}
run: |
# Delete the CLI11.hpp.
rm -f src/mlpack/bindings/cli/third_party/CLI/CLI11.hpp
# Download the release.
curl -sL https://github.com/CLIUtils/CLI11/releases/latest/download/CLI11.hpp -o src/mlpack/bindings/cli/third_party/CLI/CLI11.hpp
- name: Create Pull Request For CLI11
if: steps.cli11-header.outputs.current_tag != steps.cli11-header.outputs.release_tag
uses: peter-evans/create-pull-request@v3
with:
commit-message: Upgrade CLI11 to ${{ steps.cli11-header.outputs.release_tag }}
title: Upgrade CLI11 to ${{ steps.cli11-header.outputs.release_tag }}
body: |
Updates [CLIUtils/CLI11](https://github.com/CLIUtils/CLI11) to ${{ steps.cli11-header.outputs.release_tag }}.
Auto-generated by [create-pull-request](https://github.com/peter-evans/create-pull-request).
labels: update dependencies, automated PR
branch: cli11-header-updates-${{ steps.cli11-header.outputs.release_tag }}
@@ -1,4 +1,4 @@
# ConfigureGenerate.cmake: generate an mlpack binding file given input
# ConfigureFile.cmake: generate an mlpack binding file given input
# arguments.
#
# This file depends on the following variables being set:
+2 -2
View File
@@ -14,9 +14,9 @@ if (GO_EXECUTABLE)
RESULT_VARIABLE RESULT
)
if (RESULT EQUAL 0)
string(REGEX REPLACE ".*([0-9]+\\.[0-9]+\\.[0-9]+).*" "\\1"
string(REGEX REPLACE ".*([0-9]+\\.[0-9]+\(\\.[0-9]+\)?).*" "\\1"
GO_VERSION_STRING ${GO_VERSION_STRING})
endif()
endif()
endif()
include(FindPackageHandleStandardArgs)
+47
View File
@@ -0,0 +1,47 @@
# FindR.cmkae
# Make sure find package macros are included
set(TEMP_CMAKE_FIND_APPBUNDLE ${CMAKE_FIND_APPBUNDLE})
set(CMAKE_FIND_APPBUNDLE "NEVER")
# Find R.
find_program(R_EXECUTABLE R DOC "R executable.")
if(R_EXECUTABLE)
# Get the location of R.
execute_process(
WORKING_DIRECTORY .
COMMAND ${R_EXECUTABLE} RHOME
OUTPUT_VARIABLE R_BASE_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE
)
# Get the R version.
execute_process(
COMMAND ${R_EXECUTABLE} --version
OUTPUT_VARIABLE R_VERSION_STRING
RESULT_VARIABLE RESULT
)
if (RESULT EQUAL 0)
string(REGEX REPLACE ".*([0-9]+\\.[0-9]+\\.[0-9]+).*" "\\1"
R_VERSION_STRING ${R_VERSION_STRING})
endif ()
set(R_HOME ${R_BASE_DIR} CACHE PATH "R home directory obtained from R RHOME")
mark_as_advanced(R_HOME)
endif()
# Find the Rscript program.
find_program(RSCRIPT_EXECUTABLE Rscript DOC "Rscript executable.")
set(CMAKE_FIND_APPBUNDLE ${TEMP_CMAKE_FIND_APPBUNDLE})
mark_as_advanced(RSCRIPT_EXECUTABLE R_EXECUTABLE)
set( _REQUIRED_R_VARIABLES R_EXECUTABLE )
include( FindPackageHandleStandardArgs )
find_package_handle_standard_args(
R
REQUIRED_VARS ${_REQUIRED_R_VARIABLES}
VERSION_VAR R_VERSION_STRING
FAIL_MESSAGE "R not found"
)
+58
View File
@@ -0,0 +1,58 @@
# FindRModule.cmake: find a specific R module.
function(find_r_module module)
string(TOUPPER ${module} module_upper)
if (NOT R_${module_upper})
if (ARGC GREATER 1)
# Not required but we have version constraints.
set(VERSION_REQ ${ARGV1})
endif ()
# A module's location is usually a directory, but for binary modules
# it's a .so file.
execute_process(COMMAND ${RSCRIPT_EXECUTABLE} "-e" "find.package('${module}')"
RESULT_VARIABLE _${module}_status
OUTPUT_VARIABLE _${module}_location
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
# Some cleanup in location of R Module.
string(REGEX MATCHALL "\".*\"" _${module}_location "${_${module}_location}" )
string(REGEX REPLACE "\"" "" _${module}_location "${_${module}_location}" )
if (NOT _${module}_status)
# Now we have to check the version.
if (VERSION_REQ)
execute_process(COMMAND ${RSCRIPT_EXECUTABLE} "-e" "packageVersion('${module}')"
RESULT_VARIABLE _version_status
OUTPUT_VARIABLE _version_compare
OUTPUT_STRIP_TRAILING_WHITESPACE)
string(REGEX MATCHALL "[0-9._]*" _version_compare "${_version_compare}")
string(REGEX REPLACE "" "" _version_compare "${_version_compare}")
string(REGEX REPLACE "" "" _version_compare "${_version_compare}")
# Compare the version of the package using compareVersion().
execute_process(COMMAND ${RSCRIPT_EXECUTABLE} "-e"
"compareVersion('${_version_compare}', '${VERSION_REQ}')"
RESULT_VARIABLE _compareVersion_status
OUTPUT_VARIABLE _compareVersion_result
OUTPUT_STRIP_TRAILING_WHITESPACE)
# Extract compareVersion() result i.e. 1 -> Newer, 0 -> Equal and -1 -> Later.
string(REGEX REPLACE "\\[\\1\\]" "" _compareVersion_result "${_compareVersion_result}")
if ("${_compareVersion_result}" GREATER "-1")
set(R_${module_upper}
"${_${module}_location} (found suitable version \"${_version_compare}\", minimum required is \"${VERSION_REQ}\")"
CACHE STRING "Location of R module ${module}"
)
else ()
message(WARNING "Unsuitable version of R module ${module} (${VERSION_REQ} or greater required).")
endif ()
else ()
# No version requirement so we are done.
set(R_${module_upper} ${_${module}_location} CACHE STRING "Location of R module ${module}")
endif ()
endif ()
endif ()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(R_${module} DEFAULT_MSG R_${module_upper})
endfunction ()
+56
View File
@@ -0,0 +1,56 @@
#Findcereal.cmake
find_path(CEREAL_INCLUDE_DIR
NAMES cereal
PATHS "$ENV{ProgramFiles}/cereal/include"
)
if(CEREAL_INCLUDE_DIR)
# ------------------------------------------------------------------------
# Extract version information from <CEREAL>
# ------------------------------------------------------------------------
set(CEREAL_FOUND YES)
set(CEREAL_VERSION_MAJOR 0)
set(CEREAL_VERSION_MINOR 0)
set(CEREAL_VERSION_PATCH 0)
if(EXISTS "${CEREAL_INCLUDE_DIR}/cereal/version.hpp")
# Read and parse cereal version header file for version number
file(READ "${CEREAL_INCLUDE_DIR}/cereal/version.hpp"
_CEREAL_HEADER_CONTENTS)
string(REGEX REPLACE ".*#define CEREAL_VERSION_MAJOR ([0-9]+).*" "\\1"
CEREAL_VERSION_MAJOR "${_CEREAL_HEADER_CONTENTS}")
string(REGEX REPLACE ".*#define CEREAL_VERSION_MINOR ([0-9]+).*" "\\1"
CEREAL_VERSION_MINOR "${_CEREAL_HEADER_CONTENTS}")
string(REGEX REPLACE ".*#define CEREAL_VERSION_PATCH ([0-9]+).*" "\\1"
CEREAL_VERSION_PATCH "${_CEREAL_HEADER_CONTENTS}")
elseif(EXISTS "${CEREAL_INCLUDE_DIR}/cereal/details/polymorphic_impl_fwd.hpp")
set(CEREAL_VERSION_MAJOR 1)
set(CEREAL_VERSION_MINOR 2)
set(CEREAL_VERSION_PATCH 0)
elseif(EXISTS "${CEREAL_INCLUDE_DIR}/cereal/types/valarray.hpp")
set(CEREAL_VERSION_MAJOR 1)
set(CEREAL_VERSION_MINOR 1)
set(CEREAL_VERSION_PATCH 2)
elseif(EXISTS "${CEREAL_INCLUDE_DIR}/cereal/cereal.hpp")
set(CEREAL_VERSION_MAJOR 1)
set(CEREAL_VERSION_MINOR 1)
set(CEREAL_VERSION_PATCH 1)
else()
set(CEREAL_FOUND NO)
endif()
set(CEREAL_VERSION_STRING "${CEREAL_VERSION_MAJOR}.${CEREAL_VERSION_MINOR}.${CEREAL_VERSION_PATCH}")
endif ()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(cereal
REQUIRED_VARS CEREAL_INCLUDE_DIR
VERSION_VAR CEREAL_VERSION_STRING
)
mark_as_advanced(CEREAL_INCLUDE_DIR)
-13
View File
@@ -1,13 +0,0 @@
# GenerateGoBinding.cmake: a CMake script that actually runs the given program to
# generate an mlpack binding file.
#
# This script depends on the following arguments:
#
# GENERATE_H_PROGRAM: the program to run to generate the .h file.
# H_OUTPUT_FILE: the file to store the output in.
# GENERATE_GO_PROGRAM: the program to run to generate the .go file.
# GO_OUTPUT_FILE: the file to store the output in.
# GENERATE_CPP_PROGRAM: the program to run to generate the .cpp file.
# CPP_OUTPUT_FILE: the file to store the output in.
execute_process(COMMAND ${GENERATE_BINDING_PROGRAM}
OUTPUT_FILE ${BINDING_OUTPUT_FILE})
+56
View File
@@ -0,0 +1,56 @@
# AppendSerialization.cmake: append imports for serialization and
# deserialization for mlpack model types to the existing list of serialization
# and deserialization imports.
# This function depends on the following variables being set:
#
# * PROGRAM_MAIN_FILE: the file containing the mlpackMain() function.
# * SERIALIZATION_FILE: file to append types to
# * SERIALIZE: It is of bool type. If SERIALIZE is true we have to print
# Serialize, else Deserialize.
#
function(append_serialization SERIALIZATION_FILE PROGRAM_MAIN_FILE SERIALIZE)
include("${CMAKE_SOURCE_DIR}/CMake/StripType.cmake")
strip_type("${PROGRAM_MAIN_FILE}")
list(LENGTH MODEL_TYPES NUM_MODEL_TYPES)
if (${NUM_MODEL_TYPES} GREATER 0)
math(EXPR LOOP_MAX "${NUM_MODEL_TYPES}-1")
foreach (INDEX RANGE ${LOOP_MAX})
list(GET MODEL_TYPES ${INDEX} MODEL_TYPE)
list(GET MODEL_SAFE_TYPES ${INDEX} MODEL_SAFE_TYPE)
file(READ "${SERIALIZATION_FILE}" SERIALIZATION_FILE_CONTENTS)
if (SERIALIZE)
# See if the model type already exists.
string(FIND
"${SERIALIZATION_FILE_CONTENTS}"
"\"${MODEL_SAFE_TYPE}\" = Serialize${MODEL_SAFE_TYPE}Ptr,"
FIND_OUT)
# If it doesn't exist, append it.
if (${FIND_OUT} EQUAL -1)
# Now append the type to the list of types, and define any serialization
# function.
file(APPEND
"${SERIALIZATION_FILE}"
" \"${MODEL_SAFE_TYPE}\" = Serialize${MODEL_SAFE_TYPE}Ptr,\n")
endif()
elseif (NOT SERIALIZE)
# See if the model type already exists.
string(FIND
"${SERIALIZATION_FILE_CONTENTS}"
"\"${MODEL_SAFE_TYPE}\" = Deserialize${MODEL_SAFE_TYPE}Ptr,"
FIND_OUT)
# If it doesn't exist, append it.
if (${FIND_OUT} EQUAL -1)
# Now append the type to the list of types, and define any deserialization
# function.
file(APPEND
"${SERIALIZATION_FILE}"
" \"${MODEL_SAFE_TYPE}\" = Deserialize${MODEL_SAFE_TYPE}Ptr,\n")
endif()
endif()
endforeach ()
endif()
endfunction()
+92
View File
@@ -0,0 +1,92 @@
# ConfigureRCPP.cmake: generate an mlpack .cpp file for a R binding given
# input arguments.
#
# This file depends on the following variables being set:
#
# * PROGRAM_NAME: name of the binding
# * PROGRAM_MAIN_FILE: the file containing the mlpackMain() function.
# * R_CPP_IN: path of the r_method.cpp.in file.
# * R_CPP_OUT: name of the output .cpp file.
include("${SOURCE_DIR}/CMake/StripType.cmake")
strip_type("${PROGRAM_MAIN_FILE}")
# Extract the required part from *main.cpp.
# Example: mlpack/methods/adaboost/adaboost_main.cpp
string(REGEX REPLACE "${SOURCE_DIR}\\/src\\/" "" INCLUDE_FILE
"${PROGRAM_MAIN_FILE}")
file(READ "${MODEL_FILE}" MODEL_FILE_TYPE)
if (NOT (MODEL_FILE_TYPE MATCHES "\"${MODEL_SAFE_TYPES}\""))
file(APPEND "${MODEL_FILE}" "\"${MODEL_SAFE_TYPES}\"\n")
# Now, generate the implementation of the functions we need.
set(MODEL_PTR_IMPLS "")
list(LENGTH MODEL_TYPES NUM_MODEL_TYPES)
# Append content to the list.
if (${NUM_MODEL_TYPES} GREATER 0)
math(EXPR LOOP_MAX "${NUM_MODEL_TYPES}-1")
foreach (INDEX RANGE ${LOOP_MAX})
list(GET MODEL_TYPES ${INDEX} MODEL_TYPE)
list(GET MODEL_SAFE_TYPES ${INDEX} MODEL_SAFE_TYPE)
# Define typedef for the model.
set(MODEL_PTR_TYPEDEF "${MODEL_PTR_TYPEDEF}Rcpp::XPtr<${MODEL_TYPE}>")
# Generate the implementation.
set(MODEL_PTR_IMPLS "${MODEL_PTR_IMPLS}
// Get the pointer to a ${MODEL_TYPE} parameter.
// [[Rcpp::export]]
SEXP IO_GetParam${MODEL_SAFE_TYPE}Ptr(const std::string& paramName)
{
return std::move((${MODEL_PTR_TYPEDEF}) IO::GetParam<${MODEL_TYPE}*>(paramName));
}
// Set the pointer to a ${MODEL_TYPE} parameter.
// [[Rcpp::export]]
void IO_SetParam${MODEL_SAFE_TYPE}Ptr(const std::string& paramName, SEXP ptr)
{
IO::GetParam<${MODEL_TYPE}*>(paramName) = Rcpp::as<${MODEL_PTR_TYPEDEF}>(ptr);
IO::SetPassed(paramName);
}
// Serialize a ${MODEL_TYPE} pointer.
// [[Rcpp::export]]
Rcpp::RawVector Serialize${MODEL_SAFE_TYPE}Ptr(SEXP ptr)
{
std::ostringstream oss;
{
cereal::BinaryOutputArchive oa(oss);
oa(cereal::make_nvp(\"${MODEL_SAFE_TYPE}\",
*Rcpp::as<${MODEL_PTR_TYPEDEF}>(ptr)));
}
Rcpp::RawVector raw_vec(oss.str().size());
// Copy the string buffer so we can return one that won't get deallocated when
// we exit this function.
memcpy(&raw_vec[0], oss.str().c_str(), oss.str().size());
raw_vec.attr(\"type\") = \"${MODEL_SAFE_TYPE}\";
return raw_vec;
}
// Deserialize a ${MODEL_TYPE} pointer.
// [[Rcpp::export]]
SEXP Deserialize${MODEL_SAFE_TYPE}Ptr(Rcpp::RawVector str)
{
${MODEL_TYPE}* ptr = new ${MODEL_TYPE}();
std::istringstream iss(std::string((char *) &str[0], str.size()));
{
cereal::BinaryInputArchive ia(iss);
ia(cereal::make_nvp(\"${MODEL_SAFE_TYPE}\", *ptr));
}
// R will be responsible for freeing this.
return std::move((${MODEL_PTR_TYPEDEF})ptr);
}
")
endforeach ()
endif()
endif()
# Now configure the files.
configure_file("${R_CPP_IN}" "${R_CPP_OUT}")
+47
View File
@@ -0,0 +1,47 @@
# StripType.cmake: Extract ModelType from the main file and turn it into
# something that has no special characters that can simply be used.
# This function depends on the following variables being set:
#
# * PROGRAM_MAIN_FILE: the file containing the mlpackMain() function.
#
function(strip_type PROGRAM_MAIN_FILE)
# We need to parse the main file and find any PARAM_MODEL_* lines.
file(READ "${PROGRAM_MAIN_FILE}" MAIN_FILE)
# Grab all "PARAM_MODEL_IN(Model,", "PARAM_MODEL_IN_REQ(Model,",
# "PARAM_MODEL_OUT(Model,".
string(REGEX MATCHALL "PARAM_MODEL_IN\\([A-Za-z_<>]*," MODELS_IN
"${MAIN_FILE}")
string(REGEX MATCHALL "PARAM_MODEL_IN_REQ\\([A-Za-z_<>]*," MODELS_IN_REQ
"${MAIN_FILE}")
string(REGEX MATCHALL "PARAM_MODEL_OUT\\([A-Za-z_]*," MODELS_OUT "${MAIN_FILE}")
string(REGEX REPLACE "PARAM_MODEL_IN\\(" "" MODELS_IN_STRIP1 "${MODELS_IN}")
string(REGEX REPLACE "," "" MODELS_IN_STRIP2 "${MODELS_IN_STRIP1}")
string(REGEX REPLACE "[<>,]" "" MODELS_IN_SAFE_STRIP2 "${MODELS_IN_STRIP1}")
string(REGEX REPLACE "PARAM_MODEL_IN_REQ\\(" "" MODELS_IN_REQ_STRIP1
"${MODELS_IN_REQ}")
string(REGEX REPLACE "," "" MODELS_IN_REQ_STRIP2 "${MODELS_IN_REQ_STRIP1}")
string(REGEX REPLACE "[<>,]" "" MODELS_IN_REQ_SAFE_STRIP2
"${MODELS_IN_REQ_STRIP1}")
string(REGEX REPLACE "PARAM_MODEL_OUT\\(" "" MODELS_OUT_STRIP1 "${MODELS_OUT}")
string(REGEX REPLACE "," "" MODELS_OUT_STRIP2 "${MODELS_OUT_STRIP1}")
string(REGEX REPLACE "[<>,]" "" MODELS_OUT_SAFE_STRIP2 "${MODELS_OUT_STRIP1}")
set(MODEL_TYPES ${MODELS_IN_STRIP2} ${MODELS_IN_REQ_STRIP2}
${MODELS_OUT_STRIP2})
set(MODEL_SAFE_TYPES ${MODELS_IN_SAFE_STRIP2} ${MODELS_IN_REQ_SAFE_STRIP2}
${MODELS_OUT_SAFE_STRIP2})
if (MODEL_TYPES)
list(REMOVE_DUPLICATES MODEL_TYPES)
endif ()
if (MODEL_SAFE_TYPES)
list(REMOVE_DUPLICATES MODEL_SAFE_TYPES)
endif ()
set(MODEL_TYPES ${MODEL_TYPES} PARENT_SCOPE)
set(MODEL_SAFE_TYPES ${MODEL_SAFE_TYPES} PARENT_SCOPE)
endfunction()
+2 -35
View File
@@ -6,42 +6,9 @@
# * PROGRAM_MAIN_FILE: the file containing the mlpackMain() function.
# * SERIALIZATION_FILE: file to append types to
#
# We need to parse the main file and find any PARAM_MODEL_* lines.
function(append_model SERIALIZATION_FILE PROGRAM_MAIN_FILE)
file(READ "${PROGRAM_MAIN_FILE}" MAIN_FILE)
# Grab all "PARAM_MODEL_IN(Model,", "PARAM_MODEL_IN_REQ(Model,",
# "PARAM_MODEL_OUT(Model,".
string(REGEX MATCHALL "PARAM_MODEL_IN\\([A-Za-z_<>]*," MODELS_IN
"${MAIN_FILE}")
string(REGEX MATCHALL "PARAM_MODEL_IN_REQ\\([A-Za-z_<>]*," MODELS_IN_REQ
"${MAIN_FILE}")
string(REGEX MATCHALL "PARAM_MODEL_OUT\\([A-Za-z_]*," MODELS_OUT "${MAIN_FILE}")
string(REGEX REPLACE "PARAM_MODEL_IN\\(" "" MODELS_IN_STRIP1 "${MODELS_IN}")
string(REGEX REPLACE "," "" MODELS_IN_STRIP2 "${MODELS_IN_STRIP1}")
string(REGEX REPLACE "[<>,]" "" MODELS_IN_SAFE_STRIP2 "${MODELS_IN_STRIP1}")
string(REGEX REPLACE "PARAM_MODEL_IN_REQ\\(" "" MODELS_IN_REQ_STRIP1
"${MODELS_IN_REQ}")
string(REGEX REPLACE "," "" MODELS_IN_REQ_STRIP2 "${MODELS_IN_REQ_STRIP1}")
string(REGEX REPLACE "[<>,]" "" MODELS_IN_REQ_SAFE_STRIP2
"${MODELS_IN_REQ_STRIP1}")
string(REGEX REPLACE "PARAM_MODEL_OUT\\(" "" MODELS_OUT_STRIP1 "${MODELS_OUT}")
string(REGEX REPLACE "," "" MODELS_OUT_STRIP2 "${MODELS_OUT_STRIP1}")
string(REGEX REPLACE "[<>,]" "" MODELS_OUT_SAFE_STRIP2 "${MODELS_OUT_STRIP1}")
set(MODEL_TYPES ${MODELS_IN_STRIP2} ${MODELS_IN_REQ_STRIP2}
${MODELS_OUT_STRIP2})
set(MODEL_SAFE_TYPES ${MODELS_IN_SAFE_STRIP2} ${MODELS_IN_REQ_SAFE_STRIP2}
${MODELS_OUT_SAFE_STRIP2})
if (MODEL_TYPES)
list(REMOVE_DUPLICATES MODEL_TYPES)
endif ()
if (MODEL_SAFE_TYPES)
list(REMOVE_DUPLICATES MODEL_SAFE_TYPES)
endif ()
include("${CMAKE_SOURCE_DIR}/CMake/StripType.cmake")
strip_type("${PROGRAM_MAIN_FILE}")
# Now, generate the definitions of the functions we need.
set(MODEL_PTR_DEFNS "")
+2 -35
View File
@@ -8,41 +8,8 @@
# * GO_IN: path of the go_method.h.in/go_method.cpp.in file.
# * GO_OUT: name of the output .h/.cpp file.
#
# We need to parse the main file and find any PARAM_MODEL_* lines.
file(READ "${PROGRAM_MAIN_FILE}" MAIN_FILE)
# Grab all "PARAM_MODEL_IN(Model,", "PARAM_MODEL_IN_REQ(Model,",
# "PARAM_MODEL_OUT(Model,".
string(REGEX MATCHALL "PARAM_MODEL_IN\\([A-Za-z_<>]*," MODELS_IN
"${MAIN_FILE}")
string(REGEX MATCHALL "PARAM_MODEL_IN_REQ\\([A-Za-z_<>]*," MODELS_IN_REQ
"${MAIN_FILE}")
string(REGEX MATCHALL "PARAM_MODEL_OUT\\([A-Za-z_]*," MODELS_OUT "${MAIN_FILE}")
string(REGEX REPLACE "PARAM_MODEL_IN\\(" "" MODELS_IN_STRIP1 "${MODELS_IN}")
string(REGEX REPLACE "," "" MODELS_IN_STRIP2 "${MODELS_IN_STRIP1}")
string(REGEX REPLACE "[<>,]" "" MODELS_IN_SAFE_STRIP2 "${MODELS_IN_STRIP1}")
string(REGEX REPLACE "PARAM_MODEL_IN_REQ\\(" "" MODELS_IN_REQ_STRIP1
"${MODELS_IN_REQ}")
string(REGEX REPLACE "," "" MODELS_IN_REQ_STRIP2 "${MODELS_IN_REQ_STRIP1}")
string(REGEX REPLACE "[<>,]" "" MODELS_IN_REQ_SAFE_STRIP2
"${MODELS_IN_REQ_STRIP1}")
string(REGEX REPLACE "PARAM_MODEL_OUT\\(" "" MODELS_OUT_STRIP1 "${MODELS_OUT}")
string(REGEX REPLACE "," "" MODELS_OUT_STRIP2 "${MODELS_OUT_STRIP1}")
string(REGEX REPLACE "[<>,]" "" MODELS_OUT_SAFE_STRIP2 "${MODELS_OUT_STRIP1}")
set(MODEL_TYPES ${MODELS_IN_STRIP2} ${MODELS_IN_REQ_STRIP2}
${MODELS_OUT_STRIP2})
set(MODEL_SAFE_TYPES ${MODELS_IN_SAFE_STRIP2} ${MODELS_IN_REQ_SAFE_STRIP2}
${MODELS_OUT_SAFE_STRIP2})
if (MODEL_TYPES)
list(REMOVE_DUPLICATES MODEL_TYPES)
endif ()
if (MODEL_SAFE_TYPES)
list(REMOVE_DUPLICATES MODEL_SAFE_TYPES)
endif ()
include("${SOURCE_DIR}/CMake/StripType.cmake")
strip_type("${PROGRAM_MAIN_FILE}")
# Now, generate the definitions of the functions we need.
set(MODEL_PTR_DEFNS "")
+2 -35
View File
@@ -8,42 +8,9 @@
# * PROGRAM_MAIN_FILE: the file containing the mlpackMain() function.
# * SERIALIZATION_FILE: file to append types to
#
# We need to parse the main file and find any PARAM_MODEL_* lines.
function(append_serialization SERIALIZATION_FILE PROGRAM_NAME PROGRAM_MAIN_FILE)
file(READ "${PROGRAM_MAIN_FILE}" MAIN_FILE)
# Grab all "PARAM_MODEL_IN(Model,", "PARAM_MODEL_IN_REQ(Model,",
# "PARAM_MODEL_OUT(Model,".
string(REGEX MATCHALL "PARAM_MODEL_IN\\([A-Za-z_<>]*," MODELS_IN
"${MAIN_FILE}")
string(REGEX MATCHALL "PARAM_MODEL_IN_REQ\\([A-Za-z_<>]*," MODELS_IN_REQ
"${MAIN_FILE}")
string(REGEX MATCHALL "PARAM_MODEL_OUT\\([A-Za-z_]*," MODELS_OUT "${MAIN_FILE}")
string(REGEX REPLACE "PARAM_MODEL_IN\\(" "" MODELS_IN_STRIP1 "${MODELS_IN}")
string(REGEX REPLACE "," "" MODELS_IN_STRIP2 "${MODELS_IN_STRIP1}")
string(REGEX REPLACE "[<>,]" "" MODELS_IN_SAFE_STRIP2 "${MODELS_IN_STRIP1}")
string(REGEX REPLACE "PARAM_MODEL_IN_REQ\\(" "" MODELS_IN_REQ_STRIP1
"${MODELS_IN_REQ}")
string(REGEX REPLACE "," "" MODELS_IN_REQ_STRIP2 "${MODELS_IN_REQ_STRIP1}")
string(REGEX REPLACE "[<>,]" "" MODELS_IN_REQ_SAFE_STRIP2
"${MODELS_IN_REQ_STRIP1}")
string(REGEX REPLACE "PARAM_MODEL_OUT\\(" "" MODELS_OUT_STRIP1 "${MODELS_OUT}")
string(REGEX REPLACE "," "" MODELS_OUT_STRIP2 "${MODELS_OUT_STRIP1}")
string(REGEX REPLACE "[<>,]" "" MODELS_OUT_SAFE_STRIP2 "${MODELS_OUT_STRIP1}")
set(MODEL_TYPES ${MODELS_IN_STRIP2} ${MODELS_IN_REQ_STRIP2}
${MODELS_OUT_STRIP2})
set(MODEL_SAFE_TYPES ${MODELS_IN_SAFE_STRIP2} ${MODELS_IN_REQ_SAFE_STRIP2}
${MODELS_OUT_SAFE_STRIP2})
if (MODEL_TYPES)
list(REMOVE_DUPLICATES MODEL_TYPES)
endif ()
if (MODEL_SAFE_TYPES)
list(REMOVE_DUPLICATES MODEL_SAFE_TYPES)
endif ()
include("${CMAKE_SOURCE_DIR}/CMake/StripType.cmake")
strip_type("${PROGRAM_MAIN_FILE}")
# Now, generate the definitions of the functions we need.
set(MODEL_PTR_DEFNS "")
+2 -35
View File
@@ -7,42 +7,9 @@
# * PROGRAM_MAIN_FILE: the file containing the mlpackMain() function.
# * TYPES_FILE: file to append types to
#
# We need to parse the main file and find any PARAM_MODEL_* lines.
function(append_type TYPES_FILE PROGRAM_NAME PROGRAM_MAIN_FILE)
file(READ "${PROGRAM_MAIN_FILE}" MAIN_FILE)
# Grab all "PARAM_MODEL_IN(Model,", "PARAM_MODEL_IN_REQ(Model,",
# "PARAM_MODEL_OUT(Model,".
string(REGEX MATCHALL "PARAM_MODEL_IN\\([A-Za-z_<>]*," MODELS_IN
"${MAIN_FILE}")
string(REGEX MATCHALL "PARAM_MODEL_IN_REQ\\([A-Za-z_<>]*," MODELS_IN_REQ
"${MAIN_FILE}")
string(REGEX MATCHALL "PARAM_MODEL_OUT\\([A-Za-z_]*," MODELS_OUT "${MAIN_FILE}")
string(REGEX REPLACE "PARAM_MODEL_IN\\(" "" MODELS_IN_STRIP1 "${MODELS_IN}")
string(REGEX REPLACE "," "" MODELS_IN_STRIP2 "${MODELS_IN_STRIP1}")
string(REGEX REPLACE "[<>,]" "" MODELS_IN_SAFE_STRIP2 "${MODELS_IN_STRIP1}")
string(REGEX REPLACE "PARAM_MODEL_IN_REQ\\(" "" MODELS_IN_REQ_STRIP1
"${MODELS_IN_REQ}")
string(REGEX REPLACE "," "" MODELS_IN_REQ_STRIP2 "${MODELS_IN_REQ_STRIP1}")
string(REGEX REPLACE "[<>,]" "" MODELS_IN_REQ_SAFE_STRIP2
"${MODELS_IN_REQ_STRIP1}")
string(REGEX REPLACE "PARAM_MODEL_OUT\\(" "" MODELS_OUT_STRIP1 "${MODELS_OUT}")
string(REGEX REPLACE "," "" MODELS_OUT_STRIP2 "${MODELS_OUT_STRIP1}")
string(REGEX REPLACE "[<>,]" "" MODELS_OUT_SAFE_STRIP2 "${MODELS_OUT_STRIP1}")
set(MODEL_TYPES ${MODELS_IN_STRIP2} ${MODELS_IN_REQ_STRIP2}
${MODELS_OUT_STRIP2})
set(MODEL_SAFE_TYPES ${MODELS_IN_SAFE_STRIP2} ${MODELS_IN_REQ_SAFE_STRIP2}
${MODELS_OUT_SAFE_STRIP2})
if (MODEL_TYPES)
list(REMOVE_DUPLICATES MODEL_TYPES)
endif ()
if (MODEL_SAFE_TYPES)
list(REMOVE_DUPLICATES MODEL_SAFE_TYPES)
endif ()
include("${CMAKE_SOURCE_DIR}/CMake/StripType.cmake")
strip_type("${PROGRAM_MAIN_FILE}")
# Now, generate the definitions of the functions we need.
set(MODEL_PTR_DEFNS "")
+8 -41
View File
@@ -10,41 +10,8 @@
# * JULIA_CPP_IN: path of the julia_method.cpp.in file.
# * JULIA_CPP_OUT: name of the output .cpp file.
#
# We need to parse the main file and find any PARAM_MODEL_* lines.
file(READ "${PROGRAM_MAIN_FILE}" MAIN_FILE)
# Grab all "PARAM_MODEL_IN(Model,", "PARAM_MODEL_IN_REQ(Model,",
# "PARAM_MODEL_OUT(Model,".
string(REGEX MATCHALL "PARAM_MODEL_IN\\([A-Za-z_<>]*," MODELS_IN
"${MAIN_FILE}")
string(REGEX MATCHALL "PARAM_MODEL_IN_REQ\\([A-Za-z_<>]*," MODELS_IN_REQ
"${MAIN_FILE}")
string(REGEX MATCHALL "PARAM_MODEL_OUT\\([A-Za-z_]*," MODELS_OUT "${MAIN_FILE}")
string(REGEX REPLACE "PARAM_MODEL_IN\\(" "" MODELS_IN_STRIP1 "${MODELS_IN}")
string(REGEX REPLACE "," "" MODELS_IN_STRIP2 "${MODELS_IN_STRIP1}")
string(REGEX REPLACE "[<>,]" "" MODELS_IN_SAFE_STRIP2 "${MODELS_IN_STRIP1}")
string(REGEX REPLACE "PARAM_MODEL_IN_REQ\\(" "" MODELS_IN_REQ_STRIP1
"${MODELS_IN_REQ}")
string(REGEX REPLACE "," "" MODELS_IN_REQ_STRIP2 "${MODELS_IN_REQ_STRIP1}")
string(REGEX REPLACE "[<>,]" "" MODELS_IN_REQ_SAFE_STRIP2
"${MODELS_IN_REQ_STRIP1}")
string(REGEX REPLACE "PARAM_MODEL_OUT\\(" "" MODELS_OUT_STRIP1 "${MODELS_OUT}")
string(REGEX REPLACE "," "" MODELS_OUT_STRIP2 "${MODELS_OUT_STRIP1}")
string(REGEX REPLACE "[<>,]" "" MODELS_OUT_SAFE_STRIP2 "${MODELS_OUT_STRIP1}")
set(MODEL_TYPES ${MODELS_IN_STRIP2} ${MODELS_IN_REQ_STRIP2}
${MODELS_OUT_STRIP2})
set(MODEL_SAFE_TYPES ${MODELS_IN_SAFE_STRIP2} ${MODELS_IN_REQ_SAFE_STRIP2}
${MODELS_OUT_SAFE_STRIP2})
if (MODEL_TYPES)
list(REMOVE_DUPLICATES MODEL_TYPES)
endif ()
if (MODEL_SAFE_TYPES)
list(REMOVE_DUPLICATES MODEL_SAFE_TYPES)
endif ()
include("${SOURCE_DIR}/CMake/StripType.cmake")
strip_type("${PROGRAM_MAIN_FILE}")
# Now, generate the definitions of the functions we need.
set(MODEL_PTR_DEFNS "")
@@ -88,9 +55,9 @@ char* Serialize${MODEL_SAFE_TYPE}Ptr(void* ptr, size_t* length)
{
std::ostringstream oss;
{
boost::archive::binary_oarchive oa(oss);
cereal::BinaryOutputArchive oa(oss);
${MODEL_TYPE}* model = (${MODEL_TYPE}*) ptr;
oa << boost::serialization::make_nvp(\"${MODEL_SAFE_TYPE}\", model);
oa(CEREAL_POINTER(model));
}
*length = oss.str().length();
@@ -105,16 +72,16 @@ char* Serialize${MODEL_SAFE_TYPE}Ptr(void* ptr, size_t* length)
// Deserialize a ${MODEL_TYPE} pointer.
void* Deserialize${MODEL_SAFE_TYPE}Ptr(const char* buffer, const size_t length)
{
${MODEL_TYPE}* t = new ${MODEL_TYPE}();
${MODEL_TYPE}* model = new ${MODEL_TYPE}();
std::istringstream iss(std::string(buffer, length));
{
boost::archive::binary_iarchive ia(iss);
ia >> boost::serialization::make_nvp(\"${MODEL_SAFE_TYPE}\", t);
cereal::BinaryInputArchive ia(iss);
ia(CEREAL_POINTER(model));
}
// Julia will be responsible for freeing this.
return (void*) t;
return (void*) model;
}
")
endforeach ()
+74 -67
View File
@@ -16,8 +16,14 @@ option(BUILD_CLI_EXECUTABLES "Build command-line executables." ON)
option(DISABLE_DOWNLOADS "Disable downloads of dependencies during build." OFF)
option(DOWNLOAD_ENSMALLEN "If ensmallen is not found, download it." ON)
option(DOWNLOAD_STB_IMAGE "Download stb_image for image loading." ON)
option(BUILD_PYTHON_BINDINGS "Build Python bindings." ON)
option(BUILD_GO_SHLIB "Build Go shared library." OFF)
option(BUILD_DOCS "Build doxygen documentation (if doxygen is available)." ON)
# Set minimum library version required by mlpack.
set(ARMADILLO_VERSION "8.400.0")
set(ENSMALLEN_VERSION "2.10.0")
set(BOOST_VERSION "1.58")
set(CEREAL_VERSION "1.1.2")
if (WIN32)
option(BUILD_SHARED_LIBS
@@ -30,6 +36,15 @@ else ()
"Compile shared libraries (if OFF, static libraries are compiled)." ON)
endif()
# Detect whether the user passed BUILD_PYTHON_BINDINGS in order to determine if
# we should fail if Python isn't found.
if (BUILD_PYTHON_BINDINGS)
set(FORCE_BUILD_PYTHON_BINDINGS ON)
else()
set(FORCE_BUILD_PYTHON_BINDINGS OFF)
endif()
option(BUILD_PYTHON_BINDINGS "Build Python bindings." OFF)
# Detect whether the user passed BUILD_JULIA_BINDINGS in order to determine if
# we should fail if Julia isn't found.
if (BUILD_JULIA_BINDINGS)
@@ -48,11 +63,19 @@ else()
endif()
option(BUILD_GO_BINDINGS "Build Go bindings." ON)
# If building Go bindings then build go shared libraries.
# If building Go bindings then build go shared libraries.
if (BUILD_GO_BINDINGS)
set(BUILD_GO_SHLIB ON)
endif()
# Detect whether the user passed BUILD_R_BINDINGS in order to determine if
# we should fail if R isn't found.
if (BUILD_R_BINDINGS)
set(FORCE_BUILD_R_BINDINGS ON)
else()
set(FORCE_BUILD_R_BINDINGS OFF)
endif()
option(BUILD_R_BINDINGS "Build R bindings." ON)
# Build Markdown bindings for documentation. This is used as part of website
# generation.
option(BUILD_MARKDOWN_BINDINGS "Build Markdown bindings for website documentation." OFF)
@@ -119,7 +142,7 @@ set(COMPILER_SUPPORT_LIBRARIES "")
# If we are using MSVC, we need /bigobj.
if (MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj /Zm400")
endif ()
# If we are using MINGW, we need sections and big-obj, otherwise we create too
@@ -266,11 +289,10 @@ endif()
# ARMADILLO_INCLUDE_DIRS - directories necessary for Armadillo includes
# BOOST_ROOT - root of Boost installation
# BOOST_INCLUDEDIR - include directory for Boost
# BOOST_LIBRARYDIR - library directory for Boost
# ENSMALLEN_INCLUDE_DIR - include directory for ensmallen
# STB_IMAGE_INCLUDE_DIR - include directory for STB image library
# MATHJAX_ROOT - root of MathJax installation
find_package(Armadillo 8.400.0 REQUIRED)
find_package(Armadillo "${ARMADILLO_VERSION}" REQUIRED)
# Include directories for the previous dependencies.
set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS} ${ARMADILLO_INCLUDE_DIRS})
@@ -332,11 +354,10 @@ else ()
set(STB_AVAILABLE "1")
endif ()
# Find ensmallen.
# Once ensmallen is readily available in package repos, the automatic downloader
# here can be removed.
find_package(Ensmallen 2.10.0)
find_package(Ensmallen "${ENSMALLEN_VERSION}")
if (NOT ENSMALLEN_FOUND)
if (DOWNLOAD_ENSMALLEN)
file(DOWNLOAD http://www.ensmallen.org/files/ensmallen-latest.tar.gz
@@ -392,9 +413,14 @@ else ()
set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS} "${ENSMALLEN_INCLUDE_DIR}")
endif ()
find_package(cereal "${CEREAL_VERSION}" REQUIRED)
set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS} ${CEREAL_INCLUDE_DIR})
# Unfortunately this configuration variable is necessary and will need to be
# updated as time goes on and new versions are released.
set(Boost_ADDITIONAL_VERSIONS
"1.74.0" "1.74"
"17.3.0" "17.3"
"1.72.0" "1.72"
"1.71.0" "1.71"
"1.70.0" "1.70"
@@ -416,33 +442,11 @@ set(Boost_ADDITIONAL_VERSIONS
# TODO for the brave: transition all mlpack's CMake to 'target-based modern
# CMake'. Good luck! You'll need it.
set(Boost_NO_BOOST_CMAKE 1)
find_package(Boost 1.58
COMPONENTS
unit_test_framework
serialization
REQUIRED
)
link_directories(${Boost_LIBRARY_DIRS})
# In Visual Studio, automatic linking is performed, so we don't need to worry
# about it. Clear the list of libraries to link against and let Visual Studio
# handle it.
if (MSVC)
link_directories(${Boost_LIBRARY_DIRS})
set(CMAKE_MSVCIDE_RUN_PATH ${CMAKE_MSVCIDE_RUN_PATH} ${Boost_LIBRARY_DIRS})
message("boost lib dirs ${Boost_LIBRARY_DIRS}")
set(Boost_LIBRARIES "")
endif ()
find_package(Boost "${BOOST_VERSION}")
set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS})
set(MLPACK_LIBRARIES ${MLPACK_LIBRARIES} ${Boost_LIBRARIES})
set(MLPACK_LIBRARY_DIRS ${MLPACK_LIBRARY_DIRS} ${Boost_LIBRARY_DIRS})
# For Boost testing framework (will have no effect on non-testing executables).
# This specifies to Boost that we are dynamically linking to the Boost test
# library.
add_definitions(-DBOOST_TEST_DYN_LINK)
set(MLPACK_LIBRARIES ${MLPACK_LIBRARIES})
set(MLPACK_LIBRARY_DIRS ${MLPACK_LIBRARY_DIRS})
# Detect OpenMP support in a compiler. If the compiler supports OpenMP, flags
# to compile with OpenMP are returned and added and the HAS_OPENMP definition
@@ -545,6 +549,7 @@ add_custom_target(mlpack_arma_config ALL
COMMAND ${CMAKE_COMMAND}
-D ARMADILLO_INCLUDE_DIR="${ARMADILLO_INCLUDE_DIR}"
-D OPENMP_FOUND="${OPENMP_FOUND}"
-D CMAKE_SIZEOF_VOID_P="${CMAKE_SIZEOF_VOID_P}"
-P CMake/CreateArmaConfigInfo.cmake
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Updating arma_config.hpp (if necessary)")
@@ -592,43 +597,45 @@ add_dependencies(mlpack_headers mlpack_arma_config)
# Make a target to generate the documentation. If Doxygen isn't installed, then
# I guess this option will just be unavailable.
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.")
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 ()
# 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)
+19 -11
View File
@@ -7,7 +7,7 @@ Source:
Files: *
Copyright:
Copyright 2008-2018, Ryan Curtin <ryan@ratml.org>
Copyright 2008-2020, Ryan Curtin <ryan@ratml.org>
Copyright 2008-2013, Bill March <march@gatech.edu>
Copyright 2008-2012, Dongryeol Lee <dongryel@cc.gatech.edu>
Copyright 2008-2013, Nishant Mehta <niche@cc.gatech.edu>
@@ -22,11 +22,11 @@ Copyright:
Copyright 2012, Rajendran Mohan <rmohan88@gatech.edu>
Copyright 2012, Trironk Kiatkungwanglai <trironk@gmail.com>
Copyright 2012, Patrick Mason <patrick.s.mason@gmail.com>
Copyright 2013-2018, Marcus Edel <marcus.edel@fu-berlin.de>
Copyright 2013-2020, Marcus Edel <marcus.edel@fu-berlin.de>
Copyright 2013, Mudit Raj Gupta <mudit.raaj.gupta@gmail.com>
Copyright 2013-2018, Sumedh Ghaisas <sumedhghaisas@gmail.com>
Copyright 2014, Michael Fox <michaelfox99@gmail.com>
Copyright 2014, Ryan Birmingham <birm@gatech.edu>
Copyright 2014,2020 Ryan Birmingham <birm@gatech.edu>
Copyright 2014, Siddharth Agrawal <siddharth.950@gmail.com>
Copyright 2014, Saheb Motiani <saheb210692@gmail.com>
Copyright 2014, Yash Vadalia <yashdv@gmail.com>
@@ -37,7 +37,7 @@ Copyright:
Copyright 2014, Udit Saxena <saxenda.udit@gmail.com>
Copyright 2014-2015, Stephen Tu <tu.stephenl@gmail.com>
Copyright 2014-2015, Jaskaran Singh <jaskaranvirdi@ymail.com>
Copyright 2015&2017, Shangtong Zhang <zhangshangtong.cpp@gmail.com>
Copyright 2015,2017, Shangtong Zhang <zhangshangtong.cpp@gmail.com>
Copyright 2015, Hritik Jain <hritik.jain.cse13@itbhu.ac.in>
Copyright 2015, Vladimir Glazachev <glazachev.vladimir@gmail.com>
Copyright 2015, QiaoAn Chen <kazenoyumechen@gmail.com>
@@ -55,7 +55,7 @@ Copyright:
Copyright 2016, Palash Ahuja <abhor902@gmail.com>
Copyright 2016, Yannis Mentekidis <mentekid@gmail.com>
Copyright 2016, Ranjan Mondal <ranjan.rev@gmail.com>
Copyright 2016-2018, Mikhail Lozhnikov <lozhnikovma@gmail.com>
Copyright 2016-2020, Mikhail Lozhnikov <lozhnikovma@gmail.com>
Copyright 2016, Marcos Pividori <marcos.pividori@gmail.com>
Copyright 2016, Keon Kim <kwk236@gmail.com>
Copyright 2016, Nilay Jain <nilayjain13@gmail.com>
@@ -84,14 +84,14 @@ Copyright:
Copyright 2017, N Rajiv Vaidyanathan <rajivvaidyanathan4@gmail.com>
Copyright 2017, Kartik Nighania <kartiknighania@gmail.com>
Copyright 2017-2018, Eugene Freyman <evg.freyman@gmail.com>
Copyright 2017-2018, Manish Kumar <manish887kr@gmail.com>
Copyright 2017-2019, Manish Kumar <manish887kr@gmail.com>
Copyright 2017-2018, Haritha Sreedharan Nair <haritha1313@gmail.com>
Copyright 2017-2018, Sourabh Varshney <sourabhvarshney111@gmail.com>
Copyright 2018, Projyal Dev <projyal@gmail.com>
Copyright 2018, Nikhil Goel <nikhilgoel199797@gmail.com>
Copyright 2018, Shikhar Jaiswal <jaiswalshikhar87@gmail.com>
Copyright 2018-2020 Shikhar Jaiswal <jaiswalshikhar87@gmail.com>
Copyright 2018, B Kartheek Reddy <bkartheekreddy@gmail.com>
Copyright 2018, Atharva Khandait <akhandait45@gmail.com>
Copyright 2018-2019 Atharva Khandait <akhandait45@gmail.com>
Copyright 2018, Wenhao Huang <wenhao.huang.work@gmail.com>
Copyright 2018-2019, Roberto Hueso <robertohueso96@gmail.com>
Copyright 2018, Prabhat Sharma <prabhatsharma7298@gmail.com>
@@ -114,9 +114,9 @@ Copyright:
Copyright 2019, Miguel Canteras <mcanteras@gmail.com>
Copyright 2019, Bishwa Karki <karkeebishwa1@gmail.com>
Copyright 2019, Mehul Kumar Nirala <mehulkumarnirala@gmail.com>
Copyright 2019, Yashwant Singh Parihar <yashwantsingh.sngh@gmail.com>
Copyright 2019-2020 Yashwant Singh Parihar <yashwantsingh.sngh@gmail.com>
Copyright 2019, Heet Sankesara <heetsankesara3@gmail.com>
Copyright 2019, Jeffin Sam <sam.jeffin@gmail.com>
Copyright 2019-2020 Jeffin Sam <sam.jeffin@gmail.com>
Copyright 2019, Vikas S Shetty <shettyvikas209@gmail.com>
Copyright 2019, Khizir Siddiqui <khizirsiddiqui@gmail.com>
Copyright 2019, Tejasvi Tomar <tstomar@outlook.com>
@@ -124,7 +124,7 @@ Copyright:
Copyright 2019, Ziyang Jiang <zij004@alumni.stanford.edu>
Copyright 2019, Rohit Kartik <rohit.audrey@gmail.com>
Copyright 2019, Aditya Viki <adityaviki01@gmail.com>
Copyright 2019, Kartik Dutt <kartikdutt@live.in>
Copyright 2019-2020 Kartik Dutt <kartikdutt@live.in>
Copyright 2020, Sriram S K <sriramsk1999@gmail.com>
Copyright 2020, Manoranjan Kumar Bharti ( Nakul Bharti ) <knakul853@gmail.com>
Copyright 2020, Saraansh Tandon <saraanshtandon1999@gmail.com>
@@ -132,6 +132,14 @@ Copyright:
Copyright 2020, Lakshya Ojha <ojhalakshya@gmail.com>
Copyright 2020, Bisakh Mondal <bisakhmondal00@gmail.com>
Copyright 2020, Benson Muite <benson_muite@emailplus.org>
Copyright 2020, Sarthak Bhardwaj <7sarthakbhardwaj@gmail.com>
Copyright 2020, Aakash Kaushik <kaushikaakash7539@gmail.com>
Copyright 2020, Anush Kini <anushkini@gmail.com>
Copyright 2020, Nippun Sharma <inbox.nippun@gmail.com>
Copyright 2020, Rishabh Garg <rishabhgarg108@gmail.com>
Copyright 2020, Sudhakar Brar <dxhrmhall1449@tutanota.com>
Copyright 2020, Alex Nguyen <alexvn.edu@gmail.com>
Copyright 2020, Gaurav Ghati <gauravghatii@gmail.com>
License: BSD-3-clause
All rights reserved.
+5 -3
View File
@@ -4,7 +4,7 @@
# Project related configuration options
#---------------------------------------------------------------------------
PROJECT_NAME = mlpack
PROJECT_NUMBER = 3.2.2
PROJECT_NUMBER = 3.4.2
OUTPUT_DIRECTORY = ./doc
CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English
@@ -75,7 +75,8 @@ FILE_VERSION_FILTER =
#---------------------------------------------------------------------------
QUIET = NO
WARNINGS = YES
WARN_AS_ERROR = 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
@@ -106,7 +107,8 @@ EXCLUDE_PATTERNS = */build/* \
*.cc \
*_test.cpp \
*CLI11.hpp \
*/tests/catch.hpp
*/tests/catch.hpp \
*/boost/serialization/*
EXAMPLE_PATH =
EXAMPLE_PATTERNS = *
EXAMPLE_RECURSIVE = NO
+63
View File
@@ -1,5 +1,57 @@
### mlpack ?.?.?
###### ????-??-??
* Added an implementation to Stratify Data (#2671).
* Add `BUILD_DOCS` CMake option to control whether Doxygen documentation is
built (default ON) (#2730).
### mlpack 3.4.2
###### 2020-10-26
* Added Mean Absolute Percentage Error.
* Added Softmin activation function as layer in ann/layer.
* Fix spurious ARMA_64BIT_WORD compilation warnings on 32-bit systems (#2665).
### mlpack 3.4.1
###### 2020-09-07
* Fix incorrect parsing of required matrix/model parameters for command-line
bindings (#2600).
* Add manual type specification support to `data::Load()` and `data::Save()`
(#2084, #2135, #2602).
* Remove use of internal Armadillo functionality (#2596, #2601, #2602).
### mlpack 3.4.0
###### 2020-09-01
* Issue warnings when metrics produce NaNs in KFoldCV (#2595).
* Added bindings for _R_ during Google Summer of Code (#2556).
* Added common striptype function for all bindings (#2556).
* Refactored common utility function of bindings to bindings/util (#2556).
* Renamed InformationGain to HoeffdingInformationGain in
methods/hoeffding_trees/information_gain.hpp (#2556).
* Added macro for changing stream of printing and warnings/errors (#2556).
* Added Spatial Dropout layer (#2564).
* Force CMake to show error when it didn't find Python/modules (#2568).
* Refactor `ProgramInfo()` to separate out all the different
information (#2558).
* Add bindings for one-hot encoding (#2325).
* Added Soft Actor-Critic to RL methods (#2487).
* Added Categorical DQN to q_networks (#2454).
* Added N-step DQN to q_networks (#2461).
* Add Silhoutte Score metric and Pairwise Distances (#2406).
@@ -11,6 +63,17 @@
* Additional functionality for the ARFF loader (#2486); use case sensitive
categories (#2516).
* Add `bayesian_linear_regression` binding for the command-line, Python,
Julia, and Go. Also called "Bayesian Ridge", this is equivalent to a
version of linear regression where the regularization parameter is
automatically tuned (#2030).
* Fix defeatist search for spill tree traversals (#2566, #1269).
* Fix incremental training of logistic regression models (#2560).
* Change default configuration of `BUILD_PYTHON_BINDINGS` to `OFF` (#2575).
### mlpack 3.3.2
###### 2020-06-18
* Added Noisy DQN to q_networks (#2446).
+29 -7
View File
@@ -23,7 +23,7 @@ src="https://cdn.rawgit.com/mlpack/mlpack.org/e7d36ed8/mlpack-black.svg" style="
<p align="center">
<em>
Download:
<a href="https://www.mlpack.org/files/mlpack-3.2.2.tar.gz">current stable version (3.2.2)</a>
<a href="https://www.mlpack.org/files/mlpack-3.4.2.tar.gz">current stable version (3.4.2)</a>
</em>
</p>
@@ -32,7 +32,7 @@ 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 programs,
Python bindings, and Julia bindings.
Python bindings, Julia bindings, Go bindings and R bindings.
[//]: # (numfocus-fiscal-sponsor-attribution)
@@ -101,10 +101,10 @@ Citations are beneficial for the growth and improvement of mlpack.
mlpack has the following dependencies:
Armadillo >= 8.400.0
Boost (math_c99, unit_test_framework, serialization,
spirit) >= 1.58.0
Boost (math_c99, spirit) >= 1.58.0
CMake >= 3.2.2
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
@@ -121,6 +121,20 @@ following Python packages are installed:
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
If the STB library headers are available, image loading support will be
compiled.
@@ -132,13 +146,17 @@ 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 mlpack with the following command:
on Ubuntu, you can install the mlpack library and command-line executables (e.g.
mlpack_pca, mlpack_kmeans etc.) with the following command:
$ sudo apt-get install libmlpack-dev
$ sudo apt-get install libmlpack-dev mlpack-bin
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.2.2 available. Options include upgrading your Ubuntu version, finding
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.
There are some useful pages to consult in addition to this section:
@@ -190,6 +208,8 @@ Options are specified with the -D flag. The allowed options include:
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 as opposed to
static libraries
@@ -201,6 +221,8 @@ Options are specified with the -D flag. The allowed options include:
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)
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)
+30 -39
View File
@@ -2,47 +2,38 @@
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<!-- 1) DO NOT CHANGE the product GUID! It is forever -->
<!-- 2) %MLPACK_VERSION env var is set by .appveyor.yml -->
<Product Id="02A00C77-197D-4E91-B7D9-5836220E92E9"
UpgradeCode="6C2D7EC0-6F10-40CB-9703-1DC160A62662"
Name="mlpack"
Language="1033"
Version="$(env.MLPACK_VERSION)"
Manufacturer="mlpack">
<Package InstallerVersion="200"
Description="mlpack Windows Installer"
Compressed="yes"
InstallScope="perMachine"
Platform="x64"/>
<Product Id="02A00C77-197D-4E91-B7D9-5836220E92E9"
UpgradeCode="6C2D7EC0-6F10-40CB-9703-1DC160A62662"
Name="mlpack"
Language="1033"
Version="$(env.MLPACK_VERSION)"
Manufacturer="mlpack">
<Package InstallerVersion="200"
Description="mlpack Windows Installer"
Compressed="yes"
InstallScope="perMachine"
Platform="x64"/>
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab="yes"/>
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab="yes"/>
<Feature Id="ProductFeature" Title="mlpackWindows" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
<Property Id="MLPACK_VERSION">$(env.MLPACK_VERSION)</Property>
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLFOLDER" />
<WixVariable Id="WixUILicenseRtf" Value="..\staging\license.rtf"/>
<WixVariable Id="WixUIBannerBmp" Value="..\res\banner.jpg"/>
<WixVariable Id="WixUIDialogBmp" Value="..\res\dialog_white.jpg"/>
<UIRef Id="WixUI_InstallDir" />
</Product>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder" Name="PFiles">
<Directory Id="INSTALLDIR" Name="mlpack">
<Directory Id="Sources" />
</Directory>
</Directory>
</Directory>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFiles64Folder">
<Directory Id="INSTALLFOLDER" Name="mlpack" />
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<!-- This references the list of mlpack files automatically generated using Heat (see .wixproj BeforeBuild Target) -->
<ComponentGroupRef Id="HeatGenerated"/>
</ComponentGroup>
</Fragment>
<Feature Id="ProductFeature" Title="mlpackWindows" ConfigurableDirectory="INSTALLDIR" Level="1">
<ComponentGroupRef Id="Sources" />
</Feature>
<Property Id="MLPACK_VERSION">$(env.MLPACK_VERSION)</Property>
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLDIR" />
<WixVariable Id="WixUILicenseRtf" Value="..\staging\license.rtf"/>
<WixVariable Id="WixUIBannerBmp" Value="..\res\banner.jpg"/>
<WixVariable Id="WixUIDialogBmp" Value="..\res\dialog_white.jpg"/>
<UIRef Id="WixUI_InstallDir" />
</Product>
</Wix>
@@ -9,33 +9,36 @@
<OutputName>mlpack-windows</OutputName>
<OutputType>Package</OutputType>
<Name>mlpack-win-installer</Name>
<DefineSolutionProperties>false</DefineSolutionProperties>
<DefineConstants>SourceDir=.\Sources</DefineConstants>
<WixTargetsPath Condition=" '$(WixTargetsPath' == '' ">$(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<OutputPath>bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
<DefineConstants>Debug</DefineConstants>
<DefineConstants>Debug;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<OutputPath>bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
<DefineConstants>Debug</DefineConstants>
<OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Platform)\$(Configuration)\</IntermediateOutputPath>
<DefineConstants>Debug;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
<OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Platform)\$(Configuration)\</IntermediateOutputPath>
</PropertyGroup>
<PropertyGroup>
<DefineConstants>HarvestPath=..\staging</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Compile Include="Product.wxs" />
<Compile Include="HeatGeneratedFileList.wxs" />
</ItemGroup>
<ItemGroup>
<HarvestDirectory Include=".\Sources">
<DirectoryRefId>Sources</DirectoryRefId>
<ComponentGroupName>Sources</ComponentGroupName>
<PreprocessorVariable>var.SourceDir</PreprocessorVariable>
<SuppressRegistry>true</SuppressRegistry>
</HarvestDirectory>
<WixExtension Include="WixUIExtension">
<HintPath>$(WixExtDir)\WixUIExtension.dll</HintPath>
<Name>WixUIExtension</Name>
@@ -46,14 +49,4 @@
<Target Name="EnsureWixToolsetInstalled" Condition=" '$(WixTargetsImported)' != 'true' ">
<Error Text="The WiX Toolset v3.11 (or newer) build tools must be installed to build this project. To download the WiX Toolset, see http://wixtoolset.org/releases/" />
</Target>
<!--
To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Wix.targets.-->
<Target Name="BeforeBuild">
<HeatDirectory Directory="..\staging" PreprocessorVariable="var.HarvestPath" OutputFile="HeatGeneratedFileList.wxs" ComponentGroupName="HeatGenerated" DirectoryRefId="INSTALLFOLDER" AutogenerateGuids="true" ToolPath="$(WixToolPath)" SuppressFragments="true" SuppressRegistry="true" SuppressRootDirectory="true" />
</Target>
<!--
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>
@@ -104,16 +104,16 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>false</ConformanceMode>
<AdditionalIncludeDirectories>C:\boost\boost_1_66_0;C:\mlpack\armadillo-8.500.1\include;C:\mlpack\mlpack-3.2.2\build\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>C:\boost\boost_1_66_0;C:\mlpack\armadillo-8.500.1\include;C:\mlpack\mlpack-3.4.2\build\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>C:\mlpack\mlpack-3.2.2\build\Debug\mlpack.lib;C:\boost\boost_1_66_0\lib64-msvc-14.1\libboost_serialization-vc141-mt-gd-x64-1_66.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>C:\mlpack\mlpack-3.4.2\build\Debug\mlpack.lib;C:\boost\boost_1_66_0\lib64-msvc-14.1\libboost_serialization-vc141-mt-gd-x64-1_66.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>xcopy /y "C:\mlpack\mlpack-3.2.2\build\Debug\mlpack.dll" $(OutDir)
xcopy /y "C:\mlpack\mlpack-3.2.2\packages\OpenBLAS.0.2.14.1\lib\native\bin\x64\*.dll" $(OutDir)
<Command>xcopy /y "C:\mlpack\mlpack-3.4.2\build\Debug\mlpack.dll" $(OutDir)
xcopy /y "C:\mlpack\mlpack-3.4.2\packages\OpenBLAS.0.2.14.1\lib\native\bin\x64\*.dll" $(OutDir)
xcopy /y "$(ProjectDir)..\..\..\..\src\mlpack\tests\data\german.csv" "$(ProjectDir)data\german.csv*"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
+199 -58
View File
@@ -19,7 +19,7 @@ The document is split into several sections:
- @ref bindings_intro
- @ref bindings_code
- @ref bindings_general
- @ref bindings_general_program_info
- @ref bindings_general_program_doc
- @ref bindings_general_define_params
- @ref bindings_general_functions
- @ref bindings_general_more
@@ -128,12 +128,18 @@ using namespace std;
// being used. Note that the macros must have + on either side of them. We
// provide some extra references with the "SEE_ALSO()" macro, which is used to
// generate documentation for the website.
PROGRAM_INFO("Mean Shift Clustering",
// Short description.
// Program Name.
BINDING_NAME("Mean Shift Clustering");
// Short description.
BINDING_SHORT_DESC(
"A fast implementation of mean-shift clustering using dual-tree range "
"search. Given a dataset, this uses the mean shift algorithm to produce "
"and return a clustering of the data.",
// Long description.
"and return a clustering of the data.");
// Long description.
BINDING_LONG_DESC(
"This program performs mean shift clustering on the given dataset, storing "
"the learned cluster assignments either as a column of labels in the input "
"dataset or separately."
@@ -147,22 +153,26 @@ PROGRAM_INFO("Mean Shift Clustering",
"\n\n"
"The output labels may be saved with the " + PRINT_PARAM_STRING("output") +
" output parameter and the centroids of each cluster may be saved with the"
" " + PRINT_PARAM_STRING("centroid") + " output parameter."
"\n\n"
" " + PRINT_PARAM_STRING("centroid") + " output parameter.");
// Example.
BINDING_EXAMPLE(
"For example, to run mean shift clustering on the dataset " +
PRINT_DATASET("data") + " and store the centroids to " +
PRINT_DATASET("centroids") + ", the following command may be used: "
"\n\n" +
PRINT_CALL("mean_shift", "input", "data", "centroid", "centroids"),
SEE_ALSO("@kmeans", "#kmeans"),
SEE_ALSO("@dbscan", "#dbscan"),
SEE_ALSO("Mean shift on Wikipedia",
"https://en.wikipedia.org/wiki/Mean_shift"),
SEE_ALSO("Mean Shift, Mode Seeking, and Clustering (pdf)",
PRINT_CALL("mean_shift", "input", "data", "centroid", "centroids"));
// See also...
BINDING_SEE_ALSO("@kmeans", "#kmeans");
BINDING_SEE_ALSO("@dbscan", "#dbscan");
BINDING_SEE_ALSO("Mean shift on Wikipedia",
"https://en.wikipedia.org/wiki/Mean_shift");
BINDING_SEE_ALSO("Mean Shift, Mode Seeking, and Clustering (pdf)",
"http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.510.1222"
"&rep=rep1&type=pdf"),
SEE_ALSO("mlpack::mean_shift::MeanShift C++ class documentation",
"@doxygen/classmlpack_1_1meanshift_1_1MeanShift.html"));
"&rep=rep1&type=pdf");
BINDING_SEE_ALSO("mlpack::mean_shift::MeanShift C++ class documentation",
"@doxygen/classmlpack_1_1meanshift_1_1MeanShift.html");
// Define parameters for the executable.
@@ -228,9 +238,10 @@ void mlpackMain()
@endcode
We can see that we have defined the basic program information in the
@c PROGRAM_INFO() macro. This is, for instance, what is displayed to describe
the binding if the user passed the <tt>\--help</tt> option for a
command-line program.
@c BINDING_NAME(), @c BINDING_SHORT_DESC(), @c BINDING_LONG_DESC(),
@c BINDING_EXAMPLE() and @c BINDING_SEE_ALSO() macros. This is, for instance,
what is displayed to describe the binding if the user passed the
<tt>\--help</tt> 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
@@ -247,10 +258,12 @@ whether the parameter is input or output. Some examples:
Note that each of these macros may have slightly different syntax. See the
links above for further documentation.
In order to write a new binding, then, you simply must write a @c PROGRAM_INFO()
definition of the program with some docuentation, define the input and output
parameters as @c PARAM macros, and then write an @c mlpackMain() function that
actually performs the functionality of the binding. Inside of @c mlpackMain():
In order to write a new binding, then, you simply must write @c BINDING_NAME(),
@c BINDING_SHORT_DESC(), @c BINDING_LONG_DESC(), @c BINDING_EXAMPLE() and
@c BINDING_SEE_ALSO() definitions of the program with some docuentation, define
the input and output parameters as @c PARAM macros, and then write an
@c mlpackMain() function that actually performs the functionality of the binding.
Inside of @c mlpackMain():
- All input parameters are accessible through @c IO::GetParam<type>("name").
- All output parameters should be set by the end of the function with the
@@ -278,15 +291,27 @@ relatively clear how one could use the @c IO functionality along with CMake to
add a binding for a new mlpack machine learning method. If it is not clear,
then the examples in the following sections should clarify.
@subsection bindings_general_program_info Documenting a program with PROGRAM_INFO()
@subsection bindings_general_program_doc Documenting a program with
@c BINDING_NAME(), @c BINDING_SHORT_DESC(), @c BINDING_LONG_DESC(),
@c BINDING_EXAMPLE() and @c BINDING_SEE_ALSO().
Any mlpack program should be documented with the @c PROGRAM_INFO() macro, which
is available from the @c <mlpack/core/util/mlpack_main.hpp> header. The macro
is of the form
Any mlpack program should be documented with the @c BINDING_NAME(),
@c BINDING_SHORT_DESC(), @c BINDING_LONG_DESC() , @c BINDING_EXAMPLE() and
@c BINDING_SEE_ALSO() macros, which is available from the
@c <mlpack/core/util/mlpack_main.hpp> header. The macros
are of the form
@code
PROGRAM_INFO("program name", "short documentation", "long documentation",
SEE_ALSO("link", "description"), ...)
BINDING_NAME("program name");
BINDING_SHORT_DESC("This is a short, two-sentence description of what the program does.");
BINDING_LONG_DESC("This is a long description of what the program does."
" It might be many lines long and have lots of details about different options.");
BINDING_EXAMPLE("This contains one example for this particular binding.\n" +
PROGRAM_CALL(...));
BINDING_EXAMPLE("This contains another example for this particular binding.\n" +
PROGRAM_CALL(...));
// There could be many of these "see alsos".
BINDING_SEE_ALSO("https://en.wikipedia.org/wiki/Machine_learning");
@endcode
The short documentation should be two sentences indicating what the program
@@ -368,6 +393,14 @@ Command-line program output (snippet):
Python binding output (snippet):
The parameter 'shuffle', if set, will shuffle the data before learning.
Julia binding output (snippet):
The parameter `shuffle`, if set, will shuffle the data before learning.
Go binding output (snippet):
The parameter "Shuffle", if set, will shuffle the data before learning.
@endcode
@code
@@ -383,6 +416,14 @@ Command-line program output (snippet):
Python binding output (snippet):
The output matrix can be saved with the 'output' output parameter.
Julia binding output (snippet):
The output matrix can be saved with the `output` output parameter.
Go binding output (snippet):
The output matrix can be saved with the "output" output parameter.
@endcode
@code
@@ -408,12 +449,38 @@ Python binding output (snippet):
>>> output = program(input=x)
>>> model = output['output_model']
Julia binding output (snippet):
For example, to train a model on the dataset `x` and save the output model to
`model`, the following command can be used:
julia> model = program(input=x)
Go binding output (snippet):
For example, to train a model on the dataset "x" and save the output model to
"model", the following command can be used:
// Initialize optional parameters for Program().
param := mlpack.ProgramOptions()
param.Input = x
model := mlpack.Program(param)
@endcode
@code
Input C++ (full program, 'random_numbers_main.cpp'):
PROGRAM_INFO("Random Numbers", "This program generates random numbers with a "
// Program Name.
BINDING_NAME("Random Numbers");
// Short description.
BINDING_SHORT_DESC("An implementation of Random Numbers");
// Long description.
BINDING_LONG_DESC(
"This program generates random numbers with a "
"variety of nonsensical techniques and example parameters. The input "
"dataset, which will be ignored, can be specified with the " +
PRINT_PARAM_STRING("input") + " parameter. If you would like to subtract"
@@ -425,8 +492,10 @@ Input C++ (full program, 'random_numbers_main.cpp'):
"The output random numbers can be saved with the " +
PRINT_PARAM_STRING("output") + " output parameter. In addition, a "
"randomly generated linear regression model can be saved with the " +
PRINT_PARAM_STRING("output_model") + " output parameter."
"\n\n"
PRINT_PARAM_STRING("output_model") + " output parameter.");
// Example.
BINDING_EXAMPLE(
"For example, to generate 100 random numbers with 3 subtracted from them "
"and save the output to " + PRINT_DATASET("rand") + " and the random "
"model to " + PRINT_MODEL("rand_lr") + ", use the following "
@@ -479,17 +548,66 @@ Python binding output:
>>> output = random_numbers(num_values=100, subtract=3)
>>> rand = output['output']
>>> rand_lr = output['output_model']
Julia binding output:
Random Numbers
This program generates random numbers with a variety of nonsensical
techniques and example parameters. The input dataset, which will be
ignored, can be specified with the `input` parameter. If you would like to
subtract values from each number, specify the `subtract` parameter. The
number of random numbers to generate is specified with the `num_values`
parameter.
The output random numbers can be saved with the `output` output parameter.
In addition, a randomly generated linear regression model can be saved with
the `output_model` output parameter.
For example, to generate 100 random numbers with 3 subtracted from them and
save the output to `rand` and the random model to `rand_lr`, use the
following command:
```julia
julia> rand, rand_lr = random_numbers(num_values=100, subtract=3)
```
Go binding output:
Random Numbers
This program generates random numbers with a variety of nonsensical
techniques and example parameters. The input dataset, which will be
ignored, can be specified with the "Input" parameter. If you would like to
subtract values from each number, specify the "Subtract" parameter. The
number of random numbers to generate is specified with the "NumValues"
parameter.
The output random numbers can be saved with the "output" output parameter.
In addition, a randomly generated linear regression model can be saved with
the "outputModel" output parameter.
For example, to generate 100 random numbers with 3 subtracted from them and
save the output to "rand" and the random model to "randLr", use the
following command:
// Initialize optional parameters for RandomNumbers().
param := mlpack.RandomNumbersOptions()
param.NumValues = 100
param.Subtract=3
rand, randLr := mlpack.RandomNumbers(param)
@endcode
@subsection bindings_general_define_params Defining parameters for a program
There exist several macros that can be used after a @c PROGRAM_INFO() definition
to define the parameters that can be specified for a given mlpack program.
These macros all have the same general definition: the name of the macro
specifies the type of the parameter, whether or not the parameter is required,
and whether the parameter is an input or output parameter. Then as arguments to
the macro, the name, description, and sometimes the single-character alias and
the default value of the parameter.
There exist several macros that can be used after a @c BINDING_LONG_DESC() and
@c BINDING_EXAMPLE() definition to define the parameters that can be specified
for a given mlpack program. These macros all have the same general definition:
the name of the macro specifies the type of the parameter, whether or not the
parameter is required, and whether the parameter is an input or output parameter.
Then as arguments to the macros, the name, description, and sometimes the
single-character alias and the default value of the parameter.
To give a flavor of how these definitions look, the definition
@@ -564,8 +682,8 @@ 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
<tt>template<typename Archive> void Serialize(Archive&, const unsigned int)</tt>
(i.e. the type must be serializable via mlpack's boost::serialization shim).
<tt>template<typename Archive> void serialize(Archive&)</tt>
(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:
@@ -620,10 +738,10 @@ Python interface to the user.
mlpack's @c IO module provides a unified abstract interface for getting input
from and providing output to users without needing to consider the language
(command-line, Python, MATLAB, etc.) that the user is running the program from.
This means that after the @c PROGRAM_INFO() macro and the @c PARAM_*() macros
have been defined, a language-agnostic @c mlpackMain() function can be written.
This function then can perform the actual computation that the entire program is
meant to.
This means that after the @c BINDING_LONG_DESC() and @c BINDING_EXAMPLE() macros
and the @c PARAM_*() macros have been defined, a language-agnostic
@c mlpackMain() function can be written. This function then can perform the
actual computation that the entire program is meant to.
Inside of an @c mlpackMain() function, the @c mlpack::IO module can be used to
access input parameters and set output parameters. There are two main functions
@@ -703,7 +821,8 @@ could be created for the "random_numbers" program from earlier sections.
@code
#include <mlpack/core/util/mlpack_main.hpp>
// The PROGRAM_INFO() and PARAM_*() definitions should go here:
// BINDING_NAME(), BINDING_SHORT_DESC(), BINDING_LONG_DESC() , BINDING_EXAMPLE(),
// BINDING_SEE_ALSO() and PARAM_*() definitions should go here:
// ...
using namespace mlpack;
@@ -759,23 +878,43 @@ This section describes the internal functionality of the IO module and the
associated macros. If you are only interested in writing mlpack programs, this
section is probably not worth reading.
There are four main components involved with mlpack bindings:
There are eight main components involved with mlpack bindings:
- the IO module, a singleton class that stores parameter information
- the mlpackMain() function that defines the functionality of the binding
- the PROGRAM_INFO() macro that defines the binding name and documentation
- the BINDING_NAME() macro that defines the binding name
- the BINDING_SHORT_DESC() macro that defines the short description
- the BINDING_LONG_DESC() macro that defines the long description
- (optional) the BINDING_EXAMPLE() macro that defines example usages
- (optional) the BINDING_SEE_ALSO() macro that defines "see also" links
- the PARAM_*() macros that define parameters for the binding
The mlpack::IO module is a singleton class that stores, at runtime, the binding
name, the documentation, and the parameter information and values. In order to
do this, each parameter and the program documentation must make themselves known
to the IO singleton. This is accomplished by having the @c PROGRAM_INFO() and
@c PARAM_*() macros declare global variables that, in their constructors,
register themselves with the IO singleton.
to the IO singleton. This is accomplished by having the @c BINDING_NAME(),
@c BINDING_SHORT_DESC(), @c BINDING_LONG_DESC(), @c BINDING_EXAMPLE(),
@c BINDING_SEE_ALSO() and @c PARAM_*() macros declare global variables that,
in their constructors, register themselves with the IO singleton.
The @c PROGRAM_INFO() macro declares an object of type mlpack::util::ProgramDoc.
The @c ProgramDoc class constructor calls IO::RegisterProgramDoc() in order to
register the given program name and documentation.
The @c BINDING_NAME() macro declares an object of type mlpack::util::ProgramName.
The @c BINDING_SHORT_DESC() macro declares an object of type
mlpack::util::ShortDescription.
The @c BINDING_LONG_DESC() macro declares an object of type
mlpack::util::LongDescription.
The @c BINDING_EXAMPLE() macro declares an object of type mlpack::util::Example.
The @c BINDING_SEE_ALSO() macro declares an object of type
mlpack::util::SeeAlso.
The @c ProgramName class constructor calls IO::RegisterProgramName() in order to
register the given program name.
The @c ShortDescription class constructor calls IO::RegisterShortDescription() in order to
register the given short description.
The @c LongDescription class constructor calls IO::RegisterLongDescription() in order to
register the given long description.
The @c Example class constructor calls IO::RegisterExample() in order to
register the given example.
The @c SeeAlso class constructor calls IO::RegisterSeeAlso() in order to
register the given see-also link.
The @c PARAM_*() macros declare an object that will, in its constructor, call
IO::Add() to register that parameter with the IO singleton. The specific type
@@ -875,7 +1014,8 @@ binding:
- The options defined by @c PARAM_*() macros are of type
mlpack::bindings::cli::CLIOption.
- The parameter and value printing macros for @c PROGRAM_INFO() are set:
- The parameter and value printing macros for @c BINDING_LONG_DESC()
and BINDING_EXAMPLE() are set:
* The @c PRINT_PARAM_STRING() macro is defined as
mlpack::bindings::cli::ParamString().
* The @c PRINT_DATASET() macro is defined as
@@ -1047,9 +1187,10 @@ individually if you like). The file
the name of the program and the @c *_main.cpp file to include correctly, then
the @c mlpack::bindings::python::PrintPYX() function is called by the program.
The @c PrintPYX() function uses the parameters that have been set in the IO
singleton by the @c PROGRAM_INFO() and @c PARAM_*() macros in order to actually
print a fully-working .pyx file that can be compiled. The file has several
sections:
singleton by the @c BINDING_NAME(), @c BINDING_SHORT_DESC(),
@c BINDING_LONG_DESC(), @c BINDING_EXAMPLE(), @c BINDING_SEE_ALSO() and
@c PARAM_*() macros in order to actually print a fully-working .pyx file that
can be compiled. The file has several sections:
- Python imports (numpy/pandas/cython/etc.)
- Cython imports of C++ utility functions and Armadillo functionality
+39 -23
View File
@@ -2,11 +2,25 @@
@section build_buildintro Introduction
This document discusses how to build mlpack from source. These build directions
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 mlpack with the following command:
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:
@code
$ sudo apt-get install libmlpack-dev mlpack-bin
@endcode
On Fedora or Red Hat(EPEL):
@code
$ sudo dnf install mlpack-devel mlpack-bin
@endcode
For installing only the header files and library for building C++ applications
on top of mlpack, one could use:
@code
$ sudo apt-get install libmlpack-dev
@@ -25,12 +39,12 @@ mlpack uses CMake as a build system and allows several flexible build
configuration options. One can consult any of numerous CMake tutorials for
further documentation, but this tutorial should be enough to get mlpack built
and installed on most Linux and UNIX-like systems (including OS X). If you want
to build mlpack on Windows, see \ref build_windows (alternatively, you can read
to build mlpack on Windows, see \ref build_windows (alternatively, you can read
<a href="https://keon.io/mlpack-on-windows/">Keon's excellent tutorial</a> which
is based on older versions).
You can download the latest mlpack release from here:
<a href="https://www.mlpack.org/files/mlpack-3.2.2.tar.gz">mlpack-3.2.2</a>
<a href="https://www.mlpack.org/files/mlpack-3.4.2.tar.gz">mlpack-3.4.2</a>
@section build_simple Simple Linux build instructions
@@ -38,9 +52,9 @@ Assuming all dependencies are installed in the system, you can run the commands
below directly to build and install mlpack.
@code
$ wget https://www.mlpack.org/files/mlpack-3.2.2.tar.gz
$ tar -xvzpf mlpack-3.2.2.tar.gz
$ mkdir mlpack-3.2.2/build && cd mlpack-3.2.2/build
$ wget https://www.mlpack.org/files/mlpack-3.4.2.tar.gz
$ tar -xvzpf mlpack-3.4.2.tar.gz
$ mkdir mlpack-3.4.2/build && cd mlpack-3.4.2/build
$ cmake ../
$ make -j4 # The -j is the number of cores you want to use for a build.
$ sudo make install
@@ -65,8 +79,8 @@ configure mlpack.
First we should unpack the mlpack source and create a build directory.
@code
$ tar -xvzpf mlpack-3.2.2.tar.gz
$ cd mlpack-3.2.2
$ tar -xvzpf mlpack-3.4.2.tar.gz
$ cd mlpack-3.4.2
$ mkdir build
@endcode
@@ -78,8 +92,8 @@ mlpack depends on the following libraries, which need to be installed on the
system and have headers present:
- Armadillo >= 8.400.0 (with LAPACK support)
- Boost (math_c99, serialization, unit_test_framework, heap,
spirit) >= 1.58
- Boost (math_c99, spirit) >= 1.58
- cereal >= 1.1.2
- ensmallen >= 2.10.0 (will be downloaded if not found)
In addition, mlpack has the following optional dependencies:
@@ -95,13 +109,13 @@ For Python bindings, the following packages are required:
- pandas >= 0.15.0
- pytest-runner
In Ubuntu (>= 18.04) and Debian (>= 10) all of these dependencies can be
In Ubuntu (>= 18.04) and Debian (>= 10) all of these dependencies can be
installed through apt:
@code
# apt-get install libboost-math-dev libboost-test-dev libboost-serialization-dev
libarmadillo-dev binutils-dev python-pandas python-numpy cython
python-setuptools
# apt-get install libboost-math-dev libcereal-dev
libarmadillo-dev binutils-dev python3-pandas python3-numpy cython3
python3-setuptools
@endcode
If you are using Ubuntu 19.10 or newer, you can also install @c libensmallen-dev
@@ -112,19 +126,19 @@ packages:
# apt-get install libensmallen-dev libstb-dev
@endcode
@note For older versions of Ubuntu and Debian, Armadillo needs to be built from
source as apt installs an older version. So you need to omit
@note For older versions of Ubuntu and Debian, Armadillo needs to be built from
source as apt installs an older version. So you need to omit
\c libarmadillo-dev from the code snippet above and instead use
<a href="http://arma.sourceforge.net/download.html">this link</a>
to download the required file. Extract this file and follow the README in the
to download the required file. Extract this file and follow the README in the
uncompressed folder to build and install Armadillo.
On Fedora, Red Hat, or CentOS, these same dependencies can be obtained via dnf:
@code
# dnf install boost-devel boost-test boost-math armadillo-devel binutils-devel
python2-Cython python2-setuptools python2-numpy python2-pandas ensmallen-devel
stbi-devel
# dnf install boost-devel boost-math armadillo-devel binutils-devel
python3-Cython python3-setuptools python3-numpy python3-pandas ensmallen-devel
stbi-devel cereal-devel
@endcode
(It's also possible to use python3 packages from the package manager---mlpack
@@ -179,6 +193,8 @@ The full list of options mlpack allows:
- JULIA_EXECUTABLE=(/path/to/julia): Path to specific Julia executable
- BUILD_MARKDOWN_BINDINGS=(ON/OFF): Build Markdown bindings for website
documentation (default OFF)
- BUILD_DOCS=(ON/OFF): build Doxygen documentation, if Doxygen is available
(default ON)
- MATHJAX=(ON/OFF): use MathJax for generated Doxygen documentation (default
OFF)
- FORCE_CXX11=(ON/OFF): assume that the compiler supports C++11 instead of
+115 -10
View File
@@ -9,8 +9,13 @@
@section build_windows_intro Introduction
This tutorial will show you how to build mlpack for Windows from source, so you can
later create your own C++ applications. Before you try building mlpack, you may
This tutorial will show you how to build mlpack for Windows from source, so
you can later create your own C++ applications, using two different ways:
- Using CMake to generate an intermeditate Visual Studio solution (`.sln`).
- @ref build_visual_studio_cmake_integration "Use Visual Studio's CMake integration to directly build from the `CMakeLists`."
Before you try building mlpack, you may
want to install mlpack using vcpkg for Windows. If you don't want to install
using vcpkg, skip this section and continue with the build tutorial.
@@ -78,6 +83,23 @@ system environment variables or manually set the PATH before running CMake)
- Click on OpenBlas and check the mlpack project, then click Install
- Once it has finished installing, close Visual Studio
<b> Building OpenBLAS from Source </b>
Unfortunately, the support for building `LAPACK` and `BLAS` on Windows is quite poor, due to the need for Fortran
compiler and libraries. The easiest method to get the necessary `BLAS/LAPACK` libraries built on Windows is to
compile OpenBLAS with LLVM's `clang-cl` and `flang` to produce the required static library (`.lib`) files
compatible with the MSVC compiler. A comprehensive guide on the
<a href="https://github.com/xianyi/OpenBLAS/wiki/How-to-use-OpenBLAS-in-Microsoft-Visual-Studio">compilation
of OpenBLAS for Windows can be found here</a>.
One could always download prebuilt `LAPACK` and `BLAS` libraries for Windows. However, there are few official
sources, and some of those libraries may require further `dll`s at runtime which may not be available in your
system.
It you choose to build `OpenBLAS` from source, make sure that `LAPACK` functions are also built. Finally, make
sure that the `openblas.lib` library is linked in your `Armadillo` build (see below), as well as the library
path used for the CMake options `BLAS_LIBRARIES` and `LAPACK_LIBRARIES` in the mlpack CMake project.
<b> Boost Dependency </b>
You can either get Boost via NuGet or you can download the prebuilt Windows binaries separately.
@@ -110,7 +132,7 @@ compiler version, check if the Visual Studio compiler and Windows SDK are instal
- Build > Build Solution
- Once it has successfully finished, close Visual Studio
@section build_windows_mlpack Building mlpack
@section build_windows_mlpack Building mlpack with CMake-Generated Solution
- Create a "build" directory into "C:\mlpack\mlpack\"
- You can generate the project using either cmake via command line or GUI. If you prefer to use GUI, refer to the \ref build_windows_appendix "appendix"
@@ -129,6 +151,96 @@ cmake -G "Visual Studio 16 2019" -A x64 -DBLAS_LIBRARIES:FILEPATH="C:/mlpack/mlp
You are ready to create your first application, take a look at the @ref sample_ml_app "Sample C++ ML App"
@section build_visual_studio_cmake_integration Building mlpack with Visual Studio's CMake Integration
This project can be directly built from the `CMakeLists.txt` with the latest version of MS Visual Studio,
given you have CMake integration via the
<a href="https://docs.microsoft.com/en-us/cpp/build/cmake-projects-in-visual-studio?view=msvc-160">C++
CMake tools for Windows</a>. To open the CMake project with Visual Studio, select File->Open->CMake
in the top menu, followed by selecting the root `CMakeLists.txt` located in mlpack's root directory.
In order to allow Visual Studio to configure the CMake project, the CMake configuration json will have
to be edited to provide the <a href="https://github.com/mlpack/mlpack#3-dependencies">relevant options
shown in the `README`</a> needed to find all the dependencies. The options that you
must provide to Visual Studio's CMake are:
- `ARMADILLO_INCLUDE_DIR`
- `ARMADILLO_LIBRARY`
- `BOOST_ROOT`
- `CEREAL_INCLUDE_DIR`
- `BLAS_LIBRARIES`
- `LAPACK_LIBRARIES`
The CMake configuration json can be editted in Visual Studio by right clicking the root `CMakeLists.txt`
in the project view, selecting <b>CMake settings for mlpack</b> and finally clicking on <b>edit JSON</b>.
Adding a new CMake option can be done by adding object fields with the following format to the variables
array in the `CMakeSettings.json`:
@code
{
"name": "options_name_string",
"value": "options_value_string",
"type" : "{BOOL|FILEPATH|PATH|STRING}"
}
@endcode
Here is a full example of the `CMakeSettings.json`file:
@code
{
"configurations": [
{
"name": "x64-Debug (default)",
"generator": "Ninja",
"configurationType": "Debug",
"inheritEnvironments": [ "msvc_x64_x64" ],
"buildRoot": "${projectDir}\\out\\build\\${name}",
"installRoot": "${projectDir}\\out\\install\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "",
"ctestCommandArgs": "",
"variables": [
{
"name": "ARMADILLO_INCLUDE_DIR",
"value": "PATH/TO/CPP/DEPENDENCY/armadillo-10.1.2/include",
"type": "PATH"
},
{
"name": "ARMADILLO_LIBBRARY",
"value": "PATH/TO/CPP/DEPENDENCY/armadillo-10.1.2/lib/armadillo.lib",
"type": "PATH"
},
{
"name": "CEREAL_INCLUDE_DIR",
"value": "PATH/TO/CPP/DEPENDENCY/cereal-1.3.0/include",
"type": "PATH"
},
{
"name": "BUILD_ROOT",
"value": "PATH/TO/CPP/DEPENDENCY/boost_1_66_0",
"type": "PATH"
},
{
"name": "BOOST_INCLUDEDIR",
"value": "PATH/TO/CPP/DEPENDENCY/boost_1_66_0",
"type": "PATH"
},
{
"name": "BLAS_LIBRARIES",
"value": "PATH/TO/CPP/DEPENDENCY/OpenBLAS/lib/openblas.lib",
"type": "PATH"
},
{
"name": "LAPACK_LIBRARIES",
"value": "PATH/TO/CPP/DEPENDENCY/OpenBLAS/lib/openblas.lib",
"type": "PATH"
}
]
}
]
}
@endcode
@section build_windows_appendix Appendix
If you prefer to use cmake GUI, follow these instructions:
@@ -147,13 +259,6 @@ If you prefer to use cmake GUI, follow these instructions:
following variables and reconfigure:
- Name: `BOOST_INCLUDEDIR`; type `PATH`; value `C:/boost/`
- Name: `BOOST_LIBRARYDIR`; type `PATH`; value `C:/boost/lib64-msvc-14.2`
- If Boost is still not found, try adding the following variables and
reconfigure:
- Name: `Boost_INCLUDE_DIR`; type `PATH`; value `C:/boost/`
- Name: `Boost_SERIALIZATION_LIBRARY_DEBUG`; type `FILEPATH`; value should be `C:/boost/lib64-msvc-14.2/boost_serialization-vc142-mt-gd-x64-1_71.lib`
- Name: `Boost_SERIALIZATION_LIBRARY_RELEASE`; type `FILEPATH`; value should be `C:/boost/lib64-msvc-14.2/boost_serialization-vc142-mt-x64-1_71.lib`
- Name: `Boost_UNIT_TEST_FRAMEWORK_LIBRARY_DEBUG`; type `FILEPATH`; value should be `C:/boost/lib64-msvc-14.2/boost_unit_test_framework-vc142-mt-gd-x64-1_71.lib`
- Name: `Boost_UNIT_TEST_FRAMEWORK_LIBRARY_RELEASE`; type `FILEPATH`; value should be `C:/boost/lib64-msvc-14.2/boost_unit_test_framework-vc142-mt-x64-1_71.lib`
- Once CMake has configured successfully, hit "Generate" to create the `.sln` file.
@section build_windows_additional_information Additional Information
+4 -3
View File
@@ -10,8 +10,9 @@ This page describes how you can quickly get started using mlpack from the
command-line and gives a few examples of usage, and pointers to deeper
documentation.
This quickstart guide is also available for @ref python_quickstart "Python" and
@ref julia_quickstart "Julia".
This quickstart guide is also available for @ref python_quickstart "Python",
@ref r_quickstart "R", @ref julia_quickstart "Julia" and
@ref go_quickstart "Go".
@section cli_quickstart_install Installing mlpack
@@ -108,7 +109,7 @@ The example above has only shown a little bit of the functionality of mlpack.
Lots of other commands are available with different functionality. A full list
of commands and full documentation for each can be found on the following page:
- <a href="https://mlpack.org/doc/mlpack-git/cli_documentation.html">IO documentation</a>
- <a href="https://mlpack.org/doc/mlpack-git/cli_documentation.html">CLI documentation</a>
For more information on what mlpack does, see https://www.mlpack.org/. Next,
let's go through another example for providing movie recommendations with
+7 -8
View File
@@ -447,11 +447,11 @@ Multiple images are saved according to the vector of filenames specified.
@section formatmodels Loading and saving models
Using \c boost::serialization, mlpack is able to load and save machine learning
Using \c cereal, mlpack is able to load and save machine learning
models with ease. These models can currently be saved in three formats:
- binary (.bin); this is not human-readable, but it is small
- text (.txt); this is sort of human-readable and relatively small
- json (.json); this is sort of human-readable and relatively small
- xml (.xml); this is human-readable but very verbose and large
The type of file to save is determined by the given file extension, as with the
@@ -471,7 +471,7 @@ options; for more information, see the documentation for each program
@section formatmodelscpp Loading and saving models in C++
mlpack uses the \c boost::serialization library internally to perform loading
mlpack uses the \c cereal library internally to perform loading
and saving of models, and provides convenience overloads of mlpack::data::Load()
and mlpack::data::Save() to load and save these models.
@@ -479,13 +479,12 @@ To be serializable, a class must implement the method
\code
template<typename Archive>
void serialize(Archive& ar, const unsigned int version);
void serialize(Archive& ar);
\endcode
\note
For more information on this method and how it works, see the
boost::serialization documentation at
http://www.boost.org/libs/serialization/doc/.
cereal documentation at https://uscilab.github.io/cereal/index.html.
\note
Examples of serialize() methods can be found in most classes; one fairly
@@ -503,11 +502,11 @@ mlpack::math::Range object.
\code
// Create range and save it.
mlpack::math::Range r(0.0, 5.0);
mlpack::data::Save("range.txt", "range", r);
mlpack::data::Save("range.json", "range", r);
// Load into new range.
mlpack::math::Range newRange;
mlpack::data::Load("range.txt", "range", newRange);
mlpack::data::Load("range.json", "range", newRange);
\endcode
It is important to be sure that you load the appropriate type; if you save, for
+3 -3
View File
@@ -9,9 +9,9 @@
This page describes how you can quickly get started using mlpack from Go and
gives a few examples of usage, and pointers to deeper documentation.
This quickstart guide is also available for
@ref cli_quickstart "the command-line", @ref python_quickstart "Python"
and @ref julia_quickstart "Julia".
This quickstart guide is also available for @ref python_quickstart "Python",
@ref cli_quickstart "the command-line", @ref julia_quickstart "Julia" and
@ref r_quickstart "R".
@section go_quickstart_install Installing mlpack
+20 -14
View File
@@ -40,7 +40,7 @@ once that is done, it will call \c mlpackMain().
@code
#include <mlpack/core.hpp>
#include <mlpack/core/util/cli.hpp>
#include <mlpack/core/util/io.hpp>
// This definition below means we will only compile for the command line.
#define BINDING_TYPE BINDING_TYPE_CLI
#include <mlpack/core/util/mlpack_main.hpp>
@@ -117,10 +117,11 @@ Aborted
These four outputs can be very useful for both providing informational output
and debugging output for your mlpack program.
@section simplecli Simple IO Example
@section simpleio Simple IO Example
Through the mlpack::IO object, command-line parameters can be easily added
with the PROGRAM_INFO, PARAM_INT, PARAM_DOUBLE, PARAM_STRING, and PARAM_FLAG
with the BINDING_NAME, BINDING_SHORT_DESC, BINDING_LONG_DESC, BINDING_EXAMPLE,
BINDING_SEE_ALSO, PARAM_INT, PARAM_DOUBLE, PARAM_STRING, and PARAM_FLAG
macros.
Here is a sample use of those macros, extracted from methods/pca/pca_main.cpp.
@@ -128,26 +129,31 @@ Here is a sample use of those macros, extracted from methods/pca/pca_main.cpp.
@code
#include <mlpack/core.hpp>
#include <mlpack/core/util/cli.hpp>
#include <mlpack/core/util/io.hpp>
#include <mlpack/core/util/mlpack_main.hpp>
// Document program.
PROGRAM_INFO("Principal Components Analysis",
// Short description.
// Program Name.
BINDING_NAME("Principal Components Analysis");
// Short description.
BINDING_SHORT_DESC(
"An implementation of several strategies for principal components analysis "
"(PCA), a common preprocessing step. Given a dataset and a desired new "
"dimensionality, this can reduce the dimensionality of the data using the "
"linear transformation determined by PCA.",
// Long description.
"linear transformation determined by PCA.");
// Long description.
BINDING_LONG_DESC(
"This program performs principal components analysis on the given dataset "
"using the exact, randomized, randomized block Krylov, or QUIC SVD method. "
"It will transform the data onto its principal components, optionally "
"performing dimensionality reduction by ignoring the principal components "
"with the smallest eigenvalues."
// "See also" section for generated documentation.
SEE_ALSO("Principal component analysis on Wikipedia",
"https://en.wikipedia.org/wiki/Principal_component_analysis"),
SEE_ALSO("mlpack::pca::PCA C++ class documentation",
"with the smallest eigenvalues.");
// See also...
BINDING_SEE_ALSO("Principal component analysis on Wikipedia",
"https://en.wikipedia.org/wiki/Principal_component_analysis");
BINDING_SEE_ALSO("mlpack::pca::PCA C++ class documentation",
"@doxygen/classmlpack_1_1pca_1_1PCA.html"));
// Parameters for program.
+3 -2
View File
@@ -9,8 +9,9 @@
This page describes how you can quickly get started using mlpack from Julia and
gives a few examples of usage, and pointers to deeper documentation.
This quickstart guide is also available for
@ref cli_quickstart "the command-line" and @ref python_quickstart "Python".
This quickstart guide is also available for @ref python_quickstart "Python",
@ref cli_quickstart "the command-line", @ref go_quickstart "Go" and
@ref r_quickstart "R".
@section julia_quickstart_install Installing mlpack
+3 -3
View File
@@ -32,9 +32,9 @@ build and install mlpack. You can copy-paste the commands into your shell.
@code{.sh}
sudo apt-get install libboost-all-dev g++ cmake libarmadillo-dev python-pip wget
sudo pip install cython setuptools distutils numpy pandas
wget https://www.mlpack.org/files/mlpack-3.2.2.tar.gz
tar -xvzpf mlpack-3.2.2.tar.gz
mkdir -p mlpack-3.2.2/build/ && cd mlpack-3.2.2/build/
wget https://www.mlpack.org/files/mlpack-3.4.2.tar.gz
tar -xvzpf mlpack-3.4.2.tar.gz
mkdir -p mlpack-3.4.2/build/ && cd mlpack-3.4.2/build/
cmake ../ && make -j4 && sudo make install
@endcode
+193
View File
@@ -0,0 +1,193 @@
/**
* @file r_quickstart.hpp
* @author Yashwant Singh Parihar
@page r_quickstart mlpack in R quickstart guide
@section r_quickstart_intro Introduction
This page describes how you can quickly get started using mlpack from R and
gives a few examples of usage, and pointers to deeper documentation.
This quickstart guide is also available for @ref python_quickstart "Python",
@ref cli_quickstart "the command-line", @ref julia_quickstart "Julia" and
@ref go_quickstart "Go".
@section r_quickstart_install Installing mlpack binary package
Installing the mlpack bindings for R is straightforward; you can just use
CRAN:
@code{.R}
install.packages('mlpack')
@endcode
@section r_quickstart_source_install Installing mlpack package from source
Building the R bindings from scratch is a little more in-depth, though. For
information on that, follow the instructions on the @ref build page, and be sure
to specify @c -DBUILD_R_BINDINGS=ON to CMake; you may need to also set the
location of the R program with @c -DR_EXECUTABLE=/path/to/R.
@section r_quickstart_example Simple mlpack quickstart example
As a really simple example of how to use mlpack from R, let's do some
simple classification on a subset of the standard machine learning @c covertype
dataset. We'll first split the dataset into a training set and a testing set,
then we'll train an mlpack random forest on the training data, and finally we'll
print the accuracy of the random forest on the test dataset.
You can copy-paste this code directly into R to run it.
@code{.R}
if(!requireNamespace("data.table", quietly = TRUE)) { install.packages("data.table") }
suppressMessages({
library("mlpack")
library("data.table")
})
# Load the dataset from an online URL. Replace with 'covertype.csv.gz' if you
# want to use on the full dataset.
df <- fread("https://www.mlpack.org/datasets/covertype-small.csv.gz")
# Split the labels.
labels <- df[, .(label)]
dataset <- df[, label:=NULL]
# Split the dataset using mlpack.
prepdata <- preprocess_split(input = dataset,
input_labels = labels,
test_ratio = 0.3,
verbose = TRUE)
# Train a random forest.
output <- random_forest(training = prepdata$training,
labels = prepdata$training_labels,
print_training_accuracy = TRUE,
num_trees = 10,
minimum_leaf_size = 3,
verbose = TRUE)
rf_model <- output$output_model
# Predict the labels of the test points.
output <- random_forest(input_model = rf_model,
test = prepdata$test,
verbose = TRUE)
# Now print the accuracy. The third return value ('probabilities'), which we
# ignored here, could also be used to generate an ROC curve.
correct <- sum(output$predictions == prepdata$test_labels)
cat(correct, "out of", length(prepdata$test_labels), "test points correct",
correct / length(prepdata$test_labels) * 100.0, "%\n")
@endcode
We can see that we achieve reasonably good accuracy on the test dataset (80%+);
if we use the full @c covertype.csv.gz, the accuracy should increase
significantly (but training will take longer).
It's easy to modify the code above to do more complex things, or to use
different mlpack learners, or to interface with other machine learning toolkits.
@section r_quickstart_whatelse What else does mlpack implement?
The example above has only shown a little bit of the functionality of mlpack.
Lots of other commands are available with different functionality. A full list
of each of these commands and full documentation can be found on the following
page:
- <a href="https://www.mlpack.org/doc/mlpack-git/r_documentation.html">r documentation</a>
For more information on what mlpack does, see https://www.mlpack.org/.
Next, let's go through another example for providing movie recommendations with
mlpack.
@section r_quickstart_movierecs Using mlpack for movie recommendations
In this example, we'll train a collaborative filtering model using mlpack's
<tt><a href="https://www.mlpack.org/doc/mlpack-git/r_documentation.html#cf">cf()</a></tt> method. We'll train this on the MovieLens dataset from
https://grouplens.org/datasets/movielens/, and then we'll use the model that we
train to give recommendations.
You can copy-paste this code directly into R to run it.
@code{.R}
if(!requireNamespace("data.table", quietly = TRUE)) { install.packages("data.table") }
suppressMessages({
library("mlpack")
library("data.table")
})
# First, load the MovieLens dataset. This is taken from files.grouplens.org/
# but reposted on mlpack.org as unpacked and slightly preprocessed data.
ratings <- fread("http://www.mlpack.org/datasets/ml-20m/ratings-only.csv.gz")
movies <- fread("http://www.mlpack.org/datasets/ml-20m/movies.csv.gz")
# Hold out 10% of the dataset into a test set so we can evaluate performance.
predata <- preprocess_split(input = ratings,
test_ratio = 0.1,
verbose = TRUE)
# Train the model. Change the rank to increase/decrease the complexity of the
# model.
output <- cf(training = predata$training,
test = predata$test,
rank = 10,
verbose = TRUE,
max_iteration=2,
algorithm = "RegSVD")
cf_model <- output$output_model
# Now query the 5 top movies for user 1.
output <- cf(input_model = cf_model,
query = matrix(1),
recommendations = 10,
verbose = TRUE)
# Get the names of the movies for user 1.
cat("Recommendations for user 1:\n")
for (i in 1:10) {
cat(" ", i, ":", as.character(movies[output$output[i], 3]), "\n")
}
@endcode
Here is some example output, showing that user 1 seems to have good taste in
movies:
@code{.unparsed}
Recommendations for user 1:
0: Casablanca (1942)
1: Pan's Labyrinth (Laberinto del fauno, El) (2006)
2: Godfather, The (1972)
3: Answer This! (2010)
4: Life Is Beautiful (La Vita è bella) (1997)
5: Adventures of Tintin, The (2011)
6: Dark Knight, The (2008)
7: Out for Justice (1991)
8: Dr. Strangelove or: How I Learned to Stop Worrying and Love the Bomb (1964)
9: Schindler's List (1993)
@endcode
@section r_quickstart_nextsteps Next steps with mlpack
After working through this overview to `mlpack`'s R package, we hope you are
inspired to use `mlpack`' in your data science workflow. We recommend as part
of your next steps to look at more documentation for the R mlpack bindings:
- <a href="https://www.mlpack.org/doc/mlpack-git/r_documentation.html">R mlpack
binding documentation</a>
Also, mlpack is much more flexible from C++ and allows much greater
functionality. So, more complicated tasks are possible if you are willing to
write C++ (or perhaps Rcpp). To get started learning about mlpack in C++, the
following resources might be helpful:
- <a href="https://www.mlpack.org/doc/mlpack-git/doxygen/tutorials.html">mlpack
C++ tutorials</a>
- <a href="https://www.mlpack.org/doc/mlpack-git/doxygen/build.html">mlpack
build and installation guide</a>
- <a href="https://www.mlpack.org/doc/mlpack-git/doxygen/sample.html">Simple
sample C++ mlpack programs</a>
- <a href="https://www.mlpack.org/doc/mlpack-git/doxygen/index.html">mlpack
Doxygen documentation homepage</a>
*/
+13 -10
View File
@@ -29,17 +29,16 @@ mlpack and dependencies in Release Mode).
@code
- C:\boost\boost_1_71_0\lib\native\include
- C:\mlpack\armadillo-9.800.3\include
- C:\mlpack\mlpack-3.2.2\build\include
- C:\mlpack\mlpack-3.4.2\build\include
@endcode
- Under Linker > Input > Additional Dependencies add:
@code
- C:\mlpack\mlpack-3.2.2\build\Debug\mlpack.lib
- C:\boost\boost_1_71_0\lib64-msvc-14.2\libboost_serialization-vc142-mt-gd-x64-1_71.lib
- C:\mlpack\mlpack-3.4.2\build\Debug\mlpack.lib
@endcode
- Under Build Events > Post-Build Event > Command Line add:
@code
- xcopy /y "C:\mlpack\mlpack-3.2.2\build\Debug\mlpack.dll" $(OutDir)
- xcopy /y "C:\mlpack\mlpack-3.2.2\packages\OpenBLAS.0.2.14.1\lib\native\bin\x64\*.dll" $(OutDir)
- xcopy /y "C:\mlpack\mlpack-3.4.2\build\Debug\mlpack.dll" $(OutDir)
- xcopy /y "C:\mlpack\mlpack-3.4.2\packages\OpenBLAS.0.2.14.1\lib\native\bin\x64\*.dll" $(OutDir)
@endcode
@note Recent versions of Visual Studio set "Conformance Mode" enabled by default. This causes some issues with
@@ -94,7 +93,7 @@ copy "mlpack/tests/data/german.csv" and paste into a new "data" folder in your p
mat dataset;
bool loaded = mlpack::data::Load("data/german.csv", dataset);
if (!loaded)
return -1;
return -1;
@endcode
Then we need to extract the labels from the last dimension of the dataset and remove the
@@ -121,7 +120,7 @@ const size_t numTrees = 10;
RandomForest<GiniGain, RandomDimensionSelect> rf;
rf = RandomForest<GiniGain, RandomDimensionSelect>(dataset, labels,
numClasses, numTrees, minimumLeafSize);
numClasses, numTrees, minimumLeafSize);
@endcode
Now that the training is completed, we quickly compute the training accuracy:
@@ -143,7 +142,7 @@ to assess the quality of the trained model.
@code
const size_t k = 10;
KFoldCV<RandomForest<GiniGain, RandomDimensionSelect>, Accuracy> cv(k,
dataset, labels, numClasses);
dataset, labels, numClasses);
double cvAcc = cv.Evaluate(numTrees, minimumLeafSize);
cout << "\nKFoldCV Accuracy: " << cvAcc;
@endcode
@@ -188,12 +187,16 @@ Finally, the ultimate goal is to classify a new sample using the previously trai
Random Forest classifier provides both predictions and probabilities, we obtain both.
@code
mat sample("2 12 2 13 1 2 2 1 3 24 3 1 1 1 1 1 0 1 0 1 0 0 0");
// Create a test sample containing only one point. Because Armadillo is
// column-major, this matrix has one column (one point) and the number of rows
// is equal to the dimensionality of the point (23).
mat sample("2; 12; 2; 13; 1; 2; 2; 1; 3; 24; 3; 1; 1; 1; 1; 1; 0; 1; 0; 1;"
" 0; 0; 0");
mat probabilities;
rf.Classify(sample, predictions, probabilities);
u64 result = predictions.at(0);
cout << "\nClassification result: " << result << " , Probabilities: " <<
probabilities.at(0) << "/" << probabilities.at(1);
probabilities.at(0) << "/" << probabilities.at(1);
@endcode
@section sample_app_conclussion Final thoughts
+1 -1
View File
@@ -41,7 +41,7 @@ Below is a very simple example of timer usage in code.
@code
#include <mlpack/core.hpp>
#include <mlpack/core/util/cli.hpp>
#include <mlpack/core/util/io.hpp>
#define BINDING_TYPE BINDING_TYPE_CLI
#include <mlpack/core/util/mlpack_main.hpp>
+16 -16
View File
@@ -225,7 +225,7 @@ class ExampleTree
// tree using the given MetricType.
ExampleTree(const MatType& data, MetricType& metric);
// Initialize the tree from a given boost::serialization archive. SFINAE (the
// Initialize the tree from a given cereal archive. SFINAE (the
// second argument) is necessary to ensure that the archive is loading, not
// saving.
template<typename Archive>
@@ -330,16 +330,16 @@ class ExampleTree
// Serialize the tree (load from the given archive / save to the given
// archive, depending on its type).
template<typename Archive>
void Serialize(Archive& ar, const unsigned int version);
void serialize(Archive& ar, const uint32_t version);
protected:
// A default constructor; only meant to be used by boost::serialization. This
// must be protected so that boost::serialization will work; it does not need
// A default constructor; only meant to be used by cereal. This
// must be protected so that cereal will work; it does not need
// to return a valid tree.
ExampleTree();
// Friend access must be given for the default constructor.
friend class boost::serialization::access;
friend class cereal::access;
};
@endcode
@@ -378,7 +378,7 @@ calculation, and (usually) provides a decent bound on the minimum distance
between \f$p\f$ and any descendant point of the node.
- **Trees need to be able to be serialized.** mlpack uses the
boost::serialization library for saving and loading objects. Trees---which can
cereal library for saving and loading objects. Trees---which can
be a part of machine learning models---therefore must have the ability to be
saved and loaded. Making this all work requires a protected constructor (part
of the API) and generally makes it impossible to hold references instead of
@@ -481,10 +481,10 @@ It is possible to implement both these constructors as one by using \c
boost::optional.
The third constructor requires the tree to be initializable from a \c
boost::serialization archive:
cereal archive:
@code
// Initialize the tree from a given boost::serialization archive. SFINAE (the
// Initialize the tree from a given cereal archive. SFINAE (the
// second argument) is necessary to ensure that the archive is loading, not
// saving.
template<typename Archive>
@@ -507,7 +507,7 @@ will be required:
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 boost::serialization ).
the tree was created via \c cereal ).
Note that these constructors are not necessarily the only constructors that a
\c TreeType implementation can provide. One important example of when more
@@ -778,22 +778,22 @@ the node plus one or two levels of children.
// Serialize the tree (load from the given archive / save to the given
// archive, depending on its type).
template<typename Archive>
void Serialize(Archive& ar, const unsigned int version);
void serialize(Archive& ar);
protected:
// A default constructor; only meant to be used by boost::serialization. This
// must be protected so that boost::serialization will work; it does not need
// A default constructor; only meant to be used by cereal. This
// must be protected so that cereal will work; it does not need
// to return a valid tree.
ExampleTree();
// Friend access must be given for the default constructor.
friend class boost::serialization::access;
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 boost::serialization documentation is fairly comprehensive, but
disk. The \c cereal documentation is fairly comprehensive.
when writing a \c Serialize() method for mlpack trees you should use
\c data::CreateNVP() instead of \c BOOST_SERIALIZATION_NVP(). This is because
mlpack classes implement \c Serialize() instead of \c serialize() in order to
@@ -803,10 +803,10 @@ be useful to look at other \c Serialize() methods contained in other mlpack
classes as an example.
An important note is that it is very difficult to use references with
\c boost::serialization, because \c Serialize() may be called at any time during
\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
Therefore, be careful that \c serialize() (and the tree's destructor) properly
handle memory management!
@section treetype_traits The TreeTraits trait class
+73 -47
View File
@@ -573,8 +573,8 @@ a new reference set. This is functionally equivalent to creating a new model.
@section model_saving_loading_anntut Saving & Loading
Using \c boost::serialization (for more information about the internals see
[Serialization - Boost C++ Libraries](www.boost.org/libs/serialization/doc/)),
Using \c cereal (for more information about the internals see
[the Cereal website](http://uscilab.github.io/cereal/)),
mlpack is able to load and save machine learning models with ease. To save a
trained neural network to disk. The example below builds a model on the \c
thyroid dataset and then saves the model to the file \c model.xml for later use.
@@ -589,7 +589,7 @@ arma::mat trainData = dataset.submat(0, 0, dataset.n_rows - 4,
dataset.n_cols - 1);
// Split the data from the training set.
arma::mat trainLabelsTemp = dataset.submat(dataset.n_rows - 3, 0,
arma::mat trainLabels = dataset.submat(dataset.n_rows - 3, 0,
dataset.n_rows - 1, dataset.n_cols - 1);
// Initialize the network.
@@ -615,50 +615,76 @@ Now, we can look at the output model file, \c model.xml:
@code
$ cat model.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE boost_serialization>
<boost_serialization signature="serialization::archive" version="15">
<model class_id="0" tracking_level="0" version="0">
<parameter class_id="1" tracking_level="1" version="0" object_id="_0">
<n_rows>66</n_rows>
<n_cols>1</n_cols>
<n_elem>66</n_elem>
<vec_state>0</vec_state>
<item>-7.55971528334903642e+00</item>
<item>-9.95435955058058930e+00</item>
<item>9.31133928948225353e+00</item>
<item>-5.36784434861701953e+00</item>
...
</parameter>
<width>0</width>
<height>0</height>
<currentInput object_id="_1">
<n_rows>0</n_rows>
<n_cols>0</n_cols>
<n_elem>0</n_elem>
<vec_state>0</vec_state>
</currentInput>
<network class_id="2" tracking_level="0" version="0">
<count>3</count>
<item_version>0</item_version>
<item class_id="3" tracking_level="0" version="0">
<which>18</which>
<value class_id="4" tracking_level="1" version="0" object_id="_2">
<inSize>21</inSize>
<outSize>3</outSize>
</value>
</item>
<item>
<which>2</which>
<value class_id="5" tracking_level="1" version="0" object_id="_3"></value>
</item>
<item>
<which>20</which>
<value class_id="6" tracking_level="1" version="0" object_id="_4"></value>
</item>
</network>
</model>
</boost_serialization>
<?xml version="1.0" encoding="utf-8"?>
<cereal>
<model>
<cereal_class_version>0</cereal_class_version>
<parameter>
<n_rows>60</n_rows>
<n_cols>1</n_cols>
<vec_state>0</vec_state>
<elem>10.461979353567767</elem>
<elem>-10.040855482151116</elem>
<elem>0.18048901768535316</elem>
<elem>4.8989495084787169</elem>
<elem>-4.4381643782652276</elem>
<elem>0.049477846402230616</elem>
<elem>2.5271808924795987</elem>
<elem>-3.96993488526287</elem>
...
</parameter>
<width>0</width>
<height>0</height>
<reset>true</reset>
<value0>
<vecSize>3</vecSize>
<value0>
<which>30</which>
<value0>
<cereal_class_version>0</cereal_class_version>
<smartPointer>
<ptr_wrapper>
<valid>1</valid>
<data>
<cereal_class_version>0</cereal_class_version>
<inSize>19</inSize>
<outSize>3</outSize>
</data>
</ptr_wrapper>
</smartPointer>
</value0>
</value0>
<value1>
<which>6</which>
<value0>
<cereal_class_version>0</cereal_class_version>
<smartPointer>
<ptr_wrapper>
<valid>1</valid>
<data>
<cereal_class_version>0</cereal_class_version>
</data>
</ptr_wrapper>
</smartPointer>
</value0>
</value1>
<value2>
<which>32</which>
<value0>
<cereal_class_version>0</cereal_class_version>
<smartPointer>
<ptr_wrapper>
<valid>1</valid>
<data>
<cereal_class_version>0</cereal_class_version>
</data>
</ptr_wrapper>
</smartPointer>
</value0>
</value2>
</value0>
</model>
</cereal>
@endcode
As you can see, the \c \<parameter\> section of \c model.xml contains the trained
+1
View File
@@ -15,6 +15,7 @@ get started with mlpack in different languages.
- \ref cli_quickstart
- \ref julia_quickstart
- \ref go_quickstart
- \ref r_quickstart
@section introd_tut Introductory Tutorials
+221
View File
@@ -0,0 +1,221 @@
#!/usr/bin/env bash
#
# Release a new version of mlpack.
#
# Usage: release-mlpack.sh X Y Z
#
# where X is the major version, Y is the minor version, and Z is the patch
# version. Run this from the root of the repository.
#
# Make sure HISTORY.md is updated first!
set +e
if [ "$#" -ne "4" ];
then
echo "Usage: mlpack-release.sh <github username> <major> <minor> <patch>";
exit 1;
fi
# First, check for any unlicensed files.
output=$(
for i in $(find src/ -iname '*.[hc]pp');
do
echo -n $i": ";
cat $i | grep 'mlpack is free software;' | wc -l;
done |\
grep -v ': 1' |\
grep -v 'arma_extend' |\
grep -v 'boost_backport' |\
grep -v 'arma_config.hpp' |\
grep -v 'gitversion.hpp' |\
grep -v 'CLI11.hpp' |\
grep -v 'bindings/R/mlpack/src/boost/serialization' |\
grep -v 'tests/catch.hpp');
lines=`echo $output | grep -v '^[ ]*$' | wc -l`;
if [ "0$lines" -gt "0" ];
then
echo "Unlicensed files found! Aborting release.";
echo "$output";
exit 1;
fi
# Now, check that there are no local changes.
lines=`git diff | wc -l | sed -e 's/^\s*//g'`;
if [ "$lines" != "0" ]; then
echo "git diff returned a nonzero result!";
echo "";
git diff;
exit 1;
fi
# Next, make sure the origin is right.
dest_remote_name=`git remote -v |\
grep "mlpack/mlpack (fetch)" |\
head -1 |\
awk -F' ' '{ print $1 }'`;
if [ "a$dest_remote_name" == "a" ]; then
echo "No git remote found for https://github.com/mlpack/mlpack!";
echo "Make sure that you've got the ensmallen repository as a remote, and" \
"that the master branch from that remote is checked out.";
echo "You can do this with a fresh repository via \`git clone" \
"https://github.com/mlpack/mlpack\`.";
exit 1;
fi
# Also check that we're on the master branch, from the correct origin.
current_branch=`git branch --no-color | grep '^\* ' | awk -F' ' '{ print $2 }'`;
current_origin=`git rev-parse --abbrev-ref --symbolic-full-name @{u} |\
awk -F'/' '{ print $1 }'`;
if [ "a$current_branch" != "amaster" ]; then
echo "Current branch is $current_branch.";
echo "This script has to be run from the master branch.";
exit 1;
elif [ "a$current_origin" != "a$dest_remote_name" ]; then
echo "Current branch does not track from remote mlpack repository!";
echo "Instead, it tracks from $current_origin/master.";
echo "Make sure to check out a branch that tracks $dest_remote_name/master.";
exit 1;
fi
# Make sure `hub` is installed.
hub_output="`which hub`" || true;
if [ "a$hub_output" == "a" ]; then
echo "The Hub command-line tool must be installed for this script to run" \
"successfully.";
echo "See https://hub.github.com for more details and installation" \
"instructions.";
echo "";
echo "(apt-get install hub on Debian and Ubuntu)";
echo "(brew install hub via Homebrew)";
exit 1;
fi
# Check git remotes: we need to make sure we have a fork to push to.
github_user=$1;
remote_name`git remote -v |\
grep "$github_user/mlpack (push)" |\
head -1 |\
awk -F' ' '{ print $1 }'`;
if [ "a$remote_name" == "a" ]; then
echo "No git remote found for $github_user/mlpack!";
echo "Adding remote '$github_user'.";
git remote add $github_user https://github.com/$github_user/mlpack;
remote_name="$github_user";
fi
git fetch $github_user;
# Make sure everything is up to date.
git pull;
# Make updates to files that will be needed for the release.
MAJOR="$2";
MINOR="$3";
PATCH="$4";
# Update version.
sed --in-place -E 's/PROJECT_NUMBER([ \t]*)= .*$/PROJECT_NUMBER\1= '$MAJOR'.'$MINOR'.'$PATCH'/' \
Doxyfile;
sed --in-place 's/MLPACK_VERSION_MAJOR [0-9]*$/MLPACK_VERSION_MAJOR '$MAJOR'/' \
src/mlpack/core/util/version.hpp;
sed --in-place 's/MLPACK_VERSION_MINOR [0-9]*$/MLPACK_VERSION_MINOR '$MINOR'/' \
src/mlpack/core/util/version.hpp;
sed --in-place 's/MLPACK_VERSION_PATCH [0-9]*$/MLPACK_VERSION_PATCH '$PATCH'/' \
src/mlpack/core/util/version.hpp;
sed --in-place 's/ VERSION [0-9]*\.[0-9]*/ VERSION '$MAJOR'.'$MINOR'/' \
src/mlpack/CMakeLists.txt;
sed --in-place 's/mlpack-[0-9]\.[0-9]\.[0-9]/mlpack-'$MAJOR'.'$MINOR'.'$PATCH'/g' \
doc/guide/build.hpp;
sed --in-place 's/mlpack-[0-9]\.[0-9]\.[0-9]/mlpack-'$MAJOR'.'$MINOR'.'$PATCH'/g' \
doc/guide/python_quickstart.hpp;
sed --in-place 's/mlpack-[0-9]\.[0-9]\.[0-9]/mlpack-'$MAJOR'.'$MINOR'.'$PATCH'/g' \
doc/guide/sample_ml_app.hpp;
sed --in-place 's/mlpack-[0-9]\.[0-9]\.[0-9]/mlpack-'$MAJOR'.'$MINOR'.'$PATCH'/g' \
doc/examples/sample-ml-app/sample-ml-app/sample-ml-app.vcxproj;
sed --in-place 's/mlpack-[0-9]\.[0-9]\.[0-9]/mlpack-'$MAJOR'.'$MINOR'.'$PATCH'/g' \
README.md;
sed --in-place 's/([0-9]\.[0-9]\.[0-9])/('$MAJOR'.'$MINOR'.'$PATCH')/g' \
README.md;
sed --in-place 's/mlpack [0-9]\.[0-9]\.[0-9]/mlpack '$MAJOR'.'$MINOR'.'$PATCH'/g' \
README.md;
sed --in-place 's/### mlpack ?[.]?[.]?/### mlpack '$MAJOR'.'$MINOR'.'$PATCH'/g' HISTORY.md;
year=`date +%Y`;
month=`date +%m`;
day=`date +%d`;
sed --in-place 's/###### ????-??-??/###### '$year'-'$month'-'$day'/g' \
HISTORY.md;
# Get the latest release of ensmallen.
git clone https://github.com/mlpack/ensmallen /tmp/ensmallen;
cd /tmp/ensmallen;
ens_ver=`git describe --tags $(git rev-list --tags --max-count=1)`;
echo "Latest version of ensmallen: $ens_ver"
cd -;
sed --in-place "s/ensmallen-latest.tar.gz/ensmallen-$ens_ver.tar.gz/" CMakeLists.txt;
rm -rf /tmp/ensmallen;
# Make these changes on a release branch.
git checkout -b release-$MAJOR.$MINOR.$PATCH;
git add Doxyfile src/mlpack/core/util/version.hpp src/mlpack/CMakeLists.txt \
doc/guide/build.hpp doc/guide/python_quickstart.hpp \
doc/guide/sample_ml_app.hpp \
doc/examples/sample-ml-app/sample-ml-app/sample-ml-app.vcxproj \
CMakeLists.txt \
README.md \
HISTORY.md;
git commit -m "Update and release version $MAJOR.$MINOR.$PATCH.";
changelog_str=`cat HISTORY.md |\
awk '/^### /{f=0} /^### mlpack '"$MAJOR"'.'"$MINOR"'.'"$PATCH"'/{f=1} f{print}' |\
grep -v '^#' |\
tr '\n' '!' |\
sed -e 's/! [ ]*/ /g' |\
tr '!' '\n'`;
echo "Changelog string:"
echo "$changelog_str"
# Update version again and add a new block for HISTORY.md.
sed --in-place 's/MLPACK_VERSION_PATCH [0-9]*$/MLPACK_VERSION_PATCH '$(($PATCH + 1))'/' \
src/mlpack/core/util/version.hpp;
sed --in-place 's/ensmallen-'$ens_ver'.tar.gz/ensmallen-latest.tar.gz/' CMakeLists.txt;
echo "### mlpack ?.?.?" > HISTORY.md.new;
echo "###### ????-??-??" >> HISTORY.md.new;
echo "" >> HISTORY.md.new;
cat HISTORY.md >> HISTORY.md.new;
mv HISTORY.md.new HISTORY.md;
git add HISTORY.md;
git add src/mlpack/core/util/version.hpp CMakeLists.txt;
git commit -m "Add new block for next release to HISTORY.md.";
# Push to new branch.
git push --set-upstream $github_user release-$MAJOR.$MINOR.$PATCH;
# Next, we have to actually open the PR for the release.
hub pull-request \
-b mlpack:master \
-h $github_user:release-$MAJOR.$MINOR.$PATCH \
-m "Release version $MAJOR.$MINOR.$PATCH" \
-m "This automatically-generated pull request adds the commits necessary to
make the $MAJOR.$MINOR.$PATCH release." \
-m "Once the PR is merged, mlpack-bot will tag the release as HEAD~1 (so
that it doesn't include the new HISTORY block) and publish it." \
-m "Or, well, hopefully that will happen someday." \
-m "When you merge this PR, be sure to merge it using a *rebase*." \
-m "### Changelog" \
-m "$changelog_str" \
-l "t: release"
echo "";
echo "Switching back to 'master' branch.";
echo "If you want to access the release branch again, use \`git checkout " \
"release-$MAJOR.$MINOR.$PATCH\`.";
echo 0;
+65
View File
@@ -0,0 +1,65 @@
#!/usr/bin/env bash
#
# This script is used to update the website after an mlpack release is made.
# Push access to the mlpack.org website repository is needed. Generally, this
# script will be run by mlpack-bot, so it never needs to be run by hand.
#
# Usage: update-website-after-release.sh <major> <minor> <patch>
MAJOR=$1;
MINOR=$2;
PATCH=$3;
# Make sure that the mlpack repository exists.
dest_remote_name=`git remote -v |\
grep "mlpack/mlpack (fetch)" |\
head -1 |\
awk -F' ' '{ print $1 }'`;
if [ "a$dest_remote_name" == "a" ]; then
echo "No git remote found for mlpack/mlpack!";
echo "Make sure that you've got the mlpack repository as a remote, and" \
"that the master branch from that remote is checked out.";
echo "You can do this with a fresh repository via \`git clone" \
"https://github.com/mlpack/mlpack\`.";
exit 1;
fi
# Update the checked out repository, so that we can get the tags.
git fetch $dest_remote_name;
# Check out a copy of the ensmallen.org repository.
git clone git@github.com:mlpack/mlpack.org /tmp/mlpack.org/;
# Create the release file.
git archive --prefix=mlpack-$MAJOR.$MINOR.$PATCH/ $MAJOR.$MINOR.$PATCH |\
gzip > /tmp/mlpack.org/files/mlpack-$MAJOR.$MINOR.$PATCH.tar.gz;
# Now update the website.
wd=`pwd`;
cd /tmp/mlpack.org/;
# These may be specific to the old website.
sed --in-place 's/[0-9]\.[0-9]\.[0-9]/'$MAJOR'.'$MINOR'.'$PATCH'/g' index.md;
sed --in-place 's/[0-9]\.[0-9]\.[0-9]/'$MAJOR'.'$MINOR'.'$PATCH'/g' docs.md;
sed --in-place 's/[0-9]\.[0-9]\.[0-9]/'$MAJOR'.'$MINOR'.'$PATCH'/g' getstarted.md;
sed --in-place 's/[0-9]\.[0-9]\.[0-9]/'$MAJOR'.'$MINOR'.'$PATCH'/g' community.md;
git add index.md docs.md getstarted.md community.md;
# These may be specific to the new website.
sed --in-place 's/mlpack-[0-9]\.[0-9]\.[0-9]/mlpack-'$MAJOR'.'$MINOR'.'$PATCH'/g' html/index.html;
sed --in-place 's/Version [0-9]\.[0-9]\.[0-9]/Version '$MAJOR'.'$MINOR'.'$PATCH'/g' html/index.html;
sed --in-place 's/[0-9]\.[0-9]\.[0-9]/'$MAJOR'.'$MINOR'.'$PATCH'/g' html/getstarted.html;
sed --in-place 's/[0-9]\.[0-9]\.[0-9]/'$MAJOR'.'$MINOR'.'$PATCH'/g' html/config/install.md;
git add html/index.html html/getstarted.html html/config/install.md;
git commit -m "Update links to latest stable version.";
git add files/mlpack-$MAJOR.$MINOR.$PATCH.tar.gz;
git commit -m "Release version $MAJOR.$MINOR.$PATCH.";
# Finally, push, and we're done.
git push origin;
cd $wd;
rm -rf /tmp/mlpack.org;
+7 -63
View File
@@ -54,7 +54,7 @@ target_link_libraries(mlpack ${MLPACK_LIBRARIES})
set_target_properties(mlpack
PROPERTIES
VERSION 3.3
VERSION 3.4
SOVERSION 3
)
@@ -125,69 +125,13 @@ string(REGEX REPLACE ".*#define MLPACK_VERSION_PATCH [\"]?([0-9x]+)[\"]?.*"
set(PACKAGE_VERSION
"${MLPACK_VERSION_MAJOR}.${MLPACK_VERSION_MINOR}.${MLPACK_VERSION_PATCH}")
# If we are building Python bindings, we have to configure setup.py but only
# after we've recursed into methods/.
if (BUILDING_PYTHON_BINDINGS)
post_python_bindings()
post_julia_setup()
post_go_setup()
get_property(CYTHON_INCLUDE_DIRECTORIES DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
PROPERTY INCLUDE_DIRECTORIES)
add_custom_target(python_configure
COMMAND ${CMAKE_COMMAND}
-D SETUP_PY_IN=${CMAKE_SOURCE_DIR}/src/mlpack/bindings/python/setup.py.in
-D SETUP_PY_OUT=${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/setup.py
-D PACKAGE_VERSION="${PACKAGE_VERSION}"
-D Boost_SERIALIZATION_LIBRARY="${Boost_SERIALIZATION_LIBRARY_RELEASE}"
-D Boost_LIBRARY_DIRS="${Boost_LIBRARY_DIRS}"
-D ARMADILLO_LIBRARIES="${ARMADILLO_LIBRARIES}"
-D MLPACK_LIBRARY=$<TARGET_LINKER_FILE:mlpack>
-D MLPACK_LIBDIR=$<TARGET_LINKER_FILE_DIR:mlpack>
-D MLPACK_PYXS="${MLPACK_PYXS}"
-D OpenMP_CXX_FLAGS="${OpenMP_CXX_FLAGS}"
-D DISABLE_CFLAGS="${DISABLE_CFLAGS}"
-D CYTHON_INCLUDE_DIRECTORIES="${CYTHON_INCLUDE_DIRECTORIES}"
-D CMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}
-D OUTPUT_DIR=${CMAKE_BINARY_DIR}
-P "${CMAKE_SOURCE_DIR}/src/mlpack/bindings/python/ConfigureSetup.cmake"
BYPRODUCTS "${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/setup.py"
COMMENT "Configuring setup.py...")
add_dependencies(python_configure python_copy)
add_dependencies(python_configured python_configure)
# Append the package version to __init__.py after all the imports are loaded.
file(APPEND ${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/mlpack/__init__.py
"__version__='${PACKAGE_VERSION}'\n")
endif ()
# If we are building Julia bindings, we have to end the 'module' declaration in
# mlpack.jl
if (BUILD_JULIA_BINDINGS)
file(APPEND
"${CMAKE_BINARY_DIR}/src/mlpack/bindings/julia/mlpack/src/mlpack.jl"
"\nend\ninclude(\"functions.jl\")\ninclude(\"serialization.jl\")\nend\n")
endif ()
# If we are building Go bindings, we have to end the 'module' declaration in
# models.go
if (BUILD_GO_BINDINGS)
file(APPEND
"${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/src/mlpack.org/v1/mlpack/models.go"
"*/\n"
"import \"C\"\n\n"
"import (\n"
" \"runtime\"\n"
" \"unsafe\"\n"
")\n\n")
include("${CMAKE_SOURCE_DIR}/CMake/go/AppendModel.cmake")
# Read list content.
get_property(MODELS GLOBAL PROPERTY GO_MODELS)
foreach (models IN LISTS MODELS)
append_model(
"${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/src/mlpack.org/v1/mlpack/models.go"
${models})
endforeach()
endif()
# If we are building R-bindings, we have to run some setup after we
# recurse into methods/. If not, this macro is empty.
post_r_setup()
# If we are building Markdown documentation, we have to run some setup after we
# recurse into methods/. If not, this function is empty.
+1
View File
@@ -5,6 +5,7 @@ set(DIRS
markdown
python
go
R
tests
)
+443
View File
@@ -0,0 +1,443 @@
macro (not_found_return message)
message(STATUS "${message}")
macro (add_r_binding name)
# Do nothing.
endmacro ()
macro (post_r_setup)
# Do nothing.
endmacro ()
return()
endmacro ()
# If we are not supposed to make R bindings, define the macro so it does
# nothing and leave this file.
if (NOT BUILD_R_BINDINGS)
not_found_return("Not building R bindings.")
endif ()
if (BUILD_R_BINDINGS)
# If mlpack upgrade the version of dependencies, then we also have to update the version here.
set(RcppArmadillo_Version "0.${ARMADILLO_VERSION}")
set(RcppEnsmallen_Version "0.${ENSMALLEN_VERSION}")
set(BH_Version "${BOOST_VERSION}")
# Import find_r_module.
include(${CMAKE_SOURCE_DIR}/CMake/FindRModule.cmake)
find_package(R 4.0)
if (NOT R_FOUND)
set(R_NOT_FOUND_MSG "${R_NOT_FOUND_MSG}\n - R")
endif ()
find_r_module(roxygen2)
if (NOT R_ROXYGEN2)
set(R_NOT_FOUND_MSG "${R_NOT_FOUND_MSG}\n - roxygen2")
endif ()
find_r_module(Rcpp 0.12.12)
if (NOT R_RCPP)
set(R_NOT_FOUND_MSG "${R_NOT_FOUND_MSG}\n - Rcpp")
endif ()
find_r_module(RcppArmadillo "${RcppArmadillo_Version}")
if (NOT R_RCPPARMADILLO)
set(R_NOT_FOUND_MSG "${R_NOT_FOUND_MSG}\n - RcppArmadillo")
endif ()
find_r_module(RcppEnsmallen "${RcppEnsmallen_Version}")
if (NOT R_RCPPENSMALLEN)
set(R_NOT_FOUND_MSG "${R_NOT_FOUND_MSG}\n - RcppEnsmallen")
endif ()
find_r_module(BH "${BH_Version}")
if (NOT R_BH)
set(R_NOT_FOUND_MSG "${R_NOT_FOUND_MSG}\n - BH")
endif ()
find_r_module(testthat)
if (NOT R_TESTTHAT)
set(R_NOT_FOUND_MSG "${R_NOT_FOUND_MSG}\n - testthat")
endif ()
## We need to check here if R and other dependencies is even available, as
## it is require to build R-bindings.
if (FORCE_BUILD_R_BINDINGS)
if (NOT R_FOUND OR NOT R_RCPP OR NOT R_RCPPARMADILLO OR NOT R_RCPPENSMALLEN
OR NOT R_BH OR NOT R_ROXYGEN2 OR NOT R_TESTTHAT)
unset(BUILD_R_BINDINGS CACHE)
message(FATAL_ERROR "Could not Build R Bindings, Following modules are not available:${R_NOT_FOUND_MSG}")
endif()
else ()
if (NOT R_FOUND OR NOT R_RCPP OR NOT R_RCPPARMADILLO OR NOT R_RCPPENSMALLEN
OR NOT R_BH OR NOT R_ROXYGEN2 OR NOT R_TESTTHAT)
unset(BUILD_R_BINDINGS CACHE)
not_found_return("Not building R bindings, Following modules are not available:${R_NOT_FOUND_MSG}")
endif()
endif ()
add_custom_target(R ALL)
# Now configure DESCRIPTION.
file(READ "${CMAKE_SOURCE_DIR}/src/mlpack/core/util/version.hpp"
VERSION_HPP_CONTENTS)
string(REGEX REPLACE ".*#define MLPACK_VERSION_MAJOR ([0-9]+).*" "\\1"
MLPACK_VERSION_MAJOR "${VERSION_HPP_CONTENTS}")
string(REGEX REPLACE ".*#define MLPACK_VERSION_MINOR ([0-9]+).*" "\\1"
MLPACK_VERSION_MINOR "${VERSION_HPP_CONTENTS}")
string(REGEX REPLACE ".*#define MLPACK_VERSION_PATCH [\"]?([0-9x]+)[\"]?.*"
"\\1" MLPACK_VERSION_PATCH "${VERSION_HPP_CONTENTS}")
set(PACKAGE_VERSION
"${MLPACK_VERSION_MAJOR}.${MLPACK_VERSION_MINOR}.${MLPACK_VERSION_PATCH}")
string(TIMESTAMP PACKAGE_DATE "%Y-%m-%d")
configure_file(${CMAKE_SOURCE_DIR}/src/mlpack/bindings/R/mlpack/DESCRIPTION.in
${CMAKE_CURRENT_BINARY_DIR}/mlpack/DESCRIPTION
@ONLY)
# Create the empty NAMESPACE file that will include all export functions.
file(WRITE
"${CMAKE_CURRENT_BINARY_DIR}/mlpack/NAMESPACE"
"# Generated by roxygen2: do not edit by hand"
"\n\n")
set(CPP_SOURCES
"${CMAKE_CURRENT_SOURCE_DIR}/mlpack/src/r_util.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/mlpack/src/rcpp_mlpack.h"
"${CMAKE_CURRENT_SOURCE_DIR}/mlpack/src/Makevars"
"${CMAKE_CURRENT_SOURCE_DIR}/mlpack/src/Makevars.win"
)
set(R_SOURCES
"${CMAKE_CURRENT_SOURCE_DIR}/mlpack/R/matrix_utils.R"
"${CMAKE_CURRENT_SOURCE_DIR}/mlpack/R/package.R"
)
set(BINDINGS_SOURCES
"${CMAKE_CURRENT_SOURCE_DIR}/get_type.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/print_doc.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/print_doc_functions.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/print_doc_functions_impl.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/print_input_param.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/get_param.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/get_printable_param.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/get_r_type.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/print_input_processing.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/print_output_processing.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/print_serialize_util.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/R_option.hpp"
)
set(TESTS_SOURCES
"${CMAKE_CURRENT_SOURCE_DIR}/tests/test_r_binding_main.cpp"
)
set(R_TESTTHAT_SOURCES
"${CMAKE_CURRENT_SOURCE_DIR}/mlpack/tests/testthat/test-R_binding.R"
)
set(R_TESTS_SOURCES
"${CMAKE_CURRENT_SOURCE_DIR}/mlpack/tests/testthat.R"
)
set(LICENSE_SOURCES
"${CMAKE_SOURCE_DIR}/LICENSE.txt"
)
add_custom_target(r_copy ALL)
# First we have to create all the required directories for copy.
add_custom_command(TARGET r_copy PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory
${CMAKE_CURRENT_BINARY_DIR}/mlpack/R/
COMMAND ${CMAKE_COMMAND} -E make_directory
${CMAKE_CURRENT_BINARY_DIR}/mlpack/tests/testthat
COMMAND ${CMAKE_COMMAND} -E make_directory
${CMAKE_CURRENT_BINARY_DIR}/mlpack/src/mlpack/bindings/R/tests
)
if (BUILD_TESTS)
add_custom_command(TARGET r_copy PRE_BUILD
COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different
${TESTS_SOURCES}
${CMAKE_CURRENT_BINARY_DIR}/mlpack/src/mlpack/bindings/R/tests)
endif()
# Copy all necessary files for building package.
foreach(cpp_file ${CPP_SOURCES})
add_custom_command(TARGET r_copy PRE_BUILD
COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different
${cpp_file}
${CMAKE_CURRENT_BINARY_DIR}/mlpack/src/)
endforeach()
foreach(r_file ${R_SOURCES})
add_custom_command(TARGET r_copy PRE_BUILD
COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different
${r_file}
${CMAKE_CURRENT_BINARY_DIR}/mlpack/R/)
endforeach()
foreach(bindings_file ${BINDINGS_SOURCES})
add_custom_command(TARGET r_copy PRE_BUILD
COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different
${bindings_file}
${CMAKE_CURRENT_BINARY_DIR}/mlpack/src/mlpack/bindings/R)
endforeach()
add_custom_command(TARGET r_copy PRE_BUILD
COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different
${R_TESTTHAT_SOURCES}
${CMAKE_CURRENT_BINARY_DIR}/mlpack/tests/testthat)
add_custom_command(TARGET r_copy PRE_BUILD
COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different
${R_TESTS_SOURCES}
${CMAKE_CURRENT_BINARY_DIR}/mlpack/tests)
add_custom_command(TARGET r_copy PRE_BUILD
COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different
${LICENSE_SOURCES}
${CMAKE_CURRENT_BINARY_DIR}/mlpack)
add_custom_command(TARGET r_copy PRE_BUILD
COMMAND ${CMAKE_COMMAND} ARGS -E rename
"${CMAKE_CURRENT_BINARY_DIR}/mlpack/LICENSE.txt"
"${CMAKE_CURRENT_BINARY_DIR}/mlpack/LICENSE")
# This file will take care of multiple definition of functions in .cpp files.
add_custom_command(TARGET r_copy PRE_BUILD
COMMAND ${CMAKE_COMMAND} ARGS -E touch
"${CMAKE_CURRENT_BINARY_DIR}/mlpack/model.txt")
file(COPY
"${CMAKE_CURRENT_SOURCE_DIR}/mlpack/cleanup"
DESTINATION
"${CMAKE_CURRENT_BINARY_DIR}/mlpack/")
# Do the actual build.
add_custom_target(r_build ALL)
# "model.txt" is no longer useful, after generating src/.cpp files.
# Remove this file.
add_custom_command(TARGET r_build POST_BUILD
COMMAND ${CMAKE_COMMAND} ARGS -E remove -f "model.txt"
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mlpack"
)
# Build RcppExports.cpp/.R, NAMESPACE and man/ files.
add_custom_command(TARGET r_build POST_BUILD
COMMAND ${RSCRIPT_EXECUTABLE} ARGS "-e" "'Rcpp::compileAttributes()'"
COMMAND ${RSCRIPT_EXECUTABLE} ARGS "-e" "'roxygen2::roxygenize(\".\")'"
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mlpack"
)
# Build mlpack_${PACKAGE_VERSION}.tar.gz package.
add_custom_command(TARGET r_build POST_BUILD
COMMAND ${R_EXECUTABLE} CMD build mlpack
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
)
# Installation script for the packagae.
install(CODE
"execute_process(
COMMAND R CMD INSTALL mlpack_${PACKAGE_VERSION}.tar.gz
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}"
)
add_dependencies(R r_build)
endif ()
# Define a global list of models, use for building serialization.R file.
define_property(GLOBAL PROPERTY R_MODELS
BRIEF_DOCS "Global list of models"
FULL_DOCS "Global list of models"
)
# Initialize list of models.
set_property(GLOBAL PROPERTY R_MODELS "")
macro (add_r_binding name)
if (BUILD_R_BINDINGS)
# Append content to the list of models.
set_property(GLOBAL APPEND PROPERTY R_MODELS ${CMAKE_CURRENT_SOURCE_DIR}/${name}_main.cpp)
# 1. Generate ${name}.cpp.
add_custom_command(OUTPUT
${CMAKE_BINARY_DIR}/src/mlpack/bindings/R/mlpack/src/${name}.cpp
COMMAND ${CMAKE_COMMAND}
-DMODEL_FILE=${CMAKE_BINARY_DIR}/src/mlpack/bindings/R/mlpack/model.txt
-DPROGRAM_NAME=${name}
-DPROGRAM_MAIN_FILE=${CMAKE_CURRENT_SOURCE_DIR}/${name}_main.cpp
-DSOURCE_DIR=${CMAKE_SOURCE_DIR}
-DR_CPP_IN=${CMAKE_SOURCE_DIR}/src/mlpack/bindings/R/r_method.cpp.in
-DR_CPP_OUT=${CMAKE_BINARY_DIR}/src/mlpack/bindings/R/mlpack/src/${name}.cpp
-P ${CMAKE_SOURCE_DIR}/CMake/R/ConfigureRCPP.cmake
DEPENDS ${CMAKE_SOURCE_DIR}/src/mlpack/bindings/R/r_method.cpp.in
${CMAKE_SOURCE_DIR}/CMake/R/ConfigureRCPP.cmake)
# 2. Generate ${name}.R.
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/src/mlpack/bindings/R/build/generate_r_${name}.cpp
COMMAND ${CMAKE_COMMAND}
-DNAME=${name}
-DGENERATE_CPP_IN=${CMAKE_SOURCE_DIR}/src/mlpack/bindings/R/generate_R.cpp.in
-DGENERATE_CPP_OUT=${CMAKE_BINARY_DIR}/src/mlpack/bindings/R/build/generate_r_${name}.cpp
-DPROGRAM_MAIN_FILE=${CMAKE_CURRENT_SOURCE_DIR}/${name}_main.cpp
-P ${CMAKE_SOURCE_DIR}/CMake/ConfigureFile.cmake
DEPENDS ${CMAKE_SOURCE_DIR}/src/mlpack/bindings/R/generate_R.cpp.in
${CMAKE_SOURCE_DIR}/CMake/ConfigureFile.cmake
${CMAKE_BINARY_DIR}/src/mlpack/bindings/R/mlpack/src/${name}.cpp)
add_executable(generate_r_${name}
${CMAKE_BINARY_DIR}/src/mlpack/bindings/R/build/generate_r_${name}.cpp
${CMAKE_SOURCE_DIR}/src/mlpack/bindings/R/print_R.hpp
${CMAKE_SOURCE_DIR}/src/mlpack/bindings/R/print_R.cpp
${CMAKE_SOURCE_DIR}/src/mlpack/bindings/R/get_type.hpp
${CMAKE_SOURCE_DIR}/src/mlpack/bindings/R/R_option.hpp
${CMAKE_SOURCE_DIR}/src/mlpack/bindings/R/print_input_param.hpp
${CMAKE_SOURCE_DIR}/src/mlpack/bindings/R/print_input_processing.hpp
${CMAKE_SOURCE_DIR}/src/mlpack/bindings/R/print_serialize_util.hpp
${CMAKE_SOURCE_DIR}/src/mlpack/bindings/R/print_output_processing.hpp)
target_link_libraries(generate_r_${name} mlpack ${MLPACK_LIBRARIES})
set_target_properties(generate_r_${name} PROPERTIES
COMPILE_FLAGS "-DBINDING_TYPE=BINDING_TYPE_R"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/src/mlpack/bindings/R/build/bin/")
add_custom_command(TARGET generate_r_${name} POST_BUILD
COMMAND ${CMAKE_COMMAND}
-DGENERATE_BINDING_PROGRAM=${CMAKE_BINARY_DIR}/src/mlpack/bindings/R/build/bin/generate_r_${name}
-DBINDING_OUTPUT_FILE=${CMAKE_BINARY_DIR}/src/mlpack/bindings/R/mlpack/R/${name}.R
-P ${CMAKE_SOURCE_DIR}/CMake/GenerateBinding.cmake)
add_dependencies(generate_r_${name} r_copy)
add_dependencies(r_build generate_r_${name})
endif()
endmacro()
macro (post_r_setup)
# In Case of R_Bindings Move all of these header and source files to
# <package>/src/mlpack/.
# Collect all header and source files in the library.
file(GLOB_RECURSE R_SRC_HPP_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" *.hpp)
file(GLOB_RECURSE R_SRC_CPP_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" *.cpp)
set(R_SRC_FILES ${R_SRC_HPP_FILES} ${R_SRC_CPP_FILES})
# In case of R_Bindings we are copying all of these header to
# <package>/src/cereal/ because the currently-packaged version
# of Rcereal throws warnings on CRAN.
# Collect all header files in the cereal folder.
file(GLOB_RECURSE RCEREAL_SRC_H_FILES RELATIVE "${CEREAL_INCLUDE_DIR}"
"${CEREAL_INCLUDE_DIR}/cereal/*.h")
file(GLOB_RECURSE RCEREAL_SRC_HPP_FILES RELATIVE "${CEREAL_INCLUDE_DIR}"
"${CEREAL_INCLUDE_DIR}/cereal/*.hpp")
set(RCEREAL_SRC_FILES ${RCEREAL_SRC_HPP_FILES} ${RCEREAL_SRC_H_FILES})
# First we have to create that directory though.
execute_process(
COMMAND ${CMAKE_COMMAND} -E
make_directory ${CMAKE_BINARY_DIR}/src/mlpack/bindings/R/mlpack/src/mlpack
)
# Then copy each of the header and source files over to that directory.
set(MLPACK_SOURCES
"${CMAKE_BINARY_DIR}/src/mlpack/mlpack_export.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/prereqs.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/core.hpp"
)
foreach(mlpack_sources ${MLPACK_SOURCES})
execute_process(
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${mlpack_sources}
${CMAKE_BINARY_DIR}/src/mlpack/bindings/R/mlpack/src/mlpack
)
endforeach()
foreach(r_src_file ${R_SRC_FILES})
if ("${r_src_file}" MATCHES "methods/" OR
"${r_src_file}" MATCHES "core/" OR
"${r_src_file}" MATCHES "bindings/util")
execute_process(
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${CMAKE_CURRENT_SOURCE_DIR}/${r_src_file}
${CMAKE_BINARY_DIR}/src/mlpack/bindings/R/mlpack/src/mlpack/${r_src_file}
)
# Collect path of all source files and append to ${R_SRC}.
if ("${r_src_file}" MATCHES ".cpp" AND
NOT "${r_src_file}" MATCHES "main.cpp" AND
# Note: this implementation of MVU does not work. See #189.
NOT "${r_src_file}" MATCHES "mvu")
string(APPEND R_SRC "#include <mlpack/${r_src_file}>\n")
endif()
endif()
endforeach()
# Copy cereal headers for R-bindings.
foreach(rcereal_src_file ${RCEREAL_SRC_FILES})
execute_process(
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${CEREAL_INCLUDE_DIR}/${rcereal_src_file}
${CMAKE_BINARY_DIR}/src/mlpack/bindings/R/mlpack/src/${rcereal_src_file}
)
endforeach()
# Resolve gcc Warnings.
file(READ ${CMAKE_BINARY_DIR}/src/mlpack/bindings/R/mlpack/src/cereal/external/base64.hpp CEREAL_BASE64)
string(REGEX REPLACE
"\n#ifdef __GNUC__\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wconversion\"\n#endif\n"
"" CEREAL_BASE64 "${CEREAL_BASE64}")
string(REGEX REPLACE
"#ifdef __GNUC__\n#pragma GCC diagnostic pop\n#endif"
"" CEREAL_BASE64 "${CEREAL_BASE64}")
file(WRITE ${CMAKE_BINARY_DIR}/src/mlpack/bindings/R/mlpack/src/cereal/external/base64.hpp "${CEREAL_BASE64}")
# Then configure 'mlpack.h.in' using ${R_SRC}.
configure_file(
${CMAKE_SOURCE_DIR}/src/mlpack/bindings/R/mlpack/inst/include/mlpack.h.in
${CMAKE_BINARY_DIR}/src/mlpack/bindings/R/mlpack/inst/include/mlpack.h
@ONLY)
file(WRITE
"${CMAKE_BINARY_DIR}/src/mlpack/bindings/R/mlpack/R/serialization.R"
"#' Serialize/Unserialize an mlpack model.\n"
"#'\n"
"#' @param model Input model pointer.\n"
"#' @param filename Input filename.\n"
"#' @export\n"
"#' @rdname mlpack-serialization\n"
"Serialize <- function(model, filename) {\n"
" model_serialization_function <-\n"
" switch(attributes(model)$type,\n")
include("${CMAKE_SOURCE_DIR}/CMake/R/AppendSerialization.cmake")
# Read list content.
get_property(MODELS GLOBAL PROPERTY R_MODELS)
foreach (models IN LISTS MODELS)
append_serialization(
"${CMAKE_BINARY_DIR}/src/mlpack/bindings/R/mlpack/R/serialization.R"
${models}
TRUE)
endforeach()
file(APPEND
"${CMAKE_BINARY_DIR}/src/mlpack/bindings/R/mlpack/R/serialization.R"
" stop(\"Requested model type is not currently supported.\")\n )\n\n"
" # Read in model\n"
" con <- file(as.character(filename), \"wb\")\n"
" serialize(model_serialization_function(model), con)\n"
" close(con)\n}\n\n\n"
"#' @return For Unserialize, Output model_ptr.\n"
"#' @export\n"
"#' @rdname mlpack-serialization\n"
"Unserialize <- function(filename) {\n"
" con <- file(as.character(filename), \"rb\")\n"
" model <- unserialize(con)\n\n"
" model_unserialization_function <-\n"
" switch(attributes(model)$type,\n")
foreach (models IN LISTS MODELS)
append_serialization(
"${CMAKE_BINARY_DIR}/src/mlpack/bindings/R/mlpack/R/serialization.R"
${models}
FALSE)
endforeach()
file(APPEND
"${CMAKE_BINARY_DIR}/src/mlpack/bindings/R/mlpack/R/serialization.R"
" stop(\"Requested model type is not currently supported.\")\n )\n\n"
" model_ptr <- model_unserialization_function(model)\n"
" close(con)\n"
" return(model_ptr)\n}\n")
endmacro()
if (BUILD_TESTS AND BUILD_R_BINDINGS)
add_subdirectory(tests)
endif ()
+121
View File
@@ -0,0 +1,121 @@
/**
* @file bindings/R/R_option.hpp
* @author Yashwant Singh Parihar
*
* The R option type.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#ifndef MLPACK_BINDINGS_R_R_OPTION_HPP
#define MLPACK_BINDINGS_R_R_OPTION_HPP
#include <mlpack/core/util/param_data.hpp>
#include "get_param.hpp"
#include "get_printable_param.hpp"
#include "print_input_param.hpp"
#include "print_input_processing.hpp"
#include "print_output_processing.hpp"
#include "print_doc.hpp"
#include "print_serialize_util.hpp"
namespace mlpack {
namespace bindings {
namespace r {
/**
* The R option class.
*/
template<typename T>
class ROption
{
public:
/**
* Construct a ROption object. When constructed, it will register itself
* with IO. The testName parameter is not used and added for compatibility
* reasons.
*
* @param defaultValue Default value this parameter will be initialized to
* (for flags, this should be false, for instance).
* @param identifier The name of the option (no dashes in front; for --help,
* we would pass "help").
* @param description A short string describing the option.
* @param alias Short name of the parameter. "" for no alias.
* @param cppName Name of the C++ type of this parameter (i.e. "int").
* @param required Whether or not the option is required at runtime.
* @param input Whether or not the option is an input option.
* @param noTranspose If the parameter is a matrix and this is true, then the
* matrix will not be transposed on loading.
* @param * (testName) Is not used and added for compatibility reasons.
*/
ROption(const T defaultValue,
const std::string& identifier,
const std::string& description,
const std::string& alias,
const std::string& cppName,
const bool required = false,
const bool input = true,
const bool noTranspose = false,
const std::string& /* testName */ = "")
{
// Create the ParamData object to give to IO.
util::ParamData data;
data.desc = description;
data.name = identifier;
data.tname = TYPENAME(T);
data.alias = alias[0];
data.wasPassed = false;
data.noTranspose = noTranspose;
data.required = required;
data.input = input;
data.loaded = false;
// Only "verbose" will be persistent.
if (identifier == "verbose")
data.persistent = true;
else
data.persistent = false;
data.cppType = cppName;
// Every parameter we'll get from R will have the correct type.
data.value = boost::any(defaultValue);
// Restore the parameters for this program.
if (identifier != "verbose")
IO::RestoreSettings(IO::ProgramName(), false);
// Set the function pointers that we'll need. All of these function
// pointers will be used by both the program that generates the R, and
// also the binding itself. (The binding itself will only use GetParam,
// GetPrintableParam, and GetRawParam.)
IO::GetSingleton().functionMap[data.tname]["GetParam"] = &GetParam<T>;
IO::GetSingleton().functionMap[data.tname]["GetPrintableParam"] =
&GetPrintableParam<T>;
// These are used by the R generator.
IO::GetSingleton().functionMap[data.tname]["PrintDoc"] = &PrintDoc<T>;
IO::GetSingleton().functionMap[data.tname]["PrintInputParam"] =
&PrintInputParam<T>;
IO::GetSingleton().functionMap[data.tname]["PrintOutputProcessing"] =
&PrintOutputProcessing<T>;
IO::GetSingleton().functionMap[data.tname]["PrintInputProcessing"] =
&PrintInputProcessing<T>;
IO::GetSingleton().functionMap[data.tname]["PrintSerializeUtil"] =
&PrintSerializeUtil<T>;
// Add the ParamData object, then store. This is necessary because we may
// import more than one .so or .o that uses IO, so we have to keep the
// options separate. programName is a global variable from mlpack_main.hpp.
IO::Add(std::move(data));
if (identifier != "verbose")
IO::StoreSettings(IO::ProgramName());
IO::ClearSettings();
}
};
} // namespace r
} // namespace bindings
} // namespace mlpack
#endif
+95
View File
@@ -0,0 +1,95 @@
/**
* @file bindings/R/default_param.hpp
* @author Yashwant Singh Parihar
*
* Return the default value of a parameter, depending on its type.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#ifndef MLPACK_BINDINGS_R_DEFAULT_PARAM_HPP
#define MLPACK_BINDINGS_R_DEFAULT_PARAM_HPP
#include <mlpack/prereqs.hpp>
#include <mlpack/core/util/param_data.hpp>
#include <mlpack/core/util/is_std_vector.hpp>
namespace mlpack {
namespace bindings {
namespace r {
/**
* Return the default value of an option. This is for regular types.
*/
template<typename T>
std::string DefaultParamImpl(
util::ParamData& data,
const typename boost::disable_if<arma::is_arma_type<T>>::type* = 0,
const typename boost::disable_if<util::IsStdVector<T>>::type* = 0,
const typename boost::disable_if<data::HasSerialize<T>>::type* = 0,
const typename boost::disable_if<std::is_same<T, std::string>>::type* = 0,
const typename boost::disable_if<std::is_same<T,
std::tuple<mlpack::data::DatasetInfo, arma::mat>>>::type* = 0);
/**
* Return the default value of a vector option.
*/
template<typename T>
std::string DefaultParamImpl(
util::ParamData& data,
const typename boost::enable_if<util::IsStdVector<T>>::type* = 0);
/**
* Return the default value of a string option.
*/
template<typename T>
std::string DefaultParamImpl(
util::ParamData& data,
const typename boost::enable_if<std::is_same<T, std::string>>::type* = 0);
/**
* Return the default value of a matrix option, a tuple option, a
* serializable option, or a string option (this returns the default filename,
* or '' if the default is no file).
*/
template<typename T>
std::string DefaultParamImpl(
util::ParamData& data,
const typename boost::enable_if_c<
arma::is_arma_type<T>::value ||
std::is_same<T, std::tuple<mlpack::data::DatasetInfo,
arma::mat>>::value>::type* /* junk */ = 0);
/**
* Return the default value of a model option (this returns the default
* filename, or '' if the default is no file).
*/
template<typename T>
std::string DefaultParamImpl(
util::ParamData& data,
const typename boost::disable_if<arma::is_arma_type<T>>::type* = 0,
const typename boost::enable_if<data::HasSerialize<T>>::type* = 0);
/**
* Return the default value of an option. This is the function that will be
* placed into the IO functionMap.
*/
template<typename T>
void DefaultParam(util::ParamData& data,
const void* /* input */,
void* output)
{
std::string* outstr = (std::string*) output;
*outstr = DefaultParamImpl<typename std::remove_pointer<T>::type>(data);
}
} // namespace r
} // namespace bindings
} // namespace mlpack
// Include implementation.
#include "default_param_impl.hpp"
#endif
@@ -0,0 +1,145 @@
/**
* @file bindings/R/default_param_impl.hpp
* @author Yashwant Singh Parihar
*
* Return the default value of a parameter, depending on its type.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#ifndef MLPACK_BINDINGS_R_DEFAULT_PARAM_IMPL_HPP
#define MLPACK_BINDINGS_R_DEFAULT_PARAM_IMPL_HPP
#include "default_param.hpp"
namespace mlpack {
namespace bindings {
namespace r {
/**
* Return the default value of an option.
*/
template<typename T>
std::string DefaultParamImpl(
util::ParamData& data,
const typename boost::disable_if<arma::is_arma_type<T>>::type* /* junk */,
const typename boost::disable_if<util::IsStdVector<T>>::type* /* junk */,
const typename boost::disable_if<data::HasSerialize<T>>::type* /* junk */,
const typename boost::disable_if<std::is_same<T, std::string>>::type*,
const typename boost::disable_if<std::is_same<T,
std::tuple<mlpack::data::DatasetInfo, arma::mat>>>::type* /* junk */)
{
std::ostringstream oss;
if (std::is_same<T, bool>::value)
oss << "FALSE";
else
oss << boost::any_cast<T>(data.value);
return oss.str();
}
/**
* Return the default value of a vector option.
*/
template<typename T>
std::string DefaultParamImpl(
util::ParamData& data,
const typename boost::enable_if<util::IsStdVector<T>>::type* /* junk */)
{
// Print each element in an array delimited by square brackets.
std::ostringstream oss;
const T& vector = boost::any_cast<T>(data.value);
oss << "c(";
if (std::is_same<T, std::vector<std::string>>::value)
{
if (vector.size() > 0)
{
for (size_t i = 0; i < vector.size() - 1; ++i)
{
oss << "'" << vector[i] << "', ";
}
oss << "'" << vector[vector.size() - 1] << "'";
}
oss << ")";
}
else
{
if (vector.size() > 0)
{
for (size_t i = 0; i < vector.size() - 1; ++i)
{
oss << vector[i] << ", ";
}
oss << vector[vector.size() - 1];
}
oss << ")";
}
return oss.str();
}
/**
* Return the default value of a string option.
*/
template<typename T>
std::string DefaultParamImpl(
util::ParamData& data,
const typename boost::enable_if<std::is_same<T, std::string>>::type*)
{
const std::string& s = *boost::any_cast<std::string>(&data.value);
return "\"" + s + "\"";
}
/**
* Return the default value of a matrix option (this returns the default
* filename, or '' if the default is no file).
*/
template<typename T>
std::string DefaultParamImpl(
util::ParamData& /* data */,
const typename boost::enable_if_c<
arma::is_arma_type<T>::value ||
std::is_same<T, std::tuple<mlpack::data::DatasetInfo,
arma::mat>>::value>::type* /* junk */)
{
// Get the filename and return it, or return an empty string.
if (std::is_same<T, arma::rowvec>::value ||
std::is_same<T, arma::vec>::value ||
std::is_same<T, arma::mat>::value)
{
return "matrix(numeric(), 0, 0)";
}
else if (std::is_same<T, arma::Row<size_t>>::value ||
std::is_same<T, arma::Col<size_t>>::value ||
std::is_same<T, arma::Mat<size_t>>::value)
{
return "matrix(integer(), 0, 0)";
}
else
{
return "matrix(numeric(), 0, 0)";
}
}
/**
* Return the default value of a model option (always "None").
*/
template<typename T>
std::string DefaultParamImpl(
util::ParamData& /* data */,
const typename boost::disable_if<arma::is_arma_type<T>>::type* /* junk */,
const typename boost::enable_if<data::HasSerialize<T>>::type* /* junk */)
{
return "NA";
}
} // namespace r
} // namespace bindings
} // namespace mlpack
#endif
+39
View File
@@ -0,0 +1,39 @@
/**
* @file R/generate_R.cpp.in
* @author Yashwant Singh Parihar
*
* This is a template file to call the PrintR() function for a given binding.
*/
#define BINDING_TYPE BINDING_TYPE_R
// Disable debug output.
#ifdef DEBUG
#define HAD_DEBUG
#undef DEBUG
#endif
#include <mlpack/core/util/log.hpp>
#ifdef HAD_DEBUG
#undef HAD_DEBUG
#define DEBUG
#endif
#include <mlpack/core.hpp>
#include <mlpack/core/util/mlpack_main.hpp>
#include <mlpack/bindings/R/print_R.hpp>
// This will include the ParamData options that are part of the program.
#include <${PROGRAM_MAIN_FILE}>
using namespace mlpack;
using namespace mlpack::bindings;
using namespace mlpack::bindings::r;
using namespace std;
using namespace mlpack::util;
int main(int /* argc */, char** /* argv */)
{
// All the parameters are registered, but stored, so restore them.
// programName is defined in mlpack_main.hpp.
IO::RestoreSettings(IO::ProgramName());
PrintR(IO::GetSingleton().doc, "${NAME}");
}
+37
View File
@@ -0,0 +1,37 @@
/**
* @file bindings/R/get_param.hpp
* @author Yashwant Singh Parihar
*
* Get a parameter for a R binding.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#ifndef MLPACK_BINDINGS_R_GET_PARAM_HPP
#define MLPACK_BINDINGS_R_GET_PARAM_HPP
#include <mlpack/prereqs.hpp>
namespace mlpack {
namespace bindings {
namespace r {
/**
* All R binding types are exactly what is held in the ParamData, so no
* special handling is necessary.
*/
template<typename T>
void GetParam(util::ParamData& d,
const void* /* input */,
void* output)
{
*((T**) output) = const_cast<T*>(boost::any_cast<T>(&d.value));
}
} // namespace r
} // namespace bindings
} // namespace mlpack
#endif
@@ -0,0 +1,126 @@
/**
* @file bindings/R/get_printable_param.hpp
* @author Yashwant Singh Parihar
*
* Get a printable version of parameters.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#ifndef MLPACK_BINDINGS_R_GET_PRINTABLE_PARAM_HPP
#define MLPACK_BINDINGS_R_GET_PRINTABLE_PARAM_HPP
#include <mlpack/prereqs.hpp>
#include <mlpack/core/util/is_std_vector.hpp>
namespace mlpack {
namespace bindings {
namespace r {
/**
* Print an option of a simple type.
*/
template<typename T>
std::string GetPrintableParam(
util::ParamData& data,
const typename boost::disable_if<arma::is_arma_type<T>>::type* = 0,
const typename boost::disable_if<util::IsStdVector<T>>::type* = 0,
const typename boost::disable_if<data::HasSerialize<T>>::type* = 0,
const typename boost::disable_if<std::is_same<T,
std::tuple<data::DatasetInfo, arma::mat>>>::type* = 0)
{
std::ostringstream oss;
oss << boost::any_cast<T>(data.value);
return oss.str();
}
/**
* Print a vector option, with spaces between it.
*/
template<typename T>
std::string GetPrintableParam(
util::ParamData& data,
const typename boost::enable_if<util::IsStdVector<T>>::type* = 0)
{
const T& t = boost::any_cast<T>(data.value);
std::ostringstream oss;
for (size_t i = 0; i < t.size(); ++i)
oss << t[i] << " ";
return oss.str();
}
/**
* Print a matrix option (this prints its size).
*/
template<typename T>
std::string GetPrintableParam(
util::ParamData& data,
const typename boost::enable_if<arma::is_arma_type<T>>::type* = 0)
{
// Get the matrix.
const T& matrix = boost::any_cast<T>(data.value);
std::ostringstream oss;
oss << matrix.n_rows << "x" << matrix.n_cols << " matrix";
return oss.str();
}
/**
* Print a serializable class option (this prints the class name).
*/
template<typename T>
std::string GetPrintableParam(
util::ParamData& data,
const typename boost::disable_if<arma::is_arma_type<T>>::type* = 0,
const typename boost::enable_if<data::HasSerialize<T>>::type* = 0)
{
std::ostringstream oss;
oss << data.cppType << " model at " << boost::any_cast<T*>(data.value);
return oss.str();
}
/**
* Print a combination DatasetInfo/matrix parameter.
*/
template<typename T>
std::string GetPrintableParam(
util::ParamData& data,
const typename boost::enable_if<std::is_same<T,
std::tuple<data::DatasetInfo, arma::mat>>>::type* = 0)
{
// Get the matrix.
const T& tuple = boost::any_cast<T>(data.value);
const arma::mat& matrix = std::get<1>(tuple);
std::ostringstream oss;
oss << matrix.n_rows << "x" << matrix.n_cols << " matrix with dimension type "
<< "information";
return oss.str();
}
/**
* Print an option into a std::string. This should print a short, one-line
* representation of the object. The string will be stored in the output
* pointer.
*
* @param data Parameter data struct.
* @param * (input) Unused parameter.
* @param output Output storage for the string.
*/
template<typename T>
void GetPrintableParam(util::ParamData& data,
const void* /* input */,
void* output)
{
*((std::string*) output) =
GetPrintableParam<typename std::remove_pointer<T>::type>(data);
}
} // namespace r
} // namespace bindings
} // namespace mlpack
#endif
@@ -0,0 +1,120 @@
/**
* @file bindings/R/get_printable_type.hpp
* @author Yashwant Singh Parihar
*
* Template metaprogramming to return the string representation of the R
* type for a given R binding parameter.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#ifndef MLPACK_BINDINGS_R_GET_PRINTABLE_TYPE_HPP
#define MLPACK_BINDINGS_R_GET_PRINTABLE_TYPE_HPP
#include <mlpack/prereqs.hpp>
#include <mlpack/core/util/is_std_vector.hpp>
namespace mlpack {
namespace bindings {
namespace r {
template<typename T>
inline std::string GetPrintableType(
util::ParamData& /* d */,
const typename boost::disable_if<util::IsStdVector<T>>::type* = 0,
const typename boost::disable_if<data::HasSerialize<T>>::type* = 0,
const typename boost::disable_if<arma::is_arma_type<T>>::type* = 0,
const typename boost::disable_if<std::is_same<T,
std::tuple<data::DatasetInfo, arma::mat>>>::type* = 0);
template<>
inline std::string GetPrintableType<int>(
util::ParamData& /* d */,
const typename boost::disable_if<util::IsStdVector<int>>::type*,
const typename boost::disable_if<data::HasSerialize<int>>::type*,
const typename boost::disable_if<arma::is_arma_type<int>>::type*,
const typename boost::disable_if<std::is_same<int,
std::tuple<data::DatasetInfo, arma::mat>>>::type*);
template<>
inline std::string GetPrintableType<double>(
util::ParamData& /* d */,
const typename boost::disable_if<util::IsStdVector<double>>::type*,
const typename boost::disable_if<data::HasSerialize<double>>::type*,
const typename boost::disable_if<arma::is_arma_type<double>>::type*,
const typename boost::disable_if<std::is_same<double,
std::tuple<data::DatasetInfo, arma::mat>>>::type*);
template<>
inline std::string GetPrintableType<std::string>(
util::ParamData& /* d */,
const typename boost::disable_if<util::IsStdVector<std::string>>::type*,
const typename boost::disable_if<data::HasSerialize<std::string>>::type*,
const typename boost::disable_if<arma::is_arma_type<std::string>>::type*,
const typename boost::disable_if<std::is_same<std::string,
std::tuple<data::DatasetInfo, arma::mat>>>::type*);
template<>
inline std::string GetPrintableType<size_t>(
util::ParamData& /* d */,
const typename boost::disable_if<util::IsStdVector<size_t>>::type*,
const typename boost::disable_if<data::HasSerialize<size_t>>::type*,
const typename boost::disable_if<arma::is_arma_type<size_t>>::type*,
const typename boost::disable_if<std::is_same<size_t,
std::tuple<data::DatasetInfo, arma::mat>>>::type*);
template<>
inline std::string GetPrintableType<bool>(
util::ParamData& /* d */,
const typename boost::disable_if<util::IsStdVector<bool>>::type*,
const typename boost::disable_if<data::HasSerialize<bool>>::type*,
const typename boost::disable_if<arma::is_arma_type<bool>>::type*,
const typename boost::disable_if<std::is_same<bool,
std::tuple<data::DatasetInfo, arma::mat>>>::type*);
template<typename T>
inline std::string GetPrintableType(
util::ParamData& d,
const typename boost::enable_if<util::IsStdVector<T>>::type* = 0,
const typename boost::disable_if<std::is_same<T,
std::tuple<data::DatasetInfo, arma::mat>>>::type* = 0);
template<typename T>
inline std::string GetPrintableType(
util::ParamData& /* d */,
const typename boost::enable_if<arma::is_arma_type<T>>::type* = 0,
const typename boost::disable_if<std::is_same<T,
std::tuple<data::DatasetInfo, arma::mat>>>::type* = 0);
template<typename T>
inline std::string GetPrintableType(
util::ParamData& /* d */,
const typename boost::enable_if<std::is_same<T,
std::tuple<data::DatasetInfo, arma::mat>>>::type* = 0);
template<typename T>
inline std::string GetPrintableType(
util::ParamData& d,
const typename boost::disable_if<arma::is_arma_type<T>>::type* = 0,
const typename boost::enable_if<data::HasSerialize<T>>::type* = 0,
const typename boost::disable_if<std::is_same<T,
std::tuple<data::DatasetInfo, arma::mat>>>::type* = 0);
template<typename T>
void GetPrintableType(util::ParamData& d,
const void* /* input */,
void* output)
{
*((std::string*) output) =
GetPrintableType<typename std::remove_pointer<T>::type>(d);
}
} // namespace r
} // namespace bindings
} // namespace mlpack
#include "get_printable_type_impl.hpp"
#endif
@@ -0,0 +1,161 @@
/**
* @file bindings/R/get_printable_type_impl.hpp
* @author Yashwant Singh Parihar
*
* Template metaprogramming to return the string representation of the R
* type for a given R binding parameter.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#ifndef MLPACK_BINDINGS_R_GET_PRINTABLE_TYPE_IMPL_HPP
#define MLPACK_BINDINGS_R_GET_PRINTABLE_TYPE_IMPL_HPP
#include "get_printable_type.hpp"
namespace mlpack {
namespace bindings {
namespace r {
template<typename T>
inline std::string GetPrintableType(
util::ParamData& /* d */,
const typename boost::disable_if<util::IsStdVector<T>>::type*,
const typename boost::disable_if<data::HasSerialize<T>>::type*,
const typename boost::disable_if<arma::is_arma_type<T>>::type*,
const typename boost::disable_if<std::is_same<T,
std::tuple<data::DatasetInfo, arma::mat>>>::type*)
{
return "unknown";
}
template<>
inline std::string GetPrintableType<int>(
util::ParamData& /* d */,
const typename boost::disable_if<util::IsStdVector<int>>::type*,
const typename boost::disable_if<data::HasSerialize<int>>::type*,
const typename boost::disable_if<arma::is_arma_type<int>>::type*,
const typename boost::disable_if<std::is_same<int,
std::tuple<data::DatasetInfo, arma::mat>>>::type*)
{
return "integer";
}
template<>
inline std::string GetPrintableType<double>(
util::ParamData& /* d */,
const typename boost::disable_if<util::IsStdVector<double>>::type*,
const typename boost::disable_if<data::HasSerialize<double>>::type*,
const typename boost::disable_if<arma::is_arma_type<double>>::type*,
const typename boost::disable_if<std::is_same<double,
std::tuple<data::DatasetInfo, arma::mat>>>::type*)
{
return "numeric";
}
template<>
inline std::string GetPrintableType<std::string>(
util::ParamData& /* d */,
const typename boost::disable_if<util::IsStdVector<std::string>>::type*,
const typename boost::disable_if<data::HasSerialize<std::string>>::type*,
const typename boost::disable_if<arma::is_arma_type<std::string>>::type*,
const typename boost::disable_if<std::is_same<std::string,
std::tuple<data::DatasetInfo, arma::mat>>>::type*)
{
return "character";
}
template<>
inline std::string GetPrintableType<size_t>(
util::ParamData& /* d */,
const typename boost::disable_if<util::IsStdVector<size_t>>::type*,
const typename boost::disable_if<data::HasSerialize<size_t>>::type*,
const typename boost::disable_if<arma::is_arma_type<size_t>>::type*,
const typename boost::disable_if<std::is_same<size_t,
std::tuple<data::DatasetInfo, arma::mat>>>::type*)
{
return "integer";
}
template<>
inline std::string GetPrintableType<bool>(
util::ParamData& /* d */,
const typename boost::disable_if<util::IsStdVector<bool>>::type*,
const typename boost::disable_if<data::HasSerialize<bool>>::type*,
const typename boost::disable_if<arma::is_arma_type<bool>>::type*,
const typename boost::disable_if<std::is_same<bool,
std::tuple<data::DatasetInfo, arma::mat>>>::type*)
{
return "logical";
}
template<typename T>
inline std::string GetPrintableType(
util::ParamData& d,
const typename boost::enable_if<util::IsStdVector<T>>::type*,
const typename boost::disable_if<std::is_same<T,
std::tuple<data::DatasetInfo, arma::mat>>>::type*)
{
return "vector of " + GetPrintableType<typename T::value_type>(d) + "s";
}
template<typename T>
inline std::string GetPrintableType(
util::ParamData& /* d */,
const typename boost::enable_if<arma::is_arma_type<T>>::type*,
const typename boost::disable_if<std::is_same<T,
std::tuple<data::DatasetInfo, arma::mat>>>::type*)
{
std::string type = "numeric matrix";
if (std::is_same<typename T::elem_type, double>::value)
{
if (T::is_row || T::is_col)
type = "numeric vector";
}
else if (std::is_same<typename T::elem_type, size_t>::value)
{
type = "integer matrix";
if (T::is_row || T::is_col)
type = "integer vector";
}
return type;
}
template<typename T>
inline std::string GetPrintableType(
util::ParamData& /* d */,
const typename boost::enable_if<std::is_same<T,
std::tuple<data::DatasetInfo, arma::mat>>>::type*)
{
return "categorical matrix/data.frame";
}
template<typename T>
inline std::string GetPrintableType(
util::ParamData& d,
const typename boost::disable_if<arma::is_arma_type<T>>::type*,
const typename boost::enable_if<data::HasSerialize<T>>::type*,
const typename boost::disable_if<std::is_same<T,
std::tuple<data::DatasetInfo, arma::mat>>>::type*)
{
std::string type = util::StripType(d.cppType);
if (type == "mlpackModel")
{
// If this is true, then we are being called from the Markdown bindings.
// This will be printed as the general documentation for model types.
return "<Model> (mlpack model)";
}
else
{
return type;
}
}
} // namespace r
} // namespace bindings
} // namespace mlpack
#endif
+142
View File
@@ -0,0 +1,142 @@
/**
* @file bindings/R/get_r_type.hpp
* @author Yashwant Singh Parihar
*
* Get the R-named type of an mlpack C++ type.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#ifndef MLPACK_BINDINGS_R_GET_R_TYPE_HPP
#define MLPACK_BINDINGS_R_GET_R_TYPE_HPP
#include <mlpack/prereqs.hpp>
#include <mlpack/core/util/is_std_vector.hpp>
#include <mlpack/bindings/util/strip_type.hpp>
namespace mlpack {
namespace bindings {
namespace r {
template<typename T>
inline std::string GetRType(
util::ParamData& /* d */,
const typename boost::disable_if<util::IsStdVector<T>>::type* = 0,
const typename boost::disable_if<data::HasSerialize<T>>::type* = 0,
const typename boost::disable_if<arma::is_arma_type<T>>::type* = 0,
const typename boost::disable_if<std::is_same<T,
std::tuple<data::DatasetInfo, arma::mat>>>::type* = 0)
{
return "unknown";
}
template<>
inline std::string GetRType<bool>(
util::ParamData& /* d */,
const typename boost::disable_if<util::IsStdVector<bool>>::type*,
const typename boost::disable_if<data::HasSerialize<bool>>::type*,
const typename boost::disable_if<arma::is_arma_type<bool>>::type*,
const typename boost::disable_if<std::is_same<bool,
std::tuple<data::DatasetInfo, arma::mat>>>::type*)
{
return "logical";
}
template<>
inline std::string GetRType<int>(
util::ParamData& /* d */,
const typename boost::disable_if<util::IsStdVector<int>>::type*,
const typename boost::disable_if<data::HasSerialize<int>>::type*,
const typename boost::disable_if<arma::is_arma_type<int>>::type*,
const typename boost::disable_if<std::is_same<int,
std::tuple<data::DatasetInfo, arma::mat>>>::type*)
{
return "integer";
}
template<>
inline std::string GetRType<size_t>(
util::ParamData& /* d */,
const typename boost::disable_if<util::IsStdVector<size_t>>::type*,
const typename boost::disable_if<data::HasSerialize<size_t>>::type*,
const typename boost::disable_if<arma::is_arma_type<size_t>>::type*,
const typename boost::disable_if<std::is_same<size_t,
std::tuple<data::DatasetInfo, arma::mat>>>::type*)
{
return "integer";
}
template<>
inline std::string GetRType<double>(
util::ParamData& /* d */,
const typename boost::disable_if<util::IsStdVector<double>>::type*,
const typename boost::disable_if<data::HasSerialize<double>>::type*,
const typename boost::disable_if<arma::is_arma_type<double>>::type*,
const typename boost::disable_if<std::is_same<double,
std::tuple<data::DatasetInfo, arma::mat>>>::type*)
{
return "numeric";
}
template<>
inline std::string GetRType<std::string>(
util::ParamData& /* d */,
const typename boost::disable_if<util::IsStdVector<std::string>>::type*,
const typename boost::disable_if<data::HasSerialize<std::string>>::type*,
const typename boost::disable_if<arma::is_arma_type<std::string>>::type*,
const typename boost::disable_if<std::is_same<std::string,
std::tuple<data::DatasetInfo, arma::mat>>>::type*)
{
return "character";
}
template<typename T>
inline std::string GetRType(
util::ParamData& d,
const typename boost::enable_if<util::IsStdVector<T>>::type* = 0)
{
return GetRType<typename T::value_type>(d) + " vector";
}
template<typename T>
inline std::string GetRType(
util::ParamData& d,
const typename boost::disable_if<std::is_same<T,
std::tuple<data::DatasetInfo, arma::mat>>>::type* = 0,
const typename boost::enable_if<arma::is_arma_type<T>>::type* = 0)
{
std::string elemType = GetRType<typename T::elem_type>(d);
std::string type = "matrix";
if (T::is_row)
type = "row";
else if (T::is_col)
type = "column";
return elemType + " " + type;
}
template<typename T>
inline std::string GetRType(
util::ParamData& /* d */,
const typename boost::enable_if<std::is_same<T,
std::tuple<data::DatasetInfo, arma::mat>>>::type* = 0)
{
return "numeric matrix/data.frame with info";
}
template<typename T>
inline std::string GetRType(
util::ParamData& d,
const typename boost::disable_if<arma::is_arma_type<T>>::type* = 0,
const typename boost::enable_if<data::HasSerialize<T>>::type* = 0)
{
return util::StripType(d.cppType);
}
} // namespace r
} // namespace bindings
} // namespace mlpack
#endif
+177
View File
@@ -0,0 +1,177 @@
/**
* @file bindings/R/get_type.hpp
* @author Yashwant Singh
*
* Template metaprogramming to return the string representation of the type
* for the R bindings.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#ifndef MLPACK_BINDINGS_R_GET_TYPE_HPP
#define MLPACK_BINDINGS_R_GET_TYPE_HPP
#include <mlpack/prereqs.hpp>
#include <mlpack/core/util/param_data.hpp>
#include <mlpack/core/util/is_std_vector.hpp>
namespace mlpack {
namespace bindings {
namespace r {
template<typename T>
inline std::string GetType(
util::ParamData& /* d */,
const typename boost::disable_if<util::IsStdVector<T>>::type* = 0,
const typename boost::disable_if<data::HasSerialize<T>>::type* = 0,
const typename boost::disable_if<arma::is_arma_type<T>>::type* = 0,
const typename boost::disable_if<std::is_same<T,
std::tuple<data::DatasetInfo, arma::mat>>>::type* = 0)
{
return "unknown";
}
template<>
inline std::string GetType<int>(
util::ParamData& /* d */,
const typename boost::disable_if<util::IsStdVector<int>>::type*,
const typename boost::disable_if<data::HasSerialize<int>>::type*,
const typename boost::disable_if<arma::is_arma_type<int>>::type*,
const typename boost::disable_if<std::is_same<int,
std::tuple<data::DatasetInfo, arma::mat>>>::type*)
{
return "Int";
}
template<>
inline std::string GetType<float>(
util::ParamData& /* d */,
const typename boost::disable_if<util::IsStdVector<float>>::type*,
const typename boost::disable_if<data::HasSerialize<float>>::type*,
const typename boost::disable_if<arma::is_arma_type<float>>::type*,
const typename boost::disable_if<std::is_same<float,
std::tuple<data::DatasetInfo, arma::mat>>>::type*)
{
return "Float";
}
template<>
inline std::string GetType<double>(
util::ParamData& /* d */,
const typename boost::disable_if<util::IsStdVector<double>>::type*,
const typename boost::disable_if<data::HasSerialize<double>>::type*,
const typename boost::disable_if<arma::is_arma_type<double>>::type*,
const typename boost::disable_if<std::is_same<double,
std::tuple<data::DatasetInfo, arma::mat>>>::type*)
{
return "Double";
}
template<>
inline std::string GetType<std::string>(
util::ParamData& /* d */,
const typename boost::disable_if<util::IsStdVector<std::string>>::type*,
const typename boost::disable_if<data::HasSerialize<std::string>>::type*,
const typename boost::disable_if<arma::is_arma_type<std::string>>::type*,
const typename boost::disable_if<std::is_same<std::string,
std::tuple<data::DatasetInfo, arma::mat>>>::type*)
{
return "String";
}
template<>
inline std::string GetType<bool>(
util::ParamData& /* d */,
const typename boost::disable_if<util::IsStdVector<bool>>::type*,
const typename boost::disable_if<data::HasSerialize<bool>>::type*,
const typename boost::disable_if<arma::is_arma_type<bool>>::type*,
const typename boost::disable_if<std::is_same<bool,
std::tuple<data::DatasetInfo, arma::mat>>>::type*)
{
return "Bool";
}
template<typename T>
inline std::string GetType(
util::ParamData& d,
const typename boost::enable_if<util::IsStdVector<T>>::type* = 0,
const typename boost::disable_if<std::is_same<T,
std::tuple<data::DatasetInfo, arma::mat>>>::type* = 0)
{
return "Vec" + GetType<typename T::value_type>(d);
}
template<typename T>
inline std::string GetType(
util::ParamData& /* d */,
const typename boost::enable_if<arma::is_arma_type<T>>::type* = 0,
const typename boost::disable_if<std::is_same<T,
std::tuple<data::DatasetInfo, arma::mat>>>::type* = 0)
{
std::string type = "";
if (std::is_same<typename T::elem_type, double>::value)
{
if (T::is_row)
type = "Row";
else if (T::is_col)
type = "Col";
else
type = "Mat";
}
else if (std::is_same<typename T::elem_type, size_t>::value)
{
if (T::is_row)
type = "URow";
else if (T::is_col)
type = "UCol";
else
type = "UMat";
}
return type;
}
template<typename T>
inline std::string GetType(
util::ParamData& /* d */,
const typename boost::enable_if<std::is_same<T,
std::tuple<data::DatasetInfo, arma::mat>>>::type* = 0)
{
return "MatWithInfo";
}
template<typename T>
inline std::string GetType(
util::ParamData& d,
const typename boost::disable_if<arma::is_arma_type<T>>::type* = 0,
const typename boost::enable_if<data::HasSerialize<T>>::type* = 0)
{
return d.cppType;
}
/**
* Function is used to generate the type names that are used in calls to
* functions like IO_SetParam<type>() or setParam<type>(), and therefore
* what's returned isn't exactly the R native type used for that parameter
* type.
*
* @param d Parameter data struct.
* @param * (input) Unused parameter.
* @param output Output storage for the string.
*/
template<typename T>
void GetType(util::ParamData& d,
const void* /* input */,
void* output)
{
*((std::string*) output) =
GetType<typename std::remove_pointer<T>::type>(d);
}
} // namespace r
} // namespace bindings
} // namespace mlpack
#endif
@@ -0,0 +1,25 @@
Package: mlpack
Title: 'Rcpp' Integration for the 'mlpack' Library
Version: @PACKAGE_VERSION@
Date: @PACKAGE_DATE@
Author: mlpack Team
Maintainer: Ryan Curtin <ryan@ratml.org>
Description: 'mlpack' is a fast, flexible machine learning library, written
in C++, that aims to provide fast, extensible implementations of
cutting-edge machine learning algorithms.
SystemRequirements: A C++11 compiler. Versions 4.8.*, 4.9.* or later of GCC
will be fine.
License: BSD_3_clause + file LICENSE
Depends: R (>= 4.0.0)
Imports: Rcpp (>= 0.12.12)
LinkingTo: Rcpp,
RcppArmadillo (>= @RcppArmadillo_Version@),
BH (>= @BH_Version@),
RcppEnsmallen (>= @RcppEnsmallen_Version@)
Suggests: testthat (>= 2.1.0)
URL: https://www.mlpack.org/doc/mlpack-@PACKAGE_VERSION@/r_documentation.html,
https://github.com/mlpack/mlpack
BugReports: https://github.com/mlpack/mlpack/issues
LazyData: true
RoxygenNote: 7.1.0
Encoding: UTF-8
@@ -0,0 +1,50 @@
# matrix_utils.R: utilities for matrix conversion
#
# This file defines the to_matrix() function, which can be used to convert
# data.frame or other types of matrix-like objects to matrix for use in
# mlpack bindings(IO_SetParamMat/UMat).
#
# This file also defines the to_matirx_with_info() function, which can be used
# to construct dataset information vector from the given dataset for use in
# mlpack bindings(IO_SetParamMatWithInfo).
#
#
# mlpack is free software; you may redistribute it and/or modify it under the
# terms of the 3-clause BSD license. You should have received a copy of the
# 3-clause BSD license along with mlpack. If not, see
# http://www.opensource.org/licenses/BSD-3-Clause for more information.
# Given some matrix-like x (which should be either a matrix or
# data.frame), convert it into a matrix.
to_matrix <- function(x) {
if (!is.matrix(x) && !is.data.frame(x)) {
stop("Input must be either a `matrix` or `data.frame` not `",
class(x)[1], "`.", call. = FALSE)
}
if (is.matrix(x)) {
return(x)
} else if (is.data.frame(x)) {
y <- data.matrix(x) # requires R 4.0.0 for factor conversion.
return(y)
}
}
# Determine column classes
mark_categorical_variable = function(x) {
d <- sapply(x, class) %in% c("factor", "character", "logical")
d
}
# Given some matrix-like x (which should be either a matrix or
# data.frame), convert it into a matrix.
to_matrix_with_info <- function(x) {
# Handle transformation
transformed_x <- to_matrix(x)
# Figure out categoricals
info <- mark_categorical_variable(x)
# Return needed data.
return(list("info" = info, "data" = transformed_x))
}
+14
View File
@@ -0,0 +1,14 @@
#' mlpack
#'
#' mlpack is a fast, flexible machine learning library, written in C++, that
#' aims to provide fast, extensible implementations of cutting-edge machine
#' learning algorithms. mlpack provides these algorithms as simple command-line
#' programs, C++ classes and bindings for : Python, Julia, Go and R which can
#' then be integrated into larger-scale machine learning solutions.
#'
#' @docType package
#' @name mlpack
#' @author mlpack Team
#' @importFrom Rcpp evalCpp
#' @useDynLib mlpack
NULL
+2
View File
@@ -0,0 +1,2 @@
## compilation and editing objects
rm -f src/*.o src/*.so src/*.dylib src/*~ *~
@@ -0,0 +1,73 @@
/**
* @file inst/include/mlpack.h
* @author Yashwant Singh Parihar
*
* Include all of the base components required to work mlpack bindings.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#ifndef MLPACK_BINDINGS_R_RCPP_MLPACK_H
#define MLPACK_BINDINGS_R_RCPP_MLPACK_H
#include <Rcpp.h>
// To suppress Found __assert_fail, possibly from assert (C).
#define BOOST_DISABLE_ASSERTS
// Rcpp has its own stream object which cooperates more nicely with R's i/o
// And as of armadillo and mlpack, we can use this stream object as well.
#if !defined(ARMA_COUT_STREAM)
#define ARMA_COUT_STREAM Rcpp::Rcout
#endif
#if !defined(ARMA_CERR_STREAM)
#define ARMA_CERR_STREAM Rcpp::Rcerr
#endif
#if !defined(MLPACK_COUT_STREAM)
#define MLPACK_COUT_STREAM Rcpp::Rcout
#endif
#if !defined(MLPACK_CERR_STREAM)
#define MLPACK_CERR_STREAM Rcpp::Rcerr
#endif
// This define makes the R RNG have precedent over the C++11-based
// RNG provided by Armadillo.
#if !defined(ARMA_RNG_ALT)
#define ARMA_RNG_ALT RcppArmadillo/Alt_R_RNG.h
#endif
// To suppress warnings related to core/util/arma_util.hpp.
#define MLPACK_CORE_UTIL_ARMA_CONFIG_HPP
// Undefine macro due to macro collision.
#undef Realloc
#undef Free
@R_SRC@
#include <mlpack/core.hpp>
#undef ARMA_EXTRA_MAT_PROTO
#undef ARMA_EXTRA_MAT_MEAT
// Define R Internal macro again after including cereal headers.
#define Realloc(p,n,t) (t *) R_chk_realloc( (void *)(p), (R_SIZE_T)((n) * sizeof(t)) )
#define Free(p) (R_chk_free( (void *)(p) ), (p) = NULL)
// instead of including RcppArmadillo.h -- which re-includes parts
// of Armadillo already brought in by mlpack, we just include pieces
// needed for sugar wrapping etc
#include <RcppArmadilloConfig.h>
#include <RcppArmadilloWrap.h>
#include <RcppArmadilloAs.h>
#include <RcppArmadilloSugar.h>
// prevent inclusion of Rcpp.h and RcppArmadillo.h via the
// autogenerated RcppExports.cpp
#define Rcpp_hpp
#define RcppArmadillo__RcppArmadillo__h
#endif
@@ -0,0 +1,3 @@
PKG_CXXFLAGS = -DBOOST_MATH_PROMOTE_DOUBLE_POLICY=false -I. $(SHLIB_OPENMP_CXXFLAGS)
PKG_LIBS = $(SHLIB_OPENMP_CXXFLAGS) $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS)
CXX_STD = CXX11
@@ -0,0 +1,3 @@
PKG_CXXFLAGS = -DBOOST_MATH_PROMOTE_DOUBLE_POLICY=false -I. $(SHLIB_OPENMP_CXXFLAGS)
PKG_LIBS = $(SHLIB_OPENMP_CXXFLAGS) $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS)
CXX_STD = CXX11
+300
View File
@@ -0,0 +1,300 @@
/**
* @file src/r_util.cpp
* @author Yashwant Singh Parihar
*
* Utility functions for R-bindings.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#include <rcpp_mlpack.h>
#include <mlpack/prereqs.hpp>
#include <mlpack/core/util/io.hpp>
using namespace mlpack;
using namespace Rcpp;
template<typename eT>
bool inline inplace_transpose(arma::Mat<eT>& X)
{
try
{
X = arma::trans(X);
return false;
}
catch (std::bad_alloc&)
{
return true;
}
}
// Call IO::RestoreSettings() for a given program name.
// [[Rcpp::export]]
void IO_RestoreSettings(const std::string& programName)
{
IO::RestoreSettings(programName);
}
// Call IO::SetParam<int>().
// [[Rcpp::export]]
void IO_SetParamInt(const std::string& paramName, int paramValue)
{
IO::GetParam<int>(paramName) = paramValue;
IO::SetPassed(paramName);
}
// Call IO::SetParam<double>().
// [[Rcpp::export]]
void IO_SetParamDouble(const std::string& paramName, double paramValue)
{
IO::GetParam<double>(paramName) = paramValue;
IO::SetPassed(paramName);
}
// Call IO::SetParam<std::string>().
// [[Rcpp::export]]
void IO_SetParamString(const std::string& paramName, std::string& paramValue)
{
IO::GetParam<std::string>(paramName) = paramValue;
IO::SetPassed(paramName);
}
// Call IO::SetParam<bool>().
// [[Rcpp::export]]
void IO_SetParamBool(const std::string& paramName, bool paramValue)
{
IO::GetParam<bool>(paramName) = paramValue;
IO::SetPassed(paramName);
}
// Call IO::SetParam<std::vector<std::string>>().
// [[Rcpp::export]]
void IO_SetParamVecString(const std::string& paramName,
const std::vector<std::string>& str)
{
IO::GetParam<std::vector<std::string>>(paramName) = std::move(str);
IO::SetPassed(paramName);
}
// Call IO::SetParam<std::vector<int>>().
// [[Rcpp::export]]
void IO_SetParamVecInt(const std::string& paramName,
const std::vector<int>& ints)
{
IO::GetParam<std::vector<int>>(paramName) = std::move(ints);
IO::SetPassed(paramName);
}
// Call IO::SetParam<arma::mat>().
// [[Rcpp::export]]
void IO_SetParamMat(const std::string& paramName,
const arma::mat& paramValue)
{
IO::GetParam<arma::mat>(paramName) = paramValue.t();
IO::SetPassed(paramName);
}
// Call IO::SetParam<arma::Mat<size_t>>().
// [[Rcpp::export]]
void IO_SetParamUMat(const std::string& paramName,
const arma::Mat<size_t>& paramValue)
{
IO::GetParam<arma::Mat<size_t>>(paramName) = paramValue.t();
IO::SetPassed(paramName);
}
// Call IO::SetParam<arma::rowvec>().
// [[Rcpp::export]]
void IO_SetParamRow(const std::string& paramName,
const arma::rowvec& paramValue)
{
IO::GetParam<arma::rowvec>(paramName) = std::move(paramValue);
IO::SetPassed(paramName);
}
// Call IO::SetParam<arma::Row<size_t>>().
// [[Rcpp::export]]
void IO_SetParamURow(const std::string& paramName,
const arma::Row<size_t>& paramValue)
{
IO::GetParam<arma::Row<size_t>>(paramName) = paramValue - 1;
IO::SetPassed(paramName);
}
// Call IO::SetParam<arma::vec>().
// [[Rcpp::export]]
void IO_SetParamCol(const std::string& paramName,
const arma::vec& paramValue)
{
IO::GetParam<arma::vec>(paramName) = std::move(paramValue);
IO::SetPassed(paramName);
}
// Call IO::SetParam<arma::Col<size_t>>().
// [[Rcpp::export]]
void IO_SetParamUCol(const std::string& paramName,
const arma::Col<size_t>& paramValue)
{
IO::GetParam<arma::Col<size_t>>(paramName) = paramValue - 1;
IO::SetPassed(paramName);
}
// Call IO::SetParam<std::tuple<data::DatasetInfo, arma::mat>>().
// [[Rcpp::export]]
void IO_SetParamMatWithInfo(const std::string& paramName,
const LogicalVector& dimensions,
const arma::mat& paramValue)
{
data::DatasetInfo d(paramValue.n_cols);
for (size_t i = 0; i < d.Dimensionality(); ++i)
{
d.Type(i) = (dimensions[i]) ? data::Datatype::categorical :
data::Datatype::numeric;
}
std::get<0>(IO::GetParam<std::tuple<data::DatasetInfo, arma::mat>>(
paramName)) = std::move(d);
std::get<1>(IO::GetParam<std::tuple<data::DatasetInfo, arma::mat>>(
paramName)) = paramValue.t();
IO::SetPassed(paramName);
}
// Call IO::GetParam<int>().
// [[Rcpp::export]]
int IO_GetParamInt(const std::string& paramName)
{
return IO::GetParam<int>(paramName);
}
// Call IO::GetParam<double>().
// [[Rcpp::export]]
double IO_GetParamDouble(const std::string& paramName)
{
return IO::GetParam<double>(paramName);
}
// Call IO::GetParam<std::string>().
// [[Rcpp::export]]
std::string& IO_GetParamString(const std::string& paramName)
{
return IO::GetParam<std::string>(paramName);
}
// Call IO::GetParam<bool>().
// [[Rcpp::export]]
bool IO_GetParamBool(const std::string& paramName)
{
return IO::GetParam<bool>(paramName);
}
// Call IO::GetParam<std::vector<std::string>>().
// [[Rcpp::export]]
const std::vector<std::string>& IO_GetParamVecString(const
std::string& paramName)
{
return std::move(IO::GetParam<std::vector<std::string>>(paramName));
}
// Call IO::GetParam<std::vector<int>>().
// [[Rcpp::export]]
const std::vector<int>& IO_GetParamVecInt(const std::string& paramName)
{
return std::move(IO::GetParam<std::vector<int>>(paramName));
}
// Call IO::GetParam<arma::mat>().
// [[Rcpp::export]]
const arma::mat& IO_GetParamMat(const std::string& paramName)
{
inplace_transpose(IO::GetParam<arma::mat>(paramName));
return std::move(IO::GetParam<arma::mat>(paramName));
}
// Call IO::GetParam<arma::Mat<size_t>>().
// [[Rcpp::export]]
const arma::Mat<size_t>& IO_GetParamUMat(const std::string& paramName)
{
inplace_transpose(IO::GetParam<arma::Mat<size_t>>(paramName));
return std::move(IO::GetParam<arma::Mat<size_t>>(paramName));
}
// Call IO::GetParam<arma::rowvec>().
// [[Rcpp::export]]
const arma::vec IO_GetParamRow(const std::string& paramName)
{
return IO::GetParam<arma::rowvec>(paramName).t();
}
// Call IO::GetParam<arma::Row<size_t>>().
// [[Rcpp::export]]
const arma::Col<size_t> IO_GetParamURow(const std::string& paramName)
{
return IO::GetParam<arma::Row<size_t>>(paramName).t() + 1;
}
// Call IO::GetParam<arma::vec>().
// [[Rcpp::export]]
const arma::rowvec IO_GetParamCol(const std::string& paramName)
{
return IO::GetParam<arma::vec>(paramName).t();
}
// Call IO::GetParam<arma::Col<size_t>>().
// [[Rcpp::export]]
const arma::Row<size_t> IO_GetParamUCol(const std::string& paramName)
{
return IO::GetParam<arma::Col<size_t>>(paramName).t() + 1;
}
// Call IO::GetParam<std::tuple<data::DatasetInfo, arma::mat>>().
// [[Rcpp::export]]
List IO_GetParamMatWithInfo(const std::string& paramName)
{
const data::DatasetInfo& d = std::get<0>(
IO::GetParam<std::tuple<data::DatasetInfo, arma::mat>>(paramName));
const arma::mat& m = std::get<1>(
IO::GetParam<std::tuple<data::DatasetInfo, arma::mat>>(paramName)).t();
LogicalVector dims(d.Dimensionality());
for (size_t i = 0; i < d.Dimensionality(); ++i)
dims[i] = (d.Type(i) == data::Datatype::numeric) ? false : true;
return List::create (Rcpp::Named("Info") = std::move(dims),
Rcpp::Named("Data") = std::move(m));
}
// Enable verbose output.
// [[Rcpp::export]]
void IO_EnableVerbose()
{
Log::Info.ignoreInput = false;
}
// Disable verbose output.
// [[Rcpp::export]]
void IO_DisableVerbose()
{
Log::Info.ignoreInput = true;
}
// Reset the state of all timers.
// [[Rcpp::export]]
void IO_ResetTimers()
{
IO::GetSingleton().timer.Reset();
}
// Set an argument as passed to the IO object.
// [[Rcpp::export]]
void IO_SetPassed(const std::string& paramName)
{
IO::SetPassed(paramName);
}
// Clear settings.
// [[Rcpp::export]]
void IO_ClearSettings()
{
IO::ClearSettings();
}
@@ -0,0 +1,49 @@
/**
* @file src/rcpp_mlpack.h
* @author Dirk Eddelbuettel
* @author Yashwant Singh Parihar
*
* Include all of the base components required to work mlpack bindings.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#ifndef MLPACK_BINDINGS_R_RCPP_MLPACK_H
#define MLPACK_BINDINGS_R_RCPP_MLPACK_H
#include <Rcpp.h>
// To suppress Found __assert_fail, possibly from assert (C).
#define BOOST_DISABLE_ASSERTS
// Rcpp has its own stream object which cooperates more nicely with R's i/o
// And as of armadillo and mlpack, we can use this stream object as well.
#if !defined(ARMA_COUT_STREAM)
#define ARMA_COUT_STREAM Rcpp::Rcout
#endif
#if !defined(ARMA_CERR_STREAM)
#define ARMA_CERR_STREAM Rcpp::Rcerr
#endif
#if !defined(MLPACK_COUT_STREAM)
#define MLPACK_COUT_STREAM Rcpp::Rcout
#endif
#if !defined(MLPACK_CERR_STREAM)
#define MLPACK_CERR_STREAM Rcpp::Rcerr
#endif
// This define makes the R RNG have precedent over the C++11-based
// RNG provided by Armadillo.
#if !defined(ARMA_RNG_ALT)
#define ARMA_RNG_ALT RcppArmadillo/Alt_R_RNG.h
#endif
// To suppress warnings related to core/util/arma_util.hpp.
#define MLPACK_CORE_UTIL_ARMA_CONFIG_HPP
// Undefine macro due to macro collision.
#undef Realloc
#undef Free
#endif
@@ -0,0 +1,4 @@
library(testthat)
library(mlpack)
test_check("mlpack")
@@ -0,0 +1,297 @@
# Test that when we run the binding correctly (with correct input parameters),
# we get the expected output.
test_that("TestRunBindingCorrectly", {
output <- test_r_binding(4.0, 12, "hello",
flag1=TRUE)
expect_true(output$double_out == 5.0)
expect_true(output$int_out == 13)
expect_true(output$string_out == "hello2")
})
# If we forget the mandatory flag, we should get wrong results.
test_that("TestRunBindingNoFlag", {
output <- test_r_binding(4.0, 12, "hello")
expect_true(output$double_out != 5.0)
expect_true(output$int_out != 13)
expect_true(output$string_out != "hello2")
})
# If we give the wrong string, we should get wrong results.
test_that("TestRunBindingWrongString", {
output <- test_r_binding(4.0, 12, "goodbye",
flag1=TRUE)
expect_true(output$string_out != "hello2")
})
# If we give the wrong int, we should get wrong results.
test_that("TestRunBindingWrongInt", {
output <- test_r_binding(4.0, 15, "hello",
flag1=TRUE)
expect_true(output$int_out != 13)
})
# If we give the wrong double, we should get wrong results.
test_that("TestRunBindingWrongDouble", {
output <- test_r_binding(2.0, 12, "hello",
flag1=TRUE)
expect_true(output$double_out != 5.0)
})
# If we give the second flag, this should fail.
test_that("TestRunBadFlag", {
output <- test_r_binding(4.0, 12, "hello",
flag1=TRUE,
flag2=TRUE)
expect_true(output$double_out != 5.0)
expect_true(output$int_out != 13)
expect_true(output$string_out != "hello2")
})
# The matrix we pass in, we should get back with the third dimension doubled and
# the fifth forgotten.
test_that("TestMatrix", {
x <- matrix(rexp(500, rate = .1), ncol = 5)
output <- test_r_binding(4.0, 12, "hello",
matrix_in=x)
expect_identical(dim(output$matrix_out), as.integer(c(100, 4)))
for (i in c(1, 2, 4)) {
for (j in 1:100) {
expect_true(output$matrix_out[j, i] == x[j, i])
}
}
for (j in 1:100) {
expect_true(output$matrix_out[j, 3] == 2 * x[j, 3])
}
})
# The data.frame we pass in, we should get back with the third dimension doubled
# and the fifth forgotten.
test_that("TestDataFrame", {
y <- matrix(c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15), nrow = 3)
x <- data.frame(y)
output <- test_r_binding(4.0, 12, "hello",
matrix_in=x)
expect_identical(dim(output$matrix_out), as.integer(c(3, 4)))
for (i in c(1, 2, 4)) {
for (j in 1:3) {
expect_true(output$matrix_out[j, i] == x[j, i])
}
}
for (j in 1:3) {
expect_true(output$matrix_out[j, 3] == 2 * x[j, 3])
}
})
# Same as TestMatrix but with an unsigned matrix.
test_that("TestUMatrix", {
x <- matrix(as.integer(rexp(500, rate = .1)), ncol = 5)
output <- test_r_binding(4.0, 12, "hello",
umatrix_in=x)
expect_identical(dim(output$umatrix_out), as.integer(c(100, 4)))
for (i in c(1, 2, 4)) {
for (j in 1:100) {
expect_true(output$umatrix_out[j, i] == x[j, i])
}
}
for (j in 1:100) {
expect_true(output$umatrix_out[j, 3] == 2 * x[j, 3])
}
})
# Test a column vector input parameter.
test_that("TestCol", {
x <- matrix(rexp(100, rate = .1), nrow = 1)
output <- test_r_binding(4.0, 12, "hello",
col_in=x)
expect_identical(dim(output$col_out), as.integer(c(1, 100)))
expect_identical(output$col_out, 2 * x)
})
# Test an unsigned column vector input parameter.
test_that("TestUCol", {
x <- matrix(as.integer(rexp(100, rate = .1)), nrow = 1)
output <- test_r_binding(4.0, 12, "hello",
ucol_in=x)
expect_identical(dim(output$ucol_out), as.integer(c(1, 100)))
expect_identical(output$ucol_out, 1 + x)
})
# Test a row vector input parameter.
test_that("TestRow", {
x <- matrix(rexp(100, rate = .1), ncol = 1)
output <- test_r_binding(4.0, 12, "hello",
row_in=x)
expect_identical(dim(output$row_out), as.integer(c(100, 1)))
expect_identical(output$row_out, 2 * x)
})
# Test an unsigned row vector input parameter.
test_that("TestURow", {
x <- matrix(as.integer(rexp(100, rate = .1)), ncol = 1)
output <- test_r_binding(4.0, 12, "hello",
urow_in=x)
expect_identical(dim(output$urow_out), as.integer(c(100, 1)))
expect_identical(output$urow_out, 1 + x)
})
# Test that we can pass a matrix with all numeric features.
test_that("TestMatrixAndInfo", {
x <- matrix(rexp(500, rate = .1), ncol = 5)
output <- test_r_binding(4.0, 12, "hello",
matrix_and_info_in=x)
expect_identical(dim(output$matrix_and_info_out), as.integer(c(100, 5)))
expect_identical(output$matrix_and_info_out, 2 * x)
})
# Test that we can pass a data.frame with all numeric features.
test_that("TestDataFrameWithNoInfo", {
y <- matrix(rexp(500, rate = .1), ncol = 5)
x <- data.frame(y)
output <- test_r_binding(4.0, 12, "hello",
matrix_and_info_in=x)
expect_identical(dim(output$matrix_and_info_out), as.integer(c(100, 5)))
for (i in 1:100) {
for (j in 1:5) {
expect_true(output$matrix_and_info_out[i, j] == 2 * x[i, j])
}
}
})
# Test that we can pass a data.frame with numeric and categorical features.
test_that("TestDataFrameWithInfo", {
y <- matrix(rexp(90, rate = .1), ncol = 9)
x <- data.frame(y, "e" = letters[1:10])
output <- test_r_binding(4.0, 12, "hello",
matrix_and_info_in=x)
expect_identical(dim(output$matrix_and_info_out), as.integer(c(10, 10)))
for (i in 1:9) {
for (j in 1:10) {
expect_true(output$matrix_and_info_out[j, i] == 2 * x[j, i])
}
}
for (j in 1:10) {
expect_true(output$matrix_and_info_out[j, 10] == j)
}
})
# Test that we can pass a data.frame with numeric and categorical features.
test_that("TestDataFrameWithLogicalInfo", {
y <- matrix(rexp(90, rate = .1), ncol = 9)
x <- data.frame(y)
x["e"] <- c(T, F, F, T, T, F, F, F, F, T)
output <- test_r_binding(4.0, 12, "hello",
matrix_and_info_in=x)
expect_identical(dim(output$matrix_and_info_out), as.integer(c(10, 10)))
for (i in 1:9) {
for (j in 1:10) {
expect_true(output$matrix_and_info_out[j, i] == 2 * x[j, i])
}
}
expect_identical(output$matrix_and_info_out[, 10], as.numeric(x[, "e"]))
})
# Test that we can pass a vector of ints and get back that same vector but with
# the last element removed.
test_that("TestIntVector", {
x <- c(1, 2, 3, 4, 5)
output <- test_r_binding(4.0, 12, "hello",
vector_in=x)
expect_identical(output$vector_out, c(1:4))
})
# Test that we can pass a vector of strings and get back that same vector but
# with the last element removed.
test_that("TestStringVector", {
x <- letters[1:5]
output <- test_r_binding(4.0, 12, "hello",
str_vector_in=x)
expect_identical(output$str_vector_out, letters[1:4])
})
# If we give data other than matrix/data.frame in matrix_in/matrix_and_info_in,
# we should get an error.
test_that("TestNotMatrix", {
expect_error(test_r_binding(4.0, 12, "hello",
matrix_in="wrong"))
expect_error(test_r_binding(4.0, 12, "hello",
matrix_in=12))
expect_error(test_r_binding(4.0, 12, "hello",
matrix_in=1e6))
expect_error(test_r_binding(4.0, 12, "hello",
matrix_and_info_in="wrong"))
expect_error(test_r_binding(4.0, 12, "hello",
matrix_and_info_in=12))
expect_error(test_r_binding(4.0, 12, "hello",
matrix_and_info_in=1e6))
})
# First create a GaussianKernel object, then send it back and make sure we get
# the right double value.
test_that("TestModel", {
output1 <- test_r_binding(4.0, 12, "hello",
build_model=TRUE)
output2 <- test_r_binding(4.0, 12, "hello",
model_in=output1$model_out)
expect_true(output2$model_bw_out == 20)
})
# Test that we can serialize a model to disk and then use it again.
test_that("TestSerialization", {
output1 <- test_r_binding(4.0, 12, "hello",
build_model=TRUE)
Serialize(output1$model_out, "model.bin")
new_model <- Unserialize("model.bin")
unlink("model.bin")
output2 <- test_r_binding(4.0, 12, "hello", model_in=new_model)
expect_true(output2$model_bw_out == 20)
})
+248
View File
@@ -0,0 +1,248 @@
/**
* @file bindings/R/print_R.cpp
* @author Yashwant Singh Parihar
*
* Implementation of utility PrintR() function.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#include "print_R.hpp"
#include <mlpack/bindings/util/strip_type.hpp>
#include <mlpack/prereqs.hpp>
#include <mlpack/core/util/hyphenate_string.hpp>
using namespace mlpack;
using namespace std;
namespace mlpack {
namespace bindings {
namespace r {
/**
* Print the code for a .R binding for an mlpack program to stdout.
*
* @param doc Documentation for the binding.
* @param functionName Name of the function (i.e. "pca").
*/
void PrintR(const util::BindingDetails& doc,
const string& functionName)
{
// Restore parameters.
IO::RestoreSettings(doc.programName);
map<string, util::ParamData>& parameters = IO::Parameters();
typedef map<string, util::ParamData>::iterator ParamIter;
// First, let's get a list of input and output options. We'll take two passes
// so that the required input options are the first in the list.
vector<string> inputOptions, outputOptions;
for (ParamIter it = parameters.begin(); it != parameters.end(); ++it)
{
util::ParamData& d = it->second;
if (d.input && d.required)
{
// Ignore some parameters.
if (d.name != "help" && d.name != "info" &&
d.name != "version")
inputOptions.push_back(it->first);
}
else if (!d.input)
{
outputOptions.push_back(it->first);
}
}
for (ParamIter it = parameters.begin(); it != parameters.end(); ++it)
{
util::ParamData& d = it->second;
if (d.input && !d.required &&
d.name != "help" && d.name != "info" &&
d.name != "version")
inputOptions.push_back(it->first);
}
// Print the documentation.
// Print programName as @title.
cout << "#' @title ";
cout << util::HyphenateString(doc.programName, "#' ") << endl;
cout << "#'" << endl;
// Next print the short description as @description.
cout << "#' @description" << endl;
cout << "#' ";
cout << util::HyphenateString(doc.shortDescription, "#' ") << endl;
// Next, print information on the input options.
cout << "#'" << endl;
for (size_t i = 0; i < inputOptions.size(); ++i)
{
const string& opt = inputOptions[i];
util::ParamData& d = parameters.at(opt);
bool out = false;
IO::GetSingleton().functionMap[d.tname]["PrintDoc"](d, NULL, (void*) &out);
cout << endl;
}
cout << "#'" << endl;
// Next, print information on the output options.
if (outputOptions.size() > 0)
cout << "#' @return A list with several components:" << endl;
for (size_t i = 0; i < outputOptions.size(); ++i)
{
const string& opt = outputOptions[i];
util::ParamData& d = parameters.at(opt);
bool out = true;
IO::GetSingleton().functionMap[d.tname]["PrintDoc"](d, NULL, (void*) &out);
cout << endl;
}
cout << "#'" << endl;
// Next print the long description as @details.
cout << "#' @details" << endl;
cout << "#' ";
cout << util::HyphenateString(doc.longDescription(), "#' ") << endl;
cout << "#'" << endl;
cout << "#' @author" << endl;
cout << "#' mlpack developers" << endl;
cout << "#'" << endl;
// Next print the example as @examples.
cout << "#' @export" << endl;
if (doc.example.size() != 0)
cout << "#' @examples" << endl;
for (size_t j = 0; j < doc.example.size(); ++j)
{
const std::string str = doc.example[j]();
size_t pos = 0;
while (pos < str.length())
{
size_t splitpos = 0;
// Find where example starts.
splitpos = str.find("\n\\dontrun{", pos) - 1;
// If no example left, then print all the comments that are left.
if (splitpos == std::string::npos || splitpos > str.length())
{
splitpos = str.length();
cout << util::HyphenateString(str.substr(pos, (splitpos - pos)),
"#' # ");
break;
}
if (splitpos != 0 && pos == 0)
cout << "#' # ";
// Print comments in the "example", if there is available.
cout << util::HyphenateString(str.substr(pos, (splitpos - pos)),
"#' # ", true);
// Find where example ends.
pos = str.find("\n}", pos) + 3;
// Here length of example might be less 80, we must handle this carefully.
// Print example in the "example".
cout << util::HyphenateString(str.substr(splitpos, (pos - splitpos)),
"#' ", true);
}
cout << endl;
}
// Print the definition.
cout << functionName << " <- function(";
size_t indent = functionName.size() + 13 /* <- function(*/;
for (size_t i = 0; i < inputOptions.size(); ++i)
{
util::ParamData& d = parameters.at(inputOptions[i]);
if (i != 0)
cout << "," << endl << std::string(indent, ' ');
IO::GetSingleton().functionMap[d.tname]["PrintInputParam"](d, NULL, NULL);
}
// Print closing brace for function definition.
cout << ") {" << endl;
// Restore IO settings.
cout << " # Restore IO settings." << endl;
cout << " IO_RestoreSettings(\"" << IO::ProgramName()
<< "\")" << endl;
cout << endl;
// Handle each input argument's processing before calling mlpackMain().
cout << " # Process each input argument before calling mlpackMain()."
<< endl;
for (const string& opt : inputOptions)
{
if (opt != "verbose")
{
util::ParamData& d = parameters.at(opt);
IO::GetSingleton().functionMap[d.tname]["PrintInputProcessing"](d,
NULL, NULL);
}
}
// Special handling for verbose output.
cout << " if (verbose) {" << endl;
cout << " IO_EnableVerbose()" << endl;
cout << " } else {" << endl;
cout << " IO_DisableVerbose()" << endl;
cout << " }" << endl;
cout << endl;
// Mark output parameters as passed.
cout << " # Mark all output options as passed." << endl;
for (const string& opt : outputOptions)
{
util::ParamData& d = parameters.at(opt);
cout << " IO_SetPassed(\"" << d.name << "\")" << endl;
}
cout << endl;
// Call the program.
cout << " # Call the program." << endl;
cout << " " << functionName << "_mlpackMain()" << endl << endl;
// Add ModelType as attr to the model pointer.
cout << " # Add ModelType as attribute to the model pointer, if needed."
<< endl;
for (size_t i = 0; i < outputOptions.size(); ++i)
{
util::ParamData& d = parameters.at(outputOptions[i]);
IO::GetSingleton().functionMap[d.tname]["PrintSerializeUtil"](d,
NULL, NULL);
}
cout << endl;
// Extract the results in order.
cout << " # Extract the results in order." << endl;
cout << " out <- list(" << endl;
string indentStr(4, ' ');
for (size_t i = 0; i < outputOptions.size(); ++i)
{
if (i == 0)
cout << indentStr;
util::ParamData& d = parameters.at(outputOptions[i]);
IO::GetSingleton().functionMap[d.tname]["PrintOutputProcessing"](d,
NULL, NULL);
// Print newlines if we are returning multiple output options.
if (i + 1 < outputOptions.size())
cout << "," << endl << indentStr;
}
cout << endl << " )" << endl << endl;
// Clear the parameters.
cout << " # Clear the parameters." << endl;
cout << " IO_ClearSettings()" << endl;
cout << endl;
cout << " return(out)" << endl << "}" << endl;
}
} // namespace r
} // namespace bindings
} // namespace mlpack
+34
View File
@@ -0,0 +1,34 @@
/**
* @file bindings/R/print_R.hpp
* @author Yashwant Singh Parihar
*
* Definition of utility PrintR() function.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#ifndef MLPACK_BINDINGS_R_PRINT_R_HPP
#define MLPACK_BINDINGS_R_PRINT_R_HPP
#include <mlpack/core.hpp>
namespace mlpack {
namespace bindings {
namespace r {
/**
* Print the code for a .R binding for an mlpack program to stdout.
*
* @param doc Documentation for the binding.
* @param functionName Name of the function (i.e. "pca").
*/
void PrintR(const util::BindingDetails& doc,
const std::string& functionName);
} // namespace r
} // namespace bindings
} // namespace mlpack
#endif
+88
View File
@@ -0,0 +1,88 @@
/**
* @file bindings/R/print_doc.hpp
* @author Yashwant Singh Parihar.
*
* Print documentation for a R binding parameter.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#ifndef MLPACK_BINDINGS_R_PRINT_DOC_HPP
#define MLPACK_BINDINGS_R_PRINT_DOC_HPP
#include "get_r_type.hpp"
#include <mlpack/prereqs.hpp>
#include <mlpack/core/util/hyphenate_string.hpp>
namespace mlpack {
namespace bindings {
namespace r {
/**
* Print the docstring documentation for a given parameter. You are responsible
* for setting up the line---this does not handle indentation or anything. This
* is meant to produce a line of documentation describing a single parameter.
*
* The indent parameter (void* input, which should be a pointer to a size_t)
* should be passed to know how much to indent for a new line.
*
* @param d Parameter data struct.
* @param * (input) Pointer to size_t containing indent.
* @param output Unused parameter.
*/
template<typename T>
void PrintDoc(util::ParamData& d,
const void* /* input */,
void* output)
{
bool out = *((bool*) output);
std::ostringstream oss;
if (out)
oss << "#' \\item{" << d.name << "}{";
else
oss << "#' @param " << d.name << " ";
oss << d.desc.substr(0, d.desc.size() - 1);
// Print a default, if possible.
if (!d.required)
{
if (d.cppType == "std::string" ||
d.cppType == "double" ||
d.cppType == "int" ||
d.cppType == "bool")
{
oss << ". Default value \"";
if (d.cppType == "std::string")
{
oss << boost::any_cast<std::string>(d.value);
}
else if (d.cppType == "double")
{
oss << boost::any_cast<double>(d.value);
}
else if (d.cppType == "int")
{
oss << boost::any_cast<int>(d.value);
}
else if (d.cppType == "bool")
{
oss << (boost::any_cast<bool>(d.value) ? "TRUE" : "FALSE");
}
oss << "\"";
}
}
oss << " (" << GetRType<typename std::remove_pointer<T>::type>(d) << ").";
if (out)
oss << "}";
MLPACK_COUT_STREAM << util::HyphenateString(oss.str(), "#' ");
}
} // namespace r
} // namespace bindings
} // namespace mlpack
#endif
@@ -0,0 +1,142 @@
/**
* @file bindings/R/print_doc_functions.hpp
* @author Yashwant Singh Parihar
*
* This file contains functions useful for printing documentation strings
* related to R bindings.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#ifndef MLPACK_BINDINGS_R_PRINT_DOC_FUNCTIONS_HPP
#define MLPACK_BINDINGS_R_PRINT_DOC_FUNCTIONS_HPP
#include <mlpack/core/util/hyphenate_string.hpp>
namespace mlpack {
namespace bindings {
namespace r {
/**
* Given the name of a binding, print its R name.
*/
inline std::string GetBindingName(const std::string& bindingName);
/**
* Print any import information for the R binding.
*/
inline std::string PrintImport();
/**
* Print any special information about input options.
*/
inline std::string PrintInputOptionInfo();
/**
* Print any special information about output options.
*/
inline std::string PrintOutputOptionInfo();
/**
* Given a parameter type, print the corresponding value.
*/
template<typename T>
inline std::string PrintValue(const T& value, bool quotes);
/**
* Special overload for booleans.
*/
template<>
inline std::string PrintValue(const bool& value, bool quotes);
/**
* Given a parameter name, print its corresponding default value.
*/
inline std::string PrintDefault(const std::string& paramName);
/**
* Recursion base case.
*/
inline std::string PrintInputOptions();
/**
* Print an input option. This will throw an exception if the parameter does
* not exist in IO.
*/
template<typename T, typename... Args>
std::string PrintInputOptions(const std::string& paramName,
const T& value,
Args... args);
/**
* Recursion base case.
*/
inline std::string PrintOutputOptions(const bool /* markdown */);
template<typename T, typename... Args>
std::string PrintOutputOptions(const bool markdown,
const std::string& paramName,
const T& value,
Args... args);
/**
* Given a name of a binding and a variable number of arguments (and their
* contents), print the corresponding function call.
*/
template<typename... Args>
std::string ProgramCall(const bool markdown,
const std::string& programName,
Args... args);
/**
* Given the name of a binding, print a program call assuming that all options
* are specified.
*/
inline std::string ProgramCall(const std::string& programName);
/**
* Given the name of a model, print it. Here we do not need to modify anything.
*/
inline std::string PrintModel(const std::string& modelName);
/**
* Given the name of a matrix, print it. Here we do not need to modify
* anything.
*/
inline std::string PrintDataset(const std::string& datasetName);
/**
* Given the parameter name, determine what it would actually be when passed to
* the command line.
*/
inline std::string ParamString(const std::string& paramName);
/**
* Print whether or not we should ignore a check on the given parameter.
*/
inline bool IgnoreCheck(const std::string& paramName);
/**
* Print whether or not we should ignore a check on the given set of
* constraints.
*/
inline bool IgnoreCheck(const std::vector<std::string>& constraints);
/**
* Print whether or not we should ignore a check on the given set of
* constraints.
*/
inline bool IgnoreCheck(
const std::vector<std::pair<std::string, bool>>& constraints,
const std::string& paramName);
} // namespace r
} // namespace bindings
} // namespace mlpack
// Include implementation.
#include "print_doc_functions_impl.hpp"
#endif
@@ -0,0 +1,410 @@
/**
* @file bindings/R/print_doc_functions_impl.hpp
* @author Yashwant Singh Parihar
*
* This file contains functions useful for printing documentation strings
* related to R bindings.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#ifndef MLPACK_BINDINGS_R_PRINT_DOC_FUNCTIONS_IMPL_HPP
#define MLPACK_BINDINGS_R_PRINT_DOC_FUNCTIONS_IMPL_HPP
#include <mlpack/core/util/hyphenate_string.hpp>
namespace mlpack {
namespace bindings {
namespace r {
/**
* Given the name of a binding, print its R name.
*/
inline std::string GetBindingName(const std::string& bindingName)
{
// No modification is needed to the name---we just use it as-is.
return bindingName + "()";
}
/**
* Print any import information for the R binding.
*/
inline std::string PrintImport()
{
return "library(mlpack)";
}
/**
* Print any special information about input options.
*/
inline std::string PrintInputOptionInfo()
{
return "";
}
/**
* Print any special information about output options.
*/
inline std::string PrintOutputOptionInfo()
{
return "Results are returned in a R list. The keys of the "
"list are the names of the output parameters.";
}
/**
* Given a parameter type, print the corresponding value.
*/
template<typename T>
inline std::string PrintValue(const T& value, bool quotes)
{
std::ostringstream oss;
if (quotes)
oss << "\"";
oss << value;
if (quotes)
oss << "\"";
return oss.str();
}
/**
* Given a vector parameter type, print the corresponding value.
*/
template<typename T>
inline std::string PrintValue(const std::vector<T>& value, bool quotes)
{
std::ostringstream oss;
if (quotes)
oss << "\"";
oss << "c(";
if (value.size() > 0)
{
oss << value[0];
for (size_t i = 1; i < value.size(); ++i)
oss << ", " << value[i];
}
oss << ")";
if (quotes)
oss << "\"";
return oss.str();
}
/**
* Given a parameter name, print its corresponding default value.
*/
inline std::string PrintDefault(const std::string& paramName)
{
if (IO::Parameters().count(paramName) == 0)
throw std::invalid_argument("unknown parameter " + paramName + "!");
util::ParamData& d = IO::Parameters()[paramName];
std::string defaultValue;
IO::GetSingleton().functionMap[d.tname]["DefaultParam"](d, NULL,
(void*) &defaultValue);
return defaultValue;
}
/**
* Special overload for booleans.
*/
template<>
inline std::string PrintValue(const bool& value, bool quotes)
{
if (quotes && value)
return "\"TRUE\"";
else if (quotes && !value)
return "\"FALSE\"";
else if (!quotes && value)
return "TRUE";
else
return "FALSE";
}
/**
* Recursion base case.
*/
std::string PrintInputOptions() { return ""; }
/**
* Print an input option. This will throw an exception if the parameter does
* not exist in IO.
*/
template<typename T, typename... Args>
std::string PrintInputOptions(const std::string& paramName,
const T& value,
Args... args)
{
// See if this is part of the program.
std::string result = "";
if (IO::Parameters().count(paramName) > 0)
{
util::ParamData& d = IO::Parameters()[paramName];
if (d.input)
{
// Print the input option.
std::ostringstream oss;
oss << paramName << "=";
oss << PrintValue(value, d.tname == TYPENAME(std::string));
result = oss.str();
}
}
else
{
// Unknown parameter!
throw std::runtime_error("Unknown parameter '" + paramName + "' " +
"encountered while assembling documentation! Check PROGRAM_INFO() " +
"declaration.");
}
// Continue recursion.
std::string rest = PrintInputOptions(args...);
if (rest != "" && result != "")
result += ", " + rest;
else if (result == "")
result = rest;
return result;
}
/**
* Recursion base case.
*/
inline std::string PrintOutputOptions(const bool /* markdown */) { return ""; }
template<typename T, typename... Args>
std::string PrintOutputOptions(const bool markdown,
const std::string& paramName,
const T& value,
Args... args)
{
// See if this is part of the program.
std::string result = "";
std::string command_prefix = "R> ";
if (IO::Parameters().count(paramName) > 0)
{
util::ParamData& d = IO::Parameters()[paramName];
if (!d.input)
{
// Print a new line for the output option.
std::ostringstream oss;
if (markdown)
oss << command_prefix;
oss << value << " <- output$" << paramName;
result = oss.str();
}
}
else
{
// Unknown parameter!
throw std::runtime_error("Unknown parameter '" + paramName + "' " +
"encountered while assembling documentation! Check PROGRAM_INFO() " +
"declaration.");
}
// Continue recursion.
std::string rest = PrintOutputOptions(markdown, args...);
if (rest != "" && result != "")
result += "\n";
result += rest;
return result;
}
/**
* Given a name of a binding and a variable number of arguments (and their
* contents), print the corresponding function call.
*/
template<typename... Args>
std::string ProgramCall(const bool markdown,
const std::string& programName,
Args... args)
{
std::ostringstream oss;
if (markdown)
oss << "R> ";
// Find out if we have any output options first.
std::ostringstream ossOutput;
ossOutput << PrintOutputOptions(markdown, args...);
if (ossOutput.str() != "")
oss << "output <- ";
oss << programName << "(";
// Now process each input option.
oss << PrintInputOptions(args...);
oss << ")";
std::string call = oss.str();
oss.str(""); // Reset it.
// Now process each output option.
oss << PrintOutputOptions(markdown, args...);
if (markdown)
{
if (oss.str() == "")
return util::HyphenateString(call, 2);
else
return util::HyphenateString(call, 2) + "\n" + oss.str();
}
if (oss.str() == "")
return "\\dontrun{\n" + util::HyphenateString(call, 2) + "\n}";
else
return "\\dontrun{\n" + util::HyphenateString(call, 2) + "\n" + oss.str() +
"\n}";
}
/**
* Given the name of a binding, print a program call assuming that all options
* are specified. The programName should not be the output of GetBindingName().
*/
inline std::string ProgramCall(const std::string& programName)
{
std::ostringstream oss;
std::string command_prefix = "R> ";
oss << command_prefix;
// Determine if we have any output options.
std::map<std::string, util::ParamData>& parameters = IO::Parameters();
bool hasOutput = false;
for (auto it = parameters.begin(); it != parameters.end(); ++it)
{
if (!it->second.input)
{
hasOutput = true;
break;
}
}
if (hasOutput)
oss << "d <- ";
oss << programName << "(";
// Now iterate over every input option.
bool first = true;
for (auto it = parameters.begin(); it != parameters.end(); ++it)
{
if (!it->second.input || (it->second.persistent &&
it->second.name != "verbose"))
continue;
if (!first)
oss << ", ";
else
first = false;
// Print the input option.
oss << it->second.name << "=";
std::string value;
IO::GetSingleton().functionMap[it->second.tname]["DefaultParam"](
it->second, NULL, (void*) &value);
oss << value;
}
oss << ")";
std::string result = util::HyphenateString(oss.str(), 8);
oss.str("");
oss << result;
// Now print output lines.
for (auto it = parameters.begin(); it != parameters.end(); ++it)
{
if (it->second.input)
continue;
// Print a new line for the output option.
oss << std::endl << command_prefix << it->second.name << " <- d$"
<< it->second.name;
}
return oss.str();
}
/**
* Given the name of a model, print it. Here we do not need to modify anything.
*/
inline std::string PrintModel(const std::string& modelName)
{
return "\"" + modelName + "\"";
}
/**
* Given the name of a matrix, print it. Here we do not need to modify
* anything.
*/
inline std::string PrintDataset(const std::string& datasetName)
{
return "\"" + datasetName + "\"";
}
/**
* Print any closing call to a program.
*/
inline std::string ProgramCallClose()
{
return ")";
}
/**
* Given the parameter name, determine what it would actually be when passed to
* the command line.
*/
inline std::string ParamString(const std::string& paramName)
{
// For a R binding we don't need to know the type.
return "\"" + paramName + "\"";
}
/**
* Given the parameter name and an argument, return what should be written as
* documentation when referencing that argument.
*/
template<typename T>
inline std::string ParamString(const std::string& paramName, const T& value)
{
std::ostringstream oss;
oss << paramName << "=" << value;
return oss.str();
}
inline bool IgnoreCheck(const std::string& paramName)
{
return !IO::Parameters()[paramName].input;
}
inline bool IgnoreCheck(const std::vector<std::string>& constraints)
{
for (size_t i = 0; i < constraints.size(); ++i)
{
if (!IO::Parameters()[constraints[i]].input)
return true;
}
return false;
}
inline bool IgnoreCheck(
const std::vector<std::pair<std::string, bool>>& constraints,
const std::string& paramName)
{
for (size_t i = 0; i < constraints.size(); ++i)
{
if (!IO::Parameters()[constraints[i].first].input)
return true;
}
return !IO::Parameters()[paramName].input;
}
} // namespace r
} // namespace bindings
} // namespace mlpack
#endif
@@ -0,0 +1,42 @@
/**
* @file bindings/R/print_input_param.hpp
* @author Yashwant Singh Parihar
*
* Print the declaration of an input parameter as part of a line in a R
* function definition.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#ifndef MLPACK_BINDINGS_R_PRINT_INPUT_PARAM_HPP
#define MLPACK_BINDINGS_R_PRINT_INPUT_PARAM_HPP
#include <mlpack/prereqs.hpp>
namespace mlpack {
namespace bindings {
namespace r {
/**
* Print the declaration of an input parameter as part of a line in a R
* function definition. This doesn't include any commas or anything.
*/
template<typename T>
void PrintInputParam(util::ParamData& d,
const void* /* input */,
void* /* output */)
{
MLPACK_COUT_STREAM << d.name;
if (std::is_same<T, bool>::value)
MLPACK_COUT_STREAM << "=FALSE";
else if (!d.required)
MLPACK_COUT_STREAM << "=NA";
}
} // namespace r
} // namespace bindings
} // namespace mlpack
#endif
@@ -0,0 +1,206 @@
/**
* @file bindings/R/print_input_processing.hpp
* @author Yashwant Singh Parihar
*
* Print R code to handle input arguments.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#ifndef MLPACK_BINDINGS_R_PRINT_INPUT_PROCESSING_IMPL_HPP
#define MLPACK_BINDINGS_R_PRINT_INPUT_PROCESSING_IMPL_HPP
#include <mlpack/bindings/util/strip_type.hpp>
#include "get_type.hpp"
#include <mlpack/prereqs.hpp>
namespace mlpack {
namespace bindings {
namespace r {
/**
* Print input processing for a standard option type.
*/
template<typename T>
void PrintInputProcessing(
util::ParamData& d,
const typename boost::disable_if<arma::is_arma_type<T>>::type* = 0,
const typename boost::disable_if<data::HasSerialize<T>>::type* = 0,
const typename boost::disable_if<std::is_same<T,
std::tuple<data::DatasetInfo, arma::mat>>>::type* = 0)
{
if (!d.required)
{
/**
* This gives us code like:
*
* if (!identical(<param_name>, NA)) {
* IO_SetParam<type>("<param_name>", <param_name>)
* }
*/
MLPACK_COUT_STREAM << " if (!identical(" << d.name;
if (d.cppType == "bool")
{
MLPACK_COUT_STREAM << ", FALSE)) {" << std::endl;
}
else
{
MLPACK_COUT_STREAM << ", NA)) {" << std::endl;
}
MLPACK_COUT_STREAM << " IO_SetParam" << GetType<T>(d) << "(\""
<< d.name << "\", " << d.name << ")" << std::endl;
MLPACK_COUT_STREAM << " }" << std::endl; // Closing brace.
}
else
{
/**
* This gives us code like:
*
* IO_SetParam<type>("<param_name>", <param_name>)
*/
MLPACK_COUT_STREAM << " IO_SetParam" << GetType<T>(d) << "(\""
<< d.name << "\", " << d.name << ")" << std::endl;
}
MLPACK_COUT_STREAM << std::endl; // Extra line is to clear up the code a bit.
}
/**
* Print input processing for a matrix type.
*/
template<typename T>
void PrintInputProcessing(
util::ParamData& d,
const typename boost::enable_if<arma::is_arma_type<T>>::type* = 0)
{
if (!d.required)
{
/**
* This gives us code like:
*
* if (!identical(<param_name>, NA)) {
* IO_SetParam<type>("<param_name>", to_matrix(<param_name>))
* }
*/
MLPACK_COUT_STREAM << " if (!identical(" << d.name << ", NA)) {"
<< std::endl;
MLPACK_COUT_STREAM << " IO_SetParam" << GetType<T>(d) << "(\""
<< d.name << "\", to_matrix(" << d.name << "))" << std::endl;
MLPACK_COUT_STREAM << " }" << std::endl; // Closing brace.
}
else
{
/**
* This gives us code like:
*
* IO_SetParam<type>("<param_name>", to_matrix(<param_name>))
*/
MLPACK_COUT_STREAM << " IO_SetParam" << GetType<T>(d) << "(\""
<< d.name << "\", to_matrix(" << d.name << "))" << std::endl;
}
MLPACK_COUT_STREAM << std::endl; // Extra line is to clear up the code a bit.
}
/**
* Print input processing for a matrix with info type.
*/
template<typename T>
void PrintInputProcessing(
util::ParamData& d,
const typename boost::enable_if<std::is_same<T,
std::tuple<data::DatasetInfo, arma::mat>>>::type* = 0)
{
if (!d.required)
{
/**
* This gives us code like:
*
* if (!identical(<param_name>, NA)) {
* <param_name> = to_matrix_with_info(<param_name>)
* IO_SetParam<type>("<param_name>", <param_name>$info,
* <param_name>$data)
* }
*/
MLPACK_COUT_STREAM << " if (!identical(" << d.name << ", NA)) {"
<< std::endl;
MLPACK_COUT_STREAM << " " << d.name << " <- to_matrix_with_info("
<< d.name << ")" << std::endl;
MLPACK_COUT_STREAM << " IO_SetParam" << GetType<T>(d) << "(\""
<< d.name << "\", " << d.name << "$info, " << d.name
<< "$data)" << std::endl;
MLPACK_COUT_STREAM << " }" << std::endl; // Closing brace.
}
else
{
/**
* This gives us code like:
*
* <param_name> = to_matrix_with_info(<param_name>)
* IO_SetParam<type>("<param_name>", <param_name>$info,
* <param_name>$data)
*/
MLPACK_COUT_STREAM << " " << d.name << " <- to_matrix_with_info("
<< d.name << ")" << std::endl;
MLPACK_COUT_STREAM << " IO_SetParam" << GetType<T>(d) << "(\""
<< d.name << "\", " << d.name << "$info, " << d.name
<< "$data)" << std::endl;
}
MLPACK_COUT_STREAM << std::endl; // Extra line is to clear up the code a bit.
}
/**
* Print input processing for a serializable type.
*/
template<typename T>
void PrintInputProcessing(
util::ParamData& d,
const typename boost::disable_if<arma::is_arma_type<T>>::type* = 0,
const typename boost::enable_if<data::HasSerialize<T>>::type* = 0)
{
if (!d.required)
{
/**
* This gives us code like:
*
* if (!identical(<param_name>, NA)) {
* IO_SetParam<ModelType>Ptr("<param_name>", <param_name>)
* }
*/
MLPACK_COUT_STREAM << " if (!identical(" << d.name << ", NA)) {"
<< std::endl;
MLPACK_COUT_STREAM << " IO_SetParam" << util::StripType(d.cppType)
<< "Ptr(\"" << d.name << "\", " << d.name << ")" << std::endl;
MLPACK_COUT_STREAM << " }" << std::endl; // Closing brace.
}
else
{
/**
* This gives us code like:
*
* IO_SetParam<ModelType>Ptr("<param_name>", <param_name>)
*/
MLPACK_COUT_STREAM << " IO_SetParam" << util::StripType(d.cppType)
<< "Ptr(\"" << d.name << "\", " << d.name << ")" << std::endl;
}
MLPACK_COUT_STREAM << std::endl; // Extra line is to clear up the code a bit.
}
/**
* @param d Parameter data struct.
* @param * (input) Unused parameter.
* @param * (output) Unused parameter.
*/
template<typename T>
void PrintInputProcessing(util::ParamData& d,
const void* /* input */,
void* /* output */)
{
PrintInputProcessing<typename std::remove_pointer<T>::type>(d);
}
} // namespace r
} // namespace bindings
} // namespace mlpack
#endif
@@ -0,0 +1,122 @@
/**
* @file bindings/R/print_output_processing.hpp
* @author Yashwant Singh Parihar
*
* Print the output processing in a R binding .R file for a given
* parameter.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#ifndef MLPACK_BINDINGS_R_PRINT_OUTPUT_PROCESSING_HPP
#define MLPACK_BINDINGS_R_PRINT_OUTPUT_PROCESSING_HPP
#include <mlpack/prereqs.hpp>
#include "get_type.hpp"
namespace mlpack {
namespace bindings {
namespace r {
/**
* Print output processing for a regular parameter type.
*/
template<typename T>
void PrintOutputProcessing(
util::ParamData& d,
const typename boost::disable_if<arma::is_arma_type<T>>::type* = 0,
const typename boost::disable_if<data::HasSerialize<T>>::type* = 0,
const typename boost::disable_if<std::is_same<T,
std::tuple<data::DatasetInfo, arma::mat>>>::type* = 0)
{
/**
* This gives us code like:
*
* "<param_name>" = IO_GetParam<Type>("param_name")
*
*/
MLPACK_COUT_STREAM << " \"" << d.name << "\" = IO_GetParam" << GetType<T>(d)
<< "(\"" << d.name << "\")";
}
/**
* Print output processing for a matrix type.
*/
template<typename T>
void PrintOutputProcessing(
util::ParamData& d,
const typename boost::enable_if<arma::is_arma_type<T>>::type* = 0,
const typename std::enable_if<!std::is_same<T,
std::tuple<data::DatasetInfo, arma::mat>>::value>::type* = 0)
{
/**
* This gives us code like:
*
* "<param_name>" = IO_GetParam<Type>("param_name")
*
*/
MLPACK_COUT_STREAM << " \"" << d.name << "\" = IO_GetParam" << GetType<T>(d)
<< "(\"" << d.name << "\")";
}
/**
* Print output processing for a matrix with info type.
*/
template<typename T>
void PrintOutputProcessing(
util::ParamData& d,
const typename boost::enable_if<std::is_same<T,
std::tuple<data::DatasetInfo, arma::mat>>>::type* = 0)
{
/**
* This gives us code like:
*
* "<param_name>" = IO_GetParam<Type>("param_name")
*
*/
MLPACK_COUT_STREAM << " \"" << d.name << "\" = IO_GetParam" << GetType<T>(d)
<< "(\"" << d.name << "\")";
}
/**
* Print output processing for a serializable model.
*/
template<typename T>
void PrintOutputProcessing(
util::ParamData& d,
const typename boost::disable_if<arma::is_arma_type<T>>::type* = 0,
const typename boost::enable_if<data::HasSerialize<T>>::type* = 0)
{
/**
* This gives us code like:
*
* "<param_name>" = <param_name>
*
*/
MLPACK_COUT_STREAM << " \"" << d.name << "\" = " << d.name;
}
/**
* @param d Parameter data struct.
* @param * (input) Unused parameter.
* @param * (output) Unused parameter.
*/
template<typename T>
void PrintOutputProcessing(util::ParamData& d,
const void* /*input*/,
void* /* output */)
{
PrintOutputProcessing<typename std::remove_pointer<T>::type>(d);
}
} // namespace r
} // namespace bindings
} // namespace mlpack
#endif
@@ -0,0 +1,86 @@
/**
* @file bindings/R/print_serialize_util.hpp
* @author Yashwant Singh Parihar
*
* Print the serialize utility in a R binding .R file for a given
* parameter.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#ifndef MLPACK_BINDINGS_R_PRINT_SERIALIZE_UTIL_HPP
#define MLPACK_BINDINGS_R_PRINT_SERIALIZE_UTIL_HPP
#include <mlpack/bindings/util/strip_type.hpp>
namespace mlpack {
namespace bindings {
namespace r {
/**
* If the type is not serializable, print nothing.
*/
template<typename T>
void PrintSerializeUtil(
util::ParamData& /* d */,
const typename std::enable_if<!arma::is_arma_type<T>::value>::type* = 0,
const typename std::enable_if<!data::HasSerialize<T>::value>::type* = 0)
{
// Do Nothing.
}
/**
* Matrices are serializable but here we also print nothing.
*/
template<typename T>
void PrintSerializeUtil(
util::ParamData& /* d */,
const typename std::enable_if<arma::is_arma_type<T>::value>::type* = 0)
{
// Do Nothing.
}
/**
* For non-matrix serializable types we need to print something.
*/
template<typename T>
void PrintSerializeUtil(
util::ParamData& d,
const typename std::enable_if<!arma::is_arma_type<T>::value>::type* = 0,
const typename std::enable_if<data::HasSerialize<T>::value>::type* = 0)
{
/**
* This gives us code like:
*
* <param_name> <- IO_GetParam<ModelType>Ptr("<param_name>")
* attr(<param_name>, "type") <- "<ModelType>"
*
*/
MLPACK_COUT_STREAM << " " << d.name << " <- IO_GetParam"
<< util::StripType(d.cppType) << "Ptr(\"" << d.name << "\")";
MLPACK_COUT_STREAM << std::endl;
MLPACK_COUT_STREAM << " attr(" << d.name << ", \"type\") <- \""
<< util::StripType(d.cppType) << "\"";
MLPACK_COUT_STREAM << std::endl;
}
/**
* @param d Parameter data struct.
* @param * (input) Unused parameter.
* @param * (output) Unused parameter.
*/
template<typename T>
void PrintSerializeUtil(util::ParamData& d,
const void* /*input*/,
void* /* output */)
{
PrintSerializeUtil<typename std::remove_pointer<T>::type>(d);
}
} // namespace r
} // namespace bindings
} // namespace mlpack
#endif
+86
View File
@@ -0,0 +1,86 @@
/**
* @file bindings/R/print_type_doc.hpp
* @author Yashwant Singh Parihar
*
* Print documentation for a given type, detailing what the type actually is to
* the user.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#ifndef MLPACK_BINDINGS_R_PRINT_TYPE_DOC_HPP
#define MLPACK_BINDINGS_R_PRINT_TYPE_DOC_HPP
#include <mlpack/core/util/is_std_vector.hpp>
namespace mlpack {
namespace bindings {
namespace r {
/**
* Return a string representing the command-line type of an option.
*/
template<typename T>
std::string PrintTypeDoc(
util::ParamData& data,
const typename boost::disable_if<arma::is_arma_type<T>>::type* = 0,
const typename boost::disable_if<util::IsStdVector<T>>::type* = 0,
const typename boost::disable_if<data::HasSerialize<T>>::type* = 0,
const typename boost::disable_if<std::is_same<T,
std::tuple<data::DatasetInfo, arma::mat>>>::type* = 0);
/**
* Return a string representing the command-line type of a vector.
*/
template<typename T>
std::string PrintTypeDoc(
util::ParamData& data,
const typename std::enable_if<util::IsStdVector<T>::value>::type* = 0);
/**
* Return a string representing the command-line type of a matrix option.
*/
template<typename T>
std::string PrintTypeDoc(
util::ParamData& data,
const typename std::enable_if<arma::is_arma_type<T>::value>::type* = 0);
/**
* Return a string representing the command-line type of a matrix tuple option.
*/
template<typename T>
std::string PrintTypeDoc(
util::ParamData& data,
const typename std::enable_if<std::is_same<T,
std::tuple<data::DatasetInfo, arma::mat>>::value>::type* = 0);
/**
* Return a string representing the command-line type of a model.
*/
template<typename T>
std::string PrintTypeDoc(
util::ParamData& data,
const typename boost::disable_if<arma::is_arma_type<T>>::type* = 0,
const typename boost::enable_if<data::HasSerialize<T>>::type* = 0);
/**
* Print the command-line type of an option into a string.
*/
template<typename T>
void PrintTypeDoc(util::ParamData& data,
const void* /* input */,
void* output)
{
*((std::string*) output) =
PrintTypeDoc<typename std::remove_pointer<T>::type>(data);
}
} // namespace r
} // namespace bindings
} // namespace mlpack
#include "print_type_doc_impl.hpp"
#endif
@@ -0,0 +1,165 @@
/**
* @file bindings/R/print_type_doc_impl.hpp
* @author Yashwant Singh Parihar
*
* Print documentation for a given type.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#ifndef MLPACK_BINDINGS_R_PRINT_TYPE_DOC_IMPL_HPP
#define MLPACK_BINDINGS_R_PRINT_TYPE_DOC_IMPL_HPP
#include "print_type_doc.hpp"
namespace mlpack {
namespace bindings {
namespace r {
/**
* Return a string representing the command-line type of an option.
*/
template<typename T>
std::string PrintTypeDoc(
util::ParamData& data,
const typename boost::disable_if<arma::is_arma_type<T>>::type*,
const typename boost::disable_if<util::IsStdVector<T>>::type*,
const typename boost::disable_if<data::HasSerialize<T>>::type*,
const typename boost::disable_if<std::is_same<T,
std::tuple<data::DatasetInfo, arma::mat>>>::type*)
{
// A flag type.
if (std::is_same<T, bool>::value)
{
return "A boolean flag option (i.e. `TRUE` or `FALSE`).";
}
// An integer.
else if (std::is_same<T, int>::value)
{
return "An integer (i.e., `1`).";
}
// A floating point value.
else if (std::is_same<T, double>::value)
{
return "A floating-point number (i.e., `0.5`).";
}
// A string.
else if (std::is_same<T, std::string>::value)
{
return "A character string (i.e., `\"hello\"`).";
}
// Not sure what it is...
else
{
throw std::invalid_argument("Unknown parameter type `" + data.cppType +
"`.");
}
}
/**
* Return a string representing the command-line type of a vector.
*/
template<typename T>
std::string PrintTypeDoc(
util::ParamData& data,
const typename std::enable_if<util::IsStdVector<T>::value>::type*)
{
if (std::is_same<T, std::vector<int>>::value)
{
return "A vector of integers; i.e., `c(0, 1, 2)`.";
}
else if (std::is_same<T, std::vector<std::string>>::value)
{
return "A vector of strings; i.e., `c(\"hello\", \"goodbye\")`.";
}
else
{
throw std::invalid_argument("Unknown vector type `" + data.cppType + "`.");
}
}
/**
* Return a string representing the command-line type of a matrix option.
*/
template<typename T>
std::string PrintTypeDoc(
util::ParamData& data,
const typename std::enable_if<arma::is_arma_type<T>::value>::type*)
{
if (std::is_same<typename T::elem_type, double>::value)
{
if (T::is_col || T::is_row)
{
return "A 1-d matrix-like containing `numeric` data (could be an "
"`matrix` or a `data.frame` with one dimension of size 1).";
}
else
{
return "A 2-d matrix-like containing `numeric` data (could be an "
"`matrix` or a `data.frame` or anything convertible to an "
"2-d `matrix`).";
}
}
else if (std::is_same<typename T::elem_type, size_t>::value)
{
if (T::is_col || T::is_row)
{
return "A 1-d matrix-like containing `integer` data (could be an "
"`matrix` or a `data.frame` with one dimension of size 1).";
}
else
{
return "A 2-d matrix-like containing `integer` data (could be an "
"`matrix` or a `data.frame` or anything convertible to an "
"2-d `matrix`).";
}
}
else
{
throw std::invalid_argument("Unknown matrix type `" + data.cppType + "`.");
}
}
/**
* Return a string representing the command-line type of a matrix tuple option.
*/
template<typename T>
std::string PrintTypeDoc(
util::ParamData& /* data */,
const typename std::enable_if<std::is_same<T,
std::tuple<data::DatasetInfo, arma::mat>>::value>::type*)
{
return "A 2-d array containing `numeric` data. Like the regular 2-d matrices"
", this can be a `matrix`, or a `data.frame`. However, this type can also"
" accept a `data.frame` that has columns of type `character`, `logical` "
"or `factor`. These values will be converted to `numeric` indices before"
" being passed to mlpack, and then inside mlpack they will be properly "
"treated as categorical variables, so there is no need to do one-hot "
"encoding for this matrix type.";
}
/**
* Return a string representing the command-line type of a model.
*/
template<typename T>
std::string PrintTypeDoc(
util::ParamData& /* data */,
const typename boost::disable_if<arma::is_arma_type<T>>::type*,
const typename boost::enable_if<data::HasSerialize<T>>::type*)
{
return "An mlpack model pointer. `<Model>` refers to the type of model that "
"is being stored, so, e.g., for `cf()`, the type will be `CFModel`. "
"This type holds a pointer to C++ memory containing the mlpack model. "
"Note that this means the mlpack model itself cannot be easily inspected "
"in R. However, the pointer can be passed to subsequent calls to "
"mlpack functions, and can be serialized and deserialized via either the "
"`Serialize()` and `Unserialize()` functions.";
}
} // namespace r
} // namespace bindings
} // namespace mlpack
#endif
+23
View File
@@ -0,0 +1,23 @@
/**
* @file src/${PROGRAM_NAME}.cpp
*
* This is an autogenerated file containing implementations of C++ functions to
* be called by the R ${PROGRAM_NAME} binding.
*/
#include <rcpp_mlpack.h>
#define BINDING_TYPE BINDING_TYPE_R
#include <${INCLUDE_FILE}>
#define Realloc(p,n,t) (t *) R_chk_realloc( (void *)(p), (R_SIZE_T)((n) * sizeof(t)) )
#define Free(p) (R_chk_free( (void *)(p) ), (p) = NULL)
// [[Rcpp::export]]
void ${PROGRAM_NAME}_mlpackMain()
{
mlpackMain();
}
// Any implementations of methods for dealing with model pointers will be put
// below this comment, if needed.
${MODEL_PTR_IMPLS}
@@ -0,0 +1,6 @@
# Add the R binding test.
add_r_binding(test_r_binding)
add_test(NAME r_binding_test
COMMAND ${RSCRIPT_EXECUTABLE} -e "library(pkgload); load_all('.'); library(testthat); test_dir('tests/')"
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/src/mlpack/bindings/R/mlpack)
@@ -0,0 +1,197 @@
/**
* @file bindings/R/test_r_binding_main.cpp
* @author Yashwant Singh Parihar
*
* A binding test for R.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#include <mlpack/prereqs.hpp>
#include <mlpack/core/util/io.hpp>
#include <mlpack/core/util/mlpack_main.hpp>
#include <mlpack/core/kernels/gaussian_kernel.hpp>
using namespace std;
using namespace mlpack;
using namespace mlpack::kernel;
// Program Name.
BINDING_NAME("R binding test");
// Short description.
BINDING_SHORT_DESC(
"A simple program to test R binding functionality.");
// Long description.
BINDING_LONG_DESC(
"A simple program to test R binding functionality. You can build "
"mlpack with the BUILD_TESTS option set to off, and this binding will "
"no longer be built.");
PARAM_STRING_IN_REQ("string_in", "Input string, must be 'hello'.", "s");
PARAM_INT_IN_REQ("int_in", "Input int, must be 12.", "i");
PARAM_DOUBLE_IN_REQ("double_in", "Input double, must be 4.0.", "d");
PARAM_FLAG("flag1", "Input flag, must be specified.", "f");
PARAM_FLAG("flag2", "Input flag, must not be specified.", "F");
PARAM_MATRIX_IN("matrix_in", "Input matrix.", "m");
PARAM_UMATRIX_IN("umatrix_in", "Input unsigned matrix.", "u");
PARAM_COL_IN("col_in", "Input column.", "c");
PARAM_UCOL_IN("ucol_in", "Input unsigned column.", "");
PARAM_ROW_IN("row_in", "Input row.", "");
PARAM_UROW_IN("urow_in", "Input unsigned row.", "");
PARAM_MATRIX_AND_INFO_IN("matrix_and_info_in", "Input matrix and info.", "");
PARAM_VECTOR_IN(int, "vector_in", "Input vector of numbers.", "");
PARAM_VECTOR_IN(string, "str_vector_in", "Input vector of strings.", "");
PARAM_MODEL_IN(GaussianKernel, "model_in", "Input model.", "");
PARAM_FLAG("build_model", "If true, a model will be returned.", "");
PARAM_STRING_OUT("string_out", "Output string, will be 'hello2'.", "S");
PARAM_INT_OUT("int_out", "Output int, will be 13.");
PARAM_DOUBLE_OUT("double_out", "Output double, will be 5.0.");
PARAM_MATRIX_OUT("matrix_out", "Output matrix.", "M");
PARAM_UMATRIX_OUT("umatrix_out", "Output unsigned matrix.", "U");
PARAM_COL_OUT("col_out", "Output column. 2x input column", "");
PARAM_UCOL_OUT("ucol_out", "Output unsigned column. 2x input column.", "");
PARAM_ROW_OUT("row_out", "Output row. 2x input row.", "");
PARAM_UROW_OUT("urow_out", "Output unsigned row. 2x input row.", "");
PARAM_MATRIX_OUT("matrix_and_info_out", "Output matrix and info; all numeric "
"elements multiplied by 3.", "");
PARAM_VECTOR_OUT(int, "vector_out", "Output vector.", "");
PARAM_VECTOR_OUT(string, "str_vector_out", "Output string vector.", "");
PARAM_MODEL_OUT(GaussianKernel, "model_out", "Output model, with twice the "
"bandwidth.", "");
PARAM_DOUBLE_OUT("model_bw_out", "The bandwidth of the model.");
static void mlpackMain()
{
const string s = IO::GetParam<string>("string_in");
const int i = IO::GetParam<int>("int_in");
const double d = IO::GetParam<double>("double_in");
IO::GetParam<string>("string_out") = "wrong";
IO::GetParam<int>("int_out") = 11;
IO::GetParam<double>("double_out") = 3.0;
// Check that everything is right on the input, and then set output
// accordingly.
if (!IO::HasParam("flag2") && IO::HasParam("flag1"))
{
if (s == "hello")
IO::GetParam<string>("string_out") = "hello2";
if (i == 12)
IO::GetParam<int>("int_out") = 13;
if (d == 4.0)
IO::GetParam<double>("double_out") = 5.0;
}
// Input matrices should be at least 5 rows; the 5th row will be dropped and
// the 3rd row will be multiplied by two.
if (IO::HasParam("matrix_in"))
{
arma::mat out = move(IO::GetParam<arma::mat>("matrix_in"));
out.shed_row(4);
out.row(2) *= 2.0;
IO::GetParam<arma::mat>("matrix_out") = move(out);
}
// Input matrices should be at least 5 rows; the 5th row will be dropped and
// the 3rd row will be multiplied by two.
if (IO::HasParam("umatrix_in"))
{
arma::Mat<size_t> out =
move(IO::GetParam<arma::Mat<size_t>>("umatrix_in"));
out.shed_row(4);
out.row(2) *= 2;
IO::GetParam<arma::Mat<size_t>>("umatrix_out") = move(out);
}
// An input column or row should have all elements multiplied by two.
if (IO::HasParam("col_in"))
{
arma::vec out = move(IO::GetParam<arma::vec>("col_in"));
out *= 2.0;
IO::GetParam<arma::vec>("col_out") = move(out);
}
if (IO::HasParam("ucol_in"))
{
arma::Col<size_t> out =
move(IO::GetParam<arma::Col<size_t>>("ucol_in"));
out += 1;
IO::GetParam<arma::Col<size_t>>("ucol_out") = move(out);
}
if (IO::HasParam("row_in"))
{
arma::rowvec out = move(IO::GetParam<arma::rowvec>("row_in"));
out *= 2.0;
IO::GetParam<arma::rowvec>("row_out") = move(out);
}
if (IO::HasParam("urow_in"))
{
arma::Row<size_t> out =
move(IO::GetParam<arma::Row<size_t>>("urow_in"));
out += 1;
IO::GetParam<arma::Row<size_t>>("urow_out") = move(out);
}
// Vector arguments should have the last element removed.
if (IO::HasParam("vector_in"))
{
vector<int> out = move(IO::GetParam<vector<int>>("vector_in"));
out.pop_back();
IO::GetParam<vector<int>>("vector_out") = move(out);
}
if (IO::HasParam("str_vector_in"))
{
vector<string> out = move(IO::GetParam<vector<string>>("str_vector_in"));
out.pop_back();
IO::GetParam<vector<string>>("str_vector_out") = move(out);
}
// All numeric elements should be multiplied by 3.
if (IO::HasParam("matrix_and_info_in"))
{
typedef tuple<data::DatasetInfo, arma::mat> TupleType;
TupleType tuple = move(IO::GetParam<TupleType>("matrix_and_info_in"));
const data::DatasetInfo& di = std::get<0>(tuple);
arma::mat& m = std::get<1>(tuple);
for (size_t i = 0; i < m.n_rows; ++i)
{
if (di.Type(i) == data::Datatype::numeric)
m.row(i) *= 2.0;
}
IO::GetParam<arma::mat>("matrix_and_info_out") = move(m);
}
// If we got a request to build a model, then build it.
if (IO::HasParam("build_model"))
{
IO::GetParam<GaussianKernel*>("model_out") = new GaussianKernel(10.0);
}
// If we got an input model, double the bandwidth and output that.
if (IO::HasParam("model_in"))
{
IO::GetParam<double>("model_bw_out") =
IO::GetParam<GaussianKernel*>("model_in")->Bandwidth() * 2.0;
}
}
-1
View File
@@ -53,7 +53,6 @@ if (BUILD_CLI_EXECUTABLES)
target_link_libraries(mlpack_${name}
mlpack
${ARMADILLO_LIBRARIES}
${Boost_LIBRARIES}
${COMPILER_SUPPORT_LIBRARIES}
)
# Make sure that we set BINDING_TYPE to cli so the command-line program is
+1 -30
View File
@@ -3,7 +3,7 @@
* @author Matthew Amidon
*
* Definition of the Option class, which is used to define parameters which are
* used by CLI. The ProgramDoc class also resides here.
* used by CLI.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
@@ -164,35 +164,6 @@ class CLIOption
}
};
/**
* A static object whose constructor registers program documentation with the
* CLI class. This should not be used outside of CLI itself, and you should use
* the PROGRAM_INFO() macro to declare these objects. Only one ProgramDoc
* object should ever exist.
*
* @see core/util/io.hpp, mlpack::IO
*/
class ProgramDoc
{
public:
/**
* Construct a ProgramDoc object. When constructed, it will register itself
* with IO.
*
* @param programName Short string representing the name of the program.
* @param documentation Long string containing documentation on how to use the
* program and what it is. No newline characters are necessary; this is
* taken care of by IO later.
*/
ProgramDoc(const std::string& programName,
const std::string& documentation);
//! The name of the program.
std::string programName;
//! Documentation for what the program does.
std::string documentation;
};
} // namespace cli
} // namespace bindings
} // namespace mlpack
@@ -47,8 +47,8 @@ void ParseCommandLine(int argc, char** argv)
{
// Add the parameter to desc.
util::ParamData& d = it->second;
IO::GetSingleton().functionMap[d.tname]["AddToCLI11"]
(d, NULL, (void*) &app);
IO::GetSingleton().functionMap[d.tname]["AddToCLI11"](d, NULL, (void*)
&app);
}
// Mark that we did parsing.
@@ -136,13 +136,15 @@ void ParseCommandLine(int argc, char** argv)
util::ParamData d = iter->second;
if (d.required)
{
const std::string cliName;
// CLI11 expects the parameter name to have "--" prepended.
std::string cliName;
IO::GetSingleton().functionMap[d.tname]["MapParameterName"](d, NULL,
(void*) &cliName);
cliName = "--" + cliName;
if (!app.count(cliName))
{
Log::Fatal << "Required option --" << cliName << " is undefined."
Log::Fatal << "Required option " << cliName << " is undefined."
<< std::endl;
}
}
@@ -102,8 +102,9 @@ inline std::string ProgramCall(const std::string& programName);
/**
* Print what a user would type to invoke the given option name. Note that the
* name *must* exist in the CLI module. (Note that because of the way
* ProgramInfo is structured, this doesn't mean that all of the PARAM_*()
* declarataions need to come before the PROGRAM_INFO() declaration.)
* BINDING_LONG_DESC() and BINDING_EXAMPLE() is structured, this doesn't mean
* that all of the PARAM_*() declarataions need to come before
* BINDING_LONG_DESC() and BINDING_EXAMPLE() declaration.)
*/
inline std::string ParamString(const std::string& paramName);
@@ -67,6 +67,26 @@ inline std::string PrintValue(const T& value, bool quotes)
return oss.str();
}
/**
* Given a vector parameter type, print the corresponding value.
*/
template<typename T>
inline std::string PrintValue(const std::vector<T>& value, bool quotes)
{
std::ostringstream oss;
if (quotes)
oss << "'";
if (value.size() > 0)
{
oss << value[0];
for (size_t i = 1; i < value.size(); ++i)
oss << ", " << value[i];
}
if (quotes)
oss << "'";
return oss.str();
}
/**
* Given a parameter name, print its corresponding default value.
*/
@@ -138,8 +158,8 @@ std::string ProcessOptions(const std::string& paramName,
else
{
throw std::runtime_error("Unknown parameter '" + paramName + "' " +
"encountered while assembling documentation! Check PROGRAM_INFO() " +
"declaration.");
"encountered while assembling documentation! Check BINDING_LONG_DESC()"
+ " and BINDING_EXAMPLE() declaration.");
}
std::string rest = ProcessOptions(args...);
@@ -229,8 +249,9 @@ inline std::string ProgramCall(const std::string& programName)
/**
* Print what a user would type to invoke the given option name. Note that the
* name *must* exist in the CLI module. (Note that because of the way
* ProgramInfo is structured, this doesn't mean that all of the PARAM_*()
* declarataions need to come before the PROGRAM_INFO() declaration.)
* BINDING_LONG_DESC() and BINDING_EXAMPLE() is structured, this doesn't mean
* that all of the PARAM_*() declarataions need to come before
* BINDING_LONG_DESC() and BINDING_EXAMPLE() declaration.)
*/
inline std::string ParamString(const std::string& paramName)
{
@@ -252,7 +273,7 @@ inline std::string ParamString(const std::string& paramName)
else
{
throw std::runtime_error("Parameter '" + paramName + "' not known! Check "
"PROGRAM_INFO() definition.");
"BINDING_LONG_DESC() and BINDING_EXAMPLE() definition.");
}
}
+10 -6
View File
@@ -25,8 +25,7 @@ void PrintHelp(const std::string& param)
std::string usedParam = param;
std::map<std::string, util::ParamData>& parameters = IO::Parameters();
const std::map<char, std::string>& aliases = IO::Aliases();
util::ProgramDoc& docs = *IO::GetSingleton().doc;
util::BindingDetails& bindingDetails = IO::GetSingleton().doc;
// If we pass a single param, alias it if necessary.
if (usedParam.length() == 1 && aliases.count(usedParam[0]))
usedParam = aliases.at(usedParam[0]);
@@ -64,11 +63,16 @@ void PrintHelp(const std::string& param)
}
// Print out the descriptions.
if (docs.programName != "")
if (bindingDetails.programName != "")
{
std::cout << docs.programName << std::endl << std::endl;
std::cout << " " << util::HyphenateString(docs.documentation(), 2)
<< std::endl << std::endl;
std::cout << bindingDetails.programName << std::endl << std::endl;
std::cout << " " << util::HyphenateString(bindingDetails.longDescription(),
2) << std::endl << std::endl;
for (size_t j = 0; j < bindingDetails.example.size(); ++j)
{
std::cout << " " << util::HyphenateString(bindingDetails.example[j](), 2)
<< std::endl << std::endl;
}
}
else
std::cout << "[undocumented program]" << std::endl << std::endl;
File diff suppressed because it is too large Load Diff
+48 -25
View File
@@ -9,6 +9,29 @@ macro (not_found_return message)
endif()
endmacro ()
macro (post_go_setup)
if (BUILD_GO_BINDINGS)
# Once `GO_MODELS` is populated, generate `models.go`.
file(APPEND
"${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/src/mlpack.org/v1/mlpack/models.go"
"*/\n"
"import \"C\"\n\n"
"import (\n"
" \"runtime\"\n"
" \"unsafe\"\n"
")\n\n")
include("${CMAKE_SOURCE_DIR}/CMake/go/AppendModel.cmake")
# Read list content.
get_property(MODELS GLOBAL PROPERTY GO_MODELS)
foreach (models IN LISTS MODELS)
append_model(
"${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/src/mlpack.org/v1/mlpack/models.go"
${models})
endforeach()
endif()
endmacro ()
# If we are not supposed to make Go bindings, define the macro so it does
# nothing and leave this file.
if (NOT BUILD_GO_BINDINGS)
@@ -16,34 +39,33 @@ if (NOT BUILD_GO_BINDINGS)
endif ()
if (BUILD_GO_BINDINGS)
find_package(Go 1.11.0)
if (NOT GO_FOUND)
set(GO_NOT_FOUND_MSG "${GO_NOT_FOUND_MSG}\n - Go")
endif ()
find_package(Gonum)
if (NOT GONUM_FOUND)
set(GO_NOT_FOUND_MSG "${GO_NOT_FOUND_MSG}\n - Gonum")
endif ()
## We need to check here if Golang is even available. Although actually
## technically, I'm not sure if we even need to know! For the tests though we
## do. So it's probably a good idea to check.
if (FORCE_BUILD_GO_BINDINGS)
find_package(Go 1.11.0)
find_package(Gonum)
if (NOT GO_FOUND OR NOT GONUM_FOUND)
unset(BUILD_GO_BINDINGS CACHE)
set(BUILD_GO_SHLIB OFF)
message(FATAL_ERROR "Go or Gonum not found; unable to build Go bindings!")
message(FATAL_ERROR "\nCould not Build Go Bindings; the following modules are not available: ${GO_NOT_FOUND_MSG}")
endif()
else ()
find_package(Go 1.11.0)
find_package(Gonum)
if (NOT GO_FOUND OR NOT GONUM_FOUND)
unset(BUILD_GO_BINDINGS CACHE)
set(BUILD_GO_SHLIB OFF)
not_found_return("Not building Go bindings; the following modules are not available: ${GO_NOT_FOUND_MSG}")
endif()
endif ()
if (NOT GO_FOUND)
not_found_return("Go not found; not building Go bindings.")
endif ()
if (NOT GONUM_FOUND)
not_found_return("Gonum not found; not building Go bindings.")
endif ()
add_custom_target(go)
# All the bindings will build under "src/mlpack.org/v1/mlpack"; So if user build
@@ -81,7 +103,6 @@ if (BUILD_GO_SHLIB)
print_method_config.hpp
print_method_init.hpp
print_output_processing.hpp
camel_case.hpp
strip_type.hpp
)
@@ -146,12 +167,12 @@ if (BUILD_GO_SHLIB)
endforeach ()
endif ()
add_library(go_util SHARED
add_library(mlpack_go_util SHARED
${CMAKE_SOURCE_DIR}/src/mlpack/bindings/go/mlpack/capi/arma_util.cpp
${CMAKE_SOURCE_DIR}/src/mlpack/bindings/go/mlpack/capi/io_util.cpp)
target_link_libraries(go_util mlpack ${MLPACK_LIBRARIES})
target_compile_definitions(go_util PUBLIC "BINDING_TYPE=BINDING_TYPE_GO")
set_target_properties(go_util PROPERTIES
target_link_libraries(mlpack_go_util mlpack ${MLPACK_LIBRARIES})
target_compile_definitions(mlpack_go_util PUBLIC "BINDING_TYPE=BINDING_TYPE_GO")
set_target_properties(mlpack_go_util PROPERTIES
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/src/mlpack.org/v1/mlpack/)
# Set the include directories correctly.
@@ -159,7 +180,7 @@ if (BUILD_GO_SHLIB)
PROPERTY INCLUDE_DIRECTORIES)
set (GO_INCLDIRS "${GO_INCLUDE_DIRECTORIES}")
install(TARGETS go_util
install(TARGETS mlpack_go_util
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}")
@@ -178,7 +199,7 @@ set_property(GLOBAL PROPERTY GO_MODELS "")
macro (add_go_binding name)
if (BUILD_GO_BINDINGS)
# Include all .h that define model to models.go.
# Include all .h that define model to models.go.
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/${name}_main.cpp" MAIN_FILE)
if (MAIN_FILE MATCHES "PARAM_MODEL")
file(APPEND
@@ -195,6 +216,7 @@ if (BUILD_GO_BINDINGS)
COMMAND ${CMAKE_COMMAND}
-DPROGRAM_NAME=${name}
-DPROGRAM_MAIN_FILE=${CMAKE_CURRENT_SOURCE_DIR}/${name}_main.cpp
-DSOURCE_DIR=${CMAKE_SOURCE_DIR}
-DGO_IN=${CMAKE_SOURCE_DIR}/src/mlpack/bindings/go/go_method.h.in
-DGO_OUT=${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/src/mlpack.org/v1/mlpack/capi/${name}.h
-P ${CMAKE_SOURCE_DIR}/CMake/go/ConfigureGoHCPP.cmake
@@ -208,9 +230,9 @@ if (BUILD_GO_BINDINGS)
-DGENERATE_CPP_OUT=${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/generate_go_${name}.cpp
-DPROGRAM_MAIN_FILE=${CMAKE_CURRENT_SOURCE_DIR}/${name}_main.cpp
-DPROGRAM_NAME=${name}
-P ${CMAKE_SOURCE_DIR}/CMake/ConfigureGenerate.cmake
-P ${CMAKE_SOURCE_DIR}/CMake/ConfigureFile.cmake
DEPENDS ${CMAKE_SOURCE_DIR}/src/mlpack/bindings/go/generate_go.cpp.in
${CMAKE_SOURCE_DIR}/CMake/ConfigureGenerate.cmake)
${CMAKE_SOURCE_DIR}/CMake/ConfigureFile.cmake)
add_executable(generate_go_${name}
${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/src/mlpack.org/v1/mlpack/capi/${name}.h
@@ -224,7 +246,7 @@ if (BUILD_GO_BINDINGS)
COMMAND ${CMAKE_COMMAND}
-DGENERATE_BINDING_PROGRAM=${CMAKE_BINARY_DIR}/bin/generate_go_${name}
-DBINDING_OUTPUT_FILE=${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/src/mlpack.org/v1/mlpack/${name}.go
-P ${CMAKE_SOURCE_DIR}/CMake/GenerateGoBinding.cmake)
-P ${CMAKE_SOURCE_DIR}/CMake/GenerateBinding.cmake)
add_dependencies(go generate_go_${name})
endif ()
@@ -236,6 +258,7 @@ if(BUILD_GO_SHLIB)
COMMAND ${CMAKE_COMMAND}
-DPROGRAM_NAME=${name}
-DPROGRAM_MAIN_FILE=${CMAKE_CURRENT_SOURCE_DIR}/${name}_main.cpp
-DSOURCE_DIR=${CMAKE_SOURCE_DIR}
-DGO_IN=${CMAKE_SOURCE_DIR}/src/mlpack/bindings/go/go_method.cpp.in
-DGO_OUT=${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/build/${name}.cpp
-P ${CMAKE_SOURCE_DIR}/CMake/go/ConfigureGoHCPP.cmake
@@ -245,7 +268,7 @@ if(BUILD_GO_SHLIB)
# Build libmlpack_go_${name}.so.
add_library(mlpack_go_${name} SHARED
${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/build/${name}.cpp)
target_link_libraries(mlpack_go_${name} mlpack go_util)
target_link_libraries(mlpack_go_${name} mlpack mlpack_go_util)
set_target_properties(mlpack_go_${name} PROPERTIES
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/src/mlpack.org/v1/mlpack/")
@@ -256,7 +279,7 @@ if(BUILD_GO_SHLIB)
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}")
add_dependencies(mlpack_go_${name} go_copy)
add_dependencies(mlpack_go_${name} go_util)
add_dependencies(mlpack_go_${name} mlpack_go_util)
add_dependencies(go_shlib mlpack_go_${name})
if (BUILD_GO_BINDINGS)
+1 -1
View File
@@ -74,7 +74,7 @@ std::string DefaultParamImpl(
/**
* Return the default value of an option. This is the function that will be
* placed into the CLI functionMap.
* placed into the IO functionMap.
*/
template<typename T>
void DefaultParam(util::ParamData& data,
+1 -1
View File
@@ -45,5 +45,5 @@ int main(int /* argc */, char** /* argv */)
// programName is defined in mlpack_main.hpp.
IO::RestoreSettings(programName);
PrintGo(*IO::GetSingleton().doc, "${PROGRAM_NAME}");
PrintGo(IO::GetSingleton().doc, "${PROGRAM_NAME}");
}
+3 -3
View File
@@ -41,7 +41,7 @@ class GoOption
public:
/**
* Construct a GoOption object. When constructed, it will register itself
* with CLI. The testName parameter is not used and added for compatibility
* with IO. The testName parameter is not used and added for compatibility
* reasons.
*
* @param defaultValue Default value this parameter will be initialized to
@@ -67,7 +67,7 @@ class GoOption
const bool noTranspose = false,
const std::string& /*testName*/ = "")
{
// Create the ParamData object to give to CLI.
// Create the ParamData object to give to IO.
util::ParamData data;
data.desc = description;
@@ -117,7 +117,7 @@ class GoOption
IO::GetSingleton().functionMap[data.tname]["GetType"] = &GetType<T>;
// Add the ParamData object, then store. This is necessary because we may
// import more than one .so that uses CLI, so we have to keep the options
// import more than one .so that uses IO, so we have to keep the options
// separate. programName is a global variable from mlpack_main.hpp.
IO::Add(std::move(data));
if (identifier != "verbose" /*&& identifier != "copy_all_inputs"*/)
+1 -1
View File
@@ -2,7 +2,7 @@ package mlpack
/*
#cgo CFLAGS: -I. -I/capi -g -Wall -Wno-unused-variable
#cgo LDFLAGS: -L. -lgo_util
#cgo LDFLAGS: -L. -lmlpack_go_util
#include <stdlib.h>
#include <stdio.h>
#include <capi/io_util.h>
@@ -30,7 +30,7 @@ void mlpackToArmaMat(const char* identifier, double* mat,
// Advanced constructor.
arma::mat m(mat, row, col, false, true);
// Set input parameter with corresponding matrix in CLI.
// Set input parameter with corresponding matrix in IO.
SetParam(identifier, m);
}
@@ -45,7 +45,7 @@ void mlpackToArmaUmat(const char* identifier, double* mat,
arma::Mat<size_t> matr = arma::conv_to<arma::Mat<size_t>>::from(m);
// Set input parameter with corresponding matrix in CLI.
// Set input parameter with corresponding matrix in IO.
SetParam(identifier, matr);
}
@@ -57,7 +57,7 @@ void mlpackToArmaRow(const char* identifier, double* rowvec, const size_t elem)
// Advanced constructor.
arma::rowvec m(rowvec, elem, false, true);
// Set input parameter with corresponding row in CLI.
// Set input parameter with corresponding row in IO.
SetParam(identifier, m);
}
@@ -71,7 +71,7 @@ void mlpackToArmaUrow(const char* identifier, double* rowvec, const size_t elem)
arma::Row<size_t> matr = arma::conv_to<arma::Row<size_t>>::from(m);
// Set input parameter with corresponding row in CLI.
// Set input parameter with corresponding row in IO.
SetParam(identifier, matr);
}
@@ -83,7 +83,7 @@ void mlpackToArmaCol(const char* identifier, double* colvec, const size_t elem)
// Advanced constructor.
arma::colvec m(colvec, elem, false, true);
// Set input parameter with corresponding column in CLI.
// Set input parameter with corresponding column in IO.
SetParam(identifier, m);
}
@@ -97,7 +97,7 @@ void mlpackToArmaUcol(const char* identifier, double* colvec, const size_t elem)
arma::Col<size_t> matr = arma::conv_to<arma::Col<size_t>>::from(m);
// Set input parameter with corresponding column in CLI.
// Set input parameter with corresponding column in IO.
SetParam(identifier, matr);
}
/**
@@ -37,6 +37,11 @@ inline typename T::elem_type* GetMemory(T& m)
else
{
arma::access::rw(m.mem_state) = 1;
// With Armadillo 10 and newer, we must set `n_alloc` to 0 so that
// Armadillo does not deallocate the memory.
#if ARMA_VERSION_MAJOR >= 10
arma::access::rw(m.n_alloc) = 0;
#endif
return m.memptr();
}
}
+1 -1
View File
@@ -2,7 +2,7 @@ package mlpack
/*
#cgo CFLAGS: -I. -I/capi -g -Wall
#cgo LDFLAGS: -L${SRCDIR} -Wl,-rpath,${SRCDIR} -lgo_util
#cgo LDFLAGS: -L${SRCDIR} -Wl,-rpath,${SRCDIR} -lmlpack_go_util
#include <capi/io_util.h>
*/
import "C"

Some files were not shown because too many files have changed in this diff Show More