From 0a967d71e5fd14d80b350b58330c16c7c8507e6b Mon Sep 17 00:00:00 2001 From: Thomas Purcell <purcell@fhi-berlin.mpg.de> Date: Thu, 15 Oct 2020 15:17:57 +0200 Subject: [PATCH] Upadated parameterization Parameters now go down the tree not just the initial feature --- CMakeLists.txt | 143 +-- src/CMakeLists.txt | 17 +- .../SISSO_DI/SISSORegressor.cpp | 4 + src/feature_creation/domain/Domain.cpp | 6 +- src/feature_creation/domain/Domain.hpp | 29 +- .../feature_space/FeatureSpace.cpp | 44 +- .../feature_space/FeatureSpace.hpp | 16 +- src/feature_creation/node/FeatureNode.cpp | 3 + src/feature_creation/node/FeatureNode.hpp | 61 +- src/feature_creation/node/Node.hpp | 63 +- .../node/operator_nodes/OperatorNode.hpp | 162 +-- .../abs/absolute_value.cpp | 42 + .../abs/absolute_value.hpp | 90 +- .../abs/parameterize.cpp | 208 ---- .../abs/parameterized_absolute_value.cpp | 65 ++ .../abs/parameterized_absolute_value.hpp | 153 +++ .../abs_diff/absolute_difference.cpp | 11 +- .../abs_diff/absolute_difference.hpp | 96 +- .../abs_diff/parameterize.cpp | 212 ---- .../parameterized_absolute_difference.cpp | 65 ++ .../parameterized_absolute_difference.hpp | 153 +++ .../allowed_operator_nodes/add/add.cpp | 9 + .../allowed_operator_nodes/add/add.hpp | 95 +- .../add/parameterize.cpp | 105 -- .../add/parameterized_add.cpp | 65 ++ .../add/parameterized_add.hpp | 151 +++ .../allowed_operator_nodes/cb/cube.cpp | 10 + .../allowed_operator_nodes/cb/cube.hpp | 96 +- .../cb/parameterize.cpp | 105 -- .../cb/parameterized_cube.cpp | 67 ++ .../cb/parameterized_cube.hpp | 153 +++ .../allowed_operator_nodes/cbrt/cube_root.cpp | 10 + .../allowed_operator_nodes/cbrt/cube_root.hpp | 96 +- .../cbrt/parameterize.cpp | 113 --- .../cbrt/parameterized_cube_root.cpp | 75 ++ .../cbrt/parameterized_cube_root.hpp | 153 +++ .../allowed_operator_nodes/cos/cos.cpp | 26 + .../allowed_operator_nodes/cos/cos.hpp | 88 +- .../cos/parameterize.cpp | 214 ---- .../cos/parameterized_cos.cpp | 67 ++ .../cos/parameterized_cos.hpp | 153 +++ .../allowed_operator_nodes/div/divide.cpp | 8 + .../allowed_operator_nodes/div/divide.hpp | 96 +- .../div/parameterize.cpp | 113 --- .../div/parameterized_divide.cpp | 74 ++ .../div/parameterized_divide.hpp | 151 +++ .../exp/exponential.cpp | 10 + .../exp/exponential.hpp | 95 +- .../exp/parameterize.cpp | 105 -- .../exp/parameterized_exponential.cpp | 65 ++ .../exp/parameterized_exponential.hpp | 153 +++ .../allowed_operator_nodes/inv/inverse.cpp | 10 + .../allowed_operator_nodes/inv/inverse.hpp | 97 +- .../inv/parameterize.cpp | 113 --- .../inv/parameterized_inverse.cpp | 75 ++ .../inv/parameterized_inverse.hpp | 153 +++ .../allowed_operator_nodes/log/log.cpp | 14 +- .../allowed_operator_nodes/log/log.hpp | 96 +- .../log/parameterize.cpp | 113 --- .../log/parameterized_log.cpp | 75 ++ .../log/parameterized_log.hpp | 153 +++ .../allowed_operator_nodes/mult/multiply.cpp | 9 + .../allowed_operator_nodes/mult/multiply.hpp | 93 +- .../mult/parameterize.cpp | 34 - .../mult/parameterized_multiply.cpp | 67 ++ .../mult/parameterized_multiply.hpp | 151 +++ .../neg_exp/negative_exponential.cpp | 14 +- .../neg_exp/negative_exponential.hpp | 96 +- .../neg_exp/parameterize.cpp | 105 -- .../parameterized_negative_exponential.cpp | 67 ++ .../parameterized_negative_exponential.hpp | 153 +++ .../sin/parameterize.cpp | 214 ---- .../sin/parameterized_sin.cpp | 69 ++ .../sin/parameterized_sin.hpp | 153 +++ .../allowed_operator_nodes/sin/sin.cpp | 14 +- .../allowed_operator_nodes/sin/sin.hpp | 93 +- .../six_pow/parameterize.cpp | 105 -- .../six_pow/parameterized_sixth_power.cpp | 69 ++ .../six_pow/parameterized_sixth_power.hpp | 153 +++ .../six_pow/sixth_power.cpp | 10 + .../six_pow/sixth_power.hpp | 95 +- .../sq/parameterize.cpp | 105 -- .../sq/parameterized_square.cpp | 69 ++ .../sq/parameterized_square.hpp | 153 +++ .../allowed_operator_nodes/sq/square.cpp | 10 + .../allowed_operator_nodes/sq/square.hpp | 95 +- .../sqrt/parameterize.cpp | 119 --- .../sqrt/parameterized_square_root.cpp | 75 ++ .../sqrt/parameterized_square_root.hpp | 153 +++ .../sqrt/square_root.cpp | 10 + .../sqrt/square_root.hpp | 95 +- .../sub/parameterize.cpp | 105 -- .../sub/parameterized_subtract.cpp | 67 ++ .../sub/parameterized_subtract.hpp | 151 +++ .../allowed_operator_nodes/sub/subtract.cpp | 9 + .../allowed_operator_nodes/sub/subtract.hpp | 95 +- .../node/operator_nodes/allowed_ops.hpp | 21 +- .../operator_nodes/allowed_parameter_ops.cpp | 34 +- .../value_storage/nodes_value_containers.cpp | 8 +- .../value_storage/nodes_value_containers.hpp | 4 +- .../parameterization/NLOptWrapper.cpp | 22 + .../parameterization/NLOptWrapper.hpp | 49 + src/inputs/InputParser.cpp | 25 +- src/inputs/InputParser.hpp | 2 +- src/main.cpp | 8 +- src/python/_sisso.cpp | 11 - src/python/bindings.cpp | 919 ++++++++++++++++++ src/python/bindings.hpp | 378 +++++++ src/python/bindings_docstring_keyed.cpp | 573 +++++++++-- src/python/bindings_docstring_keyed.hpp | 128 ++- src/python/feature_creation/FeatureSpace.cpp | 20 +- .../test_classification.py | 11 +- .../test_regressor.py | 2 +- .../test_feature_space/test_feature_space.py | 2 +- tests/test_param.py | 6 +- tests/test_sisso.py | 2 +- 116 files changed, 7398 insertions(+), 3165 deletions(-) delete mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs/parameterize.cpp create mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs/parameterized_absolute_value.cpp create mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs/parameterized_absolute_value.hpp delete mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/parameterize.cpp create mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/parameterized_absolute_difference.cpp create mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/parameterized_absolute_difference.hpp delete mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/add/parameterize.cpp create mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/add/parameterized_add.cpp create mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/add/parameterized_add.hpp delete mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/cb/parameterize.cpp create mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/cb/parameterized_cube.cpp create mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/cb/parameterized_cube.hpp delete mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/parameterize.cpp create mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/parameterized_cube_root.cpp create mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/parameterized_cube_root.hpp delete mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos/parameterize.cpp create mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos/parameterized_cos.cpp create mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos/parameterized_cos.hpp delete mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/div/parameterize.cpp create mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/div/parameterized_divide.cpp create mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/div/parameterized_divide.hpp delete mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/exp/parameterize.cpp create mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/exp/parameterized_exponential.cpp create mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/exp/parameterized_exponential.hpp delete mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/inv/parameterize.cpp create mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/inv/parameterized_inverse.cpp create mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/inv/parameterized_inverse.hpp delete mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/log/parameterize.cpp create mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/log/parameterized_log.cpp create mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/log/parameterized_log.hpp delete mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/mult/parameterize.cpp create mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/mult/parameterized_multiply.cpp create mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/mult/parameterized_multiply.hpp delete mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/neg_exp/parameterize.cpp create mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/neg_exp/parameterized_negative_exponential.cpp create mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/neg_exp/parameterized_negative_exponential.hpp delete mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin/parameterize.cpp create mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin/parameterized_sin.cpp create mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin/parameterized_sin.hpp delete mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/six_pow/parameterize.cpp create mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/six_pow/parameterized_sixth_power.cpp create mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/six_pow/parameterized_sixth_power.hpp delete mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/sq/parameterize.cpp create mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/sq/parameterized_square.cpp create mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/sq/parameterized_square.hpp delete mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/sqrt/parameterize.cpp create mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/sqrt/parameterized_square_root.cpp create mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/sqrt/parameterized_square_root.hpp delete mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/sub/parameterize.cpp create mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/sub/parameterized_subtract.cpp create mode 100644 src/feature_creation/node/operator_nodes/allowed_operator_nodes/sub/parameterized_subtract.hpp create mode 100644 src/feature_creation/parameterization/NLOptWrapper.cpp create mode 100644 src/feature_creation/parameterization/NLOptWrapper.hpp create mode 100644 src/python/bindings.cpp create mode 100644 src/python/bindings.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1ba1d988..dc9d9d95 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -286,134 +286,29 @@ set(MPI_LIBRARIES, ${MPI_CXX_LIBRARIES}) list(GET MPI_CXX_LIBRARIES 0 MPI_LIBRARY) get_filename_component(MPI_DIR ${MPI_LIBRARY} DIRECTORY) -# Find Ceres +# Find NL Opt if(USE_PARAMS) - find_package(Eigen) - if(NOT EIGEN_FOUND) - set(EIGEN_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/external/eigen/build/") - set(EIGEN_INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/external/eigen/bin/") - set(EIGEN_INCLUDE_DIRS "${EIGEN_INSTALL_DIR}/include/eigen3") - - ExternalProject_Add( - external_eigen - PREFIX "external/eigen" - GIT_REPOSITORY "https://gitlab.com/libeigen/eigen.git" - GIT_TAG "3.3.7" - CMAKE_ARGS "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER};-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER};-DCMAKE_INSTALL_PREFIX=${EIGEN_INSTALL_DIR};-DINCLUDE_INSTALL_DIR=${EIGEN_INCLUDE_DIRS};" - BINARY_DIR "${EIGEN_BUILD_DIR}" - INSTALL_DIR "${EIGEN_INSTALL_DIR}" - ) - endif() - include_directories(${EIGEN_INCLUDE_DIRS}) - - find_package(Gflags) - if(NOT GFLAGS_FOUND) - set(GFLAGS_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/external/gflags/bin/") - set(GFLAGS_INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/external/gflags/bin/") - set(GFLAGS_INCLUDE_DIRS "${GFLAGS_INSTALL_DIR}/include") - set(GFLAGS_LIBRARY_DIRS "${GFLAGS_INSTALL_DIR}/lib") - - ExternalProject_Add( - external_gflags - PREFIX "external/gflags" - GIT_REPOSITORY "https://github.com/gflags/gflags.git" - GIT_TAG "v2.2.2" - CMAKE_ARGS "-DCMAKE_INSTALL_PREFIX=${GFLAGS_INSTALL_DIR};-DBUILD_SHARED_LIBS=ON;-DGFLAGS_NAMESPACE=google;-DINSTALL_HEADERS=ON" - BINARY_DIR "${GFLAGS_BUILD_DIR}" - INSTALL_DIR "${GFLAGS_INSTALL_DIR}" - INSTALL_COMMAND "" - ) - add_library( Gflags SHARED IMPORTED ) - set_property( TARGET Gflags PROPERTY IMPORTED_LOCATION ${GLOG_LIBRARY_DIRS}/libgflags.so ) - set_property( TARGET Gflags PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${GLOG_INCLUDE_DIRS} ) - add_dependencies(Gflags external_gflags) - set(GFLAG_LIBRARIES "${GFLAGS_LIBRARY_DIRS}/libgflags.so") - else() - list(GET GFLAG_LIBRARIES 0 GFLAGS_LIBRARY) - get_filename_component(GFLAGS_LIBRARY_DIRS ${GFLAGS_LIBRARY} DIRECTORY) - endif() - - include_directories("${GFLAGS_INCLUDE_DIRS}") - # find_package(Glog) - # if(NOT GLOG_FOUND) - set(GLOG_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/external/glog/build/") - set(GLOG_INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/external/glog/bin/") - set(GLOG_BIN_DIRS "${GLOG_INSTALL_DIR}/bin") - set(GLOG_INCLUDE_DIRS "${GLOG_INSTALL_DIR}/include") - set(GLOG_LIBRARY_DIRS "${GLOG_INSTALL_DIR}/lib") - set(GLOG_CMAKE_ARGS "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}") - list(APPEND GLOG_CMAKE_ARGS "-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}") - list(APPEND GLOG_CMAKE_ARGS "-DWITH_GFLAGS=ON") - list(APPEND GLOG_CMAKE_ARGS "-DBUILD_SHARED_LIBS=ON") - list(APPEND GLOG_CMAKE_ARGS "-DCMAKE_INSTALL_BINDIR=${GLOG_BIN_DIRS}") - list(APPEND GLOG_CMAKE_ARGS "-DCMAKE_INSTALL_INCLUDEDIR=${GLOG_INCLUDE_DIRS}") - list(APPEND GLOG_CMAKE_ARGS "-DCMAKE_INSTALL_LIBDIR=${GLOG_LIBRARY_DIRS}") - list(APPEND GLOG_CMAKE_ARGS "-DWITH_UNWIND=OFF") + set(NLOPT_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/external/nlopt/build/") + set(NLOPT_INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/external/nlopt/bin/") + set(NLOPT_INCLUDE_DIRS "${NLOPT_INSTALL_DIR}/include/") + set(NLOPT_LIBRARY_DIRS "${NLOPT_INSTALL_DIR}/lib/") ExternalProject_Add( - external_glog - PREFIX "external/glog" - GIT_REPOSITORY "https://github.com/google/glog.git" - GIT_TAG "v0.4.0" - CMAKE_ARGS "${GLOG_CMAKE_ARGS}" - BINARY_DIR "${GLOG_BUILD_DIR}" - INSTALL_DIR "${GLOG_INSTALL_DIR}" + external_nlopt + PREFIX "external/nlopt" + GIT_REPOSITORY "https://github.com/stevengj/nlopt.git" + GIT_TAG "v2.6.2" + CMAKE_ARGS "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER};-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER};-DCMAKE_INSTALL_PREFIX=${NLOPT_INSTALL_DIR};" + BINARY_DIR "${NLOPT_BUILD_DIR}" + INSTALL_DIR "${NLOPT_INSTALL_DIR}" ) - add_dependencies(external_glog Gflags) - add_library( glog SHARED IMPORTED ) - set_property( TARGET glog PROPERTY IMPORTED_LOCATION ${GLOG_LIBRARY_DIRS}/libglog.so ) - set_property( TARGET glog PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${GLOG_INCLUDE_DIRS} ) - add_dependencies(glog external_glog) - set(GLOG_LIBRARIES "${GLOG_LIBRARY_DIRS}/libglog.so") - # endif() - - include_directories(${GLOG_INCLUDE_DIRS}) - - set(CERES_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/external/ceres/build/") - set(CERES_INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/external/ceres/bin/") - set(CERES_INCLUDE_DIRS "${CERES_INSTALL_DIR}include") - set(CERES_LIBRARY_DIRS "${CERES_INSTALL_DIR}lib") - set(CERES_CMAKE_ARGS "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}") - list(APPEND CERES_CMAKE_ARGS "-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}") - list(APPEND CERES_CMAKE_ARGS "-DCMAKE_INSTALL_PREFIX=${CERES_INSTALL_DIR}") - list(APPEND CERES_CMAKE_ARGS "-DGFLAGS=ON") - list(APPEND CERES_CMAKE_ARGS "-DMINIGLOG=OFF") - list(APPEND CERES_CMAKE_ARGS "-DBUILD_SHARED_LIBS=ON") - list(APPEND CERES_CMAKE_ARGS "-DSUITESPARSE=OFF") - list(APPEND CERES_CMAKE_ARGS "-DCXSPARSE=OFF") - list(APPEND CERES_CMAKE_ARGS "-DEIGENSPARSE=OFF") - list(APPEND CERES_CMAKE_ARGS "-DEIGEN_INCLUDE_DIR_HINTS=${EIGEN_INCLUDE_DIRS}") - list(APPEND CERES_CMAKE_ARGS "-DGLOG_INCLUDE_DIR_HINTS=${GLOG_INCLUDE_DIRS}") - list(APPEND CERES_CMAKE_ARGS "-DGLOG_LIBRARY_DIR_HINTS=${GLOG_LIBRARY_DIRS}") - list(APPEND CERES_CMAKE_ARGS "-DGFLAGS_INCLUDE_DIR_HINTS=${GFLAGS_INCLUDE_DIRS}") - list(APPEND CERES_CMAKE_ARGS "-DGFLAGS_LIBRARY_DIR_HINTS=${GFLAGS_LIBRARY_DIRS}") - list(APPEND CERES_CMAKE_ARGS "-DLIB_SUFFIX=''") - list(APPEND CERES_CMAKE_ARGS "-DBUILD_TESTING=OFF") - list(APPEND CERES_CMAKE_ARGS "-DBUILD_EXAMPLES=OFF") - ExternalProject_Add( - external_ceres - PREFIX "external/ceres" - GIT_REPOSITORY "https://ceres-solver.googlesource.com/ceres-solver.git" - GIT_TAG "1.14.0" - CMAKE_ARGS "${CERES_CMAKE_ARGS}" - BINARY_DIR "${CERES_BUILD_DIR}" - ) - # if(NOT GFLAGS_FOUND) - add_dependencies(external_ceres Gflags) - # endif() - if(NOT GLOG_FOUND) - add_dependencies(external_ceres glog) - endif() - if(NOT EIGEN_FOUND) - add_dependencies(external_ceres external_eigen) - endif() - message(STATUS "CERES_LIBRARY_DIRS: ${CERES_LIBRARY_DIRS}") - add_library( ceres SHARED IMPORTED ) - set_property( TARGET ceres PROPERTY IMPORTED_LOCATION "${CERES_LIBRARY_DIRS}/libceres.so" ) - set_property( TARGET ceres PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CERES_INCLUDE_DIRS}" ) - add_dependencies(ceres external_ceres) - set(CERES_LIBRARIES "${CERES_LIBRARY_DIRS}/libceres.so;${GLOG_LIBRARIES};${GFLAG_LIBRARIES}") - include_directories(${CERES_INCLUDE_DIRS}) + include_directories(${NLOPT_INCLUDE_DIRS}) + add_library( nlopt SHARED IMPORTED ) + set_property(TARGET nlopt PROPERTY IMPORTED_LOCATION ${NLOPT_LIBRARY_DIRS}/libnlopt.so ) + set_property(TARGET nlopt PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${NLOPT_INCLUDE_DIRS} ) + ExternalProject_Add_StepDependencies(external_nlopt nlopt) + + set(NLOPT_LIBRARIES "${NLOPT_LIBRARY_DIRS}/libnlopt.so") endif() # Coin-Clp for linear programing diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3ae9a7b0..9682a2fa 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,9 +3,9 @@ include_directories(${CMAKE_CURRENT_LIST_DIR}) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated-declarations") -set(CMAKE_INSTALL_RPATH ${Boost_LIBRARY_DIRS};${LAPACK_DIR};${MPI_DIR}) +set(CMAKE_INSTALL_RPATH ${Boost_LIBRARY_DIRS};${LAPACK_DIR};${MPI_DIR};${COIN_CLP_LIBRARY_DIRS}) if(USE_PARAMS) - list(APPEND CMAKE_INSTALL_RPATH ${CERES_LIBRARY_DIRS};${GLOG_LIBRARY_DIRS};${GFLAGS_LIBRARY_DIRS};${COIN_CLP_LIBRARY_DIRS}) + list(APPEND CMAKE_INSTALL_RPATH ${NLOPT_LIBRARY_DIRS}) endif() message(STATUS("CMAKE_INSTALL_RPATH = ${CMAKE_INSTALL_RPATH}")) @@ -33,19 +33,14 @@ set_target_properties(sisso++ LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" ) -# add_dependencies(sisso++ ceres) -message(STATUS "CERES_LIBRARIES = ${CERES_LIBRARIES}") -message(STATUS "CERES_LIBRARY_DIRS = ${CERES_LIBRARY_DIRS}") -target_link_libraries(sisso++ ${LAPACK_LIBRARIES} ${MPI_LIBRARIES} ${Boost_LIBRARIES} ${CERES_LIBRARIES}) - -target_link_libraries(sisso++ ${LAPACK_LIBRARIES} ${MPI_LIBRARIES} -Wl,--rpath=${Boost_LIB_DIR} -Wl,--rpath=${LAPACK_DIR} ${Boost_LIBRARIES} ${COIN_CLP_LIBRARIES}) +target_link_libraries(sisso++ ${LAPACK_LIBRARIES} ${MPI_LIBRARIES} -Wl,--rpath=${Boost_LIB_DIR} -Wl,--rpath=${LAPACK_DIR} ${Boost_LIBRARIES} ${COIN_CLP_LIBRARIES} ${NLOPT_LIBRARIES}) install(TARGETS sisso++ DESTINATION ${CMAKE_CURRENT_LIST_DIR}/../bin/) if(USE_PYTHON) include(${CMAKE_CURRENT_LIST_DIR}/../cmake/TransferDocStrings.cmake) - set(CMAKE_INSTALL_RPATH "${Boost_LIBRARY_DIRS};${PYTHON_PREFIX}/lib/;${MPI_DIR};${GLOG_LIBRARY_DIRS};${GFLAGS_LIBRARY_DIRS};${COIN_CLP_LIBRARY_DIRS}") + set(CMAKE_INSTALL_RPATH "${Boost_LIBRARY_DIRS};${PYTHON_PREFIX}/lib/;${MPI_DIR};${COIN_CLP_LIBRARY_DIRS}") if(USE_PARAMS) - list(APPEND CMAKE_INSTALL_RPATH ${CERES_LIBRARY_DIRS};${GLOG_LIBRARY_DIRS}) + list(APPEND CMAKE_INSTALL_RPATH ${NLOPT_LIBRARY_DIRS}) endif() message(STATUS "CMAKE_INSTALL_RPATH = ${CMAKE_INSTALL_RPATH}") @@ -78,7 +73,7 @@ if(USE_PYTHON) SUFFIX ".so" ) - target_link_libraries(_sisso ${MPI_LIBRARIES} -Wl,--rpath=${CERES_LIBRARY_DIRS} -Wl,--rpath=${PYTHON_PREFIX}/lib/ ${LAPACK_LIBRARIES} ${PYTHON_LIBRARIES} -Wl,--rpath=${Boost_LIB_DIR} ${Boost_LIBRARIES} ${Boost_PYTHON_LIBRARIES} ${CERES_LIBRARIES} ${COIN_CLP_LIBRARIES}) + target_link_libraries(_sisso ${MPI_LIBRARIES} -Wl,--rpath=${PYTHON_PREFIX}/lib/ ${LAPACK_LIBRARIES} ${PYTHON_LIBRARIES} -Wl,--rpath=${Boost_LIB_DIR} ${Boost_LIBRARIES} ${Boost_PYTHON_LIBRARIES} ${NLOPT_LIBRARIES} ${COIN_CLP_LIBRARIES}) install(TARGETS _sisso DESTINATION "${PYTHON_INSTDIR}/cpp_sisso") install( DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/python/ DESTINATION ${PYTHON_INSTDIR}/cpp_sisso diff --git a/src/descriptor_identifier/SISSO_DI/SISSORegressor.cpp b/src/descriptor_identifier/SISSO_DI/SISSORegressor.cpp index eefbbc80..97053122 100644 --- a/src/descriptor_identifier/SISSO_DI/SISSORegressor.cpp +++ b/src/descriptor_identifier/SISSO_DI/SISSORegressor.cpp @@ -134,6 +134,7 @@ void SISSORegressor::l0_norm(std::vector<double>& prop, int n_dim) for(int rr = 0; rr < n_get_models; ++rr) { node_value_arrs::clear_temp_test_reg(); + node_value_arrs::clear_temp_reg(); for(int ii = 0; ii < n_dim; ++ii) { int index = all_inds_min[inds[rr] * n_dim + ii]; @@ -165,6 +166,9 @@ void SISSORegressor::fit() std::vector<ModelRegressor> models; for(int rr = 0; rr < std::max(_n_residual, _n_models_store); ++rr) { + node_value_arrs::clear_temp_test_reg(); + node_value_arrs::clear_temp_reg(); + node_value_arrs::clear_temp_test_reg(); model_node_ptr model_feat = std::make_shared<ModelNode>(_feat_space->phi_selected()[rr]->arr_ind(), _feat_space->phi_selected()[rr]->rung(), _feat_space->phi_selected()[rr]->expr(), _feat_space->phi_selected()[rr]->postfix_expr(), _feat_space->phi_selected()[rr]->value(), _feat_space->phi_selected()[rr]->test_value(), _feat_space->phi_selected()[rr]->domain(), _feat_space->phi_selected()[rr]->unit()); diff --git a/src/feature_creation/domain/Domain.cpp b/src/feature_creation/domain/Domain.cpp index 38975cc8..8baac96f 100644 --- a/src/feature_creation/domain/Domain.cpp +++ b/src/feature_creation/domain/Domain.cpp @@ -284,11 +284,11 @@ Domain Domain::sub(Domain domain_2, double alpha, double a) return Domain(bnd, end_pts, new_excluded_pts); } -Domain Domain::mult(Domain domain_2) +Domain Domain::mult(Domain domain_2, double alpha, double a) { std::array<double, 4> test_bnd; - std::transform(_end_points.begin(), _end_points.end(), domain_2.end_points().begin(), test_bnd.begin(), std::multiplies<double>()); - std::transform(_end_points.begin(), _end_points.end(), domain_2.end_points().rbegin(), test_bnd.rbegin(), std::multiplies<double>()); + std::transform(_end_points.begin(), _end_points.end(), domain_2.end_points().begin(), test_bnd.begin(), [&alpha, &a](double d1, double d2){return d1 * (alpha * d2 + a);}); + std::transform(_end_points.begin(), _end_points.end(), domain_2.end_points().rbegin(), test_bnd.rbegin(), [&alpha, &a](double d1, double d2){return d1 * (alpha * d2 + a);}); std::transform(test_bnd.begin(), test_bnd.end(), test_bnd.begin(), [](double d1){return std::isnan(d1) ? 0.0 : d1;}); int min_ind = std::min_element(test_bnd.begin(), test_bnd.end()) - test_bnd.begin(); diff --git a/src/feature_creation/domain/Domain.hpp b/src/feature_creation/domain/Domain.hpp index db6d7476..c6930179 100644 --- a/src/feature_creation/domain/Domain.hpp +++ b/src/feature_creation/domain/Domain.hpp @@ -252,7 +252,7 @@ public: * @param a shift parameter * @return The resulting domain */ - Domain add(Domain domain_2, double alpha, double a); + Domain add(Domain domain_2, double alpha=1.0, double a=0.0); // DocString: domain_sub /** @@ -263,7 +263,7 @@ public: * @param a shift parameter * @return The resulting domain */ - Domain sub(Domain domain_2, double alpha, double a); + Domain sub(Domain domain_2, double alpha=1.0, double a=0.0); // DocString: domain_mult /** @@ -274,7 +274,7 @@ public: * @param a shift parameter * @return The resulting domain */ - Domain mult(Domain domain_2); + Domain mult(Domain domain_2, double alpha=1.0, double a=0.0); // DocString: domain_div /** @@ -285,7 +285,7 @@ public: * @param a shift parameter * @return The resulting domain */ - Domain div(Domain domain_2, double alpha, double a); + Domain div(Domain domain_2, double alpha=1.0, double a=0.0); // DocString: domain_abs_parameters /** @@ -296,18 +296,7 @@ public: * * @return The abs(alpha * domain + a) domain */ - Domain abs(double alpha, double a); - - // DocString: domain_abs - /** - * @brief Exponential of the domain - * - * @param alpha prefactor for the domain - * @param a The shift of the domain - * - * @return The abs(alpha * domain + a) domain - */ - inline Domain abs(){return abs(1.0, 0.0);} + Domain abs(double alpha=1.0, double a=0.0); // DocString: domain_exp /** @@ -318,7 +307,7 @@ public: * * @return The exp(alpha * domain + a) domain */ - Domain exp(double alpha, double a); + Domain exp(double alpha=1.0, double a=0.0); // DocString: domain_log /** @@ -329,7 +318,7 @@ public: * * @return The log(alpha * domain + a) domain */ - Domain log(double alpha, double a); + Domain log(double alpha=1.0, double a=0.0); // DocString: domain_pow /** @@ -341,7 +330,7 @@ public: * * @return The log(alpha * domain + a) domain */ - Domain pow(double power, double alpha, double a); + Domain pow(double power, double alpha=1.0, double a=0.0); // DocString: domain_inv /** @@ -352,7 +341,7 @@ public: * * @return The log(alpha * domain + a) domain */ - Domain inv(double alpha, double a); + Domain inv(double alpha=1.0, double a=0.0); /** * @brief return true if domain_2 == this diff --git a/src/feature_creation/feature_space/FeatureSpace.cpp b/src/feature_creation/feature_space/FeatureSpace.cpp index f35144b3..a06f6238 100644 --- a/src/feature_creation/feature_space/FeatureSpace.cpp +++ b/src/feature_creation/feature_space/FeatureSpace.cpp @@ -19,11 +19,29 @@ BOOST_CLASS_EXPORT_GUID(InvNode, "InvNode") BOOST_CLASS_EXPORT_GUID(SinNode, "SinNode") BOOST_CLASS_EXPORT_GUID(CosNode, "CosNode") +BOOST_CLASS_EXPORT_GUID(AddParamNode, "AddParamNode") +BOOST_CLASS_EXPORT_GUID(SubParamNode, "SubParamNode") +BOOST_CLASS_EXPORT_GUID(AbsDiffParamNode, "AbsDiffParamNode") +BOOST_CLASS_EXPORT_GUID(MultParamNode, "MultParamNode") +BOOST_CLASS_EXPORT_GUID(DivParamNode, "DivParamNode") +BOOST_CLASS_EXPORT_GUID(SqParamNode, "SqParamNode") +BOOST_CLASS_EXPORT_GUID(SqrtParamNode, "SqrtParamNode") +BOOST_CLASS_EXPORT_GUID(CbParamNode, "CbParamNode") +BOOST_CLASS_EXPORT_GUID(CbrtParamNode, "CbrtParamNode") +BOOST_CLASS_EXPORT_GUID(SixPowParamNode, "SixPowParamNode") +BOOST_CLASS_EXPORT_GUID(ExpParamNode, "ExpParamNode") +BOOST_CLASS_EXPORT_GUID(NegExpParamNode, "NegExpParamNode") +BOOST_CLASS_EXPORT_GUID(LogParamNode, "LogParamNode") +BOOST_CLASS_EXPORT_GUID(AbsParamNode, "AbsParamNode") +BOOST_CLASS_EXPORT_GUID(InvParamNode, "InvParamNode") +BOOST_CLASS_EXPORT_GUID(SinParamNode, "SinParamNode") +BOOST_CLASS_EXPORT_GUID(CosParamNode, "CosParamNode") + FeatureSpace::FeatureSpace( std::shared_ptr<MPI_Interface> mpi_comm, std::vector<node_ptr> phi_0, std::vector<std::string> allowed_ops, - std::map<std::string, std::vector<std::string>> allowed_param_ops, + std::vector<std::string> allowed_param_ops, std::vector<double> prop, std::vector<int> task_sizes, std::string project_type, @@ -56,14 +74,16 @@ FeatureSpace::FeatureSpace( _n_rung_store(max_store_rung), _n_rung_generate(n_rung_generate) { - initialize_fs(prop, project_type); + initialize_fs(project_type); } -void FeatureSpace::initialize_fs(std::vector<double> prop, std::string project_type) +void FeatureSpace::initialize_fs(std::string project_type) { #ifndef PARAMETERIZE if(_allowed_param_ops.size() != 0) throw std::logic_error("Parameterization is not possible recompile with -DPARAMETERIZE"); + #else + nlopt_wrapper::set_objective(project_type, _prop.data(), _task_sizes); #endif if(_n_rung_store == -1) @@ -105,12 +125,12 @@ void FeatureSpace::initialize_fs(std::vector<double> prop, std::string project_t #ifdef PARAMETERIZE for(auto& op : _allowed_param_ops) { - if((op.first.compare("add") == 0) || (op.first.compare("sub") == 0) || (op.first.compare("mult") == 0) || (op.first.compare("abs_diff") == 0)) - _com_bin_param_operators.push_back(std::make_pair(allowed_op_maps::binary_param_operator_map[op.first], op.second)); - else if((op.first.compare("div") == 0)) - _bin_param_operators.push_back(std::make_pair(allowed_op_maps::binary_param_operator_map[op.first], op.second)); + if((op.compare("add") == 0) || (op.compare("sub") == 0) || (op.compare("mult") == 0) || (op.compare("abs_diff") == 0)) + _com_bin_param_operators.push_back(allowed_op_maps::binary_param_operator_map[op]); + else if((op.compare("div") == 0)) + _bin_param_operators.push_back(allowed_op_maps::binary_param_operator_map[op]); else - _un_param_operators.push_back(std::make_pair(allowed_op_maps::unary_param_operator_map[op.first], op.second)); + _un_param_operators.push_back(allowed_op_maps::unary_param_operator_map[op]); } #endif @@ -183,7 +203,7 @@ void FeatureSpace::generate_new_feats(std::vector<node_ptr>::iterator& feat, std { try { - feat_set.push_back(op.first(*feat, feat_ind, l_bound, u_bound, op.second, _prop)); + feat_set.push_back(op(*feat, feat_ind, l_bound, u_bound, _prop)); ++feat_ind; } catch(const InvalidFeatureException& e) @@ -197,7 +217,7 @@ void FeatureSpace::generate_new_feats(std::vector<node_ptr>::iterator& feat, std { try { - feat_set.push_back(op.first(*feat, *feat_2, feat_ind, l_bound, u_bound, op.second, _prop)); + feat_set.push_back(op(*feat, *feat_2, feat_ind, l_bound, u_bound, _prop)); ++feat_ind; } catch(const InvalidFeatureException& e) @@ -212,7 +232,7 @@ void FeatureSpace::generate_new_feats(std::vector<node_ptr>::iterator& feat, std { try { - feat_set.push_back(op.first(*feat, *feat_2, feat_ind, l_bound, u_bound, op.second, _prop)); + feat_set.push_back(op(*feat, *feat_2, feat_ind, l_bound, u_bound, _prop)); ++feat_ind; } catch(const InvalidFeatureException& e) @@ -221,7 +241,7 @@ void FeatureSpace::generate_new_feats(std::vector<node_ptr>::iterator& feat, std } try { - feat_set.push_back(op.first(*feat_2, *feat, feat_ind, l_bound, u_bound, op.second, _prop)); + feat_set.push_back(op(*feat_2, *feat, feat_ind, l_bound, u_bound, _prop)); ++feat_ind; } catch(const InvalidFeatureException& e) diff --git a/src/feature_creation/feature_space/FeatureSpace.hpp b/src/feature_creation/feature_space/FeatureSpace.hpp index a2a93fe3..2de1fde2 100644 --- a/src/feature_creation/feature_space/FeatureSpace.hpp +++ b/src/feature_creation/feature_space/FeatureSpace.hpp @@ -42,12 +42,12 @@ class FeatureSpace std::vector<node_ptr> _phi_0; //!< initial feature space #ifdef PARAMETERIZE - std::vector<std::pair<un_param_op_node_gen, std::vector<std::string>>> _un_param_operators; //!< list of all parameterized unary operators with free parameters - std::vector<std::pair<bin_param_op_node_gen, std::vector<std::string>>> _com_bin_param_operators; //!< list of all parameterized commutable binary operators with free parameters - std::vector<std::pair<bin_param_op_node_gen, std::vector<std::string>>> _bin_param_operators; //!< list of all parameterized binary operators with free parameters + std::vector<un_param_op_node_gen> _un_param_operators; //!< list of all parameterized unary operators with free parameters + std::vector<bin_param_op_node_gen> _com_bin_param_operators; //!< list of all parameterized commutable binary operators with free parameters + std::vector<bin_param_op_node_gen> _bin_param_operators; //!< list of all parameterized binary operators with free parameters #endif - std::map<std::string, std::vector<std::string>> _allowed_param_ops; //!< Map of parameterization operator set (set of operators and non-linear parameters used for a non-linear least squares fit to property) + std::vector<std::string> _allowed_param_ops; //!< Map of parameterization operator set (set of operators and non-linear parameters used for a non-linear least squares fit to property) std::vector<std::string> _allowed_ops; //!< list of all allowed operators strings std::vector<un_op_node_gen> _un_operators; //!< list of all unary operators std::vector<bin_op_node_gen> _com_bin_operators; //!< list of all commutable binary operators @@ -100,7 +100,7 @@ public: std::shared_ptr<MPI_Interface> mpi_comm, std::vector<node_ptr> phi_0, std::vector<std::string> allowed_ops, - std::map<std::string, std::vector<std::string>> allowed_param_ops, + std::vector<std::string> allowed_param_ops, std::vector<double> prop, std::vector<int> task_sizes, std::string project_type="regression", @@ -118,7 +118,7 @@ public: * * @param prop The property trying to be learned */ - void initialize_fs(std::vector<double> prop, std::string project_type); + void initialize_fs(std::string project_type); /** * @brief Generate the full feature set from the allowed operators and initial feature set @@ -292,7 +292,7 @@ public: FeatureSpace( py::list phi_0, py::list allowed_ops, - py::dict allowed_param_ops, + py::list allowed_param_ops, py::list prop, py::list task_sizes, std::string project_type="pearson", @@ -326,7 +326,7 @@ public: FeatureSpace( py::list phi_0, py::list allowed_ops, - py::dict allowed_param_ops, + py::list allowed_param_ops, np::ndarray prop, py::list task_sizes, std::string project_type="pearson", diff --git a/src/feature_creation/node/FeatureNode.cpp b/src/feature_creation/node/FeatureNode.cpp index f25ac14f..ece46f55 100644 --- a/src/feature_creation/node/FeatureNode.cpp +++ b/src/feature_creation/node/FeatureNode.cpp @@ -12,7 +12,10 @@ FeatureNode::FeatureNode(int feat_ind, std::string expr, std::vector<double> val _expr(expr) { if((*std::max_element(value.begin(), value.end()) > _domain) || (*std::min_element(value.begin(), value.end()) < _domain)) + { + std::cout << (*std::max_element(value.begin(), value.end())) << '\t' << (*std::min_element(value.begin(), value.end())) << std::endl; throw std::logic_error("The feature " + expr + " has values outside of the domain of " + _domain.toString()); + } if(set_val) { diff --git a/src/feature_creation/node/FeatureNode.hpp b/src/feature_creation/node/FeatureNode.hpp index a5100a14..26082b09 100644 --- a/src/feature_creation/node/FeatureNode.hpp +++ b/src/feature_creation/node/FeatureNode.hpp @@ -210,7 +210,6 @@ public: */ inline double* test_value_ptr(int offset = 0){return node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset);} - // DocString: feat_node_rung /** * @brief return the rung of the feature @@ -296,12 +295,68 @@ public: /** * @brief The parameters used for introducing more non linearity in the operators */ - inline std::array<double, 2> parameters(){return {1.0, 0.0};} + inline std::vector<double> parameters(){return {};}; /** * @brief Set the non-linear parameters + */ + inline void set_parameters(std::vector<double> params){}; + + /** + * @brief returns the number of parameters for this feature + * @return the number of parameters (_params.size()) + */ + inline int n_params(int n_cur=0){return n_cur;}; + + /** + * @brief Set the values of the training data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values + */ + inline void set_value(const double* params, int offset = -1){set_value(offset);}; + + /** + * @brief The pointer to where the feature's training data is stored + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values + * @returns the pointer to the feature's data + */ + inline double* value_ptr(const double* params, int offset = -1){return value_ptr(offset);}; + + /** + * @brief Set the values of the test data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values + */ + inline void set_test_value(const double* params, int offset = -1){set_test_value(offset);}; + + /** + * @brief The pointer to where the feature's test data is stored + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values + * @returns the pointer to the feature's data + */ + inline double* test_value_ptr(const double* params, int offset = -1){return test_value_ptr(offset);}; + + /** + * @brief The domain for the feature (min/max values) + * + * @param params parameter values for non-linear operations + * @return the domain + */ + Domain domain(double* params){return _domain;}; + + /** + * @brief The expression of the feature + * + * @param params parameter values for non-linear operations + * @return feature expression */ - inline void set_parameters(std::array<double, 2>){}; + std::string expr(double* params){return _expr;}; #endif }; diff --git a/src/feature_creation/node/Node.hpp b/src/feature_creation/node/Node.hpp index 3be05b9c..a25190b6 100644 --- a/src/feature_creation/node/Node.hpp +++ b/src/feature_creation/node/Node.hpp @@ -327,12 +327,69 @@ public: /** * @brief The parameters used for introducing more non linearity in the operators */ - virtual std::array<double, 2> parameters() = 0; + virtual std::vector<double> parameters() = 0; /** * @brief Set the non-linear parameters */ - virtual void set_parameters(std::array<double, 2>) = 0; + virtual void set_parameters(std::vector<double>) = 0; + + /** + * @brief returns the number of parameters for this feature + * @return the number of parameters (_params.size()) + */ + virtual int n_params(int n_cur = 0) = 0; + + /** + * @brief Set the values of the training data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values + */ + virtual void set_value(const double* params, int offset = -1) = 0; + + /** + * @brief The pointer to where the feature's training data is stored + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values + * @returns the pointer to the feature's data + */ + virtual double* value_ptr(const double* params, int offset = -1) = 0; + + /** + * @brief Set the values of the test data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values + */ + virtual void set_test_value(const double* params, int offset = -1) = 0; + + /** + * @brief The pointer to where the feature's test data is stored + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values + * @returns the pointer to the feature's data + */ + virtual double* test_value_ptr(const double* params, int offset = -1) = 0; + + /** + * @brief The domain for the feature (min/max values) + * + * @param params parameter values for non-linear operations + * @return the domain + */ + virtual Domain domain(double* params) = 0; + + /** + * @brief The expression of the feature + * + * @param params parameter values for non-linear operations + * @return feature expression + */ + virtual std::string expr(double* params) = 0; + #endif //DocString: node_nfeats @@ -373,7 +430,7 @@ public: * @brief The parameters used for non-linear operator nodes * @return The operator node parameters as a list [alpha, a] */ - inline py::list parameters_py(){return python_conv_utils::to_list<double, 2>(parameters());} + inline py::list parameters_py(){return python_conv_utils::to_list<double>(parameters());} #endif // DocString: node_primary_feature_decomp diff --git a/src/feature_creation/node/operator_nodes/OperatorNode.hpp b/src/feature_creation/node/operator_nodes/OperatorNode.hpp index ea1fd9aa..d43b7201 100644 --- a/src/feature_creation/node/operator_nodes/OperatorNode.hpp +++ b/src/feature_creation/node/operator_nodes/OperatorNode.hpp @@ -22,17 +22,17 @@ #include<iomanip> -#ifdef PARAMETERIZE - #include "ceres/ceres.h" - #include "glog/logging.h" - - using ceres::AutoDiffCostFunction; - using ceres::CauchyLoss; - using ceres::CostFunction; - using ceres::Problem; - using ceres::Solver; - using ceres::Solve; -#endif +// #ifdef PARAMETERIZE +// #include "ceres/ceres.h" +// #include "glog/logging.h" + +// using ceres::AutoDiffCostFunction; +// using ceres::CauchyLoss; +// using ceres::CostFunction; +// using ceres::Problem; +// using ceres::Solver; +// using ceres::Solve; +// #endif #ifdef PY_BINDINGS #include <python/conversion_utils.hpp> @@ -63,11 +63,9 @@ class OperatorNode: public Node { ar & boost::serialization::base_object<Node>(*this); ar & _feats; - ar & _params; } protected: std::array<node_ptr, N> _feats; //!< The features for the operator nodes to act on (edges of the graph) - std::array<double, 2> _params; //!< The features for the operator nodes to act on (edges of the graph) public: /** @@ -86,8 +84,7 @@ public: */ OperatorNode(std::array<node_ptr, N> feats, int feat_ind) : Node(feat_ind, feats[0]->n_samp(), feats[0]->n_test_samp()), - _feats(feats), - _params({1.0, 0.0}) + _feats(feats) {} /** @@ -272,23 +269,15 @@ public: * @param cur_expr The current expression * @return The current postfix expression of the feature */ - inline void update_postfix(std::string& cur_expr) + virtual void update_postfix(std::string& cur_expr) { std::stringstream postfix; postfix << get_postfix_term() << ":"; - if((_params[0] == 1.0) && (_params[1] == 0.0)) - { - postfix << "1.0,0.0"; - } - else - { - postfix << std::setprecision(13) << std::scientific << _params[0] << ","; - postfix << std::setprecision(13) << std::scientific << _params[1]; - } + postfix << "1.0,0.0"; cur_expr = postfix.str() + "|" + cur_expr; for(int nn = N - 1; nn >= 0; --nn) _feats[nn]->update_postfix(cur_expr); - }; + } /** * @brief Get the string character representation of the node for the postfix expression @@ -338,27 +327,98 @@ public: /** * @brief The parameters used for introducing more non linearity in the operators */ - inline std::array<double, 2> parameters(){return _params;} + virtual std::vector<double> parameters() = 0; + + /** + * @brief Solve the non-linear optimization to set the parameters + * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * + * @param prop property to fit to get the parameters + */ + virtual void get_parameters(std::vector<double>& prop) = 0; /** * @brief Set the non-linear parameters + */ + virtual void set_parameters(std::vector<double>) = 0; + + /** + * @brief returns the number of theoretical parameters for this feature + * @return the number of theoretical parameters */ - inline void set_parameters(std::array<double, 2> params){_params = params;} + inline int n_params(int n_cur = 0){return std::accumulate(_feats.begin(), _feats.end(), 2, [](double tot, node_ptr feat){return tot + feat->n_params();});} /** - * @brief Solve the non-linear optimization to set the parameters - * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * @brief Set the values of the training data for the feature inside of the value storage arrays * - * @param prop property to fit to get the parameters - * @param param_list List describing the parameters to fit + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values */ - virtual void get_parameters(std::vector<double>& prop, std::vector<std::string>& param_list) = 0; + virtual void set_value(const double* params, int offset = -1) = 0; - // DocString: op_node_reset_params /** - * @brief Reset the parameters to initial values + * @brief The pointer to where the feature's training data is stored + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values + * @returns the pointer to the feature's data */ - inline void reset_parameters(){_params = {1.0, 0.0};} + double* value_ptr(const double* params, int offset = -1) + { + if(_selected) + return node_value_arrs::get_d_matrix_ptr(_d_mat_ind); + + offset = (offset == -1) ? rung() : offset; + set_value(params, offset); + + return node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset, false); + } + + /** + * @brief Set the values of the test data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values + */ + virtual void set_test_value(const double* params, int offset = -1) = 0; + + /** + * @brief The pointer to where the feature's test data is stored + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values + * @returns the pointer to the feature's data + */ + double* test_value_ptr(const double* params, int offset = -1) + { + offset = (offset == -1) ? rung() : offset; + set_test_value(params, offset); + + return node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset, false); + } + + /** + * @brief Converts a feature into a postfix expression (reverse polish notation) + * + * @details Recursively creates a postfix representation of the string + * + * @param cur_expr The current expression + * @return The current postfix expression of the feature + */ + void update_postfix(std::string& cur_expr, double* params) + { + std::stringstream postfix; + postfix << get_postfix_term() << ":"; + postfix << std::setprecision(13) << std::scientific << params[0] << ","; + postfix << std::setprecision(13) << std::scientific << params[1]; + cur_expr = postfix.str() + "|" + cur_expr; + int n_used = 2; + for(int nn = N - 1; nn >= 0; --nn) + { + _feats[nn]->update_postfix(cur_expr, params + n_used); + n_used += _feats[nn]->n_params(); + } + } #ifdef PY_BINDINGS // DocString: op_node_param_arr @@ -369,11 +429,10 @@ public: * @param prop property to fit to get the parameters * @param param_list List describing the parameters to fit */ - inline void get_parameters(np::ndarray prop, py::list param_list) + inline void get_parameters(np::ndarray prop) { std::vector<double> prop_vec = python_conv_utils::from_ndarray<double>(prop); - std::vector<std::string> param_vec = python_conv_utils::from_list<std::string>(param_list); - get_parameters(prop_vec, param_vec); + get_parameters(prop_vec); } // DocString: op_node_param_list @@ -384,41 +443,24 @@ public: * @param prop property to fit to get the parameters * @param param_list List describing the parameters to fit */ - inline void get_parameters(py::list prop, py::list param_list) + inline void get_parameters(py::list prop) { std::vector<double> prop_vec = python_conv_utils::from_list<double>(prop); - std::vector<std::string> param_vec = python_conv_utils::from_list<std::string>(param_list); - get_parameters(prop_vec, param_vec); + get_parameters(prop_vec); } // DocString: op_node_set_param_list /** * @brief Set the non-linear parameters */ - inline void set_parameters(py::list params){_params = python_conv_utils::arr_from_list<double, 2>(params);} + inline void set_parameters(py::list params){set_parameters(python_conv_utils::from_list<double>(params));} // DocString: op_node_set_param_arr /** * @brief Set the non-linear parameters */ - inline void set_parameters(np::ndarray params){_params = python_conv_utils::arr_from_ndarray<double, 2>(params);} - + inline void set_parameters(np::ndarray params){set_parameters( python_conv_utils::from_ndarray<double>(params));} #endif - /** - * @brief Find the parameters for the operation - * - * @param problem A Problem that ceres can solve - */ - void parameterize(Problem& problem) - { - Solver::Options options; - options.max_num_iterations = 50; - options.linear_solver_type = ceres::DENSE_QR; - options.minimizer_progress_to_stdout = false; - options.logging_type = ceres::SILENT; - Solver::Summary summary; - Solve(options, &problem, &summary); - } #endif }; diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs/absolute_value.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs/absolute_value.cpp index e201cd70..b269acc8 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs/absolute_value.cpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs/absolute_value.cpp @@ -1,5 +1,7 @@ #include <feature_creation/node/operator_nodes/allowed_operator_nodes/abs/absolute_value.hpp> +BOOST_SERIALIZATION_ASSUME_ABSTRACT(AbsNode) + // BOOST_CLASS_EXPORT(AbsNode) AbsNode::AbsNode() @@ -29,6 +31,16 @@ AbsNode::AbsNode(node_ptr feat, int feat_ind, double l_bound, double u_bound): set_test_value(); } +AbsNode::AbsNode(std::array<node_ptr, 1> feats, int feat_ind): + OperatorNode(feats, feat_ind) +{ + if((feats[0]->type() == NODE_TYPE::ABS) || (feats[0]->type() == NODE_TYPE::ABS_DIFF)) + throw InvalidFeatureException(); + + set_value(); + set_test_value(); +} + void AbsNode::update_add_sub_leaves(std::map<std::string, int>& add_sub_leaves, int pl_mn, int& expected_abs_tot) { std::string key = expr(); @@ -50,3 +62,33 @@ void AbsNode::update_div_mult_leaves(std::map<std::string, double>& div_mult_lea expected_abs_tot += std::abs(fact); } + +void AbsNode::set_value(int offset) +{ + offset = (offset == -1) ? rung() : offset; + + if(_selected) + allowed_op_funcs::abs(_n_samp, _feats[0]->value_ptr(offset + 2), 1.0, 0.0, node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); + + allowed_op_funcs::abs(_n_samp, _feats[0]->value_ptr(offset + 2), 1.0, 0.0, node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); +} + +void AbsNode::set_test_value(int offset) +{ + offset = (offset == -1) ? rung() : offset; + allowed_op_funcs::abs(_n_test_samp, _feats[0]->test_value_ptr(offset + 2), 1.0, 0.0, node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); +} + +void AbsNode::set_value(const double* params, int offset) +{ + offset = (offset == -1) ? rung() : offset; + if(_selected) + allowed_op_funcs::abs(_n_samp, _feats[0]->value_ptr(params + 2, offset + 2), params[0], params[1], node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); + + allowed_op_funcs::abs(_n_samp, _feats[0]->value_ptr(params + 2, offset + 2), params[0], params[1], node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset, false)); +} +void AbsNode::set_test_value(const double* params, int offset) +{ + offset = (offset == -1) ? rung() : offset; + allowed_op_funcs::abs(_n_test_samp, _feats[0]->test_value_ptr(params + 2, offset + 2), params[0], params[1], node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset, false)); +} \ No newline at end of file diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs/absolute_value.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs/absolute_value.hpp index d881d9e2..2bc4fb72 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs/absolute_value.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs/absolute_value.hpp @@ -60,6 +60,15 @@ public: */ AbsNode(node_ptr feat, int feat_ind, double l_bound, double u_bound); + /** + * @brief Constructor without checking feature values + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + */ + AbsNode(std::array<node_ptr, 1> feats, int feat_ind); + // DocString: abs_node_unit /** * @brief Get the unit of the feature (combine the units of _feats) @@ -70,7 +79,7 @@ public: /** * @brief Get the expression for the overall feature (From root node down) */ - inline std::string expr(){return "|" + std::to_string(_params[0]) + "*" + _feats[0]->expr() + " + " + std::to_string(_params[1]) + "|";} + virtual inline std::string expr(){return "|" + _feats[0]->expr() + "|";} // DocString: abs_node_set_value /** @@ -78,14 +87,7 @@ public: * * @param offset(int) Key to determine which part of the temporary storage array to look into */ - inline void set_value(int offset = -1) - { - if(_selected) - allowed_op_funcs::abs(_n_samp, _feats[0]->value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); - - offset = (offset == -1) ? rung() : offset; - allowed_op_funcs::abs(_n_samp, _feats[0]->value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); - } + virtual void set_value(int offset = -1); // DocString: abs_node_set_test_value /** @@ -93,11 +95,7 @@ public: * * @param offset(int) Key to determine which part of the temporary storage array to look into */ - inline void set_test_value(int offset = -1) - { - offset = (offset == -1) ? rung() : offset; - allowed_op_funcs::abs(_n_test_samp, _feats[0]->test_value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); - } + virtual void set_test_value(int offset = -1); // DocString: abs_node_rung /** @@ -116,7 +114,7 @@ public: /** * @brief The domain for the feature (min/max values) */ - Domain domain(){return _feats[0]->domain().abs();} + virtual inline Domain domain(){return _feats[0]->domain().abs(1.0, 0.0);} /** * @brief Get the string character representation of the node for the postfix expression @@ -145,39 +143,55 @@ public: #ifdef PARAMETERIZE /** - * @brief Constructor - * @details Constructs the Node from node pointer of the feature to operate on + * @brief The parameters used for introducing more non linearity in the operators + */ + virtual std::vector<double> parameters(){return {};} + + /** + * @brief Solve the non-linear optimization to set the parameters + * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * + * @param prop property to fit to get the parameters + */ + virtual void get_parameters(std::vector<double>& prop){return;} + + /** + * @brief Set the non-linear parameters + */ + virtual void set_parameters(std::vector<double>){return;} + + /** + * @brief Set the values of the training data for the feature inside of the value storage arrays * - * @param feat_1 shared_ptr of the feature to operate on (A) - * @param feat_ind Index of the new feature - * @param l_bound Minimum absolute value allowed for the feature. - * @param u_bound Maximum absolute value allowed for the feature. - * @param param_list The list of parameters to optimize using non-linear least squares - * @param prop The property to fit to + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values */ - AbsNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop); + void set_value(const double* params, int offset = -1); /** - * @brief Constructor - * @details Constructs the Node from an array of features to operate on + * @brief Set the values of the test data for the feature inside of the value storage arrays * - * @param feats Features to operate over (Edges of the graph) - * @param feat_ind Index of the new feature - * @param l_bound Minimum absolute value allowed for the feature. - * @param u_bound Maximum absolute value allowed for the feature. - * @param param_list The list of parameters to optimize using non-linear least squares - * @param prop The property to fit to + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values */ - AbsNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop); + void set_test_value(const double* params, int offset = -1); /** - * @brief Solve the non-linear optimization to set the parameters - * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * @brief The domain for the feature (min/max values) * - * @param prop property to fit to get the parameters - * @param param_list List describing the parameters to fit + * @param params parameter values for non-linear operations + * @return the domain + */ + inline Domain domain(double* params){return _feats[0]->domain(params + 2).abs(params[0], params[1]);} + + /** + * @brief The expression of the feature + * + * @param params parameter values for non-linear operations + * @return feature expression */ - void get_parameters(std::vector<double>& prop, std::vector<std::string>& param_list); + inline std::string expr(double* params){return "|" + std::to_string(params[0]) + "*" + _feats[0]->expr(params + 2) + " + " + std::to_string(params[1]) + "|";} + #endif }; diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs/parameterize.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs/parameterize.cpp deleted file mode 100644 index e3863479..00000000 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs/parameterize.cpp +++ /dev/null @@ -1,208 +0,0 @@ -#include <feature_creation/node/operator_nodes/allowed_operator_nodes/abs/absolute_value.hpp> - -AbsNode::AbsNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop) : - OperatorNode(feats, feat_ind) -{ - get_parameters(prop, param_list); - set_value(); - if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) - throw InvalidFeatureException(); - - set_test_value(); -} - -AbsNode::AbsNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop) : - OperatorNode({feat}, feat_ind) -{ - get_parameters(prop, param_list); - set_value(); - if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) - throw InvalidFeatureException(); - - set_test_value(); -} - -void AbsNode::get_parameters(std::vector<double>& prop, std::vector<std::string>& param_list) -{ - if(param_list.size() == 0) - return; - Problem problem; - double b = 1.0, c = 0.0; - double* val = _feats[0]->value_ptr(rung() + 2); - if(param_list.size() > 4) - { - throw std::logic_error("Too many parameters passed to the constructor."); - } - else if(param_list.size() == 4) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<AbsResidual_alpha_a_b_c, 1, 1, 1, 1, 1>( - new AbsResidual_alpha_a_b_c(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &_params[1], &b, &c - ); - } - } - else if(param_list.size() == 3) - { - if(std::none_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("alpha") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<AbsResidual_a_b_c, 1, 1, 1, 1>( - new AbsResidual_a_b_c(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[1], &b, &c - ); - } - } - else if(std::none_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("a") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<AbsResidual_alpha_b_c, 1, 1, 1, 1>( - new AbsResidual_alpha_b_c(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &b, &c - ); - } - } - else if(std::none_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("b") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<AbsResidual_alpha_a_c, 1, 1, 1, 1>( - new AbsResidual_alpha_a_c(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &_params[1], &c - ); - } - } - else if(std::none_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("c") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<AbsResidual_alpha_a_b, 1, 1, 1, 1>( - new AbsResidual_alpha_a_b(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &_params[1], &b - ); - } - } - else - throw std::logic_error("Invalid parameter in the parameter list."); - } - else if(param_list.size() == 2) - { - if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("alpha") == 0) || s.compare("a") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<AbsResidual_alpha_a, 1, 1, 1>( - new AbsResidual_alpha_a(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &_params[1] - ); - } - } - else if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("alpha") == 0) || s.compare("b") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<AbsResidual_alpha_b, 1, 1, 1>( - new AbsResidual_alpha_b(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &b - ); - } - } - else if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("alpha") == 0) || s.compare("c") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<AbsResidual_alpha_c, 1, 1, 1>( - new AbsResidual_alpha_c(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &c - ); - } - } - else if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("a") == 0) || s.compare("b") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<AbsResidual_a_b, 1, 1, 1>( - new AbsResidual_a_b(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[1], &b - ); - } - } - else if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("a") == 0) || s.compare("c") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<AbsResidual_a_c, 1, 1, 1>( - new AbsResidual_a_c(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[1], &c - ); - } - } - else - throw std::logic_error("Invalid parameter in the parameter list."); - } - else if(param_list.size() == 1) - { - if(std::any_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("alpha") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<AbsResidual_alpha, 1, 1>( - new AbsResidual_alpha(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0] - ); - } - } - else if(std::any_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("a") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<AbsResidual_a, 1, 1>( - new AbsResidual_a(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[1] - ); - } - } - else - throw std::logic_error("Invalid parameter in the parameter list."); - } - parameterize(problem); -} diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs/parameterized_absolute_value.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs/parameterized_absolute_value.cpp new file mode 100644 index 00000000..59a02643 --- /dev/null +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs/parameterized_absolute_value.cpp @@ -0,0 +1,65 @@ +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/abs/parameterized_absolute_value.hpp> + +AbsParamNode::AbsParamNode() +{} + +AbsParamNode::AbsParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop) : + AbsNode(feats, feat_ind) +{ + _params.resize(n_params(), 0.0); + get_parameters(prop); + set_value(); + if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) + throw InvalidFeatureException(); + + set_test_value(); +} + +AbsParamNode::AbsParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop) : + AbsNode({feat}, feat_ind) +{ + _params.resize(n_params(), 0.0); + get_parameters(prop); + set_value(); + if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) + throw InvalidFeatureException(); + + set_test_value(); +} + +AbsParamNode::AbsParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound) : + AbsNode(feats, feat_ind) +{ + _params.resize(n_params(), 0.0); +} + +AbsParamNode::AbsParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound) : + AbsNode({feat}, feat_ind) +{ + _params.resize(n_params(), 0.0); +} + +void AbsParamNode::get_parameters(std::vector<double>& prop) +{ + nlopt_wrapper::feat_data d; + d._feat = this; + d._prop = prop.data(); + double minf; + + std::fill_n(_params.begin(), _params.size(), 1.0); + dcopy_(_params.size() / 2, nlopt_wrapper::_zeros.data(), 1, &_params[1], 2); + + nlopt::opt opt(nlopt::LN_SBPLX, _params.size()); + opt.set_min_objective(nlopt_wrapper::objective_reg, &d); + opt.set_maxeval(1000); + opt.set_xtol_rel(1e-2); + try + { + nlopt::result result = opt.optimize(_params, minf); + } + catch(std::exception &e) + { + std::fill_n(_params.begin(), _params.size(), 1.0); + dcopy_(_params.size() / 2, nlopt_wrapper::_zeros.data(), 1, &_params[1], 2); + } +} diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs/parameterized_absolute_value.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs/parameterized_absolute_value.hpp new file mode 100644 index 00000000..97d5b7a3 --- /dev/null +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs/parameterized_absolute_value.hpp @@ -0,0 +1,153 @@ +/** @file feature_creation/node/operator_nodes/allowed_operator_nodes/abs/parameterized_absolute_value.hpp + * @brief Class describing the parameterized absolute value operator + * + * This class represents the parameterized unary operator -> |alpha * A + a| + * + * @author Thomas A. R. Purcell (tpurcell) + * @bug No known bugs. + */ +#ifndef PARAM_ABS_VAL_NODE +#define PARAM_ABS_VAL_NODE + +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/abs/absolute_value.hpp> +#include <feature_creation/parameterization/NLOptWrapper.hpp> + +// DocString: cls_abs_node +/** + * @brief Node for the absolute value operator + * + */ +class AbsParamNode: public AbsNode +{ + using AbsNode::set_value; + using AbsNode::set_test_value; + using AbsNode::domain; + using AbsNode::expr; + + friend class boost::serialization::access; + + /** + * @brief Serialization function to send over MPI + * + * @param ar Archive representation of node + */ + template <typename Archive> + void serialize(Archive& ar, const unsigned int version) + { + ar & boost::serialization::base_object<AbsNode>(*this); + ar & _params; + } + +protected: + std::vector<double> _params; //!< The parameters vector + +public: + /** + * @brief Base Constructor + * @details This is only used for serialization + */ + AbsParamNode(); + + /** + * @brief Constructor + * @details Constructs the Node from node pointer of the feature to operate on + * + * @param feat_1 shared_ptr of the feature to operate on (A) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + * @param prop The property to fit to + */ + AbsParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop); + + /** + * @brief Constructor + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + * @param prop The property to fit to + */ + AbsParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop); + + /** + * @brief Constructor + * @details Constructs the Node from node pointer of the feature to operate on + * + * @param feat_1 shared_ptr of the feature to operate on (A) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + */ + AbsParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound); + + /** + * @brief Constructor + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + */ + AbsParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound); + + // DocString: abs_param_node_set_value + /** + * @brief Set the values of the training data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + */ + inline void set_value(int offset = -1){set_value(_params.data(), offset);} + + // DocString: abs_param_node_set_test_value + /** + * @brief Set the values of the test data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + */ + inline void set_test_value(int offset = -1){set_test_value(_params.data(), offset);} + + // DocString: abs_param_node_expr + /** + * @brief Get the expression for the overall feature (From root node down) + */ + inline std::string expr(){return expr(_params.data());} + + // DocString: abs_param_node_domain + /** + * @brief The domain for the feature (min/max values) + */ + inline Domain domain(){return domain(_params.data());} + + /** + * @brief The parameters used for introducing more non linearity in the operators + */ + inline std::vector<double> parameters(){return _params;} + + /** + * @brief Solve the non-linear optimization to set the parameters + * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * + * @param prop property to fit to get the parameters + */ + void get_parameters(std::vector<double>& prop); + + /** + * @brief Set the non-linear parameters + */ + inline void set_parameters(std::vector<double> params) + { + if(params.size() != n_params()) + throw std::logic_error("Wrong number of parameters passed to set_parameters."); + _params = params; + } +}; + +#endif \ No newline at end of file diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/absolute_difference.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/absolute_difference.cpp index d58cc832..73ad696e 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/absolute_difference.cpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/absolute_difference.cpp @@ -1,7 +1,5 @@ #include <feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/absolute_difference.hpp> -// BOOST_CLASS_EXPORT(AbsDiffNode) - AbsDiffNode::AbsDiffNode() {} @@ -29,6 +27,15 @@ AbsDiffNode::AbsDiffNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double set_test_value(); } +AbsDiffNode::AbsDiffNode(std::array<node_ptr, 2> feats, int feat_ind): + OperatorNode(feats, feat_ind) +{ + check_feats(); + + set_value(); + set_test_value(); +} + void AbsDiffNode::check_feats() { if(_feats[0]->unit() != _feats[1]->unit()) diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/absolute_difference.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/absolute_difference.hpp index 8b904b3f..0208c433 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/absolute_difference.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/absolute_difference.hpp @@ -62,6 +62,15 @@ public: */ AbsDiffNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound); + /** + * @brief Constructor without checking feature values + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + */ + AbsDiffNode(std::array<node_ptr, 2> feats, int feat_ind); + // DocString: abs_diff_node_unit /** * @brief Get the unit of the feature (combine the units of _feats) @@ -72,7 +81,7 @@ public: /** * @brief Get the expression for the overall feature (From root node down) */ - inline std::string expr(){return "|" + _feats[0]->expr() + " - (" + std::to_string(_params[0]) + "*" + _feats[1]->expr() + " + " + std::to_string(_params[1]) + ")|";} + inline std::string expr(){return "|" + _feats[0]->expr() + " - (" + _feats[1]->expr() + ")|";} // DocString: abs_diff_node_set_value /** @@ -82,11 +91,11 @@ public: */ inline void set_value(int offset = -1) { - if(_selected) - allowed_op_funcs::abs_diff(_n_samp, _feats[0]->value_ptr(offset + 2), _feats[1]->value_ptr(offset + 1), _params[0], _params[1], node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); - offset = (offset == -1) ? rung() : offset; - allowed_op_funcs::abs_diff(_n_samp, _feats[0]->value_ptr(offset + 2), _feats[1]->value_ptr(offset + 1), _params[0], _params[1], node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); + + if(_selected) + allowed_op_funcs::abs_diff(_n_samp, _feats[0]->value_ptr(offset + 2), _feats[1]->value_ptr(offset + 1), 1.0, 0.0, node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); + allowed_op_funcs::abs_diff(_n_samp, _feats[0]->value_ptr(offset + 2), _feats[1]->value_ptr(offset + 1), 1.0, 0.0, node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); } // DocString: abs_diff_node_set_test_value @@ -98,7 +107,7 @@ public: inline void set_test_value(int offset = -1) { offset = (offset == -1) ? rung() : offset; - allowed_op_funcs::abs_diff(_n_test_samp, _feats[0]->test_value_ptr(offset + 2), _feats[1]->test_value_ptr(offset + 1), _params[0], _params[1], node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); + allowed_op_funcs::abs_diff(_n_test_samp, _feats[0]->test_value_ptr(offset + 2), _feats[1]->test_value_ptr(offset + 1), 1.0, 0.0, node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); } // DocString: abs_diff_node_rung @@ -118,7 +127,7 @@ public: /** * @brief The domain for the feature (min/max values) */ - Domain domain(){return _feats[0]->domain().sub(_feats[1]->domain(), _params[0], _params[1]).abs();} + Domain domain(){return _feats[0]->domain().sub(_feats[1]->domain(), 1.0, 0.0).abs();} /** * @brief Get the string character representation of the node for the postfix expression @@ -153,39 +162,66 @@ public: #ifdef PARAMETERIZE /** - * @brief Constructor - * @details Constructs the Node from an array of features to operate on + * @brief The parameters used for introducing more non linearity in the operators + */ + virtual std::vector<double> parameters(){return {};} + + /** + * @brief Solve the non-linear optimization to set the parameters + * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * + * @param prop property to fit to get the parameters + */ + virtual void get_parameters(std::vector<double>& prop){return;} + + /** + * @brief Set the non-linear parameters + */ + virtual void set_parameters(std::vector<double>){return;} + + /** + * @brief Set the values of the training data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values + */ + inline void set_value(const double* params, int offset = -1) + { + offset = (offset == -1) ? rung() : offset; + + if(_selected) + allowed_op_funcs::abs_diff(_n_samp, _feats[0]->value_ptr(params + 2 + _feats[1]->n_params(), offset + 2), _feats[1]->value_ptr(params + 2, offset + 1), params[0], params[1], node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); + allowed_op_funcs::abs_diff(_n_samp, _feats[0]->value_ptr(params + 2 + _feats[1]->n_params(), offset + 2), _feats[1]->value_ptr(params + 2, offset + 1), params[0], params[1], node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); + } + + /** + * @brief Set the values of the test data for the feature inside of the value storage arrays * - * @param feats Features to operate over (Edges of the graph) - * @param feat_ind Index of the new feature - * @param l_bound Minimum absolute value allowed for the feature. - * @param u_bound Maximum absolute value allowed for the feature. - * @param param_list The list of parameters to optimize using non-linear least squares - * @param prop The property to fit to + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values */ - AbsDiffNode(std::array<node_ptr, 2> feats, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop); + inline void set_test_value(const double* params, int offset = -1) + { + offset = (offset == -1) ? rung() : offset; + allowed_op_funcs::abs_diff(_n_test_samp, _feats[0]->test_value_ptr(params + 2 + _feats[1]->n_params(), offset + 2), _feats[1]->test_value_ptr(params + 2, offset + 1), params[0], params[1], node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); + } /** - * @brief Constructor - * @details Constructs the Node from node pointer of the feature to operate on + * @brief The domain for the feature (min/max values) * - * @param feat_1 shared_ptr of the feature to operate on (A) - * @param feat_ind Index of the new feature - * @param l_bound Minimum absolute value allowed for the feature. - * @param u_bound Maximum absolute value allowed for the feature. - * @param param_list The list of parameters to optimize using non-linear least squares - * @param prop The property to fit to + * @param params parameter values for non-linear operations + * @return the domain */ - AbsDiffNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop); + inline Domain domain(double* params){return _feats[0]->domain(params + _feats[1]->n_params() + 2).sub(_feats[1]->domain(params + 2), params[0], params[1]).abs();} /** - * @brief Solve the non-linear optimization to set the parameters - * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * @brief The expression of the feature * - * @param prop property to fit to get the parameters - * @param param_list List describing the parameters to fit + * @param params parameter values for non-linear operations + * @return feature expression */ - void get_parameters(std::vector<double>& prop, std::vector<std::string>& param_list); + inline std::string expr(double* params){return "|(" + _feats[0]->expr(params + _feats[1]->n_params() + 2) + ") - (" + std::to_string(params[0]) + "*" + _feats[1]->expr(params + 2) + " + " + std::to_string(params[1]) + ")|";} + #endif }; diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/parameterize.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/parameterize.cpp deleted file mode 100644 index 90bb4d1b..00000000 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/parameterize.cpp +++ /dev/null @@ -1,212 +0,0 @@ -#include <feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/absolute_difference.hpp> - -AbsDiffNode::AbsDiffNode(std::array<node_ptr, 2> feats, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop): - OperatorNode(feats, feat_ind) -{ - check_feats(); - get_parameters(prop, param_list); - set_value(); - if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) - throw InvalidFeatureException(); - - set_test_value(); -} - -AbsDiffNode::AbsDiffNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop): - OperatorNode({feat_1, feat_2}, feat_ind) -{ - check_feats(); - get_parameters(prop, param_list); - set_value(); - if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) - throw InvalidFeatureException(); - - set_test_value(); -} - -void AbsDiffNode::get_parameters(std::vector<double>& prop, std::vector<std::string>& param_list) -{ - if(param_list.size() == 0) - return; - Problem problem; - double b = 1.0, c = 0.0; - double* val_1 = _feats[0]->value_ptr(rung() + 2); - double* val_2 = _feats[1]->value_ptr(rung() + 1); - - if(param_list.size() > 4) - { - throw std::logic_error("Too many parameters passed to the constructor."); - } - else if(param_list.size() == 4) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<AbsDiffResidual_alpha_a_b_c, 1, 1, 1, 1, 1>( - new AbsDiffResidual_alpha_a_b_c(val_1[ss], val_2[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &_params[1], &b, &c - ); - } - } - else if(param_list.size() == 3) - { - if(std::none_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("alpha") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<AbsDiffResidual_a_b_c, 1, 1, 1, 1>( - new AbsDiffResidual_a_b_c(val_1[ss], val_2[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[1], &b, &c - ); - } - } - else if(std::none_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("a") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<AbsDiffResidual_alpha_b_c, 1, 1, 1, 1>( - new AbsDiffResidual_alpha_b_c(val_1[ss], val_2[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &b, &c - ); - } - } - else if(std::none_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("b") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<AbsDiffResidual_alpha_a_c, 1, 1, 1, 1>( - new AbsDiffResidual_alpha_a_c(val_1[ss], val_2[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &_params[1], &c - ); - } - } - else if(std::none_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("c") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<AbsDiffResidual_alpha_a_b, 1, 1, 1, 1>( - new AbsDiffResidual_alpha_a_b(val_1[ss], val_2[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &_params[1], &b - ); - } - } - else - throw std::logic_error("Invalid parameter in the parameter list."); - } - else if(param_list.size() == 2) - { - if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("alpha") == 0) || s.compare("a") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<AbsDiffResidual_alpha_a, 1, 1, 1>( - new AbsDiffResidual_alpha_a(val_1[ss], val_2[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &_params[1] - ); - } - } - else if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("alpha") == 0) || s.compare("b") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<AbsDiffResidual_alpha_b, 1, 1, 1>( - new AbsDiffResidual_alpha_b(val_1[ss], val_2[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &b - ); - } - } - else if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("alpha") == 0) || s.compare("c") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<AbsDiffResidual_alpha_c, 1, 1, 1>( - new AbsDiffResidual_alpha_c(val_1[ss], val_2[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &c - ); - } - } - else if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("a") == 0) || s.compare("b") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<AbsDiffResidual_a_b, 1, 1, 1>( - new AbsDiffResidual_a_b(val_1[ss], val_2[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[1], &b - ); - } - } - else if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("a") == 0) || s.compare("c") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<AbsDiffResidual_a_c, 1, 1, 1>( - new AbsDiffResidual_a_c(val_1[ss], val_2[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[1], &c - ); - } - } - else - throw std::logic_error("Invalid parameter in the parameter list."); - } - else if(param_list.size() == 1) - { - if(std::any_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("alpha") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<AbsDiffResidual_alpha, 1, 1>( - new AbsDiffResidual_alpha(val_1[ss], val_2[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0] - ); - } - } - else if(std::any_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("a") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<AbsDiffResidual_a, 1, 1>( - new AbsDiffResidual_a(val_1[ss], val_2[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[1] - ); - } - } - else - throw std::logic_error("Invalid parameter in the parameter list."); - } - parameterize(problem); -} diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/parameterized_absolute_difference.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/parameterized_absolute_difference.cpp new file mode 100644 index 00000000..4d16edf3 --- /dev/null +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/parameterized_absolute_difference.cpp @@ -0,0 +1,65 @@ +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/parameterized_absolute_difference.hpp> + +AbsDiffParamNode::AbsDiffParamNode() +{} + +AbsDiffParamNode::AbsDiffParamNode(std::array<node_ptr, 2> feats, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop): + AbsDiffNode(feats, feat_ind) +{ + _params.resize(n_params(), 0.0); + get_parameters(prop); + set_value(); + if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) + throw InvalidFeatureException(); + + set_test_value(); +} + +AbsDiffParamNode::AbsDiffParamNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop): + AbsDiffNode({feat_1, feat_2}, feat_ind) +{ + _params.resize(n_params(), 0.0); + get_parameters(prop); + set_value(); + if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) + throw InvalidFeatureException(); + + set_test_value(); +} + +AbsDiffParamNode::AbsDiffParamNode(std::array<node_ptr, 2> feats, int feat_ind, double l_bound, double u_bound): + AbsDiffNode(feats, feat_ind) +{ + _params.resize(n_params(), 0.0); +} + +AbsDiffParamNode::AbsDiffParamNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound): + AbsDiffNode({feat_1, feat_2}, feat_ind) +{ + _params.resize(n_params(), 0.0); +} + +void AbsDiffParamNode::get_parameters(std::vector<double>& prop) +{ + nlopt_wrapper::feat_data d; + d._feat = this; + d._prop = prop.data(); + double minf; + + std::fill_n(_params.begin(), _params.size(), 1.0); + dcopy_(_params.size() / 2, nlopt_wrapper::_zeros.data(), 1, &_params[1], 2); + + nlopt::opt opt(nlopt::LN_SBPLX, _params.size()); + opt.set_min_objective(nlopt_wrapper::objective_reg, &d); + opt.set_maxeval(1000); + opt.set_xtol_rel(1e-2); + try + { + nlopt::result result = opt.optimize(_params, minf); + } + catch(std::exception &e) + { + std::fill_n(_params.begin(), _params.size(), 1.0); + dcopy_(_params.size() / 2, nlopt_wrapper::_zeros.data(), 1, &_params[1], 2); + } +} \ No newline at end of file diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/parameterized_absolute_difference.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/parameterized_absolute_difference.hpp new file mode 100644 index 00000000..30b3c919 --- /dev/null +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/parameterized_absolute_difference.hpp @@ -0,0 +1,153 @@ +/** @file feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/parameterized_absolute_difference.hpp + * @brief Class describing the parameterized absolute difference operator + * + * This class represents the parameterized unary operator -> |A - alpha * B + a| + * + * @author Thomas A. R. Purcell (tpurcell) + * @bug No known bugs. + */ +#ifndef PARAM_ABS_DIFF_NODE +#define PARAM_ABS_DIFF_NODE + +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/absolute_difference.hpp> +#include <feature_creation/parameterization/NLOptWrapper.hpp> + +// DocString: cls_abs_node +/** + * @brief Node for the absolute value operator + * + */ +class AbsDiffParamNode: public AbsDiffNode +{ + using AbsDiffNode::set_value; + using AbsDiffNode::set_test_value; + using AbsDiffNode::domain; + using AbsDiffNode::expr; + + friend class boost::serialization::access; + + /** + * @brief Serialization function to send over MPI + * + * @param ar Archive representation of node + */ + template <typename Archive> + void serialize(Archive& ar, const unsigned int version) + { + ar & boost::serialization::base_object<AbsDiffNode>(*this); + ar & _params; + } +protected: + std::vector<double> _params; +public: + /** + * @brief Base Constructor + * @details This is only used for serialization + */ + AbsDiffParamNode(); + + /** + * @brief Constructor + * @details Constructs the Node from node pointer of the feature to operate on + * + * @param feat_1 shared_ptr of the feature to operate on (A) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + * @param prop The property to fit to + */ + AbsDiffParamNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop); + + /** + * @brief Constructor + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + * @param prop The property to fit to + */ + AbsDiffParamNode(std::array<node_ptr, 2> feats, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop); + + /** + * @brief Constructor + * @details Constructs the Node from node pointer of the feature to operate on + * + * @param feat_1 shared_ptr of the feature to operate on (A) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + * @param prop The property to fit to + */ + AbsDiffParamNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound); + + /** + * @brief Constructor + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + * @param prop The property to fit to + */ + AbsDiffParamNode(std::array<node_ptr, 2> feats, int feat_ind, double l_bound, double u_bound); + + // DocString: abs_diff_param_node_set_value + /** + * @brief Set the values of the training data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + */ + inline void set_value(int offset = -1){set_value(_params.data(), offset);} + + // DocString: abs_diff_param_node_set_test_value + /** + * @brief Set the values of the test data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + */ + inline void set_test_value(int offset = -1){set_test_value(_params.data(), offset);} + + // DocString: abs_diff_param_node_expr + /** + * @brief Get the expression for the overall feature (From root node down) + */ + inline std::string expr(){return expr(_params.data());} + + // DocString: abs_diff_param_node_domain + /** + * @brief The domain for the feature (min/max values) + */ + inline Domain domain(){return domain(_params.data());} + + /** + * @brief The parameters used for introducing more non linearity in the operators + */ + inline std::vector<double> parameters(){return _params;} + + /** + * @brief Solve the non-linear optimization to set the parameters + * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * + * @param prop property to fit to get the parameters + */ + void get_parameters(std::vector<double>& prop); + + /** + * @brief Set the non-linear parameters + */ + inline void set_parameters(std::vector<double> params) + { + if(params.size() != n_params()) + throw std::logic_error("Wrong number of parameters passed to set_parameters."); + _params = params; + } +}; + +#endif \ No newline at end of file diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add/add.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add/add.cpp index d6b04aeb..242ba188 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add/add.cpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add/add.cpp @@ -27,6 +27,15 @@ AddNode::AddNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, set_test_value(); } +AddNode::AddNode(std::array<node_ptr, 2> feats, int feat_ind): + OperatorNode(feats, feat_ind) +{ + check_feats(); + + set_value(); + set_test_value(); +} + void AddNode::check_feats() { if(_feats[0]->unit() != _feats[1]->unit()) diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add/add.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add/add.hpp index 25dab841..f3375b37 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add/add.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add/add.hpp @@ -61,6 +61,15 @@ public: */ AddNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound); + /** + * @brief Constructor without checking feature values + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + */ + AddNode(std::array<node_ptr, 2> feats, int feat_ind); + // DocString: add_node_unit /** * @brief Get the unit of the feature (combine the units of _feats) @@ -71,7 +80,7 @@ public: /** * @brief Get the expression for the overall feature (From root node down) */ - inline std::string expr(){return "(" + _feats[0]->expr() + " + " + std::to_string(_params[0]) + "*" + _feats[1]->expr() + " + " + std::to_string(_params[1]) + ")";} + inline std::string expr(){return "[" + _feats[0]->expr() + " + " + _feats[1]->expr() + "]";} // DocString: add_node_set_value /** @@ -81,11 +90,11 @@ public: */ inline void set_value(int offset = -1) { - if(_selected) - allowed_op_funcs::add(_n_samp, _feats[0]->value_ptr(offset + 2), _feats[1]->value_ptr(offset + 1), _params[0], _params[1], node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); - offset = (offset == -1) ? rung() : offset; - allowed_op_funcs::add(_n_samp, _feats[0]->value_ptr(offset + 2), _feats[1]->value_ptr(offset + 1), _params[0], _params[1], node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); + + if(_selected) + allowed_op_funcs::add(_n_samp, _feats[0]->value_ptr(offset + 2), _feats[1]->value_ptr(offset + 1), 1.0, 0.0, node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); + allowed_op_funcs::add(_n_samp, _feats[0]->value_ptr(offset + 2), _feats[1]->value_ptr(offset + 1), 1.0, 0.0, node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); } // DocString: add_node_set_test_value @@ -97,7 +106,7 @@ public: inline void set_test_value(int offset = -1) { offset = (offset == -1) ? rung() : offset; - allowed_op_funcs::add(_n_test_samp, _feats[0]->test_value_ptr(offset + 2), _feats[1]->test_value_ptr(offset + 1), _params[0], _params[1], node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); + allowed_op_funcs::add(_n_test_samp, _feats[0]->test_value_ptr(offset + 2), _feats[1]->test_value_ptr(offset + 1), 1.0, 0.0, node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); } // DocString: add_node_rung @@ -117,7 +126,7 @@ public: /** * @brief The domain for the feature (min/max values) */ - Domain domain(){return _feats[0]->domain().add(_feats[1]->domain(), _params[0], _params[1]);} + Domain domain(){return _feats[0]->domain().add(_feats[1]->domain(), 1.0, 0.0);} /** * @brief Get the string character representation of the node for the postfix expression @@ -152,39 +161,65 @@ public: #ifdef PARAMETERIZE /** - * @brief Constructor - * @details Constructs the Node from an array of features to operate on + * @brief The parameters used for introducing more non linearity in the operators + */ + virtual std::vector<double> parameters(){return {};} + + /** + * @brief Solve the non-linear optimization to set the parameters + * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature * - * @param feats Features to operate over (Edges of the graph) - * @param feat_ind Index of the new feature - * @param l_bound Minimum absolute value allowed for the feature. - * @param u_bound Maximum absolute value allowed for the feature. - * @param param_list The list of parameters to optimize using non-linear least squares - * @param prop The property to fit to + * @param prop property to fit to get the parameters */ - AddNode(std::array<node_ptr, 2> feats, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop); + virtual void get_parameters(std::vector<double>& prop){return;} + + /** + * @brief Set the non-linear parameters + */ + virtual void set_parameters(std::vector<double>){return;} /** - * @brief Constructor - * @details Constructs the Node from node pointer of the feature to operate on + * @brief Set the values of the training data for the feature inside of the value storage arrays * - * @param feat_1 shared_ptr of the feature to operate on (A) - * @param feat_ind Index of the new feature - * @param l_bound Minimum absolute value allowed for the feature. - * @param u_bound Maximum absolute value allowed for the feature. - * @param param_list The list of parameters to optimize using non-linear least squares - * @param prop The property to fit to + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values */ - AddNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop); + inline void set_value(const double* params, int offset = -1) + { + offset = (offset == -1) ? rung() : offset; + + if(_selected) + allowed_op_funcs::add(_n_samp, _feats[0]->value_ptr(params + 2 + _feats[1]->n_params(), offset + 2), _feats[1]->value_ptr(params + 2, offset + 1), params[0], params[1], node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); + allowed_op_funcs::add(_n_samp, _feats[0]->value_ptr(params + 2 + _feats[1]->n_params(), offset + 2), _feats[1]->value_ptr(params + 2, offset + 1), params[0], params[1], node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); + } /** - * @brief Solve the non-linear optimization to set the parameters - * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * @brief Set the values of the test data for the feature inside of the value storage arrays * - * @param prop property to fit to get the parameters - * @param param_list List describing the parameters to fit + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values + */ + inline void set_test_value(const double* params, int offset = -1) + { + offset = (offset == -1) ? rung() : offset; + allowed_op_funcs::add(_n_test_samp, _feats[0]->test_value_ptr(params + 2 + _feats[1]->n_params(), offset + 2), _feats[1]->test_value_ptr(params + 2, offset + 1), params[0], params[1], node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); + } + + /** + * @brief The domain for the feature (min/max values) + * + * @param params parameter values for non-linear operations + * @return the domain + */ + inline Domain domain(double* params){return _feats[0]->domain(params + 2 + _feats[1]->n_params()).add(_feats[1]->domain(params + 2), params[0], params[1]);} + + /** + * @brief The expression of the feature + * + * @param params parameter values for non-linear operations + * @return feature expression */ - void get_parameters(std::vector<double>& prop, std::vector<std::string>& param_list); + inline std::string expr(double* params){return "[" + _feats[0]->expr(params + _feats[1]->n_params() + 2) + " + (" + std::to_string(params[0]) + "*" + _feats[1]->expr(params + 2) + " + " + std::to_string(params[1]) + ")]";} #endif }; diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add/parameterize.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add/parameterize.cpp deleted file mode 100644 index 9a135f52..00000000 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add/parameterize.cpp +++ /dev/null @@ -1,105 +0,0 @@ -#include <feature_creation/node/operator_nodes/allowed_operator_nodes/add/add.hpp> - -AddNode::AddNode(std::array<node_ptr, 2> feats, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop) : - OperatorNode(feats, feat_ind) -{ - check_feats(); - - get_parameters(prop, param_list); - set_value(); - if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) - throw InvalidFeatureException(); - - set_test_value(); -} - -AddNode::AddNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop) : - OperatorNode({feat_1, feat_2}, feat_ind) -{ - check_feats(); - - get_parameters(prop, param_list); - set_value(); - if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) - throw InvalidFeatureException(); - - set_test_value(); -} - -void AddNode::get_parameters(std::vector<double>& prop, std::vector<std::string>& param_list) -{ - if(param_list.size() == 0) - return; - Problem problem; - double b = 0.0, c = 0.0; - double* val_1 = _feats[0]->value_ptr(rung() + 2); - double* val_2 = _feats[1]->value_ptr(rung() + 1); - - if(param_list.size() > 3) - { - throw std::logic_error("Too many parameters passed to the constructor."); - } - else if(param_list.size() == 3) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<AddResidual_alpha_b_c, 1, 1, 1, 1>( - new AddResidual_alpha_b_c(val_1[ss], val_2[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &b, &c - ); - } - } - else if(param_list.size() == 2) - { - if(std::none_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("c") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<AddResidual_alpha_b, 1, 1, 1>( - new AddResidual_alpha_b(val_1[ss], val_2[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &b - ); - } - } - else if(std::none_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("b") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<AddResidual_alpha_c, 1, 1, 1>( - new AddResidual_alpha_c(val_1[ss], val_2[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &c - ); - } - } - else - throw std::logic_error("Invalid parameter in the parameter list."); - } - else if(param_list.size() == 1) - { - if(std::any_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("alpha") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<AddResidual_alpha, 1, 1>( - new AddResidual_alpha(val_1[ss], val_2[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0] - ); - } - } - else - throw std::logic_error("Invalid parameter in the parameter list."); - } - parameterize(problem); -} diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add/parameterized_add.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add/parameterized_add.cpp new file mode 100644 index 00000000..c38656ce --- /dev/null +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add/parameterized_add.cpp @@ -0,0 +1,65 @@ +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/add/parameterized_add.hpp> + +AddParamNode::AddParamNode() +{} + +AddParamNode::AddParamNode(std::array<node_ptr, 2> feats, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop) : + AddNode(feats, feat_ind) +{ + _params.resize(n_params(), 0.0); + get_parameters(prop); + set_value(); + if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) + throw InvalidFeatureException(); + + set_test_value(); +} + +AddParamNode::AddParamNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop) : + AddNode({feat_1, feat_2}, feat_ind) +{ + _params.resize(n_params(), 0.0); + get_parameters(prop); + set_value(); + if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) + throw InvalidFeatureException(); + + set_test_value(); +} + +AddParamNode::AddParamNode(std::array<node_ptr, 2> feats, int feat_ind, double l_bound, double u_bound) : + AddNode(feats, feat_ind) +{ + _params.resize(n_params(), 0.0); +} + +AddParamNode::AddParamNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound) : + AddNode({feat_1, feat_2}, feat_ind) +{ + _params.resize(n_params(), 0.0); +} + +void AddParamNode::get_parameters(std::vector<double>& prop) +{ + nlopt_wrapper::feat_data d; + d._feat = this; + d._prop = prop.data(); + double minf; + + std::fill_n(_params.begin(), _params.size(), 1.0); + dcopy_(_params.size() / 2, nlopt_wrapper::_zeros.data(), 1, &_params[1], 2); + + nlopt::opt opt(nlopt::LN_SBPLX, _params.size()); + opt.set_min_objective(nlopt_wrapper::objective_reg, &d); + opt.set_maxeval(1000); + opt.set_xtol_rel(1e-2); + try + { + nlopt::result result = opt.optimize(_params, minf); + } + catch(std::exception &e) + { + std::fill_n(_params.begin(), _params.size(), 1.0); + dcopy_(_params.size() / 2, nlopt_wrapper::_zeros.data(), 1, &_params[1], 2); + } +} diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add/parameterized_add.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add/parameterized_add.hpp new file mode 100644 index 00000000..8392f49a --- /dev/null +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add/parameterized_add.hpp @@ -0,0 +1,151 @@ +/** @file feature_creation/node/operator_nodes/allowed_operator_nodes/add/parameterized_add.hpp + * @brief Class describing the parameterized addition operator + * + * This class represents the parameterized unary operator -> A + alpha * B + a + * + * @author Thomas A. R. Purcell (tpurcell) + * @bug No known bugs. + */ +#ifndef PARAM_ADD_NODE +#define PARAM_ADD_NODE + +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/add/add.hpp> +#include <feature_creation/parameterization/NLOptWrapper.hpp> + +// DocString: cls_param_add_node +/** + * @brief Node for the absolute value operator + * + */ +class AddParamNode: public AddNode +{ + using AddNode::set_value; + using AddNode::set_test_value; + using AddNode::domain; + using AddNode::expr; + + friend class boost::serialization::access; + + /** + * @brief Serialization function to send over MPI + * + * @param ar Archive representation of node + */ + template <typename Archive> + void serialize(Archive& ar, const unsigned int version) + { + ar & boost::serialization::base_object<AddNode>(*this); + ar & _params; + } +protected: + std::vector<double> _params; +public: + /** + * @brief Base Constructor + * @details This is only used for serialization + */ + AddParamNode(); + + /** + * @brief Constructor + * @details Constructs the Node from node pointer of the feature to operate on + * + * @param feat_1 shared_ptr of the feature to operate on (A) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + * @param prop The property to fit to + */ + AddParamNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop); + + /** + * @brief Constructor + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + * @param prop The property to fit to + */ + AddParamNode(std::array<node_ptr, 2> feats, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop); + + /** + * @brief Constructor + * @details Constructs the Node from node pointer of the feature to operate on + * + * @param feat_1 shared_ptr of the feature to operate on (A) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + */ + AddParamNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound); + + /** + * @brief Constructor + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + */ + AddParamNode(std::array<node_ptr, 2> feats, int feat_ind, double l_bound, double u_bound); + + // DocString: add_param_node_set_value + /** + * @brief Set the values of the training data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + */ + inline void set_value(int offset = -1){set_value(_params.data(), offset);} + + // DocString: add_param_node_set_test_value + /** + * @brief Set the values of the test data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + */ + inline void set_test_value(int offset = -1){set_test_value(_params.data(), offset);} + + // DocString: add_param_node_expr + /** + * @brief Get the expression for the overall feature (From root node down) + */ + inline std::string expr(){return expr(_params.data());} + + // DocString: add_param_node_domain + /** + * @brief The domain for the feature (min/max values) + */ + inline Domain domain(){return domain(_params.data());} + + /** + * @brief The parameters used for introducing more non linearity in the operators + */ + inline std::vector<double> parameters(){return _params;} + + /** + * @brief Solve the non-linear optimization to set the parameters + * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * + * @param prop property to fit to get the parameters + */ + void get_parameters(std::vector<double>& prop); + + /** + * @brief Set the non-linear parameters + */ + inline void set_parameters(std::vector<double> params) + { + if(params.size() != n_params()) + throw std::logic_error("Wrong number of parameters passed to set_parameters."); + _params = params; + } +}; + +#endif \ No newline at end of file diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cb/cube.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cb/cube.cpp index aa5b30ed..7bce9b46 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cb/cube.cpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cb/cube.cpp @@ -29,6 +29,16 @@ CbNode::CbNode(node_ptr feat, int feat_ind, double l_bound, double u_bound): set_test_value(); } +CbNode::CbNode(std::array<node_ptr, 1> feats, int feat_ind): + OperatorNode(feats, feat_ind) +{ + if((feats[0]->type() == NODE_TYPE::CBRT) || (feats[0]->type() == NODE_TYPE::SQ) || (feats[0]->type() == NODE_TYPE::INV)) + throw InvalidFeatureException(); + + set_value(); + set_test_value(); +} + void CbNode::update_add_sub_leaves(std::map<std::string, int>& add_sub_leaves, int pl_mn, int& expected_abs_tot) { std::string key = expr(); diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cb/cube.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cb/cube.hpp index f1124a88..81a1aef8 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cb/cube.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cb/cube.hpp @@ -60,6 +60,15 @@ public: */ CbNode(node_ptr feat, int feat_ind, double l_bound, double u_bound); + /** + * @brief Constructor without checking feature values + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + */ + CbNode(std::array<node_ptr, 1> feats, int feat_ind); + // DocString: cb_node_unit /** * @brief Get the unit of the feature (combine the units of _feats) @@ -70,7 +79,7 @@ public: /** * @brief Get the expression for the overall feature (From root node down) */ - inline std::string expr(){return "(" + std::to_string(_params[0]) + "*" + _feats[0]->expr() + " + " + std::to_string(_params[1]) + ")^3";} + inline std::string expr(){return "(" + _feats[0]->expr() + ")^3";} // DocString: cb_node_set_value /** @@ -80,11 +89,11 @@ public: */ inline void set_value(int offset = -1) { - if(_selected) - allowed_op_funcs::cb(_n_samp, _feats[0]->value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); - offset = (offset == -1) ? rung() : offset; - allowed_op_funcs::cb(_n_samp, _feats[0]->value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); + + if(_selected) + allowed_op_funcs::cb(_n_samp, _feats[0]->value_ptr(offset + 2), 1.0, 0.0, node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); + allowed_op_funcs::cb(_n_samp, _feats[0]->value_ptr(offset + 2), 1.0, 0.0, node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); } // DocString: cb_node_set_test_value @@ -96,7 +105,7 @@ public: inline void set_test_value(int offset = -1) { offset = (offset == -1) ? rung() : offset; - allowed_op_funcs::cb(_n_test_samp, _feats[0]->test_value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); + allowed_op_funcs::cb(_n_test_samp, _feats[0]->test_value_ptr(offset + 2), 1.0, 0.0, node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); } // DocString: cb_node_rung @@ -116,7 +125,7 @@ public: /** * @brief The domain for the feature (min/max values) */ - Domain domain(){return _feats[0]->domain().pow(3.0, _params[0], _params[1]);} + Domain domain(){return _feats[0]->domain().pow(3.0, 1.0, 0.0);} /** * @brief Get the string character representation of the node for the postfix expression @@ -145,39 +154,66 @@ public: #ifdef PARAMETERIZE /** - * @brief Constructor - * @details Constructs the Node from an array of features to operate on + * @brief The parameters used for introducing more non linearity in the operators + */ + virtual std::vector<double> parameters(){return {};} + + /** + * @brief Solve the non-linear optimization to set the parameters + * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * + * @param prop property to fit to get the parameters + */ + virtual void get_parameters(std::vector<double>& prop){return;} + + /** + * @brief Set the non-linear parameters + */ + virtual void set_parameters(std::vector<double>){return;} + + /** + * @brief Set the values of the training data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values + */ + inline void set_value(const double* params, int offset = -1) + { + offset = (offset == -1) ? rung() : offset; + if(_selected) + allowed_op_funcs::cb(_n_samp, _feats[0]->value_ptr(params + 2, offset + 2), params[0], params[1], node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); + + allowed_op_funcs::cb(_n_samp, _feats[0]->value_ptr(params + 2, offset + 2), params[0], params[1], node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset, false)); + } + + /** + * @brief Set the values of the test data for the feature inside of the value storage arrays * - * @param feats Features to operate over (Edges of the graph) - * @param feat_ind Index of the new feature - * @param l_bound Minimum absolute value allowed for the feature. - * @param u_bound Maximum absolute value allowed for the feature. - * @param param_list The list of parameters to optimize using non-linear least squares - * @param prop The property to fit to + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values */ - CbNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop); + inline void set_test_value(const double* params, int offset = -1) + { + offset = (offset == -1) ? rung() : offset; + allowed_op_funcs::cb(_n_test_samp, _feats[0]->test_value_ptr(params + 2, offset + 2), params[0], params[1], node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset, false)); + } /** - * @brief Constructor - * @details Constructs the Node from node pointer of the feature to operate on + * @brief The domain for the feature (min/max values) * - * @param feat_1 shared_ptr of the feature to operate on (A) - * @param feat_ind Index of the new feature - * @param l_bound Minimum absolute value allowed for the feature. - * @param u_bound Maximum absolute value allowed for the feature. - * @param param_list The list of parameters to optimize using non-linear least squares - * @param prop The property to fit to + * @param params parameter values for non-linear operations + * @return the domain */ - CbNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop); + inline Domain domain(double* params){return _feats[0]->domain(params + 2).pow(3.0, params[0], params[1]);} /** - * @brief Solve the non-linear optimization to set the parameters - * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * @brief The expression of the feature * - * @param prop property to fit to get the parameters - * @param param_list List describing the parameters to fit + * @param params parameter values for non-linear operations + * @return feature expression */ - void get_parameters(std::vector<double>& prop, std::vector<std::string>& param_list); + inline std::string expr(double* params){return "(" + std::to_string(params[0]) + "*" + _feats[0]->expr(params + 2) + " + " + std::to_string(params[1]) + ")^3";} + #endif }; diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cb/parameterize.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cb/parameterize.cpp deleted file mode 100644 index 738c7f53..00000000 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cb/parameterize.cpp +++ /dev/null @@ -1,105 +0,0 @@ -#include <feature_creation/node/operator_nodes/allowed_operator_nodes/cb/cube.hpp> - -CbNode::CbNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop) : - OperatorNode(feats, feat_ind) -{ - if((feats[0]->type() == NODE_TYPE::CBRT) || (feats[0]->type() == NODE_TYPE::SQ) || (feats[0]->type() == NODE_TYPE::INV)) - throw InvalidFeatureException(); - - get_parameters(prop, param_list); - set_value(); - if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) - throw InvalidFeatureException(); - - set_test_value(); -} - -CbNode::CbNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop) : - OperatorNode({feat}, feat_ind) -{ - if((feat->type() == NODE_TYPE::CBRT) || (feat->type() == NODE_TYPE::SQ) || (feat->type() == NODE_TYPE::INV)) - throw InvalidFeatureException(); - - get_parameters(prop, param_list); - set_value(); - if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) - throw InvalidFeatureException(); - - set_test_value(); -} - -void CbNode::get_parameters(std::vector<double>& prop, std::vector<std::string>& param_list) -{ - if(param_list.size() == 0) - return; - Problem problem; - double c = 0.0; - double* val = _feats[0]->value_ptr(rung() + 2); - if(param_list.size() > 3) - { - throw std::logic_error("Too many parameters passed to the constructor."); - } - else if(param_list.size() == 3) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<CbResidual_alpha_a_c, 1, 1, 1, 1>( - new CbResidual_alpha_a_c(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &_params[1], &c - ); - } - } - else if(param_list.size() == 2) - { - if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("alpha") == 0) || s.compare("a") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<CbResidual_alpha_a, 1, 1, 1>( - new CbResidual_alpha_a(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &_params[1] - ); - } - } - else if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("a") == 0) || s.compare("c") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<CbResidual_a_c, 1, 1, 1>( - new CbResidual_a_c(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[1], &c - ); - } - } - else - throw std::logic_error("Invalid parameter in the parameter list."); - } - else if(param_list.size() == 1) - { - if(std::any_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("a") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<CbResidual_a, 1, 1>( - new CbResidual_a(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[1] - ); - } - } - else - throw std::logic_error("Invalid parameter in the parameter list."); - } - parameterize(problem); -} diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cb/parameterized_cube.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cb/parameterized_cube.cpp new file mode 100644 index 00000000..31c761c5 --- /dev/null +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cb/parameterized_cube.cpp @@ -0,0 +1,67 @@ +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/cb/parameterized_cube.hpp> + +CbParamNode::CbParamNode() +{} + +CbParamNode::CbParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop) : + CbNode(feats, feat_ind) +{ + _params.resize(n_params(), 0.0); + + get_parameters(prop); + set_value(); + if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) + throw InvalidFeatureException(); + + set_test_value(); +} + +CbParamNode::CbParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop) : + CbNode({feat}, feat_ind) +{ + _params.resize(n_params(), 0.0); + + get_parameters(prop); + set_value(); + if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) + throw InvalidFeatureException(); + + set_test_value(); +} + +CbParamNode::CbParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound) : + CbNode(feats, feat_ind) +{ + _params.resize(n_params(), 0.0); +} + +CbParamNode::CbParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound) : + CbNode({feat}, feat_ind) +{ + _params.resize(n_params(), 0.0); +} + +void CbParamNode::get_parameters(std::vector<double>& prop) +{ + nlopt_wrapper::feat_data d; + d._feat = this; + d._prop = prop.data(); + double minf; + + std::fill_n(_params.begin(), _params.size(), 1.0); + dcopy_(_params.size() / 2, nlopt_wrapper::_zeros.data(), 1, &_params[1], 2); + + nlopt::opt opt(nlopt::LN_SBPLX, _params.size()); + opt.set_min_objective(nlopt_wrapper::objective_reg, &d); + opt.set_maxeval(1000); + opt.set_xtol_rel(1e-2); + try + { + nlopt::result result = opt.optimize(_params, minf); + } + catch(std::exception &e) + { + std::fill_n(_params.begin(), _params.size(), 1.0); + dcopy_(_params.size() / 2, nlopt_wrapper::_zeros.data(), 1, &_params[1], 2); + } +} diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cb/parameterized_cube.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cb/parameterized_cube.hpp new file mode 100644 index 00000000..8755debd --- /dev/null +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cb/parameterized_cube.hpp @@ -0,0 +1,153 @@ +/** @file feature_creation/node/operator_nodes/allowed_operator_nodes/cb/parameterized_cube.hpp + * @brief Class describing the parameterized cube operator + * + * This class represents the parameterized unary operator -> (alpha * A + a)^3 + * + * @author Thomas A. R. Purcell (tpurcell) + * @bug No known bugs. + */ +#ifndef PARAM_CUBE_NODE +#define PARAM_CUBE_NODE + +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/cb/cube.hpp> +#include <feature_creation/parameterization/NLOptWrapper.hpp> + +// DocString: cls_abs_node +/** + * @brief Node for the absolute value operator + * + */ +class CbParamNode: public CbNode +{ + using CbNode::set_value; + using CbNode::set_test_value; + using CbNode::domain; + using CbNode::expr; + + friend class boost::serialization::access; + + /** + * @brief Serialization function to send over MPI + * + * @param ar Archive representation of node + */ + template <typename Archive> + void serialize(Archive& ar, const unsigned int version) + { + ar & boost::serialization::base_object<CbNode>(*this); + ar & _params; + } + +protected: + std::vector<double> _params; //!< The parameters vector + +public: + /** + * @brief Base Constructor + * @details This is only used for serialization + */ + CbParamNode(); + + /** + * @brief Constructor + * @details Constructs the Node from node pointer of the feature to operate on + * + * @param feat_1 shared_ptr of the feature to operate on (A) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + * @param prop The property to fit to + */ + CbParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop); + + /** + * @brief Constructor + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + * @param prop The property to fit to + */ + CbParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop); + + /** + * @brief Constructor + * @details Constructs the Node from node pointer of the feature to operate on + * + * @param feat_1 shared_ptr of the feature to operate on (A) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + */ + CbParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound); + + /** + * @brief Constructor + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + */ + CbParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound); + + // DocString: cb_param_node_set_value + /** + * @brief Set the values of the training data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + */ + inline void set_value(int offset = -1){set_value(_params.data(), offset);} + + // DocString: cb_param_node_set_test_value + /** + * @brief Set the values of the test data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + */ + inline void set_test_value(int offset = -1){set_test_value(_params.data(), offset);} + + // DocString: cb_param_node_expr + /** + * @brief Get the expression for the overall feature (From root node down) + */ + inline std::string expr(){return expr(_params.data());} + + // DocString: cb_param_node_domain + /** + * @brief The domain for the feature (min/max values) + */ + inline Domain domain(){return domain(_params.data());} + + /** + * @brief The parameters used for introducing more non linearity in the operators + */ + inline std::vector<double> parameters(){return _params;} + + /** + * @brief Solve the non-linear optimization to set the parameters + * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * + * @param prop property to fit to get the parameters + */ + void get_parameters(std::vector<double>& prop); + + /** + * @brief Set the non-linear parameters + */ + inline void set_parameters(std::vector<double> params) + { + if(params.size() != n_params()) + throw std::logic_error("Wrong number of parameters passed to set_parameters."); + _params = params; + } +}; + +#endif \ No newline at end of file diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/cube_root.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/cube_root.cpp index 58644993..b0f29fde 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/cube_root.cpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/cube_root.cpp @@ -35,6 +35,16 @@ CbrtNode::CbrtNode(node_ptr feat, int feat_ind, double l_bound, double u_bound): set_test_value(); } +CbrtNode::CbrtNode(std::array<node_ptr, 1> feats, int feat_ind): + OperatorNode(feats, feat_ind) +{ + if((feats[0]->type() == NODE_TYPE::CB) || (feats[0]->type() == NODE_TYPE::SQ) || (feats[0]->type() == NODE_TYPE::SIX_POW) || (feats[0]->type() == NODE_TYPE::INV)) + throw InvalidFeatureException(); + + set_value(); + set_test_value(); +} + void CbrtNode::update_add_sub_leaves(std::map<std::string, int>& add_sub_leaves, int pl_mn, int& expected_abs_tot) { std::string key = expr(); diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/cube_root.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/cube_root.hpp index a6a568ee..fa660bab 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/cube_root.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/cube_root.hpp @@ -60,6 +60,15 @@ public: */ CbrtNode(node_ptr feat, int feat_ind, double l_bound, double u_bound); + /** + * @brief Constructor without checking feature values + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + */ + CbrtNode(std::array<node_ptr, 1> feats, int feat_ind); + // DocString: cbrt_node_unit /** * @brief Get the unit of the feature (combine the units of _feats) @@ -70,7 +79,7 @@ public: /** * @brief Get the expression for the overall feature (From root node down) */ - inline std::string expr(){return "cbrt(" + std::to_string(_params[0]) + "*" + _feats[0]->expr() + " + " + std::to_string(_params[1]) + ")";} + inline std::string expr(){return "cbrt(" + _feats[0]->expr() + ")";} // DocString: cbrt_node_set_value /** @@ -80,11 +89,11 @@ public: */ inline void set_value(int offset = -1) { - if(_selected) - allowed_op_funcs::cbrt(_n_samp, _feats[0]->value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); - offset = (offset == -1) ? rung() : offset; - allowed_op_funcs::cbrt(_n_samp, _feats[0]->value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); + + if(_selected) + allowed_op_funcs::cbrt(_n_samp, _feats[0]->value_ptr(offset + 2), 1.0, 0.0, node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); + allowed_op_funcs::cbrt(_n_samp, _feats[0]->value_ptr(offset + 2), 1.0, 0.0, node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); } // DocString: cbrt_node_set_test_value @@ -96,7 +105,7 @@ public: inline void set_test_value(int offset = -1) { offset = (offset == -1) ? rung() : offset; - allowed_op_funcs::cbrt(_n_test_samp, _feats[0]->test_value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); + allowed_op_funcs::cbrt(_n_test_samp, _feats[0]->test_value_ptr(offset + 2), 1.0, 0.0, node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); } // DocString: cbrt_node_rung @@ -116,7 +125,7 @@ public: /** * @brief The domain for the feature (min/max values) */ - Domain domain(){return _feats[0]->domain().pow(1.0 / 3.0, _params[0], _params[1]);} + Domain domain(){return _feats[0]->domain().pow(1.0 / 3.0, 1.0, 0.0);} /** * @brief Get the string character representation of the node for the postfix expression @@ -145,39 +154,66 @@ public: #ifdef PARAMETERIZE /** - * @brief Constructor - * @details Constructs the Node from an array of features to operate on + * @brief The parameters used for introducing more non linearity in the operators + */ + virtual std::vector<double> parameters(){return {};} + + /** + * @brief Solve the non-linear optimization to set the parameters + * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * + * @param prop property to fit to get the parameters + */ + virtual void get_parameters(std::vector<double>& prop){return;} + + /** + * @brief Set the non-linear parameters + */ + virtual void set_parameters(std::vector<double>){return;} + + /** + * @brief Set the values of the training data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values + */ + inline void set_value(const double* params, int offset = -1) + { + offset = (offset == -1) ? rung() : offset; + if(_selected) + allowed_op_funcs::cbrt(_n_samp, _feats[0]->value_ptr(params + 2, offset + 2), params[0], params[1], node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); + + allowed_op_funcs::cbrt(_n_samp, _feats[0]->value_ptr(params + 2, offset + 2), params[0], params[1], node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset, false)); + } + + /** + * @brief Set the values of the test data for the feature inside of the value storage arrays * - * @param feats Features to operate over (Edges of the graph) - * @param feat_ind Index of the new feature - * @param l_bound Minimum absolute value allowed for the feature. - * @param u_bound Maximum absolute value allowed for the feature. - * @param param_list The list of parameters to optimize using non-linear least squares - * @param prop The property to fit to + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values */ - CbrtNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop); + inline void set_test_value(const double* params, int offset = -1) + { + offset = (offset == -1) ? rung() : offset; + allowed_op_funcs::cbrt(_n_test_samp, _feats[0]->test_value_ptr(params + 2, offset + 2), params[0], params[1], node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset, false)); + } /** - * @brief Constructor - * @details Constructs the Node from node pointer of the feature to operate on + * @brief The domain for the feature (min/max values) * - * @param feat_1 shared_ptr of the feature to operate on (A) - * @param feat_ind Index of the new feature - * @param l_bound Minimum absolute value allowed for the feature. - * @param u_bound Maximum absolute value allowed for the feature. - * @param param_list The list of parameters to optimize using non-linear least squares - * @param prop The property to fit to + * @param params parameter values for non-linear operations + * @return the domain */ - CbrtNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop); + inline Domain domain(double* params){return _feats[0]->domain(params + 2).pow(1.0 / 3.0, params[0], params[1]);} /** - * @brief Solve the non-linear optimization to set the parameters - * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * @brief The expression of the feature * - * @param prop property to fit to get the parameters - * @param param_list List describing the parameters to fit + * @param params parameter values for non-linear operations + * @return feature expression */ - void get_parameters(std::vector<double>& prop, std::vector<std::string>& param_list); + inline std::string expr(double* params){return "cbrt(" + std::to_string(params[0]) + "*" + _feats[0]->expr(params + 2) + " + " + std::to_string(params[1]) + ")";} + #endif }; diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/parameterize.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/parameterize.cpp deleted file mode 100644 index ef107ad2..00000000 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/parameterize.cpp +++ /dev/null @@ -1,113 +0,0 @@ -#include <feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/cube_root.hpp> - -CbrtNode::CbrtNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop) : - OperatorNode(feats, feat_ind) -{ - if((feats[0]->type() == NODE_TYPE::CB) || (feats[0]->type() == NODE_TYPE::SQ) || (feats[0]->type() == NODE_TYPE::SIX_POW) || (feats[0]->type() == NODE_TYPE::INV)) - throw InvalidFeatureException(); - - get_parameters(prop, param_list); - - if(_params[0] * _feats[0]->domain() + _params[1] < 0.0) - throw InvalidFeatureException(); - - set_value(); - if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) - throw InvalidFeatureException(); - - set_test_value(); -} - -CbrtNode::CbrtNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop) : - OperatorNode({feat}, feat_ind) -{ - if((feat->type() == NODE_TYPE::CB) || (feat->type() == NODE_TYPE::SQ) || (feat->type() == NODE_TYPE::SIX_POW) || (feat->type() == NODE_TYPE::INV)) - throw InvalidFeatureException(); - - get_parameters(prop, param_list); - - if(_params[0] * _feats[0]->domain() + _params[1] < 0.0) - throw InvalidFeatureException(); - - set_value(); - if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) - throw InvalidFeatureException(); - - set_test_value(); -} - -void CbrtNode::get_parameters(std::vector<double>& prop, std::vector<std::string>& param_list) -{ - if(param_list.size() == 0) - return; - Problem problem; - double c = 0.0; - double* val = _feats[0]->value_ptr(rung() + 2); - if(param_list.size() > 3) - { - throw std::logic_error("Too many parameters passed to the constructor."); - } - else if(param_list.size() == 3) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<CbrtResidual_alpha_a_c, 1, 1, 1, 1>( - new CbrtResidual_alpha_a_c(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &_params[1], &c - ); - } - } - else if(param_list.size() == 2) - { - if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("alpha") == 0) || s.compare("a") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<CbrtResidual_alpha_a, 1, 1, 1>( - new CbrtResidual_alpha_a(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &_params[1] - ); - } - } - else if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("a") == 0) || s.compare("c") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<CbrtResidual_a_c, 1, 1, 1>( - new CbrtResidual_a_c(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[1], &c - ); - } - } - else - throw std::logic_error("Invalid parameter in the parameter list."); - } - else if(param_list.size() == 1) - { - if(std::any_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("a") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<CbrtResidual_a, 1, 1>( - new CbrtResidual_a(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[1] - ); - } - } - else - throw std::logic_error("Invalid parameter in the parameter list."); - } - parameterize(problem); -} \ No newline at end of file diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/parameterized_cube_root.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/parameterized_cube_root.cpp new file mode 100644 index 00000000..80bd717c --- /dev/null +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/parameterized_cube_root.cpp @@ -0,0 +1,75 @@ +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/parameterized_cube_root.hpp> + +CbrtParamNode::CbrtParamNode() +{} + +CbrtParamNode::CbrtParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop) : + CbrtNode(feats, feat_ind) +{ + _params.resize(n_params(), 0.0); + + get_parameters(prop); + + if(_params[0] * _feats[0]->domain() + _params[1] <= 0.0) + throw InvalidFeatureException(); + + set_value(); + if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) + throw InvalidFeatureException(); + + set_test_value(); +} + +CbrtParamNode::CbrtParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop) : + CbrtNode({feat}, feat_ind) +{ + _params.resize(n_params(), 0.0); + + get_parameters(prop); + + if(_params[0] * _feats[0]->domain() + _params[1] <= 0.0) + throw InvalidFeatureException(); + + set_value(); + if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) + throw InvalidFeatureException(); + + set_test_value(); +} + +CbrtParamNode::CbrtParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound) : + CbrtNode(feats, feat_ind) +{ + _params.resize(n_params(), 0.0); +} + +CbrtParamNode::CbrtParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound) : + CbrtNode({feat}, feat_ind) +{ + _params.resize(n_params(), 0.0); +} + +void CbrtParamNode::get_parameters(std::vector<double>& prop) +{ + nlopt_wrapper::feat_data d; + d._feat = this; + d._prop = prop.data(); + double minf; + + std::fill_n(_params.begin(), _params.size(), 1.0); + dcopy_(_params.size() / 2, nlopt_wrapper::_zeros.data(), 1, &_params[1], 2); + + nlopt::opt opt(nlopt::LN_SBPLX, _params.size()); + opt.set_min_objective(nlopt_wrapper::objective_reg, &d); + opt.set_maxeval(1000); + opt.set_xtol_rel(1e-2); + try + { + nlopt::result result = opt.optimize(_params, minf); + } + catch(std::exception &e) + { + std::fill_n(_params.begin(), _params.size(), 1.0); + dcopy_(_params.size() / 2, nlopt_wrapper::_zeros.data(), 1, &_params[1], 2); + } +} diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/parameterized_cube_root.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/parameterized_cube_root.hpp new file mode 100644 index 00000000..f838256d --- /dev/null +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/parameterized_cube_root.hpp @@ -0,0 +1,153 @@ +/** @file feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/parameterized_cube_root.hpp + * @brief Class describing the parameterized cube root operator + * + * This class represents the parameterized unary operator -> cbrt(alpha * A + a) + * + * @author Thomas A. R. Purcell (tpurcell) + * @bug No known bugs. + */ +#ifndef PARAM_CBRT_NODE +#define PARAM_CBRT_NODE + +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/cube_root.hpp> +#include <feature_creation/parameterization/NLOptWrapper.hpp> + +// DocString: cls_abs_node +/** + * @brief Node for the absolute value operator + * + */ +class CbrtParamNode: public CbrtNode +{ + using CbrtNode::set_value; + using CbrtNode::set_test_value; + using CbrtNode::domain; + using CbrtNode::expr; + + friend class boost::serialization::access; + + /** + * @brief Serialization function to send over MPI + * + * @param ar Archive representation of node + */ + template <typename Archive> + void serialize(Archive& ar, const unsigned int version) + { + ar & boost::serialization::base_object<CbrtNode>(*this); + ar & _params; + } + +protected: + std::vector<double> _params; //!< The parameters vector + +public: + /** + * @brief Base Constructor + * @details This is only used for serialization + */ + CbrtParamNode(); + + /** + * @brief Constructor + * @details Constructs the Node from node pointer of the feature to operate on + * + * @param feat_1 shared_ptr of the feature to operate on (A) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + * @param prop The property to fit to + */ + CbrtParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop); + + /** + * @brief Constructor + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + * @param prop The property to fit to + */ + CbrtParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop); + + /** + * @brief Constructor + * @details Constructs the Node from node pointer of the feature to operate on + * + * @param feat_1 shared_ptr of the feature to operate on (A) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + */ + CbrtParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound); + + /** + * @brief Constructor + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + */ + CbrtParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound); + + // DocString: cbrt_param_node_set_value + /** + * @brief Set the values of the training data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + */ + inline void set_value(int offset = -1){set_value(_params.data(), offset);} + + // DocString: cbrt_param_node_set_test_value + /** + * @brief Set the values of the test data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + */ + inline void set_test_value(int offset = -1){set_test_value(_params.data(), offset);} + + // DocString: cbrt_param_node_expr + /** + * @brief Get the expression for the overall feature (From root node down) + */ + inline std::string expr(){return expr(_params.data());} + + // DocString: cbrt_param_node_domain + /** + * @brief The domain for the feature (min/max values) + */ + inline Domain domain(){return domain(_params.data());} + + /** + * @brief The parameters used for introducing more non linearity in the operators + */ + inline std::vector<double> parameters(){return _params;} + + /** + * @brief Solve the non-linear optimization to set the parameters + * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * + * @param prop property to fit to get the parameters + */ + void get_parameters(std::vector<double>& prop); + + /** + * @brief Set the non-linear parameters + */ + inline void set_parameters(std::vector<double> params) + { + if(params.size() != n_params()) + throw std::logic_error("Wrong number of parameters passed to set_parameters."); + _params = params; + } +}; + +#endif \ No newline at end of file diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos/cos.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos/cos.cpp index b60e9512..50f2afff 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos/cos.cpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos/cos.cpp @@ -35,6 +35,16 @@ CosNode::CosNode(node_ptr feat, int feat_ind, double l_bound, double u_bound): set_test_value(); } +CosNode::CosNode(std::array<node_ptr, 1> feats, int feat_ind): + OperatorNode(feats, feat_ind) +{ + if((feats[0]->type() == NODE_TYPE::SIN) || (feats[0]->type() == NODE_TYPE::COS)) + throw InvalidFeatureException(); + + set_value(); + set_test_value(); +} + void CosNode::update_add_sub_leaves(std::map<std::string, int>& add_sub_leaves, int pl_mn, int& expected_abs_tot) { std::string key = expr(); @@ -56,3 +66,19 @@ void CosNode::update_div_mult_leaves(std::map<std::string, double>& div_mult_lea expected_abs_tot += std::abs(fact); } + + +void CosNode::set_value(const double* params, int offset) +{ + offset = (offset == -1) ? rung() : offset; + if(_selected) + allowed_op_funcs::cos(_n_samp, _feats[0]->value_ptr(params + 2, offset + 2), params[0], params[1], node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); + + allowed_op_funcs::cos(_n_samp, _feats[0]->value_ptr(params + 2, offset + 2), params[0], params[1], node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset, false)); +} + +void CosNode::set_test_value(const double* params, int offset) +{ + offset = (offset == -1) ? rung() : offset; + allowed_op_funcs::cos(_n_test_samp, _feats[0]->test_value_ptr(params + 2, offset + 2), params[0], params[1], node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset, false)); +} diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos/cos.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos/cos.hpp index 4f4c9e8f..d52fadeb 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos/cos.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos/cos.hpp @@ -60,6 +60,15 @@ public: */ CosNode(node_ptr feat, int feat_ind, double l_bound, double u_bound); + /** + * @brief Constructor without checking feature values + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + */ + CosNode(std::array<node_ptr, 1> feats, int feat_ind); + // DocString: cos_node_unit /** * @brief Get the unit of the feature (combine the units of _feats) @@ -70,7 +79,7 @@ public: /** * @brief Get the expression for the overall feature (From root node down) */ - inline std::string expr(){return "cos(" + std::to_string(_params[0]) + "*" + _feats[0]->expr() + " + " + std::to_string(_params[1]) + ")";} + inline std::string expr(){return "cos(" + _feats[0]->expr() + ")";} // DocString: cos_node_set_value /** @@ -78,13 +87,13 @@ public: * * @param offset(int) Key to determine which part of the temporary storage array to look into */ - inline void set_value(int offset = -1) + virtual inline void set_value(int offset = -1) { - if(_selected) - allowed_op_funcs::cos(_n_samp, _feats[0]->value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); - offset = (offset == -1) ? rung() : offset; - allowed_op_funcs::cos(_n_samp, _feats[0]->value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); + + if(_selected) + allowed_op_funcs::cos(_n_samp, _feats[0]->value_ptr(offset + 2), 1.0, 0.0, node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); + allowed_op_funcs::cos(_n_samp, _feats[0]->value_ptr(offset + 2), 1.0, 0.0, node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); } // DocString: cos_node_set_test_value @@ -93,10 +102,10 @@ public: * * @param offset(int) Key to determine which part of the temporary storage array to look into */ - inline void set_test_value(int offset = -1) + virtual inline void set_test_value(int offset = -1) { offset = (offset == -1) ? rung() : offset; - allowed_op_funcs::cos(_n_test_samp, _feats[0]->test_value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); + allowed_op_funcs::cos(_n_test_samp, _feats[0]->test_value_ptr(offset + 2), 1.0, 0.0, node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); } // DocString: cos_node_rung @@ -145,40 +154,55 @@ public: #ifdef PARAMETERIZE /** - * @brief Constructor - * @details Constructs the Node from an array of features to operate on + * @brief The parameters used for introducing more non linearity in the operators + */ + virtual std::vector<double> parameters(){return {};} + + /** + * @brief Solve the non-linear optimization to set the parameters + * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * + * @param prop property to fit to get the parameters + */ + virtual void get_parameters(std::vector<double>& prop){return;} + + /** + * @brief Set the non-linear parameters + */ + virtual void set_parameters(std::vector<double>){return;} + + /** + * @brief Set the values of the training data for the feature inside of the value storage arrays * - * @param feats Features to operate over (Edges of the graph) - * @param feat_ind Index of the new feature - * @param l_bound Minimum absolute value allowed for the feature. - * @param u_bound Maximum absolute value allowed for the feature. - * @param param_list The list of parameters to optimize using non-linear least squares - * @param prop The property to fit to + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values */ - CosNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop); + void set_value(const double* params, int offset = -1); /** - * @brief Constructor - * @details Constructs the Node from node pointer of the feature to operate on + * @brief Set the values of the test data for the feature inside of the value storage arrays * - * @param feat_1 shared_ptr of the feature to operate on (A) - * @param feat_ind Index of the new feature - * @param l_bound Minimum absolute value allowed for the feature. - * @param u_bound Maximum absolute value allowed for the feature. - * @param param_list The list of parameters to optimize using non-linear least squares - * @param prop The property to fit to + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values */ - CosNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop); + void set_test_value(const double* params, int offset = -1); /** - * @brief Solve the non-linear optimization to set the parameters - * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * @brief The domain for the feature (min/max values) * - * @param prop property to fit to get the parameters - * @param param_list List describing the parameters to fit + * @param params parameter values for non-linear operations + * @return the domain + */ + inline Domain domain(double* params) {return Domain(-1.0, 1.0);} + + /** + * @brief The expression of the feature + * + * @param params parameter values for non-linear operations + * @return feature expression */ - void get_parameters(std::vector<double>& prop, std::vector<std::string>& param_list); + inline std::string expr(double* params) {return "cos(" + std::to_string(params[0]) + "*" + _feats[0]->expr( params + 2) + " + " + std::to_string(params[1]) + ")";} #endif }; -#endif \ No newline at end of file +#endif diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos/parameterize.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos/parameterize.cpp deleted file mode 100644 index 6137d2df..00000000 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos/parameterize.cpp +++ /dev/null @@ -1,214 +0,0 @@ -#include <feature_creation/node/operator_nodes/allowed_operator_nodes/cos/cos.hpp> - -CosNode::CosNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop) : - OperatorNode(feats, feat_ind) -{ - if((feats[0]->type() == NODE_TYPE::SIN) || (feats[0]->type() == NODE_TYPE::COS)) - throw InvalidFeatureException(); - - get_parameters(prop, param_list); - set_value(); - if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) - throw InvalidFeatureException(); - - set_test_value(); -} - -CosNode::CosNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop) : - OperatorNode({feat}, feat_ind) -{ - if((feat->type() == NODE_TYPE::SIN) || (feat->type() == NODE_TYPE::COS)) - throw InvalidFeatureException(); - - get_parameters(prop, param_list); - set_value(); - if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) - throw InvalidFeatureException(); - - set_test_value(); -} - -void CosNode::get_parameters(std::vector<double>& prop, std::vector<std::string>& param_list) -{ - if(param_list.size() == 0) - return; - Problem problem; - double b = 1.0, c = 0.0; - double* val = _feats[0]->value_ptr(rung() + 2); - if(param_list.size() > 4) - { - throw std::logic_error("Too many parameters passed to the constructor."); - } - else if(param_list.size() == 4) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<CosResidual_alpha_a_b_c, 1, 1, 1, 1, 1>( - new CosResidual_alpha_a_b_c(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &_params[1], &b, &c - ); - } - } - else if(param_list.size() == 3) - { - if(std::none_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("alpha") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<CosResidual_a_b_c, 1, 1, 1, 1>( - new CosResidual_a_b_c(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[1], &b, &c - ); - } - } - else if(std::none_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("a") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<CosResidual_alpha_b_c, 1, 1, 1, 1>( - new CosResidual_alpha_b_c(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &b, &c - ); - } - } - else if(std::none_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("b") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<CosResidual_alpha_a_c, 1, 1, 1, 1>( - new CosResidual_alpha_a_c(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &_params[1], &c - ); - } - } - else if(std::none_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("c") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<CosResidual_alpha_a_b, 1, 1, 1, 1>( - new CosResidual_alpha_a_b(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &_params[1], &b - ); - } - } - else - throw std::logic_error("Invalid parameter in the parameter list."); - } - else if(param_list.size() == 2) - { - if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("alpha") == 0) || s.compare("a") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<CosResidual_alpha_a, 1, 1, 1>( - new CosResidual_alpha_a(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &_params[1] - ); - } - } - else if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("alpha") == 0) || s.compare("b") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<CosResidual_alpha_b, 1, 1, 1>( - new CosResidual_alpha_b(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &b - ); - } - } - else if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("alpha") == 0) || s.compare("c") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<CosResidual_alpha_c, 1, 1, 1>( - new CosResidual_alpha_c(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &c - ); - } - } - else if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("a") == 0) || s.compare("b") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<CosResidual_a_b, 1, 1, 1>( - new CosResidual_a_b(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[1], &b - ); - } - } - else if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("a") == 0) || s.compare("c") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<CosResidual_a_c, 1, 1, 1>( - new CosResidual_a_c(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[1], &c - ); - } - } - else - throw std::logic_error("Invalid parameter in the parameter list."); - } - else if(param_list.size() == 1) - { - if(std::any_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("alpha") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<CosResidual_alpha, 1, 1>( - new CosResidual_alpha(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0] - ); - } - } - else if(std::any_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("a") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<CosResidual_a, 1, 1>( - new CosResidual_a(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[1] - ); - } - } - else - throw std::logic_error("Invalid parameter in the parameter list."); - } - parameterize(problem); -} diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos/parameterized_cos.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos/parameterized_cos.cpp new file mode 100644 index 00000000..9da2f69a --- /dev/null +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos/parameterized_cos.cpp @@ -0,0 +1,67 @@ +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/cos/parameterized_cos.hpp> + +CosParamNode::CosParamNode() +{} + +CosParamNode::CosParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop) : + CosNode(feats, feat_ind) +{ + _params.resize(n_params(), 0.0); + + get_parameters(prop); + set_value(); + if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) + throw InvalidFeatureException(); + + set_test_value(); +} + +CosParamNode::CosParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop) : + CosNode({feat}, feat_ind) +{ + _params.resize(n_params(), 0.0); + + get_parameters(prop); + set_value(); + if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) + throw InvalidFeatureException(); + + set_test_value(); +} + +CosParamNode::CosParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound) : + CosNode(feats, feat_ind) +{ + _params.resize(n_params(), 0.0); +} + +CosParamNode::CosParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound) : + CosNode({feat}, feat_ind) +{ + _params.resize(n_params(), 0.0); +} + +void CosParamNode::get_parameters(std::vector<double>& prop) +{ + nlopt_wrapper::feat_data d; + d._feat = this; + d._prop = prop.data(); + double minf; + + std::fill_n(_params.begin(), _params.size(), 1.0); + dcopy_(_params.size() / 2, nlopt_wrapper::_zeros.data(), 1, &_params[1], 2); + + nlopt::opt opt(nlopt::LN_SBPLX, _params.size()); + opt.set_min_objective(nlopt_wrapper::objective_reg, &d); + opt.set_maxeval(1000); + opt.set_xtol_rel(1e-2); + try + { + nlopt::result result = opt.optimize(_params, minf); + } + catch(std::exception &e) + { + std::fill_n(_params.begin(), _params.size(), 1.0); + dcopy_(_params.size() / 2, nlopt_wrapper::_zeros.data(), 1, &_params[1], 2); + } +} diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos/parameterized_cos.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos/parameterized_cos.hpp new file mode 100644 index 00000000..76939c9b --- /dev/null +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos/parameterized_cos.hpp @@ -0,0 +1,153 @@ +/** @file feature_creation/node/operator_nodes/allowed_operator_nodes/cos/parameterized_cos.hpp + * @brief Class describing the parameterized cos operator + * + * This class represents the parameterized unary operator -> cos(alpha * A + a) + * + * @author Thomas A. R. Purcell (tpurcell) + * @bug No known bugs. + */ +#ifndef PARAM_COS_NODE +#define PARAM_COS_NODE + +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/cos/cos.hpp> +#include <feature_creation/parameterization/NLOptWrapper.hpp> + +// DocString: cls_abs_node +/** + * @brief Node for the absolute value operator + * + */ +class CosParamNode: public CosNode +{ + using CosNode::set_value; + using CosNode::set_test_value; + using CosNode::domain; + using CosNode::expr; + + friend class boost::serialization::access; + + /** + * @brief Serialization function to send over MPI + * + * @param ar Archive representation of node + */ + template <typename Archive> + void serialize(Archive& ar, const unsigned int version) + { + ar & boost::serialization::base_object<CosNode>(*this); + ar & _params; + } + +protected: + std::vector<double> _params; //!< The parameters vector + +public: + /** + * @brief Base Constructor + * @details This is only used for serialization + */ + CosParamNode(); + + /** + * @brief Constructor + * @details Constructs the Node from node pointer of the feature to operate on + * + * @param feat_1 shared_ptr of the feature to operate on (A) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + * @param prop The property to fit to + */ + CosParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop); + + /** + * @brief Constructor + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + * @param prop The property to fit to + */ + CosParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop); + + /** + * @brief Constructor + * @details Constructs the Node from node pointer of the feature to operate on + * + * @param feat_1 shared_ptr of the feature to operate on (A) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + */ + CosParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound); + + /** + * @brief Constructor + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + */ + CosParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound); + + // DocString: cos_param_node_set_value + /** + * @brief Set the values of the training data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + */ + inline void set_value(int offset = -1){set_value(_params.data(), offset);} + + // DocString: cos_param_node_set_test_value + /** + * @brief Set the values of the test data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + */ + inline void set_test_value(int offset = -1){set_test_value(_params.data(), offset);} + + // DocString: cos_param_node_expr + /** + * @brief Get the expression for the overall feature (From root node down) + */ + inline std::string expr(){return expr(_params.data());} + + // DocString: cos_param_node_domain + /** + * @brief The domain for the feature (min/max values) + */ + inline Domain domain(){return domain(_params.data());} + + /** + * @brief The parameters used for introducing more non linearity in the operators + */ + inline std::vector<double> parameters(){return _params;} + + /** + * @brief Solve the non-linear optimization to set the parameters + * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * + * @param prop property to fit to get the parameters + */ + void get_parameters(std::vector<double>& prop); + + /** + * @brief Set the non-linear parameters + */ + inline void set_parameters(std::vector<double> params) + { + if(params.size() != n_params()) + throw std::logic_error("Wrong number of parameters passed to set_parameters."); + _params = params; + } +}; + +#endif \ No newline at end of file diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/div/divide.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/div/divide.cpp index 5f28d97d..5bb796d4 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/div/divide.cpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/div/divide.cpp @@ -33,6 +33,14 @@ DivNode::DivNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, set_test_value(); } +DivNode::DivNode(std::array<node_ptr, 2> feats, int feat_ind): + OperatorNode(feats, feat_ind) +{ + check_feats(); + set_value(); + set_test_value(); +} + void DivNode::check_feats() { if((_feats[0]->type() == NODE_TYPE::INV) || (_feats[1]->type() == NODE_TYPE::INV) || (_feats[1]->type() == NODE_TYPE::DIV)) diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/div/divide.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/div/divide.hpp index 9afea84d..77015722 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/div/divide.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/div/divide.hpp @@ -61,6 +61,15 @@ public: */ DivNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound); + /** + * @brief Constructor without checking feature values + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + */ + DivNode(std::array<node_ptr, 2> feats, int feat_ind); + // DocString: div_node_unit /** * @brief Get the unit of the feature (combine the units of _feats) @@ -71,7 +80,7 @@ public: /** * @brief Get the expression for the overall feature (From root node down) */ - inline std::string expr(){return "[(" + _feats[0]->expr() + ") / (" + std::to_string(_params[0]) + "*" + _feats[1]->expr() + " + " + std::to_string(_params[1]) + ")]";} + inline std::string expr(){return "[(" + _feats[0]->expr() + ") / (" + _feats[1]->expr() + ")]";} // DocString: div_node_set_value /** @@ -81,11 +90,11 @@ public: */ inline void set_value(int offset = -1) { - if(_selected) - allowed_op_funcs::div(_n_samp, _feats[0]->value_ptr(offset + 2), _feats[1]->value_ptr(offset + 1), _params[0], _params[1], node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); - offset = (offset == -1) ? rung() : offset; - allowed_op_funcs::div(_n_samp, _feats[0]->value_ptr(offset + 2), _feats[1]->value_ptr(offset + 1), _params[0], _params[1], node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); + + if(_selected) + allowed_op_funcs::div(_n_samp, _feats[0]->value_ptr(offset + 2), _feats[1]->value_ptr(offset + 1), 1.0, 0.0, node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); + allowed_op_funcs::div(_n_samp, _feats[0]->value_ptr(offset + 2), _feats[1]->value_ptr(offset + 1), 1.0, 0.0, node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); } // DocString: div_node_set_test_value @@ -97,7 +106,7 @@ public: inline void set_test_value(int offset = -1) { offset = (offset == -1) ? rung() : offset; - allowed_op_funcs::div(_n_test_samp, _feats[0]->test_value_ptr(offset + 2), _feats[1]->test_value_ptr(offset + 1), _params[0], _params[1], node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); + allowed_op_funcs::div(_n_test_samp, _feats[0]->test_value_ptr(offset + 2), _feats[1]->test_value_ptr(offset + 1), 1.0, 0.0, node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); } // DocString: div_node_rung @@ -117,7 +126,7 @@ public: /** * @brief The domain for the feature (min/max values) */ - Domain domain(){return _feats[0]->domain().div(_feats[1]->domain(), _params[0], _params[1]);} + Domain domain(){return _feats[0]->domain().div(_feats[1]->domain());} /** * @brief Get the string character representation of the node for the postfix expression @@ -152,39 +161,66 @@ public: #ifdef PARAMETERIZE /** - * @brief Constructor - * @details Constructs the Node from an array of features to operate on + * @brief The parameters used for introducing more non linearity in the operators + */ + virtual std::vector<double> parameters(){return {};} + + /** + * @brief Solve the non-linear optimization to set the parameters + * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * + * @param prop property to fit to get the parameters + */ + virtual void get_parameters(std::vector<double>& prop){return;} + + /** + * @brief Set the non-linear parameters + */ + virtual void set_parameters(std::vector<double>){return;} + + /** + * @brief Set the values of the training data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values + */ + inline void set_value(const double* params, int offset = -1) + { + offset = (offset == -1) ? rung() : offset; + + if(_selected) + allowed_op_funcs::div(_n_samp, _feats[0]->value_ptr(params + 2 + _feats[1]->n_params(), offset + 2), _feats[1]->value_ptr(params + 2, offset + 1), params[0], params[1], node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); + allowed_op_funcs::div(_n_samp, _feats[0]->value_ptr(params + 2 + _feats[1]->n_params(), offset + 2), _feats[1]->value_ptr(params + 2, offset + 1), params[0], params[1], node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); + } + + /** + * @brief Set the values of the test data for the feature inside of the value storage arrays * - * @param feats Features to operate over (Edges of the graph) - * @param feat_ind Index of the new feature - * @param l_bound Minimum absolute value allowed for the feature. - * @param u_bound Maximum absolute value allowed for the feature. - * @param param_list The list of parameters to optimize using non-linear least squares - * @param prop The property to fit to + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values */ - DivNode(std::array<node_ptr, 2> feats, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop); + inline void set_test_value(const double* params, int offset = -1) + { + offset = (offset == -1) ? rung() : offset; + allowed_op_funcs::div(_n_test_samp, _feats[0]->test_value_ptr(params + 2 + _feats[1]->n_params(), offset + 2), _feats[1]->test_value_ptr(params + 2, offset + 1), params[0], params[1], node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); + } /** - * @brief Constructor - * @details Constructs the Node from node pointer of the feature to operate on + * @brief The domain for the feature (min/max values) * - * @param feat_1 shared_ptr of the feature to operate on (A) - * @param feat_ind Index of the new feature - * @param l_bound Minimum absolute value allowed for the feature. - * @param u_bound Maximum absolute value allowed for the feature. - * @param param_list The list of parameters to optimize using non-linear least squares - * @param prop The property to fit to + * @param params parameter values for non-linear operations + * @return the domain */ - DivNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop); + inline Domain domain(double* params){return _feats[0]->domain(params + _feats[1]->n_params() + 2).div(_feats[1]->domain(params + 2), params[0], params[1]);} /** - * @brief Solve the non-linear optimization to set the parameters - * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * @brief The expression of the feature * - * @param prop property to fit to get the parameters - * @param param_list List describing the parameters to fit + * @param params parameter values for non-linear operations + * @return feature expression */ - void get_parameters(std::vector<double>& prop, std::vector<std::string>& param_list); + inline std::string expr(double* params){return "[(" + _feats[0]->expr(params + _feats[1]->n_params() + 2) + ") / (" + std::to_string(params[0]) + "*" + _feats[1]->expr(params + 2) + " + " + std::to_string(params[1]) + ")]";} + #endif }; diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/div/parameterize.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/div/parameterize.cpp deleted file mode 100644 index 784f613b..00000000 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/div/parameterize.cpp +++ /dev/null @@ -1,113 +0,0 @@ -#include <feature_creation/node/operator_nodes/allowed_operator_nodes/div/divide.hpp> - -DivNode::DivNode(std::array<node_ptr, 2> feats, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop) : - OperatorNode(feats, feat_ind) -{ - check_feats(); - - get_parameters(prop, param_list); - - if((_params[0] * _feats[1]->domain() + _params[1]).contains(0.0)) - throw InvalidFeatureException(); - - set_value(); - if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) - throw InvalidFeatureException(); - - set_test_value(); -} - -DivNode::DivNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop) : - OperatorNode({feat_1, feat_2}, feat_ind) -{ - check_feats(); - - get_parameters(prop, param_list); - - if((_params[0] * _feats[1]->domain() + _params[1]).contains(0.0)) - throw InvalidFeatureException(); - - set_value(); - if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) - throw InvalidFeatureException(); - - set_test_value(); -} - -void DivNode::get_parameters(std::vector<double>& prop, std::vector<std::string>& param_list) -{ - if(param_list.size() == 0) - return; - Problem problem; - double c = 0.0; - double* val_1 = _feats[0]->value_ptr(rung() + 2); - double* val_2 = _feats[1]->value_ptr(rung() + 1); - - if(param_list.size() > 3) - { - throw std::logic_error("Too many parameters passed to the constructor."); - } - else if(param_list.size() == 3) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<DivResidual_alpha_a_c, 1, 1, 1, 1>( - new DivResidual_alpha_a_c(val_1[ss], val_2[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &_params[1], &c - ); - } - } - else if(param_list.size() == 2) - { - if(std::none_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("alpha") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<DivResidual_a_c, 1, 1, 1>( - new DivResidual_a_c(val_1[ss], val_2[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[1], &c - ); - } - } - else if(std::none_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("c") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<DivResidual_alpha_a, 1, 1, 1>( - new DivResidual_alpha_a(val_1[ss], val_2[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &_params[1] - ); - } - } - else - throw std::logic_error("Invalid parameter in the parameter list."); - } - else if(param_list.size() == 1) - { - if(std::any_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("a") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<DivResidual_a, 1, 1>( - new DivResidual_a(val_1[ss], val_2[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[1] - ); - } - } - else - throw std::logic_error("Invalid parameter in the parameter list."); - } - parameterize(problem); -} diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/div/parameterized_divide.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/div/parameterized_divide.cpp new file mode 100644 index 00000000..52a30a27 --- /dev/null +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/div/parameterized_divide.cpp @@ -0,0 +1,74 @@ +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/div/parameterized_divide.hpp> +DivParamNode::DivParamNode() +{} + +DivParamNode::DivParamNode(std::array<node_ptr, 2> feats, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop) : + DivNode(feats, feat_ind) +{ + _params.resize(n_params(), 0.0); + + get_parameters(prop); + + if((_params[0] * _feats[0]->domain() + _params[1]).contains(0.0)) + throw InvalidFeatureException(); + + set_value(); + if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) + throw InvalidFeatureException(); + + set_test_value(); +} + +DivParamNode::DivParamNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop) : + DivNode({feat_1, feat_2}, feat_ind) +{ + _params.resize(n_params(), 0.0); + + get_parameters(prop); + + if((_params[0] * _feats[0]->domain() + _params[1]).contains(0.0)) + throw InvalidFeatureException(); + + set_value(); + if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) + throw InvalidFeatureException(); + + set_test_value(); +} + +DivParamNode::DivParamNode(std::array<node_ptr, 2> feats, int feat_ind, double l_bound, double u_bound) : + DivNode(feats, feat_ind) +{ + _params.resize(n_params(), 0.0); +} + +DivParamNode::DivParamNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound) : + DivNode({feat_1, feat_2}, feat_ind) +{ + _params.resize(n_params(), 0.0); +} + +void DivParamNode::get_parameters(std::vector<double>& prop) +{ + nlopt_wrapper::feat_data d; + d._feat = this; + d._prop = prop.data(); + double minf; + + std::fill_n(_params.begin(), _params.size(), 1.0); + dcopy_(_params.size() / 2, nlopt_wrapper::_zeros.data(), 1, &_params[1], 2); + + nlopt::opt opt(nlopt::LN_SBPLX, _params.size()); + opt.set_min_objective(nlopt_wrapper::objective_reg, &d); + opt.set_maxeval(1000); + opt.set_xtol_rel(1e-2); + try + { + nlopt::result result = opt.optimize(_params, minf); + } + catch(std::exception &e) + { + std::fill_n(_params.begin(), _params.size(), 1.0); + dcopy_(_params.size() / 2, nlopt_wrapper::_zeros.data(), 1, &_params[1], 2); + } +} diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/div/parameterized_divide.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/div/parameterized_divide.hpp new file mode 100644 index 00000000..db7f4bbb --- /dev/null +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/div/parameterized_divide.hpp @@ -0,0 +1,151 @@ +/** @file feature_creation/node/operator_nodes/allowed_operator_nodes/div/parameterized_divide.hpp + * @brief Class describing the parameterized addition operator + * + * This class represents the parameterized unary operator -> A / (alpha * B + a) + * + * @author Thomas A. R. Purcell (tpurcell) + * @bug No known bugs. + */ +#ifndef PARAM_DIV_NODE +#define PARAM_DIV_NODE + +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/div/divide.hpp> +#include <feature_creation/parameterization/NLOptWrapper.hpp> + +// DocString: cls_param_add_node +/** + * @brief Node for the absolute value operator + * + */ +class DivParamNode: public DivNode +{ + using DivNode::set_value; + using DivNode::set_test_value; + using DivNode::domain; + using DivNode::expr; + + friend class boost::serialization::access; + + /** + * @brief Serialization function to send over MPI + * + * @param ar Archive representation of node + */ + template <typename Archive> + void serialize(Archive& ar, const unsigned int version) + { + ar & boost::serialization::base_object<DivNode>(*this); + ar & _params; + } +protected: + std::vector<double> _params; +public: + /** + * @brief Base Constructor + * @details This is only used for serialization + */ + DivParamNode(); + + /** + * @brief Constructor + * @details Constructs the Node from node pointer of the feature to operate on + * + * @param feat_1 shared_ptr of the feature to operate on (A) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + * @param prop The property to fit to + */ + DivParamNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop); + + /** + * @brief Constructor + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + * @param prop The property to fit to + */ + DivParamNode(std::array<node_ptr, 2> feats, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop); + + /** + * @brief Constructor + * @details Constructs the Node from node pointer of the feature to operate on + * + * @param feat_1 shared_ptr of the feature to operate on (A) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + */ + DivParamNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound); + + /** + * @brief Constructor + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + */ + DivParamNode(std::array<node_ptr, 2> feats, int feat_ind, double l_bound, double u_bound); + + // DocString: div_param_node_set_value + /** + * @brief Set the values of the training data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + */ + inline void set_value(int offset = -1){set_value(_params.data(), offset);} + + // DocString: div_param_node_set_test_value + /** + * @brief Set the values of the test data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + */ + inline void set_test_value(int offset = -1){set_test_value(_params.data(), offset);} + + // DocString: div_param_node_expr + /** + * @brief Get the expression for the overall feature (From root node down) + */ + inline std::string expr(){return expr(_params.data());} + + // DocString: div_param_node_domain + /** + * @brief The domain for the feature (min/max values) + */ + inline Domain domain(){return domain(_params.data());} + + /** + * @brief The parameters used for introducing more non linearity in the operators + */ + inline std::vector<double> parameters(){return _params;} + + /** + * @brief Solve the non-linear optimization to set the parameters + * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * + * @param prop property to fit to get the parameters + */ + void get_parameters(std::vector<double>& prop); + + /** + * @brief Set the non-linear parameters + */ + inline void set_parameters(std::vector<double> params) + { + if(params.size() != n_params()) + throw std::logic_error("Wrong number of parameters passed to set_parameters."); + _params = params; + } +}; + +#endif \ No newline at end of file diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exp/exponential.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exp/exponential.cpp index 77695faf..8969e83e 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exp/exponential.cpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exp/exponential.cpp @@ -35,6 +35,16 @@ ExpNode::ExpNode(node_ptr feat, int feat_ind, double l_bound, double u_bound): set_test_value(); } +ExpNode::ExpNode(std::array<node_ptr, 1> feats, int feat_ind): + OperatorNode(feats, feat_ind) +{ + if((feats[0]->type() == NODE_TYPE::NEG_EXP) || (feats[0]->type() == NODE_TYPE::EXP) || (feats[0]->type() == NODE_TYPE::ADD) || (feats[0]->type() == NODE_TYPE::SUB) || (feats[0]->type() == NODE_TYPE::LOG)) + throw InvalidFeatureException(); + + set_value(); + set_test_value(); +} + void ExpNode::update_add_sub_leaves(std::map<std::string, int>& add_sub_leaves, int pl_mn, int& expected_abs_tot) { std::string key = expr(); diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exp/exponential.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exp/exponential.hpp index feadc6f2..91674b01 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exp/exponential.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exp/exponential.hpp @@ -60,6 +60,15 @@ public: */ ExpNode(node_ptr feat, int feat_ind, double l_bound, double u_bound); + /** + * @brief Constructor without checking feature values + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + */ + ExpNode(std::array<node_ptr, 1> feats, int feat_ind); + // DocString: exp_node_unit /** * @brief Get the unit of the feature (combine the units of _feats) @@ -70,7 +79,7 @@ public: /** * @brief Get the expression for the overall feature (From root node down) */ - inline std::string expr(){return "exp(" + std::to_string(_params[0]) + "*" + _feats[0]->expr() + " + " + std::to_string(_params[1]) + ")";} + inline std::string expr(){return "exp(" + _feats[0]->expr() + ")";} // DocString: exp_node_set_value /** @@ -80,11 +89,11 @@ public: */ inline void set_value(int offset = -1) { - if(_selected) - allowed_op_funcs::exp(_n_samp, _feats[0]->value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); - offset = (offset == -1) ? rung() : offset; - allowed_op_funcs::exp(_n_samp, _feats[0]->value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); + + if(_selected) + allowed_op_funcs::exp(_n_samp, _feats[0]->value_ptr(offset + 2), 1.0, 0.0, node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); + allowed_op_funcs::exp(_n_samp, _feats[0]->value_ptr(offset + 2), 1.0, 0.0, node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); } // DocString: exp_node_set_test_value @@ -96,7 +105,7 @@ public: inline void set_test_value(int offset = -1) { offset = (offset == -1) ? rung() : offset; - allowed_op_funcs::exp(_n_test_samp, _feats[0]->test_value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); + allowed_op_funcs::exp(_n_test_samp, _feats[0]->test_value_ptr(offset + 2), 1.0, 0.0, node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); } // DocString: exp_node_rung @@ -116,7 +125,7 @@ public: /** * @brief The domain for the feature (min/max values) */ - Domain domain(){return _feats[0]->domain().exp(_params[0], _params[1]);} + Domain domain(){return _feats[0]->domain().exp(1.0, 0.0);} /** * @brief Get the string character representation of the node for the postfix expression @@ -145,39 +154,65 @@ public: #ifdef PARAMETERIZE /** - * @brief Constructor - * @details Constructs the Node from an array of features to operate on + * @brief The parameters used for introducing more non linearity in the operators + */ + virtual std::vector<double> parameters(){return {};} + + /** + * @brief Solve the non-linear optimization to set the parameters + * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature * - * @param feats Features to operate over (Edges of the graph) - * @param feat_ind Index of the new feature - * @param l_bound Minimum absolute value allowed for the feature. - * @param u_bound Maximum absolute value allowed for the feature. - * @param param_list The list of parameters to optimize using non-linear least squares - * @param prop The property to fit to + * @param prop property to fit to get the parameters */ - ExpNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop); + virtual void get_parameters(std::vector<double>& prop){return;} + + /** + * @brief Set the non-linear parameters + */ + virtual void set_parameters(std::vector<double>){return;} /** - * @brief Constructor - * @details Constructs the Node from node pointer of the feature to operate on + * @brief Set the values of the training data for the feature inside of the value storage arrays * - * @param feat_1 shared_ptr of the feature to operate on (A) - * @param feat_ind Index of the new feature - * @param l_bound Minimum absolute value allowed for the feature. - * @param u_bound Maximum absolute value allowed for the feature. - * @param param_list The list of parameters to optimize using non-linear least squares - * @param prop The property to fit to + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values */ - ExpNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop); + inline void set_value(const double* params, int offset = -1) + { + offset = (offset == -1) ? rung() : offset; + if(_selected) + allowed_op_funcs::exp(_n_samp, _feats[0]->value_ptr(params + 2, offset + 2), params[0], params[1], node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); + + allowed_op_funcs::exp(_n_samp, _feats[0]->value_ptr(params + 2, offset + 2), params[0], params[1], node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset, false)); + } /** - * @brief Solve the non-linear optimization to set the parameters - * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * @brief Set the values of the test data for the feature inside of the value storage arrays * - * @param prop property to fit to get the parameters - * @param param_list List describing the parameters to fit + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values + */ + inline void set_test_value(const double* params, int offset = -1) + { + offset = (offset == -1) ? rung() : offset; + allowed_op_funcs::exp(_n_test_samp, _feats[0]->test_value_ptr(params + 2, offset + 2), params[0], params[1], node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset, false)); + } + + /** + * @brief The domain for the feature (min/max values) + * + * @param params parameter values for non-linear operations + * @return the domain + */ + inline Domain domain(double* params){return _feats[0]->domain(params + 2).exp(params[0], params[1]);} + + /** + * @brief The expression of the feature + * + * @param params parameter values for non-linear operations + * @return feature expression */ - void get_parameters(std::vector<double>& prop, std::vector<std::string>& param_list); + inline std::string expr(double* params){return "exp(" + std::to_string(params[0]) + "*" + _feats[0]->expr(params + 2) + " + " + std::to_string(params[1]) + ")";} #endif }; diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exp/parameterize.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exp/parameterize.cpp deleted file mode 100644 index 2a211717..00000000 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exp/parameterize.cpp +++ /dev/null @@ -1,105 +0,0 @@ -#include <feature_creation/node/operator_nodes/allowed_operator_nodes/exp/exponential.hpp> - -ExpNode::ExpNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop) : - OperatorNode(feats, feat_ind) -{ - if((feats[0]->type() == NODE_TYPE::NEG_EXP) || (feats[0]->type() == NODE_TYPE::EXP) || (feats[0]->type() == NODE_TYPE::ADD) || (feats[0]->type() == NODE_TYPE::SUB) || (feats[0]->type() == NODE_TYPE::LOG)) - throw InvalidFeatureException(); - - get_parameters(prop, param_list); - set_value(); - if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) - throw InvalidFeatureException(); - - set_test_value(); -} - -ExpNode::ExpNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop) : - OperatorNode({feat}, feat_ind) -{ - if((feat->type() == NODE_TYPE::NEG_EXP) || (feat->type() == NODE_TYPE::EXP) || (feat->type() == NODE_TYPE::ADD) || (feat->type() == NODE_TYPE::SUB) || (feat->type() == NODE_TYPE::LOG)) - throw InvalidFeatureException(); - - get_parameters(prop, param_list); - set_value(); - if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) - throw InvalidFeatureException(); - - set_test_value(); -} - -void ExpNode::get_parameters(std::vector<double>& prop, std::vector<std::string>& param_list) -{ - if(param_list.size() == 0) - return; - Problem problem; - double b = 1.0, c = 0.0; - double* val = _feats[0]->value_ptr(rung() + 2); - if(param_list.size() > 3) - { - throw std::logic_error("Too many parameters passed to the constructor."); - } - else if(param_list.size() == 3) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<ExpResidual_alpha_a_c, 1, 1, 1, 1>( - new ExpResidual_alpha_a_c(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &_params[1], &c - ); - } - } - else if(param_list.size() == 2) - { - if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("alpha") == 0) || s.compare("a") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<ExpResidual_alpha_a, 1, 1, 1>( - new ExpResidual_alpha_a(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &_params[1] - ); - } - } - else if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("alpha") == 0) || s.compare("c") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<ExpResidual_alpha_c, 1, 1, 1>( - new ExpResidual_alpha_c(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &c - ); - } - } - else - throw std::logic_error("Invalid parameter in the parameter list."); - } - else if(param_list.size() == 1) - { - if(std::any_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("alpha") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<ExpResidual_alpha, 1, 1>( - new ExpResidual_alpha(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0] - ); - } - } - else - throw std::logic_error("Invalid parameter in the parameter list."); - } - parameterize(problem); -} diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exp/parameterized_exponential.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exp/parameterized_exponential.cpp new file mode 100644 index 00000000..76e9363c --- /dev/null +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exp/parameterized_exponential.cpp @@ -0,0 +1,65 @@ +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/exp/parameterized_exponential.hpp> + +ExpParamNode::ExpParamNode() +{} + +ExpParamNode::ExpParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop) : + ExpNode(feats, feat_ind) +{ + _params.resize(n_params(), 0.0); + get_parameters(prop); + set_value(); + if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) + throw InvalidFeatureException(); + + set_test_value(); +} + +ExpParamNode::ExpParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop) : + ExpNode({feat}, feat_ind) +{ + _params.resize(n_params(), 0.0); + get_parameters(prop); + set_value(); + if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) + throw InvalidFeatureException(); + + set_test_value(); +} + +ExpParamNode::ExpParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound) : + ExpNode(feats, feat_ind) +{ + _params.resize(n_params(), 0.0); +} + +ExpParamNode::ExpParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound) : + ExpNode({feat}, feat_ind) +{ + _params.resize(n_params(), 0.0); +} + +void ExpParamNode::get_parameters(std::vector<double>& prop) +{ + nlopt_wrapper::feat_data d; + d._feat = this; + d._prop = prop.data(); + double minf; + + std::fill_n(_params.begin(), _params.size(), 1.0); + dcopy_(_params.size() / 2, nlopt_wrapper::_zeros.data(), 1, &_params[1], 2); + + nlopt::opt opt(nlopt::LN_SBPLX, _params.size()); + opt.set_min_objective(nlopt_wrapper::objective_reg, &d); + opt.set_maxeval(1000); + opt.set_xtol_rel(1e-2); + try + { + nlopt::result result = opt.optimize(_params, minf); + } + catch(std::exception &e) + { + std::fill_n(_params.begin(), _params.size(), 1.0); + dcopy_(_params.size() / 2, nlopt_wrapper::_zeros.data(), 1, &_params[1], 2); + } +} diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exp/parameterized_exponential.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exp/parameterized_exponential.hpp new file mode 100644 index 00000000..78da2782 --- /dev/null +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exp/parameterized_exponential.hpp @@ -0,0 +1,153 @@ +/** @file feature_creation/node/operator_nodes/allowed_operator_nodes/exp/parameterized_exponetial.hpp + * @brief Class describing the parameterized exp operator + * + * This class represents the parameterized unary operator -> exp(alpha * A + a) + * + * @author Thomas A. R. Purcell (tpurcell) + * @bug No known bugs. + */ +#ifndef PARAM_EXP_NODE +#define PARAM_EXP_NODE + +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/exp/exponential.hpp> +#include <feature_creation/parameterization/NLOptWrapper.hpp> + +// DocString: cls_abs_node +/** + * @brief Node for the absolute value operator + * + */ +class ExpParamNode: public ExpNode +{ + using ExpNode::set_value; + using ExpNode::set_test_value; + using ExpNode::domain; + using ExpNode::expr; + + friend class boost::serialization::access; + + /** + * @brief Serialization function to send over MPI + * + * @param ar Archive representation of node + */ + template <typename Archive> + void serialize(Archive& ar, const unsigned int version) + { + ar & boost::serialization::base_object<ExpNode>(*this); + ar & _params; + } + +protected: + std::vector<double> _params; //!< The parameters vector + +public: + /** + * @brief Base Constructor + * @details This is only used for serialization + */ + ExpParamNode(); + + /** + * @brief Constructor + * @details Constructs the Node from node pointer of the feature to operate on + * + * @param feat_1 shared_ptr of the feature to operate on (A) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + * @param prop The property to fit to + */ + ExpParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop); + + /** + * @brief Constructor + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + * @param prop The property to fit to + */ + ExpParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop); + + /** + * @brief Constructor + * @details Constructs the Node from node pointer of the feature to operate on + * + * @param feat_1 shared_ptr of the feature to operate on (A) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + */ + ExpParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound); + + /** + * @brief Constructor + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + */ + ExpParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound); + + // DocString: exp_param_node_set_value + /** + * @brief Set the values of the training data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + */ + inline void set_value(int offset = -1){set_value(_params.data(), offset);} + + // DocString: exp_param_node_set_test_value + /** + * @brief Set the values of the test data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + */ + inline void set_test_value(int offset = -1){set_test_value(_params.data(), offset);} + + // DocString: exp_param_node_expr + /** + * @brief Get the expression for the overall feature (From root node down) + */ + inline std::string expr(){return expr(_params.data());} + + // DocString: exp_param_node_domain + /** + * @brief The domain for the feature (min/max values) + */ + inline Domain domain(){return domain(_params.data());} + + /** + * @brief The parameters used for introducing more non linearity in the operators + */ + inline std::vector<double> parameters(){return _params;} + + /** + * @brief Solve the non-linear optimization to set the parameters + * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * + * @param prop property to fit to get the parameters + */ + void get_parameters(std::vector<double>& prop); + + /** + * @brief Set the non-linear parameters + */ + inline void set_parameters(std::vector<double> params) + { + if(params.size() != n_params()) + throw std::logic_error("Wrong number of parameters passed to set_parameters."); + _params = params; + } +}; + +#endif \ No newline at end of file diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inv/inverse.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inv/inverse.cpp index 47a7e3be..1773bcc3 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inv/inverse.cpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inv/inverse.cpp @@ -35,6 +35,16 @@ InvNode::InvNode(node_ptr feat, int feat_ind, double l_bound, double u_bound): set_test_value(); } +InvNode::InvNode(std::array<node_ptr, 1> feats, int feat_ind): + OperatorNode(feats, feat_ind) +{ + if((feats[0]->type() == NODE_TYPE::DIV) || (feats[0]->type() == NODE_TYPE::EXP) || (feats[0]->type() == NODE_TYPE::NEG_EXP) || (feats[0]->type() == NODE_TYPE::INV)) + throw InvalidFeatureException(); + + set_value(); + set_test_value(); +} + void InvNode::update_add_sub_leaves(std::map<std::string, int>& add_sub_leaves, int pl_mn, int& expected_abs_tot) { std::string key = expr(); diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inv/inverse.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inv/inverse.hpp index e14095ea..64a1c50f 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inv/inverse.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inv/inverse.hpp @@ -38,7 +38,7 @@ public: InvNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound); /** - * @brief Constructor + * @brief Constructor without checking feature values * @details Constructs the Node from node pointer of the feature to operate on * * @param feat_1 shared_ptr of the feature to operate on (A) @@ -48,6 +48,15 @@ public: */ InvNode(node_ptr feat, int feat_ind, double l_bound, double u_bound); + /** + * @brief Constructor + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + */ + InvNode(std::array<node_ptr, 1> feats, int feat_ind); + // DocString: inv_node_unit /** * @brief Get the unit of the feature (combine the units of _feats) @@ -58,7 +67,7 @@ public: /** * @brief Get the expression for the overall feature (From root node down) */ - inline std::string expr(){return "1.0 / (" + std::to_string(_params[0]) + "*" + _feats[0]->expr() + " + " + std::to_string(_params[1]) + ")";} + inline std::string expr(){return "1.0 / (" + _feats[0]->expr() + ")";} // DocString: inv_node_set_value /** @@ -68,11 +77,11 @@ public: */ inline void set_value(int offset = -1) { - if(_selected) - allowed_op_funcs::inv(_n_samp, _feats[0]->value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); - offset = (offset == -1) ? rung() : offset; - allowed_op_funcs::inv(_n_samp, _feats[0]->value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); + + if(_selected) + allowed_op_funcs::inv(_n_samp, _feats[0]->value_ptr(offset + 2), 1.0, 0.0, node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); + allowed_op_funcs::inv(_n_samp, _feats[0]->value_ptr(offset + 2), 1.0, 0.0, node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); } // DocString: inv_node_set_test_value @@ -84,7 +93,7 @@ public: inline void set_test_value(int offset = -1) { offset = (offset == -1) ? rung() : offset; - allowed_op_funcs::inv(_n_test_samp, _feats[0]->test_value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); + allowed_op_funcs::inv(_n_test_samp, _feats[0]->test_value_ptr(offset + 2), 1.0, 0.0, node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); } // DocString: inv_node_rung @@ -104,7 +113,7 @@ public: /** * @brief The domain for the feature (min/max values) */ - Domain domain(){return _feats[0]->domain().inv(_params[0], _params[1]);} + Domain domain(){return _feats[0]->domain().inv(1.0, 0.0);} /** * @brief Get the string character representation of the node for the postfix expression @@ -133,39 +142,65 @@ public: #ifdef PARAMETERIZE /** - * @brief Constructor - * @details Constructs the Node from an array of features to operate on + * @brief The parameters used for introducing more non linearity in the operators + */ + virtual std::vector<double> parameters(){return {};} + + /** + * @brief Solve the non-linear optimization to set the parameters + * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature * - * @param feats Features to operate over (Edges of the graph) - * @param feat_ind Index of the new feature - * @param l_bound Minimum absolute value allowed for the feature. - * @param u_bound Maximum absolute value allowed for the feature. - * @param param_list The list of parameters to optimize using non-linear least squares - * @param prop The property to fit to + * @param prop property to fit to get the parameters */ - InvNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop); + virtual void get_parameters(std::vector<double>& prop){return;} + + /** + * @brief Set the non-linear parameters + */ + virtual void set_parameters(std::vector<double>){return;} /** - * @brief Constructor - * @details Constructs the Node from node pointer of the feature to operate on + * @brief Set the values of the training data for the feature inside of the value storage arrays * - * @param feat_1 shared_ptr of the feature to operate on (A) - * @param feat_ind Index of the new feature - * @param l_bound Minimum absolute value allowed for the feature. - * @param u_bound Maximum absolute value allowed for the feature. - * @param param_list The list of parameters to optimize using non-linear least squares - * @param prop The property to fit to + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values */ - InvNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop); + inline void set_value(const double* params, int offset = -1) + { + offset = (offset == -1) ? rung() : offset; + if(_selected) + allowed_op_funcs::inv(_n_samp, _feats[0]->value_ptr(params + 2, offset + 2), params[0], params[1], node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); + + allowed_op_funcs::inv(_n_samp, _feats[0]->value_ptr(params + 2, offset + 2), params[0], params[1], node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset, false)); + } /** - * @brief Solve the non-linear optimization to set the parameters - * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * @brief Set the values of the test data for the feature inside of the value storage arrays * - * @param prop property to fit to get the parameters - * @param param_list List describing the parameters to fit + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values + */ + inline void set_test_value(const double* params, int offset = -1) + { + offset = (offset == -1) ? rung() : offset; + allowed_op_funcs::inv(_n_test_samp, _feats[0]->test_value_ptr(params + 2, offset + 2), params[0], params[1], node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset, false)); + } + + /** + * @brief The domain for the feature (min/max values) + * + * @param params parameter values for non-linear operations + * @return the domain + */ + inline Domain domain(double* params){return _feats[0]->domain(params + 2).inv(params[0], params[1]);} + + /** + * @brief The expression of the feature + * + * @param params parameter values for non-linear operations + * @return feature expression */ - void get_parameters(std::vector<double>& prop, std::vector<std::string>& param_list); + inline std::string expr(double* params){return "1.0 / (" + std::to_string(params[0]) + "*" + _feats[0]->expr(params + 2) + " + " + std::to_string(params[1]) + ")";} #endif }; #endif \ No newline at end of file diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inv/parameterize.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inv/parameterize.cpp deleted file mode 100644 index 2f321821..00000000 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inv/parameterize.cpp +++ /dev/null @@ -1,113 +0,0 @@ -#include <feature_creation/node/operator_nodes/allowed_operator_nodes/inv/inverse.hpp> - -InvNode::InvNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop) : - OperatorNode(feats, feat_ind) -{ - if((feats[0]->type() == NODE_TYPE::DIV) || (feats[0]->type() == NODE_TYPE::EXP) || (feats[0]->type() == NODE_TYPE::NEG_EXP) || (feats[0]->type() == NODE_TYPE::INV)) - throw InvalidFeatureException(); - - get_parameters(prop, param_list); - - if((_params[0] * _feats[0]->domain() + _params[1]).contains(0.0)) - throw InvalidFeatureException(); - - set_value(); - if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) - throw InvalidFeatureException(); - - set_test_value(); -} - -InvNode::InvNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop) : - OperatorNode({feat}, feat_ind) -{ - if((feat->type() == NODE_TYPE::DIV) || (feat->type() == NODE_TYPE::EXP) || (feat->type() == NODE_TYPE::NEG_EXP) || (feat->type() == NODE_TYPE::INV)) - throw InvalidFeatureException(); - - get_parameters(prop, param_list); - - if((_params[0] * _feats[0]->domain() + _params[1]).contains(0.0)) - throw InvalidFeatureException(); - - set_value(); - if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) - throw InvalidFeatureException(); - - set_test_value(); -} - -void InvNode::get_parameters(std::vector<double>& prop, std::vector<std::string>& param_list) -{ - if(param_list.size() == 0) - return; - Problem problem; - double c = 0.0; - double* val = _feats[0]->value_ptr(rung() + 2); - if(param_list.size() > 3) - { - throw std::logic_error("Too many parameters passed to the constructor."); - } - else if(param_list.size() == 3) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<InvResidual_alpha_a_c, 1, 1, 1, 1>( - new InvResidual_alpha_a_c(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &_params[1], &c - ); - } - } - else if(param_list.size() == 2) - { - if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("alpha") == 0) || s.compare("a") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<InvResidual_alpha_a, 1, 1, 1>( - new InvResidual_alpha_a(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &_params[1] - ); - } - } - else if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("a") == 0) || s.compare("c") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<InvResidual_a_c, 1, 1, 1>( - new InvResidual_a_c(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[1], &c - ); - } - } - else - throw std::logic_error("Invalid parameter in the parameter list."); - } - else if(param_list.size() == 1) - { - if(std::any_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("a") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<InvResidual_a, 1, 1>( - new InvResidual_a(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[1] - ); - } - } - else - throw std::logic_error("Invalid parameter in the parameter list."); - } - parameterize(problem); -} diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inv/parameterized_inverse.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inv/parameterized_inverse.cpp new file mode 100644 index 00000000..b394e8ed --- /dev/null +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inv/parameterized_inverse.cpp @@ -0,0 +1,75 @@ +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/inv/parameterized_inverse.hpp> + +InvParamNode::InvParamNode() +{} + +InvParamNode::InvParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop) : + InvNode(feats, feat_ind) +{ + _params.resize(n_params(), 0.0); + + get_parameters(prop); + + if((_params[0] * _feats[0]->domain() + _params[1]).contains(0.0)) + throw InvalidFeatureException(); + + set_value(); + if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) + throw InvalidFeatureException(); + + set_test_value(); +} + +InvParamNode::InvParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop) : + InvNode({feat}, feat_ind) +{ + _params.resize(n_params(), 0.0); + + get_parameters(prop); + + if((_params[0] * _feats[0]->domain() + _params[1]).contains(0.0)) + throw InvalidFeatureException(); + + set_value(); + if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) + throw InvalidFeatureException(); + + set_test_value(); +} + +InvParamNode::InvParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound) : + InvNode(feats, feat_ind) +{ + _params.resize(n_params(), 0.0); +} + +InvParamNode::InvParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound) : + InvNode({feat}, feat_ind) +{ + _params.resize(n_params(), 0.0); +} + +void InvParamNode::get_parameters(std::vector<double>& prop) +{ + nlopt_wrapper::feat_data d; + d._feat = this; + d._prop = prop.data(); + double minf; + + std::fill_n(_params.begin(), _params.size(), 1.0); + dcopy_(_params.size() / 2, nlopt_wrapper::_zeros.data(), 1, &_params[1], 2); + + nlopt::opt opt(nlopt::LN_SBPLX, _params.size()); + opt.set_min_objective(nlopt_wrapper::objective_reg, &d); + opt.set_maxeval(1000); + opt.set_xtol_rel(1e-2); + try + { + nlopt::result result = opt.optimize(_params, minf); + } + catch(std::exception &e) + { + std::fill_n(_params.begin(), _params.size(), 1.0); + dcopy_(_params.size() / 2, nlopt_wrapper::_zeros.data(), 1, &_params[1], 2); + } +} diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inv/parameterized_inverse.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inv/parameterized_inverse.hpp new file mode 100644 index 00000000..ffdc23b1 --- /dev/null +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inv/parameterized_inverse.hpp @@ -0,0 +1,153 @@ +/** @file feature_creation/node/operator_nodes/allowed_operator_nodes/inv/parameterized_inverse.hpp + * @brief Class describing the parameterized inverse operator + * + * This class represents the parameterized unary operator -> 1.0 / (alpha * A + a) + * + * @author Thomas A. R. Purcell (tpurcell) + * @bug No known bugs. + */ +#ifndef PARAM_INV_NODE +#define PARAM_INV_NODE + +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/inv/inverse.hpp> +#include <feature_creation/parameterization/NLOptWrapper.hpp> + +// DocString: cls_abs_node +/** + * @brief Node for the absolute value operator + * + */ +class InvParamNode: public InvNode +{ + using InvNode::set_value; + using InvNode::set_test_value; + using InvNode::domain; + using InvNode::expr; + + friend class boost::serialization::access; + + /** + * @brief Serialization function to send over MPI + * + * @param ar Archive representation of node + */ + template <typename Archive> + void serialize(Archive& ar, const unsigned int version) + { + ar & boost::serialization::base_object<InvNode>(*this); + ar & _params; + } + +protected: + std::vector<double> _params; //!< The parameters vector + +public: + /** + * @brief Base Constructor + * @details This is only used for serialization + */ + InvParamNode(); + + /** + * @brief Constructor + * @details Constructs the Node from node pointer of the feature to operate on + * + * @param feat_1 shared_ptr of the feature to operate on (A) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + * @param prop The property to fit to + */ + InvParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop); + + /** + * @brief Constructor + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + * @param prop The property to fit to + */ + InvParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop); + + /** + * @brief Constructor + * @details Constructs the Node from node pointer of the feature to operate on + * + * @param feat_1 shared_ptr of the feature to operate on (A) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + */ + InvParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound); + + /** + * @brief Constructor + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + */ + InvParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound); + + // DocString: inv_param_node_set_value + /** + * @brief Set the values of the training data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + */ + inline void set_value(int offset = -1){set_value(_params.data(), offset);} + + // DocString: inv_param_node_set_test_value + /** + * @brief Set the values of the test data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + */ + inline void set_test_value(int offset = -1){set_test_value(_params.data(), offset);} + + // DocString: inv_param_node_expr + /** + * @brief Get the expression for the overall feature (From root node down) + */ + inline std::string expr(){return expr(_params.data());} + + // DocString: inv_param_node_domain + /** + * @brief The domain for the feature (min/max values) + */ + inline Domain domain(){return domain(_params.data());} + + /** + * @brief The parameters used for introducing more non linearity in the operators + */ + inline std::vector<double> parameters(){return _params;} + + /** + * @brief Solve the non-linear optimization to set the parameters + * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * + * @param prop property to fit to get the parameters + */ + void get_parameters(std::vector<double>& prop); + + /** + * @brief Set the non-linear parameters + */ + inline void set_parameters(std::vector<double> params) + { + if(params.size() != n_params()) + throw std::logic_error("Wrong number of parameters passed to set_parameters."); + _params = params; + } +}; + +#endif \ No newline at end of file diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log/log.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log/log.cpp index ea1a8b36..19cd8fe9 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log/log.cpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log/log.cpp @@ -20,7 +20,7 @@ LogNode::LogNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, do if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) throw InvalidFeatureException(); - set_test_value(); + set_test_value(); } LogNode::LogNode(node_ptr feat, int feat_ind, double l_bound, double u_bound): @@ -39,7 +39,17 @@ LogNode::LogNode(node_ptr feat, int feat_ind, double l_bound, double u_bound): if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) throw InvalidFeatureException(); - set_test_value(); + set_test_value(); +} + +LogNode::LogNode(std::array<node_ptr, 1> feats, int feat_ind): + OperatorNode(feats, feat_ind) +{ + if((feats[0]->type() == NODE_TYPE::NEG_EXP) || (feats[0]->type() == NODE_TYPE::EXP) || (feats[0]->type() == NODE_TYPE::DIV) || (feats[0]->type() == NODE_TYPE::INV) || (feats[0]->type() == NODE_TYPE::MULT) || (feats[0]->type() == NODE_TYPE::LOG) || (feats[0]->type() == NODE_TYPE::SIX_POW) || (feats[0]->type() == NODE_TYPE::CB) || (feats[0]->type() == NODE_TYPE::SQ) || (feats[0]->type() == NODE_TYPE::CBRT) || (feats[0]->type() == NODE_TYPE::SQRT)) + throw InvalidFeatureException(); + + set_value(); + set_test_value(); } void LogNode::update_add_sub_leaves(std::map<std::string, int>& add_sub_leaves, int pl_mn, int& expected_abs_tot) diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log/log.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log/log.hpp index 3aaf42e4..e87952a0 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log/log.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log/log.hpp @@ -60,6 +60,15 @@ public: */ LogNode(node_ptr feat, int feat_ind, double l_bound, double u_bound); + /** + * @brief Constructor without checking feature values + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + */ + LogNode(std::array<node_ptr, 1> feats, int feat_ind); + // DocString: log_node_unit /** * @brief Get the unit of the feature (combine the units of _feats) @@ -70,7 +79,7 @@ public: /** * @brief Get the expression for the overall feature (From root node down) */ - inline std::string expr(){return "log(" + std::to_string(_params[0]) + "*" + _feats[0]->expr() + " + " + std::to_string(_params[1]) + ")";} + inline std::string expr(){return "log(" + _feats[0]->expr() + ")";} // DocString: log_node_set_value /** @@ -80,11 +89,11 @@ public: */ inline void set_value(int offset = -1) { - if(_selected) - allowed_op_funcs::log(_n_samp, _feats[0]->value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); - offset = (offset == -1) ? rung() : offset; - allowed_op_funcs::log(_n_samp, _feats[0]->value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); + + if(_selected) + allowed_op_funcs::log(_n_samp, _feats[0]->value_ptr(offset + 2), 1.0, 0.0, node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); + allowed_op_funcs::log(_n_samp, _feats[0]->value_ptr(offset + 2), 1.0, 0.0, node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); } // DocString: log_node_set_test_value @@ -96,7 +105,7 @@ public: inline void set_test_value(int offset = -1) { offset = (offset == -1) ? rung() : offset; - allowed_op_funcs::log(_n_test_samp, _feats[0]->test_value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); + allowed_op_funcs::log(_n_test_samp, _feats[0]->test_value_ptr(offset + 2), 1.0, 0.0, node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); } // DocString: log_node_rung @@ -116,7 +125,7 @@ public: /** * @brief The domain for the feature (min/max values) */ - Domain domain(){return _feats[0]->domain().log(_params[0], _params[1]);} + Domain domain(){return _feats[0]->domain().log(1.0, 0.0);} /** * @brief Get the string character representation of the node for the postfix expression @@ -145,39 +154,66 @@ public: #ifdef PARAMETERIZE /** - * @brief Constructor - * @details Constructs the Node from an array of features to operate on + * @brief The parameters used for introducing more non linearity in the operators + */ + virtual std::vector<double> parameters(){return {};} + + /** + * @brief Solve the non-linear optimization to set the parameters + * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * + * @param prop property to fit to get the parameters + */ + virtual void get_parameters(std::vector<double>& prop){return;} + + /** + * @brief Set the non-linear parameters + */ + virtual void set_parameters(std::vector<double>){return;} + + /** + * @brief Set the values of the training data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values + */ + inline void set_value(const double* params, int offset = -1) + { + offset = (offset == -1) ? rung() : offset; + if(_selected) + allowed_op_funcs::log(_n_samp, _feats[0]->value_ptr(params + 2, offset + 2), params[0], params[1], node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); + + allowed_op_funcs::log(_n_samp, _feats[0]->value_ptr(params + 2, offset + 2), params[0], params[1], node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset, false)); + } + + /** + * @brief Set the values of the test data for the feature inside of the value storage arrays * - * @param feats Features to operate over (Edges of the graph) - * @param feat_ind Index of the new feature - * @param l_bound Minimum absolute value allowed for the feature. - * @param u_bound Maximum absolute value allowed for the feature. - * @param param_list The list of parameters to optimize using non-linear least squares - * @param prop The property to fit to + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values */ - LogNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop); + inline void set_test_value(const double* params, int offset = -1) + { + offset = (offset == -1) ? rung() : offset; + allowed_op_funcs::log(_n_test_samp, _feats[0]->test_value_ptr(params + 2, offset + 2), params[0], params[1], node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset, false)); + } /** - * @brief Constructor - * @details Constructs the Node from node pointer of the feature to operate on + * @brief The domain for the feature (min/max values) * - * @param feat_1 shared_ptr of the feature to operate on (A) - * @param feat_ind Index of the new feature - * @param l_bound Minimum absolute value allowed for the feature. - * @param u_bound Maximum absolute value allowed for the feature. - * @param param_list The list of parameters to optimize using non-linear least squares - * @param prop The property to fit to + * @param params parameter values for non-linear operations + * @return the domain */ - LogNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop); + inline Domain domain(double* params){return _feats[0]->domain(params + 2).log(params[0], params[1]);} /** - * @brief Solve the non-linear optimization to set the parameters - * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * @brief The expression of the feature * - * @param prop property to fit to get the parameters - * @param param_list List describing the parameters to fit + * @param params parameter values for non-linear operations + * @return feature expression */ - void get_parameters(std::vector<double>& prop, std::vector<std::string>& param_list); + inline std::string expr(double* params){return "log(" + std::to_string(params[0]) + "*" + _feats[0]->expr(params + 2) + " + " + std::to_string(params[1]) + ")";} + #endif }; diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log/parameterize.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log/parameterize.cpp deleted file mode 100644 index d1c65f0f..00000000 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log/parameterize.cpp +++ /dev/null @@ -1,113 +0,0 @@ -#include <feature_creation/node/operator_nodes/allowed_operator_nodes/log/log.hpp> - -LogNode::LogNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop) : - OperatorNode(feats, feat_ind) -{ - if((feats[0]->type() == NODE_TYPE::NEG_EXP) || (feats[0]->type() == NODE_TYPE::EXP) || (feats[0]->type() == NODE_TYPE::DIV) || (feats[0]->type() == NODE_TYPE::INV) || (feats[0]->type() == NODE_TYPE::MULT) || (feats[0]->type() == NODE_TYPE::LOG) || (feats[0]->type() == NODE_TYPE::SIX_POW) || (feats[0]->type() == NODE_TYPE::CB) || (feats[0]->type() == NODE_TYPE::SQ) || (feats[0]->type() == NODE_TYPE::CBRT) || (feats[0]->type() == NODE_TYPE::SQRT)) - throw InvalidFeatureException(); - - get_parameters(prop, param_list); - - if(_params[0] * _feats[0]->domain() + _params[1] <= 0.0) - throw InvalidFeatureException(); - - set_value(); - if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) - throw InvalidFeatureException(); - - set_test_value(); -} - -LogNode::LogNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop) : - OperatorNode({feat}, feat_ind) -{ - if((feat->type() == NODE_TYPE::NEG_EXP) || (feat->type() == NODE_TYPE::EXP) || (feat->type() == NODE_TYPE::DIV) || (feat->type() == NODE_TYPE::INV) || (feat->type() == NODE_TYPE::MULT) || (feat->type() == NODE_TYPE::LOG) || (feat->type() == NODE_TYPE::SIX_POW) || (feat->type() == NODE_TYPE::CB) || (feat->type() == NODE_TYPE::SQ) || (feat->type() == NODE_TYPE::CBRT) || (feat->type() == NODE_TYPE::SQRT)) - throw InvalidFeatureException(); - - get_parameters(prop, param_list); - - if(_params[0] * _feats[0]->domain() + _params[1] <= 0.0) - throw InvalidFeatureException(); - - set_value(); - if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) - throw InvalidFeatureException(); - - set_test_value(); -} - -void LogNode::get_parameters(std::vector<double>& prop, std::vector<std::string>& param_list) -{ - if(param_list.size() == 0) - return; - Problem problem; - double b = 1.0, c = 0.0; - double* val = _feats[0]->value_ptr(rung() + 2); - if(param_list.size() > 3) - { - throw std::logic_error("Too many parameters passed to the constructor."); - } - else if(param_list.size() == 3) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<LogResidual_alpha_a_b, 1, 1, 1, 1>( - new LogResidual_alpha_a_b(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &_params[1], &b - ); - } - } - else if(param_list.size() == 2) - { - if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("alpha") == 0) || s.compare("a") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<LogResidual_alpha_a, 1, 1, 1>( - new LogResidual_alpha_a(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &_params[1] - ); - } - } - else if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("a") == 0) || s.compare("b") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<LogResidual_a_b, 1, 1, 1>( - new LogResidual_a_b(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[1], &b - ); - } - } - else - throw std::logic_error("Invalid parameter in the parameter list."); - } - else if(param_list.size() == 1) - { - if(std::any_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("a") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<LogResidual_a, 1, 1>( - new LogResidual_a(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[1] - ); - } - } - else - throw std::logic_error("Invalid parameter in the parameter list."); - } - parameterize(problem); -} diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log/parameterized_log.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log/parameterized_log.cpp new file mode 100644 index 00000000..d0438748 --- /dev/null +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log/parameterized_log.cpp @@ -0,0 +1,75 @@ +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/log/parameterized_log.hpp> + +LogParamNode::LogParamNode() +{} + +LogParamNode::LogParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop) : + LogNode(feats, feat_ind) +{ + _params.resize(n_params(), 0.0); + + get_parameters(prop); + + if(_params[0] * _feats[0]->domain() + _params[1] <= 0.0) + throw InvalidFeatureException(); + + set_value(); + if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) + throw InvalidFeatureException(); + + set_test_value(); +} + +LogParamNode::LogParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop) : + LogNode({feat}, feat_ind) +{ + _params.resize(n_params(), 0.0); + + get_parameters(prop); + + if(_params[0] * _feats[0]->domain() + _params[1] <= 0.0) + throw InvalidFeatureException(); + + set_value(); + if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) + throw InvalidFeatureException(); + + set_test_value(); +} + +LogParamNode::LogParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound) : + LogNode(feats, feat_ind) +{ + _params.resize(n_params(), 0.0); +} + +LogParamNode::LogParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound) : + LogNode({feat}, feat_ind) +{ + _params.resize(n_params(), 0.0); +} + +void LogParamNode::get_parameters(std::vector<double>& prop) +{ + nlopt_wrapper::feat_data d; + d._feat = this; + d._prop = prop.data(); + double minf; + + std::fill_n(_params.begin(), _params.size(), 1.0); + dcopy_(_params.size() / 2, nlopt_wrapper::_zeros.data(), 1, &_params[1], 2); + + nlopt::opt opt(nlopt::LN_SBPLX, _params.size()); + opt.set_min_objective(nlopt_wrapper::objective_reg, &d); + opt.set_maxeval(1000); + opt.set_xtol_rel(1e-6); + try + { + nlopt::result result = opt.optimize(_params, minf); + } + catch(std::exception &e) + { + std::fill_n(_params.begin(), _params.size(), 1.0); + dcopy_(_params.size() / 2, nlopt_wrapper::_zeros.data(), 1, &_params[1], 2); + } +} diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log/parameterized_log.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log/parameterized_log.hpp new file mode 100644 index 00000000..e6db88e3 --- /dev/null +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log/parameterized_log.hpp @@ -0,0 +1,153 @@ +/** @file feature_creation/node/operator_nodes/allowed_operator_nodes/log/parameterized_log.hpp + * @brief Class describing the parameterized log operator + * + * This class represents the parameterized unary operator -> log(alpha * A + a) + * + * @author Thomas A. R. Purcell (tpurcell) + * @bug No known bugs. + */ +#ifndef PARAM_LOG_NODE +#define PARAM_LOG_NODE + +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/log/log.hpp> +#include <feature_creation/parameterization/NLOptWrapper.hpp> + +// DocString: cls_abs_node +/** + * @brief Node for the absolute value operator + * + */ +class LogParamNode: public LogNode +{ + using LogNode::set_value; + using LogNode::set_test_value; + using LogNode::domain; + using LogNode::expr; + + friend class boost::serialization::access; + + /** + * @brief Serialization function to send over MPI + * + * @param ar Archive representation of node + */ + template <typename Archive> + void serialize(Archive& ar, const unsigned int version) + { + ar & boost::serialization::base_object<LogNode>(*this); + ar & _params; + } + +protected: + std::vector<double> _params; //!< The parameters vector + +public: + /** + * @brief Base Constructor + * @details This is only used for serialization + */ + LogParamNode(); + + /** + * @brief Constructor + * @details Constructs the Node from node pointer of the feature to operate on + * + * @param feat_1 shared_ptr of the feature to operate on (A) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + * @param prop The property to fit to + */ + LogParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop); + + /** + * @brief Constructor + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + * @param prop The property to fit to + */ + LogParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop); + + /** + * @brief Constructor + * @details Constructs the Node from node pointer of the feature to operate on + * + * @param feat_1 shared_ptr of the feature to operate on (A) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + */ + LogParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound); + + /** + * @brief Constructor + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + */ + LogParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound); + + // DocString: log_param_node_set_value + /** + * @brief Set the values of the training data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + */ + inline void set_value(int offset = -1){set_value(_params.data(), offset);} + + // DocString: log_param_node_set_test_value + /** + * @brief Set the values of the test data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + */ + inline void set_test_value(int offset = -1){set_test_value(_params.data(), offset);} + + // DocString: log_param_node_expr + /** + * @brief Get the expression for the overall feature (From root node down) + */ + inline std::string expr(){return expr(_params.data());} + + // DocString: log_param_node_domain + /** + * @brief The domain for the feature (min/max values) + */ + inline Domain domain(){return domain(_params.data());} + + /** + * @brief The parameters used for introducing more non linearity in the operators + */ + inline std::vector<double> parameters(){return _params;} + + /** + * @brief Solve the non-linear optimization to set the parameters + * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * + * @param prop property to fit to get the parameters + */ + void get_parameters(std::vector<double>& prop); + + /** + * @brief Set the non-linear parameters + */ + inline void set_parameters(std::vector<double> params) + { + if(params.size() != n_params()) + throw std::logic_error("Wrong number of parameters passed to set_parameters."); + _params = params; + } +}; + +#endif \ No newline at end of file diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/mult/multiply.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/mult/multiply.cpp index 9d30eee3..f0366d93 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/mult/multiply.cpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/mult/multiply.cpp @@ -27,6 +27,15 @@ MultNode::MultNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_boun set_test_value(); } +MultNode::MultNode(std::array<node_ptr, 2> feats, int feat_ind): + OperatorNode(feats, feat_ind) +{ + check_feats(); + + set_value(); + set_test_value(); +} + void MultNode::check_feats() { if((_feats[0]->type() == NODE_TYPE::INV) || (_feats[1]->type() == NODE_TYPE::INV) || ((_feats[0]->type() == NODE_TYPE::DIV) && (_feats[1]->type() == NODE_TYPE::DIV))) diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/mult/multiply.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/mult/multiply.hpp index cc00e6a9..58695c87 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/mult/multiply.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/mult/multiply.hpp @@ -61,6 +61,15 @@ public: */ MultNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound); + /** + * @brief Constructor without checking feature values + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + */ + MultNode(std::array<node_ptr, 2> feats, int feat_ind); + // DocString: mult_node_unit /** * @brief Get the unit of the feature (combine the units of _feats) @@ -71,7 +80,7 @@ public: /** * @brief Get the expression for the overall feature (From root node down) */ - inline std::string expr(){return "[(" + std::to_string(_params[0]) + "*" + _feats[0]->expr() + ") * (" + _feats[1]->expr() + ")]";} + inline std::string expr(){return "[(" + _feats[0]->expr() + ") * (" + _feats[1]->expr() + ")]";} // DocString: mult_node_set_value /** @@ -81,11 +90,11 @@ public: */ inline void set_value(int offset = -1) { - if(_selected) - allowed_op_funcs::mult(_n_samp, _feats[0]->value_ptr(offset + 2), _feats[1]->value_ptr(offset + 1), _params[0], _params[1], node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); - offset = (offset == -1) ? rung() : offset; - allowed_op_funcs::mult(_n_samp, _feats[0]->value_ptr(offset + 2), _feats[1]->value_ptr(offset + 1), _params[0], _params[1], node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); + + if(_selected) + allowed_op_funcs::mult(_n_samp, _feats[0]->value_ptr(offset + 2), _feats[1]->value_ptr(offset + 1), 1.0, 0.0, node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); + allowed_op_funcs::mult(_n_samp, _feats[0]->value_ptr(offset + 2), _feats[1]->value_ptr(offset + 1), 1.0, 0.0, node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); } // DocString: mult_node_set_test_value @@ -97,7 +106,7 @@ public: inline void set_test_value(int offset = -1) { offset = (offset == -1) ? rung() : offset; - allowed_op_funcs::mult(_n_test_samp, _feats[0]->test_value_ptr(offset + 2), _feats[1]->test_value_ptr(offset + 1), _params[0], _params[1], node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); + allowed_op_funcs::mult(_n_test_samp, _feats[0]->test_value_ptr(offset + 2), _feats[1]->test_value_ptr(offset + 1), 1.0, 0.0, node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); } // DocString: mult_node_rung @@ -152,39 +161,65 @@ public: #ifdef PARAMETERIZE /** - * @brief Constructor - * @details Constructs the Node from an array of features to operate on + * @brief The parameters used for introducing more non linearity in the operators + */ + virtual std::vector<double> parameters(){return {};} + + /** + * @brief Solve the non-linear optimization to set the parameters + * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature * - * @param feats Features to operate over (Edges of the graph) - * @param feat_ind Index of the new feature - * @param l_bound Minimum absolute value allowed for the feature. - * @param u_bound Maximum absolute value allowed for the feature. - * @param param_list The list of parameters to optimize using non-linear least squares - * @param prop The property to fit to + * @param prop property to fit to get the parameters */ - MultNode(std::array<node_ptr, 2> feats, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop); + virtual void get_parameters(std::vector<double>& prop){return;} + + /** + * @brief Set the non-linear parameters + */ + virtual void set_parameters(std::vector<double>){return;} /** - * @brief Constructor - * @details Constructs the Node from node pointer of the feature to operate on + * @brief Set the values of the training data for the feature inside of the value storage arrays * - * @param feat_1 shared_ptr of the feature to operate on (A) - * @param feat_ind Index of the new feature - * @param l_bound Minimum absolute value allowed for the feature. - * @param u_bound Maximum absolute value allowed for the feature. - * @param param_list The list of parameters to optimize using non-linear least squares - * @param prop The property to fit to + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values */ - MultNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop); + inline void set_value(const double* params, int offset = -1) + { + offset = (offset == -1) ? rung() : offset; + + if(_selected) + allowed_op_funcs::mult(_n_samp, _feats[0]->value_ptr(params + 2 + _feats[1]->n_params(), offset + 2), _feats[1]->value_ptr(params + 2, offset + 1), params[0], params[1], node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); + allowed_op_funcs::mult(_n_samp, _feats[0]->value_ptr(params + 2 + _feats[1]->n_params(), offset + 2), _feats[1]->value_ptr(params + 2, offset + 1), params[0], params[1], node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); + } /** - * @brief Solve the non-linear optimization to set the parameters - * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * @brief Set the values of the test data for the feature inside of the value storage arrays * - * @param prop property to fit to get the parameters - * @param param_list List describing the parameters to fit + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values + */ + inline void set_test_value(const double* params, int offset = -1) + { + offset = (offset == -1) ? rung() : offset; + allowed_op_funcs::mult(_n_test_samp, _feats[0]->test_value_ptr(params + 2 + _feats[1]->n_params(), offset + 2), _feats[1]->test_value_ptr(params + 2, offset + 1), params[0], params[1], node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); + } + + /** + * @brief The domain for the feature (min/max values) + * + * @param params parameter values for non-linear operations + * @return the domain + */ + inline Domain domain(double* params){return _feats[0]->domain(params + _feats[1]->n_params() + 2).mult(_feats[1]->domain(params + 2), params[0], params[1]);} + + /** + * @brief The expression of the feature + * + * @param params parameter values for non-linear operations + * @return feature expression */ - void get_parameters(std::vector<double>& prop, std::vector<std::string>& param_list); + inline std::string expr(double* params){return "[(" + _feats[0]->expr(params + _feats[1]->n_params() + 2) + ") * (" + std::to_string(params[0]) + "*" + _feats[1]->expr(params + 2) + " + " + std::to_string(params[1]) + ")]";} #endif }; diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/mult/parameterize.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/mult/parameterize.cpp deleted file mode 100644 index 8888ed01..00000000 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/mult/parameterize.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include <feature_creation/node/operator_nodes/allowed_operator_nodes/mult/multiply.hpp> - -MultNode::MultNode(std::array<node_ptr, 2> feats, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop): - OperatorNode(feats, feat_ind) -{ - check_feats(); - - get_parameters(prop, param_list); - set_value(); - if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) - throw InvalidFeatureException(); - - set_test_value(); -} - -MultNode::MultNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop): - OperatorNode({feat_1, feat_2}, feat_ind) -{ - check_feats(); - - get_parameters(prop, param_list); - set_value(); - if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) - throw InvalidFeatureException(); - - set_test_value(); -} - -void MultNode::get_parameters(std::vector<double>& prop, std::vector<std::string>& param_list) -{ - if(param_list.size() == 0) - return; - throw std::logic_error("Too many parameters passed to the constructor."); -} diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/mult/parameterized_multiply.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/mult/parameterized_multiply.cpp new file mode 100644 index 00000000..a6b52b42 --- /dev/null +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/mult/parameterized_multiply.cpp @@ -0,0 +1,67 @@ +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/mult/parameterized_multiply.hpp> + +MultParamNode::MultParamNode() +{} + +MultParamNode::MultParamNode(std::array<node_ptr, 2> feats, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop): + MultNode(feats, feat_ind) +{ + _params.resize(n_params(), 0.0); + + get_parameters(prop); + set_value(); + if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) + throw InvalidFeatureException(); + + set_test_value(); +} + +MultParamNode::MultParamNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop): + MultNode({feat_1, feat_2}, feat_ind) +{ + _params.resize(n_params(), 0.0); + + get_parameters(prop); + set_value(); + if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) + throw InvalidFeatureException(); + + set_test_value(); +} + +MultParamNode::MultParamNode(std::array<node_ptr, 2> feats, int feat_ind, double l_bound, double u_bound): + MultNode(feats, feat_ind) +{ + _params.resize(n_params(), 0.0); +} + +MultParamNode::MultParamNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound): + MultNode({feat_1, feat_2}, feat_ind) +{ + _params.resize(n_params(), 0.0); +} + +void MultParamNode::get_parameters(std::vector<double>& prop) +{ + nlopt_wrapper::feat_data d; + d._feat = this; + d._prop = prop.data(); + double minf; + + std::fill_n(_params.begin(), _params.size(), 1.0); + dcopy_(_params.size() / 2, nlopt_wrapper::_zeros.data(), 1, &_params[1], 2); + + nlopt::opt opt(nlopt::LN_SBPLX, _params.size()); + opt.set_min_objective(nlopt_wrapper::objective_reg, &d); + opt.set_maxeval(1000); + opt.set_xtol_rel(1e-2); + try + { + nlopt::result result = opt.optimize(_params, minf); + } + catch(std::exception &e) + { + std::fill_n(_params.begin(), _params.size(), 1.0); + dcopy_(_params.size() / 2, nlopt_wrapper::_zeros.data(), 1, &_params[1], 2); + } +} diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/mult/parameterized_multiply.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/mult/parameterized_multiply.hpp new file mode 100644 index 00000000..4bcd9e9e --- /dev/null +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/mult/parameterized_multiply.hpp @@ -0,0 +1,151 @@ +/** @file feature_creation/node/operator_nodes/allowed_operator_nodes/div/parameterized_multiply.hpp + * @brief Class describing the parameterized addition operator + * + * This class represents the parameterized unary operator -> A * (alpha * B + a) + * + * @author Thomas A. R. Purcell (tpurcell) + * @bug No known bugs. + */ +#ifndef PARAM_MULT_NODE +#define PARAM_MULT_NODE + +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/mult/multiply.hpp> +#include <feature_creation/parameterization/NLOptWrapper.hpp> + +// DocString: cls_param_add_node +/** + * @brief Node for the absolute value operator + * + */ +class MultParamNode: public MultNode +{ + using MultNode::set_value; + using MultNode::set_test_value; + using MultNode::domain; + using MultNode::expr; + + friend class boost::serialization::access; + + /** + * @brief Serialization function to send over MPI + * + * @param ar Archive representation of node + */ + template <typename Archive> + void serialize(Archive& ar, const unsigned int version) + { + ar & boost::serialization::base_object<MultNode>(*this); + ar & _params; + } +protected: + std::vector<double> _params; +public: + /** + * @brief Base Constructor + * @details This is only used for serialization + */ + MultParamNode(); + + /** + * @brief Constructor + * @details Constructs the Node from node pointer of the feature to operate on + * + * @param feat_1 shared_ptr of the feature to operate on (A) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + * @param prop The property to fit to + */ + MultParamNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop); + + /** + * @brief Constructor + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + * @param prop The property to fit to + */ + MultParamNode(std::array<node_ptr, 2> feats, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop); + + /** + * @brief Constructor + * @details Constructs the Node from node pointer of the feature to operate on + * + * @param feat_1 shared_ptr of the feature to operate on (A) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + */ + MultParamNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound); + + /** + * @brief Constructor + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + */ + MultParamNode(std::array<node_ptr, 2> feats, int feat_ind, double l_bound, double u_bound); + + // DocString: mult_param_node_set_value + /** + * @brief Set the values of the training data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + */ + inline void set_value(int offset = -1){set_value(_params.data(), offset);} + + // DocString: mult_param_node_set_test_value + /** + * @brief Set the values of the test data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + */ + inline void set_test_value(int offset = -1){set_test_value(_params.data(), offset);} + + // DocString: mult_param_node_expr + /** + * @brief Get the expression for the overall feature (From root node down) + */ + inline std::string expr(){return expr(_params.data());} + + // DocString: mult_param_node_domain + /** + * @brief The domain for the feature (min/max values) + */ + inline Domain domain(){return domain(_params.data());} + + /** + * @brief The parameters used for introducing more non linearity in the operators + */ + inline std::vector<double> parameters(){return _params;} + + /** + * @brief Solve the non-linear optimization to set the parameters + * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * + * @param prop property to fit to get the parameters + */ + void get_parameters(std::vector<double>& prop); + + /** + * @brief Set the non-linear parameters + */ + inline void set_parameters(std::vector<double> params) + { + if(params.size() != n_params()) + throw std::logic_error("Wrong number of parameters passed to set_parameters."); + _params = params; + } +}; + +#endif \ No newline at end of file diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/neg_exp/negative_exponential.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/neg_exp/negative_exponential.cpp index 4e0b6fcc..a166ef61 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/neg_exp/negative_exponential.cpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/neg_exp/negative_exponential.cpp @@ -17,7 +17,7 @@ NegExpNode::NegExpNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bou throw InvalidFeatureException(); set_test_value(); - } +} NegExpNode::NegExpNode(node_ptr feat, int feat_ind, double l_bound, double u_bound): OperatorNode({feat}, feat_ind) @@ -33,7 +33,17 @@ NegExpNode::NegExpNode(node_ptr feat, int feat_ind, double l_bound, double u_bou throw InvalidFeatureException(); set_test_value(); - } +} + +NegExpNode::NegExpNode(std::array<node_ptr, 1> feats, int feat_ind): + OperatorNode(feats, feat_ind) +{ + if((feats[0]->type() == NODE_TYPE::NEG_EXP) || (feats[0]->type() == NODE_TYPE::EXP) || (feats[0]->type() == NODE_TYPE::ADD) || (feats[0]->type() == NODE_TYPE::SUB) || (feats[0]->type() == NODE_TYPE::LOG)) + throw InvalidFeatureException(); + + set_value(); + set_test_value(); +} void NegExpNode::update_add_sub_leaves(std::map<std::string, int>& add_sub_leaves, int pl_mn, int& expected_abs_tot) { diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/neg_exp/negative_exponential.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/neg_exp/negative_exponential.hpp index 6c03be6b..d9af14bc 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/neg_exp/negative_exponential.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/neg_exp/negative_exponential.hpp @@ -61,6 +61,15 @@ public: */ NegExpNode(node_ptr feat, int feat_ind, double l_bound, double u_bound); + /** + * @brief Constructor without checking feature values + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + */ + NegExpNode(std::array<node_ptr, 1> feats, int feat_ind); + // DocString: neg_exp_node_unit /** * @brief Get the unit of the feature (combine the units of _feats) @@ -71,7 +80,7 @@ public: /** * @brief Get the expression for the overall feature (From root node down) */ - inline std::string expr(){return "exp[-1.0*(" + std::to_string(_params[0]) + "*" + _feats[0]->expr() + " + " + std::to_string(_params[1]) + ")]";} + inline std::string expr(){return "exp[-1.0*(" + _feats[0]->expr() + ")]";} // DocString: neg_exp_node_set_value /** @@ -81,11 +90,11 @@ public: */ inline void set_value(int offset = -1) { - if(_selected) - allowed_op_funcs::neg_exp(_n_samp, _feats[0]->value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); - offset = (offset == -1) ? rung() : offset; - allowed_op_funcs::neg_exp(_n_samp, _feats[0]->value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); + + if(_selected) + allowed_op_funcs::neg_exp(_n_samp, _feats[0]->value_ptr(offset + 2), 1.0, 0.0, node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); + allowed_op_funcs::neg_exp(_n_samp, _feats[0]->value_ptr(offset + 2), 1.0, 0.0, node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); }; // DocString: neg_exp_node_set_test_value @@ -97,7 +106,7 @@ public: inline void set_test_value(int offset = -1) { offset = (offset == -1) ? rung() : offset; - allowed_op_funcs::neg_exp(_n_test_samp, _feats[0]->test_value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); + allowed_op_funcs::neg_exp(_n_test_samp, _feats[0]->test_value_ptr(offset + 2), 1.0, 0.0, node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); }; // DocString: neg_exp_node_rung @@ -117,7 +126,7 @@ public: /** * @brief The domain for the feature (min/max values) */ - Domain domain(){return _feats[0]->domain().exp(-1.0 * _params[0], _params[1]);} + Domain domain(){return _feats[0]->domain().exp(-1.0, 0.0);} /** * @brief Get the string character representation of the node for the postfix expression @@ -146,39 +155,66 @@ public: #ifdef PARAMETERIZE /** - * @brief Constructor - * @details Constructs the Node from an array of features to operate on + * @brief The parameters used for introducing more non linearity in the operators + */ + virtual std::vector<double> parameters(){return {};} + + /** + * @brief Solve the non-linear optimization to set the parameters + * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * + * @param prop property to fit to get the parameters + */ + virtual void get_parameters(std::vector<double>& prop){return;} + + /** + * @brief Set the non-linear parameters + */ + virtual void set_parameters(std::vector<double>){return;} + + /** + * @brief Set the values of the training data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values + */ + inline void set_value(const double* params, int offset = -1) + { + offset = (offset == -1) ? rung() : offset; + if(_selected) + allowed_op_funcs::neg_exp(_n_samp, _feats[0]->value_ptr(params + 2, offset + 2), params[0], params[1], node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); + + allowed_op_funcs::neg_exp(_n_samp, _feats[0]->value_ptr(params + 2, offset + 2), params[0], params[1], node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset, false)); + } + + /** + * @brief Set the values of the test data for the feature inside of the value storage arrays * - * @param feats Features to operate over (Edges of the graph) - * @param feat_ind Index of the new feature - * @param l_bound Minimum absolute value allowed for the feature. - * @param u_bound Maximum absolute value allowed for the feature. - * @param param_list The list of parameters to optimize using non-linear least squares - * @param prop The property to fit to + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values */ - NegExpNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop); + inline void set_test_value(const double* params, int offset = -1) + { + offset = (offset == -1) ? rung() : offset; + allowed_op_funcs::neg_exp(_n_test_samp, _feats[0]->test_value_ptr(params + 2, offset + 2), params[0], params[1], node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset, false)); + } /** - * @brief Constructor - * @details Constructs the Node from node pointer of the feature to operate on + * @brief The domain for the feature (min/max values) * - * @param feat_1 shared_ptr of the feature to operate on (A) - * @param feat_ind Index of the new feature - * @param l_bound Minimum absolute value allowed for the feature. - * @param u_bound Maximum absolute value allowed for the feature. - * @param param_list The list of parameters to optimize using non-linear least squares - * @param prop The property to fit to + * @param params parameter values for non-linear operations + * @return the domain */ - NegExpNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop); + inline Domain domain(double* params){return _feats[0]->domain(params + 2).exp(-1.0 * params[0], params[1]);} /** - * @brief Solve the non-linear optimization to set the parameters - * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * @brief The expression of the feature * - * @param prop property to fit to get the parameters - * @param param_list List describing the parameters to fit + * @param params parameter values for non-linear operations + * @return feature expression */ - void get_parameters(std::vector<double>& prop, std::vector<std::string>& param_list); + inline std::string expr(double* params){return "exp[-1.0*(" + std::to_string(params[0]) + "*" + _feats[0]->expr(params + 2) + " + " + std::to_string(params[1]) + ")]";} + #endif }; diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/neg_exp/parameterize.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/neg_exp/parameterize.cpp deleted file mode 100644 index 5d21fe50..00000000 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/neg_exp/parameterize.cpp +++ /dev/null @@ -1,105 +0,0 @@ -#include <feature_creation/node/operator_nodes/allowed_operator_nodes/neg_exp/negative_exponential.hpp> - -NegExpNode::NegExpNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop) : - OperatorNode(feats, feat_ind) -{ - if((feats[0]->type() == NODE_TYPE::NEG_EXP) || (feats[0]->type() == NODE_TYPE::EXP) || (feats[0]->type() == NODE_TYPE::ADD) || (feats[0]->type() == NODE_TYPE::SUB) || (feats[0]->type() == NODE_TYPE::LOG)) - throw InvalidFeatureException(); - - get_parameters(prop, param_list); - set_value(); - if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) - throw InvalidFeatureException(); - - set_test_value(); -} - -NegExpNode::NegExpNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop) : - OperatorNode({feat}, feat_ind) -{ - if((feat->type() == NODE_TYPE::NEG_EXP) || (feat->type() == NODE_TYPE::EXP) || (feat->type() == NODE_TYPE::ADD) || (feat->type() == NODE_TYPE::SUB) || (feat->type() == NODE_TYPE::LOG)) - throw InvalidFeatureException(); - - get_parameters(prop, param_list); - set_value(); - if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) - throw InvalidFeatureException(); - - set_test_value(); -} - -void NegExpNode::get_parameters(std::vector<double>& prop, std::vector<std::string>& param_list) -{ - if(param_list.size() == 0) - return; - Problem problem; - double b = 1.0, c = 0.0; - double* val = _feats[0]->value_ptr(rung() + 2); - if(param_list.size() > 3) - { - throw std::logic_error("Too many parameters passed to the constructor."); - } - else if(param_list.size() == 3) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<NegExpResidual_alpha_a_c, 1, 1, 1, 1>( - new NegExpResidual_alpha_a_c(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &_params[1], &c - ); - } - } - else if(param_list.size() == 2) - { - if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("alpha") == 0) || s.compare("a") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<NegExpResidual_alpha_a, 1, 1, 1>( - new NegExpResidual_alpha_a(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &_params[1] - ); - } - } - else if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("alpha") == 0) || s.compare("c") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<NegExpResidual_alpha_c, 1, 1, 1>( - new NegExpResidual_alpha_c(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &c - ); - } - } - else - throw std::logic_error("Invalid parameter in the parameter list."); - } - else if(param_list.size() == 1) - { - if(std::any_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("alpha") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<NegExpResidual_alpha, 1, 1>( - new NegExpResidual_alpha(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0] - ); - } - } - else - throw std::logic_error("Invalid parameter in the parameter list."); - } - parameterize(problem); -} diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/neg_exp/parameterized_negative_exponential.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/neg_exp/parameterized_negative_exponential.cpp new file mode 100644 index 00000000..2fac9ab1 --- /dev/null +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/neg_exp/parameterized_negative_exponential.cpp @@ -0,0 +1,67 @@ +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/neg_exp/parameterized_negative_exponential.hpp> + +NegExpParamNode::NegExpParamNode() +{} + +NegExpParamNode::NegExpParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop) : + NegExpNode(feats, feat_ind) +{ + _params.resize(n_params(), 0.0); + + get_parameters(prop); + set_value(); + if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) + throw InvalidFeatureException(); + + set_test_value(); +} + +NegExpParamNode::NegExpParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop) : + NegExpNode({feat}, feat_ind) +{ + _params.resize(n_params(), 0.0); + + get_parameters(prop); + set_value(); + if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) + throw InvalidFeatureException(); + + set_test_value(); +} + +NegExpParamNode::NegExpParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound) : + NegExpNode(feats, feat_ind) +{ + _params.resize(n_params(), 0.0); +} + +NegExpParamNode::NegExpParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound) : + NegExpNode({feat}, feat_ind) +{ + _params.resize(n_params(), 0.0); +} + +void NegExpParamNode::get_parameters(std::vector<double>& prop) +{ + nlopt_wrapper::feat_data d; + d._feat = this; + d._prop = prop.data(); + double minf; + + std::fill_n(_params.begin(), _params.size(), 1.0); + dcopy_(_params.size() / 2, nlopt_wrapper::_zeros.data(), 1, &_params[1], 2); + + nlopt::opt opt(nlopt::LN_SBPLX, _params.size()); + opt.set_min_objective(nlopt_wrapper::objective_reg, &d); + opt.set_maxeval(1000); + opt.set_xtol_rel(1e-2); + try + { + nlopt::result result = opt.optimize(_params, minf); + } + catch(std::exception &e) + { + std::fill_n(_params.begin(), _params.size(), 1.0); + dcopy_(_params.size() / 2, nlopt_wrapper::_zeros.data(), 1, &_params[1], 2); + } +} diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/neg_exp/parameterized_negative_exponential.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/neg_exp/parameterized_negative_exponential.hpp new file mode 100644 index 00000000..75127876 --- /dev/null +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/neg_exp/parameterized_negative_exponential.hpp @@ -0,0 +1,153 @@ +/** @file feature_creation/node/operator_nodes/allowed_operator_nodes/neg_exp/parameterized_negative_exponetial.hpp + * @brief Class describing the parameterized neg_exp operator + * + * This class represents the parameterized unary operator -> exp(-alpha * A + a) + * + * @author Thomas A. R. Purcell (tpurcell) + * @bug No known bugs. + */ +#ifndef PARAM_NEG_EXP_NODE +#define PARAM_NEG_EXP_NODE + +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/neg_exp/negative_exponential.hpp> +#include <feature_creation/parameterization/NLOptWrapper.hpp> + +// DocString: cls_abs_node +/** + * @brief Node for the absolute value operator + * + */ +class NegExpParamNode: public NegExpNode +{ + using NegExpNode::set_value; + using NegExpNode::set_test_value; + using NegExpNode::domain; + using NegExpNode::expr; + + friend class boost::serialization::access; + + /** + * @brief Serialization function to send over MPI + * + * @param ar Archive representation of node + */ + template <typename Archive> + void serialize(Archive& ar, const unsigned int version) + { + ar & boost::serialization::base_object<NegExpNode>(*this); + ar & _params; + } + +protected: + std::vector<double> _params; //!< The parameters vector + +public: + /** + * @brief Base Constructor + * @details This is only used for serialization + */ + NegExpParamNode(); + + /** + * @brief Constructor + * @details Constructs the Node from node pointer of the feature to operate on + * + * @param feat_1 shared_ptr of the feature to operate on (A) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + * @param prop The property to fit to + */ + NegExpParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop); + + /** + * @brief Constructor + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + * @param prop The property to fit to + */ + NegExpParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop); + + /** + * @brief Constructor + * @details Constructs the Node from node pointer of the feature to operate on + * + * @param feat_1 shared_ptr of the feature to operate on (A) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + */ + NegExpParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound); + + /** + * @brief Constructor + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + */ + NegExpParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound); + + // DocString: neg_exp_param_node_set_value + /** + * @brief Set the values of the training data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + */ + inline void set_value(int offset = -1){set_value(_params.data(), offset);} + + // DocString: neg_exp_param_node_set_test_value + /** + * @brief Set the values of the test data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + */ + inline void set_test_value(int offset = -1){set_test_value(_params.data(), offset);} + + // DocString: neg_exp_param_node_expr + /** + * @brief Get the expression for the overall feature (From root node down) + */ + inline std::string expr(){return expr(_params.data());} + + // DocString: neg_exp_param_node_domain + /** + * @brief The domain for the feature (min/max values) + */ + inline Domain domain(){return domain(_params.data());} + + /** + * @brief The parameters used for introducing more non linearity in the operators + */ + inline std::vector<double> parameters(){return _params;} + + /** + * @brief Solve the non-linear optimization to set the parameters + * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * + * @param prop property to fit to get the parameters + */ + void get_parameters(std::vector<double>& prop); + + /** + * @brief Set the non-linear parameters + */ + inline void set_parameters(std::vector<double> params) + { + if(params.size() != n_params()) + throw std::logic_error("Wrong number of parameters passed to set_parameters."); + _params = params; + } +}; + +#endif \ No newline at end of file diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin/parameterize.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin/parameterize.cpp deleted file mode 100644 index e5730a38..00000000 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin/parameterize.cpp +++ /dev/null @@ -1,214 +0,0 @@ -#include <feature_creation/node/operator_nodes/allowed_operator_nodes/sin/sin.hpp> - -SinNode::SinNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop) : - OperatorNode(feats, feat_ind) -{ - if((feats[0]->type() == NODE_TYPE::SIN) || (feats[0]->type() == NODE_TYPE::COS)) - throw InvalidFeatureException(); - - get_parameters(prop, param_list); - set_value(); - if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) - throw InvalidFeatureException(); - - set_test_value(); -} - -SinNode::SinNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop) : - OperatorNode({feat}, feat_ind) -{ - if((feat->type() == NODE_TYPE::SIN) || (feat->type() == NODE_TYPE::COS)) - throw InvalidFeatureException(); - - get_parameters(prop, param_list); - set_value(); - if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) - throw InvalidFeatureException(); - - set_test_value(); -} - -void SinNode::get_parameters(std::vector<double>& prop, std::vector<std::string>& param_list) -{ - if(param_list.size() == 0) - return; - Problem problem; - double b = 1.0, c = 0.0; - double* val = _feats[0]->value_ptr(rung() + 2); - if(param_list.size() > 4) - { - throw std::logic_error("Too many parameters passed to the constructor."); - } - else if(param_list.size() == 4) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<SinResidual_alpha_a_b_c, 1, 1, 1, 1, 1>( - new SinResidual_alpha_a_b_c(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &_params[1], &b, &c - ); - } - } - else if(param_list.size() == 3) - { - if(std::none_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("alpha") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<SinResidual_a_b_c, 1, 1, 1, 1>( - new SinResidual_a_b_c(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[1], &b, &c - ); - } - } - else if(std::none_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("a") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<SinResidual_alpha_b_c, 1, 1, 1, 1>( - new SinResidual_alpha_b_c(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &b, &c - ); - } - } - else if(std::none_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("b") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<SinResidual_alpha_a_c, 1, 1, 1, 1>( - new SinResidual_alpha_a_c(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &_params[1], &c - ); - } - } - else if(std::none_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("c") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<SinResidual_alpha_a_b, 1, 1, 1, 1>( - new SinResidual_alpha_a_b(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &_params[1], &b - ); - } - } - else - throw std::logic_error("Invalid parameter in the parameter list."); - } - else if(param_list.size() == 2) - { - if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("alpha") == 0) || s.compare("a") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<SinResidual_alpha_a, 1, 1, 1>( - new SinResidual_alpha_a(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &_params[1] - ); - } - } - else if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("alpha") == 0) || s.compare("b") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<SinResidual_alpha_b, 1, 1, 1>( - new SinResidual_alpha_b(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &b - ); - } - } - else if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("alpha") == 0) || s.compare("c") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<SinResidual_alpha_c, 1, 1, 1>( - new SinResidual_alpha_c(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &c - ); - } - } - else if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("a") == 0) || s.compare("b") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<SinResidual_a_b, 1, 1, 1>( - new SinResidual_a_b(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[1], &b - ); - } - } - else if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("a") == 0) || s.compare("c") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<SinResidual_a_c, 1, 1, 1>( - new SinResidual_a_c(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[1], &c - ); - } - } - else - throw std::logic_error("Invalid parameter in the parameter list."); - } - else if(param_list.size() == 1) - { - if(std::any_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("alpha") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<SinResidual_alpha, 1, 1>( - new SinResidual_alpha(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0] - ); - } - } - else if(std::any_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("a") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<SinResidual_a, 1, 1>( - new SinResidual_a(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[1] - ); - } - } - else - throw std::logic_error("Invalid parameter in the parameter list."); - } - parameterize(problem); -} diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin/parameterized_sin.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin/parameterized_sin.cpp new file mode 100644 index 00000000..5b844b58 --- /dev/null +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin/parameterized_sin.cpp @@ -0,0 +1,69 @@ +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/sin/parameterized_sin.hpp> + +SinParamNode::SinParamNode() +{} + +SinParamNode::SinParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop) : + SinNode(feats, feat_ind) +{ + _params.resize(n_params(), 0.0); + + get_parameters(prop); + + set_value(); + if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) + throw InvalidFeatureException(); + + set_test_value(); +} + +SinParamNode::SinParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop) : + SinNode({feat}, feat_ind) +{ + _params.resize(n_params(), 0.0); + + get_parameters(prop); + + set_value(); + if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) + throw InvalidFeatureException(); + + set_test_value(); +} + +SinParamNode::SinParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound) : + SinNode(feats, feat_ind) +{ + _params.resize(n_params(), 0.0); +} + +SinParamNode::SinParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound) : + SinNode({feat}, feat_ind) +{ + _params.resize(n_params(), 0.0); +} + +void SinParamNode::get_parameters(std::vector<double>& prop) +{ + nlopt_wrapper::feat_data d; + d._feat = this; + d._prop = prop.data(); + double minf; + + std::fill_n(_params.begin(), _params.size(), 1.0); + dcopy_(_params.size() / 2, nlopt_wrapper::_zeros.data(), 1, &_params[1], 2); + + nlopt::opt opt(nlopt::LN_SBPLX, _params.size()); + opt.set_min_objective(nlopt_wrapper::objective_reg, &d); + opt.set_maxeval(1000); + opt.set_xtol_rel(1e-2); + try + { + nlopt::result result = opt.optimize(_params, minf); + } + catch(std::exception &e) + { + std::fill_n(_params.begin(), _params.size(), 1.0); + dcopy_(_params.size() / 2, nlopt_wrapper::_zeros.data(), 1, &_params[1], 2); + } +} diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin/parameterized_sin.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin/parameterized_sin.hpp new file mode 100644 index 00000000..dd09603a --- /dev/null +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin/parameterized_sin.hpp @@ -0,0 +1,153 @@ +/** @file feature_creation/node/operator_nodes/allowed_operator_nodes/sin/parameterized_sin.hpp + * @brief Class describing the parameterized sin operator + * + * This class represents the parameterized unary operator -> sin(alpha * A + a) + * + * @author Thomas A. R. Purcell (tpurcell) + * @bug No known bugs. + */ +#ifndef PARAM_SIN_NODE +#define PARAM_SIN_NODE + +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/sin/sin.hpp> +#include <feature_creation/parameterization/NLOptWrapper.hpp> + +// DocString: cls_abs_node +/** + * @brief Node for the absolute value operator + * + */ +class SinParamNode: public SinNode +{ + using SinNode::set_value; + using SinNode::set_test_value; + using SinNode::domain; + using SinNode::expr; + + friend class boost::serialization::access; + + /** + * @brief Serialization function to send over MPI + * + * @param ar Archive representation of node + */ + template <typename Archive> + void serialize(Archive& ar, const unsigned int version) + { + ar & boost::serialization::base_object<SinNode>(*this); + ar & _params; + } + +protected: + std::vector<double> _params; //!< The parameters vector + +public: + /** + * @brief Base Constructor + * @details This is only used for serialization + */ + SinParamNode(); + + /** + * @brief Constructor + * @details Constructs the Node from node pointer of the feature to operate on + * + * @param feat_1 shared_ptr of the feature to operate on (A) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + * @param prop The property to fit to + */ + SinParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop); + + /** + * @brief Constructor + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + * @param prop The property to fit to + */ + SinParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop); + + /** + * @brief Constructor + * @details Constructs the Node from node pointer of the feature to operate on + * + * @param feat_1 shared_ptr of the feature to operate on (A) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + */ + SinParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound); + + /** + * @brief Constructor + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + */ + SinParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound); + + // DocString: sin_param_node_set_value + /** + * @brief Set the values of the training data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + */ + inline void set_value(int offset = -1){set_value(_params.data(), offset);} + + // DocString: sin_param_node_set_test_value + /** + * @brief Set the values of the test data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + */ + inline void set_test_value(int offset = -1){set_test_value(_params.data(), offset);} + + // DocString: sin_param_node_expr + /** + * @brief Get the expression for the overall feature (From root node down) + */ + inline std::string expr(){return expr(_params.data());} + + // DocString: sin_param_node_domain + /** + * @brief The domain for the feature (min/max values) + */ + inline Domain domain(){return domain(_params.data());} + + /** + * @brief The parameters used for introducing more non linearity in the operators + */ + inline std::vector<double> parameters(){return _params;} + + /** + * @brief Solve the non-linear optimization to set the parameters + * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * + * @param prop property to fit to get the parameters + */ + void get_parameters(std::vector<double>& prop); + + /** + * @brief Set the non-linear parameters + */ + inline void set_parameters(std::vector<double> params) + { + if(params.size() != n_params()) + throw std::logic_error("Wrong number of parameters passed to set_parameters."); + _params = params; + } +}; + +#endif \ No newline at end of file diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin/sin.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin/sin.cpp index bf0690de..0bcc6170 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin/sin.cpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin/sin.cpp @@ -17,7 +17,7 @@ SinNode::SinNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, do throw InvalidFeatureException(); set_test_value(); - } +} SinNode::SinNode(node_ptr feat, int feat_ind, double l_bound, double u_bound): OperatorNode({feat}, feat_ind) @@ -34,7 +34,17 @@ SinNode::SinNode(node_ptr feat, int feat_ind, double l_bound, double u_bound): throw InvalidFeatureException(); set_test_value(); - } +} + +SinNode::SinNode(std::array<node_ptr, 1> feats, int feat_ind): + OperatorNode(feats, feat_ind) +{ + if((feats[0]->type() == NODE_TYPE::SIN) || (feats[0]->type() == NODE_TYPE::COS)) + throw InvalidFeatureException(); + + set_value(); + set_test_value(); +} void SinNode::update_add_sub_leaves(std::map<std::string, int>& add_sub_leaves, int pl_mn, int& expected_abs_tot) { diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin/sin.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin/sin.hpp index 8f0dbf3b..992bf8f0 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin/sin.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin/sin.hpp @@ -61,6 +61,15 @@ public: */ SinNode(node_ptr feat, int feat_ind, double l_bound, double u_bound); + /** + * @brief Constructor without checking feature values + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + */ + SinNode(std::array<node_ptr, 1> feats, int feat_ind); + // DocString: sin_node_unit /** * @brief Get the unit of the feature (combine the units of _feats) @@ -71,7 +80,7 @@ public: /** * @brief Get the expression for the overall feature (From root node down) */ - inline std::string expr(){return "sin(" + std::to_string(_params[0]) + "*" + _feats[0]->expr() + " + " + std::to_string(_params[1]) + ")";} + inline std::string expr(){return "sin(" + _feats[0]->expr() + ")";} // DocString: sin_node_set_value /** @@ -81,11 +90,11 @@ public: */ inline void set_value(int offset = -1) { - if(_selected) - allowed_op_funcs::sin(_n_samp, _feats[0]->value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); - offset = (offset == -1) ? rung() : offset; - allowed_op_funcs::sin(_n_samp, _feats[0]->value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); + + if(_selected) + allowed_op_funcs::sin(_n_samp, _feats[0]->value_ptr(offset + 2), 1.0, 0.0, node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); + allowed_op_funcs::sin(_n_samp, _feats[0]->value_ptr(offset + 2), 1.0, 0.0, node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); } // DocString: sin_node_set_test_value @@ -97,7 +106,7 @@ public: inline void set_test_value(int offset = -1) { offset = (offset == -1) ? rung() : offset; - allowed_op_funcs::sin(_n_test_samp, _feats[0]->test_value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); + allowed_op_funcs::sin(_n_test_samp, _feats[0]->test_value_ptr(offset + 2), 1.0, 0.0, node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); } // DocString: sin_node_rung @@ -146,39 +155,65 @@ public: #ifdef PARAMETERIZE /** - * @brief Constructor - * @details Constructs the Node from an array of features to operate on + * @brief The parameters used for introducing more non linearity in the operators + */ + virtual std::vector<double> parameters(){return {};} + + /** + * @brief Solve the non-linear optimization to set the parameters + * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature * - * @param feats Features to operate over (Edges of the graph) - * @param feat_ind Index of the new feature - * @param l_bound Minimum absolute value allowed for the feature. - * @param u_bound Maximum absolute value allowed for the feature. - * @param param_list The list of parameters to optimize using non-linear least squares - * @param prop The property to fit to + * @param prop property to fit to get the parameters */ - SinNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop); + virtual void get_parameters(std::vector<double>& prop){return;} + + /** + * @brief Set the non-linear parameters + */ + virtual void set_parameters(std::vector<double>){return;} /** - * @brief Constructor - * @details Constructs the Node from node pointer of the feature to operate on + * @brief Set the values of the training data for the feature inside of the value storage arrays * - * @param feat_1 shared_ptr of the feature to operate on (A) - * @param feat_ind Index of the new feature - * @param l_bound Minimum absolute value allowed for the feature. - * @param u_bound Maximum absolute value allowed for the feature. - * @param param_list The list of parameters to optimize using non-linear least squares - * @param prop The property to fit to + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values */ - SinNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop); + inline void set_value(const double* params, int offset = -1) + { + offset = (offset == -1) ? rung() : offset; + if(_selected) + allowed_op_funcs::sin(_n_samp, _feats[0]->value_ptr(params + 2, offset + 2), params[0], params[1], node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); + + allowed_op_funcs::sin(_n_samp, _feats[0]->value_ptr(params + 2, offset + 2), params[0], params[1], node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset, false)); + } /** - * @brief Solve the non-linear optimization to set the parameters - * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * @brief Set the values of the test data for the feature inside of the value storage arrays * - * @param prop property to fit to get the parameters - * @param param_list List describing the parameters to fit + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values + */ + inline void set_test_value(const double* params, int offset = -1) + { + offset = (offset == -1) ? rung() : offset; + allowed_op_funcs::sin(_n_test_samp, _feats[0]->test_value_ptr(params + 2, offset + 2), params[0], params[1], node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset, false)); + } + + /** + * @brief The domain for the feature (min/max values) + * + * @param params parameter values for non-linear operations + * @return the domain + */ + inline Domain domain(double* params){return Domain(-1.0, 1.0);} + + /** + * @brief The expression of the feature + * + * @param params parameter values for non-linear operations + * @return feature expression */ - void get_parameters(std::vector<double>& prop, std::vector<std::string>& param_list); + inline std::string expr(double* params){return "sin(" + std::to_string(params[0]) + "*" + _feats[0]->expr(params + 2) + " + " + std::to_string(params[1]) + ")";} #endif }; diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/six_pow/parameterize.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/six_pow/parameterize.cpp deleted file mode 100644 index 0d372c03..00000000 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/six_pow/parameterize.cpp +++ /dev/null @@ -1,105 +0,0 @@ -#include <feature_creation/node/operator_nodes/allowed_operator_nodes/six_pow/sixth_power.hpp> - -SixPowNode::SixPowNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop) : - OperatorNode(feats, feat_ind) -{ - if((feats[0]->type() == NODE_TYPE::CBRT) || (feats[0]->type() == NODE_TYPE::SQRT) || (feats[0]->type() == NODE_TYPE::SQ) || (feats[0]->type() == NODE_TYPE::CB) || (feats[0]->type() == NODE_TYPE::INV)) - throw InvalidFeatureException(); - - get_parameters(prop, param_list); - set_value(); - if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) - throw InvalidFeatureException(); - - set_test_value(); -} - -SixPowNode::SixPowNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop) : - OperatorNode({feat}, feat_ind) -{ - if((feat->type() == NODE_TYPE::CBRT) || (feat->type() == NODE_TYPE::SQRT) || (feat->type() == NODE_TYPE::SQ) || (feat->type() == NODE_TYPE::CB) || (feat->type() == NODE_TYPE::INV)) - throw InvalidFeatureException(); - - get_parameters(prop, param_list); - set_value(); - if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) - throw InvalidFeatureException(); - - set_test_value(); -} - -void SixPowNode::get_parameters(std::vector<double>& prop, std::vector<std::string>& param_list) -{ - if(param_list.size() == 0) - return; - Problem problem; - double c = 0.0; - double* val = _feats[0]->value_ptr(rung() + 2); - if(param_list.size() > 3) - { - throw std::logic_error("Too many parameters passed to the constructor."); - } - else if(param_list.size() == 3) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<SixPowResidual_alpha_a_c, 1, 1, 1, 1>( - new SixPowResidual_alpha_a_c(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &_params[1], &c - ); - } - } - else if(param_list.size() == 2) - { - if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("alpha") == 0) || s.compare("a") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<SixPowResidual_alpha_a, 1, 1, 1>( - new SixPowResidual_alpha_a(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &_params[1] - ); - } - } - else if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("a") == 0) || s.compare("c") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<SixPowResidual_a_c, 1, 1, 1>( - new SixPowResidual_a_c(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[1], &c - ); - } - } - else - throw std::logic_error("Invalid parameter in the parameter list."); - } - else if(param_list.size() == 1) - { - if(std::any_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("a") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<SixPowResidual_a, 1, 1>( - new SixPowResidual_a(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[1] - ); - } - } - else - throw std::logic_error("Invalid parameter in the parameter list."); - } - parameterize(problem); -} diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/six_pow/parameterized_sixth_power.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/six_pow/parameterized_sixth_power.cpp new file mode 100644 index 00000000..200fa995 --- /dev/null +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/six_pow/parameterized_sixth_power.cpp @@ -0,0 +1,69 @@ +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/six_pow/parameterized_sixth_power.hpp> + +SixPowParamNode::SixPowParamNode() +{} + +SixPowParamNode::SixPowParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop) : + SixPowNode(feats, feat_ind) +{ + _params.resize(n_params(), 0.0); + + get_parameters(prop); + + set_value(); + if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) + throw InvalidFeatureException(); + + set_test_value(); +} + +SixPowParamNode::SixPowParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop) : + SixPowNode({feat}, feat_ind) +{ + _params.resize(n_params(), 0.0); + + get_parameters(prop); + + set_value(); + if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) + throw InvalidFeatureException(); + + set_test_value(); +} + +SixPowParamNode::SixPowParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound) : + SixPowNode(feats, feat_ind) +{ + _params.resize(n_params(), 0.0); +} + +SixPowParamNode::SixPowParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound) : + SixPowNode({feat}, feat_ind) +{ + _params.resize(n_params(), 0.0); +} + +void SixPowParamNode::get_parameters(std::vector<double>& prop) +{ + nlopt_wrapper::feat_data d; + d._feat = this; + d._prop = prop.data(); + double minf; + + std::fill_n(_params.begin(), _params.size(), 1.0); + dcopy_(_params.size() / 2, nlopt_wrapper::_zeros.data(), 1, &_params[1], 2); + + nlopt::opt opt(nlopt::LN_SBPLX, _params.size()); + opt.set_min_objective(nlopt_wrapper::objective_reg, &d); + opt.set_maxeval(1000); + opt.set_xtol_rel(1e-2); + try + { + nlopt::result result = opt.optimize(_params, minf); + } + catch(std::exception &e) + { + std::fill_n(_params.begin(), _params.size(), 1.0); + dcopy_(_params.size() / 2, nlopt_wrapper::_zeros.data(), 1, &_params[1], 2); + } +} diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/six_pow/parameterized_sixth_power.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/six_pow/parameterized_sixth_power.hpp new file mode 100644 index 00000000..99e01e99 --- /dev/null +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/six_pow/parameterized_sixth_power.hpp @@ -0,0 +1,153 @@ +/** @file feature_creation/node/operator_nodes/allowed_operator_nodes/six_pow/parameterized_sixth_pow.hpp + * @brief Class describing the parameterized sixth power operator + * + * This class represents the parameterized unary operator -> (alpha * A + a)^6 + * + * @author Thomas A. R. Purcell (tpurcell) + * @bug No known bugs. + */ +#ifndef PARAM_SIX_POW_NODE +#define PARAM_SIX_POW_NODE + +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/six_pow/sixth_power.hpp> +#include <feature_creation/parameterization/NLOptWrapper.hpp> + +// DocString: cls_abs_node +/** + * @brief Node for the absolute value operator + * + */ +class SixPowParamNode: public SixPowNode +{ + using SixPowNode::set_value; + using SixPowNode::set_test_value; + using SixPowNode::domain; + using SixPowNode::expr; + + friend class boost::serialization::access; + + /** + * @brief Serialization function to send over MPI + * + * @param ar Archive representation of node + */ + template <typename Archive> + void serialize(Archive& ar, const unsigned int version) + { + ar & boost::serialization::base_object<SixPowNode>(*this); + ar & _params; + } + +protected: + std::vector<double> _params; //!< The parameters vector + +public: + /** + * @brief Base Constructor + * @details This is only used for serialization + */ + SixPowParamNode(); + + /** + * @brief Constructor + * @details Constructs the Node from node pointer of the feature to operate on + * + * @param feat_1 shared_ptr of the feature to operate on (A) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + * @param prop The property to fit to + */ + SixPowParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop); + + /** + * @brief Constructor + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + * @param prop The property to fit to + */ + SixPowParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop); + + /** + * @brief Constructor + * @details Constructs the Node from node pointer of the feature to operate on + * + * @param feat_1 shared_ptr of the feature to operate on (A) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + */ + SixPowParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound); + + /** + * @brief Constructor + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + */ + SixPowParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound); + + // DocString: six_pow_param_node_set_value + /** + * @brief Set the values of the training data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + */ + inline void set_value(int offset = -1){set_value(_params.data(), offset);} + + // DocString: six_pow_param_node_set_test_value + /** + * @brief Set the values of the test data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + */ + inline void set_test_value(int offset = -1){set_test_value(_params.data(), offset);} + + // DocString: six_pow_param_node_expr + /** + * @brief Get the expression for the overall feature (From root node down) + */ + inline std::string expr(){return expr(_params.data());} + + // DocString: six_pow_param_node_domain + /** + * @brief The domain for the feature (min/max values) + */ + inline Domain domain(){return domain(_params.data());} + + /** + * @brief The parameters used for introducing more non linearity in the operators + */ + inline std::vector<double> parameters(){return _params;} + + /** + * @brief Solve the non-linear optimization to set the parameters + * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * + * @param prop property to fit to get the parameters + */ + void get_parameters(std::vector<double>& prop); + + /** + * @brief Set the non-linear parameters + */ + inline void set_parameters(std::vector<double> params) + { + if(params.size() != n_params()) + throw std::logic_error("Wrong number of parameters passed to set_parameters."); + _params = params; + } +}; + +#endif \ No newline at end of file diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/six_pow/sixth_power.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/six_pow/sixth_power.cpp index 13c7c349..afef68b0 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/six_pow/sixth_power.cpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/six_pow/sixth_power.cpp @@ -29,6 +29,16 @@ SixPowNode::SixPowNode(node_ptr feat, int feat_ind, double l_bound, double u_bou set_test_value(); } +SixPowNode::SixPowNode(std::array<node_ptr, 1> feats, int feat_ind): + OperatorNode(feats, feat_ind) +{ + if((feats[0]->type() == NODE_TYPE::CBRT) || (feats[0]->type() == NODE_TYPE::SQRT) || (feats[0]->type() == NODE_TYPE::SQ) || (feats[0]->type() == NODE_TYPE::CB) || (feats[0]->type() == NODE_TYPE::INV)) + throw InvalidFeatureException(); + + set_value(); + set_test_value(); +} + void SixPowNode::update_add_sub_leaves(std::map<std::string, int>& add_sub_leaves, int pl_mn, int& expected_abs_tot) { std::string key = expr(); diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/six_pow/sixth_power.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/six_pow/sixth_power.hpp index e1138cf8..8ce2ac34 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/six_pow/sixth_power.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/six_pow/sixth_power.hpp @@ -61,6 +61,15 @@ public: */ SixPowNode(node_ptr feat, int feat_ind, double l_bound, double u_bound); + /** + * @brief Constructor without checking feature values + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + */ + SixPowNode(std::array<node_ptr, 1> feats, int feat_ind); + // DocString: six_pow_node_unit /** * @brief Get the unit of the feature (combine the units of _feats) @@ -71,7 +80,7 @@ public: /** * @brief Get the expression for the overall feature (From root node down) */ - inline std::string expr(){return "(" + std::to_string(_params[0]) + "*" + _feats[0]->expr() + " + " + std::to_string(_params[1]) + ")^6";} + inline std::string expr(){return "(" + _feats[0]->expr() + ")^6";} // DocString: six_pow_node_set_value /** @@ -81,11 +90,11 @@ public: */ inline void set_value(int offset = -1) { - if(_selected) - allowed_op_funcs::sixth_pow(_n_samp, _feats[0]->value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); - offset = (offset == -1) ? rung() : offset; - allowed_op_funcs::sixth_pow(_n_samp, _feats[0]->value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); + + if(_selected) + allowed_op_funcs::sixth_pow(_n_samp, _feats[0]->value_ptr(offset + 2), 1.0, 0.0, node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); + allowed_op_funcs::sixth_pow(_n_samp, _feats[0]->value_ptr(offset + 2), 1.0, 0.0, node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); } // DocString: six_pow_node_set_test_value @@ -97,7 +106,7 @@ public: inline void set_test_value(int offset = -1) { offset = (offset == -1) ? rung() : offset; - allowed_op_funcs::sixth_pow(_n_test_samp, _feats[0]->test_value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); + allowed_op_funcs::sixth_pow(_n_test_samp, _feats[0]->test_value_ptr(offset + 2), 1.0, 0.0, node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); } // DocString: six_pow_node_rung @@ -117,7 +126,7 @@ public: /** * @brief The domain for the feature (min/max values) */ - Domain domain(){return _feats[0]->domain().pow(6.0, _params[0], _params[1]);} + Domain domain(){return _feats[0]->domain().pow(6.0, 1.0, 0.0);} /** * @brief Get the string character representation of the node for the postfix expression @@ -146,39 +155,65 @@ public: #ifdef PARAMETERIZE /** - * @brief Constructor - * @details Constructs the Node from an array of features to operate on + * @brief The parameters used for introducing more non linearity in the operators + */ + virtual std::vector<double> parameters(){return {};} + + /** + * @brief Solve the non-linear optimization to set the parameters + * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature * - * @param feats Features to operate over (Edges of the graph) - * @param feat_ind Index of the new feature - * @param l_bound Minimum absolute value allowed for the feature. - * @param u_bound Maximum absolute value allowed for the feature. - * @param param_list The list of parameters to optimize using non-linear least squares - * @param prop The property to fit to + * @param prop property to fit to get the parameters */ - SixPowNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop); + virtual void get_parameters(std::vector<double>& prop){return;} + + /** + * @brief Set the non-linear parameters + */ + virtual void set_parameters(std::vector<double>){return;} /** - * @brief Constructor - * @details Constructs the Node from node pointer of the feature to operate on + * @brief Set the values of the training data for the feature inside of the value storage arrays * - * @param feat_1 shared_ptr of the feature to operate on (A) - * @param feat_ind Index of the new feature - * @param l_bound Minimum absolute value allowed for the feature. - * @param u_bound Maximum absolute value allowed for the feature. - * @param param_list The list of parameters to optimize using non-linear least squares - * @param prop The property to fit to + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values */ - SixPowNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop); + inline void set_value(const double* params, int offset = -1) + { + offset = (offset == -1) ? rung() : offset; + if(_selected) + allowed_op_funcs::sixth_pow(_n_samp, _feats[0]->value_ptr(params + 2, offset + 2), params[0], params[1], node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); + + allowed_op_funcs::sixth_pow(_n_samp, _feats[0]->value_ptr(params + 2, offset + 2), params[0], params[1], node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset, false)); + } /** - * @brief Solve the non-linear optimization to set the parameters - * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * @brief Set the values of the test data for the feature inside of the value storage arrays * - * @param prop property to fit to get the parameters - * @param param_list List describing the parameters to fit + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values + */ + inline void set_test_value(const double* params, int offset = -1) + { + offset = (offset == -1) ? rung() : offset; + allowed_op_funcs::sixth_pow(_n_test_samp, _feats[0]->test_value_ptr(params + 2, offset + 2), params[0], params[1], node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset, false)); + } + + /** + * @brief The domain for the feature (min/max values) + * + * @param params parameter values for non-linear operations + * @return the domain + */ + inline Domain domain(double* params){return _feats[0]->domain(params + 2).pow(6.0, params[0], params[1]);} + + /** + * @brief The expression of the feature + * + * @param params parameter values for non-linear operations + * @return feature expression */ - void get_parameters(std::vector<double>& prop, std::vector<std::string>& param_list); + inline std::string expr(double* params){return "(" + std::to_string(params[0]) + "*" + _feats[0]->expr(params + 2) + " + " + std::to_string(params[1]) + ")^6";} #endif }; diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sq/parameterize.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sq/parameterize.cpp deleted file mode 100644 index ceb996f9..00000000 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sq/parameterize.cpp +++ /dev/null @@ -1,105 +0,0 @@ -#include <feature_creation/node/operator_nodes/allowed_operator_nodes/sq/square.hpp> - -SqNode::SqNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop) : - OperatorNode(feats, feat_ind) -{ - if((feats[0]->type() == NODE_TYPE::SQRT) || (feats[0]->type() == NODE_TYPE::INV)) - throw InvalidFeatureException(); - - get_parameters(prop, param_list); - set_value(); - if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) - throw InvalidFeatureException(); - - set_test_value(); -} - -SqNode::SqNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop) : - OperatorNode({feat}, feat_ind) -{ - if((feat->type() == NODE_TYPE::SQRT) || (feat->type() == NODE_TYPE::INV)) - throw InvalidFeatureException(); - - get_parameters(prop, param_list); - set_value(); - if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) - throw InvalidFeatureException(); - - set_test_value(); -} - -void SqNode::get_parameters(std::vector<double>& prop, std::vector<std::string>& param_list) -{ - if(param_list.size() == 0) - return; - Problem problem; - double c = 0.0; - double* val = _feats[0]->value_ptr(rung() + 2); - if(param_list.size() > 3) - { - throw std::logic_error("Too many parameters passed to the constructor."); - } - else if(param_list.size() == 3) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<SqResidual_alpha_a_c, 1, 1, 1, 1>( - new SqResidual_alpha_a_c(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &_params[1], &c - ); - } - } - else if(param_list.size() == 2) - { - if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("alpha") == 0) || s.compare("a") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<SqResidual_alpha_a, 1, 1, 1>( - new SqResidual_alpha_a(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &_params[1] - ); - } - } - else if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("a") == 0) || s.compare("c") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<SqResidual_a_c, 1, 1, 1>( - new SqResidual_a_c(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[1], &c - ); - } - } - else - throw std::logic_error("Invalid parameter in the parameter list."); - } - else if(param_list.size() == 1) - { - if(std::any_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("a") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<SqResidual_a, 1, 1>( - new SqResidual_a(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[1] - ); - } - } - else - throw std::logic_error("Invalid parameter in the parameter list."); - } - parameterize(problem); -} diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sq/parameterized_square.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sq/parameterized_square.cpp new file mode 100644 index 00000000..00601cac --- /dev/null +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sq/parameterized_square.cpp @@ -0,0 +1,69 @@ +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/sq/parameterized_square.hpp> + +SqParamNode::SqParamNode() +{} + +SqParamNode::SqParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop) : + SqNode(feats, feat_ind) +{ + _params.resize(n_params(), 0.0); + + get_parameters(prop); + + set_value(); + if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) + throw InvalidFeatureException(); + + set_test_value(); +} + +SqParamNode::SqParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop) : + SqNode({feat}, feat_ind) +{ + _params.resize(n_params(), 0.0); + + get_parameters(prop); + + set_value(); + if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) + throw InvalidFeatureException(); + + set_test_value(); +} + +SqParamNode::SqParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound) : + SqNode(feats, feat_ind) +{ + _params.resize(n_params(), 0.0); +} + +SqParamNode::SqParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound) : + SqNode({feat}, feat_ind) +{ + _params.resize(n_params(), 0.0); +} + +void SqParamNode::get_parameters(std::vector<double>& prop) +{ + nlopt_wrapper::feat_data d; + d._feat = this; + d._prop = prop.data(); + double minf; + + std::fill_n(_params.begin(), _params.size(), 1.0); + dcopy_(_params.size() / 2, nlopt_wrapper::_zeros.data(), 1, &_params[1], 2); + + nlopt::opt opt(nlopt::LN_SBPLX, _params.size()); + opt.set_min_objective(nlopt_wrapper::objective_reg, &d); + opt.set_maxeval(1000); + opt.set_xtol_rel(1e-2); + try + { + nlopt::result result = opt.optimize(_params, minf); + } + catch(std::exception &e) + { + std::fill_n(_params.begin(), _params.size(), 1.0); + dcopy_(_params.size() / 2, nlopt_wrapper::_zeros.data(), 1, &_params[1], 2); + } +} diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sq/parameterized_square.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sq/parameterized_square.hpp new file mode 100644 index 00000000..4fcdfce8 --- /dev/null +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sq/parameterized_square.hpp @@ -0,0 +1,153 @@ +/** @file feature_creation/node/operator_nodes/allowed_operator_nodes/sq/parameterized_square.hpp + * @brief Class describing the parameterized square operator + * + * This class represents the parameterized unary operator -> (alpha * A + a)^2 + * + * @author Thomas A. R. Purcell (tpurcell) + * @bug No known bugs. + */ +#ifndef PARAM_SQ_NODE +#define PARAM_SQ_NODE + +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/sq/square.hpp> +#include <feature_creation/parameterization/NLOptWrapper.hpp> + +// DocString: cls_abs_node +/** + * @brief Node for the absolute value operator + * + */ +class SqParamNode: public SqNode +{ + using SqNode::set_value; + using SqNode::set_test_value; + using SqNode::domain; + using SqNode::expr; + + friend class boost::serialization::access; + + /** + * @brief Serialization function to send over MPI + * + * @param ar Archive representation of node + */ + template <typename Archive> + void serialize(Archive& ar, const unsigned int version) + { + ar & boost::serialization::base_object<SqNode>(*this); + ar & _params; + } + +protected: + std::vector<double> _params; //!< The parameters vector + +public: + /** + * @brief Base Constructor + * @details This is only used for serialization + */ + SqParamNode(); + + /** + * @brief Constructor + * @details Constructs the Node from node pointer of the feature to operate on + * + * @param feat_1 shared_ptr of the feature to operate on (A) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + * @param prop The property to fit to + */ + SqParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop); + + /** + * @brief Constructor + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + * @param prop The property to fit to + */ + SqParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop); + + /** + * @brief Constructor + * @details Constructs the Node from node pointer of the feature to operate on + * + * @param feat_1 shared_ptr of the feature to operate on (A) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + */ + SqParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound); + + /** + * @brief Constructor + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + */ + SqParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound); + + // DocString: sq_param_node_set_value + /** + * @brief Set the values of the training data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + */ + inline void set_value(int offset = -1){set_value(_params.data(), offset);} + + // DocString: sq_param_node_set_test_value + /** + * @brief Set the values of the test data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + */ + inline void set_test_value(int offset = -1){set_test_value(_params.data(), offset);} + + // DocString: sq_param_node_expr + /** + * @brief Get the expression for the overall feature (From root node down) + */ + inline std::string expr(){return expr(_params.data());} + + // DocString: sq_param_node_domain + /** + * @brief The domain for the feature (min/max values) + */ + inline Domain domain(){return domain(_params.data());} + + /** + * @brief The parameters used for introducing more non linearity in the operators + */ + inline std::vector<double> parameters(){return _params;} + + /** + * @brief Solve the non-linear optimization to set the parameters + * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * + * @param prop property to fit to get the parameters + */ + void get_parameters(std::vector<double>& prop); + + /** + * @brief Set the non-linear parameters + */ + inline void set_parameters(std::vector<double> params) + { + if(params.size() != n_params()) + throw std::logic_error("Wrong number of parameters passed to set_parameters."); + _params = params; + } +}; + +#endif \ No newline at end of file diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sq/square.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sq/square.cpp index 8dd19b2e..5d4f4435 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sq/square.cpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sq/square.cpp @@ -29,6 +29,16 @@ SqNode::SqNode(node_ptr feat, int feat_ind, double l_bound, double u_bound): set_test_value(); } +SqNode::SqNode(std::array<node_ptr, 1> feats, int feat_ind): + OperatorNode(feats, feat_ind) +{ + if((feats[0]->type() == NODE_TYPE::SQRT) || (feats[0]->type() == NODE_TYPE::INV)) + throw InvalidFeatureException(); + + set_value(); + set_test_value(); +} + void SqNode::update_add_sub_leaves(std::map<std::string, int>& add_sub_leaves, int pl_mn, int& expected_abs_tot) { std::string key = expr(); diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sq/square.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sq/square.hpp index 2e880468..23d874b6 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sq/square.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sq/square.hpp @@ -60,6 +60,15 @@ public: */ SqNode(node_ptr feat, int feat_ind, double l_bound, double u_bound); + /** + * @brief Constructor without checking feature values + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + */ + SqNode(std::array<node_ptr, 1> feats, int feat_ind); + // DocString: sq_node_unit /** * @brief Get the unit of the feature (combine the units of _feats) @@ -70,7 +79,7 @@ public: /** * @brief Get the expression for the overall feature (From root node down) */ - inline std::string expr(){return "(" + std::to_string(_params[0]) + "*" + _feats[0]->expr() + " + " + std::to_string(_params[1]) + ")^2";} + inline std::string expr(){return "(" + _feats[0]->expr() + ")^2";} // DocString: sq_node_set_value /** @@ -80,11 +89,11 @@ public: */ inline void set_value(int offset = -1) { - if(_selected) - allowed_op_funcs::sq(_n_samp, _feats[0]->value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); - offset = (offset == -1) ? rung() : offset; - allowed_op_funcs::sq(_n_samp, _feats[0]->value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); + + if(_selected) + allowed_op_funcs::sq(_n_samp, _feats[0]->value_ptr(offset + 2), 1.0, 0.0, node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); + allowed_op_funcs::sq(_n_samp, _feats[0]->value_ptr(offset + 2), 1.0, 0.0, node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); } // DocString: sq_node_set_test_value @@ -96,7 +105,7 @@ public: inline void set_test_value(int offset = -1) { offset = (offset == -1) ? rung() : offset; - allowed_op_funcs::sq(_n_test_samp, _feats[0]->test_value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); + allowed_op_funcs::sq(_n_test_samp, _feats[0]->test_value_ptr(offset + 2), 1.0, 0.0, node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); } // DocString: sq_node_rung @@ -116,7 +125,7 @@ public: /** * @brief The domain for the feature (min/max values) */ - Domain domain(){return _feats[0]->domain().pow(2.0, _params[0], _params[1]);} + Domain domain(){return _feats[0]->domain().pow(2.0, 1.0, 0.0);} /** * @brief Get the string character representation of the node for the postfix expression @@ -145,39 +154,65 @@ public: #ifdef PARAMETERIZE /** - * @brief Constructor - * @details Constructs the Node from an array of features to operate on + * @brief The parameters used for introducing more non linearity in the operators + */ + virtual std::vector<double> parameters(){return {};} + + /** + * @brief Solve the non-linear optimization to set the parameters + * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature * - * @param feats Features to operate over (Edges of the graph) - * @param feat_ind Index of the new feature - * @param l_bound Minimum absolute value allowed for the feature. - * @param u_bound Maximum absolute value allowed for the feature. - * @param param_list The list of parameters to optimize using non-linear least squares - * @param prop The property to fit to + * @param prop property to fit to get the parameters */ - SqNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop); + virtual void get_parameters(std::vector<double>& prop){return;} + + /** + * @brief Set the non-linear parameters + */ + virtual void set_parameters(std::vector<double>){return;} /** - * @brief Constructor - * @details Constructs the Node from node pointer of the feature to operate on + * @brief Set the values of the training data for the feature inside of the value storage arrays * - * @param feat_1 shared_ptr of the feature to operate on (A) - * @param feat_ind Index of the new feature - * @param l_bound Minimum absolute value allowed for the feature. - * @param u_bound Maximum absolute value allowed for the feature. - * @param param_list The list of parameters to optimize using non-linear least squares - * @param prop The property to fit to + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values */ - SqNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop); + inline void set_value(const double* params, int offset = -1) + { + offset = (offset == -1) ? rung() : offset; + if(_selected) + allowed_op_funcs::sq(_n_samp, _feats[0]->value_ptr(params + 2, offset + 2), params[0], params[1], node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); + + allowed_op_funcs::sq(_n_samp, _feats[0]->value_ptr(params + 2, offset + 2), params[0], params[1], node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset, false)); + } /** - * @brief Solve the non-linear optimization to set the parameters - * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * @brief Set the values of the test data for the feature inside of the value storage arrays * - * @param prop property to fit to get the parameters - * @param param_list List describing the parameters to fit + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values + */ + inline void set_test_value(const double* params, int offset = -1) + { + offset = (offset == -1) ? rung() : offset; + allowed_op_funcs::sq(_n_test_samp, _feats[0]->test_value_ptr(params + 2, offset + 2), params[0], params[1], node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset, false)); + } + + /** + * @brief The domain for the feature (min/max values) + * + * @param params parameter values for non-linear operations + * @return the domain + */ + inline Domain domain(double* params){return _feats[0]->domain(params + 2).pow(2.0, params[0], params[1]);} + + /** + * @brief The expression of the feature + * + * @param params parameter values for non-linear operations + * @return feature expression */ - void get_parameters(std::vector<double>& prop, std::vector<std::string>& param_list); + inline std::string expr(double* params){return "(" + std::to_string(params[0]) + "*" + _feats[0]->expr(params + 2) + " + " + std::to_string(params[1]) + ")^2";} #endif }; diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sqrt/parameterize.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sqrt/parameterize.cpp deleted file mode 100644 index b38c5abf..00000000 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sqrt/parameterize.cpp +++ /dev/null @@ -1,119 +0,0 @@ -#include <feature_creation/node/operator_nodes/allowed_operator_nodes/sqrt/square_root.hpp> - -SqrtNode::SqrtNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop) : - OperatorNode(feats, feat_ind) -{ - if((feats[0]->type() == NODE_TYPE::SQ) || (feats[0]->type() == NODE_TYPE::CB) || (feats[0]->type() == NODE_TYPE::SIX_POW) || (feats[0]->type() == NODE_TYPE::CBRT) || (feats[0]->type() == NODE_TYPE::INV)) - throw InvalidFeatureException(); - - if((_feats[0]->domain() < 0.0)) - throw InvalidFeatureException(); - - get_parameters(prop, param_list); - - if(_params[0] * _feats[0]->domain() + _params[1] < 0.0) - throw InvalidFeatureException(); - - set_value(); - if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) - throw InvalidFeatureException(); - - set_test_value(); -} - -SqrtNode::SqrtNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop) : - OperatorNode({feat}, feat_ind) -{ - if((feat->type() == NODE_TYPE::SQ) || (feat->type() == NODE_TYPE::CB) || (feat->type() == NODE_TYPE::SIX_POW) || (feat->type() == NODE_TYPE::CBRT) || (feat->type() == NODE_TYPE::INV)) - throw InvalidFeatureException(); - - if((_feats[0]->domain() < 0.0)) - throw InvalidFeatureException(); - - get_parameters(prop, param_list); - - if(_params[0] * _feats[0]->domain() + _params[1] < 0.0) - throw InvalidFeatureException(); - - set_value(); - if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) - throw InvalidFeatureException(); - - set_test_value(); -} - -void SqrtNode::get_parameters(std::vector<double>& prop, std::vector<std::string>& param_list) -{ - if(param_list.size() == 0) - return; - Problem problem; - double c = 0.0; - double* val = _feats[0]->value_ptr(rung() + 2); - if(param_list.size() > 3) - { - throw std::logic_error("Too many parameters passed to the constructor."); - } - else if(param_list.size() == 3) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<SqrtResidual_alpha_a_c, 1, 1, 1, 1>( - new SqrtResidual_alpha_a_c(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &_params[1], &c - ); - } - } - else if(param_list.size() == 2) - { - if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("alpha") == 0) || s.compare("a") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<SqrtResidual_alpha_a, 1, 1, 1>( - new SqrtResidual_alpha_a(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &_params[1] - ); - } - } - else if(std::all_of(param_list.begin(), param_list.end(), [](std::string s){return (s.compare("a") == 0) || s.compare("c") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<SqrtResidual_a_c, 1, 1, 1>( - new SqrtResidual_a_c(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[1], &c - ); - } - } - else - throw std::logic_error("Invalid parameter in the parameter list."); - } - else if(param_list.size() == 1) - { - if(std::any_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("a") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<SqrtResidual_a, 1, 1>( - new SqrtResidual_a(val[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[1] - ); - } - } - else - throw std::logic_error("Invalid parameter in the parameter list."); - } - parameterize(problem); -} diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sqrt/parameterized_square_root.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sqrt/parameterized_square_root.cpp new file mode 100644 index 00000000..c15266e9 --- /dev/null +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sqrt/parameterized_square_root.cpp @@ -0,0 +1,75 @@ +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/sqrt/parameterized_square_root.hpp> + +SqrtParamNode::SqrtParamNode() +{} + +SqrtParamNode::SqrtParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop) : + SqrtNode(feats, feat_ind) +{ + _params.resize(n_params(), 0.0); + + get_parameters(prop); + + if(_params[0] * _feats[0]->domain() + _params[1] < 0.0) + throw InvalidFeatureException(); + + set_value(); + if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) + throw InvalidFeatureException(); + + set_test_value(); +} + +SqrtParamNode::SqrtParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop) : + SqrtNode({feat}, feat_ind) +{ + _params.resize(n_params(), 0.0); + + get_parameters(prop); + + if(_params[0] * _feats[0]->domain() + _params[1] < 0.0) + throw InvalidFeatureException(); + + set_value(); + if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) + throw InvalidFeatureException(); + + set_test_value(); +} + +SqrtParamNode::SqrtParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound) : + SqrtNode(feats, feat_ind) +{ + _params.resize(n_params(), 0.0); +} + +SqrtParamNode::SqrtParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound) : + SqrtNode({feat}, feat_ind) +{ + _params.resize(n_params(), 0.0); +} + +void SqrtParamNode::get_parameters(std::vector<double>& prop) +{ + nlopt_wrapper::feat_data d; + d._feat = this; + d._prop = prop.data(); + double minf; + + std::fill_n(_params.begin(), _params.size(), 1.0); + dcopy_(_params.size() / 2, nlopt_wrapper::_zeros.data(), 1, &_params[1], 2); + + nlopt::opt opt(nlopt::LN_SBPLX, _params.size()); + opt.set_min_objective(nlopt_wrapper::objective_reg, &d); + opt.set_maxeval(1000); + opt.set_xtol_rel(1e-2); + try + { + nlopt::result result = opt.optimize(_params, minf); + } + catch(std::exception &e) + { + std::fill_n(_params.begin(), _params.size(), 1.0); + dcopy_(_params.size() / 2, nlopt_wrapper::_zeros.data(), 1, &_params[1], 2); + } +} diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sqrt/parameterized_square_root.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sqrt/parameterized_square_root.hpp new file mode 100644 index 00000000..53db8d8c --- /dev/null +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sqrt/parameterized_square_root.hpp @@ -0,0 +1,153 @@ +/** @file feature_creation/node/operator_nodes/allowed_operator_nodes/sqrt/parameterized_square_root.hpp + * @brief Class describing the parameterized square root operator + * + * This class represents the parameterized unary operator -> sqrt(alpha * A + a) + * + * @author Thomas A. R. Purcell (tpurcell) + * @bug No known bugs. + */ +#ifndef PARAM_SQRT_NODE +#define PARAM_SQRT_NODE + +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/sqrt/square_root.hpp> +#include <feature_creation/parameterization/NLOptWrapper.hpp> + +// DocString: cls_abs_node +/** + * @brief Node for the absolute value operator + * + */ +class SqrtParamNode: public SqrtNode +{ + using SqrtNode::set_value; + using SqrtNode::set_test_value; + using SqrtNode::domain; + using SqrtNode::expr; + + friend class boost::serialization::access; + + /** + * @brief Serialization function to send over MPI + * + * @param ar Archive representation of node + */ + template <typename Archive> + void serialize(Archive& ar, const unsigned int version) + { + ar & boost::serialization::base_object<SqrtNode>(*this); + ar & _params; + } + +protected: + std::vector<double> _params; //!< The parameters vector + +public: + /** + * @brief Base Constructor + * @details This is only used for serialization + */ + SqrtParamNode(); + + /** + * @brief Constructor + * @details Constructs the Node from node pointer of the feature to operate on + * + * @param feat_1 shared_ptr of the feature to operate on (A) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + * @param prop The property to fit to + */ + SqrtParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop); + + /** + * @brief Constructor + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + * @param prop The property to fit to + */ + SqrtParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop); + + /** + * @brief Constructor + * @details Constructs the Node from node pointer of the feature to operate on + * + * @param feat_1 shared_ptr of the feature to operate on (A) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + */ + SqrtParamNode(node_ptr feat, int feat_ind, double l_bound, double u_bound); + + /** + * @brief Constructor + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + */ + SqrtParamNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound); + + // DocString: sqrt_param_node_set_value + /** + * @brief Set the values of the training data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + */ + inline void set_value(int offset = -1){set_value(_params.data(), offset);} + + // DocString: sqrt_param_node_set_test_value + /** + * @brief Set the values of the test data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + */ + inline void set_test_value(int offset = -1){set_test_value(_params.data(), offset);} + + // DocString: sqrt_param_node_expr + /** + * @brief Get the expression for the overall feature (From root node down) + */ + inline std::string expr(){return expr(_params.data());} + + // DocString: sqrt_param_node_domain + /** + * @brief The domain for the feature (min/max values) + */ + inline Domain domain(){return domain(_params.data());} + + /** + * @brief The parameters used for introducing more non linearity in the operators + */ + inline std::vector<double> parameters(){return _params;} + + /** + * @brief Solve the non-linear optimization to set the parameters + * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * + * @param prop property to fit to get the parameters + */ + void get_parameters(std::vector<double>& prop); + + /** + * @brief Set the non-linear parameters + */ + inline void set_parameters(std::vector<double> params) + { + if(params.size() != n_params()) + throw std::logic_error("Wrong number of parameters passed to set_parameters."); + _params = params; + } +}; + +#endif \ No newline at end of file diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sqrt/square_root.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sqrt/square_root.cpp index efadeae8..6a4ee9f4 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sqrt/square_root.cpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sqrt/square_root.cpp @@ -35,6 +35,16 @@ SqrtNode::SqrtNode(node_ptr feat, int feat_ind, double l_bound, double u_bound): set_test_value(); } +SqrtNode::SqrtNode(std::array<node_ptr, 1> feats, int feat_ind): + OperatorNode(feats, feat_ind) +{ + if((feats[0]->type() == NODE_TYPE::SQ) || (feats[0]->type() == NODE_TYPE::CB) || (feats[0]->type() == NODE_TYPE::SIX_POW) || (feats[0]->type() == NODE_TYPE::CBRT) || (feats[0]->type() == NODE_TYPE::INV)) + throw InvalidFeatureException(); + + set_value(); + set_test_value(); +} + void SqrtNode::update_add_sub_leaves(std::map<std::string, int>& add_sub_leaves, int pl_mn, int& expected_abs_tot) { std::string key = expr(); diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sqrt/square_root.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sqrt/square_root.hpp index 00a5ea48..035d703f 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sqrt/square_root.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sqrt/square_root.hpp @@ -61,6 +61,15 @@ public: */ SqrtNode(node_ptr feat, int feat_ind, double l_bound, double u_bound); + /** + * @brief Constructor without checking feature values + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + */ + SqrtNode(std::array<node_ptr, 1> feats, int feat_ind); + // DocString: sqrt_node_unit /** * @brief Get the unit of the feature (combine the units of _feats) @@ -71,7 +80,7 @@ public: /** * @brief Get the expression for the overall feature (From root node down) */ - inline std::string expr(){return "sqrt(" + std::to_string(_params[0]) + "*" + _feats[0]->expr() + " + " + std::to_string(_params[1]) + ")";} + inline std::string expr(){return "sqrt(" + _feats[0]->expr() + ")";} // DocString: sqrt_node_set_value /** @@ -81,11 +90,11 @@ public: */ inline void set_value(int offset = -1) { - if(_selected) - allowed_op_funcs::sqrt(_n_samp, _feats[0]->value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); - offset = (offset == -1) ? rung() : offset; - allowed_op_funcs::sqrt(_n_samp, _feats[0]->value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); + + if(_selected) + allowed_op_funcs::sqrt(_n_samp, _feats[0]->value_ptr(offset + 2), 1.0, 0.0, node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); + allowed_op_funcs::sqrt(_n_samp, _feats[0]->value_ptr(offset + 2), 1.0, 0.0, node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); } // DocString: sqrt_node_set_test_value @@ -97,7 +106,7 @@ public: inline void set_test_value(int offset = -1) { offset = (offset == -1) ? rung() : offset; - allowed_op_funcs::sqrt(_n_test_samp, _feats[0]->test_value_ptr(offset + 2), _params[0], _params[1], node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); + allowed_op_funcs::sqrt(_n_test_samp, _feats[0]->test_value_ptr(offset + 2), 1.0, 0.0, node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); } // DocString: sqrt_node_rung @@ -117,7 +126,7 @@ public: /** * @brief The domain for the feature (min/max values) */ - Domain domain(){return _feats[0]->domain().pow(0.5, _params[0], _params[1]);} + Domain domain(){return _feats[0]->domain().pow(0.5, 1.0, 0.0);} /** * @brief Get the string character representation of the node for the postfix expression @@ -146,39 +155,65 @@ public: #ifdef PARAMETERIZE /** - * @brief Constructor - * @details Constructs the Node from an array of features to operate on + * @brief The parameters used for introducing more non linearity in the operators + */ + virtual std::vector<double> parameters(){return {};} + + /** + * @brief Solve the non-linear optimization to set the parameters + * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature * - * @param feats Features to operate over (Edges of the graph) - * @param feat_ind Index of the new feature - * @param l_bound Minimum absolute value allowed for the feature. - * @param u_bound Maximum absolute value allowed for the feature. - * @param param_list The list of parameters to optimize using non-linear least squares - * @param prop The property to fit to + * @param prop property to fit to get the parameters */ - SqrtNode(std::array<node_ptr, 1> feats, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop); + virtual void get_parameters(std::vector<double>& prop){return;} + + /** + * @brief Set the non-linear parameters + */ + virtual void set_parameters(std::vector<double>){return;} /** - * @brief Constructor - * @details Constructs the Node from node pointer of the feature to operate on + * @brief Set the values of the training data for the feature inside of the value storage arrays * - * @param feat_1 shared_ptr of the feature to operate on (A) - * @param feat_ind Index of the new feature - * @param l_bound Minimum absolute value allowed for the feature. - * @param u_bound Maximum absolute value allowed for the feature. - * @param param_list The list of parameters to optimize using non-linear least squares - * @param prop The property to fit to + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values */ - SqrtNode(node_ptr feat, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop); + inline void set_value(const double* params, int offset = -1) + { + offset = (offset == -1) ? rung() : offset; + if(_selected) + allowed_op_funcs::sqrt(_n_samp, _feats[0]->value_ptr(params + 2, offset + 2), params[0], params[1], node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); + + allowed_op_funcs::sqrt(_n_samp, _feats[0]->value_ptr(params + 2, offset + 2), params[0], params[1], node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset, false)); + } /** - * @brief Solve the non-linear optimization to set the parameters - * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * @brief Set the values of the test data for the feature inside of the value storage arrays * - * @param prop property to fit to get the parameters - * @param param_list List describing the parameters to fit + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values + */ + inline void set_test_value(const double* params, int offset = -1) + { + offset = (offset == -1) ? rung() : offset; + allowed_op_funcs::sqrt(_n_test_samp, _feats[0]->test_value_ptr(params + 2, offset + 2), params[0], params[1], node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset, false)); + } + + /** + * @brief The domain for the feature (min/max values) + * + * @param params parameter values for non-linear operations + * @return the domain + */ + inline Domain domain(double* params){return _feats[0]->domain(params + 2).pow(1.0 / 2.0, params[0], params[1]);} + + /** + * @brief The expression of the feature + * + * @param params parameter values for non-linear operations + * @return feature expression */ - void get_parameters(std::vector<double>& prop, std::vector<std::string>& param_list); + inline std::string expr(double* params){return "sqrt(" + std::to_string(params[0]) + "*" + _feats[0]->expr(params + 2) + " + " + std::to_string(params[1]) + ")";} #endif }; diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sub/parameterize.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sub/parameterize.cpp deleted file mode 100644 index 80bedaa3..00000000 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sub/parameterize.cpp +++ /dev/null @@ -1,105 +0,0 @@ -#include <feature_creation/node/operator_nodes/allowed_operator_nodes/sub/subtract.hpp> - -SubNode::SubNode(std::array<node_ptr, 2> feats, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop) : - OperatorNode(feats, feat_ind) -{ - check_feats(); - - get_parameters(prop, param_list); - set_value(); - if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) - throw InvalidFeatureException(); - - set_test_value(); -} - -SubNode::SubNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop) : - OperatorNode({feat_1, feat_2}, feat_ind) -{ - check_feats(); - - get_parameters(prop, param_list); - set_value(); - if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) - throw InvalidFeatureException(); - - set_test_value(); -} - -void SubNode::get_parameters(std::vector<double>& prop, std::vector<std::string>& param_list) -{ - if(param_list.size() == 0) - return; - Problem problem; - double b = 0.0, c = 0.0; - double* val_1 = _feats[0]->value_ptr(rung() + 2); - double* val_2 = _feats[1]->value_ptr(rung() + 1); - - if(param_list.size() > 3) - { - throw std::logic_error("Too many parameters passed to the constructor."); - } - else if(param_list.size() == 3) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<SubResidual_alpha_b_c, 1, 1, 1, 1>( - new SubResidual_alpha_b_c(val_1[ss], val_2[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &b, &c - ); - } - } - else if(param_list.size() == 2) - { - if(std::none_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("c") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<SubResidual_alpha_b, 1, 1, 1>( - new SubResidual_alpha_b(val_1[ss], val_2[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &b - ); - } - } - else if(std::none_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("b") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<SubResidual_alpha_c, 1, 1, 1>( - new SubResidual_alpha_c(val_1[ss], val_2[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0], &c - ); - } - } - else - throw std::logic_error("Invalid parameter in the parameter list."); - } - else if(param_list.size() == 1) - { - if(std::any_of(param_list.begin(), param_list.end(), [](std::string s){return s.compare("alpha") == 0;})) - { - for (int ss = 0; ss < _n_samp; ++ss) - { - problem.AddResidualBlock( - new AutoDiffCostFunction<SubResidual_alpha, 1, 1>( - new SubResidual_alpha(val_1[ss], val_2[ss], prop[ss]) - ), - new CauchyLoss(0.5), - &_params[0] - ); - } - } - else - throw std::logic_error("Invalid parameter in the parameter list."); - } - parameterize(problem); -} diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sub/parameterized_subtract.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sub/parameterized_subtract.cpp new file mode 100644 index 00000000..3b2f50fc --- /dev/null +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sub/parameterized_subtract.cpp @@ -0,0 +1,67 @@ +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/sub/parameterized_subtract.hpp> + +SubParamNode::SubParamNode() +{} + +SubParamNode::SubParamNode(std::array<node_ptr, 2> feats, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop) : + SubNode(feats, feat_ind) +{ + _params.resize(n_params(), 0.0); + + get_parameters(prop); + set_value(); + if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) + throw InvalidFeatureException(); + + set_test_value(); +} + +SubParamNode::SubParamNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop) : + SubNode({feat_1, feat_2}, feat_ind) +{ + _params.resize(n_params(), 0.0); + + get_parameters(prop); + set_value(); + if(is_nan() || is_const() || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) > u_bound) || (util_funcs::max_abs_val<double>(value_ptr(), _n_samp) < l_bound)) + throw InvalidFeatureException(); + + set_test_value(); +} + +SubParamNode::SubParamNode(std::array<node_ptr, 2> feats, int feat_ind, double l_bound, double u_bound) : + SubNode(feats, feat_ind) +{ + _params.resize(n_params(), 0.0); +} + +SubParamNode::SubParamNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound) : + SubNode({feat_1, feat_2}, feat_ind) +{ + _params.resize(n_params(), 0.0); +} + +void SubParamNode::get_parameters(std::vector<double>& prop) +{ + nlopt_wrapper::feat_data d; + d._feat = this; + d._prop = prop.data(); + double minf; + + std::fill_n(_params.begin(), _params.size(), 1.0); + dcopy_(_params.size() / 2, nlopt_wrapper::_zeros.data(), 1, &_params[1], 2); + + nlopt::opt opt(nlopt::LN_SBPLX, _params.size()); + opt.set_min_objective(nlopt_wrapper::objective_reg, &d); + opt.set_maxeval(1000); + opt.set_xtol_rel(1e-2); + try + { + nlopt::result result = opt.optimize(_params, minf); + } + catch(std::exception &e) + { + std::fill_n(_params.begin(), _params.size(), 1.0); + dcopy_(_params.size() / 2, nlopt_wrapper::_zeros.data(), 1, &_params[1], 2); + } +} diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sub/parameterized_subtract.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sub/parameterized_subtract.hpp new file mode 100644 index 00000000..7de44c42 --- /dev/null +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sub/parameterized_subtract.hpp @@ -0,0 +1,151 @@ +/** @file feature_creation/node/operator_nodes/allowed_operator_nodes/sub/parameterized_subtract.hpp + * @brief Class describing the parameterized addition operator + * + * This class represents the parameterized unary operator -> A - (alpha * B + a) + * + * @author Thomas A. R. Purcell (tpurcell) + * @bug No known bugs. + */ +#ifndef PARAM_SUB_NODE +#define PARAM_SUB_NODE + +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/sub/subtract.hpp> +#include <feature_creation/parameterization/NLOptWrapper.hpp> + +// DocString: cls_param_add_node +/** + * @brief Node for the absolute value operator + * + */ +class SubParamNode: public SubNode +{ + using SubNode::set_value; + using SubNode::set_test_value; + using SubNode::domain; + using SubNode::expr; + + friend class boost::serialization::access; + + /** + * @brief Serialization function to send over MPI + * + * @param ar Archive representation of node + */ + template <typename Archive> + void serialize(Archive& ar, const unsigned int version) + { + ar & boost::serialization::base_object<SubNode>(*this); + ar & _params; + } +protected: + std::vector<double> _params; +public: + /** + * @brief Base Constructor + * @details This is only used for serialization + */ + SubParamNode(); + + /** + * @brief Constructor + * @details Constructs the Node from node pointer of the feature to operate on + * + * @param feat_1 shared_ptr of the feature to operate on (A) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + * @param prop The property to fit to + */ + SubParamNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop); + + /** + * @brief Constructor + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + * @param prop The property to fit to + */ + SubParamNode(std::array<node_ptr, 2> feats, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop); + + /** + * @brief Constructor + * @details Constructs the Node from node pointer of the feature to operate on + * + * @param feat_1 shared_ptr of the feature to operate on (A) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + */ + SubParamNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound); + + /** + * @brief Constructor + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + * @param l_bound Minimum absolute value allowed for the feature. + * @param u_bound Maximum absolute value allowed for the feature. + * @param param_list The list of parameters to optimize using non-linear least squares + */ + SubParamNode(std::array<node_ptr, 2> feats, int feat_ind, double l_bound, double u_bound); + + // DocString: sub_param_node_set_value + /** + * @brief Set the values of the training data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + */ + inline void set_value(int offset = -1){set_value(_params.data(), offset);} + + // DocString: sub_param_node_set_test_value + /** + * @brief Set the values of the test data for the feature inside of the value storage arrays + * + * @param offset(int) Key to determine which part of the temporary storage array to look into + */ + inline void set_test_value(int offset = -1){set_test_value(_params.data(), offset);} + + // DocString: sub_param_node_expr + /** + * @brief Get the expression for the overall feature (From root node down) + */ + inline std::string expr(){return expr(_params.data());} + + // DocString: sub_param_node_domain + /** + * @brief The domain for the feature (min/max values) + */ + inline Domain domain(){return domain(_params.data());} + + /** + * @brief The parameters used for introducing more non linearity in the operators + */ + inline std::vector<double> parameters(){return _params;} + + /** + * @brief Solve the non-linear optimization to set the parameters + * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * + * @param prop property to fit to get the parameters + */ + void get_parameters(std::vector<double>& prop); + + /** + * @brief Set the non-linear parameters + */ + inline void set_parameters(std::vector<double> params) + { + if(params.size() != n_params()) + throw std::logic_error("Wrong number of parameters passed to set_parameters."); + _params = params; + } +}; + +#endif \ No newline at end of file diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sub/subtract.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sub/subtract.cpp index 377acd7b..3a8a6738 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sub/subtract.cpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sub/subtract.cpp @@ -27,6 +27,15 @@ SubNode::SubNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, set_test_value(); } +SubNode::SubNode(std::array<node_ptr, 2> feats, int feat_ind): + OperatorNode(feats, feat_ind) +{ + check_feats(); + + set_value(); + set_test_value(); +} + void SubNode::check_feats() { if(_feats[0]->unit() != _feats[1]->unit()) diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sub/subtract.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sub/subtract.hpp index 2951f79c..15e57db5 100644 --- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sub/subtract.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sub/subtract.hpp @@ -62,6 +62,15 @@ public: */ SubNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound); + /** + * @brief Constructor without checking feature values + * @details Constructs the Node from an array of features to operate on + * + * @param feats Features to operate over (Edges of the graph) + * @param feat_ind Index of the new feature + */ + SubNode(std::array<node_ptr, 2> feats, int feat_ind); + // DocString: sub_node_unit /** * @brief Get the unit of the feature (combine the units of _feats) @@ -72,7 +81,7 @@ public: /** * @brief Get the expression for the overall feature (From root node down) */ - inline std::string expr(){return "[(" + _feats[0]->expr() + ") - (" + std::to_string(_params[0]) + "*" + _feats[1]->expr() + ")]";} + inline std::string expr(){return "[(" + _feats[0]->expr() + ") - (" + _feats[1]->expr() + ")]";} // DocString: sub_node_set_value /** @@ -82,11 +91,11 @@ public: */ inline void set_value(int offset = -1) { - if(_selected) - allowed_op_funcs::sub(_n_samp, _feats[0]->value_ptr(offset + 2), _feats[1]->value_ptr(offset + 1), _params[0], _params[1], node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); - offset = (offset == -1) ? rung() : offset; - allowed_op_funcs::sub(_n_samp, _feats[0]->value_ptr(offset + 2), _feats[1]->value_ptr(offset + 1), _params[0], _params[1], node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); + + if(_selected) + allowed_op_funcs::sub(_n_samp, _feats[0]->value_ptr(offset + 2), _feats[1]->value_ptr(offset + 1), 1.0, 0.0, node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); + allowed_op_funcs::sub(_n_samp, _feats[0]->value_ptr(offset + 2), _feats[1]->value_ptr(offset + 1), 1.0, 0.0, node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); } // DocString: sub_node_set_test_value @@ -98,7 +107,7 @@ public: inline void set_test_value(int offset = -1) { offset = (offset == -1) ? rung() : offset; - allowed_op_funcs::sub(_n_test_samp, _feats[0]->test_value_ptr(offset + 2), _feats[1]->test_value_ptr(offset + 1), _params[0], _params[1], node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); + allowed_op_funcs::sub(_n_test_samp, _feats[0]->test_value_ptr(offset + 2), _feats[1]->test_value_ptr(offset + 1), 1.0, 0.0, node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); } // DocString: sub_node_rung @@ -118,7 +127,7 @@ public: /** * @brief The domain for the feature (min/max values) */ - Domain domain(){return _feats[0]->domain().sub(_feats[1]->domain(), _params[0], _params[1]);} + Domain domain(){return _feats[0]->domain().sub(_feats[1]->domain(), 1.0, 0.0);} /** * @brief Get the string character representation of the node for the postfix expression @@ -153,39 +162,65 @@ public: #ifdef PARAMETERIZE /** - * @brief Constructor - * @details Constructs the Node from an array of features to operate on + * @brief The parameters used for introducing more non linearity in the operators + */ + virtual std::vector<double> parameters(){return {};} + + /** + * @brief Solve the non-linear optimization to set the parameters + * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature * - * @param feats Features to operate over (Edges of the graph) - * @param feat_ind Index of the new feature - * @param l_bound Minimum absolute value allowed for the feature. - * @param u_bound Maximum absolute value allowed for the feature. - * @param param_list The list of parameters to optimize using non-linear least squares - * @param prop The property to fit to + * @param prop property to fit to get the parameters */ - SubNode(std::array<node_ptr, 2> feats, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop); + virtual void get_parameters(std::vector<double>& prop){return;} + + /** + * @brief Set the non-linear parameters + */ + virtual void set_parameters(std::vector<double>){return;} /** - * @brief Constructor - * @details Constructs the Node from node pointer of the feature to operate on + * @brief Set the values of the training data for the feature inside of the value storage arrays * - * @param feat_1 shared_ptr of the feature to operate on (A) - * @param feat_ind Index of the new feature - * @param l_bound Minimum absolute value allowed for the feature. - * @param u_bound Maximum absolute value allowed for the feature. - * @param param_list The list of parameters to optimize using non-linear least squares - * @param prop The property to fit to + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values */ - SubNode(node_ptr feat_1, node_ptr feat_2, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop); + inline void set_value(const double* params, int offset = -1) + { + offset = (offset == -1) ? rung() : offset; + + if(_selected) + allowed_op_funcs::sub(_n_samp, _feats[0]->value_ptr(params + 2 + _feats[1]->n_params(), offset + 2), _feats[1]->value_ptr(params + 2, offset + 1), params[0], params[1], node_value_arrs::get_d_matrix_ptr(_d_mat_ind)); + allowed_op_funcs::sub(_n_samp, _feats[0]->value_ptr(params + 2 + _feats[1]->n_params(), offset + 2), _feats[1]->value_ptr(params + 2, offset + 1), params[0], params[1], node_value_arrs::get_value_ptr(_arr_ind, _feat_ind, offset)); + } /** - * @brief Solve the non-linear optimization to set the parameters - * @details Fits the data points from _feats->value_ptr and prop to get the parameters for the feature + * @brief Set the values of the test data for the feature inside of the value storage arrays * - * @param prop property to fit to get the parameters - * @param param_list List describing the parameters to fit + * @param offset(int) Key to determine which part of the temporary storage array to look into + * @param params pointer to the parameter values + */ + inline void set_test_value(const double* params, int offset = -1) + { + offset = (offset == -1) ? rung() : offset; + allowed_op_funcs::sub(_n_test_samp, _feats[0]->test_value_ptr(params + 2 + _feats[1]->n_params(), offset + 2), _feats[1]->test_value_ptr(params + 2, offset + 1), params[0], params[1], node_value_arrs::get_test_value_ptr(_arr_ind, _feat_ind, offset)); + } + + /** + * @brief The domain for the feature (min/max values) + * + * @param params parameter values for non-linear operations + * @return the domain + */ + inline Domain domain(double* params){return _feats[0]->domain(params + _feats[1]->n_params() + 2).sub(_feats[1]->domain(params + 2), params[0], params[1]);} + + /** + * @brief The expression of the feature + * + * @param params parameter values for non-linear operations + * @return feature expression */ - void get_parameters(std::vector<double>& prop, std::vector<std::string>& param_list); + inline std::string expr(double* params){return "[(" + _feats[0]->expr(params + _feats[1]->n_params() + 2) + ") - (" + std::to_string(params[0]) + "*" + _feats[1]->expr(params + 2) + " + " + std::to_string(params[1]) + ")]";} #endif }; diff --git a/src/feature_creation/node/operator_nodes/allowed_ops.hpp b/src/feature_creation/node/operator_nodes/allowed_ops.hpp index c1b0a8a2..2d404e88 100644 --- a/src/feature_creation/node/operator_nodes/allowed_ops.hpp +++ b/src/feature_creation/node/operator_nodes/allowed_ops.hpp @@ -25,6 +25,23 @@ #include <feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/cube_root.hpp> #include <feature_creation/node/operator_nodes/allowed_operator_nodes/sin/sin.hpp> #include <feature_creation/node/operator_nodes/allowed_operator_nodes/cos/cos.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/add/parameterized_add.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/sub/parameterized_subtract.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/abs/parameterized_absolute_value.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/abs_diff/parameterized_absolute_difference.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/mult/parameterized_multiply.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/div/parameterized_divide.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/inv/parameterized_inverse.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/exp/parameterized_exponential.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/neg_exp/parameterized_negative_exponential.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/log/parameterized_log.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/sq/parameterized_square.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/cb/parameterized_cube.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/six_pow/parameterized_sixth_power.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/sqrt/parameterized_square_root.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/cbrt/parameterized_cube_root.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/sin/parameterized_sin.hpp> +#include <feature_creation/node/operator_nodes/allowed_operator_nodes/cos/parameterized_cos.hpp> #include <map> #include <iostream> @@ -32,8 +49,8 @@ typedef std::function<node_ptr(node_ptr, int, double, double)> un_op_node_gen; typedef std::function<node_ptr(node_ptr, node_ptr, int, double, double)> bin_op_node_gen; #ifdef PARAMETERIZE - typedef std::function<node_ptr(node_ptr, int, double, double, std::vector<std::string>&, std::vector<double>&)> un_param_op_node_gen; - typedef std::function<node_ptr(node_ptr, node_ptr, int, double, double, std::vector<std::string>&, std::vector<double>&)> bin_param_op_node_gen; + typedef std::function<node_ptr(node_ptr, int, double, double, std::vector<double>&)> un_param_op_node_gen; + typedef std::function<node_ptr(node_ptr, node_ptr, int, double, double, std::vector<double>&)> bin_param_op_node_gen; #endif namespace allowed_op_maps diff --git a/src/feature_creation/node/operator_nodes/allowed_parameter_ops.cpp b/src/feature_creation/node/operator_nodes/allowed_parameter_ops.cpp index 6d71c8b4..cc522f8a 100644 --- a/src/feature_creation/node/operator_nodes/allowed_parameter_ops.cpp +++ b/src/feature_creation/node/operator_nodes/allowed_parameter_ops.cpp @@ -5,22 +5,22 @@ std::map<std::string, bin_param_op_node_gen> allowed_op_maps::binary_param_opera void allowed_op_maps::set_param_node_maps() { - allowed_op_maps::binary_param_operator_map["add"] = [](node_ptr f1, node_ptr f2, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop){return std::make_shared<AddNode>(f1, f2, feat_ind, l_bound, u_bound, param_list, prop);}; - allowed_op_maps::binary_param_operator_map["sub"] = [](node_ptr f1, node_ptr f2, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop){return std::make_shared<SubNode>(f1, f2, feat_ind, l_bound, u_bound, param_list, prop);}; - allowed_op_maps::binary_param_operator_map["abs_diff"] = [](node_ptr f1, node_ptr f2, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop){return std::make_shared<AbsDiffNode>(f1, f2, feat_ind, l_bound, u_bound, param_list, prop);}; - allowed_op_maps::binary_param_operator_map["mult"] = [](node_ptr f1, node_ptr f2, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop){return std::make_shared<MultNode>(f1, f2, feat_ind, l_bound, u_bound, param_list, prop);}; - allowed_op_maps::binary_param_operator_map["div"] = [](node_ptr f1, node_ptr f2, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop){return std::make_shared<DivNode>(f1, f2, feat_ind, l_bound, u_bound, param_list, prop);}; + allowed_op_maps::binary_param_operator_map["add"] = [](node_ptr f1, node_ptr f2, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop){return std::make_shared<AddParamNode>(f1, f2, feat_ind, l_bound, u_bound, prop);}; + allowed_op_maps::binary_param_operator_map["sub"] = [](node_ptr f1, node_ptr f2, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop){return std::make_shared<SubParamNode>(f1, f2, feat_ind, l_bound, u_bound, prop);}; + allowed_op_maps::binary_param_operator_map["abs_diff"] = [](node_ptr f1, node_ptr f2, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop){return std::make_shared<AbsDiffParamNode>(f1, f2, feat_ind, l_bound, u_bound, prop);}; + allowed_op_maps::binary_param_operator_map["mult"] = [](node_ptr f1, node_ptr f2, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop){return std::make_shared<MultParamNode>(f1, f2, feat_ind, l_bound, u_bound, prop);}; + allowed_op_maps::binary_param_operator_map["div"] = [](node_ptr f1, node_ptr f2, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop){return std::make_shared<DivParamNode>(f1, f2, feat_ind, l_bound, u_bound, prop);}; - allowed_op_maps::unary_param_operator_map["exp"] = [](node_ptr f1, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop){return std::make_shared<ExpNode>(f1, feat_ind, l_bound, u_bound, param_list, prop);}; - allowed_op_maps::unary_param_operator_map["neg_exp"] = [](node_ptr f1, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop){return std::make_shared<NegExpNode>(f1, feat_ind, l_bound, u_bound, param_list, prop);}; - allowed_op_maps::unary_param_operator_map["inv"] = [](node_ptr f1, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop){return std::make_shared<InvNode>(f1, feat_ind, l_bound, u_bound, param_list, prop);}; - allowed_op_maps::unary_param_operator_map["sq"] = [](node_ptr f1, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop){return std::make_shared<SqNode>(f1, feat_ind, l_bound, u_bound, param_list, prop);}; - allowed_op_maps::unary_param_operator_map["cb"] = [](node_ptr f1, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop){return std::make_shared<CbNode>(f1, feat_ind, l_bound, u_bound, param_list, prop);}; - allowed_op_maps::unary_param_operator_map["six_pow"] = [](node_ptr f1, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop){return std::make_shared<SixPowNode>(f1, feat_ind, l_bound, u_bound, param_list, prop);}; - allowed_op_maps::unary_param_operator_map["sqrt"] = [](node_ptr f1, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop){return std::make_shared<SqrtNode>(f1, feat_ind, l_bound, u_bound, param_list, prop);}; - allowed_op_maps::unary_param_operator_map["cbrt"] = [](node_ptr f1, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop){return std::make_shared<CbrtNode>(f1, feat_ind, l_bound, u_bound, param_list, prop);}; - allowed_op_maps::unary_param_operator_map["log"] = [](node_ptr f1, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop){return std::make_shared<LogNode>(f1, feat_ind, l_bound, u_bound, param_list, prop);}; - allowed_op_maps::unary_param_operator_map["abs"] = [](node_ptr f1, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop){return std::make_shared<AbsNode>(f1, feat_ind, l_bound, u_bound, param_list, prop);}; - allowed_op_maps::unary_param_operator_map["sin"] = [](node_ptr f1, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop){return std::make_shared<SinNode>(f1, feat_ind, l_bound, u_bound, param_list, prop);}; - allowed_op_maps::unary_param_operator_map["cos"] = [](node_ptr f1, int feat_ind, double l_bound, double u_bound, std::vector<std::string>& param_list, std::vector<double>& prop){return std::make_shared<CosNode>(f1, feat_ind, l_bound, u_bound, param_list, prop);}; + allowed_op_maps::unary_param_operator_map["exp"] = [](node_ptr f1, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop){return std::make_shared<ExpParamNode>(f1, feat_ind, l_bound, u_bound, prop);}; + allowed_op_maps::unary_param_operator_map["neg_exp"] = [](node_ptr f1, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop){return std::make_shared<NegExpParamNode>(f1, feat_ind, l_bound, u_bound, prop);}; + allowed_op_maps::unary_param_operator_map["inv"] = [](node_ptr f1, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop){return std::make_shared<InvParamNode>(f1, feat_ind, l_bound, u_bound, prop);}; + allowed_op_maps::unary_param_operator_map["sq"] = [](node_ptr f1, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop){return std::make_shared<SqParamNode>(f1, feat_ind, l_bound, u_bound, prop);}; + allowed_op_maps::unary_param_operator_map["cb"] = [](node_ptr f1, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop){return std::make_shared<CbParamNode>(f1, feat_ind, l_bound, u_bound, prop);}; + allowed_op_maps::unary_param_operator_map["six_pow"] = [](node_ptr f1, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop){return std::make_shared<SixPowParamNode>(f1, feat_ind, l_bound, u_bound, prop);}; + allowed_op_maps::unary_param_operator_map["sqrt"] = [](node_ptr f1, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop){return std::make_shared<SqrtParamNode>(f1, feat_ind, l_bound, u_bound, prop);}; + allowed_op_maps::unary_param_operator_map["cbrt"] = [](node_ptr f1, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop){return std::make_shared<CbrtParamNode>(f1, feat_ind, l_bound, u_bound, prop);}; + allowed_op_maps::unary_param_operator_map["log"] = [](node_ptr f1, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop){return std::make_shared<LogParamNode>(f1, feat_ind, l_bound, u_bound, prop);}; + allowed_op_maps::unary_param_operator_map["abs"] = [](node_ptr f1, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop){return std::make_shared<AbsParamNode>(f1, feat_ind, l_bound, u_bound, prop);}; + allowed_op_maps::unary_param_operator_map["sin"] = [](node_ptr f1, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop){return std::make_shared<SinParamNode>(f1, feat_ind, l_bound, u_bound, prop);}; + allowed_op_maps::unary_param_operator_map["cos"] = [](node_ptr f1, int feat_ind, double l_bound, double u_bound, std::vector<double>& prop){return std::make_shared<CosParamNode>(f1, feat_ind, l_bound, u_bound, prop);}; } diff --git a/src/feature_creation/node/value_storage/nodes_value_containers.cpp b/src/feature_creation/node/value_storage/nodes_value_containers.cpp index a0fca7d1..f6801040 100644 --- a/src/feature_creation/node/value_storage/nodes_value_containers.cpp +++ b/src/feature_creation/node/value_storage/nodes_value_containers.cpp @@ -66,21 +66,21 @@ void node_value_arrs::resize_values_arr(int n_dims, int n_feat, bool use_temp) } } -double* node_value_arrs::get_value_ptr(int arr_ind, int feat_ind, int offset) +double* node_value_arrs::get_value_ptr(int arr_ind, int feat_ind, int offset, bool modify_reg) { if(arr_ind < N_STORE_FEATURES) return access_value_arr(arr_ind); - temp_storage_reg(arr_ind, offset) = feat_ind; + temp_storage_reg(arr_ind, offset) = feat_ind * modify_reg - (!modify_reg); return access_temp_storage((arr_ind % N_STORE_FEATURES) + (offset % 3) * N_STORE_FEATURES); } -double* node_value_arrs::get_test_value_ptr(int arr_ind, int feat_ind, int offset) +double* node_value_arrs::get_test_value_ptr(int arr_ind, int feat_ind, int offset, bool modify_reg) { if(arr_ind < N_STORE_FEATURES) return access_test_value_arr(arr_ind); - temp_storage_test_reg(arr_ind, offset) = feat_ind; + temp_storage_test_reg(arr_ind, offset) = feat_ind * modify_reg - (!modify_reg); return access_temp_storage_test((arr_ind % N_STORE_FEATURES) + (offset % 3) * N_STORE_FEATURES); } diff --git a/src/feature_creation/node/value_storage/nodes_value_containers.hpp b/src/feature_creation/node/value_storage/nodes_value_containers.hpp index 32af493c..4a7cd8f8 100644 --- a/src/feature_creation/node/value_storage/nodes_value_containers.hpp +++ b/src/feature_creation/node/value_storage/nodes_value_containers.hpp @@ -132,7 +132,7 @@ namespace node_value_arrs * * @return The value pointer */ - double* get_value_ptr(int arr_ind, int feat_ind, int offset = 0); + double* get_value_ptr(int arr_ind, int feat_ind, int offset = 0, bool modify_reg = true); /** * @brief Get a Node's test_value_ptr @@ -143,7 +143,7 @@ namespace node_value_arrs * * @return The value pointer */ - double* get_test_value_ptr(int arr_ind, int feat_ind, int offset = 0); + double* get_test_value_ptr(int arr_ind, int feat_ind, int offset = 0, bool modify_reg = true); /** * @brief Get the pointer to a particular selected Node from sis diff --git a/src/feature_creation/parameterization/NLOptWrapper.cpp b/src/feature_creation/parameterization/NLOptWrapper.cpp new file mode 100644 index 00000000..f34b3614 --- /dev/null +++ b/src/feature_creation/parameterization/NLOptWrapper.cpp @@ -0,0 +1,22 @@ +#include <feature_creation/parameterization/NLOptWrapper.hpp> + +std::function<double(unsigned int n, const double* p, double* grad, void* data)> nlopt_wrapper::_objective; +std::vector<double> nlopt_wrapper::_zeros; + +void nlopt_wrapper::set_objective(std::string calc_type, double* prop, std::vector<int> sizes) +{ + _zeros.resize(100, 0.0); + if(calc_type.compare("classification") == 0) + { + convex_hull::initialize_projection(sizes, prop); + _objective = objective_reg; + } + else if(calc_type.compare("regression") == 0) + { + _objective = objective_class; + } + else + { + throw std::logic_error("projection type can not determined"); + } +} diff --git a/src/feature_creation/parameterization/NLOptWrapper.hpp b/src/feature_creation/parameterization/NLOptWrapper.hpp new file mode 100644 index 00000000..ed75fa0a --- /dev/null +++ b/src/feature_creation/parameterization/NLOptWrapper.hpp @@ -0,0 +1,49 @@ +/** @file feature_creation/parameterization/NLOptWrapper.hpp + * @brief Wrapper and functions to use libnlopt to find parameterizations for features + * + * @author Thomas A. R. Purcell (tpurcell) + * @bug No known bugs. + */ +#ifndef NL_OPT_WRAPPER +#define NL_OPT_WRAPPER + +#include <nlopt.hpp> +#include <feature_creation/node/Node.hpp> +#include <classification/utils.hpp> + +namespace nlopt_wrapper +{ + typedef struct + { + double *_prop; //!< pointer to the property vector + Node* _feat; //!< Node pointer of the feature to parameterize + } feat_data; + + static double objective_class(unsigned int n, const double* p, double* grad, void* data) + { + feat_data* d = (feat_data*) data; + return convex_hull::overlap_1d(d->_feat->value_ptr(p)); + } + + static double objective_reg(unsigned int n, const double* p, double* grad, void* data) + { + feat_data* d = (feat_data*) data; + double score = util_funcs::r2(d->_feat->value_ptr(p), d->_prop, d->_feat->n_samp()); + return -1.0 * std::isfinite(score) * score; + } + + extern std::function<double(unsigned int n, const double* p, double* grad, void* data)> _objective; //!< Objective function to use + extern std::vector<double> _zeros; //!< array of zeros to fill parameters + + /** + * @brief Set up the projection operator for the objective function + * + * @param calc_type [description] + * @param prop [description] + * @param N [description] + */ + void set_objective(std::string calc_type, double* prop, std::vector<int> sizes); +} + + +#endif \ No newline at end of file diff --git a/src/inputs/InputParser.cpp b/src/inputs/InputParser.cpp index 52f09203..541ed534 100644 --- a/src/inputs/InputParser.cpp +++ b/src/inputs/InputParser.cpp @@ -2,6 +2,7 @@ InputParser::InputParser(pt::ptree IP, std::string fn, std::shared_ptr<MPI_Interface> comm) : _opset(as_vector<std::string>(IP, "opset")), + _param_opset(as_vector<std::string>(IP, "param_opset")), _filename(fn), _data_file(IP.get<std::string>("data_file", "data.csv")), _prop_key(IP.get<std::string>("property_key", "prop")), @@ -148,24 +149,6 @@ InputParser::InputParser(pt::ptree IP, std::string fn, std::shared_ptr<MPI_Inter "sqrt", "cbrt" }; - for(pt::ptree::value_type ¶m_op : IP.get_child("param_opset")) - { - _param_opset[param_op.first] = as_vector<std::string>(param_op.second); - if(_fix_intercept) - { - std::vector<std::string>::iterator it = std::find(_param_opset[param_op.first].begin(), _param_opset[param_op.first].end(), "c"); - if(it != _param_opset[param_op.first].end()) - _param_opset[param_op.first].erase(it); - - it = std::find(fix_intercept_problem_a.begin(), fix_intercept_problem_a.end(), param_op.first); - if(it != fix_intercept_problem_a.end()) - { - it = std::find(_param_opset[param_op.first].begin(), _param_opset[param_op.first].end(), "a"); - if(it != _param_opset[param_op.first].end()) - _param_opset[param_op.first].erase(it); - } - } - } if((_opset.size() == 0) && (_param_opset.size() == 0)) { @@ -316,6 +299,12 @@ void InputParser::generate_feature_space(std::shared_ptr<MPI_Interface> comm, st std::array<double, 2> end_points; end_points[0] = *std::min_element(data[ff].begin(), data[ff].end()); end_points[1] = *std::max_element(data[ff].begin(), data[ff].end()); + + double range = end_points[1] - end_points[0]; + + end_points[0] -= range * 0.01; + end_points[1] += range * 0.01; + domain_list[ff] = std::make_shared<Domain>(end_points); } phi_0.push_back(std::make_shared<FeatureNode>(ff, headers[ff], data[ff], test_data[ff], *domain_list[ff], units[ff])); diff --git a/src/inputs/InputParser.hpp b/src/inputs/InputParser.hpp index 4b41aa29..e71265ac 100644 --- a/src/inputs/InputParser.hpp +++ b/src/inputs/InputParser.hpp @@ -36,7 +36,7 @@ class InputParser { public: - std::map<std::string, std::vector<std::string>> _param_opset; //!< Map of parameterization operator set (set of operators and non-linear parameters used for a non-linear least squares fit to property) + std::vector<std::string> _param_opset; //!< Map of parameterization operator set (set of operators and non-linear parameters used for a non-linear least squares fit to property) std::vector<std::string> _opset; //!< List of all operators for feature combination std::vector<double> _prop_train; //!< The values of the property in the training set std::vector<double> _prop_test; //!< The values of the property in the test set diff --git a/src/main.cpp b/src/main.cpp index f27916e8..41cf1fb5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,16 +2,16 @@ #include <descriptor_identifier/SISSO_DI/SISSORegressor.hpp> #include <descriptor_identifier/SISSO_DI/SISSOClassifier.hpp> #include <iostream> -#include <gflags/gflags.h> +// #include <gflags/gflags.h> int main(int argc, char const *argv[]) { allowed_op_maps::set_node_maps(); #ifdef PARAMETERIZE - google::InitGoogleLogging("XXX"); - google::SetCommandLineOption("GLOG_minloglevel", "3"); - google::SetCommandLineOption("stderrthreshold", "3"); + // google::InitGoogleLogging("XXX"); + // google::SetCommandLineOption("GLOG_minloglevel", "3"); + // google::SetCommandLineOption("stderrthreshold", "3"); allowed_op_maps::set_param_node_maps(); #endif diff --git a/src/python/_sisso.cpp b/src/python/_sisso.cpp index 86158e2b..9e25c4a9 100644 --- a/src/python/_sisso.cpp +++ b/src/python/_sisso.cpp @@ -6,21 +6,10 @@ #include <mpi_interface/MPI_Interface.hpp> #include <Python.h> -#ifdef PARAMETERIZE - #include <gflags/gflags.h> -#endif - static void finalize(); BOOST_PYTHON_MODULE(_sisso) { - - #ifdef PARAMETERIZE - google::InitGoogleLogging("XXX"); - google::SetCommandLineOption("GLOG_minloglevel", "3"); - google::SetCommandLineOption("stderrthreshold", "3"); - #endif - py::docstring_options local_docstring_options(true, true, true); Py_Initialize(); diff --git a/src/python/bindings.cpp b/src/python/bindings.cpp new file mode 100644 index 00000000..ae31f904 --- /dev/null +++ b/src/python/bindings.cpp @@ -0,0 +1,919 @@ +#include <python/bindings.hpp> + +using namespace boost::python; + +void sisso::register_all() +{ + sisso::descriptor_identifier::registerModel(); + sisso::descriptor_identifier::registerModelRegressor(); + sisso::descriptor_identifier::registerModelClassifier(); + sisso::descriptor_identifier::registerSISSO_DI(); + sisso::descriptor_identifier::registerSISSORegressor(); + sisso::descriptor_identifier::registerSISSOClassifier(); + sisso::feature_creation::registerFeatureSpace(); + sisso::feature_creation::registerDomain(); + sisso::feature_creation::registerUnit(); + sisso::feature_creation::node::registerNode(); + sisso::feature_creation::node::registerFeatureNode(); + sisso::feature_creation::node::registerModelNode(); + sisso::feature_creation::node::registerOperatorNode<1>(); + sisso::feature_creation::node::registerOperatorNode<2>(); + sisso::feature_creation::node::registerAddNode(); + sisso::feature_creation::node::registerSubNode(); + sisso::feature_creation::node::registerDivNode(); + sisso::feature_creation::node::registerMultNode(); + sisso::feature_creation::node::registerAbsDiffNode(); + sisso::feature_creation::node::registerAbsNode(); + sisso::feature_creation::node::registerInvNode(); + sisso::feature_creation::node::registerLogNode(); + sisso::feature_creation::node::registerExpNode(); + sisso::feature_creation::node::registerNegExpNode(); + sisso::feature_creation::node::registerSinNode(); + sisso::feature_creation::node::registerCosNode(); + sisso::feature_creation::node::registerCbNode(); + sisso::feature_creation::node::registerCbrtNode(); + sisso::feature_creation::node::registerSqNode(); + sisso::feature_creation::node::registerSqrtNode(); + sisso::feature_creation::node::registerSixPowNode(); + + def("phi_selected_from_file", &str2node::phi_selected_from_file_py); + def("initialize_values_arr", &node_value_arrs::initialize_values_arr); + def("initialize_d_matrix_arr", &node_value_arrs::initialize_d_matrix_arr); +} + +void sisso::feature_creation::registerFeatureSpace() +{ + void (FeatureSpace::*sis_list)(list) = &FeatureSpace::sis; + void (FeatureSpace::*sis_ndarray)(np::ndarray) = &FeatureSpace::sis; + + class_<FeatureSpace>("FeatureSpace", init<list, list, list, np::ndarray, list, optional<std::string, int, int, int, int, double, double, double>>()) + .def(init<list, list, list, list, list, optional<std::string, int, int, int, int, double, double, double>>()) + .def(init<std::string, list, list, optional<std::string, int, double>>()) + .def("sis", sis_list, "Wrapper function for SIS using a python list\nArgs:\n prop (list): The property to perform SIS over as a python list") + .def("sis", sis_ndarray, "Wrapper function for SIS using a numpy array\nArgs:\n prop (np.ndarray): The property to perform SIS over as a numpy array") + .def("feat_in_phi", &FeatureSpace::feat_in_phi, "Is a feature in this process' _phi?\nArgs:\n ind: The index of the feature\n\nReturns:\n True if feature is in this rank's _phi") + .def("remove_feature", &FeatureSpace::remove_feature, "Remove a feature from phi\nArgs:\n ind: index of feature to remove") + .def("get_feature", &FeatureSpace::get_feature, "Return a feature at a specified index\nArgs:\n ind: index of the feature to get\n\nReturns:\n A ModelNode of the feature at index ind") + .add_property("phi_selected", &FeatureSpace::phi_selected_py, "The selected feature space (cpp definition in <python/feature_creation/FeatureSpace.cpp>)\n\nReturns:\n _phi_selected as a python list") + .add_property("phi0", &FeatureSpace::phi0_py, "The initial feature space (cpp definition in <python/feature_creation/FeatureSpace.cpp>)\n\nReturns:\n _phi0 as a python list") + .add_property("phi", &FeatureSpace::phi_py, "The feature space (cpp definition in <python/feature_creation/FeatureSpace.cpp>)\n\nReturns:\n _phi as a python list") + .add_property("scores", &FeatureSpace::scores_py, "The vector of projection scores for SIS\n\nReturns:\n _scores as a numpy array") + .add_property("task_sizes", &FeatureSpace::task_sizes_py, "The vector storing the number of samples in each task\n\nReturns:\n _task_sizes as a python list") + .add_property("allowed_ops", &FeatureSpace::allowed_ops_py, "The list of allowed operator nodes\n\nReturns:\n _allowed_ops as a python list") + .add_property("start_gen", &FeatureSpace::start_gen_py, "The index in _phi where each generation starts\n\nReturns:\n _start_gen as a python list") + .add_property("feature_space_file", &FeatureSpace::feature_space_file, "The feature space filename") + .add_property("l_bound", &FeatureSpace::l_bound, "The minimum absolute value of the feature") + .add_property("u_bound", &FeatureSpace::u_bound, "The maximum absolute value of the feature") + .add_property("max_phi", &FeatureSpace::max_phi, "The maximum rung of the feature space") + .add_property("n_sis_select", &FeatureSpace::n_sis_select, "The number of features selected in each SIS step") + .add_property("n_samp", &FeatureSpace::n_samp, "The number of samples per feature") + .add_property("n_feat", &FeatureSpace::n_feat, "The number of features in the feature space") + .add_property("n_rung_store", &FeatureSpace::n_rung_store, "The number of rungs whose feature training data is stored in memory") + .add_property("n_rung_generate", &FeatureSpace::n_rung_generate, "The number of rungs to be generated on the fly during SIS") + ; +} + +void sisso::feature_creation::registerUnit() +{ + class_<Unit>("Unit", init<>()) + .def(init<std::map<std::string, double>>()) + .def(init<std::string>()) + .def(init<Unit&>()) + .def("__str__", &Unit::toString, "Convert the unit into a string") + .def("__repr__", &Unit::toString, "Convert the unit into a string") + .def("inverse", &Unit::inverse, "Inverse operator for units\n\nReturns:\n The inverse of this unit") + .def(self * self) + .def(self / self) + .def(self *= self) + .def(self /= self) + .def(self == self) + .def(self != self) + .def("__pow__", &Unit::operator^, "Exponentiation operator for units\nArgs:\n power: power to exponentiate the unit\n\nReturns:\n The unit raised to the power") + ; +} + +void sisso::feature_creation::registerDomain() +{ + class_<Domain>("Domain", init<>()) + .def(init<std::string>()) + .def(init<double, double>()) + .def(init<double, double, double, double>()) + .def(init<Domain&>()) + .def("__str__", &Domain::toString, "Convert the domain into a string") + .def("__repr__", &Domain::toString, "Convert the domain into a string") + .def("__pow__", &Domain::operator^, "Exponentiation operator for domain\nArgs:\n power: power to exponentiate the domain\n\nReturns:\n The domain raised to the power") + .def("inv", &Domain::inv, "The inverse of the domain\nArgs:\n alpha: prefactor for the domain\n a: The shift of the domain\n\nReturns:\n The log(alpha * domain + a) domain") + .def("exp", &Domain::exp, "Exponential of the domain\nArgs:\n alpha: prefactor for the domain\n a: The shift of the domain\n\nReturns:\n The exp(alpha * domain + a) domain") + .def("log", &Domain::log, "Logarithm of the domain\nArgs:\n alpha: prefactor for the domain\n a: The shift of the domain\n\nReturns:\n The log(alpha * domain + a) domain") + .def("add", &Domain::add, "Addition operator with a scale and a shift\nArgs:\n domain_2: the second domain to operate on\n alpha: scale parameter\n a: shift parameter\n\nReturns:\n The resulting domain") + .def("sub", &Domain::sub, "Subtraction operator with a scale and a shift\nArgs:\n domain_2: the second domain to operate on\n alpha: scale parameter\n a: shift parameter\n\nReturns:\n The resulting domain") + .def("mult", &Domain::mult, "Multiplication operator with a scale and a shift\nArgs:\n domain_2: the second domain to operate on\n alpha: scale parameter\n a: shift parameter\n\nReturns:\n The resulting domain") + .def("div", &Domain::div, "Division operator with a scale and a shift\nArgs:\n domain_2: the second domain to operate on\n alpha: scale parameter\n a: shift parameter\n\nReturns:\n The resulting domain") + .def("pow", &Domain::pow, "Exponentiation operator for domain\nArgs:\n power: power to exponentiate the domain\n\nReturns:\n The domain raised to the power") + .def("abs", &Domain::abs, "Exponential of the domain\nArgs:\n alpha: prefactor for the domain\n a: The shift of the domain\n\nReturns:\n The abs(alpha * domain + a) domain") + .def("__contains__", &Domain::contains, "Returns true if number is inside the domain\nArgs:\n number: number to check\n\nReturns:\n True if number is inside the domain") + .def(self + self) + .def(self - self) + .def(self * self) + .def(self / self) + .def(self + double()) + .def(self - double()) + .def(self * double()) + .def(self / double()) + .def(self == self) + .def(self != self) + .def(double() + self) + .def(double() - self) + .def(double() * self) + .def(double() / self) + .add_property("end_points", &Domain::end_points_py, "") + .add_property("excluded_points", &Domain::excluded_points_py, "") + ; +} + +#ifdef PARAMETERIZE + void sisso::feature_creation::node::registerNode() + { + void (Node::*reindex_1)(int) = &Node::reindex; + void (Node::*reindex_2)(int, int) = &Node::reindex; + // void (Node::*expr_no_param)() = &Node::expr; + + class_<sisso::feature_creation::node::NodeWrap, boost::noncopyable>("Node", no_init) + .def("reindex", reindex_1, "Reindex the feature\nre-index the feature to be continuous\nArgs:\n ind (int): the new feature and array index") + .def("reindex", reindex_2, "Reindex the feature\nre-index the feature to be continuous\nArgs:\n ind (int): the new feature index\n arr_ind (int): the new array index") + // .def("__str__", expr_no_param, "Get the expression for the overall feature (From root node down)") + // .def("__repr__", expr_no_param, "Get the expression for the overall feature (From root node down)") + .add_property("n_samp", &Node::n_samp, "") + .add_property("n_test_samp", &Node::n_test_samp, "") + .add_property("feat_ind", &Node::feat_ind, "The feature index") + .add_property("arr_ind", &Node::arr_ind, "The feature array index") + .add_property("selected", &Node::selected, &Node::set_selected, "") + .add_property("d_mat_ind", &Node::d_mat_ind, &Node::set_d_mat_ind, "") + .add_property("value", &Node::value_py, "The training data of the feature\n\nReturns:\n The training data as a numpy array") + .add_property("test_value", &Node::test_value_py, "The test data of the feature\n\nReturns:\n The test data as a numpy array") + .add_property("primary_feat_decomp", &Node::primary_feature_decomp_py, "Get the primary feature decomposition of a feature\n\nReturns:\n A python dict representing the primary feature comprising a feature") + .add_property("postfix_expr", &Node::postfix_expr, "Get the postfix expression for the feature\n\nReturns:\n The postfix string for the expression") + .add_property("parameters", &Node::parameters_py, "The parameters used for non-linear operator nodes\n\nReturns:\n The operator node parameters as a list [alpha, a]") + // .def("domain", pure_virtual(&Node::domain), "The domain for the feature (min/max values)") + // .def("expr", pure_virtual(expr_no_param), "Get the expression for the overall feature (From root node down)") + .def("unit", pure_virtual(&Node::unit), "Get the unit for the overall feature (From root node down)") + // .def("set_value", pure_virtual(&Node::set_value), "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + // .def("set_test_value", pure_virtual(&Node::set_test_value), "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("is_nan", pure_virtual(&Node::is_nan), "Check if the feature contains NaN") + .def("is_const", pure_virtual(&Node::is_const), "Check if feature is constant") + .def("rung", pure_virtual(&Node::rung), "return the rung of the feature\nArgs:\n cur_rung (int): The rung current rung of the feature tree (used to recursively calculate rung)") + .def("n_feats", pure_virtual(&Node::n_feats), "") + .def("feat", pure_virtual(&Node::feat), "") + ; + } +#else + void sisso::feature_creation::node::registerNode() + { + void (Node::*reindex_1)(int) = &Node::reindex; + void (Node::*reindex_2)(int, int) = &Node::reindex; + class_<sisso::feature_creation::node::NodeWrap, boost::noncopyable>("Node", no_init) + .def("reindex", reindex_1, "Reindex the feature\nre-index the feature to be continuous\nArgs:\n ind (int): the new feature and array index") + .def("reindex", reindex_2, "Reindex the feature\nre-index the feature to be continuous\nArgs:\n ind (int): the new feature index\n arr_ind (int): the new array index") + // .def("__str__", &Node::expr, "Get the expression for the overall feature (From root node down)") + // .def("__repr__", &Node::expr, "Get the expression for the overall feature (From root node down)") + .add_property("n_samp", &Node::n_samp, "") + .add_property("n_test_samp", &Node::n_test_samp, "") + .add_property("feat_ind", &Node::feat_ind, "The feature index") + .add_property("arr_ind", &Node::arr_ind, "The feature array index") + .add_property("selected", &Node::selected, &Node::set_selected, "") + .add_property("d_mat_ind", &Node::d_mat_ind, &Node::set_d_mat_ind, "") + .add_property("value", &Node::value_py, "The training data of the feature\n\nReturns:\n The training data as a numpy array") + .add_property("test_value", &Node::test_value_py, "The test data of the feature\n\nReturns:\n The test data as a numpy array") + .add_property("primary_feat_decomp", &Node::primary_feature_decomp_py, "Get the primary feature decomposition of a feature\n\nReturns:\n A python dict representing the primary feature comprising a feature") + .add_property("postfix_expr", &Node::postfix_expr, "Get the postfix expression for the feature\n\nReturns:\n The postfix string for the expression") + // .def("expr", pure_virtual(&Node::expr), "Get the expression for the overall feature (From root node down)") + .def("unit", pure_virtual(&Node::unit), "Get the unit for the overall feature (From root node down)") + // .def("set_value", pure_virtual(&Node::set_value), "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + // .def("set_test_value", pure_virtual(&Node::set_test_value), "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("is_nan", pure_virtual(&Node::is_nan), "Check if the feature contains NaN") + .def("is_const", pure_virtual(&Node::is_const), "Check if feature is constant") + .def("rung", pure_virtual(&Node::rung), "return the rung of the feature\nArgs:\n cur_rung (int): The rung current rung of the feature tree (used to recursively calculate rung)") + .def("n_feats", pure_virtual(&Node::n_feats), "") + .def("feat", pure_virtual(&Node::feat), "") + ; + } +#endif + +void sisso::feature_creation::node::registerFeatureNode() +{ + std::string (FeatureNode::*expr_1)() = &FeatureNode::expr; + std::string (FeatureNode::*expr_const)() const = &FeatureNode::expr; + void (FeatureNode::*set_value_no_param)(int) = &FeatureNode::set_value; + void (FeatureNode::*set_test_value_no_param)(int) = &FeatureNode::set_test_value; + Domain (FeatureNode::*domain_no_param)() = &FeatureNode::domain; + + using namespace boost::python; + class_<FeatureNode, bases<Node>>("FeatureNode", init<int, std::string, np::ndarray, np::ndarray, Domain, Unit>()) + .def(init<int, std::string, py::list, py::list, Domain, Unit>()) + .def("is_nan", &FeatureNode::is_nan, "Check if the feature contains NaN") + .def("is_const", &FeatureNode::is_const, "Check if feature is constant") + .def("set_value", set_value_no_param, "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("set_test_value", set_test_value_no_param, "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .add_property("expr", expr_1, "Get the string expression used to represent the primary feature") + .add_property("expr", expr_const, "Get the string expression used to represent the primary feature") + .add_property("domain", domain_no_param, "The domain for the feature (min/max values)") + .add_property("unit", &FeatureNode::unit, "The unit of the primary feature") + .add_property("rung", &FeatureNode::rung, "return the rung of the feature\nArgs:\n cur_rung: The rung current rung of the feature tree (used to recursively calculate rung)") + ; +} + +void sisso::feature_creation::node::registerModelNode() +{ + std::string (ModelNode::*expr_1)() = &ModelNode::expr; + std::string (ModelNode::*expr_const)() const = &ModelNode::expr; + + using namespace boost::python; + class_<ModelNode, bases<FeatureNode>>("ModelNode", init<int, int, std::string, std::string, std::vector<double>, std::vector<double>, Domain, Unit>()) + .def("is_nan", &ModelNode::is_nan, "Check if the feature contains NaN") + .def("is_const", &ModelNode::is_const, "Check if feature is constant") + .def("set_value", &ModelNode::set_value, "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("set_test_value", &ModelNode::set_test_value, "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .add_property("rung", &ModelNode::rung, "return the rung of the feature\nArgs:\n cur_rung (int): The rung current rung of the feature tree (used to recursively calculate rung)") + ; +} + +void sisso::feature_creation::node::registerAddNode() +{ + void (AddNode::*set_value_no_param)(int) = &AddNode::set_value; + void (AddNode::*set_test_value_no_param)(int) = &AddNode::set_test_value; + std::string (AddNode::*expr_no_param)() = &AddNode::expr; + Domain (AddNode::*domain_no_param)() = &AddNode::domain; + + class_<AddNode, bases<OperatorNode<2>>>("AddNode", init<node_ptr, node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("set_test_value", set_test_value_no_param, "Set the test value for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .add_property("expr", expr_no_param, "Get the expression for the overall feature (From root node down)") + .add_property("domain", domain_no_param, "The domain for the feature (min/max values)") + .add_property("unit", &AddNode::unit, "Get the unit of the feature (combine the units of _feats)") + .add_property("rung", &AddNode::rung, "return the rung of the feature\nArgs:\n cur_rung: The rung current rung of the feature tree (used to recursively calculate rung)") + ; +} + +void sisso::feature_creation::node::registerSubNode() +{ + void (SubNode::*set_value_no_param)(int) = &SubNode::set_value; + void (SubNode::*set_test_value_no_param)(int) = &SubNode::set_test_value; + std::string (SubNode::*expr_no_param)() = &SubNode::expr; + Domain (SubNode::*domain_no_param)() = &SubNode::domain; + + class_<SubNode, bases<OperatorNode<2>>>("SubNode", init<node_ptr, node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("set_test_value", set_test_value_no_param, "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .add_property("expr", expr_no_param, "Get the expression for the overall feature (From root node down)") + .add_property("domain", domain_no_param, "The domain for the feature (min/max values)") + .add_property("unit", &SubNode::unit, "Get the unit of the feature (combine the units of _feats)") + .add_property("rung", &SubNode::rung, "return the rung of the feature\nArgs:\n cur_rung: The rung current rung of the feature tree (used to recursively calculate rung)") + ; +} + +void sisso::feature_creation::node::registerDivNode() +{ + void (DivNode::*set_value_no_param)(int) = &DivNode::set_value; + void (DivNode::*set_test_value_no_param)(int) = &DivNode::set_test_value; + std::string (DivNode::*expr_no_param)() = &DivNode::expr; + Domain (DivNode::*domain_no_param)() = &DivNode::domain; + + class_<DivNode, bases<OperatorNode<2>>>("DivNode", init<node_ptr, node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("set_test_value", set_test_value_no_param, "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .add_property("expr", expr_no_param, "Get the expression for the overall feature (From root node down)") + .add_property("domain", domain_no_param, "The domain for the feature (min/max values)") + .add_property("unit", &DivNode::unit, "Get the unit of the feature (combine the units of _feats)") + .add_property("rung", &DivNode::rung, "return the rung of the feature\nArgs:\n cur_rung: The rung current rung of the feature tree (used to recursively calculate rung)") + ; +} + +void sisso::feature_creation::node::registerMultNode() +{ + void (MultNode::*set_value_no_param)(int) = &MultNode::set_value; + void (MultNode::*set_test_value_no_param)(int) = &MultNode::set_test_value; + std::string (MultNode::*expr_no_param)() = &MultNode::expr; + Domain (MultNode::*domain_no_param)() = &MultNode::domain; + + class_<MultNode, bases<OperatorNode<2>>>("MultNode", init<node_ptr, node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("set_test_value", set_test_value_no_param, "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .add_property("expr", expr_no_param, "Get the expression for the overall feature (From root node down)") + .add_property("domain", domain_no_param, "The domain for the feature (min/max values)") + .add_property("unit", &MultNode::unit, "Get the unit of the feature (combine the units of _feats)") + .add_property("rung", &MultNode::rung, "return the rung of the feature\nArgs:\n cur_rung: The rung current rung of the feature tree (used to recursively calculate rung)") + ; +} + +void sisso::feature_creation::node::registerAbsDiffNode() +{ + void (AbsDiffNode::*set_value_no_param)(int) = &AbsDiffNode::set_value; + void (AbsDiffNode::*set_test_value_no_param)(int) = &AbsDiffNode::set_test_value; + std::string (AbsDiffNode::*expr_no_param)() = &AbsDiffNode::expr; + Domain (AbsDiffNode::*domain_no_param)() = &AbsDiffNode::domain; + + class_<AbsDiffNode, bases<OperatorNode<2>>>("AbsDiffNode", init<node_ptr, node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("set_test_value", set_test_value_no_param, "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .add_property("expr", expr_no_param, "Get the expression for the overall feature (From root node down)") + .add_property("domain", domain_no_param, "The domain for the feature (min/max values)") + .add_property("unit", &AbsDiffNode::unit, "Get the unit of the feature (combine the units of _feats)") + .add_property("rung", &AbsDiffNode::rung, "return the rung of the feature\nArgs:\n cur_rung: The rung current rung of the feature tree (used to recursively calculate rung)") + ; +} + +void sisso::feature_creation::node::registerAbsNode() +{ + void (AbsNode::*set_value_no_param)(int) = &AbsNode::set_value; + void (AbsNode::*set_test_value_no_param)(int) = &AbsNode::set_test_value; + std::string (AbsNode::*expr_no_param)() = &AbsNode::expr; + Domain (AbsNode::*domain_no_param)() = &AbsNode::domain; + + class_<AbsNode, bases<OperatorNode<1>>>("AbsNode", init<node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("set_test_value", set_test_value_no_param, "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .add_property("expr", expr_no_param, "Get the expression for the overall feature (From root node down)") + .add_property("domain", domain_no_param, "The domain for the feature (min/max values)") + .add_property("unit", &AbsNode::unit, "Get the unit of the feature (combine the units of _feats)") + .add_property("rung", &AbsNode::rung, "return the rung of the feature\nArgs:\n cur_rung: The rung current rung of the feature tree (used to recursively calculate rung)") + ; +} + +void sisso::feature_creation::node::registerInvNode() +{ + void (InvNode::*set_value_no_param)(int) = &InvNode::set_value; + void (InvNode::*set_test_value_no_param)(int) = &InvNode::set_test_value; + std::string (InvNode::*expr_no_param)() = &InvNode::expr; + Domain (InvNode::*domain_no_param)() = &InvNode::domain; + + class_<InvNode, bases<OperatorNode<1>>>("InvNode", init<node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("set_test_value", set_test_value_no_param, "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .add_property("expr", expr_no_param, "Get the expression for the overall feature (From root node down)") + .add_property("domain", domain_no_param, "The domain for the feature (min/max values)") + .add_property("unit", &InvNode::unit, "Get the unit of the feature (combine the units of _feats)") + .add_property("rung", &InvNode::rung, "return the rung of the feature\nArgs:\n cur_rung: The rung current rung of the feature tree (used to recursively calculate rung)") + ; +} + +void sisso::feature_creation::node::registerLogNode() +{ + void (LogNode::*set_value_no_param)(int) = &LogNode::set_value; + void (LogNode::*set_test_value_no_param)(int) = &LogNode::set_test_value; + std::string (LogNode::*expr_no_param)() = &LogNode::expr; + Domain (LogNode::*domain_no_param)() = &LogNode::domain; + + class_<LogNode, bases<OperatorNode<1>>>("LogNode", init<node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("set_test_value", set_test_value_no_param, "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .add_property("expr", expr_no_param, "Get the expression for the overall feature (From root node down)") + .add_property("domain", domain_no_param, "The domain for the feature (min/max values)") + .add_property("unit", &LogNode::unit, "Get the unit of the feature (combine the units of _feats)") + .add_property("rung", &LogNode::rung, "return the rung of the feature\nArgs:\n cur_rung: The rung current rung of the feature tree (used to recursively calculate rung)") + ; +} + +void sisso::feature_creation::node::registerExpNode() +{ + void (ExpNode::*set_value_no_param)(int) = &ExpNode::set_value; + void (ExpNode::*set_test_value_no_param)(int) = &ExpNode::set_test_value; + std::string (ExpNode::*expr_no_param)() = &ExpNode::expr; + Domain (ExpNode::*domain_no_param)() = &ExpNode::domain; + + class_<ExpNode, bases<OperatorNode<1>>>("ExpNode", init<node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("set_test_value", set_test_value_no_param, "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .add_property("expr", expr_no_param, "Get the expression for the overall feature (From root node down)") + .add_property("domain", domain_no_param, "The domain for the feature (min/max values)") + .add_property("unit", &ExpNode::unit, "Get the unit of the feature (combine the units of _feats)") + .add_property("rung", &ExpNode::rung, "return the rung of the feature\nArgs:\n cur_rung: The rung current rung of the feature tree (used to recursively calculate rung)") + ; +} + +void sisso::feature_creation::node::registerNegExpNode() +{ + void (NegExpNode::*set_value_no_param)(int) = &NegExpNode::set_value; + void (NegExpNode::*set_test_value_no_param)(int) = &NegExpNode::set_test_value; + std::string (NegExpNode::*expr_no_param)() = &NegExpNode::expr; + Domain (NegExpNode::*domain_no_param)() = &NegExpNode::domain; + + class_<NegExpNode, bases<OperatorNode<1>>>("NegExpNode", init<node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("set_test_value", set_test_value_no_param, "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .add_property("expr", expr_no_param, "Get the expression for the overall feature (From root node down)") + .add_property("domain", domain_no_param, "The domain for the feature (min/max values)") + .add_property("unit", &NegExpNode::unit, "Get the unit of the feature (combine the units of _feats)") + .add_property("rung", &NegExpNode::rung, "return the rung of the feature\nArgs:\n cur_rung: The rung current rung of the feature tree (used to recursively calculate rung)") + ; +} + +void sisso::feature_creation::node::registerSinNode() +{ + void (SinNode::*set_value_no_param)(int) = &SinNode::set_value; + void (SinNode::*set_test_value_no_param)(int) = &SinNode::set_test_value; + std::string (SinNode::*expr_no_param)() = &SinNode::expr; + Domain (SinNode::*domain_no_param)() = &SinNode::domain; + + class_<SinNode, bases<OperatorNode<1>>>("SinNode", init<node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("set_test_value", set_test_value_no_param, "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .add_property("expr", expr_no_param, "Get the expression for the overall feature (From root node down)") + .add_property("domain", domain_no_param, "The domain for the feature (min/max values)") + .add_property("unit", &SinNode::unit, "Get the unit of the feature (combine the units of _feats)") + .add_property("rung", &SinNode::rung, "return the rung of the feature\nArgs:\n cur_rung: The rung current rung of the feature tree (used to recursively calculate rung)") + ; +} + +void sisso::feature_creation::node::registerCosNode() +{ + void (CosNode::*set_value_no_param)(int) = &CosNode::set_value; + void (CosNode::*set_test_value_no_param)(int) = &CosNode::set_test_value; + std::string (CosNode::*expr_no_param)() = &CosNode::expr; + Domain (CosNode::*domain_no_param)() = &CosNode::domain; + + class_<CosNode, bases<OperatorNode<1>>>("CosNode", init<node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("set_test_value", set_test_value_no_param, "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .add_property("expr", expr_no_param, "Get the expression for the overall feature (From root node down)") + .add_property("domain", domain_no_param, "The domain for the feature (min/max values)") + .add_property("unit", &CosNode::unit, "Get the unit of the feature (combine the units of _feats)") + .add_property("rung", &CosNode::rung, "return the rung of the feature\nArgs:\n cur_rung: The rung current rung of the feature tree (used to recursively calculate rung)") + ; +} + +void sisso::feature_creation::node::registerCbNode() +{ + void (CbNode::*set_value_no_param)(int) = &CbNode::set_value; + void (CbNode::*set_test_value_no_param)(int) = &CbNode::set_test_value; + std::string (CbNode::*expr_no_param)() = &CbNode::expr; + Domain (CbNode::*domain_no_param)() = &CbNode::domain; + + class_<CbNode, bases<OperatorNode<1>>>("CbNode", init<node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("set_test_value", set_test_value_no_param, "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .add_property("expr", expr_no_param, "Get the expression for the overall feature (From root node down)") + .add_property("domain", domain_no_param, "The domain for the feature (min/max values)") + .add_property("unit", &CbNode::unit, "Get the unit of the feature (combine the units of _feats)") + .add_property("rung", &CbNode::rung, "return the rung of the feature\nArgs:\n cur_rung: The rung current rung of the feature tree (used to recursively calculate rung)") + ; +} + +void sisso::feature_creation::node::registerCbrtNode() +{ + void (CbrtNode::*set_value_no_param)(int) = &CbrtNode::set_value; + void (CbrtNode::*set_test_value_no_param)(int) = &CbrtNode::set_test_value; + std::string (CbrtNode::*expr_no_param)() = &CbrtNode::expr; + Domain (CbrtNode::*domain_no_param)() = &CbrtNode::domain; + + class_<CbrtNode, bases<OperatorNode<1>>>("CbrtNode", init<node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("set_test_value", set_test_value_no_param, "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .add_property("expr", expr_no_param, "Get the expression for the overall feature (From root node down)") + .add_property("domain", domain_no_param, "The domain for the feature (min/max values)") + .add_property("unit", &CbrtNode::unit, "Get the unit of the feature (combine the units of _feats)") + .add_property("rung", &CbrtNode::rung, "return the rung of the feature\nArgs:\n cur_rung: The rung current rung of the feature tree (used to recursively calculate rung)") + ; +} + +void sisso::feature_creation::node::registerSqNode() +{ + void (SqNode::*set_value_no_param)(int) = &SqNode::set_value; + void (SqNode::*set_test_value_no_param)(int) = &SqNode::set_test_value; + std::string (SqNode::*expr_no_param)() = &SqNode::expr; + Domain (SqNode::*domain_no_param)() = &SqNode::domain; + + class_<SqNode, bases<OperatorNode<1>>>("SqNode", init<node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("set_test_value", set_test_value_no_param, "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .add_property("expr", expr_no_param, "Get the expression for the overall feature (From root node down)") + .add_property("domain", domain_no_param, "The domain for the feature (min/max values)") + .add_property("unit", &SqNode::unit, "Get the unit of the feature (combine the units of _feats)") + .add_property("rung", &SqNode::rung, "return the rung of the feature\nArgs:\n cur_rung: The rung current rung of the feature tree (used to recursively calculate rung)") + ; +} + +void sisso::feature_creation::node::registerSqrtNode() +{ + void (SqrtNode::*set_value_no_param)(int) = &SqrtNode::set_value; + void (SqrtNode::*set_test_value_no_param)(int) = &SqrtNode::set_test_value; + std::string (SqrtNode::*expr_no_param)() = &SqrtNode::expr; + Domain (SqrtNode::*domain_no_param)() = &SqrtNode::domain; + + class_<SqrtNode, bases<OperatorNode<1>>>("SqrtNode", init<node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("set_test_value", set_test_value_no_param, "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .add_property("expr", expr_no_param, "Get the expression for the overall feature (From root node down)") + .add_property("domain", domain_no_param, "The domain for the feature (min/max values)") + .add_property("unit", &SqrtNode::unit, "Get the unit of the feature (combine the units of _feats)") + .add_property("rung", &SqrtNode::rung, "return the rung of the feature\nArgs:\n cur_rung: The rung current rung of the feature tree (used to recursively calculate rung)") + ; +} + +void sisso::feature_creation::node::registerSixPowNode() +{ + void (SixPowNode::*set_value_no_param)(int) = &SixPowNode::set_value; + void (SixPowNode::*set_test_value_no_param)(int) = &SixPowNode::set_test_value; + std::string (SixPowNode::*expr_no_param)() = &SixPowNode::expr; + Domain (SixPowNode::*domain_no_param)() = &SixPowNode::domain; + + class_<SixPowNode, bases<OperatorNode<1>>>("SixPowNode", init<node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("set_test_value", set_test_value_no_param, "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .add_property("expr", expr_no_param, "Get the expression for the overall feature (From root node down)") + .add_property("domain", domain_no_param, "The domain for the feature (min/max values)") + .add_property("unit", &SixPowNode::unit, "Get the unit of the feature (combine the units of _feats)") + .add_property("rung", &SixPowNode::rung, "return the rung of the feature\nArgs:\n cur_rung: The rung current rung of the feature tree (used to recursively calculate rung)") + ; +} + +void sisso::feature_creation::node::registerAddParamNode() +{ + void (AddParamNode::*set_value_no_param)(int) = &AddParamNode::set_value; + void (AddParamNode::*set_test_value_no_param)(int) = &AddParamNode::set_test_value; + std::string (AddParamNode::*expr_no_param)() = &AddParamNode::expr; + Domain (AddParamNode::*domain_no_param)() = &AddParamNode::domain; + + class_<AddParamNode, bases<AddNode>>("AddParamNode", init<node_ptr, node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("set_test_value", set_test_value_no_param, "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .add_property("expr", expr_no_param, "Get the expression for the overall feature (From root node down)") + .add_property("domain", domain_no_param, "The domain for the feature (min/max values)") + .add_property("unit", &AddParamNode::unit, "") + .add_property("rung", &AddParamNode::rung, "") + ; +} + +void sisso::feature_creation::node::registerSubParamNode() +{ + void (SubParamNode::*set_value_no_param)(int) = &SubParamNode::set_value; + void (SubParamNode::*set_test_value_no_param)(int) = &SubParamNode::set_test_value; + std::string (SubParamNode::*expr_no_param)() = &SubParamNode::expr; + Domain (SubParamNode::*domain_no_param)() = &SubParamNode::domain; + + class_<SubParamNode, bases<SubNode>>("SubNode", init<node_ptr, node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("set_test_value", set_test_value_no_param, "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .add_property("expr", expr_no_param, "Get the expression for the overall feature (From root node down)") + .add_property("domain", domain_no_param, "The domain for the feature (min/max values)") + .add_property("unit", &SubParamNode::unit, "") + .add_property("rung", &SubParamNode::rung, "") + ; +} + +void sisso::feature_creation::node::registerDivParamNode() +{ + void (DivParamNode::*set_value_no_param)(int) = &DivParamNode::set_value; + void (DivParamNode::*set_test_value_no_param)(int) = &DivParamNode::set_test_value; + std::string (DivParamNode::*expr_no_param)() = &DivParamNode::expr; + Domain (DivParamNode::*domain_no_param)() = &DivParamNode::domain; + + class_<DivParamNode, bases<DivNode>>("DivNode", init<node_ptr, node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("set_test_value", set_test_value_no_param, "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .add_property("expr", expr_no_param, "Get the expression for the overall feature (From root node down)") + .add_property("domain", domain_no_param, "The domain for the feature (min/max values)") + .add_property("unit", &DivParamNode::unit, "") + .add_property("rung", &DivParamNode::rung, "") + ; +} + +void sisso::feature_creation::node::registerMultParamNode() +{ + void (MultParamNode::*set_value_no_param)(int) = &MultParamNode::set_value; + void (MultParamNode::*set_test_value_no_param)(int) = &MultParamNode::set_test_value; + std::string (MultParamNode::*expr_no_param)() = &MultParamNode::expr; + Domain (MultParamNode::*domain_no_param)() = &MultParamNode::domain; + + class_<MultParamNode, bases<MultNode>>("MultNode", init<node_ptr, node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("set_test_value", set_test_value_no_param, "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .add_property("expr", expr_no_param, "Get the expression for the overall feature (From root node down)") + .add_property("domain", domain_no_param, "The domain for the feature (min/max values)") + .add_property("unit", &MultParamNode::unit, "") + .add_property("rung", &MultParamNode::rung, "") + ; +} + +void sisso::feature_creation::node::registerAbsDiffParamNode() +{ + void (AbsDiffParamNode::*set_value_no_param)(int) = &AbsDiffParamNode::set_value; + void (AbsDiffParamNode::*set_test_value_no_param)(int) = &AbsDiffParamNode::set_test_value; + std::string (AbsDiffParamNode::*expr_no_param)() = &AbsDiffParamNode::expr; + Domain (AbsDiffParamNode::*domain_no_param)() = &AbsDiffParamNode::domain; + + class_<AbsDiffParamNode, bases<AbsDiffNode>>("AbsDiffNode", init<node_ptr, node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("set_test_value", set_test_value_no_param, "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .add_property("expr", expr_no_param, "Get the expression for the overall feature (From root node down)") + .add_property("domain", domain_no_param, "The domain for the feature (min/max values)") + .add_property("unit", &AbsDiffParamNode::unit, "") + .add_property("rung", &AbsDiffParamNode::rung, "") + ; +} + +void sisso::feature_creation::node::registerAbsParamNode() +{ + void (AbsParamNode::*set_value_no_param)(int) = &AbsParamNode::set_value; + void (AbsParamNode::*set_test_value_no_param)(int) = &AbsParamNode::set_test_value; + std::string (AbsParamNode::*expr_no_param)() = &AbsParamNode::expr; + Domain (AbsParamNode::*domain_no_param)() = &AbsParamNode::domain; + + class_<AbsParamNode, bases<AbsNode>>("AbsNode", init<node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("set_test_value", set_test_value_no_param, "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .add_property("expr", expr_no_param, "Get the expression for the overall feature (From root node down)") + .add_property("domain", domain_no_param, "The domain for the feature (min/max values)") + .add_property("unit", &AbsParamNode::unit, "") + .add_property("rung", &AbsParamNode::rung, "") + ; +} + +void sisso::feature_creation::node::registerInvParamNode() +{ + void (InvParamNode::*set_value_no_param)(int) = &InvParamNode::set_value; + void (InvParamNode::*set_test_value_no_param)(int) = &InvParamNode::set_test_value; + std::string (InvParamNode::*expr_no_param)() = &InvParamNode::expr; + Domain (InvParamNode::*domain_no_param)() = &InvParamNode::domain; + + class_<InvParamNode, bases<InvNode>>("InvNode", init<node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("set_test_value", set_test_value_no_param, "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .add_property("expr", expr_no_param, "Get the expression for the overall feature (From root node down)") + .add_property("domain", domain_no_param, "The domain for the feature (min/max values)") + .add_property("unit", &InvParamNode::unit, "") + .add_property("rung", &InvParamNode::rung, "") + ; +} + +void sisso::feature_creation::node::registerLogParamNode() +{ + void (LogParamNode::*set_value_no_param)(int) = &LogParamNode::set_value; + void (LogParamNode::*set_test_value_no_param)(int) = &LogParamNode::set_test_value; + std::string (LogParamNode::*expr_no_param)() = &LogParamNode::expr; + Domain (LogParamNode::*domain_no_param)() = &LogParamNode::domain; + + class_<LogParamNode, bases<LogNode>>("LogNode", init<node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "") + .def("set_test_value", set_test_value_no_param, "") + .add_property("expr", expr_no_param, "") + .add_property("domain", domain_no_param, "") + .add_property("unit", &LogParamNode::unit, "") + .add_property("rung", &LogParamNode::rung, "") + ; +} + +void sisso::feature_creation::node::registerExpParamNode() +{ + void (ExpParamNode::*set_value_no_param)(int) = &ExpParamNode::set_value; + void (ExpParamNode::*set_test_value_no_param)(int) = &ExpParamNode::set_test_value; + std::string (ExpParamNode::*expr_no_param)() = &ExpParamNode::expr; + Domain (ExpParamNode::*domain_no_param)() = &ExpParamNode::domain; + + class_<ExpParamNode, bases<ExpNode>>("ExpNode", init<node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("set_test_value", set_test_value_no_param, "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .add_property("expr", expr_no_param, "Get the expression for the overall feature (From root node down)") + .add_property("domain", domain_no_param, "The domain for the feature (min/max values)") + .add_property("unit", &ExpParamNode::unit, "") + .add_property("rung", &ExpParamNode::rung, "") + ; +} + +void sisso::feature_creation::node::registerNegExpParamNode() +{ + void (NegExpParamNode::*set_value_no_param)(int) = &NegExpParamNode::set_value; + void (NegExpParamNode::*set_test_value_no_param)(int) = &NegExpParamNode::set_test_value; + std::string (NegExpParamNode::*expr_no_param)() = &NegExpParamNode::expr; + Domain (NegExpParamNode::*domain_no_param)() = &NegExpParamNode::domain; + + class_<NegExpParamNode, bases<NegExpNode>>("NegExpNode", init<node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("set_test_value", set_test_value_no_param, "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .add_property("expr", expr_no_param, "Get the expression for the overall feature (From root node down)") + .add_property("domain", domain_no_param, "The domain for the feature (min/max values)") + .add_property("unit", &NegExpParamNode::unit, "") + .add_property("rung", &NegExpParamNode::rung, "") + ; +} + +void sisso::feature_creation::node::registerSinParamNode() +{ + void (SinParamNode::*set_value_no_param)(int) = &SinParamNode::set_value; + void (SinParamNode::*set_test_value_no_param)(int) = &SinParamNode::set_test_value; + std::string (SinParamNode::*expr_no_param)() = &SinParamNode::expr; + Domain (SinParamNode::*domain_no_param)() = &SinParamNode::domain; + + class_<SinParamNode, bases<SinNode>>("SinParamNode", init<node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("set_test_value", set_test_value_no_param, "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .add_property("expr", expr_no_param, "Get the expression for the overall feature (From root node down)") + .add_property("domain", domain_no_param, "The domain for the feature (min/max values)") + .add_property("unit", &SinParamNode::unit, "") + .add_property("rung", &SinParamNode::rung, "") + ; +} + +void sisso::feature_creation::node::registerCosParamNode() +{ + void (CosParamNode::*set_value_no_param)(int) = &CosParamNode::set_value; + void (CosParamNode::*set_test_value_no_param)(int) = &CosParamNode::set_test_value; + std::string (CosParamNode::*expr_no_param)() = &CosParamNode::expr; + Domain (CosParamNode::*domain_no_param)() = &CosParamNode::domain; + + class_<CosParamNode, bases<CosNode>>("CosParamNode", init<node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("set_test_value", set_test_value_no_param, "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .add_property("expr", expr_no_param, "Get the expression for the overall feature (From root node down)") + .add_property("domain", domain_no_param, "The domain for the feature (min/max values)") + .add_property("unit", &CosParamNode::unit, "") + .add_property("rung", &CosParamNode::rung, "") + ; +} + +void sisso::feature_creation::node::registerCbParamNode() +{ + void (CbParamNode::*set_value_no_param)(int) = &CbParamNode::set_value; + void (CbParamNode::*set_test_value_no_param)(int) = &CbParamNode::set_test_value; + std::string (CbParamNode::*expr_no_param)() = &CbParamNode::expr; + Domain (CbParamNode::*domain_no_param)() = &CbParamNode::domain; + + class_<CbParamNode, bases<CbNode>>("CbParamNode", init<node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("set_test_value", set_test_value_no_param, "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .add_property("expr", expr_no_param, "Get the expression for the overall feature (From root node down)") + .add_property("domain", domain_no_param, "The domain for the feature (min/max values)") + .add_property("unit", &CbParamNode::unit, "") + .add_property("rung", &CbParamNode::rung, "") + ; +} + +void sisso::feature_creation::node::registerCbrtParamNode() +{ + void (CbrtParamNode::*set_value_no_param)(int) = &CbrtParamNode::set_value; + void (CbrtParamNode::*set_test_value_no_param)(int) = &CbrtParamNode::set_test_value; + std::string (CbrtParamNode::*expr_no_param)() = &CbrtParamNode::expr; + Domain (CbrtParamNode::*domain_no_param)() = &CbrtParamNode::domain; + + class_<CbrtParamNode, bases<CbrtNode>>("CbrtParamNode", init<node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("set_test_value", set_test_value_no_param, "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .add_property("expr", expr_no_param, "Get the expression for the overall feature (From root node down)") + .add_property("domain", domain_no_param, "The domain for the feature (min/max values)") + .add_property("unit", &CbrtParamNode::unit, "") + .add_property("rung", &CbrtParamNode::rung, "") + ; +} + +void sisso::feature_creation::node::registerSqParamNode() +{ + void (SqParamNode::*set_value_no_param)(int) = &SqParamNode::set_value; + void (SqParamNode::*set_test_value_no_param)(int) = &SqParamNode::set_test_value; + std::string (SqParamNode::*expr_no_param)() = &SqParamNode::expr; + Domain (SqParamNode::*domain_no_param)() = &SqParamNode::domain; + + class_<SqParamNode, bases<SqNode>>("SqParamNode", init<node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("set_test_value", set_test_value_no_param, "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .add_property("expr", expr_no_param, "Get the expression for the overall feature (From root node down)") + .add_property("domain", domain_no_param, "The domain for the feature (min/max values)") + .add_property("unit", &SqParamNode::unit, "") + .add_property("rung", &SqParamNode::rung, "") + ; +} + +void sisso::feature_creation::node::registerSqrtParamNode() +{ + void (SqrtParamNode::*set_value_no_param)(int) = &SqrtParamNode::set_value; + void (SqrtParamNode::*set_test_value_no_param)(int) = &SqrtParamNode::set_test_value; + std::string (SqrtParamNode::*expr_no_param)() = &SqrtParamNode::expr; + Domain (SqrtParamNode::*domain_no_param)() = &SqrtParamNode::domain; + + class_<SqrtParamNode, bases<SqrtNode>>("SqrtParamNode", init<node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("set_test_value", set_test_value_no_param, "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .add_property("expr", expr_no_param, "Get the expression for the overall feature (From root node down)") + .add_property("domain", domain_no_param, "The domain for the feature (min/max values)") + .add_property("unit", &SqrtParamNode::unit, "") + .add_property("rung", &SqrtParamNode::rung, "") + ; +} + +void sisso::feature_creation::node::registerSixPowParamNode() +{ + void (SixPowParamNode::*set_value_no_param)(int) = &SixPowParamNode::set_value; + void (SixPowParamNode::*set_test_value_no_param)(int) = &SixPowParamNode::set_test_value; + std::string (SixPowParamNode::*expr_no_param)() = &SixPowParamNode::expr; + Domain (SixPowParamNode::*domain_no_param)() = &SixPowParamNode::domain; + + class_<SixPowParamNode, bases<SixPowNode>>("SixPowParamNode", init<node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("set_test_value", set_test_value_no_param, "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .add_property("expr", expr_no_param, "Get the expression for the overall feature (From root node down)") + .add_property("domain", domain_no_param, "The domain for the feature (min/max values)") + .add_property("unit", &SixPowParamNode::unit, "") + .add_property("rung", &SixPowParamNode::rung, "") + ; +} + +void sisso::descriptor_identifier::registerModel() +{ + class_<sisso::descriptor_identifier::Model_Wrap, boost::noncopyable>("Model", no_init) + .add_property("n_samp_train", &Model::n_samp_train, "Total number of samples being trained on") + .add_property("n_samp_test", &Model::n_samp_test, "Total number of samples being tested") + .add_property("n_dim", &Model::n_dim, "The dimensionality of the data") + .add_property("prop_train", &Model::prop_train, "The training data property to be learned\n\nReturns:\n _prop_train as a numpy ndarray") + .add_property("prop_test", &Model::prop_test, "The test values for the property\n\nReturns:\n _prop_test as a numpy ndarray") + .add_property("feats", &Model::feats, "The features of the model\n\nReturns:\n A python list containing all of the features") + .add_property("coefs", &Model::coefs, "The coefficient array for the model\n\nReturns:\n The coefficients as a python list") + .add_property("prop_unit", &Model::prop_unit, "The unit of the property\n\nReturns:\n The unit of the property") + .add_property("task_size_train", &Model::task_sizes_train, "@DocString_model_task_sizes_train") + .add_property("task_size_test", &Model::task_sizes_test, "@DocString_model_task_sizes_test") + .add_property("fix_intercept", &Model::fix_intercept, "@DocString_model_fix_intercept") + ; +} + +void sisso::descriptor_identifier::registerModelRegressor() +{ + class_<ModelRegressor, bases<Model>>("ModelRegressor", init<Unit, std::vector<double>, std::vector<double>, std::vector<model_node_ptr>, std::vector<int>, std::vector<int>, bool>()) + .def(init<std::string>()) + .def(init<std::string, std::string>()) + .def("__str__", &ModelRegressor::toString, "Convert the model to a string") + .def("__repr__", &ModelRegressor::toString, "Convert the model to a string") + .add_property("fit", &ModelRegressor::prop_train_est, "The estimation of the property\n\nReturns:\n _prop_train_est as a numpy ndarray") + .add_property("predict", &ModelRegressor::prop_test_est, "The estimation of the properties test values\n\nReturns:\n _prop_test_est as a numpy ndarray") + .add_property("train_error", &ModelRegressor::train_error, "The training error\n\nReturns:\n _train_error as a numpy ndarray") + .add_property("test_error", &ModelRegressor::test_error, "The test error\n\nReturns:\n _test_error as a numpy ndarray") + .add_property("rmse", &ModelRegressor::rmse, "The training rmse of the model") + .add_property("test_rmse", &ModelRegressor::test_rmse, "The test rmse of the model") + .add_property("max_ae", &ModelRegressor::max_ae, "The max Absolute error of the training data") + .add_property("test_max_ae", &ModelRegressor::test_max_ae, "The max Absolute error of the testing data") + .add_property("mae", &ModelRegressor::mae, "The mean absolute error of the model\n\nReturns:\n The mean absolute error of the training data") + .add_property("test_mae", &ModelRegressor::test_mae, "The mean absolute test error of the model\n\nReturns:\n The mean absolute error of the test data") + .add_property("mape", &ModelRegressor::mape, "The mean absolute error of the model\n\nReturns:\n The mean absolute error of the training data") + .add_property("test_mape", &ModelRegressor::test_mape, "The mean absolute test error of the model\n\nReturns:\n The mean absolute error of the test data") + .add_property("percentile_25_ae", &ModelRegressor::percentile_25_ae, "The mean absolute error of the model\n\nReturns:\n The mean absolute error of the training data") + .add_property("percentile_25_test_ae", &ModelRegressor::percentile_25_test_ae, "") + .add_property("percentile_50_ae", &ModelRegressor::percentile_50_ae, "The mean absolute error of the model\n\nReturns:\n The mean absolute error of the training data") + .add_property("percentile_50_test_ae", &ModelRegressor::percentile_50_test_ae, "") + .add_property("percentile_75_ae", &ModelRegressor::percentile_75_ae, "The mean absolute error of the model\n\nReturns:\n The mean absolute error of the training data") + .add_property("percentile_75_test_ae", &ModelRegressor::percentile_75_test_ae, "") + .add_property("percentile_95_ae", &ModelRegressor::percentile_95_ae, "The mean absolute error of the model\n\nReturns:\n The mean absolute error of the training data") + .add_property("percentile_95_test_ae", &ModelRegressor::percentile_95_ae, "The mean absolute test error of the model\n\nReturns:\n The mean absolute error of the test data") + ; +} + +void sisso::descriptor_identifier::registerModelClassifier() +{ + class_<ModelClassifier, bases<Model>>("ModelClassifier", init<Unit, std::vector<double>, std::vector<double>, std::vector<model_node_ptr>, std::vector<int>, std::vector<int>, bool>()) + .def(init<std::string>()) + .def(init<std::string, std::string>()) + .def(init<ModelClassifier, py::list, np::ndarray, np::ndarray>()) + .def(init<ModelClassifier, np::ndarray, np::ndarray, np::ndarray>()) + .def("__str__", &ModelClassifier::toString, "Convert the model to a string") + .def("__repr__", &ModelClassifier::toString, "Convert the model to a string") + .def("to_file", &ModelClassifier::to_file_py, "Convert the ModelClassifier into an output file\nArgs:\n filename: The name of the file to output to\n train: If true output the training data\n test_inds: The indexes of the test set") + .add_property("fit", &ModelClassifier::prop_train_est, "The estimation of the property\n\nReturns:\n _prop_train_est as a numpy ndarray") + .add_property("predict", &ModelClassifier::prop_test_est, "The estimation of the properties test values\n\nReturns:\n _prop_test_est as a numpy ndarray") + .add_property("train_error", &ModelClassifier::train_error, "The training error\n\nReturns:\n _train_error as a numpy ndarray") + .add_property("test_error", &ModelClassifier::test_error, "The test error\n\nReturns:\n _test_error as a numpy ndarray") + .add_property("percent_error", &ModelClassifier::percent_train_error, "Percent of all training samples misclassified") + .add_property("percent_test_error", &ModelClassifier::percent_test_error, "Percent of all tset samples misclassified") + .add_property("n_convex_overlap_train", &ModelClassifier::n_convex_overlap_train, "") + .add_property("n_convex_overlap_test", &ModelClassifier::n_convex_overlap_test, "") + .add_property("n_svm_misclassified_train", &ModelClassifier::n_svm_misclassified_train, "") + .add_property("n_svm_misclassified_test", &ModelClassifier::n_svm_misclassified_test, "") + ; +} + +void sisso::descriptor_identifier::registerSISSO_DI() +{ + class_<sisso::descriptor_identifier::SISSO_DI_Wrap, boost::noncopyable>("SISSO_DI", no_init) + .add_property("prop", &SISSO_DI::prop_py, "") + .add_property("prop_test", &SISSO_DI::prop_test_py, "") + .add_property("n_samp", &SISSO_DI::n_samp, "") + .add_property("n_dim", &SISSO_DI::n_dim, "") + .add_property("n_residual", &SISSO_DI::n_residual, "") + .add_property("n_models_store", &SISSO_DI::n_models_store, "") + .add_property("feat_space", &SISSO_DI::feat_space, "") + .add_property("task_sizes_train", &SISSO_DI::task_sizes_train, "") + .add_property("task_sizes_test", &SISSO_DI::task_sizes_test, "") + ; +} + +void sisso::descriptor_identifier::registerSISSORegressor() +{ + class_<SISSORegressor, bases<SISSO_DI>>("SISSORegressor", init<std::shared_ptr<FeatureSpace>, Unit, np::ndarray, np::ndarray, py::list, py::list, py::list, int, int, int, optional<bool>>()) + .def("fit", &SISSORegressor::fit, "Perform SISSO to generate the models\nIteratively pefrom SISSO on the Feature space and property until the model dimensionality is equal to _n_dim") + .def(init<std::shared_ptr<FeatureSpace>, Unit, py::list, py::list, py::list, py::list, py::list, int, int, int, optional<bool>>()) + .add_property("models", &SISSORegressor::models_py, "The selected models (cpp definition in <python/descriptor_identifier/SISSO_DI.cpp)\n\nReturns:\n models as a python list") + ; +} + +void sisso::descriptor_identifier::registerSISSOClassifier() +{ + class_<SISSOClassifier, bases<SISSO_DI>>("SISSOClassifier", init<std::shared_ptr<FeatureSpace>, Unit, np::ndarray, np::ndarray, py::list, py::list, py::list, int, int, int>()) + .def(init<std::shared_ptr<FeatureSpace>, Unit, py::list, py::list, py::list, py::list, py::list, int, int, int>()) + .def("fit", &SISSOClassifier::fit, "Perform SISSO to generate the models\nIteratively pefrom SISSO on the Feature space and property until the model dimensionality is equal to _n_dim") + .add_property("models", &SISSOClassifier::models_py, "The selected models (cpp definition in <python/descriptor_identifier/SISSO_DI.cpp)\n\nReturns:\n models as a python list") + ; +} diff --git a/src/python/bindings.hpp b/src/python/bindings.hpp new file mode 100644 index 00000000..42626a88 --- /dev/null +++ b/src/python/bindings.hpp @@ -0,0 +1,378 @@ +/** @file python/bindings.hpp + * @brief Definitions to convert C++ classes into python classes + * + * @author Thomas A. R. Purcell (tpurcell) + * @bug No known bugs. + */ +#ifndef PYTHON_BINDING +#define PYTHON_BINDINGS + +#include <descriptor_identifier/SISSO_DI/SISSO_DI.hpp> +#include <descriptor_identifier/SISSO_DI/SISSORegressor.hpp> +#include <descriptor_identifier/SISSO_DI/SISSOClassifier.hpp> +#include <feature_creation/feature_space/FeatureSpace.hpp> +#include <python/feature_creation/node_utils.hpp> + +namespace py = boost::python; +namespace np = boost::python::numpy; + +namespace sisso +{ + /** + * @brief Register all C++ classes as python classes + * @details [long description] + */ + void register_all(); + + namespace feature_creation + { + static void registerFeatureSpace(); + static void registerDomain(); + static void registerUnit(); + namespace node + { + /** + * @brief struct used wrap a Node object for conversion + */ + struct NodeWrap : Node, py::wrapper<Node> + { + public: + inline std::string expr(){return this->get_override("expr")();} + inline std::string expr(double*){return this->get_override("expr")();} + inline Unit unit(){return this->get_override("unit")();} + inline std::vector<double> value(){return this->get_override("value")();} + inline std::vector<double> test_value(){return this->get_override("test_value")();} + inline void set_value(int offset = -1){this->get_override("set_value")();} + inline void set_test_value(int offset = -1){this->get_override("set_test_value")();} + inline double* value_ptr(int offset = -1){return this->get_override("value_ptr")();} + inline double* test_value_ptr(int offset = -1){return this->get_override("test_value_ptr")();} + inline void set_value(double* params, int offset = -1){this->get_override("set_value")();} + inline void set_test_value(double* params, int offset = -1){this->get_override("set_test_value")();} + inline double* value_ptr(double* params, int offset = -1){return this->get_override("value_ptr")();} + inline double* test_value_ptr(double* params, int offset = -1){return this->get_override("test_value_ptr")();} + inline bool is_nan(){return this->get_override("is_nan")();} + inline bool is_const(){return this->get_override("is_const")();} + inline NODE_TYPE type(){return this->get_override("type")();} + inline int rung(int cur_rung = 0){return this->get_override("rung")();} + inline std::map<int, int> primary_feature_decomp(){return this->get_override("primary_feature_decomp")();} + inline void update_primary_feature_decomp(std::map<int, int>& pf_decomp){this->get_override("update_primary_feature_decomp")();} + inline void update_postfix(std::string& cur_expr){this->get_override("update_postfix")();} + inline std::string get_postfix_term(){return this->get_override("get_postfix_term")();} + inline void update_add_sub_leaves(std::map<std::string, int>& add_sub_leaves, int pl_mn, int& expected_abs_tot){this->get_override("update_add_sub_leaves")();} + inline void update_div_mult_leaves(std::map<std::string, double>& div_mult_leaves, double fact, double& expected_abs_tot){this->get_override("update_div_mult_leaves")();} + inline std::vector<double> parameters(){return this->get_override("parameters")();} + inline void set_parameters(std::vector<double>){this->get_override("set_parameters")();} + inline Domain domain(){return this->get_override("domain")();} + inline Domain domain(double* params){return this->get_override("domain")();} + inline int n_feats(){this->get_override("n_feats");} + inline std::shared_ptr<Node> feat(int ind){this->get_override("feat");} + }; + /** + * @brief struct used wrap an OperatorNode object for conversion + */ + template<int N> + struct OperatorNodeWrap : OperatorNode<N>, py::wrapper<OperatorNode<N>> + { + inline void set_value(int offset = -1){this->get_override("set_value")();} + inline void set_test_value(int offset = -1){this->get_override("set_test_value")();} + inline void set_value(const double* params, int offset = -1){this->get_override("set_value")();} + inline void set_test_value(const double* params, int offset = -1){this->get_override("set_test_value")();} + inline NODE_TYPE type(){return this->get_override("type")();} + inline int rung(int cur_rung = 0){return this->get_override("rung")();} + inline Unit unit(){return this->get_override("unit")();} + inline std::string get_postfix_term(){return this->get_override("get_postfix_term")();} + inline Domain domain(double* params){return this->get_override("domain")();} + inline Domain domain(){return this->get_override("domain")();} + inline std::string expr(double* params){return this->get_override("expr")();} + inline std::string expr(){return this->get_override("expr")();} + inline void update_add_sub_leaves(std::map<std::string, int>& add_sub_leaves, int pl_mn, int& expected_abs_tot){this->get_override("update_add_sub_leaves")();} + inline void update_div_mult_leaves(std::map<std::string, double>& div_mult_leaves, double fact, double& expected_abs_tot){this->get_override("update_div_mult_leaves")();} + inline void get_parameters(std::vector<double>& prop){this->get_override("get_parameters")();} + inline void set_parameters(std::vector<double>){this->get_override("set_parameters")();} + inline std::vector<double> parameters(){return this->get_override("parameters")();} + }; + + /** + * @brief Register the Node for accessing the object via python + */ + static void registerNode(); + + /** + * @brief Register the FeatureNode for accessing the object via python + */ + static void registerFeatureNode(); + + /** + * @brief Register the ModelNode for accessing the object via python + */ + static void registerModelNode(); + + #ifndef PARAMETERIZE + /** + * @brief Register the OperatorNode for accessing the object via python + */ + template<int N> + static void registerOperatorNode() + { + py::class_<OperatorNodeWrap<N>, py::bases<Node>, boost::noncopyable>("OperatorNode") + .def("is_nan", &OperatorNode<N>::is_nan, "Check if the feature contains NaN") + .def("is_const", &OperatorNode<N>::is_const, "Check if feature is constant") + .def("set_value", py::pure_virtual(&OperatorNode<N>::set_value), "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("set_test_value", py::pure_virtual(&OperatorNode<N>::set_test_value), "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("rung", py::pure_virtual(&OperatorNode<N>::rung), "return the rung of the feature\nArgs:\n cur_rung: The rung current rung of the feature tree (used to recursively calculate rung)") + .def("expr", py::pure_virtual(&OperatorNode<N>::expr), "Get the expression for the overall feature (From root node down)") + .def("unit", py::pure_virtual(&OperatorNode<N>::unit), "Get the unit of the feature (combine the units of _feats)") + .def("domain", pure_virtual(&OperatorNode<N>::domain), "The domain for the feature (min/max values)") + .add_property("n_feats", &OperatorNode<N>::n_feats, "") + .add_property("feat", &OperatorNode<N>::feat, "") + ; + } + #else + /** + * @brief Register the OperatorNode for accessing the object via python + */ + template<int N> + static void registerOperatorNode() + { + void (OperatorNode<N>::*get_parameters_list)(py::list) = &OperatorNode<N>::get_parameters; + void (OperatorNode<N>::*get_parameters_arr)(np::ndarray) = &OperatorNode<N>::get_parameters; + void (OperatorNode<N>::*set_params_list)(py::list) = &OperatorNode<N>::set_parameters; + void (OperatorNode<N>::*set_params_arr)(np::ndarray) = &OperatorNode<N>::set_parameters; + py::class_<OperatorNodeWrap<N>, py::bases<Node>, boost::noncopyable>("OperatorNode") + .def("is_nan", &OperatorNode<N>::is_nan, "Check if the feature contains NaN") + .def("is_const", &OperatorNode<N>::is_const, "Check if feature is constant") + // .def("set_value", py::pure_virtual(&OperatorNode<N>::set_value), "Set the values of the training data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + // .def("set_test_value", py::pure_virtual(&OperatorNode<N>::set_test_value), "Set the values of the test data for the feature inside of the value storage arrays\nArgs:\n offset (int): Key to determine which part of the temporary storage array to look into") + .def("rung", py::pure_virtual(&OperatorNode<N>::rung), "return the rung of the feature\nArgs:\n cur_rung: The rung current rung of the feature tree (used to recursively calculate rung)") + // .def("expr", py::pure_virtual(&OperatorNode<N>::expr), "Get the expression for the overall feature (From root node down)") + .def("unit", py::pure_virtual(&OperatorNode<N>::unit), "Get the unit of the feature (combine the units of _feats)") + .def("get_parameters", get_parameters_arr, "Solve the non-linear optimization to set the parameters\nFits the data points from _feats->value_ptr and prop to get the parameters for the feature\nArgs:\n prop: property to fit to get the parameters\n param_list: List describing the parameters to fit") + .def("get_parameters", get_parameters_list, "Solve the non-linear optimization to set the parameters\nFits the data points from _feats->value_ptr and prop to get the parameters for the feature\nArgs:\n prop: property to fit to get the parameters\n param_list: List describing the parameters to fit") + .def("set_parameters", set_params_arr, "Set the non-linear parameters") + .def("set_parameters", set_params_list, "Set the non-linear parameters") + .add_property("n_feats", &OperatorNode<N>::n_feats, "") + .add_property("feat", &OperatorNode<N>::feat, "") + ; + } + #endif + + /** + * @brief Register the AddNode object for conversion to a python object + */ + static void registerAddNode(); + + /** + * @brief Register the SubNode object for conversion to a python object + */ + static void registerSubNode(); + + /** + * @brief Register the DivNode object for conversion to a python object + */ + static void registerDivNode(); + + /** + * @brief Register the MultNode object for conversion to a python object + */ + static void registerMultNode(); + + /** + * @brief Register the AbsDiffNode object for conversion to a python object + */ + static void registerAbsDiffNode(); + + /** + * @brief Register the AbsNode object for conversion to a python object + */ + static void registerAbsNode(); + + /** + * @brief Register the InvNode object for conversion to a python object + */ + static void registerInvNode(); + + /** + * @brief Register the LogNode object for conversion to a python object + */ + static void registerLogNode(); + + /** + * @brief Register the ExpNode object for conversion to a python object + */ + static void registerExpNode(); + + /** + * @brief Register the NegExpNode object for conversion to a python object + */ + static void registerNegExpNode(); + + /** + * @brief Register the SinNode object for conversion to a python object + */ + static void registerSinNode(); + + /** + * @brief Register the CosNode object for conversion to a python object + */ + static void registerCosNode(); + + /** + * @brief Register the CbNode object for conversion to a python object + */ + static void registerCbNode(); + + /** + * @brief Register the CbrtNode object for conversion to a python object + */ + static void registerCbrtNode(); + + /** + * @brief Register the SqNode object for conversion to a python object + */ + static void registerSqNode(); + + /** + * @brief Register the SqrtNode object for conversion to a python object + */ + static void registerSqrtNode(); + + /** + * @brief Register the SixPowNode object for conversion to a python object + */ + static void registerSixPowNode(); + + /** + * @brief Register the AddParamNode object for conversion to a python object + */ + static void registerAddParamNode(); + + /** + * @brief Register the SubParamNode object for conversion to a python object + */ + static void registerSubParamNode(); + + /** + * @brief Register the DivParamNode object for conversion to a python object + */ + static void registerDivParamNode(); + + /** + * @brief Register the MultParamNode object for conversion to a python object + */ + static void registerMultParamNode(); + + /** + * @brief Register the AbsDiffParamNode object for conversion to a python object + */ + static void registerAbsDiffParamNode(); + + /** + * @brief Register the AbsParamNode object for conversion to a python object + */ + static void registerAbsParamNode(); + + /** + * @brief Register the InvParamNode object for conversion to a python object + */ + static void registerInvParamNode(); + + /** + * @brief Register the LogParamNode object for conversion to a python object + */ + static void registerLogParamNode(); + + /** + * @brief Register the ExpParamNode object for conversion to a python object + */ + static void registerExpParamNode(); + + /** + * @brief Register the NegExpParamNode object for conversion to a python object + */ + static void registerNegExpParamNode(); + + /** + * @brief Register the SinParamNode object for conversion to a python object + */ + static void registerSinParamNode(); + + /** + * @brief Register the CosParamNode object for conversion to a python object + */ + static void registerCosParamNode(); + + /** + * @brief Register the CbParamNode object for conversion to a python object + */ + static void registerCbParamNode(); + + /** + * @brief Register the CbrtParamNode object for conversion to a python object + */ + static void registerCbrtParamNode(); + + /** + * @brief Register the SqParamNode object for conversion to a python object + */ + static void registerSqParamNode(); + + /** + * @brief Register the SqrtParamNode object for conversion to a python object + */ + static void registerSqrtParamNode(); + + /** + * @brief Register the SixPowParamNode object for conversion to a python object + */ + static void registerSixPowParamNode(); + + } + } + + namespace descriptor_identifier + { + struct SISSO_DI_Wrap : SISSO_DI, py::wrapper<SISSO_DI> + { + inline void l0_norm(){this->get_override("l0_norm")();} + inline void fit(){this->get_override("fit")();} + }; + + struct Model_Wrap : Model, py::wrapper<Model> + { + inline void to_file(std::string filename, bool train = true, std::vector<int> test_inds = {}){this->get_override("to_file")();} + }; + + /** + * @brief Register the Model object for conversion to a python object + */ + static void registerModel(); + + /** + * @brief Register the Model object for conversion to a python object + */ + static void registerModelRegressor(); + + /** + * @brief Register the Model object for conversion to a python object + */ + static void registerModelClassifier(); + + /** + * @brief Register the SISSORegressor object for conversion to a python object + */ + static void registerSISSO_DI(); + + /** + * @brief Register the SISSORegressor object for conversion to a python object + */ + static void registerSISSORegressor(); + + + /** + * @brief Register the SISSORegressor object for conversion to a python object + */ + static void registerSISSOClassifier(); + } +} + +#endif diff --git a/src/python/bindings_docstring_keyed.cpp b/src/python/bindings_docstring_keyed.cpp index df2e8e86..ebb02370 100644 --- a/src/python/bindings_docstring_keyed.cpp +++ b/src/python/bindings_docstring_keyed.cpp @@ -46,8 +46,8 @@ void sisso::feature_creation::registerFeatureSpace() void (FeatureSpace::*sis_list)(list) = &FeatureSpace::sis; void (FeatureSpace::*sis_ndarray)(np::ndarray) = &FeatureSpace::sis; - class_<FeatureSpace>("FeatureSpace", init<list, list, dict, np::ndarray, list, optional<std::string, int, int, int, int, double, double, double>>()) - .def(init<list, list, dict, list, list, optional<std::string, int, int, int, int, double, double, double>>()) + class_<FeatureSpace>("FeatureSpace", init<list, list, list, np::ndarray, list, optional<std::string, int, int, int, int, double, double, double>>()) + .def(init<list, list, list, list, list, optional<std::string, int, int, int, int, double, double, double>>()) .def(init<std::string, list, list, optional<std::string, int, double>>()) .def("sis", sis_list, "@DocString_feat_space_sis_list@") .def("sis", sis_ndarray, "@DocString_feat_space_sis_arr@") @@ -94,9 +94,6 @@ void sisso::feature_creation::registerUnit() void sisso::feature_creation::registerDomain() { - Domain (Domain::*abs_parameters)(double, double) = &Domain::abs; - Domain (Domain::*abs_bare)() = &Domain::abs; - class_<Domain>("Domain", init<>()) .def(init<std::string>()) .def(init<double, double>()) @@ -105,7 +102,6 @@ void sisso::feature_creation::registerDomain() .def("__str__", &Domain::toString, "@DocString_domain_str@") .def("__repr__", &Domain::toString, "@DocString_domain_str@") .def("__pow__", &Domain::operator^, "@DocString_domain_pow@") - .def("__abs__", abs_bare, "@DocString_domain_abs@") .def("inv", &Domain::inv, "@DocString_domain_inv@") .def("exp", &Domain::exp, "@DocString_domain_exp@") .def("log", &Domain::log, "@DocString_domain_log@") @@ -114,7 +110,7 @@ void sisso::feature_creation::registerDomain() .def("mult", &Domain::mult, "@DocString_domain_mult@") .def("div", &Domain::div, "@DocString_domain_div@") .def("pow", &Domain::pow, "@DocString_domain_pow@") - .def("abs", abs_parameters, "@DocString_domain_abs_parameters@") + .def("abs", &Domain::abs, "@DocString_domain_abs_parameters@") .def("__contains__", &Domain::contains, "@DocString_domain_contains@") .def(self + self) .def(self - self) @@ -140,11 +136,13 @@ void sisso::feature_creation::registerDomain() { void (Node::*reindex_1)(int) = &Node::reindex; void (Node::*reindex_2)(int, int) = &Node::reindex; + // void (Node::*expr_no_param)() = &Node::expr; + class_<sisso::feature_creation::node::NodeWrap, boost::noncopyable>("Node", no_init) .def("reindex", reindex_1, "@DocString_node_reindex_1@") .def("reindex", reindex_2, "@DocString_node_reindex_2@") - .def("__str__", &Node::expr, "@DocString_node_expr@") - .def("__repr__", &Node::expr, "@DocString_node_expr@") + // .def("__str__", expr_no_param, "@DocString_node_expr@") + // .def("__repr__", expr_no_param, "@DocString_node_expr@") .add_property("n_samp", &Node::n_samp, "@DocString_node_n_samp@") .add_property("n_test_samp", &Node::n_test_samp, "@DocString_node_n_test_samp@") .add_property("feat_ind", &Node::feat_ind, "@DocString_node_feat_ind@") @@ -156,11 +154,11 @@ void sisso::feature_creation::registerDomain() .add_property("primary_feat_decomp", &Node::primary_feature_decomp_py, "@DocString_node_primary_feature_decomp@") .add_property("postfix_expr", &Node::postfix_expr, "@DocString_node_postfix_expr@") .add_property("parameters", &Node::parameters_py, "@DocString_node_parameters_py@") - .def("domain", pure_virtual(&Node::domain), "@DocString_node_domain@") - .def("expr", pure_virtual(&Node::expr), "@DocString_node_expr@") + // .def("domain", pure_virtual(&Node::domain), "@DocString_node_domain@") + // .def("expr", pure_virtual(expr_no_param), "@DocString_node_expr@") .def("unit", pure_virtual(&Node::unit), "@DocString_node_unit@") - .def("set_value", pure_virtual(&Node::set_value), "@DocString_node_set_value@") - .def("set_test_value", pure_virtual(&Node::set_test_value), "@DocString_node_set_test_value@") + // .def("set_value", pure_virtual(&Node::set_value), "@DocString_node_set_value@") + // .def("set_test_value", pure_virtual(&Node::set_test_value), "@DocString_node_set_test_value@") .def("is_nan", pure_virtual(&Node::is_nan), "@DocString_node_is_nan@") .def("is_const", pure_virtual(&Node::is_const), "@DocString_node_is_const@") .def("rung", pure_virtual(&Node::rung), "@DocString_node_rung@") @@ -176,8 +174,8 @@ void sisso::feature_creation::registerDomain() class_<sisso::feature_creation::node::NodeWrap, boost::noncopyable>("Node", no_init) .def("reindex", reindex_1, "@DocString_node_reindex_1@") .def("reindex", reindex_2, "@DocString_node_reindex_2@") - .def("__str__", &Node::expr, "@DocString_node_expr@") - .def("__repr__", &Node::expr, "@DocString_node_expr@") + // .def("__str__", &Node::expr, "@DocString_node_expr@") + // .def("__repr__", &Node::expr, "@DocString_node_expr@") .add_property("n_samp", &Node::n_samp, "@DocString_node_n_samp@") .add_property("n_test_samp", &Node::n_test_samp, "@DocString_node_n_test_samp@") .add_property("feat_ind", &Node::feat_ind, "@DocString_node_feat_ind@") @@ -188,10 +186,10 @@ void sisso::feature_creation::registerDomain() .add_property("test_value", &Node::test_value_py, "@DocString_node_test_value_py@") .add_property("primary_feat_decomp", &Node::primary_feature_decomp_py, "@DocString_node_primary_feature_decomp@") .add_property("postfix_expr", &Node::postfix_expr, "@DocString_node_postfix_expr@") - .def("expr", pure_virtual(&Node::expr), "@DocString_node_expr@") + // .def("expr", pure_virtual(&Node::expr), "@DocString_node_expr@") .def("unit", pure_virtual(&Node::unit), "@DocString_node_unit@") - .def("set_value", pure_virtual(&Node::set_value), "@DocString_node_set_value@") - .def("set_test_value", pure_virtual(&Node::set_test_value), "@DocString_node_set_test_value@") + // .def("set_value", pure_virtual(&Node::set_value), "@DocString_node_set_value@") + // .def("set_test_value", pure_virtual(&Node::set_test_value), "@DocString_node_set_test_value@") .def("is_nan", pure_virtual(&Node::is_nan), "@DocString_node_is_nan@") .def("is_const", pure_virtual(&Node::is_const), "@DocString_node_is_const@") .def("rung", pure_virtual(&Node::rung), "@DocString_node_rung@") @@ -205,20 +203,22 @@ void sisso::feature_creation::node::registerFeatureNode() { std::string (FeatureNode::*expr_1)() = &FeatureNode::expr; std::string (FeatureNode::*expr_const)() const = &FeatureNode::expr; + void (FeatureNode::*set_value_no_param)(int) = &FeatureNode::set_value; + void (FeatureNode::*set_test_value_no_param)(int) = &FeatureNode::set_test_value; + Domain (FeatureNode::*domain_no_param)() = &FeatureNode::domain; using namespace boost::python; class_<FeatureNode, bases<Node>>("FeatureNode", init<int, std::string, np::ndarray, np::ndarray, Domain, Unit>()) .def(init<int, std::string, py::list, py::list, Domain, Unit>()) .def("is_nan", &FeatureNode::is_nan, "@DocString_feat_node_is_nan@") .def("is_const", &FeatureNode::is_const, "@DocString_feat_node_is_const@") - .def("set_value", &FeatureNode::set_value, "@DocString_feat_node_set_value@") - .def("set_test_value", &FeatureNode::set_test_value, "@DocString_feat_node_set_test_value@") + .def("set_value", set_value_no_param, "@DocString_feat_node_set_value@") + .def("set_test_value", set_test_value_no_param, "@DocString_feat_node_set_test_value@") .add_property("expr", expr_1, "@DocString_feat_node_expr_1@") .add_property("expr", expr_const, "@DocString_feat_node_expr_const@") - .add_property("domain", &FeatureNode::domain, "@DocString_feat_node_domain@") + .add_property("domain", domain_no_param, "@DocString_feat_node_domain@") .add_property("unit", &FeatureNode::unit, "@DocString_feat_node_unit@") .add_property("rung", &FeatureNode::rung, "@DocString_feat_node_rung@") - .add_property("domain", &FeatureNode::domain, "@DocString_feat_node_domain@") ; } @@ -239,220 +239,579 @@ void sisso::feature_creation::node::registerModelNode() void sisso::feature_creation::node::registerAddNode() { + void (AddNode::*set_value_no_param)(int) = &AddNode::set_value; + void (AddNode::*set_test_value_no_param)(int) = &AddNode::set_test_value; + std::string (AddNode::*expr_no_param)() = &AddNode::expr; + Domain (AddNode::*domain_no_param)() = &AddNode::domain; + class_<AddNode, bases<OperatorNode<2>>>("AddNode", init<node_ptr, node_ptr, int, double, double>()) - .def("set_value", &AddNode::set_value, "@DocString_add_node_set_value@") - .def("set_test_value", &AddNode::set_test_value, "@DocString_add_node_set_test_value@") - .add_property("expr", &AddNode::expr, "@DocString_add_node_expr@") - .add_property("bounds", &AddNode::domain, "@DocString_add_node_domain@") + .def("set_value", set_value_no_param, "@DocString_add_node_set_value@") + .def("set_test_value", set_test_value_no_param, "@DocString_add_node_set_test_value@") + .add_property("expr", expr_no_param, "@DocString_add_node_expr@") + .add_property("domain", domain_no_param, "@DocString_add_node_domain@") .add_property("unit", &AddNode::unit, "@DocString_add_node_unit@") .add_property("rung", &AddNode::rung, "@DocString_add_node_rung@") - .add_property("domain", &AddNode::domain, "@DocString_add_node_domain@") ; } void sisso::feature_creation::node::registerSubNode() { + void (SubNode::*set_value_no_param)(int) = &SubNode::set_value; + void (SubNode::*set_test_value_no_param)(int) = &SubNode::set_test_value; + std::string (SubNode::*expr_no_param)() = &SubNode::expr; + Domain (SubNode::*domain_no_param)() = &SubNode::domain; + class_<SubNode, bases<OperatorNode<2>>>("SubNode", init<node_ptr, node_ptr, int, double, double>()) - .def("set_value", &SubNode::set_value, "@DocString_sub_node_set_value@") - .def("set_test_value", &SubNode::set_test_value, "@DocString_sub_node_set_test_value@") - .add_property("expr", &SubNode::expr, "@DocString_sub_node_expr@") - .add_property("bounds", &SubNode::domain, "@DocString_sub_node_domain@") + .def("set_value", set_value_no_param, "@DocString_sub_node_set_value@") + .def("set_test_value", set_test_value_no_param, "@DocString_sub_node_set_test_value@") + .add_property("expr", expr_no_param, "@DocString_sub_node_expr@") + .add_property("domain", domain_no_param, "@DocString_sub_node_domain@") .add_property("unit", &SubNode::unit, "@DocString_sub_node_unit@") .add_property("rung", &SubNode::rung, "@DocString_sub_node_rung@") - .add_property("domain", &SubNode::domain, "@DocString_sub_node_domain@") ; } void sisso::feature_creation::node::registerDivNode() { + void (DivNode::*set_value_no_param)(int) = &DivNode::set_value; + void (DivNode::*set_test_value_no_param)(int) = &DivNode::set_test_value; + std::string (DivNode::*expr_no_param)() = &DivNode::expr; + Domain (DivNode::*domain_no_param)() = &DivNode::domain; + class_<DivNode, bases<OperatorNode<2>>>("DivNode", init<node_ptr, node_ptr, int, double, double>()) - .def("set_value", &DivNode::set_value, "@DocString_div_node_set_value@") - .def("set_test_value", &DivNode::set_test_value, "@DocString_div_node_set_test_value@") - .add_property("expr", &DivNode::expr, "@DocString_div_node_expr@") - .add_property("bounds", &DivNode::domain, "@DocString_div_node_domain@") + .def("set_value", set_value_no_param, "@DocString_div_node_set_value@") + .def("set_test_value", set_test_value_no_param, "@DocString_div_node_set_test_value@") + .add_property("expr", expr_no_param, "@DocString_div_node_expr@") + .add_property("domain", domain_no_param, "@DocString_div_node_domain@") .add_property("unit", &DivNode::unit, "@DocString_div_node_unit@") .add_property("rung", &DivNode::rung, "@DocString_div_node_rung@") - .add_property("domain", &DivNode::domain, "@DocString_div_node_domain@") ; } void sisso::feature_creation::node::registerMultNode() { + void (MultNode::*set_value_no_param)(int) = &MultNode::set_value; + void (MultNode::*set_test_value_no_param)(int) = &MultNode::set_test_value; + std::string (MultNode::*expr_no_param)() = &MultNode::expr; + Domain (MultNode::*domain_no_param)() = &MultNode::domain; + class_<MultNode, bases<OperatorNode<2>>>("MultNode", init<node_ptr, node_ptr, int, double, double>()) - .def("set_value", &MultNode::set_value, "@DocString_mult_node_set_value@") - .def("set_test_value", &MultNode::set_test_value, "@DocString_mult_node_set_test_value@") - .add_property("expr", &MultNode::expr, "@DocString_mult_node_expr@") - .add_property("bounds", &MultNode::domain, "@DocString_mult_node_domain@") + .def("set_value", set_value_no_param, "@DocString_mult_node_set_value@") + .def("set_test_value", set_test_value_no_param, "@DocString_mult_node_set_test_value@") + .add_property("expr", expr_no_param, "@DocString_mult_node_expr@") + .add_property("domain", domain_no_param, "@DocString_mult_node_domain@") .add_property("unit", &MultNode::unit, "@DocString_mult_node_unit@") .add_property("rung", &MultNode::rung, "@DocString_mult_node_rung@") - .add_property("domain", &MultNode::domain, "@DocString_mult_node_domain@") ; } void sisso::feature_creation::node::registerAbsDiffNode() { + void (AbsDiffNode::*set_value_no_param)(int) = &AbsDiffNode::set_value; + void (AbsDiffNode::*set_test_value_no_param)(int) = &AbsDiffNode::set_test_value; + std::string (AbsDiffNode::*expr_no_param)() = &AbsDiffNode::expr; + Domain (AbsDiffNode::*domain_no_param)() = &AbsDiffNode::domain; + class_<AbsDiffNode, bases<OperatorNode<2>>>("AbsDiffNode", init<node_ptr, node_ptr, int, double, double>()) - .def("set_value", &AbsDiffNode::set_value, "@DocString_abs_diff_node_set_value@") - .def("set_test_value", &AbsDiffNode::set_test_value, "@DocString_abs_diff_node_set_test_value@") - .add_property("expr", &AbsDiffNode::expr, "@DocString_abs_diff_node_expr@") - .add_property("bounds", &AbsDiffNode::domain, "@DocString_abs_diff_node_domain@") + .def("set_value", set_value_no_param, "@DocString_abs_diff_node_set_value@") + .def("set_test_value", set_test_value_no_param, "@DocString_abs_diff_node_set_test_value@") + .add_property("expr", expr_no_param, "@DocString_abs_diff_node_expr@") + .add_property("domain", domain_no_param, "@DocString_abs_diff_node_domain@") .add_property("unit", &AbsDiffNode::unit, "@DocString_abs_diff_node_unit@") .add_property("rung", &AbsDiffNode::rung, "@DocString_abs_diff_node_rung@") - .add_property("domain", &AbsDiffNode::domain, "@DocString_abs_diff_node_domain@") ; } void sisso::feature_creation::node::registerAbsNode() { + void (AbsNode::*set_value_no_param)(int) = &AbsNode::set_value; + void (AbsNode::*set_test_value_no_param)(int) = &AbsNode::set_test_value; + std::string (AbsNode::*expr_no_param)() = &AbsNode::expr; + Domain (AbsNode::*domain_no_param)() = &AbsNode::domain; + class_<AbsNode, bases<OperatorNode<1>>>("AbsNode", init<node_ptr, int, double, double>()) - .def("set_value", &AbsNode::set_value, "@DocString_abs_node_set_value@") - .def("set_test_value", &AbsNode::set_test_value, "@DocString_abs_node_set_test_value@") - .add_property("expr", &AbsNode::expr, "@DocString_abs_node_expr@") - .add_property("bounds", &AbsNode::domain, "@DocString_abs_node_domain@") + .def("set_value", set_value_no_param, "@DocString_abs_node_set_value@") + .def("set_test_value", set_test_value_no_param, "@DocString_abs_node_set_test_value@") + .add_property("expr", expr_no_param, "@DocString_abs_node_expr@") + .add_property("domain", domain_no_param, "@DocString_abs_node_domain@") .add_property("unit", &AbsNode::unit, "@DocString_abs_node_unit@") .add_property("rung", &AbsNode::rung, "@DocString_abs_node_rung@") - .add_property("domain", &AbsNode::domain, "@DocString_abs_node_domain@") ; } void sisso::feature_creation::node::registerInvNode() { + void (InvNode::*set_value_no_param)(int) = &InvNode::set_value; + void (InvNode::*set_test_value_no_param)(int) = &InvNode::set_test_value; + std::string (InvNode::*expr_no_param)() = &InvNode::expr; + Domain (InvNode::*domain_no_param)() = &InvNode::domain; + class_<InvNode, bases<OperatorNode<1>>>("InvNode", init<node_ptr, int, double, double>()) - .def("set_value", &InvNode::set_value, "@DocString_inv_node_set_value@") - .def("set_test_value", &InvNode::set_test_value, "@DocString_inv_node_set_test_value@") - .add_property("expr", &InvNode::expr, "@DocString_inv_node_expr@") - .add_property("bounds", &InvNode::domain, "@DocString_inv_node_domain@") + .def("set_value", set_value_no_param, "@DocString_inv_node_set_value@") + .def("set_test_value", set_test_value_no_param, "@DocString_inv_node_set_test_value@") + .add_property("expr", expr_no_param, "@DocString_inv_node_expr@") + .add_property("domain", domain_no_param, "@DocString_inv_node_domain@") .add_property("unit", &InvNode::unit, "@DocString_inv_node_unit@") .add_property("rung", &InvNode::rung, "@DocString_inv_node_rung@") - .add_property("domain", &InvNode::domain, "@DocString_inv_node_domain@") ; } void sisso::feature_creation::node::registerLogNode() { + void (LogNode::*set_value_no_param)(int) = &LogNode::set_value; + void (LogNode::*set_test_value_no_param)(int) = &LogNode::set_test_value; + std::string (LogNode::*expr_no_param)() = &LogNode::expr; + Domain (LogNode::*domain_no_param)() = &LogNode::domain; + class_<LogNode, bases<OperatorNode<1>>>("LogNode", init<node_ptr, int, double, double>()) - .def("set_value", &LogNode::set_value, "@DocString_log_node_set_value@") - .def("set_test_value", &LogNode::set_test_value, "@DocString_log_node_set_test_value@") - .add_property("expr", &LogNode::expr, "@DocString_log_node_expr@") - .add_property("bounds", &LogNode::domain, "@DocString_log_node_domain@") + .def("set_value", set_value_no_param, "@DocString_log_node_set_value@") + .def("set_test_value", set_test_value_no_param, "@DocString_log_node_set_test_value@") + .add_property("expr", expr_no_param, "@DocString_log_node_expr@") + .add_property("domain", domain_no_param, "@DocString_log_node_domain@") .add_property("unit", &LogNode::unit, "@DocString_log_node_unit@") .add_property("rung", &LogNode::rung, "@DocString_log_node_rung@") - .add_property("domain", &LogNode::domain, "@DocString_log_node_domain@") ; } void sisso::feature_creation::node::registerExpNode() { + void (ExpNode::*set_value_no_param)(int) = &ExpNode::set_value; + void (ExpNode::*set_test_value_no_param)(int) = &ExpNode::set_test_value; + std::string (ExpNode::*expr_no_param)() = &ExpNode::expr; + Domain (ExpNode::*domain_no_param)() = &ExpNode::domain; + class_<ExpNode, bases<OperatorNode<1>>>("ExpNode", init<node_ptr, int, double, double>()) - .def("set_value", &ExpNode::set_value, "@DocString_exp_node_set_value@") - .def("set_test_value", &ExpNode::set_test_value, "@DocString_exp_node_set_test_value@") - .add_property("expr", &ExpNode::expr, "@DocString_exp_node_expr@") - .add_property("bounds", &ExpNode::domain, "@DocString_exp_node_domain@") + .def("set_value", set_value_no_param, "@DocString_exp_node_set_value@") + .def("set_test_value", set_test_value_no_param, "@DocString_exp_node_set_test_value@") + .add_property("expr", expr_no_param, "@DocString_exp_node_expr@") + .add_property("domain", domain_no_param, "@DocString_exp_node_domain@") .add_property("unit", &ExpNode::unit, "@DocString_exp_node_unit@") .add_property("rung", &ExpNode::rung, "@DocString_exp_node_rung@") - .add_property("domain", &ExpNode::domain, "@DocString_exp_node_domain@") ; } void sisso::feature_creation::node::registerNegExpNode() { + void (NegExpNode::*set_value_no_param)(int) = &NegExpNode::set_value; + void (NegExpNode::*set_test_value_no_param)(int) = &NegExpNode::set_test_value; + std::string (NegExpNode::*expr_no_param)() = &NegExpNode::expr; + Domain (NegExpNode::*domain_no_param)() = &NegExpNode::domain; + class_<NegExpNode, bases<OperatorNode<1>>>("NegExpNode", init<node_ptr, int, double, double>()) - .def("set_value", &NegExpNode::set_value, "@DocString_neg_exp_node_set_value@") - .def("set_test_value", &NegExpNode::set_test_value, "@DocString_neg_exp_node_set_test_value@") - .add_property("expr", &NegExpNode::expr, "@DocString_neg_exp_node_expr@") - .add_property("bounds", &NegExpNode::domain, "@DocString_neg_exp_node_domain@") + .def("set_value", set_value_no_param, "@DocString_neg_exp_node_set_value@") + .def("set_test_value", set_test_value_no_param, "@DocString_neg_exp_node_set_test_value@") + .add_property("expr", expr_no_param, "@DocString_neg_exp_node_expr@") + .add_property("domain", domain_no_param, "@DocString_neg_exp_node_domain@") .add_property("unit", &NegExpNode::unit, "@DocString_neg_exp_node_unit@") .add_property("rung", &NegExpNode::rung, "@DocString_neg_exp_node_rung@") - .add_property("domain", &NegExpNode::domain, "@DocString_neg_exp_node_domain@") ; } void sisso::feature_creation::node::registerSinNode() { + void (SinNode::*set_value_no_param)(int) = &SinNode::set_value; + void (SinNode::*set_test_value_no_param)(int) = &SinNode::set_test_value; + std::string (SinNode::*expr_no_param)() = &SinNode::expr; + Domain (SinNode::*domain_no_param)() = &SinNode::domain; + class_<SinNode, bases<OperatorNode<1>>>("SinNode", init<node_ptr, int, double, double>()) - .def("set_value", &SinNode::set_value, "@DocString_sin_node_set_value@") - .def("set_test_value", &SinNode::set_test_value, "@DocString_sin_node_set_test_value@") - .add_property("expr", &SinNode::expr, "@DocString_sin_node_expr@") - .add_property("bounds", &SinNode::domain, "@DocString_sin_node_domain@") + .def("set_value", set_value_no_param, "@DocString_sin_node_set_value@") + .def("set_test_value", set_test_value_no_param, "@DocString_sin_node_set_test_value@") + .add_property("expr", expr_no_param, "@DocString_sin_node_expr@") + .add_property("domain", domain_no_param, "@DocString_sin_node_domain@") .add_property("unit", &SinNode::unit, "@DocString_sin_node_unit@") .add_property("rung", &SinNode::rung, "@DocString_sin_node_rung@") - .add_property("domain", &SinNode::domain, "@DocString_sin_node_domain@") ; } void sisso::feature_creation::node::registerCosNode() { + void (CosNode::*set_value_no_param)(int) = &CosNode::set_value; + void (CosNode::*set_test_value_no_param)(int) = &CosNode::set_test_value; + std::string (CosNode::*expr_no_param)() = &CosNode::expr; + Domain (CosNode::*domain_no_param)() = &CosNode::domain; + class_<CosNode, bases<OperatorNode<1>>>("CosNode", init<node_ptr, int, double, double>()) - .def("set_value", &CosNode::set_value, "@DocString_cos_node_set_value@") - .def("set_test_value", &CosNode::set_test_value, "@DocString_cos_node_set_test_value@") - .add_property("expr", &CosNode::expr, "@DocString_cos_node_expr@") - .add_property("bounds", &CosNode::domain, "@DocString_cos_node_domain@") + .def("set_value", set_value_no_param, "@DocString_cos_node_set_value@") + .def("set_test_value", set_test_value_no_param, "@DocString_cos_node_set_test_value@") + .add_property("expr", expr_no_param, "@DocString_cos_node_expr@") + .add_property("domain", domain_no_param, "@DocString_cos_node_domain@") .add_property("unit", &CosNode::unit, "@DocString_cos_node_unit@") .add_property("rung", &CosNode::rung, "@DocString_cos_node_rung@") - .add_property("domain", &CosNode::domain, "@DocString_cos_node_domain@") ; } void sisso::feature_creation::node::registerCbNode() { + void (CbNode::*set_value_no_param)(int) = &CbNode::set_value; + void (CbNode::*set_test_value_no_param)(int) = &CbNode::set_test_value; + std::string (CbNode::*expr_no_param)() = &CbNode::expr; + Domain (CbNode::*domain_no_param)() = &CbNode::domain; + class_<CbNode, bases<OperatorNode<1>>>("CbNode", init<node_ptr, int, double, double>()) - .def("set_value", &CbNode::set_value, "@DocString_cb_node_set_value@") - .def("set_test_value", &CbNode::set_test_value, "@DocString_cb_node_set_test_value@") - .add_property("expr", &CbNode::expr, "@DocString_cb_node_expr@") - .add_property("bounds", &CbNode::domain, "@DocString_cb_node_domain@") + .def("set_value", set_value_no_param, "@DocString_cb_node_set_value@") + .def("set_test_value", set_test_value_no_param, "@DocString_cb_node_set_test_value@") + .add_property("expr", expr_no_param, "@DocString_cb_node_expr@") + .add_property("domain", domain_no_param, "@DocString_cb_node_domain@") .add_property("unit", &CbNode::unit, "@DocString_cb_node_unit@") - .add_property("domain", &CbNode::domain, "@DocString_cb_node_domain@") + .add_property("rung", &CbNode::rung, "@DocString_cb_node_rung@") ; } void sisso::feature_creation::node::registerCbrtNode() { + void (CbrtNode::*set_value_no_param)(int) = &CbrtNode::set_value; + void (CbrtNode::*set_test_value_no_param)(int) = &CbrtNode::set_test_value; + std::string (CbrtNode::*expr_no_param)() = &CbrtNode::expr; + Domain (CbrtNode::*domain_no_param)() = &CbrtNode::domain; + class_<CbrtNode, bases<OperatorNode<1>>>("CbrtNode", init<node_ptr, int, double, double>()) - .def("set_value", &CbrtNode::set_value, "@DocString_cbrt_node_set_value@") - .def("set_test_value", &CbrtNode::set_test_value, "@DocString_cbrt_node_set_test_value@") - .add_property("expr", &CbrtNode::expr, "@DocString_cbrt_node_expr@") - .add_property("bounds", &CbrtNode::domain, "@DocString_cbrt_node_domain@") + .def("set_value", set_value_no_param, "@DocString_cbrt_node_set_value@") + .def("set_test_value", set_test_value_no_param, "@DocString_cbrt_node_set_test_value@") + .add_property("expr", expr_no_param, "@DocString_cbrt_node_expr@") + .add_property("domain", domain_no_param, "@DocString_cbrt_node_domain@") .add_property("unit", &CbrtNode::unit, "@DocString_cbrt_node_unit@") - .add_property("domain", &CbrtNode::domain, "@DocString_cbrt_node_domain@") + .add_property("rung", &CbrtNode::rung, "@DocString_cbrt_node_rung@") ; } void sisso::feature_creation::node::registerSqNode() { + void (SqNode::*set_value_no_param)(int) = &SqNode::set_value; + void (SqNode::*set_test_value_no_param)(int) = &SqNode::set_test_value; + std::string (SqNode::*expr_no_param)() = &SqNode::expr; + Domain (SqNode::*domain_no_param)() = &SqNode::domain; + class_<SqNode, bases<OperatorNode<1>>>("SqNode", init<node_ptr, int, double, double>()) - .def("set_value", &SqNode::set_value, "@DocString_sq_node_set_value@") - .def("set_test_value", &SqNode::set_test_value, "@DocString_sq_node_set_test_value@") - .add_property("expr", &SqNode::expr, "@DocString_sq_node_expr@") - .add_property("bounds", &SqNode::domain, "@DocString_sq_node_domain@") + .def("set_value", set_value_no_param, "@DocString_sq_node_set_value@") + .def("set_test_value", set_test_value_no_param, "@DocString_sq_node_set_test_value@") + .add_property("expr", expr_no_param, "@DocString_sq_node_expr@") + .add_property("domain", domain_no_param, "@DocString_sq_node_domain@") .add_property("unit", &SqNode::unit, "@DocString_sq_node_unit@") .add_property("rung", &SqNode::rung, "@DocString_sq_node_rung@") - .add_property("domain", &SqNode::domain, "@DocString_sq_node_domain@") ; } void sisso::feature_creation::node::registerSqrtNode() { + void (SqrtNode::*set_value_no_param)(int) = &SqrtNode::set_value; + void (SqrtNode::*set_test_value_no_param)(int) = &SqrtNode::set_test_value; + std::string (SqrtNode::*expr_no_param)() = &SqrtNode::expr; + Domain (SqrtNode::*domain_no_param)() = &SqrtNode::domain; + class_<SqrtNode, bases<OperatorNode<1>>>("SqrtNode", init<node_ptr, int, double, double>()) - .def("set_value", &SqrtNode::set_value, "@DocString_sqrt_node_set_value@") - .def("set_test_value", &SqrtNode::set_test_value, "@DocString_sqrt_node_set_test_value@") - .add_property("expr", &SqrtNode::expr, "@DocString_sqrt_node_expr@") - .add_property("bounds", &SqrtNode::domain, "@DocString_sqrt_node_domain@") + .def("set_value", set_value_no_param, "@DocString_sqrt_node_set_value@") + .def("set_test_value", set_test_value_no_param, "@DocString_sqrt_node_set_test_value@") + .add_property("expr", expr_no_param, "@DocString_sqrt_node_expr@") + .add_property("domain", domain_no_param, "@DocString_sqrt_node_domain@") .add_property("unit", &SqrtNode::unit, "@DocString_sqrt_node_unit@") .add_property("rung", &SqrtNode::rung, "@DocString_sqrt_node_rung@") - .add_property("domain", &SqrtNode::domain, "@DocString_sqrt_node_domain@") ; } void sisso::feature_creation::node::registerSixPowNode() { + void (SixPowNode::*set_value_no_param)(int) = &SixPowNode::set_value; + void (SixPowNode::*set_test_value_no_param)(int) = &SixPowNode::set_test_value; + std::string (SixPowNode::*expr_no_param)() = &SixPowNode::expr; + Domain (SixPowNode::*domain_no_param)() = &SixPowNode::domain; + class_<SixPowNode, bases<OperatorNode<1>>>("SixPowNode", init<node_ptr, int, double, double>()) - .def("set_value", &SixPowNode::set_value, "@DocString_six_pow_node_set_value@") - .def("set_test_value", &SixPowNode::set_test_value, "@DocString_six_pow_node_set_test_value@") - .add_property("expr", &SixPowNode::expr, "@DocString_six_pow_node_expr@") - .add_property("bounds", &SixPowNode::domain, "@DocString_six_pow_node_domain@") + .def("set_value", set_value_no_param, "@DocString_six_pow_node_set_value@") + .def("set_test_value", set_test_value_no_param, "@DocString_six_pow_node_set_test_value@") + .add_property("expr", expr_no_param, "@DocString_six_pow_node_expr@") + .add_property("domain", domain_no_param, "@DocString_six_pow_node_domain@") .add_property("unit", &SixPowNode::unit, "@DocString_six_pow_node_unit@") .add_property("rung", &SixPowNode::rung, "@DocString_six_pow_node_rung@") - .add_property("domain", &SixPowNode::domain, "@DocString_six_pow_node_domain@") + ; +} + +void sisso::feature_creation::node::registerAddParamNode() +{ + void (AddParamNode::*set_value_no_param)(int) = &AddParamNode::set_value; + void (AddParamNode::*set_test_value_no_param)(int) = &AddParamNode::set_test_value; + std::string (AddParamNode::*expr_no_param)() = &AddParamNode::expr; + Domain (AddParamNode::*domain_no_param)() = &AddParamNode::domain; + + class_<AddParamNode, bases<AddNode>>("AddParamNode", init<node_ptr, node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "@DocString_add_param_node_set_value@") + .def("set_test_value", set_test_value_no_param, "@DocString_add_param_node_set_test_value@") + .add_property("expr", expr_no_param, "@DocString_add_param_node_expr@") + .add_property("domain", domain_no_param, "@DocString_add_param_node_domain@") + .add_property("unit", &AddParamNode::unit, "@DocString_add_param_node_unit@") + .add_property("rung", &AddParamNode::rung, "@DocString_add_param_node_rung@") + ; +} + +void sisso::feature_creation::node::registerSubParamNode() +{ + void (SubParamNode::*set_value_no_param)(int) = &SubParamNode::set_value; + void (SubParamNode::*set_test_value_no_param)(int) = &SubParamNode::set_test_value; + std::string (SubParamNode::*expr_no_param)() = &SubParamNode::expr; + Domain (SubParamNode::*domain_no_param)() = &SubParamNode::domain; + + class_<SubParamNode, bases<SubNode>>("SubNode", init<node_ptr, node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "@DocString_sub_param_node_set_value@") + .def("set_test_value", set_test_value_no_param, "@DocString_sub_param_node_set_test_value@") + .add_property("expr", expr_no_param, "@DocString_sub_param_node_expr@") + .add_property("domain", domain_no_param, "@DocString_sub_param_node_domain@") + .add_property("unit", &SubParamNode::unit, "@DocString_sub_param_node_unit@") + .add_property("rung", &SubParamNode::rung, "@DocString_sub_param_node_rung@") + ; +} + +void sisso::feature_creation::node::registerDivParamNode() +{ + void (DivParamNode::*set_value_no_param)(int) = &DivParamNode::set_value; + void (DivParamNode::*set_test_value_no_param)(int) = &DivParamNode::set_test_value; + std::string (DivParamNode::*expr_no_param)() = &DivParamNode::expr; + Domain (DivParamNode::*domain_no_param)() = &DivParamNode::domain; + + class_<DivParamNode, bases<DivNode>>("DivNode", init<node_ptr, node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "@DocString_div_param_node_set_value@") + .def("set_test_value", set_test_value_no_param, "@DocString_div_param_node_set_test_value@") + .add_property("expr", expr_no_param, "@DocString_div_param_node_expr@") + .add_property("domain", domain_no_param, "@DocString_div_param_node_domain@") + .add_property("unit", &DivParamNode::unit, "@DocString_div_param_node_unit@") + .add_property("rung", &DivParamNode::rung, "@DocString_div_param_node_rung@") + ; +} + +void sisso::feature_creation::node::registerMultParamNode() +{ + void (MultParamNode::*set_value_no_param)(int) = &MultParamNode::set_value; + void (MultParamNode::*set_test_value_no_param)(int) = &MultParamNode::set_test_value; + std::string (MultParamNode::*expr_no_param)() = &MultParamNode::expr; + Domain (MultParamNode::*domain_no_param)() = &MultParamNode::domain; + + class_<MultParamNode, bases<MultNode>>("MultNode", init<node_ptr, node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "@DocString_mult_param_node_set_value@") + .def("set_test_value", set_test_value_no_param, "@DocString_mult_param_node_set_test_value@") + .add_property("expr", expr_no_param, "@DocString_mult_param_node_expr@") + .add_property("domain", domain_no_param, "@DocString_mult_param_node_domain@") + .add_property("unit", &MultParamNode::unit, "@DocString_mult_param_node_unit@") + .add_property("rung", &MultParamNode::rung, "@DocString_mult_param_node_rung@") + ; +} + +void sisso::feature_creation::node::registerAbsDiffParamNode() +{ + void (AbsDiffParamNode::*set_value_no_param)(int) = &AbsDiffParamNode::set_value; + void (AbsDiffParamNode::*set_test_value_no_param)(int) = &AbsDiffParamNode::set_test_value; + std::string (AbsDiffParamNode::*expr_no_param)() = &AbsDiffParamNode::expr; + Domain (AbsDiffParamNode::*domain_no_param)() = &AbsDiffParamNode::domain; + + class_<AbsDiffParamNode, bases<AbsDiffNode>>("AbsDiffNode", init<node_ptr, node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "@DocString_abs_diff_param_node_set_value@") + .def("set_test_value", set_test_value_no_param, "@DocString_abs_diff_param_node_set_test_value@") + .add_property("expr", expr_no_param, "@DocString_abs_diff_param_node_expr@") + .add_property("domain", domain_no_param, "@DocString_abs_diff_param_node_domain@") + .add_property("unit", &AbsDiffParamNode::unit, "@DocString_abs_diff_param_node_unit@") + .add_property("rung", &AbsDiffParamNode::rung, "@DocString_abs_diff_param_node_rung@") + ; +} + +void sisso::feature_creation::node::registerAbsParamNode() +{ + void (AbsParamNode::*set_value_no_param)(int) = &AbsParamNode::set_value; + void (AbsParamNode::*set_test_value_no_param)(int) = &AbsParamNode::set_test_value; + std::string (AbsParamNode::*expr_no_param)() = &AbsParamNode::expr; + Domain (AbsParamNode::*domain_no_param)() = &AbsParamNode::domain; + + class_<AbsParamNode, bases<AbsNode>>("AbsNode", init<node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "@DocString_abs_param_node_set_value@") + .def("set_test_value", set_test_value_no_param, "@DocString_abs_param_node_set_test_value@") + .add_property("expr", expr_no_param, "@DocString_abs_param_node_expr@") + .add_property("domain", domain_no_param, "@DocString_abs_param_node_domain@") + .add_property("unit", &AbsParamNode::unit, "@DocString_abs_param_node_unit@") + .add_property("rung", &AbsParamNode::rung, "@DocString_abs_param_node_rung@") + ; +} + +void sisso::feature_creation::node::registerInvParamNode() +{ + void (InvParamNode::*set_value_no_param)(int) = &InvParamNode::set_value; + void (InvParamNode::*set_test_value_no_param)(int) = &InvParamNode::set_test_value; + std::string (InvParamNode::*expr_no_param)() = &InvParamNode::expr; + Domain (InvParamNode::*domain_no_param)() = &InvParamNode::domain; + + class_<InvParamNode, bases<InvNode>>("InvNode", init<node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "@DocString_inv_param_node_set_value@") + .def("set_test_value", set_test_value_no_param, "@DocString_inv_param_node_set_test_value@") + .add_property("expr", expr_no_param, "@DocString_inv_param_node_expr@") + .add_property("domain", domain_no_param, "@DocString_inv_param_node_domain@") + .add_property("unit", &InvParamNode::unit, "@DocString_inv_param_node_unit@") + .add_property("rung", &InvParamNode::rung, "@DocString_inv_param_node_rung@") + ; +} + +void sisso::feature_creation::node::registerLogParamNode() +{ + void (LogParamNode::*set_value_no_param)(int) = &LogParamNode::set_value; + void (LogParamNode::*set_test_value_no_param)(int) = &LogParamNode::set_test_value; + std::string (LogParamNode::*expr_no_param)() = &LogParamNode::expr; + Domain (LogParamNode::*domain_no_param)() = &LogParamNode::domain; + + class_<LogParamNode, bases<LogNode>>("LogNode", init<node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "@DocString_log_param_node_set_value@") + .def("set_test_value", set_test_value_no_param, "@DocString_log_param_node_set_test_value@") + .add_property("expr", expr_no_param, "@DocString_log_param_node_expr@") + .add_property("domain", domain_no_param, "@DocString_log_param_node_domain@") + .add_property("unit", &LogParamNode::unit, "@DocString_log_param_node_unit@") + .add_property("rung", &LogParamNode::rung, "@DocString_log_param_node_rung@") + ; +} + +void sisso::feature_creation::node::registerExpParamNode() +{ + void (ExpParamNode::*set_value_no_param)(int) = &ExpParamNode::set_value; + void (ExpParamNode::*set_test_value_no_param)(int) = &ExpParamNode::set_test_value; + std::string (ExpParamNode::*expr_no_param)() = &ExpParamNode::expr; + Domain (ExpParamNode::*domain_no_param)() = &ExpParamNode::domain; + + class_<ExpParamNode, bases<ExpNode>>("ExpNode", init<node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "@DocString_exp_param_node_set_value@") + .def("set_test_value", set_test_value_no_param, "@DocString_exp_param_node_set_test_value@") + .add_property("expr", expr_no_param, "@DocString_exp_param_node_expr@") + .add_property("domain", domain_no_param, "@DocString_exp_param_node_domain@") + .add_property("unit", &ExpParamNode::unit, "@DocString_exp_param_node_unit@") + .add_property("rung", &ExpParamNode::rung, "@DocString_exp_param_node_rung@") + ; +} + +void sisso::feature_creation::node::registerNegExpParamNode() +{ + void (NegExpParamNode::*set_value_no_param)(int) = &NegExpParamNode::set_value; + void (NegExpParamNode::*set_test_value_no_param)(int) = &NegExpParamNode::set_test_value; + std::string (NegExpParamNode::*expr_no_param)() = &NegExpParamNode::expr; + Domain (NegExpParamNode::*domain_no_param)() = &NegExpParamNode::domain; + + class_<NegExpParamNode, bases<NegExpNode>>("NegExpNode", init<node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "@DocString_neg_exp_param_node_set_value@") + .def("set_test_value", set_test_value_no_param, "@DocString_neg_exp_param_node_set_test_value@") + .add_property("expr", expr_no_param, "@DocString_neg_exp_param_node_expr@") + .add_property("domain", domain_no_param, "@DocString_neg_exp_param_node_domain@") + .add_property("unit", &NegExpParamNode::unit, "@DocString_neg_exp_param_node_unit@") + .add_property("rung", &NegExpParamNode::rung, "@DocString_neg_exp_param_node_rung@") + ; +} + +void sisso::feature_creation::node::registerSinParamNode() +{ + void (SinParamNode::*set_value_no_param)(int) = &SinParamNode::set_value; + void (SinParamNode::*set_test_value_no_param)(int) = &SinParamNode::set_test_value; + std::string (SinParamNode::*expr_no_param)() = &SinParamNode::expr; + Domain (SinParamNode::*domain_no_param)() = &SinParamNode::domain; + + class_<SinParamNode, bases<SinNode>>("SinParamNode", init<node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "@DocString_sin_param_node_set_value@") + .def("set_test_value", set_test_value_no_param, "@DocString_sin_param_node_set_test_value@") + .add_property("expr", expr_no_param, "@DocString_sin_param_node_expr@") + .add_property("domain", domain_no_param, "@DocString_sin_param_node_domain@") + .add_property("unit", &SinParamNode::unit, "@DocString_sin_param_node_unit@") + .add_property("rung", &SinParamNode::rung, "@DocString_sin_param_node_rung@") + ; +} + +void sisso::feature_creation::node::registerCosParamNode() +{ + void (CosParamNode::*set_value_no_param)(int) = &CosParamNode::set_value; + void (CosParamNode::*set_test_value_no_param)(int) = &CosParamNode::set_test_value; + std::string (CosParamNode::*expr_no_param)() = &CosParamNode::expr; + Domain (CosParamNode::*domain_no_param)() = &CosParamNode::domain; + + class_<CosParamNode, bases<CosNode>>("CosParamNode", init<node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "@DocString_cos_param_node_set_value@") + .def("set_test_value", set_test_value_no_param, "@DocString_cos_param_node_set_test_value@") + .add_property("expr", expr_no_param, "@DocString_cos_param_node_expr@") + .add_property("domain", domain_no_param, "@DocString_cos_param_node_domain@") + .add_property("unit", &CosParamNode::unit, "@DocString_cos_param_node_unit@") + .add_property("rung", &CosParamNode::rung, "@DocString_cos_param_node_rung@") + ; +} + +void sisso::feature_creation::node::registerCbParamNode() +{ + void (CbParamNode::*set_value_no_param)(int) = &CbParamNode::set_value; + void (CbParamNode::*set_test_value_no_param)(int) = &CbParamNode::set_test_value; + std::string (CbParamNode::*expr_no_param)() = &CbParamNode::expr; + Domain (CbParamNode::*domain_no_param)() = &CbParamNode::domain; + + class_<CbParamNode, bases<CbNode>>("CbParamNode", init<node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "@DocString_cb_param_node_set_value@") + .def("set_test_value", set_test_value_no_param, "@DocString_cb_param_node_set_test_value@") + .add_property("expr", expr_no_param, "@DocString_cb_param_node_expr@") + .add_property("domain", domain_no_param, "@DocString_cb_param_node_domain@") + .add_property("unit", &CbParamNode::unit, "@DocString_cb_param_node_unit@") + .add_property("rung", &CbParamNode::rung, "@DocString_cb_param_node_rung@") + ; +} + +void sisso::feature_creation::node::registerCbrtParamNode() +{ + void (CbrtParamNode::*set_value_no_param)(int) = &CbrtParamNode::set_value; + void (CbrtParamNode::*set_test_value_no_param)(int) = &CbrtParamNode::set_test_value; + std::string (CbrtParamNode::*expr_no_param)() = &CbrtParamNode::expr; + Domain (CbrtParamNode::*domain_no_param)() = &CbrtParamNode::domain; + + class_<CbrtParamNode, bases<CbrtNode>>("CbrtParamNode", init<node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "@DocString_cbrt_param_node_set_value@") + .def("set_test_value", set_test_value_no_param, "@DocString_cbrt_param_node_set_test_value@") + .add_property("expr", expr_no_param, "@DocString_cbrt_param_node_expr@") + .add_property("domain", domain_no_param, "@DocString_cbrt_param_node_domain@") + .add_property("unit", &CbrtParamNode::unit, "@DocString_cbrt_param_node_unit@") + .add_property("rung", &CbrtParamNode::rung, "@DocString_cbrt_param_node_rung@") + ; +} + +void sisso::feature_creation::node::registerSqParamNode() +{ + void (SqParamNode::*set_value_no_param)(int) = &SqParamNode::set_value; + void (SqParamNode::*set_test_value_no_param)(int) = &SqParamNode::set_test_value; + std::string (SqParamNode::*expr_no_param)() = &SqParamNode::expr; + Domain (SqParamNode::*domain_no_param)() = &SqParamNode::domain; + + class_<SqParamNode, bases<SqNode>>("SqParamNode", init<node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "@DocString_sq_param_node_set_value@") + .def("set_test_value", set_test_value_no_param, "@DocString_sq_param_node_set_test_value@") + .add_property("expr", expr_no_param, "@DocString_sq_param_node_expr@") + .add_property("domain", domain_no_param, "@DocString_sq_param_node_domain@") + .add_property("unit", &SqParamNode::unit, "@DocString_sq_param_node_unit@") + .add_property("rung", &SqParamNode::rung, "@DocString_sq_param_node_rung@") + ; +} + +void sisso::feature_creation::node::registerSqrtParamNode() +{ + void (SqrtParamNode::*set_value_no_param)(int) = &SqrtParamNode::set_value; + void (SqrtParamNode::*set_test_value_no_param)(int) = &SqrtParamNode::set_test_value; + std::string (SqrtParamNode::*expr_no_param)() = &SqrtParamNode::expr; + Domain (SqrtParamNode::*domain_no_param)() = &SqrtParamNode::domain; + + class_<SqrtParamNode, bases<SqrtNode>>("SqrtParamNode", init<node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "@DocString_sqrt_param_node_set_value@") + .def("set_test_value", set_test_value_no_param, "@DocString_sqrt_param_node_set_test_value@") + .add_property("expr", expr_no_param, "@DocString_sqrt_param_node_expr@") + .add_property("domain", domain_no_param, "@DocString_sqrt_param_node_domain@") + .add_property("unit", &SqrtParamNode::unit, "@DocString_sqrt_param_node_unit@") + .add_property("rung", &SqrtParamNode::rung, "@DocString_sqrt_param_node_rung@") + ; +} + +void sisso::feature_creation::node::registerSixPowParamNode() +{ + void (SixPowParamNode::*set_value_no_param)(int) = &SixPowParamNode::set_value; + void (SixPowParamNode::*set_test_value_no_param)(int) = &SixPowParamNode::set_test_value; + std::string (SixPowParamNode::*expr_no_param)() = &SixPowParamNode::expr; + Domain (SixPowParamNode::*domain_no_param)() = &SixPowParamNode::domain; + + class_<SixPowParamNode, bases<SixPowNode>>("SixPowParamNode", init<node_ptr, int, double, double>()) + .def("set_value", set_value_no_param, "@DocString_six_pow_param_node_set_value@") + .def("set_test_value", set_test_value_no_param, "@DocString_six_pow_param_node_set_test_value@") + .add_property("expr", expr_no_param, "@DocString_six_pow_param_node_expr@") + .add_property("domain", domain_no_param, "@DocString_six_pow_param_node_domain@") + .add_property("unit", &SixPowParamNode::unit, "@DocString_six_pow_param_node_unit@") + .add_property("rung", &SixPowParamNode::rung, "@DocString_six_pow_param_node_rung@") ; } diff --git a/src/python/bindings_docstring_keyed.hpp b/src/python/bindings_docstring_keyed.hpp index cee337fa..e80f6bb6 100644 --- a/src/python/bindings_docstring_keyed.hpp +++ b/src/python/bindings_docstring_keyed.hpp @@ -38,26 +38,32 @@ namespace sisso { public: inline std::string expr(){return this->get_override("expr")();} + inline std::string expr(double*){return this->get_override("expr")();} inline Unit unit(){return this->get_override("unit")();} inline std::vector<double> value(){return this->get_override("value")();} inline std::vector<double> test_value(){return this->get_override("test_value")();} inline void set_value(int offset = -1){this->get_override("set_value")();} - inline double* value_ptr(int offset = -1){return this->get_override("value_ptr")();} inline void set_test_value(int offset = -1){this->get_override("set_test_value")();} + inline double* value_ptr(int offset = -1){return this->get_override("value_ptr")();} inline double* test_value_ptr(int offset = -1){return this->get_override("test_value_ptr")();} + inline void set_value(double* params, int offset = -1){this->get_override("set_value")();} + inline void set_test_value(double* params, int offset = -1){this->get_override("set_test_value")();} + inline double* value_ptr(double* params, int offset = -1){return this->get_override("value_ptr")();} + inline double* test_value_ptr(double* params, int offset = -1){return this->get_override("test_value_ptr")();} inline bool is_nan(){return this->get_override("is_nan")();} inline bool is_const(){return this->get_override("is_const")();} inline NODE_TYPE type(){return this->get_override("type")();} inline int rung(int cur_rung = 0){return this->get_override("rung")();} inline std::map<int, int> primary_feature_decomp(){return this->get_override("primary_feature_decomp")();} - void update_primary_feature_decomp(std::map<int, int>& pf_decomp){this->get_override("update_primary_feature_decomp")();} - void update_postfix(std::string& cur_expr){this->get_override("update_postfix")();} - std::string get_postfix_term(){return this->get_override("get_postfix_term")();} + inline void update_primary_feature_decomp(std::map<int, int>& pf_decomp){this->get_override("update_primary_feature_decomp")();} + inline void update_postfix(std::string& cur_expr){this->get_override("update_postfix")();} + inline std::string get_postfix_term(){return this->get_override("get_postfix_term")();} inline void update_add_sub_leaves(std::map<std::string, int>& add_sub_leaves, int pl_mn, int& expected_abs_tot){this->get_override("update_add_sub_leaves")();} inline void update_div_mult_leaves(std::map<std::string, double>& div_mult_leaves, double fact, double& expected_abs_tot){this->get_override("update_div_mult_leaves")();} - std::array<double, 2> parameters(){return this->get_override("parameters")();} - void set_parameters(std::array<double, 2>){this->get_override("set_parameters")();} - Domain domain(){return this->get_override("domain")();} + inline std::vector<double> parameters(){return this->get_override("parameters")();} + inline void set_parameters(std::vector<double>){this->get_override("set_parameters")();} + inline Domain domain(){return this->get_override("domain")();} + inline Domain domain(double* params){return this->get_override("domain")();} inline int n_feats(){this->get_override("n_feats");} inline std::shared_ptr<Node> feat(int ind){this->get_override("feat");} }; @@ -69,15 +75,21 @@ namespace sisso { inline void set_value(int offset = -1){this->get_override("set_value")();} inline void set_test_value(int offset = -1){this->get_override("set_test_value")();} + inline void set_value(const double* params, int offset = -1){this->get_override("set_value")();} + inline void set_test_value(const double* params, int offset = -1){this->get_override("set_test_value")();} inline NODE_TYPE type(){return this->get_override("type")();} inline int rung(int cur_rung = 0){return this->get_override("rung")();} - inline std::string expr(){return this->get_override("expr")();} inline Unit unit(){return this->get_override("unit")();} inline std::string get_postfix_term(){return this->get_override("get_postfix_term")();} + inline Domain domain(double* params){return this->get_override("domain")();} + inline Domain domain(){return this->get_override("domain")();} + inline std::string expr(double* params){return this->get_override("expr")();} + inline std::string expr(){return this->get_override("expr")();} inline void update_add_sub_leaves(std::map<std::string, int>& add_sub_leaves, int pl_mn, int& expected_abs_tot){this->get_override("update_add_sub_leaves")();} inline void update_div_mult_leaves(std::map<std::string, double>& div_mult_leaves, double fact, double& expected_abs_tot){this->get_override("update_div_mult_leaves")();} - inline void get_parameters(std::vector<double>& prop, std::vector<std::string>& param_list){this->get_override("get_parameters")();} - Domain domain(){return this->get_override("domain")();} + inline void get_parameters(std::vector<double>& prop){this->get_override("get_parameters")();} + inline void set_parameters(std::vector<double>){this->get_override("set_parameters")();} + inline std::vector<double> parameters(){return this->get_override("parameters")();} }; /** @@ -122,23 +134,22 @@ namespace sisso template<int N> static void registerOperatorNode() { - void (OperatorNode<N>::*get_parameters_list)(py::list, py::list) = &OperatorNode<N>::get_parameters; - void (OperatorNode<N>::*get_parameters_arr)(np::ndarray, py::list) = &OperatorNode<N>::get_parameters; + void (OperatorNode<N>::*get_parameters_list)(py::list) = &OperatorNode<N>::get_parameters; + void (OperatorNode<N>::*get_parameters_arr)(np::ndarray) = &OperatorNode<N>::get_parameters; void (OperatorNode<N>::*set_params_list)(py::list) = &OperatorNode<N>::set_parameters; void (OperatorNode<N>::*set_params_arr)(np::ndarray) = &OperatorNode<N>::set_parameters; py::class_<OperatorNodeWrap<N>, py::bases<Node>, boost::noncopyable>("OperatorNode") .def("is_nan", &OperatorNode<N>::is_nan, "@DocString_op_node_is_nan@") .def("is_const", &OperatorNode<N>::is_const, "@DocString_op_node_is_const@") - .def("set_value", py::pure_virtual(&OperatorNode<N>::set_value), "@DocString_op_node_set_value@") - .def("set_test_value", py::pure_virtual(&OperatorNode<N>::set_test_value), "@DocString_op_node_set_test_value@") + // .def("set_value", py::pure_virtual(&OperatorNode<N>::set_value), "@DocString_op_node_set_value@") + // .def("set_test_value", py::pure_virtual(&OperatorNode<N>::set_test_value), "@DocString_op_node_set_test_value@") .def("rung", py::pure_virtual(&OperatorNode<N>::rung), "@DocString_op_node_rung@") - .def("expr", py::pure_virtual(&OperatorNode<N>::expr), "@DocString_op_node_expr@") + // .def("expr", py::pure_virtual(&OperatorNode<N>::expr), "@DocString_op_node_expr@") .def("unit", py::pure_virtual(&OperatorNode<N>::unit), "@DocString_op_node_unit@") .def("get_parameters", get_parameters_arr, "@DocString_op_node_param_arr@") .def("get_parameters", get_parameters_list, "@DocString_op_node_param_list@") .def("set_parameters", set_params_arr, "@DocString_op_node_set_param_arr@") .def("set_parameters", set_params_list, "@DocString_op_node_set_param_list@") - .def("reset_parameters", &OperatorNode<N>::reset_parameters, "@DocString_op_node_reset_params@") .add_property("n_feats", &OperatorNode<N>::n_feats, "@DocString_op_node_n_feats@") .add_property("feat", &OperatorNode<N>::feat, "@DocString_op_node_feat@") ; @@ -230,6 +241,91 @@ namespace sisso */ static void registerSixPowNode(); + /** + * @brief Register the AddParamNode object for conversion to a python object + */ + static void registerAddParamNode(); + + /** + * @brief Register the SubParamNode object for conversion to a python object + */ + static void registerSubParamNode(); + + /** + * @brief Register the DivParamNode object for conversion to a python object + */ + static void registerDivParamNode(); + + /** + * @brief Register the MultParamNode object for conversion to a python object + */ + static void registerMultParamNode(); + + /** + * @brief Register the AbsDiffParamNode object for conversion to a python object + */ + static void registerAbsDiffParamNode(); + + /** + * @brief Register the AbsParamNode object for conversion to a python object + */ + static void registerAbsParamNode(); + + /** + * @brief Register the InvParamNode object for conversion to a python object + */ + static void registerInvParamNode(); + + /** + * @brief Register the LogParamNode object for conversion to a python object + */ + static void registerLogParamNode(); + + /** + * @brief Register the ExpParamNode object for conversion to a python object + */ + static void registerExpParamNode(); + + /** + * @brief Register the NegExpParamNode object for conversion to a python object + */ + static void registerNegExpParamNode(); + + /** + * @brief Register the SinParamNode object for conversion to a python object + */ + static void registerSinParamNode(); + + /** + * @brief Register the CosParamNode object for conversion to a python object + */ + static void registerCosParamNode(); + + /** + * @brief Register the CbParamNode object for conversion to a python object + */ + static void registerCbParamNode(); + + /** + * @brief Register the CbrtParamNode object for conversion to a python object + */ + static void registerCbrtParamNode(); + + /** + * @brief Register the SqParamNode object for conversion to a python object + */ + static void registerSqParamNode(); + + /** + * @brief Register the SqrtParamNode object for conversion to a python object + */ + static void registerSqrtParamNode(); + + /** + * @brief Register the SixPowParamNode object for conversion to a python object + */ + static void registerSixPowParamNode(); + } } diff --git a/src/python/feature_creation/FeatureSpace.cpp b/src/python/feature_creation/FeatureSpace.cpp index 3c444b0e..d6105c89 100644 --- a/src/python/feature_creation/FeatureSpace.cpp +++ b/src/python/feature_creation/FeatureSpace.cpp @@ -3,7 +3,7 @@ FeatureSpace::FeatureSpace( py::list phi_0, py::list allowed_ops, - py::dict allowed_param_ops, + py::list allowed_param_ops, py::list prop, py::list task_sizes, std::string project_type, @@ -17,6 +17,7 @@ FeatureSpace::FeatureSpace( ): _phi(python_conv_utils::shared_ptr_vec_from_list<Node, FeatureNode>(phi_0)), _phi_0(_phi), + _allowed_param_ops(python_conv_utils::from_list<std::string>(allowed_param_ops)), _allowed_ops(python_conv_utils::from_list<std::string>(allowed_ops)), _prop(python_conv_utils::from_list<double>(prop)), _scores(py::len(phi_0), 0.0), @@ -34,19 +35,14 @@ FeatureSpace::FeatureSpace( _n_rung_store(max_store_rung), _n_rung_generate(n_rung_generate) { - for(int kk = 0; kk < py::len(allowed_param_ops.keys()); ++kk) - { - std::string key = py::extract<std::string>(allowed_param_ops.keys()[kk]); - _allowed_param_ops[key] = python_conv_utils::from_list<std::string>(py::extract<py::list>(allowed_param_ops.values()[kk])); - } _n_samp = _phi_0[0]->n_samp(); - initialize_fs(python_conv_utils::from_list<double>(prop), project_type); + initialize_fs(project_type); } FeatureSpace::FeatureSpace( py::list phi_0, py::list allowed_ops, - py::dict allowed_param_ops, + py::list allowed_param_ops, np::ndarray prop, py::list task_sizes, std::string project_type, @@ -60,6 +56,7 @@ FeatureSpace::FeatureSpace( ): _phi(python_conv_utils::shared_ptr_vec_from_list<Node, FeatureNode>(phi_0)), _phi_0(_phi), + _allowed_param_ops(python_conv_utils::from_list<std::string>(allowed_param_ops)), _allowed_ops(python_conv_utils::from_list<std::string>(allowed_ops)), _prop(python_conv_utils::from_ndarray<double>(prop)), _scores(py::len(phi_0), 0.0), @@ -77,13 +74,8 @@ FeatureSpace::FeatureSpace( _n_rung_store(max_store_rung), _n_rung_generate(n_rung_generate) { - for(int kk = 0; kk < py::len(allowed_param_ops.keys()); ++kk) - { - std::string key = py::extract<std::string>(allowed_param_ops.keys()[kk]); - _allowed_param_ops[key] = python_conv_utils::from_list<std::string>(py::extract<py::list>(allowed_param_ops.values()[kk])); - } _n_samp = _phi_0[0]->n_samp(); - initialize_fs(python_conv_utils::from_ndarray<double>(prop), project_type); + initialize_fs(project_type); } FeatureSpace::FeatureSpace( diff --git a/tests/test_classification/test_classification.py b/tests/test_classification/test_classification.py index f2d8a910..ba1418bc 100644 --- a/tests/test_classification/test_classification.py +++ b/tests/test_classification/test_classification.py @@ -69,13 +69,20 @@ def test_sisso_classifier(): test_data[3][15] = 10.0 phi_0 = [ - FeatureNode(ff, f"feat_{ff}", train_data[ff], test_data[ff], Domain("(-inf, inf)"), Unit()) + FeatureNode( + ff, + f"feat_{ff}", + train_data[ff], + test_data[ff], + Domain("(-inf, inf)"), + Unit(), + ) for ff in range(10) ] op_set = ["add", "sub", "mult", "sq", "cb", "sqrt", "cbrt"] - feat_space = generate_fs(phi_0, prop, [80], op_set, {}, "classification", 1, 10) + feat_space = generate_fs(phi_0, prop, [80], op_set, [], "classification", 1, 10) sisso = SISSOClassifier( feat_space, Unit("m"), prop, prop_test, [80], [20], list(range(10)), 2, 1, 1 ) diff --git a/tests/test_descriptor_identifier/test_regressor.py b/tests/test_descriptor_identifier/test_regressor.py index 17861399..57df9d33 100644 --- a/tests/test_descriptor_identifier/test_regressor.py +++ b/tests/test_descriptor_identifier/test_regressor.py @@ -38,7 +38,7 @@ def test_sisso_regressor(): op_set = ["add", "sub", "mult", "sq", "cb", "sqrt", "cbrt"] - feat_space = generate_fs(phi_0, prop, [90], op_set, {}, "regression", 2, 10) + feat_space = generate_fs(phi_0, prop, [90], op_set, [], "regression", 2, 10) sisso = SISSORegressor( feat_space, diff --git a/tests/test_feature_creation/test_feature_space/test_feature_space.py b/tests/test_feature_creation/test_feature_space/test_feature_space.py index 14889b76..e1cca0af 100644 --- a/tests/test_feature_creation/test_feature_space/test_feature_space.py +++ b/tests/test_feature_creation/test_feature_space/test_feature_space.py @@ -27,7 +27,7 @@ def test_feature_space(): op_set = ["add", "sub", "mult", "sq", "cb", "sqrt", "cbrt"] - feat_space = generate_fs(phi_0, prop, [90], op_set, {}, "regression", 2, 10) + feat_space = generate_fs(phi_0, prop, [90], op_set, [], "regression", 2, 10) feat_space.sis(prop) shutil.rmtree("feature_space/") diff --git a/tests/test_param.py b/tests/test_param.py index 80240375..e2726539 100644 --- a/tests/test_param.py +++ b/tests/test_param.py @@ -10,11 +10,7 @@ def test_param(): df=parent / "data_param.csv", prop_key="Prop", allowed_ops="all", - allowed_param_ops={ - "exp": ["alpha", "a", "c"], - "log": ["alpha", "a", "b"], - "sq": ["a"], - }, + allowed_param_ops=["exp", "log", "sq"], cols="all", max_phi=2, n_sis_select=20, diff --git a/tests/test_sisso.py b/tests/test_sisso.py index 30a10c2b..2b446fdb 100644 --- a/tests/test_sisso.py +++ b/tests/test_sisso.py @@ -10,7 +10,7 @@ def test_sisso(): df=str(parent / "data.csv"), prop_key="Prop", allowed_ops="all", - allowed_param_ops={}, + allowed_param_ops=[], cols="all", max_phi=2, n_sis_select=20, -- GitLab