From 5657c1cd9fab86d967458b6fdb90fd69505513f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Monta=C3=B1ana?= Date: Fri, 2 Dec 2022 12:54:09 +0100 Subject: [PATCH] Refactor tests --- fimdlp/CPPFImdlp.cpp | 155 ++++++++++++++++--------- fimdlp/CPPFImdlp.h | 45 +++---- fimdlp/Metrics.cpp | 23 ++-- fimdlp/Metrics.h | 14 +-- fimdlp/cfimdlp.pyx | 8 +- fimdlp/cppfimdlp.cpython-310-darwin.so | Bin 269996 -> 269628 bytes fimdlp/testcpp/FImdlp_unittest.cc | 95 ++++++++++----- fimdlp/testcpp/Metrics_unittest.cc | 36 +++--- fimdlp/testcpp/test | 12 ++ fimdlp/testcpp/test.sh | 2 +- fimdlp/typesFImdlp.h | 15 +++ prueba/FImdlp.cpp | 13 +-- prueba/FImdlp.h | 8 +- sample.py | 13 ++- 14 files changed, 265 insertions(+), 174 deletions(-) create mode 100755 fimdlp/testcpp/test create mode 100644 fimdlp/typesFImdlp.h diff --git a/fimdlp/CPPFImdlp.cpp b/fimdlp/CPPFImdlp.cpp index e9418f5..e1ed848 100644 --- a/fimdlp/CPPFImdlp.cpp +++ b/fimdlp/CPPFImdlp.cpp @@ -2,16 +2,9 @@ #include #include #include -#include #include #include "Metrics.h" -namespace mdlp -{ - std::ostream &operator<<(std::ostream &os, const CutPointBody &cut) - { - os << "(" << cut.start << ", " << cut.end << ") -> (" << cut.fromValue << ", " << cut.toValue << "]"; - return os; - } +namespace mdlp { CPPFImdlp::CPPFImdlp() : debug(false), precision(6) { divider = pow(10, precision); @@ -23,70 +16,125 @@ namespace mdlp CPPFImdlp::~CPPFImdlp() { } - std::vector CPPFImdlp::getCutPoints() + std::vector CPPFImdlp::getCutPoints() { return cutPoints; } - std::vector CPPFImdlp::getDiscretizedValues() + labels CPPFImdlp::getDiscretizedValues() { return xDiscretized; } - void CPPFImdlp::fit(std::vector &X, std::vector &y) + void CPPFImdlp::fit(samples& X, labels& y) { this->X = X; this->y = y; this->indices = sortIndices(X); + this->xDiscretized = labels(X.size(), -1); + this->numClasses = Metrics::numClasses(y, indices, 0, X.size()); + computeCutPoints(); filterCutPoints(); applyCutPoints(); } - std::vector &CPPFImdlp::transform(std::vector &X) + labels& CPPFImdlp::transform(samples& X) { - std::vector indices_transform = sortIndices(X); + indices_t indices_transform = sortIndices(X); applyCutPoints(); return xDiscretized; } - void CPPFImdlp::debugPoints(std::vector &X, std::vector &y) + void CPPFImdlp::debugPoints(samples& X, labels& y) { std::cout << "+++++++++++++++++++++++" << std::endl; // for (auto i : sortIndices(X)) - std::vector indices = sortIndices(X); - for (size_t i = 0; i < indices.size(); i++) - { + 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]]); } std::cout << "+++++++++++++++++++++++" << std::endl; fit(X, y); - for (auto item : cutPoints) - { - std::cout << item << " X[" << item.end << "]=" << X[item.end] << std::endl; + for (auto item : cutPoints) { + std::cout << item.start << " X[" << item.end << "]=" << X[item.end] << std::endl; } } void CPPFImdlp::applyCutPoints() { + for (auto cut : cutPoints) { + for (size_t i = cut.start; i < cut.end; i++) { + xDiscretized[indices[i]] = cut.classNumber; + } + } } - bool CPPFImdlp::evaluateCutPoint(CutPointBody point) + bool CPPFImdlp::evaluateCutPoint(CutPoint_t rest, CutPoint_t candidate) { - return true; + int k, k1, k2; + float ig, delta; + float ent, ent1, ent2; + float N = float(rest.end - rest.start); + if (N < 2) { + return false; + } + + k = Metrics::numClasses(y, indices, rest.start, rest.end); + k1 = Metrics::numClasses(y, indices, rest.start, candidate.end); + k2 = Metrics::numClasses(y, indices, candidate.end, rest.end); + ent = Metrics::entropy(y, indices, rest.start, rest.end, numClasses); + 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); + float term = 1 / N * (log2(N - 1) + delta); + std::cout << candidate + std::cout << "k=" << k << " k1=" << k1 << " k2=" << k2 << " ent=" << ent << " ent1=" << ent1 << " ent2=" << ent2 << std::endl; + std::cout << "ig=" << ig << " delta=" << delta << " N " << N << " term " << term << std::endl; + return (ig > term); } void CPPFImdlp::filterCutPoints() { - std::vector filtered; - for (auto item : cutPoints) - { - if (evaluateCutPoint(item)) - { + std::vector filtered; + CutPoint_t rest; + int classNumber = 0; + + rest.start = 0; + rest.end = X.size(); + rest.fromValue = std::numeric_limits::lowest(); + rest.toValue = std::numeric_limits::max(); + rest.classNumber = classNumber; + bool lastReject = false, first = true; + for (auto item : cutPoints) { + if (evaluateCutPoint(rest, item)) { + std::cout << "Accepted" << std::endl; + if (lastReject) { + if (first) { + item.fromValue = std::numeric_limits::lowest(); + item.start = indices[0]; + } else { + item.fromValue = filtered.back().toValue; + item.start = filtered.back().end; + } + } + //Assign class number to the interval (cutpoint) + item.classNumber = classNumber++; filtered.push_back(item); + first = false; + } else { + std::cout << "Rejected" << std::endl; + lastReject = true; } } + if (!first) + filtered.back().toValue = std::numeric_limits::max(); + else { + filtered.push_back(rest); + } + cutPoints = filtered; } void CPPFImdlp::computeCutPoints() { - std::vector cutPts; - CutPointBody cutPoint; - std::vector cutIdx; + std::vector cutPts; + CutPoint_t cutPoint; + indices_t cutIdx; float xPrev, xCur, xPivot; int yPrev, yCur, yPivot; size_t idxPrev, idxPivot, idx, numElements, start; @@ -99,28 +147,25 @@ namespace mdlp bool firstCutPoint = true; if (debug) printf("*idx=%lu -> (-1, -1) Prev(%3.1f, %d) Elementos: %lu\n", idx, xCur, yCur, numElements); - while (idx < numElements) - { + 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 - do - { + do { idx++; xCur = X[indices[idx]]; yCur = y[indices[idx]]; - if (yCur != yPivot && xCur == xPivot) - { + if (yCur != yPivot && xCur == xPivot) { yPivot = -1; } if (debug) printf(">idx=%lu -> Prev(%3.1f, %d) Pivot(%3.1f, %d) Cur(%3.1f, %d) \n", idx, xPrev, yPrev, xPivot, yPivot, xCur, yCur); - } while (idx < numElements && xCur == xPivot); - if (yPivot == -1 || yPrev != yCur) - { + } + while (idx < numElements && xCur == xPivot); + if (yPivot == -1 || yPrev != yCur) { cutPoint.start = start; cutPoint.end = idx - 1; start = idx; @@ -128,8 +173,7 @@ namespace mdlp cutPoint.toValue = (xPrev + xCur) / 2; cutPoint.classNumber = -1; firstCutPoint = false; - if (debug) - { + if (debug) { 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); @@ -139,8 +183,7 @@ namespace mdlp xPrev = xPivot; idxPrev = indices[idxPivot]; } - if (idx == numElements) - { + if (idx == numElements) { cutPoint.start = start; cutPoint.end = numElements; cutPoint.fromValue = firstCutPoint ? std::numeric_limits::lowest() : cutPts.back().toValue; @@ -155,31 +198,27 @@ namespace mdlp } void CPPFImdlp::computeCutPointsAnt() { - std::vector cutPts; - std::vector cutIdx; + samples cutPts; + labels cutIdx; float xPrev, cutPoint; int yPrev; size_t idxPrev; xPrev = X.at(indices[0]); yPrev = y.at(indices[0]); idxPrev = indices[0]; - if (debug) - { + if (debug) { std::cout << "Entropy: " << Metrics::entropy(y, indices, 0, y.size(), Metrics::numClasses(y, indices, 0, indices.size())) << std::endl; } - for (auto index = indices.begin(); index != indices.end(); ++index) - { + for (auto index = indices.begin(); index != indices.end(); ++index) { // Definition 2 Cut points are always on boundaries - if (y.at(*index) != yPrev && xPrev < X.at(*index)) - { + if (y.at(*index) != yPrev && xPrev < X.at(*index)) { cutPoint = round(divider * (X.at(*index) + xPrev) / 2) / divider; - if (debug) - { + if (debug) { std::cout << "Cut point: " << (xPrev + X.at(*index)) / 2 << " //"; std::cout << X.at(*index) << " -> " << y.at(*index) << " yPrev= " << yPrev; std::cout << "* (" << X.at(*index) << ", " << xPrev << ")=" - << ((X.at(*index) + xPrev) / 2) << "idxPrev" - << idxPrev << std::endl; + << ((X.at(*index) + xPrev) / 2) << "idxPrev" + << idxPrev << std::endl; } cutPts.push_back(cutPoint); cutIdx.push_back(idxPrev); @@ -191,13 +230,13 @@ namespace mdlp // cutPoints = cutPts; } // Argsort from https://stackoverflow.com/questions/1577475/c-sorting-and-keeping-track-of-indexes - std::vector CPPFImdlp::sortIndices(std::vector &X) + indices_t CPPFImdlp::sortIndices(samples& X) { - std::vector 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]; }); + { return X[i1] < X[i2]; }); return idx; } } diff --git a/fimdlp/CPPFImdlp.h b/fimdlp/CPPFImdlp.h index 8897fbc..f0ebed9 100644 --- a/fimdlp/CPPFImdlp.h +++ b/fimdlp/CPPFImdlp.h @@ -1,44 +1,37 @@ #ifndef CPPFIMDLP_H #define CPPFIMDLP_H -#include +#include "typesFImdlp.h" #include -namespace mdlp -{ - struct CutPointBody - { - size_t start, end; // indices of the sorted vector - int classNumber; // class assigned to the cut point - float fromValue, toValue; // Values of the variable - }; - class CPPFImdlp - { +namespace mdlp { + class CPPFImdlp { private: bool debug; int precision; float divider; - std::vector indices; // sorted indices to use with X and y - std::vector X; - std::vector y; - std::vector xDiscretized; - std::vector cutPoints; + indices_t indices; // sorted indices to use with X and y + samples X; + labels y; + labels xDiscretized; + int numClasses; + std::vector cutPoints; protected: - std::vector sortIndices(std::vector &); - bool evaluateCutPoint(CutPointBody); - void filterCutPoints(); - void computeCutPoints(); - void applyCutPoints(); + indices_t sortIndices(samples&); void computeCutPointsAnt(); + void computeCutPoints(); + bool evaluateCutPoint(CutPoint_t, CutPoint_t); + void filterCutPoints(); + void applyCutPoints(); public: CPPFImdlp(); CPPFImdlp(int, bool debug = false); ~CPPFImdlp(); - std::vector getCutPoints(); - std::vector getDiscretizedValues(); - void debugPoints(std::vector &, std::vector &); - void fit(std::vector &, std::vector &); - std::vector &transform(std::vector &); + std::vector getCutPoints(); + labels getDiscretizedValues(); + void debugPoints(samples&, labels&); + void fit(samples&, labels&); + labels& transform(samples&); }; } #endif \ No newline at end of file diff --git a/fimdlp/Metrics.cpp b/fimdlp/Metrics.cpp index 96d5596..7f9b060 100644 --- a/fimdlp/Metrics.cpp +++ b/fimdlp/Metrics.cpp @@ -1,40 +1,35 @@ #include "Metrics.h" #include -namespace mdlp -{ +namespace mdlp { Metrics::Metrics() { } - int Metrics::numClasses(std::vector &y, std::vector indices, size_t start, size_t end) + int Metrics::numClasses(labels& y, indices_t indices, size_t start, size_t end) { std::set numClasses; - for (auto i = start; i < end; ++i) - { + for (auto i = start; i < end; ++i) { numClasses.insert(y[indices[i]]); } return numClasses.size(); } - float Metrics::entropy(std::vector &y, std::vector &indices, size_t start, size_t end, int nClasses) + float Metrics::entropy(labels& y, indices_t& indices, size_t start, size_t end, int nClasses) { float entropy = 0; int nElements = 0; - std::vector counts(nClasses + 1, 0); - for (auto i = &indices[start]; i != &indices[end]; ++i) - { + labels counts(nClasses + 1, 0); + for (auto i = &indices[start]; i != &indices[end]; ++i) { counts[y[*i]]++; nElements++; } - for (auto count : counts) - { - if (count > 0) - { + for (auto count : counts) { + if (count > 0) { float p = (float)count / nElements; entropy -= p * log2(p); } } return entropy; } - float Metrics::informationGain(std::vector &y, std::vector &indices, size_t start, size_t end, size_t cutPoint, int nClasses) + float Metrics::informationGain(labels& y, indices_t& indices, size_t start, size_t end, size_t cutPoint, int nClasses) { float iGain = 0.0; float entropy, entropyLeft, entropyRight; diff --git a/fimdlp/Metrics.h b/fimdlp/Metrics.h index e3d4344..41b9b2c 100644 --- a/fimdlp/Metrics.h +++ b/fimdlp/Metrics.h @@ -1,16 +1,14 @@ #ifndef METRICS_H #define METRICS_H -#include +#include "typesFImdlp.h" #include -namespace mdlp -{ - class Metrics - { +namespace mdlp { + class Metrics { public: Metrics(); - static int numClasses(std::vector &, std::vector, size_t, size_t); - static float entropy(std::vector &, std::vector &, size_t, size_t, int); - static float informationGain(std::vector &, std::vector &, size_t, size_t, size_t, int); + static int numClasses(labels&, indices_t, size_t, size_t); + static float entropy(labels&, indices_t&, size_t, size_t, int); + static float informationGain(labels&, indices_t&, size_t, size_t, size_t, int); }; } #endif \ No newline at end of file diff --git a/fimdlp/cfimdlp.pyx b/fimdlp/cfimdlp.pyx index 7aeedf1..ccce80f 100644 --- a/fimdlp/cfimdlp.pyx +++ b/fimdlp/cfimdlp.pyx @@ -12,13 +12,13 @@ cdef extern from "CPPFImdlp.h" namespace "mdlp": CPPFImdlp() except + CPPFImdlp(int, bool) except + void fit(vector[float]&, vector[int]&) - vector[float] transform(vector[float]&) - vector[float] getDiscretizedValues() + vector[int] transform(vector[float]&) + vector[int] getDiscretizedValues() vector[CutPointBody] getCutPoints() void debugPoints(vector[float]&, vector[int]&) -class PCutPointBody: +class PCutPoint_t: def __init__(self, start, end, fromValue, toValue): self.start = start self.end = end @@ -37,7 +37,7 @@ cdef class CFImdlp: return self.thisptr.transform(X) def get_discretized_values(self): return self.thisptr.getDiscretizedValues() - def get_cut_points(self, X, y): + def get_cut_points(self): return self.thisptr.getCutPoints() def debug_points(self, X, y): return self.thisptr.debugPoints(X, y) diff --git a/fimdlp/cppfimdlp.cpython-310-darwin.so b/fimdlp/cppfimdlp.cpython-310-darwin.so index cc256ee4d05574c673a8b49fa8a1f3be50f7f32d..cccc05b2f82997ac2be169cfceb38aab77a5317a 100755 GIT binary patch delta 72617 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 delta 64958 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

