diff --git a/cmake/ShogunUtils.cmake b/cmake/ShogunUtils.cmake index 4fcfb533c53..eca6cdad079 100644 --- a/cmake/ShogunUtils.cmake +++ b/cmake/ShogunUtils.cmake @@ -75,31 +75,31 @@ ENDMACRO() # based on compiz_discover_tests function (shogun_discover_tests EXECUTABLE) - add_dependencies (${EXECUTABLE} discover_gtest_tests) - - add_custom_command (TARGET ${EXECUTABLE} - POST_BUILD - COMMAND ${CMAKE_COMMAND} -D UNIT_TEST_CMD=${CMAKE_BINARY_DIR}/bin/${EXECUTABLE} - -D DISCOVER_CMD=${CMAKE_BINARY_DIR}/bin/discover_gtest_tests - -D WORKING_DIR=${CMAKE_CURRENT_BINARY_DIR} - -P ${CMAKE_MODULE_PATH}/discover_unit_tests.cmake - COMMENT "Discovering Tests in ${EXECUTABLE}" - DEPENDS - VERBATIM) + add_dependencies (${EXECUTABLE} discover_gtest_tests) + + add_custom_command (TARGET ${EXECUTABLE} + POST_BUILD + COMMAND ${CMAKE_COMMAND} -D UNIT_TEST_CMD=${CMAKE_BINARY_DIR}/bin/${EXECUTABLE} + -D DISCOVER_CMD=${CMAKE_BINARY_DIR}/bin/discover_gtest_tests + -D WORKING_DIR=${CMAKE_CURRENT_BINARY_DIR} + -P ${CMAKE_MODULE_PATH}/discover_unit_tests.cmake + COMMENT "Discovering Tests in ${EXECUTABLE}" + DEPENDS + VERBATIM) endfunction () MACRO(AddMetaIntegrationTest META_TARGET CONDITION) - IF (${CONDITION}) - add_test(NAME integration_meta_${META_TARGET}-${NAME_WITH_DIR} - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND meta_example_integration_tester ${REL_DIR} ${NAME}.dat ${META_TARGET} generated_results reference_results) - set_tests_properties( - integration_meta_${META_TARGET}-${NAME_WITH_DIR} - PROPERTIES - LABELS "integration" - DEPENDS generated_${META_TARGET}-${NAME_WITH_DIR} - ) - ENDIF() + IF (${CONDITION}) + add_test(NAME integration_meta_${META_TARGET}-${NAME_WITH_DIR} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND meta_example_integration_tester ${REL_DIR} ${NAME}.dat ${META_TARGET} generated_results reference_results) + set_tests_properties( + integration_meta_${META_TARGET}-${NAME_WITH_DIR} + PROPERTIES + LABELS "integration" + DEPENDS generated_${META_TARGET}-${NAME_WITH_DIR} + ) + ENDIF() ENDMACRO() MACRO(AddLibShogunExample EXAMPLE_CPP) @@ -144,18 +144,23 @@ macro(ADD_LIBRARY_DEPENDENCY) set(oneValueArgs LIBRARY CONFIG_FLAG VERSION SCOPE) set(multiValueArgs TARGETS) cmake_parse_arguments(ADD_LIBRARY_DEPENDENCY "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) - STRING(TOUPPER ${ADD_LIBRARY_DEPENDENCY_LIBRARY} LIBRARY_PREFIX) - OPTION(ENABLE_${LIBRARY_PREFIX} "Use ${LIBRARY_PREFIX}" ON) + SET(LIBRARY_PREFIX ${ADD_LIBRARY_DEPENDENCY_LIBRARY}) + STRING(TOUPPER ${ADD_LIBRARY_DEPENDENCY_LIBRARY} LIBRARY_PREFIX_UPPER) + OPTION(ENABLE_${LIBRARY_PREFIX_UPPER} "Use ${LIBRARY_PREFIX}" ON) if (${ADD_LIBRARY_DEPENDENCY_REQUIRED}) find_package(${ADD_LIBRARY_DEPENDENCY_LIBRARY} REQUIRED ${ADD_LIBRARY_DEPENDENCY_VERSION}) else() find_package(${ADD_LIBRARY_DEPENDENCY_LIBRARY} ${ADD_LIBRARY_DEPENDENCY_VERSION}) endif() - if (${LIBRARY_PREFIX}_FOUND AND ENABLE_${LIBRARY_PREFIX}) + if ((${LIBRARY_PREFIX}_FOUND OR ${LIBRARY_PREFIX_UPPER}_FOUND) AND ENABLE_${LIBRARY_PREFIX_UPPER}) if (${LIBRARY_PREFIX}_INCLUDE_DIR) set(LIBRARY_HEADER ${${LIBRARY_PREFIX}_INCLUDE_DIR}) + elseif (${LIBRARY_PREFIX_UPPER}_INCLUDE_DIR) + set(LIBRARY_HEADER ${${LIBRARY_PREFIX_UPPER}_INCLUDE_DIR}) elseif (${LIBRARY_PREFIX}_INCLUDE_DIRS) set(LIBRARY_HEADER ${${LIBRARY_PREFIX}_INCLUDE_DIRS}) + elseif (${LIBRARY_PREFIX_UPPER}_INCLUDE_DIRS) + set(LIBRARY_HEADER ${${LIBRARY_PREFIX_UPPER}_INCLUDE_DIRS}) else () message(${${LIBRARY_PREFIX}_INCLUDE_DIR}) message(FATAL_ERROR "Found ${ADD_LIBRARY_DEPENDENCY_LIBRARY}, but not it's headers!") @@ -163,15 +168,23 @@ macro(ADD_LIBRARY_DEPENDENCY) set(${ADD_LIBRARY_DEPENDENCY_CONFIG_FLAG} ON CACHE BOOL "Use ${LIBRARY_PREFIX}" FORCE) + if (${LIBRARY_PREFIX}_LIBRARIES) + set(LIBRARY_LIBS ${${LIBRARY_PREFIX}_LIBRARIES}) + elseif(${LIBRARY_PREFIX_UPPER}_LIBRARIES) + set(LIBRARY_LIBS ${${LIBRARY_PREFIX_UPPER}_LIBRARIES}) + else() + message(FATAL_ERROR "Found ${ADD_LIBRARY_DEPENDENCY_LIBRARY}, but not it's libraries!") + endif() + ForEach (element ${ADD_LIBRARY_DEPENDENCY_TARGETS}) if (TARGET ${element}) get_target_property(TARGET_TYPE ${element} TYPE) if (${TARGET_TYPE} STREQUAL INTERFACE_LIBRARY) target_include_directories(${element} INTERFACE ${LIBRARY_HEADER}) - target_link_libraries(${element} INTERFACE ${${LIBRARY_PREFIX}_LIBRARIES}) + target_link_libraries(${element} INTERFACE ${LIBRARY_LIBS}) else() if (NOT ${TARGET_TYPE} STREQUAL OBJECT_LIBRARY) - target_link_libraries(${element} ${ADD_LIBRARY_DEPENDENCY_SCOPE} ${${LIBRARY_PREFIX}_LIBRARIES}) + target_link_libraries(${element} ${ADD_LIBRARY_DEPENDENCY_SCOPE} ${LIBRARY_LIBS}) endif() target_include_directories(${element} ${ADD_LIBRARY_DEPENDENCY_SCOPE} ${LIBRARY_HEADER}) endif() @@ -225,12 +238,12 @@ endfunction() function(SET_LINALG_BACKEND COMPONENT FLAG) OPTION(USE_EIGEN3_${FLAG} "Use ${COMPONENT} Eigen3" ON) CMAKE_DEPENDENT_OPTION( - USE_VIENNACL_${FLAG} "Use ${COMPONENT} ViennaCL" OFF - "VIENNACL_FOUND;USE_VIENNACL;NOT USE_EIGEN3_${FLAG}" ON) + USE_VIENNACL_${FLAG} "Use ${COMPONENT} ViennaCL" OFF + "VIENNACL_FOUND;USE_VIENNACL;NOT USE_EIGEN3_${FLAG}" ON) if(NOT ${COMPONENT}) - set(${COMPONENT} EIGEN3 CACHE STRING - "Set linear algebra backend ${COMPONENT}: EIGEN3, VIENNACL" - FORCE) + set(${COMPONENT} EIGEN3 CACHE STRING + "Set linear algebra backend ${COMPONENT}: EIGEN3, VIENNACL" + FORCE) endif() if (${COMPONENT} STREQUAL "EIGEN3") @@ -264,7 +277,7 @@ function(GET_META_EXAMPLE_VARS META_EXAMPLE EX_NAME REL_DIR NAME_WITH_DIR) endfunction() function(GET_INTERFACE_VARS INTERFACE DIRECTORY EXTENSION) - string(REGEX MATCH "INTERFACE_([a-zA-Z]+)" _dir ${INTERFACE}) + string(REGEX MATCH "INTERFACE_([a-zA-Z]+)" _dir ${INTERFACE}) STRING(TOLOWER "${CMAKE_MATCH_1}" _dir) SET(${DIRECTORY} ${_dir} PARENT_SCOPE) @@ -314,4 +327,4 @@ function(ADD_SHOGUN_BENCHMARK REL_BENCHMARK_NAME) if(ARGN) set_tests_properties(${BENCHMARK_NAME} PROPERTIES ${ARGN}) endif() -endfunction() +endfunction() \ No newline at end of file diff --git a/cmake/external/RapidJSON.cmake b/cmake/external/RapidJSON.cmake new file mode 100644 index 00000000000..0a6efe738c4 --- /dev/null +++ b/cmake/external/RapidJSON.cmake @@ -0,0 +1,16 @@ +set(RAPIDJSON_PREFIX ${CMAKE_BINARY_DIR}/RapidJSON) +set(RAPIDJSON_INCLUDE_DIR "${RAPIDJSON_PREFIX}/src/RapidJSON/include") +include(ExternalProject) +ExternalProject_Add( + RapidJSON + PREFIX ${RAPIDJSON_PREFIX} + DOWNLOAD_DIR ${THIRD_PARTY_DIR}/RapidJSON + URL https://github.com/Tencent/rapidjson/archive/v1.1.0.tar.gz + URL_MD5 badd12c511e081fec6c89c43a7027bce + CMAKE_ARGS -DRAPIDJSON_BUILD_DOC:BOOL=OFF + -DRAPIDJSON_BUILD_EXAMPLES:BOOL=OFF + -DRAPIDJSON_BUILD_TESTS:BOOL=OFF + INSTALL_COMMAND "" +) + +LIST(APPEND SHOGUN_DEPENDS RapidJSON) \ No newline at end of file diff --git a/src/interfaces/swig/IO.i b/src/interfaces/swig/IO.i index 75c0e10899e..4e59008adf4 100644 --- a/src/interfaces/swig/IO.i +++ b/src/interfaces/swig/IO.i @@ -25,6 +25,7 @@ %rename(SimpleFile) CSimpleFile; %rename(MemoryMappedFile) CMemoryMappedFile; +%shared_ptr(shogun::OpenMLFlow) %include %include @@ -120,6 +121,7 @@ namespace shogun %include %include +%include %include %include %include diff --git a/src/interfaces/swig/IO_includes.i b/src/interfaces/swig/IO_includes.i index 7bbdb373ccb..89401074d62 100644 --- a/src/interfaces/swig/IO_includes.i +++ b/src/interfaces/swig/IO_includes.i @@ -13,6 +13,7 @@ #include #include +#include #include #include #include diff --git a/src/interfaces/swig/SGBase.i b/src/interfaces/swig/SGBase.i index 27f0d067dd6..de7f79a772b 100644 --- a/src/interfaces/swig/SGBase.i +++ b/src/interfaces/swig/SGBase.i @@ -8,6 +8,7 @@ %include "stdint.i" %include "std_string.i" %include "exception.i" +%include "std_shared_ptr.i" %feature("ref") shogun::CSGObject "SG_REF($this);" %feature("unref") shogun::CSGObject "SG_UNREF($this);" diff --git a/src/shogun/CMakeLists.txt b/src/shogun/CMakeLists.txt index 1698bc05e9f..8290d3a49b4 100644 --- a/src/shogun/CMakeLists.txt +++ b/src/shogun/CMakeLists.txt @@ -1,6 +1,6 @@ INCLUDE_DIRECTORIES( - ${CMAKE_SOURCE_DIR}/src - ${CMAKE_BINARY_DIR}/src + ${CMAKE_SOURCE_DIR}/src + ${CMAKE_BINARY_DIR}/src ) include(GenerateExportHeader) @@ -34,33 +34,33 @@ set(SHOGUN_CLING_LIBRARY_DIR "\"${CMAKE_INSTALL_PREFIX}/${SHOGUN_LIB_INSTALL}\"" if (MSVC OR BUILD_BENCHMARKS) SET(LIBSHOGUN_BUILD_STATIC ON - CACHE BOOL "Build libshogun static library" FORCE) + CACHE BOOL "Build libshogun static library" FORCE) endif() # Allow to hide non-bsd compatible codes OPTION(LICENSE_GPL_SHOGUN "Include GPL codes of Shogun (non-BSD compatible) in build" ON) SET(USE_GPL_SHOGUN 0) IF (LICENSE_GPL_SHOGUN) - SET(SHOGUN_GPL_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/src/gpl) - IF(EXISTS "${SHOGUN_GPL_INCLUDE_DIR}/shogun") - SET(USE_GPL_SHOGUN 1) + SET(SHOGUN_GPL_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/src/gpl) + IF(EXISTS "${SHOGUN_GPL_INCLUDE_DIR}/shogun") + SET(USE_GPL_SHOGUN 1) - FILE(GLOB_RECURSE GPL_LIBSHOGUN_SRC ${SHOGUN_GPL_INCLUDE_DIR}/*.${EXT_SRC_CPP} ${SHOGUN_GPL_INCLUDE_DIR}/*.${EXT_SRC_C}) - FILE(GLOB_RECURSE GPL_LIBSHOGUN_HEADERS ${SHOGUN_GPL_INCLUDE_DIR}/*.${EXT_SRC_HEADER}) + FILE(GLOB_RECURSE GPL_LIBSHOGUN_SRC ${SHOGUN_GPL_INCLUDE_DIR}/*.${EXT_SRC_CPP} ${SHOGUN_GPL_INCLUDE_DIR}/*.${EXT_SRC_C}) + FILE(GLOB_RECURSE GPL_LIBSHOGUN_HEADERS ${SHOGUN_GPL_INCLUDE_DIR}/*.${EXT_SRC_HEADER}) - LIST(APPEND LIBSHOGUN_SRC ${GPL_LIBSHOGUN_SRC}) - LIST(APPEND LIBSHOGUN_HEADERS ${GPL_LIBSHOGUN_HEADERS}) - INCLUDE_DIRECTORIES(${SHOGUN_GPL_INCLUDE_DIR}) + LIST(APPEND LIBSHOGUN_SRC ${GPL_LIBSHOGUN_SRC}) + LIST(APPEND LIBSHOGUN_HEADERS ${GPL_LIBSHOGUN_HEADERS}) + INCLUDE_DIRECTORIES(${SHOGUN_GPL_INCLUDE_DIR}) - SET(USE_GPL_SHOGUN 1) - ELSE() - MESSAGE(FATAL_ERROR "Shogun can only be built with GPL codes if the source files are in ${SHOGUN_GPL_INCLUDE_DIR}. Please download or disable with LICENSE_GPL_SHOGUN=OFF.\n") - ENDIF() + SET(USE_GPL_SHOGUN 1) + ELSE() + MESSAGE(FATAL_ERROR "Shogun can only be built with GPL codes if the source files are in ${SHOGUN_GPL_INCLUDE_DIR}. Please download or disable with LICENSE_GPL_SHOGUN=OFF.\n") + ENDIF() ENDIF() OPTION(USE_SVMLIGHT "SVMLight" ON) IF(USE_SVMLIGHT AND NOT USE_GPL_SHOGUN) - MESSAGE(FATAL_ERROR "Can only use SVMLight when GPL codes are included. Disable by USE_SVMLIGHT=OFF") + MESSAGE(FATAL_ERROR "Can only use SVMLight when GPL codes are included. Disable by USE_SVMLIGHT=OFF") ENDIF() # add target to compile the libshogun sources @@ -72,13 +72,13 @@ ENDIF() # Generate versionstring.h ADD_CUSTOM_TARGET( - version - ${CMAKE_COMMAND} - -D SRC=${CMAKE_CURRENT_SOURCE_DIR}/lib/versionstring.h.in - -D DST=${CMAKE_CURRENT_BINARY_DIR}/lib/versionstring.h - -D ROOT_DIR=${CMAKE_SOURCE_DIR} - -P ${CMAKE_SOURCE_DIR}/cmake/version.cmake - COMMENT "Generating version header" + version + ${CMAKE_COMMAND} + -D SRC=${CMAKE_CURRENT_SOURCE_DIR}/lib/versionstring.h.in + -D DST=${CMAKE_CURRENT_BINARY_DIR}/lib/versionstring.h + -D ROOT_DIR=${CMAKE_SOURCE_DIR} + -P ${CMAKE_SOURCE_DIR}/cmake/version.cmake + COMMENT "Generating version header" ) add_dependencies(libshogun version) @@ -97,12 +97,12 @@ FOREACH(template ${LIBSHOGUN_SRC_TMP}) ENDFOREACH() ADD_CUSTOM_COMMAND(OUTPUT ${generated_cpp} - COMMAND ${CMAKE_COMMAND} -E copy_if_different ${template} ${generated_cpp} - COMMAND ${PYTHON_EXECUTABLE} ${generator_script} ${generated_cpp} -in ${CMAKE_CURRENT_BINARY_DIR}/headers_list.txt - DEPENDS ${template} ${generator_script} version ${LIBSHOGUN_HEADERS} ${CMAKE_CURRENT_BINARY_DIR}/headers_list.txt - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMENT "Generating ${generated_cpp}" - ) + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${template} ${generated_cpp} + COMMAND ${PYTHON_EXECUTABLE} ${generator_script} ${generated_cpp} -in ${CMAKE_CURRENT_BINARY_DIR}/headers_list.txt + DEPENDS ${template} ${generator_script} version ${LIBSHOGUN_HEADERS} ${CMAKE_CURRENT_BINARY_DIR}/headers_list.txt + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating ${generated_cpp}" + ) ADD_CUSTOM_TARGET(${generated_target} DEPENDS ${generated_cpp}) add_dependencies(libshogun ${generated_target}) @@ -113,18 +113,18 @@ ENDFOREACH() add_library(shogun SHARED $ ${CMAKE_CURRENT_BINARY_DIR}/lib/config.h) generate_export_header(shogun) set_target_properties( - shogun PROPERTIES - VERSION ${LIBSHOGUNVER} - SOVERSION ${LIBSHOGUNSO} - INTERFACE_shogun_MAJOR_VERSION ${SHOGUN_VERSION_MAJOR}) + shogun PROPERTIES + VERSION ${LIBSHOGUNVER} + SOVERSION ${LIBSHOGUNSO} + INTERFACE_shogun_MAJOR_VERSION ${SHOGUN_VERSION_MAJOR}) set_property(TARGET shogun APPEND PROPERTY COMPATIBLE_INTERFACE_STRING ${SHOGUN_VERSION_MAJOR}) target_include_directories(shogun PUBLIC - $ - $ - $ -) + $ + $ + $ + ) IF (${USE_GPL_SHOGUN}) - target_include_directories(shogun PUBLIC $) + target_include_directories(shogun PUBLIC $) ENDIF() get_property(dirs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES) @@ -137,33 +137,28 @@ endforeach() add_library(shogun_deps INTERFACE) target_link_libraries(shogun_deps INTERFACE shogun) target_include_directories(shogun_deps INTERFACE - $ - $ -) + $ + $ + ) IF (${USE_GPL_SHOGUN}) - target_include_directories(shogun_deps INTERFACE $) + target_include_directories(shogun_deps INTERFACE $) ENDIF() -# add bundled libraries to dependency -if(SHOGUN_DEPENDS) - add_dependencies(libshogun ${SHOGUN_DEPENDS}) -endif() - # add target for static library if enabled if (LIBSHOGUN_BUILD_STATIC) add_library(shogun-static STATIC $ ${CMAKE_CURRENT_BINARY_DIR}/lib/config.h) set_property(TARGET shogun-static PROPERTY OUTPUT_NAME shogun) target_include_directories(shogun-static PUBLIC - $ - $ - $ - ) + $ + $ + $ + ) IF (${USE_GPL_SHOGUN}) target_include_directories(shogun-static PUBLIC $) ENDIF() if(MSVC) - target_link_libraries(shogun-static PUBLIC winmm.lib) + target_link_libraries(shogun-static PUBLIC winmm.lib Shlwapi.lib) endif() ENDIF() @@ -171,20 +166,13 @@ IF(MSVC) IF(MSVC_VERSION VERSION_LESS "1700") include(external/MSIntTypes) SHOGUN_INCLUDE_DIRS(SCOPE PUBLIC - $ - $ - ) + $ + $ + ) ENDIF() - # bundle dirent - include(external/MSDirent) - SHOGUN_INCLUDE_DIRS(SCOPE PUBLIC - $ - $ - ) - - target_link_libraries(shogun PUBLIC winmm) - target_link_libraries(shogun_deps INTERFACE winmm) + target_link_libraries(shogun PUBLIC winmm Shlwapi) + target_link_libraries(shogun_deps INTERFACE winmm Shlwapi) ENDIF() ########################### compiler capabilities @@ -258,7 +246,7 @@ if (NOT MSVC) SET(USE_HOARD 1) SET(POSTLINKFLAGS ${POSTLINKFLAGS} ${Hoard_LIBRARIES}) else () - message(FATAL_ERROR "Unable to use hoard malloc: library not found") + message(FATAL_ERROR "Unable to use hoard malloc: library not found") endif () else() message(STATUS "Using system's malloc") @@ -291,49 +279,49 @@ endif() include(external/StanMath) SHOGUN_INCLUDE_DIRS(SCOPE PUBLIC SYSTEM - $ - $ -) + $ + $ + ) SHOGUN_INCLUDE_DIRS(SCOPE PUBLIC SYSTEM - $ - $ -) + $ + $ + ) SHOGUN_INCLUDE_DIRS(SCOPE PUBLIC SYSTEM - $ - $ -) + $ + $ + ) SHOGUN_INCLUDE_DIRS(SCOPE PUBLIC SYSTEM - $ - $ -) + $ + $ + ) ####### LINALG # ViennaCL detection SHOGUN_DEPENDENCIES( - LIBRARY ViennaCL - SCOPE PRIVATE - VERSION ${VIENNACL_VERSION_MINIMUM} - CONFIG_FLAG HAVE_VIENNACL) + LIBRARY ViennaCL + SCOPE PRIVATE + VERSION ${VIENNACL_VERSION_MINIMUM} + CONFIG_FLAG HAVE_VIENNACL) ####### /LINALG FIND_PACKAGE(rxcpp) IF(NOT rxcpp_FOUND) - include(external/rxcpp) - SHOGUN_INCLUDE_DIRS(SCOPE PUBLIC SYSTEM - $ - $ - ) + include(external/rxcpp) + SHOGUN_INCLUDE_DIRS(SCOPE PUBLIC SYSTEM + $ + $ + ) ELSE() - SHOGUN_INCLUDE_DIRS(SCOPE PUBLIC SYSTEM ${rxcpp_INCLUDE_DIR}) + SHOGUN_INCLUDE_DIRS(SCOPE PUBLIC SYSTEM ${rxcpp_INCLUDE_DIR}) ENDIF() # TFLogger package FIND_PACKAGE(TFLogger 0.1.0 CONFIG) IF (TFLogger_FOUND) - SET(HAVE_TFLOGGER 1) - SHOGUN_INCLUDE_DIRS(SCOPE PRIVATE SYSTEM ${TFLogger_INCLUDE_DIR}) - target_link_libraries(shogun PRIVATE tflogger::tflogger) + SET(HAVE_TFLOGGER 1) + SHOGUN_INCLUDE_DIRS(SCOPE PRIVATE SYSTEM ${TFLogger_INCLUDE_DIR}) + target_link_libraries(shogun PRIVATE tflogger::tflogger) ENDIF() #### LAPACK @@ -344,35 +332,40 @@ CHECK_CXX_SOURCE_COMPILES("#include \n int main(int argc, char** argv) IF (NOT HAVE_STD_VARIANT) include(external/variant) SHOGUN_INCLUDE_DIRS(SCOPE PUBLIC SYSTEM - $ - $ - ) + $ + $ + ) ENDIF() SHOGUN_DEPENDENCIES( - LIBRARY GLPK - SCOPE PRIVATE - CONFIG_FLAG USE_GLPK) + LIBRARY GLPK + SCOPE PRIVATE + CONFIG_FLAG USE_GLPK) SHOGUN_DEPENDENCIES( - LIBRARY CPLEX - SCOPE PRIVATE - CONFIG_FLAG USE_CPLEX) + LIBRARY LibArchive + SCOPE PRIVATE + CONFIG_FLAG HAVE_LIBARCHIVE) SHOGUN_DEPENDENCIES( - LIBRARY ARPACK - SCOPE PRIVATE - CONFIG_FLAG HAVE_ARPACK) + LIBRARY CPLEX + SCOPE PRIVATE + CONFIG_FLAG USE_CPLEX) SHOGUN_DEPENDENCIES( - LIBRARY Mosek - SCOPE PRIVATE - CONFIG_FLAG USE_MOSEK) + LIBRARY ARPACK + SCOPE PRIVATE + CONFIG_FLAG HAVE_ARPACK) SHOGUN_DEPENDENCIES( - LIBRARY Protobuf - SCOPE PUBLIC - CONFIG_FLAG HAVE_PROTOBUF) + LIBRARY Mosek + SCOPE PRIVATE + CONFIG_FLAG USE_MOSEK) + +SHOGUN_DEPENDENCIES( + LIBRARY Protobuf + SCOPE PUBLIC + CONFIG_FLAG HAVE_PROTOBUF) IF (PROTOBUF_FOUND AND ENABLE_PROTOBUF) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/io/protobuf) @@ -383,12 +376,12 @@ IF (PROTOBUF_FOUND AND ENABLE_PROTOBUF) SET(name "${CMAKE_CURRENT_BINARY_DIR}/io/protobuf/${FIL_WE}") ADD_CUSTOM_COMMAND( - OUTPUT "${name}.pb.cc" "${name}.pb.h" - COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} ${FIL} - --cpp_out ${CMAKE_CURRENT_BINARY_DIR}/io/protobuf - --proto_path ${CMAKE_CURRENT_SOURCE_DIR}/io/protobuf - COMMENT "Running C++ protocol buffer compiler on ${FIL_WE}.proto" - ) + OUTPUT "${name}.pb.cc" "${name}.pb.h" + COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} ${FIL} + --cpp_out ${CMAKE_CURRENT_BINARY_DIR}/io/protobuf + --proto_path ${CMAKE_CURRENT_SOURCE_DIR}/io/protobuf + COMMENT "Running C++ protocol buffer compiler on ${FIL_WE}.proto" + ) ADD_CUSTOM_TARGET("${FIL_WE}Protobuf" DEPENDS "${name}.pb.cc") add_dependencies(libshogun "${FIL_WE}Protobuf") set_source_files_properties(${name}.pb.cc PROPERTIES GENERATED ON) @@ -407,55 +400,58 @@ IF(BUNDLE_JSON) SET(POSTLINKFLAGS ${POSTLINKFLAGS} ${JSON_LDFLAGS}) ELSE() SHOGUN_DEPENDENCIES( - LIBRARY JSON - SCOPE PUBLIC - CONFIG_FLAG HAVE_JSON - VERSION 0.11) + LIBRARY JSON + SCOPE PUBLIC + CONFIG_FLAG HAVE_JSON + VERSION 0.11) ENDIF() SHOGUN_DEPENDENCIES( - LIBRARY LibXml2 - SCOPE PUBLIC - CONFIG_FLAG HAVE_XML) + LIBRARY LibXml2 + SCOPE PUBLIC + CONFIG_FLAG HAVE_XML) +# RapidJSON +include(external/RapidJSON) +SHOGUN_INCLUDE_DIRS(SCOPE PUBLIC ${RAPIDJSON_INCLUDE_DIR}) if (NOT WIN32) # FIXME: HDF5 linking on WIN32 is broken. # at least with the hdf5 supplied in anaconda SHOGUN_DEPENDENCIES( - LIBRARY HDF5 - SCOPE PUBLIC - CONFIG_FLAG HAVE_HDF5) + LIBRARY HDF5 + SCOPE PUBLIC + CONFIG_FLAG HAVE_HDF5) endif () SHOGUN_DEPENDENCIES( - LIBRARY CURL - SCOPE PRIVATE - CONFIG_FLAG HAVE_CURL) + LIBRARY CURL + SCOPE PRIVATE + CONFIG_FLAG HAVE_CURL) SHOGUN_DEPENDENCIES( - LIBRARY ZLIB - SCOPE PRIVATE - CONFIG_FLAG USE_GZIP) + LIBRARY ZLIB + SCOPE PRIVATE + CONFIG_FLAG USE_GZIP) SHOGUN_DEPENDENCIES( - LIBRARY BZip2 - SCOPE PRIVATE - CONFIG_FLAG USE_BZIP2) + LIBRARY BZip2 + SCOPE PRIVATE + CONFIG_FLAG USE_BZIP2) SHOGUN_DEPENDENCIES( - LIBRARY LibLZMA - SCOPE PRIVATE - CONFIG_FLAG USE_LZMA) + LIBRARY LibLZMA + SCOPE PRIVATE + CONFIG_FLAG USE_LZMA) SHOGUN_DEPENDENCIES( - LIBRARY SNAPPY - SCOPE PRIVATE - CONFIG_FLAG USE_SNAPPY) + LIBRARY SNAPPY + SCOPE PRIVATE + CONFIG_FLAG USE_SNAPPY) SHOGUN_DEPENDENCIES( - LIBRARY LZO - SCOPE PRIVATE - CONFIG_FLAG USE_LZO) + LIBRARY LZO + SCOPE PRIVATE + CONFIG_FLAG USE_LZO) #integration OPTION(OpenCV "OpenCV Integration" OFF) @@ -483,25 +479,25 @@ IF(BUNDLE_NLOPT) SET(POSTLINKFLAGS ${POSTLINKFLAGS} ${NLOPT_LIBRARIES}) ELSE() SHOGUN_DEPENDENCIES( - LIBRARY NLopt - SCOPE PRIVATE - CONFIG_FLAG HAVE_NLOPT) + LIBRARY NLopt + SCOPE PRIVATE + CONFIG_FLAG HAVE_NLOPT) ENDIF() SHOGUN_DEPENDENCIES( - LIBRARY LpSolve - SCOPE PRIVATE - CONFIG_FLAG USE_LPSOLVE) + LIBRARY LpSolve + SCOPE PRIVATE + CONFIG_FLAG USE_LPSOLVE) SHOGUN_DEPENDENCIES( - LIBRARY ColPack - SCOPE PRIVATE - CONFIG_FLAG HAVE_COLPACK) + LIBRARY ColPack + SCOPE PRIVATE + CONFIG_FLAG HAVE_COLPACK) SHOGUN_DEPENDENCIES( - LIBRARY ARPREC - SCOPE PRIVATE - CONFIG_FLAG HAVE_ARPREC) + LIBRARY ARPREC + SCOPE PRIVATE + CONFIG_FLAG HAVE_ARPREC) ###### checks for random # PRNG settings @@ -511,12 +507,12 @@ SET(DSFMT_MEXP ${MEXP}) CHECK_FUNCTION_EXISTS(arc4random HAVE_ARC4RANDOM) IF(NOT HAVE_ARC4RANDOM) - # assume that /dev/random is non-blocking if /dev/urandom does not exist - if(EXISTS /dev/urandom) - set(DEV_RANDOM "/dev/urandom" CACHE INTERNAL "" FORCE) - elseif( EXISTS /dev/random ) - set(DEV_RANDOM "/dev/random" CACHE INTERNAL "" FORCE) - endif() + # assume that /dev/random is non-blocking if /dev/urandom does not exist + if(EXISTS /dev/urandom) + set(DEV_RANDOM "/dev/urandom" CACHE INTERNAL "" FORCE) + elseif( EXISTS /dev/random ) + set(DEV_RANDOM "/dev/random" CACHE INTERNAL "" FORCE) + endif() ENDIF() ############################ HMM @@ -535,11 +531,16 @@ OPTION(USE_LOGSUMARRAY "Use sum array, supposed to be a bit more accurate" OFF) #kernelcache to use 4-byte-floating-point values instead of 8-byte-doubles OPTION(USE_SHORTREAL_KERNELCACHE "Kernelcache to use 4-byte-floating-point values instead of 8-byte-doubles" ON) +# add bundled libraries to dependency +if(SHOGUN_DEPENDS) + add_dependencies(libshogun ${SHOGUN_DEPENDS}) +endif() + OPTION(USE_LOGCACHE "Use (1+exp(x)) log cache (is much faster but less accurate)" OFF) ################## linker optimisations OPTION(INCREMENTAL_LINKING "Enable incremantal linking") SET(INCREMENTAL_LINKING_DIR ${CMAKE_BINARY_DIR}/linker_cache - CACHE PATH "Incremental linking cache directory") + CACHE PATH "Incremental linking cache directory") OPTION(ENABLE_LTO "Enable link-time optimisation") include(LDGOLD) @@ -561,7 +562,7 @@ target_link_libraries(shogun PUBLIC ${POSTLINKFLAGS}) IF (BUILD_BENCHMARKS) IF (NOT BUILD_TYPE_UC STREQUAL "RELEASE") MESSAGE(WARNING "You are building benchmark against non-Release mode!" - "The results might not reflect the actual runtimes...") + "The results might not reflect the actual runtimes...") ENDIF() find_package(benchmark CONFIG REQUIRED) @@ -571,16 +572,16 @@ IF (BUILD_BENCHMARKS) target_link_libraries(shogun_benchmark_main benchmark::benchmark shogun-static) elseif(MSVC) target_link_libraries(shogun_benchmark_main - benchmark::benchmark - Shlwapi.lib - shogun-static - ) + benchmark::benchmark + Shlwapi.lib + shogun-static + ) else() target_link_libraries(shogun_benchmark_main - benchmark::benchmark - pthread - shogun-static - ) + benchmark::benchmark + pthread + shogun-static + ) endif() set(SHOGUN_BENCHMARK_LINK_LIBS shogun_benchmark_main) @@ -602,15 +603,15 @@ IF (LICENSE_GPL_SHOGUN) ENDIF() INSTALL( - DIRECTORY ${INCLUDE_HEADERS_DIR_LIST} - DESTINATION ${INCLUDE_INSTALL_DIR} - COMPONENT headers - FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp" - PATTERN "CMakeFiles*" EXCLUDE - PATTERN "*.dir" EXCLUDE - PATTERN "*Debug*" EXCLUDE - PATTERN "*Release*" EXCLUDE - PATTERN ".settings" EXCLUDE) + DIRECTORY ${INCLUDE_HEADERS_DIR_LIST} + DESTINATION ${INCLUDE_INSTALL_DIR} + COMPONENT headers + FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp" + PATTERN "CMakeFiles*" EXCLUDE + PATTERN "*.dir" EXCLUDE + PATTERN "*Debug*" EXCLUDE + PATTERN "*Release*" EXCLUDE + PATTERN ".settings" EXCLUDE) # set the desidered targets to be installed set(INSTALL_TARGETS shogun) @@ -619,41 +620,41 @@ if (LIBSHOGUN_BUILD_STATIC) endif() INSTALL( - TARGETS ${INSTALL_TARGETS} - EXPORT ShogunTargets - ARCHIVE DESTINATION ${SHOGUN_LIB_INSTALL} - RUNTIME DESTINATION ${SHOGUN_LIB_INSTALL} - LIBRARY DESTINATION ${SHOGUN_LIB_INSTALL} - INCLUDES DESTINATION ${INCLUDE_INSTALL_DIR} + TARGETS ${INSTALL_TARGETS} + EXPORT ShogunTargets + ARCHIVE DESTINATION ${SHOGUN_LIB_INSTALL} + RUNTIME DESTINATION ${SHOGUN_LIB_INSTALL} + LIBRARY DESTINATION ${SHOGUN_LIB_INSTALL} + INCLUDES DESTINATION ${INCLUDE_INSTALL_DIR} ) file(TO_CMAKE_PATH ${SHOGUN_LIB_INSTALL}/cmake/shogun CONFIG_PACKAGE_DIR) configure_package_config_file( - ${CMAKE_SOURCE_DIR}/cmake/ShogunConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/ShogunConfig.cmake - INSTALL_DESTINATION ${SHOGUN_LIB_INSTALL}/cmake/shogun - PATH_VARS INCLUDE_INSTALL_DIR CONFIG_PACKAGE_DIR) + ${CMAKE_SOURCE_DIR}/cmake/ShogunConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/ShogunConfig.cmake + INSTALL_DESTINATION ${SHOGUN_LIB_INSTALL}/cmake/shogun + PATH_VARS INCLUDE_INSTALL_DIR CONFIG_PACKAGE_DIR) write_basic_package_version_file( - "${CMAKE_CURRENT_BINARY_DIR}/ShogunConfigVersion.cmake" - VERSION ${VERSION} - COMPATIBILITY SameMajorVersion + "${CMAKE_CURRENT_BINARY_DIR}/ShogunConfigVersion.cmake" + VERSION ${VERSION} + COMPATIBILITY SameMajorVersion ) export(EXPORT ShogunTargets - FILE "${CMAKE_CURRENT_BINARY_DIR}/ShogunTargets.cmake" - NAMESPACE shogun:: -) + FILE "${CMAKE_CURRENT_BINARY_DIR}/ShogunTargets.cmake" + NAMESPACE shogun:: + ) install( - EXPORT ShogunTargets - FILE ShogunTargets.cmake - NAMESPACE shogun:: - DESTINATION ${CONFIG_PACKAGE_DIR} + EXPORT ShogunTargets + FILE ShogunTargets.cmake + NAMESPACE shogun:: + DESTINATION ${CONFIG_PACKAGE_DIR} ) install( - FILES - "${CMAKE_CURRENT_BINARY_DIR}/ShogunConfig.cmake" - "${CMAKE_CURRENT_BINARY_DIR}/ShogunConfigVersion.cmake" - DESTINATION ${CONFIG_PACKAGE_DIR} -) + FILES + "${CMAKE_CURRENT_BINARY_DIR}/ShogunConfig.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/ShogunConfigVersion.cmake" + DESTINATION ${CONFIG_PACKAGE_DIR} +) \ No newline at end of file diff --git a/src/shogun/io/OpenMLFlow.cpp b/src/shogun/io/OpenMLFlow.cpp new file mode 100644 index 00000000000..505869d6789 --- /dev/null +++ b/src/shogun/io/OpenMLFlow.cpp @@ -0,0 +1,187 @@ +/* + * This software is distributed under BSD 3-clause license (see LICENSE file). + * + * Authors: Gil Hoben + */ + +#include + +#ifdef HAVE_CURL + +using namespace shogun; +using namespace rapidjson; + +size_t writer(char* data, size_t size, size_t nmemb, std::string* buffer_in) +{ + // adapted from https://stackoverflow.com/a/5780603 + // Is there anything in the buffer? + if (buffer_in->empty()) + { + // Append the data to the buffer + buffer_in->append(data, size * nmemb); + + return size * nmemb; + } + + return 0; +} + +const char* OpenMLReader::xml_server = "https://www.openml.org/api/v1/xml"; +const char* OpenMLReader::json_server = "https://www.openml.org/api/v1/json"; +const char* OpenMLReader::dataset_description = "/data/{}"; +const char* OpenMLReader::list_data_qualities = "/data/qualities/list"; +const char* OpenMLReader::data_features = "/data/features/{}"; +const char* OpenMLReader::list_dataset_qualities = "/data/qualities/{}"; +const char* OpenMLReader::list_dataset_filter = "/data/list/{}"; +const char* OpenMLReader::flow_file = "/flow/{}"; + +const std::unordered_map + OpenMLReader::m_format_options = {{"xml", xml_server}, + {"json", json_server}}; +const std::unordered_map + OpenMLReader::m_request_options = { + {"dataset_description", dataset_description}, + {"list_data_qualities", list_data_qualities}, + {"data_features", data_features}, + {"list_dataset_qualities", list_dataset_qualities}, + {"list_dataset_filter", list_dataset_filter}, + {"flow_file", flow_file}}; + +OpenMLReader::OpenMLReader(const std::string& api_key) : m_api_key(api_key) +{ +} + +void OpenMLReader::openml_curl_request_helper(const std::string& url) +{ + CURL* curl_handle = nullptr; + + curl_handle = curl_easy_init(); + + if (!curl_handle) + { + SG_SERROR("Failed to initialise curl handle.") + return; + } + + curl_easy_setopt(curl_handle, CURLOPT_URL, url.c_str()); + curl_easy_setopt(curl_handle, CURLOPT_HTTPGET, 1); + curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, writer); + curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &m_curl_response_buffer); + + CURLcode res = curl_easy_perform(curl_handle); + + openml_curl_error_helper(curl_handle, res); + + curl_easy_cleanup(curl_handle); +} + +void OpenMLReader::openml_curl_error_helper(CURL* curl_handle, CURLcode code) +{ + if (code != CURLE_OK) + { + // TODO: call curl_easy_cleanup(curl_handle) ? + SG_SERROR("Curl error: %s\n", curl_easy_strerror(code)) + } +// else +// { +// long response_code; +// curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &response_code); + // if (response_code == 200) + // return; + // else + // { + // if (response_code == 181) + // SG_SERROR("Unknown flow. The flow with the given ID was not + //found in the database.") else if (response_code == 180) SG_SERROR("") + // SG_SERROR("Server code: %d\n", response_code) + // } +// } +} + +std::shared_ptr +OpenMLFlow::download_flow(const std::string& flow_id, const std::string& api_key) +{ + Document document; + parameters_type params; + components_type components; + std::string name; + std::string description; + std::string class_name; + + // get flow and parse with RapidJSON + auto reader = OpenMLReader(api_key); + auto return_string = reader.get("flow_file", "json", flow_id); + document.Parse(return_string.c_str()); + check_flow_response(document); + + // store root for convenience. We know it exists from previous check. + const Value& root = document["flow"]; + + // handle parameters + if (root.HasMember("parameter")) + { + std::unordered_map param_dict; + + if (root["parameter"].IsArray()) + { + for (const auto &v : root["parameter"].GetArray()) { + emplace_string_to_map(v, param_dict, "data_type"); + emplace_string_to_map(v, param_dict, "default_value"); + emplace_string_to_map(v, param_dict, "description"); + params.emplace(v["name"].GetString(), param_dict); + param_dict.clear(); + } + } + else + { + // parameter can also be a dict, instead of array + const auto v = root["parameter"].GetObject(); + emplace_string_to_map(v, param_dict, "data_type"); + emplace_string_to_map(v, param_dict, "default_value"); + emplace_string_to_map(v, param_dict, "description"); + params.emplace(v["name"].GetString(), param_dict); + } + } + + // handle components, i.e. kernels + if (root.HasMember("component")) + { + for (const auto& v : root["component"].GetArray()) + { + components.emplace( + v["identifier"].GetString(), + OpenMLFlow::download_flow(v["flow"]["id"].GetString(), api_key)); + } + } + + // get remaining information from flow + if (root.HasMember("name")) + name = root["name"].GetString(); + if (root.HasMember("description")) + description = root["description"].GetString(); + if (root.HasMember("class_name")) + class_name = root["class_name"].GetString(); + + auto flow = std::make_shared(name, description, class_name, components, params); + + return flow; +} + +void OpenMLFlow::check_flow_response(Document& doc) +{ + if (SG_UNLIKELY(doc.HasMember("error"))) + { + const Value& root = doc["error"]; + SG_SERROR( + "Server error %s: %s\n", root["code"].GetString(), + root["message"].GetString()) + return; + } + REQUIRE(doc.HasMember("flow"), "Unexpected format of OpenML flow.\n"); +} + +void OpenMLFlow::upload_flow(const std::shared_ptr& flow) +{ +} + +#endif // HAVE_CURL diff --git a/src/shogun/io/OpenmlFlow.h b/src/shogun/io/OpenMLFlow.h similarity index 59% rename from src/shogun/io/OpenmlFlow.h rename to src/shogun/io/OpenMLFlow.h index 6787df3e252..dee68423269 100644 --- a/src/shogun/io/OpenmlFlow.h +++ b/src/shogun/io/OpenMLFlow.h @@ -7,16 +7,22 @@ #ifndef SHOGUN_OPENMLFLOW_H #define SHOGUN_OPENMLFLOW_H +#include + #ifdef HAVE_CURL +#include #include #include +#include + +#include +#include #include #include #include #include -#include namespace shogun { @@ -90,10 +96,7 @@ namespace shogun return m_curl_response_buffer; } - void post(const std::string& request, const std::string& data); - private: - std::string m_curl_response_buffer; /** @@ -107,9 +110,10 @@ namespace shogun /** * Handles all possible codes * + * @param curl_handle curl handle used in the request * @param code the code returned by the query */ - void openml_curl_error_helper(CURLcode code); + void openml_curl_error_helper(CURL* curl_handle, CURLcode code); std::string m_api_key; @@ -132,21 +136,85 @@ namespace shogun static const char* flow_file; }; + class OpenMLWritter + { + public: + OpenMLWritter(const std::string& api_key) : m_api_key(api_key){}; + + private: + std::string m_api_key; + }; + class OpenMLFlow { public: - explicit OpenMLFlow( - const std::string& api_key, const std::string& flow_id) - : m_api_key(api_key), m_flow_id(flow_id){}; + using components_type = + std::unordered_map>; + using parameters_type = std::unordered_map< + std::string, std::unordered_map>; + + OpenMLFlow( + const std::string& name, const std::string& description, + const std::string& model, components_type components, + parameters_type parameters) + : m_name(name), m_description(description), m_class_name(model), + m_parameters(parameters), m_components(components) + { + } + + ~OpenMLFlow()= default; - void download_flow(); + static std::shared_ptr + download_flow(const std::string& flow_id, const std::string& api_key); - static void upload_flow(const OpenMLFlow& flow); + static void upload_flow(const std::shared_ptr& flow); + + std::shared_ptr get_subflow(const std::string& name) + { + auto find_flow = m_components.find(name); + if (find_flow != m_components.end()) + return find_flow->second; + else + SG_SERROR( + "The provided subflow could not be found in this flow!") + return nullptr; + } private: - std::string m_api_key; - std::string m_flow_id; + std::string m_name; + std::string m_description; + std::string m_class_name; + parameters_type m_parameters; + components_type m_components; + +#ifndef SWIG + static void check_flow_response(rapidjson::Document& doc); + + static SG_FORCED_INLINE void emplace_string_to_map( + const rapidjson::GenericValue>& v, + std::unordered_map& param_dict, + const std::string& name) + { + if (v[name.c_str()].GetType() == rapidjson::Type::kStringType) + param_dict.emplace(name, v[name.c_str()].GetString()); + else + param_dict.emplace(name, ""); + } + + static SG_FORCED_INLINE void emplace_string_to_map( + const rapidjson::GenericObject< + true, rapidjson::GenericValue>>& v, + std::unordered_map& param_dict, + const std::string& name) + { + if (v[name.c_str()].GetType() == rapidjson::Type::kStringType) + param_dict.emplace(name, v[name.c_str()].GetString()); + else + param_dict.emplace(name, ""); + } + +#endif // SWIG }; } // namespace shogun #endif // HAVE_CURL diff --git a/src/shogun/io/OpenmlFlow.cpp b/src/shogun/io/OpenmlFlow.cpp deleted file mode 100644 index f9cdb19af00..00000000000 --- a/src/shogun/io/OpenmlFlow.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* - * This software is distributed under BSD 3-clause license (see LICENSE file). - * - * Authors: Gil Hoben - */ - -#ifdef HAVE_CURL - -#include -#include "OpenmlFlow.h" - - -using namespace shogun; - -size_t writer(char *data, size_t size, size_t nmemb, std::string* buffer_in) -{ - // adapted from https://stackoverflow.com/a/5780603 - // Is there anything in the buffer? - if (buffer_in->empty()) - { - // Append the data to the buffer - buffer_in->append(data, size * nmemb); - - return size * nmemb; - } - - return 0; -} - -const char* OpenMLReader::xml_server = "https://www.openml.org/api/v1/xml"; -const char* OpenMLReader::json_server = "https://www.openml.org/api/v1/json"; -const char* OpenMLReader::dataset_description = "/data/{}"; -const char* OpenMLReader::list_data_qualities = "/data/qualities/list"; -const char* OpenMLReader::data_features = "/data/features/{}"; -const char* OpenMLReader::list_dataset_qualities = "/data/qualities/{}"; -const char* OpenMLReader::list_dataset_filter = "/data/list/{}"; -const char* OpenMLReader::flow_file = "/flow/{}"; - -const std::unordered_map - OpenMLReader::m_format_options = {{"xml", xml_server}, - {"json", json_server}}; -const std::unordered_map - OpenMLReader::m_request_options = { - - {"dataset_description", dataset_description}, - {"list_data_qualities", list_data_qualities}, - {"data_features", data_features}, - {"list_dataset_qualities", list_dataset_qualities}, - {"list_dataset_filter", list_dataset_filter}, - {"flow_file", flow_file}}; - -OpenMLReader::OpenMLReader(const std::string& api_key) : m_api_key(api_key) -{ -} - -void OpenMLReader::post(const std::string& request, const std::string& data) -{ -} - -void OpenMLReader::openml_curl_request_helper(const std::string& url) -{ - CURL* curl_handle = nullptr; - - curl_handle = curl_easy_init(); - - if (!curl_handle) - { - SG_SERROR("Failed to initialise curl handle.") - return; - } - - curl_easy_setopt(curl_handle, CURLOPT_URL, url.c_str()); - curl_easy_setopt(curl_handle, CURLOPT_HTTPGET,1); - curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, writer); - curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &m_curl_response_buffer); - - CURLcode res = curl_easy_perform(curl_handle); - - openml_curl_error_helper(res); - - curl_easy_cleanup(curl_handle); -} - -void OpenMLReader::openml_curl_error_helper(CURLcode code) { - -} - - -void OpenMLFlow::download_flow() -{ - - auto reader = OpenMLReader(m_api_key); - auto return_string = reader.get("flow_file", "json", m_flow_id); -} - -void OpenMLFlow::upload_flow(const OpenMLFlow& flow) -{ -} - -#endif // HAVE_CURL