From f28465a64f30b98e65f10ed543f379b80601943d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Monta=C3=B1ana?= Date: Fri, 2 Dec 2022 23:25:53 +0100 Subject: [PATCH] Fix some errors in CPPFImdlp --- .gitignore | 3 +- fimdlp/CMakeLists.txt | 183 +++++++++++++++++++++++++ fimdlp/CPPFImdlp.cpp | 86 ++++++------ fimdlp/CPPFImdlp.h | 2 +- fimdlp/Metrics.cpp | 5 +- fimdlp/cppfimdlp.cpython-310-darwin.so | Bin 0 -> 124968 bytes fimdlp/testcpp/CMakeLists.txt | 13 +- fimdlp/testcpp/FImdlp_unittest.cc | 125 ++++++++++++----- sample.py | 34 ++--- 9 files changed, 355 insertions(+), 96 deletions(-) create mode 100644 fimdlp/CMakeLists.txt create mode 100755 fimdlp/cppfimdlp.cpython-310-darwin.so diff --git a/.gitignore b/.gitignore index ceb5580..b3632c1 100644 --- a/.gitignore +++ b/.gitignore @@ -130,4 +130,5 @@ dmypy.json cfimdlp.cpp .vscode/* **/.idea/* - +cmake-build-debug +cmake-build-debug/** diff --git a/fimdlp/CMakeLists.txt b/fimdlp/CMakeLists.txt new file mode 100644 index 0000000..abd9f8d --- /dev/null +++ b/fimdlp/CMakeLists.txt @@ -0,0 +1,183 @@ +cmake_minimum_required(VERSION 3.24) +project(fimdlp) + +set(CMAKE_CXX_STANDARD 14) + +include_directories(.) +include_directories(testcpp/build/_deps/googletest-src/googlemock/include) +include_directories(testcpp/build/_deps/googletest-src/googlemock/include/gmock) +include_directories(testcpp/build/_deps/googletest-src/googlemock/include/gmock/internal) +include_directories(testcpp/build/_deps/googletest-src/googlemock/include/gmock/internal/custom) +include_directories(testcpp/build/_deps/googletest-src/googlemock/test) +include_directories(testcpp/build/_deps/googletest-src/googletest/include) +include_directories(testcpp/build/_deps/googletest-src/googletest/include/gtest) +include_directories(testcpp/build/_deps/googletest-src/googletest/include/gtest/internal) +include_directories(testcpp/build/_deps/googletest-src/googletest/include/gtest/internal/custom) +include_directories(testcpp/build/_deps/googletest-src/googletest/samples) +include_directories(testcpp/build/_deps/googletest-src/googletest/src) +include_directories(testcpp/build/_deps/googletest-src/googletest/test) + +add_executable(fimdlp + testcpp/build/_deps/googletest-src/googlemock/include/gmock/internal/custom/gmock-generated-actions.h + testcpp/build/_deps/googletest-src/googlemock/include/gmock/internal/custom/gmock-matchers.h + testcpp/build/_deps/googletest-src/googlemock/include/gmock/internal/custom/gmock-port.h + testcpp/build/_deps/googletest-src/googlemock/include/gmock/internal/gmock-internal-utils.h + testcpp/build/_deps/googletest-src/googlemock/include/gmock/internal/gmock-port.h + testcpp/build/_deps/googletest-src/googlemock/include/gmock/internal/gmock-pp.h + testcpp/build/_deps/googletest-src/googlemock/include/gmock/gmock-actions.h + testcpp/build/_deps/googletest-src/googlemock/include/gmock/gmock-cardinalities.h + testcpp/build/_deps/googletest-src/googlemock/include/gmock/gmock-function-mocker.h + testcpp/build/_deps/googletest-src/googlemock/include/gmock/gmock-matchers.h + testcpp/build/_deps/googletest-src/googlemock/include/gmock/gmock-more-actions.h + testcpp/build/_deps/googletest-src/googlemock/include/gmock/gmock-more-matchers.h + testcpp/build/_deps/googletest-src/googlemock/include/gmock/gmock-nice-strict.h + testcpp/build/_deps/googletest-src/googlemock/include/gmock/gmock-spec-builders.h + testcpp/build/_deps/googletest-src/googlemock/include/gmock/gmock.h + testcpp/build/_deps/googletest-src/googlemock/src/gmock-all.cc + testcpp/build/_deps/googletest-src/googlemock/src/gmock-cardinalities.cc + testcpp/build/_deps/googletest-src/googlemock/src/gmock-internal-utils.cc + testcpp/build/_deps/googletest-src/googlemock/src/gmock-matchers.cc + testcpp/build/_deps/googletest-src/googlemock/src/gmock-spec-builders.cc + testcpp/build/_deps/googletest-src/googlemock/src/gmock.cc + testcpp/build/_deps/googletest-src/googlemock/src/gmock_main.cc + testcpp/build/_deps/googletest-src/googlemock/test/gmock-actions_test.cc + testcpp/build/_deps/googletest-src/googlemock/test/gmock-cardinalities_test.cc + testcpp/build/_deps/googletest-src/googlemock/test/gmock-function-mocker_test.cc + testcpp/build/_deps/googletest-src/googlemock/test/gmock-internal-utils_test.cc + testcpp/build/_deps/googletest-src/googlemock/test/gmock-matchers-arithmetic_test.cc + testcpp/build/_deps/googletest-src/googlemock/test/gmock-matchers-comparisons_test.cc + testcpp/build/_deps/googletest-src/googlemock/test/gmock-matchers-containers_test.cc + testcpp/build/_deps/googletest-src/googlemock/test/gmock-matchers-misc_test.cc + testcpp/build/_deps/googletest-src/googlemock/test/gmock-matchers_test.h + testcpp/build/_deps/googletest-src/googlemock/test/gmock-more-actions_test.cc + testcpp/build/_deps/googletest-src/googlemock/test/gmock-nice-strict_test.cc + testcpp/build/_deps/googletest-src/googlemock/test/gmock-port_test.cc + testcpp/build/_deps/googletest-src/googlemock/test/gmock-pp-string_test.cc + testcpp/build/_deps/googletest-src/googlemock/test/gmock-pp_test.cc + testcpp/build/_deps/googletest-src/googlemock/test/gmock-spec-builders_test.cc + testcpp/build/_deps/googletest-src/googlemock/test/gmock_all_test.cc + testcpp/build/_deps/googletest-src/googlemock/test/gmock_ex_test.cc + testcpp/build/_deps/googletest-src/googlemock/test/gmock_leak_test_.cc + testcpp/build/_deps/googletest-src/googlemock/test/gmock_link2_test.cc + testcpp/build/_deps/googletest-src/googlemock/test/gmock_link_test.cc + testcpp/build/_deps/googletest-src/googlemock/test/gmock_link_test.h + testcpp/build/_deps/googletest-src/googlemock/test/gmock_output_test_.cc + testcpp/build/_deps/googletest-src/googlemock/test/gmock_stress_test.cc + testcpp/build/_deps/googletest-src/googlemock/test/gmock_test.cc + testcpp/build/_deps/googletest-src/googletest/include/gtest/internal/custom/gtest-port.h + testcpp/build/_deps/googletest-src/googletest/include/gtest/internal/custom/gtest-printers.h + testcpp/build/_deps/googletest-src/googletest/include/gtest/internal/custom/gtest.h + testcpp/build/_deps/googletest-src/googletest/include/gtest/internal/gtest-death-test-internal.h + testcpp/build/_deps/googletest-src/googletest/include/gtest/internal/gtest-filepath.h + testcpp/build/_deps/googletest-src/googletest/include/gtest/internal/gtest-internal.h + testcpp/build/_deps/googletest-src/googletest/include/gtest/internal/gtest-param-util.h + testcpp/build/_deps/googletest-src/googletest/include/gtest/internal/gtest-port-arch.h + testcpp/build/_deps/googletest-src/googletest/include/gtest/internal/gtest-port.h + testcpp/build/_deps/googletest-src/googletest/include/gtest/internal/gtest-string.h + testcpp/build/_deps/googletest-src/googletest/include/gtest/internal/gtest-type-util.h + testcpp/build/_deps/googletest-src/googletest/include/gtest/gtest-assertion-result.h + testcpp/build/_deps/googletest-src/googletest/include/gtest/gtest-death-test.h + testcpp/build/_deps/googletest-src/googletest/include/gtest/gtest-matchers.h + testcpp/build/_deps/googletest-src/googletest/include/gtest/gtest-message.h + testcpp/build/_deps/googletest-src/googletest/include/gtest/gtest-param-test.h + testcpp/build/_deps/googletest-src/googletest/include/gtest/gtest-printers.h + testcpp/build/_deps/googletest-src/googletest/include/gtest/gtest-spi.h + testcpp/build/_deps/googletest-src/googletest/include/gtest/gtest-test-part.h + testcpp/build/_deps/googletest-src/googletest/include/gtest/gtest-typed-test.h + testcpp/build/_deps/googletest-src/googletest/include/gtest/gtest.h + testcpp/build/_deps/googletest-src/googletest/include/gtest/gtest_pred_impl.h + testcpp/build/_deps/googletest-src/googletest/include/gtest/gtest_prod.h + testcpp/build/_deps/googletest-src/googletest/samples/prime_tables.h + testcpp/build/_deps/googletest-src/googletest/samples/sample1.cc + testcpp/build/_deps/googletest-src/googletest/samples/sample1.h + testcpp/build/_deps/googletest-src/googletest/samples/sample10_unittest.cc + testcpp/build/_deps/googletest-src/googletest/samples/sample1_unittest.cc + testcpp/build/_deps/googletest-src/googletest/samples/sample2.cc + testcpp/build/_deps/googletest-src/googletest/samples/sample2.h + testcpp/build/_deps/googletest-src/googletest/samples/sample2_unittest.cc + testcpp/build/_deps/googletest-src/googletest/samples/sample3-inl.h + testcpp/build/_deps/googletest-src/googletest/samples/sample3_unittest.cc + testcpp/build/_deps/googletest-src/googletest/samples/sample4.cc + testcpp/build/_deps/googletest-src/googletest/samples/sample4.h + testcpp/build/_deps/googletest-src/googletest/samples/sample4_unittest.cc + testcpp/build/_deps/googletest-src/googletest/samples/sample5_unittest.cc + testcpp/build/_deps/googletest-src/googletest/samples/sample6_unittest.cc + testcpp/build/_deps/googletest-src/googletest/samples/sample7_unittest.cc + testcpp/build/_deps/googletest-src/googletest/samples/sample8_unittest.cc + testcpp/build/_deps/googletest-src/googletest/samples/sample9_unittest.cc + testcpp/build/_deps/googletest-src/googletest/src/gtest-all.cc + testcpp/build/_deps/googletest-src/googletest/src/gtest-assertion-result.cc + testcpp/build/_deps/googletest-src/googletest/src/gtest-death-test.cc + testcpp/build/_deps/googletest-src/googletest/src/gtest-filepath.cc + testcpp/build/_deps/googletest-src/googletest/src/gtest-internal-inl.h + testcpp/build/_deps/googletest-src/googletest/src/gtest-matchers.cc + testcpp/build/_deps/googletest-src/googletest/src/gtest-port.cc + testcpp/build/_deps/googletest-src/googletest/src/gtest-printers.cc + testcpp/build/_deps/googletest-src/googletest/src/gtest-test-part.cc + testcpp/build/_deps/googletest-src/googletest/src/gtest-typed-test.cc + testcpp/build/_deps/googletest-src/googletest/src/gtest.cc + testcpp/build/_deps/googletest-src/googletest/src/gtest_main.cc + testcpp/build/_deps/googletest-src/googletest/test/googletest-break-on-failure-unittest_.cc + testcpp/build/_deps/googletest-src/googletest/test/googletest-catch-exceptions-test_.cc + testcpp/build/_deps/googletest-src/googletest/test/googletest-color-test_.cc + testcpp/build/_deps/googletest-src/googletest/test/googletest-death-test-test.cc + testcpp/build/_deps/googletest-src/googletest/test/googletest-death-test_ex_test.cc + testcpp/build/_deps/googletest-src/googletest/test/googletest-env-var-test_.cc + testcpp/build/_deps/googletest-src/googletest/test/googletest-failfast-unittest_.cc + testcpp/build/_deps/googletest-src/googletest/test/googletest-filepath-test.cc + testcpp/build/_deps/googletest-src/googletest/test/googletest-filter-unittest_.cc + testcpp/build/_deps/googletest-src/googletest/test/googletest-global-environment-unittest_.cc + testcpp/build/_deps/googletest-src/googletest/test/googletest-list-tests-unittest_.cc + testcpp/build/_deps/googletest-src/googletest/test/googletest-listener-test.cc + testcpp/build/_deps/googletest-src/googletest/test/googletest-message-test.cc + testcpp/build/_deps/googletest-src/googletest/test/googletest-options-test.cc + testcpp/build/_deps/googletest-src/googletest/test/googletest-output-test_.cc + testcpp/build/_deps/googletest-src/googletest/test/googletest-param-test-invalid-name1-test_.cc + testcpp/build/_deps/googletest-src/googletest/test/googletest-param-test-invalid-name2-test_.cc + testcpp/build/_deps/googletest-src/googletest/test/googletest-param-test-test.cc + testcpp/build/_deps/googletest-src/googletest/test/googletest-param-test-test.h + testcpp/build/_deps/googletest-src/googletest/test/googletest-param-test2-test.cc + testcpp/build/_deps/googletest-src/googletest/test/googletest-port-test.cc + testcpp/build/_deps/googletest-src/googletest/test/googletest-printers-test.cc + testcpp/build/_deps/googletest-src/googletest/test/googletest-setuptestsuite-test_.cc + testcpp/build/_deps/googletest-src/googletest/test/googletest-shuffle-test_.cc + testcpp/build/_deps/googletest-src/googletest/test/googletest-test-part-test.cc + testcpp/build/_deps/googletest-src/googletest/test/googletest-throw-on-failure-test_.cc + testcpp/build/_deps/googletest-src/googletest/test/googletest-uninitialized-test_.cc + testcpp/build/_deps/googletest-src/googletest/test/gtest-typed-test2_test.cc + testcpp/build/_deps/googletest-src/googletest/test/gtest-typed-test_test.cc + testcpp/build/_deps/googletest-src/googletest/test/gtest-typed-test_test.h + testcpp/build/_deps/googletest-src/googletest/test/gtest-unittest-api_test.cc + testcpp/build/_deps/googletest-src/googletest/test/gtest_all_test.cc + testcpp/build/_deps/googletest-src/googletest/test/gtest_assert_by_exception_test.cc + testcpp/build/_deps/googletest-src/googletest/test/gtest_environment_test.cc + testcpp/build/_deps/googletest-src/googletest/test/gtest_help_test_.cc + testcpp/build/_deps/googletest-src/googletest/test/gtest_list_output_unittest_.cc + testcpp/build/_deps/googletest-src/googletest/test/gtest_main_unittest.cc + testcpp/build/_deps/googletest-src/googletest/test/gtest_no_test_unittest.cc + testcpp/build/_deps/googletest-src/googletest/test/gtest_pred_impl_unittest.cc + testcpp/build/_deps/googletest-src/googletest/test/gtest_premature_exit_test.cc + testcpp/build/_deps/googletest-src/googletest/test/gtest_prod_test.cc + testcpp/build/_deps/googletest-src/googletest/test/gtest_repeat_test.cc + testcpp/build/_deps/googletest-src/googletest/test/gtest_skip_in_environment_setup_test.cc + testcpp/build/_deps/googletest-src/googletest/test/gtest_skip_test.cc + testcpp/build/_deps/googletest-src/googletest/test/gtest_sole_header_test.cc + testcpp/build/_deps/googletest-src/googletest/test/gtest_stress_test.cc + testcpp/build/_deps/googletest-src/googletest/test/gtest_test_macro_stack_footprint_test.cc + testcpp/build/_deps/googletest-src/googletest/test/gtest_testbridge_test_.cc + testcpp/build/_deps/googletest-src/googletest/test/gtest_throw_on_failure_ex_test.cc + testcpp/build/_deps/googletest-src/googletest/test/gtest_unittest.cc + testcpp/build/_deps/googletest-src/googletest/test/gtest_xml_outfile1_test_.cc + testcpp/build/_deps/googletest-src/googletest/test/gtest_xml_outfile2_test_.cc + testcpp/build/_deps/googletest-src/googletest/test/gtest_xml_output_unittest_.cc + testcpp/build/_deps/googletest-src/googletest/test/production.cc + testcpp/build/_deps/googletest-src/googletest/test/production.h + testcpp/CMakeLists.txt + testcpp/FImdlp_unittest.cc + testcpp/Metrics_unittest.cc + cfimdlp.cpp + CPPFImdlp.cpp + CPPFImdlp.h + Metrics.cpp + Metrics.h + typesFImdlp.h) diff --git a/fimdlp/CPPFImdlp.cpp b/fimdlp/CPPFImdlp.cpp index 1238d5a..416e101 100644 --- a/fimdlp/CPPFImdlp.cpp +++ b/fimdlp/CPPFImdlp.cpp @@ -1,7 +1,6 @@ #include "CPPFImdlp.h" #include #include -#include #include #include "Metrics.h" namespace mdlp { @@ -16,14 +15,15 @@ namespace mdlp { CPPFImdlp::CPPFImdlp() : proposed(true), precision(6), debug(false) { divider = pow(10, precision); + numClasses = 0; } CPPFImdlp::CPPFImdlp(bool proposed, int precision, bool debug) : proposed(proposed), precision(precision), debug(debug) { divider = pow(10, precision); + numClasses = 0; } CPPFImdlp::~CPPFImdlp() - { - } + = default; std::vector CPPFImdlp::getCutPoints() { return cutPoints; @@ -32,11 +32,19 @@ namespace mdlp { { return xDiscretized; } - void CPPFImdlp::fit(samples& X, labels& y) + void CPPFImdlp::fit(samples& X_, labels& y_) { - this->X = X; - this->y = y; - this->indices = sortIndices(X); + X = X_; + y = y_; + if (X.size() != y.size()) { + std::cerr << "X and y must have the same size" << std::endl; + return; + } + if (X.size() == 0) { + std::cerr << "X and y must have at least one element" << std::endl; + return; + } + this->indices = sortIndices(X_); this->xDiscretized = labels(X.size(), -1); this->numClasses = Metrics::numClasses(y, indices, 0, X.size()); @@ -48,24 +56,24 @@ namespace mdlp { filterCutPoints(); applyCutPoints(); } - labels& CPPFImdlp::transform(samples& X) + labels& CPPFImdlp::transform(samples& X_) { - indices_t indices_transform = sortIndices(X); + indices_t indices_transform = sortIndices(X_); applyCutPoints(); return xDiscretized; } - void CPPFImdlp::debugPoints(samples& X, labels& y) + void CPPFImdlp::debugPoints(samples& X_, labels& y_) { std::cout << "+++++++++++++++++++++++" << std::endl; // for (auto i : sortIndices(X)) - indices_t indices = sortIndices(X); - for (size_t i = 0; i < indices.size(); i++) { - printf("(%3lu, %3lu) -> (%3.1f, %d)\n", i, indices[i], X[indices[i]], y[indices[i]]); + indices_t indices_n = sortIndices(X); + for (size_t i = 0; i < indices_n.size(); i++) { + printf("(%3lu, %3lu) -> (%3.1f, %d)\n", i, indices_n[i], X_[indices_n[i]], y_[indices_n[i]]); } std::cout << "+++++++++++++++++++++++" << std::endl; - fit(X, y); + fit(X_, y_); for (auto item : cutPoints) { - std::cout << item.start << " X[" << item.end << "]=" << X[item.end] << std::endl; + std::cout << item.start << " X_[" << item.end << "]=" << X_[item.end] << std::endl; } } void CPPFImdlp::applyCutPoints() @@ -81,7 +89,7 @@ namespace mdlp { int k, k1, k2; float ig, delta; float ent, ent1, ent2; - float N = float(rest.end - rest.start); + auto N = float(rest.end - rest.start); if (N < 2) { return false; } @@ -92,7 +100,7 @@ namespace mdlp { ent1 = Metrics::entropy(y, indices, rest.start, candidate.end, numClasses); ent2 = Metrics::entropy(y, indices, candidate.end, rest.end, numClasses); ig = Metrics::informationGain(y, indices, rest.start, rest.end, candidate.end, numClasses); - delta = log2(pow(3, k) - 2) - (k * ent - k1 * ent1 - k2 * ent2); + delta = log2(pow(3, float(k)) - 2) - (float(k) * ent - float(k1) * ent1 - float(k2) * ent2); float term = 1 / N * (log2(N - 1) + delta); if (debug) { std::cout << "Rest: " << rest; @@ -116,7 +124,8 @@ namespace mdlp { bool lastReject = false, first = true; for (auto item : cutPoints) { if (evaluateCutPoint(rest, item)) { - std::cout << "Accepted" << std::endl; + if (debug) + std::cout << "Accepted" << std::endl; if (lastReject) { if (first) { item.fromValue = std::numeric_limits::lowest(); @@ -132,13 +141,14 @@ namespace mdlp { first = false; rest.start = item.end; } else { - std::cout << "Rejected" << std::endl; + if (debug) + std::cout << "Rejected" << std::endl; lastReject = true; } } if (!first) { filtered.back().toValue = std::numeric_limits::max(); - filtered.back().end = X.size(); + filtered.back().end = X.size() - 1; } else { filtered.push_back(rest); } @@ -149,15 +159,13 @@ namespace mdlp { { cutPoints_t cutPts; cutPoint_t cutPoint; - indices_t cutIdx; float xPrev, xCur, xPivot; int yPrev, yCur, yPivot; - size_t idxPrev, idxPivot, idx, numElements, start; + size_t idx, numElements, start; xCur = xPrev = X[indices[0]]; yCur = yPrev = y[indices[0]]; numElements = indices.size() - 1; - idxPrev = indices[0]; idx = start = 0; bool firstCutPoint = true; if (debug) @@ -165,7 +173,6 @@ namespace mdlp { while (idx < numElements) { xPivot = xCur; yPivot = yCur; - idxPivot = indices[idx]; if (debug) printf(" Prev(%3.1f, %d) Pivot(%3.1f, %d) Cur(%3.1f, %d) \n", idx, xPrev, yPrev, xPivot, yPivot, xCur, yCur); // Read the same values and check class changes @@ -192,30 +199,29 @@ namespace mdlp { printf("Cutpoint idx=%lu Cur(%3.1f, %d) Prev(%3.1f, %d) Pivot(%3.1f, %d) = (%3.1g, %3.1g] \n", idx, xCur, yCur, xPrev, yPrev, xPivot, yPivot, cutPoint.fromValue, cutPoint.toValue); } cutPts.push_back(cutPoint); - cutIdx.push_back(idxPrev); } yPrev = yPivot; xPrev = xPivot; - idxPrev = indices[idxPivot]; } if (idx == numElements) { cutPoint.start = start; - cutPoint.end = numElements; + cutPoint.end = numElements + 1; cutPoint.fromValue = firstCutPoint ? std::numeric_limits::lowest() : cutPts.back().toValue; cutPoint.toValue = std::numeric_limits::max(); cutPoint.classNumber = -1; if (debug) printf("Final Cutpoint idx=%lu Cur(%3.1f, %d) Prev(%3.1f, %d) Pivot(%3.1f, %d) = (%3.1g, %3.1g] \n", idx, xCur, yCur, xPrev, yPrev, xPivot, yPivot, cutPoint.fromValue, cutPoint.toValue); cutPts.push_back(cutPoint); - cutIdx.push_back(idxPrev); } + for (auto cutPt : cutPts) + std::cout << "Cut point: " << cutPt; cutPoints = cutPts; } void CPPFImdlp::computeCutPointsOriginal() { cutPoints_t cutPts; cutPoint_t cutPoint; - float xPrev = std::numeric_limits::lowest(); + float xPrev; int yPrev; bool first = true; // idxPrev is the index of the init instance of the cutPoint @@ -236,40 +242,34 @@ namespace mdlp { cutPoint.end = index; cutPoint.classNumber = -1; cutPoint.toValue = round(divider * (X[idx] + xPrev) / 2) / divider; - if (debug) { - std::cout << "Cut point: " << cutPoint << " //"; - std::cout << X[idx] << " -> " << y[idx] << " yPrev= " - << yPrev << idxPrev << std::endl; - } idxPrev = index; cutPts.push_back(cutPoint); } xPrev = X[idx]; yPrev = y[idx]; } - std::cout << "Came to here" << first << std::endl; if (first) { cutPoint.start = 0; cutPoint.classNumber = -1; cutPoint.fromValue = std::numeric_limits::lowest(); cutPoint.toValue = std::numeric_limits::max(); - cutPoints.push_back(cutPoint); + cutPts.push_back(cutPoint); } else cutPts.back().toValue = std::numeric_limits::max(); cutPts.back().end = X.size(); if (debug) - for (auto cutPoint : cutPts) - std::cout << "Cut point: " << cutPoint << std::endl; + for (auto cutPt : cutPts) + std::cout << "-Cut point: " << cutPt; cutPoints = cutPts; } // Argsort from https://stackoverflow.com/questions/1577475/c-sorting-and-keeping-track-of-indexes - indices_t CPPFImdlp::sortIndices(samples& X) + indices_t CPPFImdlp::sortIndices(samples& X_) { - indices_t idx(X.size()); + indices_t idx(X_.size()); std::iota(idx.begin(), idx.end(), 0); - for (std::size_t i = 0; i < X.size(); i++) - stable_sort(idx.begin(), idx.end(), [&X](size_t i1, size_t i2) - { return X[i1] < X[i2]; }); + for (std::size_t i = 0; i < X_.size(); i++) + stable_sort(idx.begin(), idx.end(), [&X_](size_t i1, size_t i2) + { return X_[i1] < X_[i2]; }); return idx; } } diff --git a/fimdlp/CPPFImdlp.h b/fimdlp/CPPFImdlp.h index f242eaf..9dc01ad 100644 --- a/fimdlp/CPPFImdlp.h +++ b/fimdlp/CPPFImdlp.h @@ -17,7 +17,7 @@ namespace mdlp { cutPoints_t cutPoints; protected: - indices_t sortIndices(samples&); + static indices_t sortIndices(samples&); void computeCutPointsOriginal(); void computeCutPointsProposed(); bool evaluateCutPoint(cutPoint_t, cutPoint_t); diff --git a/fimdlp/Metrics.cpp b/fimdlp/Metrics.cpp index c26751f..6887400 100644 --- a/fimdlp/Metrics.cpp +++ b/fimdlp/Metrics.cpp @@ -2,8 +2,7 @@ #include namespace mdlp { Metrics::Metrics() - { - } + = default; int Metrics::numClasses(labels& y, indices_t indices, size_t start, size_t end) { std::set numClasses; @@ -31,7 +30,7 @@ namespace mdlp { } float Metrics::informationGain(labels& y, indices_t& indices, size_t start, size_t end, size_t cutPoint, int nClasses) { - float iGain = 0.0; + float iGain; float entropy, entropyLeft, entropyRight; int nClassesLeft, nClassesRight; int nElementsLeft = cutPoint - start, nElementsRight = end - cutPoint; diff --git a/fimdlp/cppfimdlp.cpython-310-darwin.so b/fimdlp/cppfimdlp.cpython-310-darwin.so new file mode 100755 index 0000000000000000000000000000000000000000..314839fccf78775936216b15d766c25686e3bbd5 GIT binary patch literal 124968 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 = X; - this->indices = indices; + X = X_; + indices = indices_; indices_t testSortedIndices = sortIndices(X); float prev = X[testSortedIndices[0]]; for (auto i = 0; i < X.size(); ++i) { @@ -30,21 +29,11 @@ namespace mdlp { prev = X[testSortedIndices[i]]; } } - std::vector testCutPoints(samples& X, indices_t& indices, labels& y) - { - this->X = X; - this->y = y; - this->indices = indices; - this->numClasses = Metrics::numClasses(y, indices, 0, X.size()); - - //computeCutPoints(); - return getCutPoints(); - } }; // TEST_F(TestMetrics, SortIndices) { - samples X = { 5.7, 5.3, 5.2, 5.1, 5.0, 5.6, 5.1, 6.0, 5.1, 5.9 }; + X = { 5.7, 5.3, 5.2, 5.1, 5.0, 5.6, 5.1, 6.0, 5.1, 5.9 }; indices_t indices = { 4, 3, 6, 8, 2, 1, 5, 0, 9, 7 }; check_sorted_vector(X, indices); X = { 5.77, 5.88, 5.99 }; @@ -54,23 +43,97 @@ namespace mdlp { indices = { 2, 1, 0 }; check_sorted_vector(X, indices); } - // TEST_F(TestMetrics, EvaluateCutPoint) - // { - // cutPoint_t rest, candidate; - // rest.start = 0; - // rest.end = 10; - // candidate.start = 0; - // candidate.end = 5; - // float computed = evaluateCutPoint(rest, candidate); - // ASSERT_NEAR(0.468996, computed, precision_test); - // } + TEST_F(TestMetrics, EvaluateCutPoint) + { + cutPoint_t rest, candidate; + rest.start = 0; + rest.end = 10; + rest.classNumber = -1; + rest.fromValue = -1; + rest.toValue = 1000; + candidate.start = 0; + candidate.end = 4; + candidate.fromValue = -1; + candidate.toValue = 5.15; + candidate.classNumber = -1; + EXPECT_FALSE(evaluateCutPoint(rest, candidate)); + } TEST_F(TestMetrics, ComputeCutPointsOriginal) { - std::vector computed, expected; + cutPoints_t computed, expected; + expected = { + { 0, 4, -1, -3.4028234663852886e+38, 5.15 }, { 4, 6, -1, 5.15, 5.45 }, + { 6, 7, -1, 5.45, 5.65 }, { 7, 10, -1, 5.65, 3.4028234663852886e+38 } + }; computeCutPointsOriginal(); computed = getCutPoints(); - for (auto cut : computed) { - std::cout << cut.classNumber << " -> (" << cut.start << ", " << cut.end << ") -> (" << cut.fromValue << ", " << cut.toValue << ")" << std::endl; + EXPECT_EQ(computed.size(), 4); + for (auto i = 0; i < 4; i++) { + EXPECT_EQ(computed[i].start, expected[i].start); + EXPECT_EQ(computed[i].end, expected[i].end); + EXPECT_EQ(computed[i].classNumber, expected[i].classNumber); + EXPECT_NEAR(computed[i].fromValue, expected[i].fromValue, precision_test); + EXPECT_NEAR(computed[i].toValue, expected[i].toValue, precision_test); + } + } + TEST_F(TestMetrics, ComputeCutPointsOriginalGCase) + { + cutPoints_t computed, expected; + expected = { + { 0, 4, -1, -3.4028234663852886e+38, 3.4028234663852886e+38 }, + }; + X = {0, 1, 2, 2}; + y = {1, 1, 1, 2}; + fit(X, y); + computeCutPointsOriginal(); + computed = getCutPoints(); + EXPECT_EQ(computed.size(), 1); + for (auto i = 0; i < 1; i++) { + EXPECT_EQ(computed[i].start, expected[i].start); + EXPECT_EQ(computed[i].end, expected[i].end); + EXPECT_EQ(computed[i].classNumber, expected[i].classNumber); + EXPECT_NEAR(computed[i].fromValue, expected[i].fromValue, precision_test); + EXPECT_NEAR(computed[i].toValue, expected[i].toValue, precision_test); + } + } + TEST_F(TestMetrics, ComputeCutPointsProposed) + { + cutPoints_t computed, expected; + expected = { + { 0, 3, -1, -3.4028234663852886e+38, 5.1 }, { 4, 4, -1, 5.1, 5.2 }, + { 5, 5, -1, 5.2, 5.4 }, { 6, 8, -1, 5.4, 5.85 }, + { 9, 10, -1, 5.85, 3.4028234663852886e+38 } + }; + computeCutPointsProposed(); + computed = getCutPoints(); + EXPECT_EQ(computed.size(), 5); + for (auto i = 0; i < 5; i++) { + EXPECT_EQ(computed[i].start, expected[i].start); + EXPECT_EQ(computed[i].end, expected[i].end); + EXPECT_EQ(computed[i].classNumber, expected[i].classNumber); + EXPECT_NEAR(computed[i].fromValue, expected[i].fromValue, precision_test); + EXPECT_NEAR(computed[i].toValue, expected[i].toValue, precision_test); + } + } + TEST_F(TestMetrics, ComputeCutPointsProposedGCase) + { + cutPoints_t computed, expected; + expected = { + { 0, 2, -1, -3.4028234663852886e+38, 1.5 }, + { 3, 4, -1, 1.5, 3.4028234663852886e+38 } + }; + X = {0, 1, 2, 2}; + y = {1, 1, 1, 2}; + fit(X, y); + computeCutPointsProposed(); + computed = getCutPoints(); + EXPECT_EQ(computed.size(), 2); + for (auto i = 0; i < 1; i++) { + EXPECT_EQ(computed[i].start, expected[i].start); + EXPECT_EQ(computed[i].end, expected[i].end); + EXPECT_EQ(computed[i].classNumber, expected[i].classNumber); + EXPECT_NEAR(computed[i].fromValue, expected[i].fromValue, precision_test); + EXPECT_NEAR(computed[i].toValue, expected[i].toValue, precision_test); } } } \ No newline at end of file diff --git a/sample.py b/sample.py index 6f7285d..cf2f926 100644 --- a/sample.py +++ b/sample.py @@ -61,32 +61,34 @@ data = load_iris() X = data.data y = data.target features = data.feature_names -test = FImdlp() -test.fit(X, y, features=features) -test.transform(X) +# test = FImdlp() +# test.fit(X, y, features=features) +# test.transform(X) +# test.get_cut_points() -# test = CFImdlp(debug=False) +test = CFImdlp(debug=True, proposed=False) # # k = test.cut_points(X[:, 0], y) # # print(k) # # k = test.cut_points_ant(X[:, 0], y) # # print(k) # # test.debug_points(X[:, 0], y) -# X = [5.7, 5.3, 5.2, 5.1, 5.0, 5.6, 5.1, 6.0, 5.1, 5.9] -# indices = [4, 3, 6, 8, 2, 1, 5, 0, 9, 7] -# y = [1, 1, 1, 1, 1, 2, 2, 2, 2, 2] +X = [5.7, 5.3, 5.2, 5.1, 5.0, 5.6, 5.1, 6.0, 5.1, 5.9] +indices = [4, 3, 6, 8, 2, 1, 5, 0, 9, 7] +y = [1, 1, 1, 1, 1, 2, 2, 2, 2, 2] # # To check # indices2 = np.argsort(X) # Xs = np.array(X)[indices2] # ys = np.array(y)[indices2] -# # test.fit(X[:, 0], y) -# test.fit(X, y) -# result = test.get_cut_points() -# for item in result: -# print( -# f"Class={item['classNumber']} - ({item['start']:3d}, {item['end']:3d})" -# f" -> ({item['fromValue']:3.1f}, {item['toValue']:3.1f}]" -# ) -# print(test.get_discretized_values()) + +# test.fit(X[:, 0], y) +test.fit(X, y) +result = test.get_cut_points() +for item in result: + print( + f"*Class={item['classNumber']} - ({item['start']:3d}, {item['end']:3d})" + f" -> ({item['fromValue']:3.1f}, {item['toValue']:3.1f}]" + ) +print(test.get_discretized_values()) # print(Xs, ys) # print("**********************")