Merge branch 'master' into nsteplearning

This commit is contained in:
Marcus Edel
2020-06-24 21:34:08 +02:00
committed by GitHub
42 changed files with 785 additions and 925 deletions
+1 -1
View File
@@ -43,7 +43,7 @@ steps:
- script: |
unset BOOST_ROOT
mkdir build && cd build
export GOPATH=$PWD
export GOPATH=$PWD/src/mlpack/bindings/go
go get -u -t gonum.org/v1/gonum/...
cmake $(CMakeArgs) ..
displayName: 'CMake'
+1 -1
View File
@@ -28,7 +28,7 @@ steps:
- script: |
unset BOOST_ROOT
mkdir build && cd build
export GOPATH=$PWD
export GOPATH=$PWD/src/mlpack/bindings/go
go get -u -t gonum.org/v1/gonum/...
export PYPATH=$(which python)
cmake $(CMakeArgs) -DPYTHON_EXECUTABLE=$PYPATH ..
-14
View File
@@ -1,14 +0,0 @@
# ConfigureGoHCPP.cmake: generate an mlpack .h file for a Go 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.
# * GENERATE_GO_IN: path of the generate_go.cpp.in file.
# * GENERATE_GO_OUT: name of the output .go file.
# * GENERATE_CPP_IN: path of the generate_cpp.cpp.in file.
# * GENERATE_CPP_OUT: name of the output .cpp file.
# * GENERATE_H_IN: path of the generate_h.cpp.in file.
# * GENERATE_H_OUT: name of the output .h file.
configure_file("${GENERATE_BINDING_IN}" "${GENERATE_BINDING_OUT}")
+116
View File
@@ -0,0 +1,116 @@
# AppendModel.cmake: append model definition and gettter setter methods for
# mlpack model types to the existing file of models.go.
# 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
#
# 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 ()
# Now, generate the definitions of the functions we need.
set(MODEL_PTR_DEFNS "")
set(MODEL_PTR_IMPLS "")
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)
# Convert the model type similar to goStrippedType(bindings/go/strip_type.hpp).
string(LENGTH ${MODEL_SAFE_TYPE} NUM_MODEL_CHAR)
if (${NUM_MODEL_CHAR} GREATER 0)
math(EXPR LAST_CHAR_INDEX "${NUM_MODEL_CHAR}-1")
set(BREAK 0)
foreach (INDEX RANGE ${LAST_CHAR_INDEX})
if (NOT "${MODEL_SAFE_TYPE}" MATCHES "[^A-Z]")
string(TOLOWER ${MODEL_SAFE_TYPE} GOMODEL_SAFE_TYPE)
break()
endif()
string(SUBSTRING ${MODEL_SAFE_TYPE} "${INDEX}" "1" MODEL_CHAR)
if (${BREAK} EQUAL 0)
string(TOLOWER ${MODEL_CHAR} MODEL_CHAR)
string(APPEND GOMODEL_SAFE_TYPE ${MODEL_CHAR})
math(EXPR INDEX1 "${INDEX}+1")
math(EXPR INDEX2 "${INDEX}+2")
string(SUBSTRING "${MODEL_SAFE_TYPE}" "${INDEX1}" "1" MODEL_CHAR1)
string(SUBSTRING "${MODEL_SAFE_TYPE}" "${INDEX2}" "1" MODEL_CHAR2)
if ("${MODEL_CHAR1}" MATCHES "[A-Z]" AND "${MODEL_CHAR2}" MATCHES "[^A-Z]")
set(BREAK 1)
endif()
else ()
string(APPEND GOMODEL_SAFE_TYPE ${MODEL_CHAR})
endif()
endif()
endforeach()
# See if the model type already exists.
file(READ "${SERIALIZATION_FILE}" SERIALIZATION_FILE_CONTENTS)
string(FIND
"${SERIALIZATION_FILE_CONTENTS}"
"type ${GOMODEL_SAFE_TYPE} struct {\n"
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}"
"type ${GOMODEL_SAFE_TYPE} struct {\n"
" mem unsafe.Pointer \n"
"}\n\n"
"func (m *${GOMODEL_SAFE_TYPE}) alloc"
"${MODEL_SAFE_TYPE}(identifier string) {\n"
" m.mem = C.mlpackGet${MODEL_SAFE_TYPE}Ptr(C.CString(identifier))\n"
" runtime.KeepAlive(m)\n"
"}\n\n"
"func (m *${GOMODEL_SAFE_TYPE}) get"
"${MODEL_SAFE_TYPE}(identifier string) {\n"
" m.alloc${MODEL_SAFE_TYPE}(identifier)\n"
"}\n\n"
"func set${MODEL_SAFE_TYPE}(identifier string, ptr *"
"${GOMODEL_SAFE_TYPE}) {\n"
" C.mlpackSet${MODEL_SAFE_TYPE}"
"Ptr(C.CString(identifier), (unsafe.Pointer)(ptr.mem))\n"
"}\n\n")
endif ()
endforeach ()
endif()
endfunction()
+115
View File
@@ -0,0 +1,115 @@
# ConfigureGoHCPP.cmake: generate an mlpack .h/.cpp file for a Go 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.
# * 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 ()
# Now, generate the definitions of the functions we need.
set(MODEL_PTR_DEFNS "")
set(MODEL_PTR_IMPLS "")
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)
# Generate the definition.
set(MODEL_PTR_DEFNS "${MODEL_PTR_DEFNS}
// Set the pointer to a ${MODEL_TYPE} parameter.
extern void mlpackSet${MODEL_SAFE_TYPE}Ptr(const char* identifier, void* value);
// Get the pointer to a ${MODEL_TYPE} parameter.
extern void* mlpackGet${MODEL_SAFE_TYPE}Ptr(const char* identifier);
"
)
# Generate the implementation.
set(MODEL_PTR_IMPLS "${MODEL_PTR_IMPLS}
// Set the pointer to a ${MODEL_TYPE} parameter.
extern \"C\" void mlpackSet${MODEL_SAFE_TYPE}Ptr(
const char* identifier,
void* value)
{
mlpack::util::SetParamPtr<${MODEL_TYPE}>(identifier,
static_cast<${MODEL_TYPE}*>(value));
}
// Get the pointer to a ${MODEL_TYPE} parameter.
extern \"C\" void *mlpackGet${MODEL_SAFE_TYPE}Ptr(const char* identifier)
{
${MODEL_TYPE} *modelptr = CLI::GetParam<${MODEL_TYPE}*>(identifier);
return modelptr;
}
")
endforeach ()
endif()
# Convert ${PROGRAM_NAME} from snake_case to CamelCase.
string(LENGTH ${PROGRAM_NAME} NUM_MODEL_CHAR)
if (${NUM_MODEL_CHAR} GREATER 0)
math(EXPR LAST_CHAR_INDEX "${NUM_MODEL_CHAR}-2")
string(SUBSTRING ${PROGRAM_NAME} "0" "1" MODEL_CHAR)
string(TOUPPER ${MODEL_CHAR} MODEL_CHAR)
string(APPEND GOPROGRAM_NAME ${MODEL_CHAR})
foreach (INDEX0 RANGE ${LAST_CHAR_INDEX})
math(EXPR INDEX0 "${INDEX0}+1")
math(EXPR INDEX1 "${INDEX0}+1")
math(EXPR INDEX2 "${INDEX0}-1")
string(SUBSTRING "${PROGRAM_NAME}" "${INDEX0}" "1" MODEL_CHAR1)
string(SUBSTRING "${PROGRAM_NAME}" "${INDEX1}" "1" MODEL_CHAR2)
string(SUBSTRING "${PROGRAM_NAME}" "${INDEX2}" "1" MODEL_CHAR3)
if ("${MODEL_CHAR1}" MATCHES "_")
string(TOUPPER ${MODEL_CHAR2} MODEL_CHAR2)
string(APPEND GOPROGRAM_NAME ${MODEL_CHAR2})
set(INDEX0 ${INDEX1})
elseif ("${MODEL_CHAR3}" MATCHES "_")
continue()
else()
string(APPEND GOPROGRAM_NAME ${MODEL_CHAR1})
endif()
endforeach()
endif()
# Now configure the files.
configure_file("${GO_IN}" "${GO_OUT}")
+4
View File
@@ -2,6 +2,10 @@
###### ????-??-??
* Added N-step DQN to q_networks (#2461).
* Add Silhoutte Score metric and Pairwise Distances (#2406).
* Add Go bindings for some missed models (#2460).
### mlpack 3.3.2
###### 2020-06-18
* Added Noisy DQN to q_networks (#2446).
+2 -2
View File
@@ -41,7 +41,7 @@ You can copy-paste this code directly into main.go to run it.
package main
import (
"github.com/mlpack.org/v1/mlpack"
"mlpack.org/v1/mlpack"
"fmt"
)
func main() {
@@ -134,7 +134,7 @@ package main
import (
"github.com/frictionlessdata/tableschema-go/csv"
"github.com/mlpack.org/v1/mlpack"
"mlpack.org/v1/mlpack"
"gonum.org/v1/gonum/mat"
"fmt"
)
+2 -2
View File
@@ -37,7 +37,7 @@ print the accuracy of the random forest on the test dataset.
You can copy-paste this code directly into Julia to run it. You may need to add
some extra packages with, e.g., `using Pkg; Pkg.add("CSV");
Pkg.add("DataFrames"); Pkg.add("Zlib")`.
Pkg.add("DataFrames"); Pkg.add("Libz")`.
@code{.julia}
using CSV
@@ -56,7 +56,7 @@ dataset = select!(df, Not(:label))
# Split the dataset using mlpack.
test, test_labels, train, train_labels = mlpack.preprocess_split(
input=dataset,
dataset,
input_labels=labels,
test_ratio=0.3)
+23
View File
@@ -156,6 +156,29 @@ if (BUILD_JULIA_BINDINGS)
"\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 Markdown documentation, we have to run some setup after we
# recurse into methods/. If not, this function is empty.
post_markdown_setup()
+87 -97
View File
@@ -24,6 +24,7 @@ if (BUILD_GO_BINDINGS)
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!")
endif()
else ()
@@ -31,6 +32,7 @@ if (BUILD_GO_BINDINGS)
find_package(Gonum)
if (NOT GO_FOUND OR NOT GONUM_FOUND)
unset(BUILD_GO_BINDINGS CACHE)
set(BUILD_GO_SHLIB OFF)
endif()
endif ()
@@ -43,6 +45,16 @@ if (BUILD_GO_BINDINGS)
endif ()
add_custom_target(go)
# All the bindings will build under "src/mlpack.org/v1/mlpack"; So if user build
# go-bindings from source, then he/she can use the same import path as documented
# on "mlpack.org" by setting GOPATH=/path/to/mlpack/build/src/mlpack/bindings/go.
# Create model.go with package definition.
file(WRITE
"${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/src/mlpack.org/v1/mlpack/models.go"
"package mlpack"
"\n\n"
"/*\n")
endif()
if (BUILD_GO_SHLIB)
@@ -58,8 +70,6 @@ if (BUILD_GO_SHLIB)
mlpack/cli_util.h
mlpack/cli_util.hpp
print_class_defn.hpp
print_cpp.cpp
print_cpp.hpp
print_defn_input.hpp
print_defn_output.hpp
print_doc.hpp
@@ -67,9 +77,6 @@ if (BUILD_GO_SHLIB)
print_doc_functions_impl.hpp
print_go.hpp
print_go.cpp
print_h.hpp
print_h.cpp
print_import_decl.hpp
print_input_processing.hpp
print_method_config.hpp
print_method_init.hpp
@@ -85,24 +92,15 @@ if (BUILD_GO_SHLIB)
mlpack/cli_util.go
mlpack/doc.go
mlpack/numcsv.go
mlpack/go.mod
mlpack/go.sum
)
# These are all the files we need to compile Go bindings for mlpack that are
# not a part of mlpack itself.
set(CAPI_SOURCES
mlpack/capi/arma_util.cpp
mlpack/capi/arma_util.h
mlpack/capi/arma_util.hpp
mlpack/capi/cli_util.cpp
mlpack/capi/cli_util.h
mlpack/capi/cli_util.hpp
)
# These are all the files we need to compile Go bindings for mlpack that are
# not a part of mlpack itself.
set(UTIL_SOURCES
mlpack/capi/arma_util.cpp
mlpack/capi/cli_util.cpp
)
set(TEST_SOURCES
@@ -111,47 +109,50 @@ if (BUILD_GO_SHLIB)
add_custom_target(go_shlib ALL DEPENDS mlpack)
add_custom_target(go_copy ALL DEPENDS mlpack)
if (BUILD_TESTS OR BUILD_GO_SHLIB)
foreach(test_file ${TEST_SOURCES})
add_custom_command(TARGET go_copy PRE_BUILD
COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different
${CMAKE_CURRENT_SOURCE_DIR}/${test_file}
${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/tests/)
endforeach ()
endif ()
# Copy necessary files after making the mlpack/ directory.
add_custom_command(TARGET go_copy PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory
${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/mlpack/
${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/src/mlpack.org/v1/mlpack/
COMMAND ${CMAKE_COMMAND} -E make_directory
${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/mlpack/capi/)
${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/src/mlpack.org/v1/mlpack/capi/
COMMAND ${CMAKE_COMMAND} -E make_directory
${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/src/mlpack.org/v1/mlpack/tests/)
foreach(go_file ${CAPI_SOURCES})
add_custom_command(TARGET go_copy PRE_BUILD
COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different
${CMAKE_CURRENT_SOURCE_DIR}/${go_file}
${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/mlpack/capi/)
${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/src/mlpack.org/v1/mlpack/capi/)
endforeach()
add_custom_command(TARGET go_copy PRE_BUILD
COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different
$<TARGET_FILE:mlpack>
${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/mlpack/)
${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/src/mlpack.org/v1/mlpack/)
foreach(cgo_file ${CGO_SOURCES})
add_custom_command(TARGET go_copy PRE_BUILD
COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different
${CMAKE_CURRENT_SOURCE_DIR}/${cgo_file}
${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/mlpack/)
${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/src/mlpack.org/v1/mlpack/)
endforeach()
if (BUILD_TESTS OR BUILD_GO_SHLIB)
foreach(test_file ${TEST_SOURCES})
add_custom_command(TARGET go_copy PRE_BUILD
COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different
${CMAKE_CURRENT_SOURCE_DIR}/${test_file}
${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/src/mlpack.org/v1/mlpack/tests/)
endforeach ()
endif ()
add_library(go_util SHARED
${CMAKE_SOURCE_DIR}/src/mlpack/bindings/go/mlpack/capi/arma_util.cpp
${CMAKE_SOURCE_DIR}/src/mlpack/bindings/go/mlpack/capi/cli_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
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/mlpack/)
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/src/mlpack.org/v1/mlpack/)
# Set the include directories correctly.
get_property(GO_INCLUDE_DIRECTORIES DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
@@ -164,47 +165,55 @@ if (BUILD_GO_SHLIB)
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}")
endif()
# Define a global list of models.
define_property(GLOBAL PROPERTY GO_MODELS
BRIEF_DOCS "Global list of models"
FULL_DOCS "Global list of models"
)
# Initialize list.
set_property(GLOBAL PROPERTY GO_MODELS "")
# Add a macro to build a go binding.
macro (add_go_binding name)
if (BUILD_GO_BINDINGS)
# Append sources (with directory name) to list of all mlpack sources (used at
# the parent scope).
set(MLPACK_SRCS ${MLPACK_SRCS} ${DIR_SRCS} PARENT_SCOPE)
# Create .h file for C API, e.g. pca.h.
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/generate_h_${name}.cpp
COMMAND ${CMAKE_COMMAND}
-DGENERATE_BINDING_IN=${CMAKE_SOURCE_DIR}/src/mlpack/bindings/go/generate_h.cpp.in
-DGENERATE_BINDING_OUT=${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/generate_h_${name}.cpp
-DPROGRAM_MAIN_FILE=${CMAKE_CURRENT_SOURCE_DIR}/${name}_main.cpp
-DPROGRAM_NAME=${name}
-P ${CMAKE_SOURCE_DIR}/CMake/ConfigureGoHCPP.cmake
DEPENDS ${CMAKE_SOURCE_DIR}/src/mlpack/bindings/go/generate_h.cpp.in)
# 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
"${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/src/mlpack.org/v1/mlpack/models.go"
"#include <capi/${name}.h>\n")
endif()
add_executable(generate_h_${name}
${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/generate_h_${name}.cpp
${CMAKE_SOURCE_DIR}/src/mlpack/bindings/go/print_h.hpp
${CMAKE_SOURCE_DIR}/src/mlpack/bindings/go/print_h.cpp)
target_link_libraries(generate_h_${name} mlpack ${MLPACK_LIBRARIES})
set_target_properties(generate_h_${name} PROPERTIES COMPILE_FLAGS
-DBINDING_TYPE=BINDING_TYPE_GO)
add_custom_command(TARGET generate_h_${name} POST_BUILD
# Append content to the list.
set_property(GLOBAL APPEND PROPERTY GO_MODELS ${CMAKE_CURRENT_SOURCE_DIR}/${name}_main.cpp)
# Create ${name}.h.
add_custom_command(OUTPUT
${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/src/mlpack.org/v1/mlpack/capi/${name}.h
COMMAND ${CMAKE_COMMAND}
-DGENERATE_BINDING_PROGRAM=${CMAKE_BINARY_DIR}/bin/generate_h_${name}
-DBINDING_OUTPUT_FILE=${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/mlpack/capi/${name}.h
-P ${CMAKE_SOURCE_DIR}/CMake/GenerateGoBinding.cmake)
-DPROGRAM_NAME=${name}
-DPROGRAM_MAIN_FILE=${CMAKE_CURRENT_SOURCE_DIR}/${name}_main.cpp
-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
DEPENDS ${CMAKE_SOURCE_DIR}/src/mlpack/bindings/go/go_method.h.in
${CMAKE_SOURCE_DIR}/CMake/go/ConfigureGoHCPP.cmake)
# Create .go file, pca.go.
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/generate_go_${name}.cpp
COMMAND ${CMAKE_COMMAND}
-DGENERATE_BINDING_IN=${CMAKE_SOURCE_DIR}/src/mlpack/bindings/go/generate_go.cpp.in
-DGENERATE_BINDING_OUT=${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/generate_go_${name}.cpp
-DGENERATE_CPP_IN=${CMAKE_SOURCE_DIR}/src/mlpack/bindings/go/generate_go.cpp.in
-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/ConfigureGoHCPP.cmake
DEPENDS ${CMAKE_SOURCE_DIR}/src/mlpack/bindings/go/generate_go.cpp.in)
-P ${CMAKE_SOURCE_DIR}/CMake/ConfigureGenerate.cmake
DEPENDS ${CMAKE_SOURCE_DIR}/src/mlpack/bindings/go/generate_go.cpp.in
${CMAKE_SOURCE_DIR}/CMake/ConfigureGenerate.cmake)
add_executable(generate_go_${name}
${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/src/mlpack.org/v1/mlpack/capi/${name}.h
${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/generate_go_${name}.cpp
${CMAKE_SOURCE_DIR}/src/mlpack/bindings/go/print_go.hpp
${CMAKE_SOURCE_DIR}/src/mlpack/bindings/go/print_go.cpp)
@@ -214,63 +223,44 @@ if (BUILD_GO_BINDINGS)
add_custom_command(TARGET generate_go_${name} POST_BUILD
COMMAND ${CMAKE_COMMAND}
-DGENERATE_BINDING_PROGRAM=${CMAKE_BINARY_DIR}/bin/generate_go_${name}
-DBINDING_OUTPUT_FILE=${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/mlpack/${name}.go
-DBINDING_OUTPUT_FILE=${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/src/mlpack.org/v1/mlpack/${name}.go
-P ${CMAKE_SOURCE_DIR}/CMake/GenerateGoBinding.cmake)
add_dependencies(generate_h_${name} generate_go_${name})
add_dependencies(go generate_h_${name})
add_dependencies(go generate_go_${name})
endif ()
if(BUILD_GO_SHLIB)
# Append sources (with directory name) to list of all mlpack sources (used at
# the parent scope).
set(MLPACK_SRCS ${MLPACK_SRCS} ${DIR_SRCS} PARENT_SCOPE)
# Create .cpp file for C API, e.g. pca.cpp.
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/generate_cpp_${name}.cpp
COMMAND ${CMAKE_COMMAND}
-DGENERATE_BINDING_IN=${CMAKE_SOURCE_DIR}/src/mlpack/bindings/go/generate_cpp.cpp.in
-DGENERATE_BINDING_OUT=${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/generate_cpp_${name}.cpp
-DPROGRAM_MAIN_FILE=${CMAKE_CURRENT_SOURCE_DIR}/${name}_main.cpp
-DPROGRAM_NAME=${name}
-P ${CMAKE_SOURCE_DIR}/CMake/ConfigureGoHCPP.cmake
DEPENDS ${CMAKE_SOURCE_DIR}/src/mlpack/bindings/go/generate_cpp.cpp.in)
add_executable(generate_cpp_${name}
${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/generate_cpp_${name}.cpp
${CMAKE_SOURCE_DIR}/src/mlpack/bindings/go/print_cpp.hpp
${CMAKE_SOURCE_DIR}/src/mlpack/bindings/go/print_cpp.cpp)
target_link_libraries(generate_cpp_${name} mlpack ${MLPACK_LIBRARIES})
set_target_properties(generate_cpp_${name} PROPERTIES COMPILE_FLAGS
-DBINDING_TYPE=BINDING_TYPE_GO)
add_custom_command(TARGET generate_cpp_${name} POST_BUILD
# Create ${name}.cpp.
add_custom_command(OUTPUT
${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/build/${name}.cpp
COMMAND ${CMAKE_COMMAND}
-DGENERATE_BINDING_PROGRAM=${CMAKE_BINARY_DIR}/bin/generate_cpp_${name}
-DBINDING_OUTPUT_FILE=${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/mlpack/capi/${name}.cpp
-P ${CMAKE_SOURCE_DIR}/CMake/GenerateGoBinding.cmake)
-DPROGRAM_NAME=${name}
-DPROGRAM_MAIN_FILE=${CMAKE_CURRENT_SOURCE_DIR}/${name}_main.cpp
-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
DEPENDS ${CMAKE_SOURCE_DIR}/src/mlpack/bindings/go/go_method.cpp.in
${CMAKE_SOURCE_DIR}/CMake/go/ConfigureGoHCPP.cmake)
add_dependencies(generate_cpp_${name} go_copy)
# Create, e.g., libmlpack_go_pca.so.
# Build libmlpack_go_${name}.so.
add_library(mlpack_go_${name} SHARED
${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/mlpack/capi/${name}.cpp)
set_source_files_properties(${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/mlpack/capi/${name}.cpp
PROPERTIES GENERATED TRUE)
target_link_libraries(mlpack_go_${name} mlpack ${MLPACK_LIBRARIES})
target_compile_definitions(mlpack_go_${name} PUBLIC "BINDING_TYPE=BINDING_TYPE_GO")
${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/build/${name}.cpp)
target_link_libraries(mlpack_go_${name} mlpack go_util)
set_target_properties(mlpack_go_${name} PROPERTIES
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/mlpack/)
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/src/mlpack.org/v1/mlpack/")
install(TARGETS mlpack_go_${name}
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}")
add_dependencies(mlpack_go_${name} generate_cpp_${name})
add_dependencies(mlpack_go_${name} go_copy)
add_dependencies(mlpack_go_${name} go_util)
add_dependencies(go_shlib mlpack_go_${name})
if (BUILD_GO_BINDINGS)
add_dependencies(mlpack_go_${name} generate_h_${name})
add_dependencies(mlpack_go_${name} generate_go_${name})
add_dependencies(go mlpack_go_${name})
endif()
endif()
@@ -1,49 +0,0 @@
/*
* @file bindings/go/generate_cpp_${PROGRAM_NAME}.cpp
* @author Yasmine Dumouchel
*
* This is an automatically-generated file that is used to generate the .cpp
* files that are used for the Go bindings. This program will print the
* .cpp file on stdout when run and doesn't need any input parameters.
*
* The CMake variable ${PROGRAM_NAME} must be set for
* this to configure correctly.
*
* 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.
*/
#define BINDING_TYPE BINDING_TYPE_GO
// 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/go/print_cpp.hpp>
// This will include the ParamData options that are a part of the program.
#include <${PROGRAM_MAIN_FILE}>
using namespace mlpack;
using namespace mlpack::bindings;
using namespace mlpack::bindings::go;
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.
CLI::RestoreSettings(programName);
PrintCPP(*CLI::GetSingleton().doc, "${PROGRAM_MAIN_FILE}", "${PROGRAM_NAME}");
}
-49
View File
@@ -1,49 +0,0 @@
/*
* @file bindings/go/generate_h_${PROGRAM_NAME}.cpp
* @author Yasmine Dumouchel
*
* This is an automatically-generated file that is used to generate the .h
* files that are used for the Go bindings. This program will print the
* .h file on stdout when run and doesn't need any input parameters.
*
* The CMake variable ${PROGRAM_NAME} must be set for
* this to configure correctly.
*
* 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.
*/
#define BINDING_TYPE BINDING_TYPE_GO
// 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/go/print_h.hpp>
// This will include the ParamData options that are a part of the program.
#include <${PROGRAM_MAIN_FILE}>
using namespace mlpack;
using namespace mlpack::bindings;
using namespace mlpack::bindings::go;
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.
CLI::RestoreSettings(programName);
PrintH(*CLI::GetSingleton().doc, "${PROGRAM_NAME}");
}
View File
View File
+24
View File
@@ -0,0 +1,24 @@
/**
* @file build/${PROGRAM_NAME}.cpp
*
* This is an autogenerated file containing implementations of C functions to be
* called by the Go ${PROGRAM_NAME} binding.
*/
#define BINDING_TYPE BINDING_TYPE_GO
#include <${PROGRAM_MAIN_FILE}>
#include <mlpack/bindings/go/mlpack/capi/cli_util.hpp>
static void ${GOPROGRAM_NAME}MlpackMain()
{
mlpackMain();
}
extern "C" void mlpack${GOPROGRAM_NAME}()
{
${GOPROGRAM_NAME}MlpackMain();
}
// Any implementations of methods for dealing with model pointers will be put
// below this comment, if needed.
${MODEL_PTR_IMPLS}
+28
View File
@@ -0,0 +1,28 @@
/**
* @file capi/${PROGRAM_NAME}.h
*
* This is an autogenerated header file for functions specified to the %NAME%
* binding to be called by Go.
*/
#ifndef GO_${PROGRAM_NAME}_H
#define GO_${PROGRAM_NAME}_H
#include <stddef.h>
#if defined(__cplusplus) || defined(c_plusplus)
extern "C"
{
#endif
extern void mlpack${GOPROGRAM_NAME}();
// Any definitions of methods for dealing with model pointers will be put below
// this comment, if needed.
${MODEL_PTR_DEFNS}
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif
#endif
-11
View File
@@ -20,11 +20,9 @@
#include "print_defn_input.hpp"
#include "print_defn_output.hpp"
#include "print_doc.hpp"
#include "print_import_decl.hpp"
#include "print_input_processing.hpp"
#include "print_method_config.hpp"
#include "print_method_init.hpp"
#include "print_model_util.hpp"
#include "print_output_processing.hpp"
namespace mlpack {
@@ -103,13 +101,6 @@ class GoOption
CLI::GetSingleton().functionMap[data.tname]["DefaultParam"] =
&DefaultParam<T>;
CLI::GetSingleton().functionMap[data.tname]["PrintModelUtilCPP"] =
&PrintModelUtilCPP<T>;
CLI::GetSingleton().functionMap[data.tname]["PrintModelUtilH"] =
&PrintModelUtilH<T>;
CLI::GetSingleton().functionMap[data.tname]["PrintModelUtilGo"] =
&PrintModelUtilGo<T>;
CLI::GetSingleton().functionMap[data.tname]["PrintDefnInput"] =
&PrintDefnInput<T>;
CLI::GetSingleton().functionMap[data.tname]["PrintDefnOutput"] =
@@ -121,8 +112,6 @@ class GoOption
&PrintMethodConfig<T>;
CLI::GetSingleton().functionMap[data.tname]["PrintMethodInit"] =
&PrintMethodInit<T>;
CLI::GetSingleton().functionMap[data.tname]["ImportDecl"] =
&ImportDecl<T>;
CLI::GetSingleton().functionMap[data.tname]["PrintInputProcessing"] =
&PrintInputProcessing<T>;
CLI::GetSingleton().functionMap[data.tname]["GetType"] = &GetType<T>;
+1 -1
View File
@@ -7,4 +7,4 @@ programs, Go bindings, and C++ classes which can then be integrated into
larger-scale machine learning solutions.
*/
package mlpack
package mlpack // import "mlpack.org/v1/mlpack"
+5
View File
@@ -0,0 +1,5 @@
module mlpack.org/v1/mlpack
go 1.13
require gonum.org/v1/gonum v0.7.0
+18
View File
@@ -0,0 +1,18 @@
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2 h1:y102fOLFqhV41b+4GPiJoa0k/x+pJcEi2/HB1Y5T6fU=
golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
gonum.org/v1/gonum v0.7.0 h1:Hdks0L0hgznZLG9nzXb8vZ0rRvqNvAcgAp84y7Mwkgw=
gonum.org/v1/gonum v0.7.0/go.mod h1:L02bwd0sqlsvRv41G7wGWFCsVNZFv/k1xzGIxeANHGM=
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0 h1:OE9mWmgKkjJyEmDAAtGMPjXu+YNeGvK9VTSHY6+Qihc=
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
-74
View File
@@ -1,74 +0,0 @@
/**
* @file bindings/go/print_cpp.cpp
* @author Yasmine Dumouchel
*
* Implementation of function to generate a .cpp file given a list of parameters
* for the 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_cpp.hpp"
#include "camel_case.hpp"
#include <mlpack/core/util/cli.hpp>
#include <mlpack/core/util/hyphenate_string.hpp>
#include <set>
using namespace mlpack::util;
using namespace std;
namespace mlpack {
namespace bindings {
namespace go {
/**
* Given a list of parameter definition and program documentation, print a
* generated .cpp file to stdout.
*/
void PrintCPP(const ProgramDoc& programInfo,
const string& mainFilename,
const string& functionName)
{
// Restore parameters.
CLI::RestoreSettings(programInfo.programName);
const std::map<std::string, util::ParamData>& parameters = CLI::Parameters();
typedef std::map<std::string, util::ParamData>::const_iterator ParamIter;
// First, we must generate the header comment and namespace.
cout << "#include <" << mainFilename << ">" << endl;
cout << "#include <mlpack/bindings/go/mlpack/capi/cli_util.hpp>" << endl;
cout << endl;
cout << "using namespace mlpack;" << endl;
cout << "using namespace mlpack::util;" << endl;
cout << "using namespace std;" << endl;
cout << endl;
// Then we must print utility function for model type parameters if needed.
for (ParamIter it = parameters.begin(); it != parameters.end(); ++it)
{
const util::ParamData& d = it->second;
if (d.input)
CLI::GetSingleton().functionMap[d.tname]["PrintModelUtilCPP"](d,
NULL, NULL);
}
// Finally, we generate the wrapper function for mlpackMain().
std::string goFunctionName = CamelCase(functionName, false);
cout << "static void " << goFunctionName << "MlpackMain()" << endl;
cout << "{" << endl;
cout << " " << "mlpackMain();" << endl;
cout << "}" << endl;
cout << endl;
cout << "extern \"C\" void mlpack" << goFunctionName << "()" << endl;
cout << "{" << endl;
cout << " " << goFunctionName << "MlpackMain();" << endl;
cout << "}" << endl;
cout << endl;
}
} // namespace go
} // namespace bindings
} // namespace mlpack
-35
View File
@@ -1,35 +0,0 @@
/**
* @file bindings/go/print_cpp.hpp
* @author Yasmine Dumouchel
*
* Given a list of ParamData structures, emit a .cpp file defining the
* Go 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_GO_PRINT_CPP_HPP
#define MLPACK_BINDINGS_GO_PRINT_CPP_HPP
#include <mlpack/core.hpp>
namespace mlpack {
namespace bindings {
namespace go {
/**
* Given a list of parameter definition and program documentation, print a
* generated .cpp file to stdout.
*/
void PrintCPP(const util::ProgramDoc& programInfo,
const std::string& mainFilename,
const std::string& functionName);
} // namespace go
} // namespace bindings
} // namespace mlpack
#endif
+7 -17
View File
@@ -81,16 +81,15 @@ void PrintGo(const util::ProgramDoc& programInfo,
cout << endl;
// Then we must print the import of the gonum package.
cout << "import (" << endl;
cout << " " << "\"gonum.org/v1/gonum/mat\" " << endl;
for (size_t i = 0; i < inputOptions.size(); ++i)
for (ParamIter it = parameters.begin(); it != parameters.end(); ++it)
{
const util::ParamData& d = parameters.at(inputOptions[i]);
size_t indent = 2;
CLI::GetSingleton().functionMap[d.tname]["ImportDecl"](d,
(void*) &indent, NULL);
const util::ParamData& d = it->second;
if ((d.cppType).compare(0, 6, "arma::") == 0)
{
std::cout << "import \"gonum.org/v1/gonum/mat\" " << std::endl;
break;
}
}
cout << ")" << endl;
cout << endl;
std::string goFunctionName = CamelCase(functionName, false);
@@ -123,15 +122,6 @@ void PrintGo(const util::ProgramDoc& programInfo,
cout << "}" << endl;
cout << endl;
// Then we must print utility function for model type parameters if needed.
for (ParamIter it = parameters.begin(); it != parameters.end(); ++it)
{
const util::ParamData& d = it->second;
if (d.input)
CLI::GetSingleton().functionMap[d.tname]["PrintModelUtilGo"](d,
NULL, NULL);
}
// Print the comment describing the function and its parameters.
cout << "/*" << endl;
cout << " " << HyphenateString(programInfo.documentation(), 2) << endl;
-73
View File
@@ -1,73 +0,0 @@
/**
* @file bindings/go/print_h.cpp
* @author Yasmine Dumouchel
*
* Implementation of function to generate a .h file given a list of parameters
* for the 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_h.hpp"
#include "camel_case.hpp"
#include <mlpack/core/util/cli.hpp>
#include <mlpack/core/util/hyphenate_string.hpp>
#include <set>
using namespace mlpack::util;
using namespace std;
namespace mlpack {
namespace bindings {
namespace go {
/**
* Given a list of parameter definition and program documentation, print a
* generated .h file to stdout.
*
* @param programInfo Documentation for the program.
* @param functionName Name of the function (i.e. "pca").
*/
void PrintH(const util::ProgramDoc& programInfo,
const std::string& functionName)
{
// Restore parameters.
CLI::RestoreSettings(programInfo.programName);
const std::map<std::string, util::ParamData>& parameters = CLI::Parameters();
typedef std::map<std::string, util::ParamData>::const_iterator ParamIter;
// First, we must generate the header comment and namespace.
cout << "#include <stdint.h>" << endl;
cout << "#include <stddef.h>" << endl;
cout << endl;
cout << "#if defined(__cplusplus) || defined(c_plusplus)" << endl;
cout << "extern \"C\" {" << endl;
cout << "#endif" << endl;
cout << endl;
// Then we must print utility function for model type parameters if needed.
for (ParamIter it = parameters.begin(); it != parameters.end(); ++it)
{
const util::ParamData& d = it->second;
if (d.input)
CLI::GetSingleton().functionMap[d.tname]["PrintModelUtilH"](d,
NULL, NULL);
}
std::string goFunctionName = CamelCase(functionName, false);
// We generate the wrapper function for mlpackMain().
cout << "extern void mlpack" << goFunctionName << "();" << endl;
cout << endl;
// Finally we close print the closing bracket for extern C.
cout << "#if defined(__cplusplus) || defined(c_plusplus)" << endl;
cout << "}" << endl;
cout << "#endif" << endl;
}
} // namespace go
} // namespace bindings
} // namespace mlpack
-37
View File
@@ -1,37 +0,0 @@
/**
* @file bindings/go/print_h.hpp
* @author Yasmine Dumouchel
*
* Given a list of ParamData structures, emit a .h file defining the
* Go 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_GO_PRINT_H_HPP
#define MLPACK_BINDINGS_GO_PRINT_H_HPP
#include <mlpack/core.hpp>
namespace mlpack {
namespace bindings {
namespace go {
/**
* Given a list of parameter definition and program documentation, print a
* generated .h file to stdout.
*
* @param programInfo Documentation for the program.
* @param functionName Name of the function (i.e. "pca").
*/
void PrintH(const util::ProgramDoc& programInfo,
const std::string& functionName);
} // namespace go
} // namespace bindings
} // namespace mlpack
#endif
@@ -1,85 +0,0 @@
/**
* @file bindings/go/print_import_decl.hpp
* @author Yasmine Dumouchel
*
* Print the necessary imports for go 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_GO_IMPORT_DECL_HPP
#define MLPACK_BINDINGS_GO_IMPORT_DECL_HPP
#include <mlpack/prereqs.hpp>
namespace mlpack {
namespace bindings {
namespace go {
/**
* For a serializable type, print a cppclass definition.
*/
template<typename T>
void ImportDecl(
const util::ParamData& /* d */,
const size_t indent,
const typename boost::disable_if<arma::is_arma_type<T>>::type* = 0,
const typename boost::enable_if<data::HasSerialize<T>>::type* = 0)
{
/**
* This will give output of the form:
*/
const std::string prefix = std::string(indent, ' ');
// Now import all the necessary packages.
std::cout << prefix << "\"runtime\" " << std::endl;
std::cout << prefix << "\"unsafe\" " << std::endl;
}
/**
* For a non-serializable type, print nothing.
*/
template<typename T>
void ImportDecl(
const util::ParamData& /* d */,
const size_t /* indent */,
const typename boost::disable_if<arma::is_arma_type<T>>::type* = 0,
const typename boost::disable_if<data::HasSerialize<T>>::type* = 0)
{
// Print nothing.
}
/**
* For a matrix type, print nothing.
*/
template<typename T>
void ImportDecl(
const util::ParamData& /* d */,
const size_t /* indent */,
const typename boost::enable_if<arma::is_arma_type<T>>::type* = 0)
{
// Print nothing.
}
/**
* Print the cppclass definition for a serializable model; print nothing for a
* non-serializable type.
*
* @param d Parameter info struct.
* @param indent Pointer to size_t indicating indent.
* @param * (output) Unused parameter.
*/
template<typename T>
void ImportDecl(const util::ParamData& d,
const void* indent,
void* /* output */)
{
ImportDecl<typename std::remove_pointer<T>::type>(d, *((size_t*) indent));
}
} // namespace go
} // namespace bindings
} // namespace mlpack
#endif
@@ -296,8 +296,8 @@ void PrintInputProcessing(
{
goParamName = CamelCase(goParamName, true);
// Print function call to set the given parameter into the cli.
std::cout << prefix << "set" << strippedType << "(\"" << goParamName
<< "\", " << paramName << ")" << std::endl;
std::cout << prefix << "set" << strippedType << "(\"" << d.name
<< "\", " << goParamName << ")" << std::endl;
// Print function call to set the given parameter as passed.
std::cout << prefix << "setPassed(\"" << d.name << "\")" << std::endl;
-349
View File
@@ -1,349 +0,0 @@
/**
* @file bindings/go/print_model_util.hpp
* @author Yasmine Dumouchel
*
* Print the functions and structs associated with serializable model.
* for generating the .cpp, .h, and .go 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_GO_PRINT_CLASS_DEFN_HPP
#define MLPACK_BINDINGS_GO_PRINT_CLASS_DEFN_HPP
#include "strip_type.hpp"
namespace mlpack {
namespace bindings {
namespace go {
/**
* Non-serializable models don't require any special definitions, so this prints
* nothing.
*/
template<typename T>
void PrintModelUtilCPP(
const 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)
{
// Do nothing.
}
/**
* Matrices don't require any special definitions, so this prints nothing.
*/
template<typename T>
void PrintModelUtilCPP(
const util::ParamData& /* d */,
const typename boost::enable_if<arma::is_arma_type<T>>::type* = 0)
{
// Do nothing.
}
/**
* Matrices with Info don't require any special definitions, so this prints nothing.
*/
template<typename T>
void PrintModelUtilCPP(
const util::ParamData& /* d */,
const typename boost::enable_if<std::is_same<T,
std::tuple<data::DatasetInfo, arma::mat>>>::type* = 0)
{
// Do nothing.
}
/**
* Serializable models require a special class definition.
*/
template<typename T>
void PrintModelUtilCPP(
const 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)
{
// First, we have to parse the type. If we have something like, e.g.,
// 'LogisticRegression<>', we must convert this to 'LogisticRegression[].'
std::string goStrippedType, strippedType, printedType, defaultsType;
StripType(d.cppType, goStrippedType, strippedType, printedType, defaultsType);
/**
* This gives us code like:
*
* extern "C" void mlpackSet\<Type\>Ptr(
* const char* identifier,
* void *value)
* {
* SetParamPtr\<Type\>(identifier,
* static_cast\<Type\>*(value));
* }
*
*/
std::cout << "extern \"C\" void mlpackSet" << strippedType
<< "Ptr(" << std::endl;
std::cout << " const char* identifier, " << std::endl;
std::cout << " void* value)" << std::endl;
std::cout << "{" << std::endl;
std::cout << " SetParamPtr<" << printedType
<< ">(identifier," << std::endl;
std::cout << " static_cast<" << printedType
<< "*>(value));" << std::endl;
std::cout << "}" << std::endl;
std::cout << std::endl;
/**
* This gives us code like:
*
* extern "C" void *mlpackGet\<Type\>Ptr(const char* identifier)
* {
* \<Type\> *modelptr = GetParamPtr\<Type\>(identifier);
* return modelptr;
* }
*
*/
std::cout << "extern \"C\" void *mlpackGet" << strippedType
<< "Ptr(const char* identifier)" << std::endl;
std::cout << "{" << std::endl;
std::cout << " " << printedType << " *modelptr = GetParamPtr<"
<< printedType << ">(identifier);" << std::endl;
std::cout << " return modelptr;" << std::endl;
std::cout << "}" << std::endl;
std::cout << std::endl;
}
/**
* Print the function to set and get serialization models from Go to mlpack.
*
* @param d Parameter data.
* @param * (input) Unused parameter.
* @param * (output) Unused parameter.
*/
template<typename T>
void PrintModelUtilCPP(const util::ParamData& d,
const void* /* input */,
void* /* output */)
{
PrintModelUtilCPP<typename std::remove_pointer<T>::type>(d);
}
/**
* Non-serializable models don't require any special definitions, so this prints
* nothing.
*/
template<typename T>
void PrintModelUtilH(
const 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)
{
// Do nothing.
}
/**
* Matrices don't require any special definitions, so this prints nothing.
*/
template<typename T>
void PrintModelUtilH(
const util::ParamData& /* d */,
const typename boost::enable_if<arma::is_arma_type<T>>::type* = 0)
{
// Do nothing.
}
/**
* Matrices with Info don't require any special definitions, so this prints nothing.
*/
template<typename T>
void PrintModelUtilH(
const util::ParamData& /* d */,
const typename boost::enable_if<std::is_same<T,
std::tuple<data::DatasetInfo, arma::mat>>>::type* = 0)
{
// Do nothing.
}
/**
* Serializable models require a special class definition.
*/
template<typename T>
void PrintModelUtilH(
const 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)
{
// First, we have to parse the type. If we have something like, e.g.,
// 'LogisticRegression<>', we must convert this to 'LogisticRegression[].'
std::string goStrippedType, strippedType, printedType, defaultsType;
StripType(d.cppType, goStrippedType, strippedType, printedType, defaultsType);
/**
* This gives us code like:
*
* extern void *mlpackSet\<Type\>Ptr(const char* identifier, void* value);
*
*/
std::cout << "extern void mlpackSet" << strippedType
<< "Ptr(const char* identifier, void* value);" << std::endl;
std::cout << std::endl;
/**
* This gives us code like:
*
* extern void *mlpackGet\<Type\>Ptr(const char* identifier);
*
*/
std::cout << "extern void *mlpackGet" << strippedType
<< "Ptr(const char* identifier);" << std::endl;
std::cout << std::endl;
}
/**
* Print the function to set and get serialization models from Go to mlpack.
*
* @param d Parameter data.
* @param * (input) Unused parameter.
* @param * (output) Unused parameter.
*/
template<typename T>
void PrintModelUtilH(const util::ParamData& d,
const void* /* input */,
void* /* output */)
{
PrintModelUtilH<typename std::remove_pointer<T>::type>(d);
}
/**
* Non-serializable models don't require any special definitions, so this prints
* nothing.
*/
template<typename T>
void PrintModelUtilGo(
const 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)
{
// Do nothing.
}
/**
* Matrices don't require any special definitions, so this prints nothing.
*/
template<typename T>
void PrintModelUtilGo(
const util::ParamData& /* d */,
const typename boost::enable_if<arma::is_arma_type<T>>::type* = 0)
{
// Do nothing.
}
/**
* Matrices with Info don't require any special definitions, so this prints nothing.
*/
template<typename T>
void PrintModelUtilGo(
const util::ParamData& /* d */,
const typename boost::enable_if<std::is_same<T,
std::tuple<data::DatasetInfo, arma::mat>>>::type* = 0)
{
// Do nothing.
}
/**
* Serializable models require a special class definition.
*/
template<typename T>
void PrintModelUtilGo(
const 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)
{
// First, we have to parse the type. If we have something like, e.g.,
// 'LogisticRegression<>', we must convert this to 'LogisticRegression[].'
std::string goStrippedType, strippedType, printedType, defaultsType;
StripType(d.cppType, goStrippedType, strippedType, printedType, defaultsType);
/**
* This gives us code like:
*
* type \<Type\> struct {
* mem unsafe.Pointer
* }
*
*/
std::cout << "type " << goStrippedType << " struct {" << std::endl;
std::cout << " mem unsafe.Pointer" << std::endl;
std::cout << "}" << std::endl;
std::cout << std::endl;
/**
* This gives us code like:
*
* func (m *\<Type\>) alloc\<Type\>(identifier string) {
* m.mem = C.mlpackGet\<Type\>Ptr(C.CString(identifier))
* runtime.KeepAlive(m)
* }
*
*/
std::cout << "func (m *" << goStrippedType << ") alloc"
<< strippedType << "(identifier string) {" << std::endl;
std::cout << " m.mem = C.mlpackGet" << strippedType
<< "Ptr(C.CString(identifier))" << std::endl;
std::cout << " runtime.KeepAlive(m)" << std::endl;
std::cout << "}" << std::endl;
std::cout << std::endl;
/**
* This gives us code like:
*
* func (m *\<Type\>) get\<Type\>(identifier string) {
* m.alloc\<Type\>(identifier)
* }
*
*/
std::cout << "func (m *" << goStrippedType << ") get"
<< strippedType << "(identifier string) {" << std::endl;
std::cout << " m.alloc" << strippedType << "(identifier)" << std::endl;
std::cout << "}" << std::endl;
std::cout << std::endl;
// Print function to set specified mlpack parameter object ptr from Go.
std::cout << "func set" << strippedType
<< "(identifier string, ptr *" << goStrippedType << ") {"
<< std::endl;
std::cout << " C.mlpackSet" << strippedType
<< "Ptr(C.CString(identifier), (unsafe.Pointer)(ptr.mem))"
<< std::endl;
std::cout << "}" << std::endl;
std::cout << std::endl;
}
/**
* Print the Go struct for Go serialization model and their associated
* set and get methods.
*
* @param d Parameter data.
* @param * (input) Unused parameter.
* @param * (output) Unused parameter.
*/
template<typename T>
void PrintModelUtilGo(const util::ParamData& d,
const void* /* input */,
void* /* output */)
{
PrintModelUtilGo<typename std::remove_pointer<T>::type>(d);
}
} // namespace go
} // namespace bindings
} // namespace mlpack
#endif
+3 -2
View File
@@ -4,7 +4,8 @@ add_go_binding(test_go_binding)
if (BUILD_GO_BINDINGS)
add_test(NAME go_binding_test
COMMAND go test -v ${CMAKE_CURRENT_SOURCE_DIR}/go_binding_test.go
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/mlpack/)
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/src/mlpack.org/v1/mlpack/)
set_tests_properties(go_binding_test
PROPERTIES ENVIRONMENT "GOPATH=$ENV{GOPATH}:${CMAKE_BINARY_DIR};LD_LIBRARY_PATH=$ENV{LD_LIBRARY_PATH}:${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/mlpack/")
PROPERTIES ENVIRONMENT "GOPATH=$ENV{GOPATH}:${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/;
LD_LIBRARY_PATH=$ENV{LD_LIBRARY_PATH}:${CMAKE_BINARY_DIR}/src/mlpack/bindings/go/src/mlpack.org/v1/mlpack/")
endif()
@@ -1,7 +1,7 @@
package main
import (
"mlpack/bindings/go/mlpack"
"mlpack.org/v1/mlpack"
"testing"
"os"
+8 -8
View File
@@ -21,7 +21,7 @@ if (BUILD_JULIA_BINDINGS)
find_package(Julia 0.7.0)
if (NOT JULIA_FOUND)
unset(BUILD_JULIA_BINDINGS CACHE)
message(FATAL_ERROR "Could not Build Julia Bindings")
message(FATAL_ERROR "Julia not found; cannot build Julia bindings!")
endif()
else ()
find_package(Julia 0.7.0)
@@ -148,12 +148,12 @@ if (BUILD_JULIA_BINDINGS)
${CMAKE_BINARY_DIR}/src/mlpack/bindings/julia/mlpack/build/julia_${name}.h
${CMAKE_BINARY_DIR}/src/mlpack/bindings/julia/mlpack/build/julia_${name}.cpp
COMMAND ${CMAKE_COMMAND}
-DPROGRAM_NAME="${name}"
-DPROGRAM_MAIN_FILE="${CMAKE_CURRENT_SOURCE_DIR}/${name}_main.cpp"
-DJULIA_H_IN="${CMAKE_SOURCE_DIR}/src/mlpack/bindings/julia/julia_method.h.in"
-DJULIA_H_OUT="${CMAKE_BINARY_DIR}/src/mlpack/bindings/julia/mlpack/build/julia_${name}.h"
-DJULIA_CPP_IN="${CMAKE_SOURCE_DIR}/src/mlpack/bindings/julia/julia_method.cpp.in"
-DJULIA_CPP_OUT="${CMAKE_BINARY_DIR}/src/mlpack/bindings/julia/mlpack/build/julia_${name}.cpp"
-DPROGRAM_NAME=${name}
-DPROGRAM_MAIN_FILE=${CMAKE_CURRENT_SOURCE_DIR}/${name}_main.cpp
-DJULIA_H_IN=${CMAKE_SOURCE_DIR}/src/mlpack/bindings/julia/julia_method.h.in
-DJULIA_H_OUT=${CMAKE_BINARY_DIR}/src/mlpack/bindings/julia/mlpack/build/julia_${name}.h
-DJULIA_CPP_IN=${CMAKE_SOURCE_DIR}/src/mlpack/bindings/julia/julia_method.cpp.in
-DJULIA_CPP_OUT=${CMAKE_BINARY_DIR}/src/mlpack/bindings/julia/mlpack/build/julia_${name}.cpp
-P ${CMAKE_SOURCE_DIR}/CMake/julia/ConfigureJuliaHCPP.cmake
DEPENDS ${CMAKE_SOURCE_DIR}/src/mlpack/bindings/julia/julia_method.h.in
${CMAKE_SOURCE_DIR}/src/mlpack/bindings/julia/julia_method.cpp.in
@@ -218,7 +218,7 @@ if (BUILD_JULIA_BINDINGS)
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/src/mlpack/bindings/julia/mlpack/build/bin/")
add_custom_command(TARGET generate_jl_${name} POST_BUILD
COMMAND ${CMAKE_COMMAND}
-DGENERATE_BINDING_PROGRAM="${CMAKE_BINARY_DIR}/src/mlpack/bindings/julia/mlpack/build/bin/generate_jl_${name}"
-DGENERATE_BINDING_PROGRAM=${CMAKE_BINARY_DIR}/src/mlpack/bindings/julia/mlpack/build/bin/generate_jl_${name}
-DBINDING_OUTPUT_FILE=${CMAKE_BINARY_DIR}/src/mlpack/bindings/julia/mlpack/src/${name}.jl
-P ${CMAKE_SOURCE_DIR}/CMake/GenerateBinding.cmake)
+25
View File
@@ -1,6 +1,7 @@
/**
* @file core/cv/metrics/facilities.hpp
* @author Kirill Mishchenko
* @author Khizir Siddiqui
*
* Functionality that is used more than in one metric.
*
@@ -13,6 +14,7 @@
#define MLPACK_CORE_CV_METRICS_FACILITIES_HPP
#include <mlpack/core.hpp>
#include <mlpack/core/metrics/lmetric.hpp>
namespace mlpack {
namespace cv {
@@ -40,6 +42,29 @@ void AssertSizes(const DataType& data,
}
}
/**
* Pairwise distance of the given data.
*
* @param data Column-major matrix.
* @param metric Distance metric to be used.
*/
template<typename DataType, typename Metric>
DataType PairwiseDistances(const DataType& data,
const Metric& metric)
{
DataType distances = DataType(data.n_cols, data.n_cols, arma::fill::none);
for (size_t i = 0; i < data.n_cols; i++)
{
for (size_t j = 0; j < i; j++)
{
distances(i, j) = metric.Evaluate(data.col(i), data.col(j));
distances(j, i) = distances(i, j);
}
}
distances.diag().zeros();
return distances;
}
} // namespace cv
} // namespace mlpack
@@ -0,0 +1,108 @@
/**
* @file silhouette_score.hpp
* @author Khizir Siddiqui
*
* The Silhouette metric.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#ifndef MLPACK_CORE_CV_METRICS_SILHOUETTE_SCORE_HPP
#define MLPACK_CORE_CV_METRICS_SILHOUETTE_SCORE_HPP
#include <mlpack/core.hpp>
namespace mlpack {
namespace cv {
/**
* The Silhouette Score is a metric of performance for clustering
* that represents the quality of clusters made as a result.
* It provides an indication of goodness of fit and therefore a measure of how
* well unseen samples are likely to be predicted by the model, considering
* the inter-cluster and intra-cluster dissimilarities.
* Silhoutte Score is dependent on the metric used to calculate the
* dissimilarities. The best possible score is @f$ s(i) = 1.0 @f$.
* Smaller values of Silhouette Score indicate poor clustering.
* Negative values would occur when a wrong label was put on the element.
* Values near zero indicate overlapping clusters.
* For an element i @f$ a(i) @f$ is within cluster average dissimilarity
* and @f$ b(i) @f$ is minimum of average dissimilarity from other clusters.
* the Silhouette Score @f$ s(i) @f$ of a Sample is calculated by
* @f{eqnarray*}{
* s(i) &=& \frac{b(i) - a(i)}{max\{b(i), a(i)\}}
* @f}
*
* The Overall Silhouette Score is the mean of individual silhoutte scores.
*/
class SilhouetteScore
{
public:
/**
* Find the overall silhouette score.
*
* @param X Column-major data used for clustering.
* @param labels Labels assigned to data by clustering.
* @param metric Metric to be used to calculate dissimilarity.
* @return (double) silhouette score.
*/
template<typename DataType, typename Metric>
static double Overall(const DataType& X,
const arma::Row<size_t>& labels,
const Metric& metric);
/**
* Find the individual silhouette scores for precomputted dissimilarites.
*
* @param distances Square matrix containing distances between data points.
* @param labels Labels assigned to data by clustering.
* @return (arma::rowvec) element-wise silhouette score.
*/
template<typename DataType>
static arma::rowvec SamplesScore(const DataType& distances,
const arma::Row<size_t>& labels);
/**
* Find silhouette score of all individual elements.
* (Distance not precomputed).
*
* @param X Column-major data used for clustering.
* @param labels Labels assigned to data by clustering.
* @param metric Metric to be used to calculate dissimilarity.
* @return (arma::rowvec) element-wise silhouette score.
*/
template<typename DataType, typename Metric>
static arma::rowvec SamplesScore(const DataType& X,
const arma::Row<size_t>& labels,
const Metric& metric);
/**
* Find mean distance of element from a given cluster.
*
* @param distances colvec containing distances from other elements.
* @param labels Labels assigned to data by clustering.
* @param label label of the target cluster.
* @param sameCluster true if calculating mean distance from same cluster.
* @return (double) distance from the cluster.
*/
static double MeanDistanceFromCluster(const arma::colvec& distances,
const arma::Row<size_t>& labels,
const size_t& label,
const bool& sameCluster = false);
/**
* Information for hyper-parameter tuning code. It indicates that we want
* to maximize the metric.
*/
static const bool NeedsMinimization = false;
};
} // namespace cv
} // namespace mlpack
// Include implementation.
#include "silhouette_score_impl.hpp"
#endif
@@ -0,0 +1,108 @@
/**
* @file silhouette_score_impl.hpp
* @author Khizir Siddiqui
*
* The implementation of the class SilhouetteScore.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#ifndef MLPACK_CORE_CV_METRICS_SILHOUETTE_SCORE_IMPL_HPP
#define MLPACK_CORE_CV_METRICS_SILHOUETTE_SCORE_IMPL_HPP
#include <mlpack/core/cv/metrics/facilities.hpp>
namespace mlpack {
namespace cv {
template<typename DataType, typename Metric>
double SilhouetteScore::Overall(const DataType& X,
const arma::Row<size_t>& labels,
const Metric& metric)
{
AssertSizes(X, labels, "SilhouetteScore::Overall()");
return arma::mean(SamplesScore(X, labels, metric));
}
template<typename DataType>
arma::rowvec SilhouetteScore::SamplesScore(const DataType& distances,
const arma::Row<size_t>& labels)
{
AssertSizes(distances, labels, "SilhouetteScore::SamplesScore()");
// Stores the silhouette scores of individual samples.
arma::rowvec sampleScores(distances.n_rows);
// Finds one index per cluster.
arma::ucolvec clusterLabels = arma::find_unique(labels, false);
for (size_t i = 0; i < distances.n_rows; i++)
{
double interClusterDistance = DBL_MAX, intraClusterDistance = 0;
double minInterClusterDistance = DBL_MAX;
for (size_t j = 0; j < clusterLabels.n_elem; j++)
{
size_t clusterLabel = labels(clusterLabels(j));
if (labels(i) != clusterLabel) {
interClusterDistance = MeanDistanceFromCluster(
distances.col(i), labels, clusterLabel, false);
if (interClusterDistance < minInterClusterDistance) {
minInterClusterDistance = interClusterDistance;
}
} else {
intraClusterDistance = MeanDistanceFromCluster(
distances.col(i), labels, clusterLabel, true);
if (intraClusterDistance == 0) {
// s(i) = 0, no more calculation needed.
break;
}
}
}
if (intraClusterDistance == 0) {
// i is the only element in the cluster.
sampleScores(i) = 0.0;
} else {
sampleScores(i) = minInterClusterDistance - intraClusterDistance;
sampleScores(i) /= std::max(
intraClusterDistance, minInterClusterDistance);
}
}
return sampleScores;
}
template<typename DataType, typename Metric>
arma::rowvec SilhouetteScore::SamplesScore(const DataType& X,
const arma::Row<size_t>& labels,
const Metric& metric)
{
AssertSizes(X, labels, "SilhouetteScore::SamplesScore()");
DataType distances = PairwiseDistances(X, metric);
return SamplesScore(distances, labels);
}
double SilhouetteScore::MeanDistanceFromCluster(const arma::colvec& distances,
const arma::Row<size_t>& labels,
const size_t& elemLabel,
const bool& sameCluster)
{
// Find indices of elements with same label as elemLabel.
arma::uvec sameClusterIndices = arma::find(labels == elemLabel);
// Numver of elements in the given cluster.
size_t numSameCluster = sameClusterIndices.n_elem;
if ((sameCluster == true) && (numSameCluster == 1))
{
// Return 0 if subject element is the only element in cluster.
return 0.0;
} else {
double distance = arma::accu(distances.elem(sameClusterIndices));
distance /= (numSameCluster - sameCluster);
return distance;
}
}
} // namespace cv
} // namespace mlpack
#endif
+4 -4
View File
@@ -33,11 +33,11 @@ add_markdown_docs(gmm_train "cli;python;julia;go" "clustering")
add_cli_executable(gmm_generate)
add_python_binding(gmm_generate)
add_julia_binding(gmm_generate)
#add_go_binding(gmm_generate)
add_markdown_docs(gmm_generate "cli;python;julia" "clustering")
add_go_binding(gmm_generate)
add_markdown_docs(gmm_generate "cli;python;julia;go" "clustering")
add_cli_executable(gmm_probability)
add_python_binding(gmm_probability)
add_julia_binding(gmm_probability)
#add_go_binding(gmm_probability)
add_markdown_docs(gmm_probability "cli;python;julia" "clustering")
add_go_binding(gmm_probability)
add_markdown_docs(gmm_probability "cli;python;julia;go" "clustering")
+8 -8
View File
@@ -22,23 +22,23 @@ set(MLPACK_SRCS ${MLPACK_SRCS} ${DIR_SRCS} PARENT_SCOPE)
add_cli_executable(hmm_train)
add_python_binding(hmm_train)
add_julia_binding(hmm_train)
#add_go_binding(hmm_train)
add_markdown_docs(hmm_train "cli;python;julia" "misc. / other")
add_go_binding(hmm_train)
add_markdown_docs(hmm_train "cli;python;julia;go" "misc. / other")
add_cli_executable(hmm_loglik)
add_python_binding(hmm_loglik)
add_julia_binding(hmm_loglik)
#add_go_binding(hmm_loglik)
add_markdown_docs(hmm_loglik "cli;python;julia" "misc. / other")
add_go_binding(hmm_loglik)
add_markdown_docs(hmm_loglik "cli;python;julia;go" "misc. / other")
add_cli_executable(hmm_viterbi)
add_python_binding(hmm_viterbi)
add_julia_binding(hmm_viterbi)
#add_go_binding(hmm_viterbi)
add_markdown_docs(hmm_viterbi "cli;python;julia" "misc. / other")
add_go_binding(hmm_viterbi)
add_markdown_docs(hmm_viterbi "cli;python;julia;go" "misc. / other")
add_cli_executable(hmm_generate)
add_python_binding(hmm_generate)
add_julia_binding(hmm_generate)
#add_go_binding(hmm_generate)
add_markdown_docs(hmm_generate "cli;python;julia" "misc. / other")
add_go_binding(hmm_generate)
add_markdown_docs(hmm_generate "cli;python;julia;go" "misc. / other")
+3 -1
View File
@@ -21,4 +21,6 @@ set(MLPACK_SRCS ${MLPACK_SRCS} ${DIR_SRCS} PARENT_SCOPE)
add_cli_executable(kde)
add_python_binding(kde)
add_markdown_docs(kde "cli;python" "misc. / other")
add_julia_binding(kde)
add_go_binding(kde)
add_markdown_docs(kde "cli;python;julia;go" "misc. / other")
+3 -1
View File
@@ -9,8 +9,10 @@
* 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/cli.hpp>
#include <mlpack/core/util/mlpack_main.hpp>
#include <mlpack/core.hpp>
#include "kde.hpp"
#include "kde_model.hpp"
+1 -1
View File
@@ -2,4 +2,4 @@ add_cli_executable(nmf)
add_python_binding(nmf)
add_julia_binding(nmf)
add_go_binding(nmf)
add_markdown_docs(nmf "cli;python;julia" "misc. / other")
add_markdown_docs(nmf "cli;python;julia;go" "misc. / other")
+1
View File
@@ -33,6 +33,7 @@ add_executable(mlpack_test
drusilla_select_test.cpp
emst_test.cpp
fastmks_test.cpp
facilities_test.cpp
feedforward_network_test.cpp
gan_test.cpp
gmm_test.cpp
+16
View File
@@ -18,6 +18,7 @@
#include <mlpack/core/cv/metrics/precision.hpp>
#include <mlpack/core/cv/metrics/recall.hpp>
#include <mlpack/core/cv/metrics/r2_score.hpp>
#include <mlpack/core/cv/metrics/silhouette_score.hpp>
#include <mlpack/core/cv/simple_cv.hpp>
#include <mlpack/core/cv/k_fold_cv.hpp>
#include <mlpack/methods/ann/ffn.hpp>
@@ -719,4 +720,19 @@ BOOST_AUTO_TEST_CASE(KFoldCVWithDTTestUnevenBinsWeighted)
BOOST_REQUIRE_GT(accuracy, 0.7);
}
/**
* Test Silhouette Score
*/
BOOST_AUTO_TEST_CASE(SilhouetteScoreTest)
{
arma::mat X;
X << 0 << 1 << 1 << 0 << 0 << arma::endr
<< 0 << 1 << 2 << 0 << 0 << arma::endr
<< 1 << 1 << 3 << 2 << 0 << arma::endr;
arma::Row<size_t> labels = {0, 1, 2, 0, 0};
metric::EuclideanDistance metric;
double silhouetteScore = SilhouetteScore::Overall(X, labels, metric);
BOOST_REQUIRE_CLOSE(silhouetteScore, 0.1121684822489150, 1e-5);
}
BOOST_AUTO_TEST_SUITE_END();
+60
View File
@@ -0,0 +1,60 @@
/**
* @file facilities_test.cpp
* @author Khizir Siddiqui
*
* Test file for facilities in metrics.
*
* 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/core.hpp>
#include <mlpack/core/cv/metrics/facilities.hpp>
#include <mlpack/core/metrics/lmetric.hpp>
#include <mlpack/core/data/load.hpp>
#include <boost/test/unit_test.hpp>
#include "test_tools.hpp"
using namespace mlpack;
using namespace mlpack::cv;
BOOST_AUTO_TEST_SUITE(FacilitiesTest);
/**
* The unequal sizes for data and labels show throw an error.
*/
BOOST_AUTO_TEST_CASE(AssertSizesTest)
{
// Load the dataset.
arma::mat dataset;
data::Load("iris_train.csv", dataset);
// Load the labels.
arma::Row<size_t> labels;
data::Load("iris_test_labels.csv", labels);
BOOST_REQUIRE_THROW(
AssertSizes(dataset, labels, "test"), std::invalid_argument);
}
/**
* Pairwise distances.
*/
BOOST_AUTO_TEST_CASE(PairwiseDistanceTest)
{
arma::mat X;
X << 0 << 1 << 1 << 0 << 0 << arma::endr
<< 0 << 1 << 2 << 0 << 0 << arma::endr
<< 1 << 1 << 3 << 2 << 0 << arma::endr;
metric::EuclideanDistance metric;
arma::mat dist = PairwiseDistances(X, metric);
BOOST_REQUIRE_EQUAL(dist(0, 0), 0);
BOOST_REQUIRE_CLOSE(dist(1, 0), 1.41421, 1e-3);
BOOST_REQUIRE_EQUAL(dist(2, 0), 3);
}
BOOST_AUTO_TEST_SUITE_END();