diff --git a/CMakeLists.txt b/CMakeLists.txt index 5be85b6..db18df1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,8 +68,8 @@ endif (ENABLE_CLANG_TIDY) # -------------------------------------------------- # find_library(BayesNet NAMES libBayesNet BayesNet libBayesNet.a PATHS ${PyClassifiers_SOURCE_DIR}/../lib/lib REQUIRED) # find_path(Bayesnet_INCLUDE_DIRS REQUIRED NAMES bayesnet PATHS ${PyClassifiers_SOURCE_DIR}/../lib/include) -find_library(bayesnet NAMES libbayesnet bayesnet libbayesnet.a PATHS ${Platform_SOURCE_DIR}/../lib/lib REQUIRED) -find_path(Bayesnet_INCLUDE_DIRS REQUIRED NAMES bayesnet PATHS ${Platform_SOURCE_DIR}/../lib/include) +find_library(bayesnet NAMES libbayesnet bayesnet libbayesnet.a PATHS ../lib REQUIRED) +find_path(Bayesnet_INCLUDE_DIRS REQUIRED NAMES bayesnet PATHS ../lib/include) message(STATUS "BayesNet=${bayesnet}") message(STATUS "Bayesnet_INCLUDE_DIRS=${Bayesnet_INCLUDE_DIRS}") @@ -82,9 +82,8 @@ add_subdirectory(pyclfs) # ------- if (ENABLE_TESTING) MESSAGE("Testing enabled") - add_git_submodule(lib/catch2) - add_git_submodule(lib/mdlp) - add_subdirectory(lib/Files) + find_package(Catch2 CONFIG REQUIRED) + find_package(arff-files CONFIG REQUIRED) include(CTest) add_subdirectory(tests) endif (ENABLE_TESTING) @@ -96,4 +95,4 @@ install(TARGETS PyClassifiers LIBRARY DESTINATION lib CONFIGURATIONS Release) install(DIRECTORY pyclfs/ DESTINATION include/pyclassifiers FILES_MATCHING CONFIGURATIONS Release PATTERN "*.h" PATTERN "*.hpp") -install(FILES ${Bayesnet_INCLUDE_DIRS}/bayesnet/config.h DESTINATION include/pyclassifiers CONFIGURATIONS Release) \ No newline at end of file +install(FILES ${Bayesnet_INCLUDE_DIRS}/bayesnet/config.h DESTINATION include/pyclassifiers CONFIGURATIONS Release) diff --git a/Makefile b/Makefile index 61959f1..c02ec3b 100644 --- a/Makefile +++ b/Makefile @@ -52,7 +52,7 @@ debug: ## Build a debug version of the project @echo ">>> Building Debug PyClassifiers..."; @if [ -d ./$(f_debug) ]; then rm -rf ./$(f_debug); fi @mkdir $(f_debug); - @cmake -S . -B $(f_debug) -D CMAKE_BUILD_TYPE=Debug -D ENABLE_TESTING=ON -D CODE_COVERAGE=ON + @cmake -S . -B $(f_debug) -D CMAKE_BUILD_TYPE=Debug -D ENABLE_TESTING=ON -D CODE_COVERAGE=ON -DCMAKE_TOOLCHAIN_FILE=${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake @echo ">>> Done"; release: ## Build a Release version of the project diff --git a/pyclfs/AdaBoost.cc b/pyclfs/AdaBoost.cc new file mode 100644 index 0000000..bf3fedc --- /dev/null +++ b/pyclfs/AdaBoost.cc @@ -0,0 +1,20 @@ +#include "AdaBoost.h" + +namespace pywrap { + AdaBoost::AdaBoost() : PyClassifier("sklearn.ensemble", "AdaBoostClassifier", true) + { + validHyperparameters = { "n_estimators", "n_jobs", "random_state" }; + } + int AdaBoost::getNumberOfEdges() const + { + return callMethodSumOfItems("get_n_leaves"); + } + int AdaBoost::getNumberOfStates() const + { + return callMethodSumOfItems("get_depth"); + } + int AdaBoost::getNumberOfNodes() const + { + return callMethodSumOfItems("node_count"); + } +} /* namespace pywrap */ \ No newline at end of file diff --git a/pyclfs/AdaBoost.h b/pyclfs/AdaBoost.h new file mode 100644 index 0000000..8cc8fb7 --- /dev/null +++ b/pyclfs/AdaBoost.h @@ -0,0 +1,15 @@ +#ifndef ADABOOST_H +#define ADABOOST_H +#include "PyClassifier.h" + +namespace pywrap { + class AdaBoost : public PyClassifier { + public: + AdaBoost(); + ~AdaBoost() = default; + int getNumberOfEdges() const override; + int getNumberOfStates() const override; + int getNumberOfNodes() const override; + }; +} /* namespace pywrap */ +#endif /* ADABOOST_H */ \ No newline at end of file diff --git a/pyclfs/CMakeLists.txt b/pyclfs/CMakeLists.txt index e14ab7c..db171e3 100644 --- a/pyclfs/CMakeLists.txt +++ b/pyclfs/CMakeLists.txt @@ -4,5 +4,5 @@ include_directories( ${PyClassifiers_SOURCE_DIR}/lib/json/include ${Bayesnet_INCLUDE_DIRS} ) -add_library(PyClassifiers ODTE.cc STree.cc SVC.cc RandomForest.cc XGBoost.cc PyClassifier.cc PyWrap.cc) +add_library(PyClassifiers ODTE.cc STree.cc SVC.cc RandomForest.cc XGBoost.cc AdaBoost.cc PyClassifier.cc PyWrap.cc) target_link_libraries(PyClassifiers nlohmann_json::nlohmann_json ${Python3_LIBRARIES} "${TORCH_LIBRARIES}" ${LIBTORCH_PYTHON} Boost::boost Boost::python Boost::numpy) \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 44fd486..79384e3 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -2,9 +2,6 @@ if(ENABLE_TESTING) set(TEST_PYCLASSIFIERS "unit_tests_pyclassifiers") include_directories( ${PyClassifiers_SOURCE_DIR} - ${PyClassifiers_SOURCE_DIR}/lib/Files - ${PyClassifiers_SOURCE_DIR}/lib/mdlp/src - ${PyClassifiers_SOURCE_DIR}/lib/json/include ${Python3_INCLUDE_DIRS} ${TORCH_INCLUDE_DIRS} ${CMAKE_BINARY_DIR}/configured_files/include @@ -13,5 +10,5 @@ if(ENABLE_TESTING) file(GLOB_RECURSE PyClassifiers_SOURCES "${PyClassifiers_SOURCE_DIR}/pyclfs/*.cc") set(TEST_SOURCES_PYCLASSIFIERS TestPythonClassifiers.cc TestUtils.cc ${PyClassifiers_SOURCES}) add_executable(${TEST_PYCLASSIFIERS} ${TEST_SOURCES_PYCLASSIFIERS}) - target_link_libraries(${TEST_PYCLASSIFIERS} PUBLIC "${TORCH_LIBRARIES}" ${Python3_LIBRARIES} ${LIBTORCH_PYTHON} Boost::boost Boost::python Boost::numpy ArffFiles fimdlp Catch2::Catch2WithMain) + target_link_libraries(${TEST_PYCLASSIFIERS} PUBLIC "${TORCH_LIBRARIES}" ${Python3_LIBRARIES} ${LIBTORCH_PYTHON} Boost::boost Boost::python Boost::numpy fimdlp Catch2::Catch2WithMain) endif(ENABLE_TESTING) \ No newline at end of file diff --git a/tests/TestPythonClassifiers.cc b/tests/TestPythonClassifiers.cc index 903f468..0300788 100644 --- a/tests/TestPythonClassifiers.cc +++ b/tests/TestPythonClassifiers.cc @@ -10,14 +10,16 @@ #include "pyclfs/SVC.h" #include "pyclfs/RandomForest.h" #include "pyclfs/XGBoost.h" +#include "pyclfs/AdaBoost.h" #include "pyclfs/ODTE.h" #include "TestUtils.h" +#include TEST_CASE("Test Python Classifiers score", "[PyClassifiers]") { map , float> scores = { // Diabetes - {{"diabetes", "STree"}, 0.81641}, {{"diabetes", "ODTE"}, 0.854166687}, {{"diabetes", "SVC"}, 0.76823}, {{"diabetes", "RandomForest"}, 1.0}, + {{"diabetes", "STree"}, 0.81641}, {{"diabetes", "ODTE"}, 0.856770813f}, {{"diabetes", "SVC"}, 0.76823}, {{"diabetes", "RandomForest"}, 1.0}, // Ecoli {{"ecoli", "STree"}, 0.8125}, {{"ecoli", "ODTE"}, 0.875}, {{"ecoli", "SVC"}, 0.89583}, {{"ecoli", "RandomForest"}, 1.0}, // Glass @@ -35,8 +37,8 @@ TEST_CASE("Test Python Classifiers score", "[PyClassifiers]") map versions = { {"ODTE", "1.0.0-1"}, {"STree", "1.4.0"}, - {"SVC", "1.5.1"}, - {"RandomForest", "1.5.1"} + {"SVC", "1.5.2"}, + {"RandomForest", "1.5.2"} }; auto clf = models[name]; @@ -58,6 +60,15 @@ TEST_CASE("Test Python Classifiers score", "[PyClassifiers]") REQUIRE(clf->getVersion() == versions[name]); } } +TEST_CASE("AdaBoostClassifier", "[PyClassifiers]") +{ + auto raw = RawDatasets("iris", false); + auto clf = pywrap::AdaBoost(); + clf.fit(raw.Xt, raw.yt, raw.featurest, raw.classNamet, raw.statest); + clf.setHyperparameters(nlohmann::json::parse("{ \"n_estimators\": 100 }")); + auto score = clf.score(raw.Xt, raw.yt); + REQUIRE(score == Catch::Approx(0.9599999f).epsilon(raw.epsilon)); +} TEST_CASE("Classifiers features", "[PyClassifiers]") { auto raw = RawDatasets("iris", false); diff --git a/tests/TestUtils.h b/tests/TestUtils.h index 72954c0..238f0c6 100644 --- a/tests/TestUtils.h +++ b/tests/TestUtils.h @@ -5,8 +5,8 @@ #include #include #include -#include "ArffFiles.h" -#include "CPPFImdlp.h" +#include "ArffFiles/ArffFiles.hpp" +#include "fimdlp/CPPFImdlp.h" bool file_exists(const std::string& name); std::pair, map> discretize(std::vector& X, mdlp::labels_t& y, std::vector features); diff --git a/vcpkg.json b/vcpkg.json index d9b7888..14f81e4 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -8,7 +8,7 @@ "libtorch-bin", "folding", "argparse", - "libxlsxwriter" + "catch2" ], "overrides": [ { @@ -36,8 +36,8 @@ "version": "3.2" }, { - "name": "libxlsxwriter", - "version": "1.2.2" + "name": "catch2", + "version": "3.8.1" }, { "name": "nlohmann-json",