hOtG&1w;F-hj5_FN`4+bl6V$`(o(1 zT$;$BB_hHbuphj!&_YP@E=K9Aaww#Z7m=`d)HV4?dq@>0+3iKHDO99qc=(wL9G1eq zmjaB^-N@}R^bhlp;7g#df%>6j=YUclu#2M!Mb(A|46LJsQ%Me{xUSX5k*osA>F#TU zY=aDJMsXKkl*XU#|7~_AfFa6oa$O(ie zT3+DrKn}D&NtHB9cQr0lqFWvFD^|p44W)9+QV|l8rUMpsP01{$9)1;iSJIH{CuN?J`@NZd3(KNa>E6eR* zOQAkTphjPm*?{{03CN$AUFM=Z@~{O!(?f3`x$7MfInaPxsEf*#<=&Run-q~e*H#;s z#$}j>GR)jdHQJ=;B-{qys1KOFBr~ZE(RXCW6(ZRDLJnOa0)i+-Rj9tuYxSi$D>9S( z0U^EVu@&;=6{4drRrBPzN5E>Gr(hnimX z-1ZtO!N|x+`UFnpHT5M4!)4z!P%`xPmT#^R{%vqHE+-AIO&Zce&3_wsq8p%0AgVVn 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 testSort(std::vector &X) + //TestMetrics(samples X, labels y, indices_t indices) : X(X), y(y), indices(indices), CPPFImdlp(true) {} + indices_t indices; // sorted indices to use with X and y + samples X; + labels y; + samples xDiscretized; + int numClasses; + float precision_test = 0.000001; + void SetUp() override { - return sortIndices(X); + 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 }; + numClasses = 2; + } + void check_sorted_vector(samples& X, indices_t indices) + { + this->X = X; + this->indices = indices; + indices_t testSortedIndices = sortIndices(X); + float prev = X[testSortedIndices[0]]; + for (auto i = 0; i < X.size(); ++i) { + EXPECT_EQ(testSortedIndices[i], indices[i]); + EXPECT_LE(prev, X[testSortedIndices[i]]); + 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(); } }; - void check_sorted_vector(std::vector &X, std::vector indices) + // + TEST_F(TestMetrics, SortIndices) { - TestMetrics testClass = TestMetrics(); - std::vector testSortedIndices = testClass.testSort(X); - float prev = X[testSortedIndices[0]]; - for (auto i = 0; i < X.size(); ++i) - { - EXPECT_EQ(testSortedIndices[i], indices[i]); - EXPECT_LE(prev, X[testSortedIndices[i]]); - prev = X[testSortedIndices[i]]; + samples 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 }; + indices = { 0, 1, 2 }; + check_sorted_vector(X, indices); + X = { 5.33, 5.22, 5.11 }; + 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, ComputeCutPoints) + { + std::vector computed, expected; + computeCutPoints(); + computed = getCutPoints(); + for (auto cut : computed) { + std::cout << "(" << cut.start << ", " << cut.end << ") -> (" << cut.fromValue << ", " << cut.toValue << ")" << std::endl; } } - TEST(FImdlpTest, SortIndices) - { - - std::vector X = {5.7, 5.3, 5.2, 5.1, 5.0, 5.6, 5.1, 6.0, 5.1, 5.9}; - std::vector indices = {4, 3, 6, 8, 2, 1, 5, 0, 9, 7}; - check_sorted_vector(X, indices); - X = {5.77, 5.88, 5.99}; - indices = {0, 1, 2}; - check_sorted_vector(X, indices); - X = {5.33, 5.22, 5.11}; - indices = {2, 1, 0}; - check_sorted_vector(X, indices); - } } \ No newline at end of file diff --git a/fimdlp/testcpp/Metrics_unittest.cc b/fimdlp/testcpp/Metrics_unittest.cc index 3c25fe2..c04ec0f 100644 --- a/fimdlp/testcpp/Metrics_unittest.cc +++ b/fimdlp/testcpp/Metrics_unittest.cc @@ -1,33 +1,31 @@ #include "gtest/gtest.h" #include "../Metrics.h" -namespace -{ - +namespace mdlp { float precision = 0.000001; TEST(MetricTest, NumClasses) { - std::vector y = {1, 1, 1, 1, 1, 1, 1, 1, 2, 1}; - std::vector indices = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - EXPECT_EQ(1, mdlp::Metrics::numClasses(y, indices, 4, 8)); - EXPECT_EQ(2, mdlp::Metrics::numClasses(y, indices, 0, 10)); - EXPECT_EQ(2, mdlp::Metrics::numClasses(y, indices, 8, 10)); + labels y = { 1, 1, 1, 1, 1, 1, 1, 1, 2, 1 }; + indices_t indices = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + EXPECT_EQ(1, Metrics::numClasses(y, indices, 4, 8)); + EXPECT_EQ(2, Metrics::numClasses(y, indices, 0, 10)); + EXPECT_EQ(2, Metrics::numClasses(y, indices, 8, 10)); } TEST(MetricTest, Entropy) { - std::vector y = {1, 1, 1, 1, 1, 2, 2, 2, 2, 2}; - std::vector indices = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - EXPECT_EQ(1, mdlp::Metrics::entropy(y, indices, 0, 10, 2)); - EXPECT_EQ(0, mdlp::Metrics::entropy(y, indices, 0, 5, 1)); - std::vector yz = {1, 1, 1, 1, 1, 1, 1, 1, 2, 1}; - ASSERT_NEAR(0.468996, mdlp::Metrics::entropy(yz, indices, 0, 10, 2), precision); + labels y = { 1, 1, 1, 1, 1, 2, 2, 2, 2, 2 }; + indices_t indices = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + EXPECT_EQ(1, Metrics::entropy(y, indices, 0, 10, 2)); + EXPECT_EQ(0, Metrics::entropy(y, indices, 0, 5, 1)); + labels yz = { 1, 1, 1, 1, 1, 1, 1, 1, 2, 1 }; + ASSERT_NEAR(0.468996, Metrics::entropy(yz, indices, 0, 10, 2), precision); } TEST(MetricTest, InformationGain) { - std::vector y = {1, 1, 1, 1, 1, 2, 2, 2, 2, 2}; - std::vector indices = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - std::vector yz = {1, 1, 1, 1, 1, 1, 1, 1, 2, 1}; - ASSERT_NEAR(1, mdlp::Metrics::informationGain(y, indices, 0, 10, 5, 2), precision); - ASSERT_NEAR(0.108032, mdlp::Metrics::informationGain(yz, indices, 0, 10, 5, 2), precision); + labels y = { 1, 1, 1, 1, 1, 2, 2, 2, 2, 2 }; + indices_t indices = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + labels yz = { 1, 1, 1, 1, 1, 1, 1, 1, 2, 1 }; + ASSERT_NEAR(1, Metrics::informationGain(y, indices, 0, 10, 5, 2), precision); + ASSERT_NEAR(0.108032, Metrics::informationGain(yz, indices, 0, 10, 5, 2), precision); } } \ No newline at end of file diff --git a/fimdlp/testcpp/test b/fimdlp/testcpp/test new file mode 100755 index 0000000..e27cdde --- /dev/null +++ b/fimdlp/testcpp/test @@ -0,0 +1,12 @@ +cmake -S . -B build -Wno-dev +if test $? -ne 0; then + echo "Error in creating build commands." + exit 1 +fi +cmake --build build +if test $? -ne 0; then + echo "Error in build command." + exit 1 +fi +cd build +ctest --output-on-failure diff --git a/fimdlp/testcpp/test.sh b/fimdlp/testcpp/test.sh index 7c0aa40..e27cdde 100755 --- a/fimdlp/testcpp/test.sh +++ b/fimdlp/testcpp/test.sh @@ -1,4 +1,4 @@ -cmake -S . -B build +cmake -S . -B build -Wno-dev if test $? -ne 0; then echo "Error in creating build commands." exit 1 diff --git a/fimdlp/typesFImdlp.h b/fimdlp/typesFImdlp.h new file mode 100644 index 0000000..7214ce9 --- /dev/null +++ b/fimdlp/typesFImdlp.h @@ -0,0 +1,15 @@ +#ifndef TYPES_H +#define TYPES_H +#include +namespace mdlp { + typedef std::vector samples; + typedef std::vector labels; + typedef std::vector indices_t; + struct CutPointBody { + size_t start, end; // indices of the sorted vector + int classNumber; // class assigned to the cut point + float fromValue, toValue; + }; + typedef CutPointBody CutPoint_t; +} +#endif \ No newline at end of file diff --git a/prueba/FImdlp.cpp b/prueba/FImdlp.cpp index 19241c7..68c2f69 100644 --- a/prueba/FImdlp.cpp +++ b/prueba/FImdlp.cpp @@ -1,21 +1,18 @@ #include "FImdlp.h" -namespace FImdlp -{ +namespace FImdlp { FImdlp::FImdlp() { } FImdlp::~FImdlp() { } - std::vector FImdlp::cutPoints(std::vector &X, std::vector &y) + samples FImdlp::cutPoints(labels& X, labels& y) { - std::vector cutPts; + samples cutPts; int i, ant = X.at(0); int n = X.size(); - for (i = 1; i < n; i++) - { - if (X.at(i) != ant) - { + for (i = 1; i < n; i++) { + if (X.at(i) != ant) { cutPts.push_back(float(X.at(i) + ant) / 2); ant = X.at(i); } diff --git a/prueba/FImdlp.h b/prueba/FImdlp.h index d15cf8b..90c90ca 100644 --- a/prueba/FImdlp.h +++ b/prueba/FImdlp.h @@ -2,14 +2,12 @@ #define FIMDLP_H #include #include -namespace FImdlp -{ - class FImdlp - { +namespace FImdlp { + class FImdlp { public: FImdlp(); ~FImdlp(); - std::vector cutPoints(std::vector &, std::vector &); + samples cutPoints(labels&, labels&); }; } #endif \ No newline at end of file diff --git a/sample.py b/sample.py index 804cfc8..fd969bb 100644 --- a/sample.py +++ b/sample.py @@ -18,13 +18,22 @@ test = CFImdlp(debug=False) # k = test.cut_points_ant(X[:, 0], y) # print(k) # test.debug_points(X[:, 0], y) -result = test.cut_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] +# 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(test.transform(X)) +# print(X) +# print(indices) +# print(np.array(X)[indices]) # X = np.array( # [