diff --git a/Makefile b/Makefile index 3b4d7b6..e8f93c5 100644 --- a/Makefile +++ b/Makefile @@ -49,11 +49,12 @@ release: ## Build a Release version of the project @cmake -S . -B build -D CMAKE_BUILD_TYPE=Release; @echo ">>> Done"; -test: ## Run tests +opt = "" +test: ## Run tests (opt="-s") to verbose output the tests, (opt="-c='Test Maximum Spanning Tree'") to run only that section @echo ">>> Running tests..."; $(MAKE) clean @cmake --build build --target unit_tests ; - @if [ -f build/tests/unit_tests ]; then cd build/tests ; ./unit_tests ; fi ; + @if [ -f build/tests/unit_tests ]; then cd build/tests ; ./unit_tests $(opt) ; fi ; @echo ">>> Done"; coverage: ## Run tests and generate coverage report (build/index.html) diff --git a/tests/TestBayesMetrics.cc b/tests/TestBayesMetrics.cc index 26eea82..6389a3b 100644 --- a/tests/TestBayesMetrics.cc +++ b/tests/TestBayesMetrics.cc @@ -6,41 +6,58 @@ using namespace std; -TEST_CASE("Metrics Test", "[Metrics]") +TEST_CASE("Metrics Test", "[BayesNet]") { string file_name = GENERATE("glass", "iris", "ecoli", "diabetes"); map>> resultsKBest = { - {"glass", {7, { 3, 2, 0, 1, 6, 7, 5 }}}, - {"iris", {3, { 1, 0, 2 }} }, - {"ecoli", {6, { 2, 3, 1, 0, 4, 5 }}}, - {"diabetes", {2, { 2, 0 }}} + {"glass", {7, { 0, 1, 7, 6, 3, 5, 2 }}}, + {"iris", {3, { 0, 3, 2 }} }, + {"ecoli", {6, { 2, 4, 1, 0, 6, 5 }}}, + {"diabetes", {2, { 7, 1 }}} + }; + map resultsMI = { + {"glass", 0.12805398}, + {"iris", 0.3158139948}, + {"ecoli", 0.0089431099}, + {"diabetes", 0.0345470614} + }; + map>> resultsMST = { + {"glass", {{0,6}, {0,5}, {0,3}, {6,2}, {6,7}, {5,1}, {5,8}, {5,4}}}, + {"iris", {{0,1},{0,2},{1,3}}}, + {"ecoli", {{0,1}, {0,2}, {1,5}, {1,3}, {5,6}, {5,4}}}, + {"diabetes", {{0,7}, {0,2}, {0,6}, {2,3}, {3,4}, {3,5}, {4,1}}} }; auto [XDisc, yDisc, featuresDisc, classNameDisc, statesDisc] = loadDataset(file_name, true, true); int classNumStates = statesDisc.at(classNameDisc).size(); auto yresized = torch::transpose(yDisc.view({ yDisc.size(0), 1 }), 0, 1); torch::Tensor dataset = torch::cat({ XDisc, yresized }, 0); int nSamples = dataset.size(1); + double epsilon = 1e-5; + torch::Tensor weights = torch::full({ nSamples }, 1.0 / nSamples, torch::kDouble); + bayesnet::Metrics metrics(dataset, featuresDisc, classNameDisc, classNumStates); SECTION("Test Constructor") { - bayesnet::Metrics metrics(XDisc, featuresDisc, classNameDisc, classNumStates); REQUIRE(metrics.getScoresKBest().size() == 0); } SECTION("Test SelectKBestWeighted") { - bayesnet::Metrics metrics(XDisc, featuresDisc, classNameDisc, classNumStates); - torch::Tensor weights = torch::full({ nSamples }, 1.0 / nSamples, torch::kDouble); vector kBest = metrics.SelectKBestWeighted(weights, true, resultsKBest.at(file_name).first); REQUIRE(kBest.size() == resultsKBest.at(file_name).first); REQUIRE(kBest == resultsKBest.at(file_name).second); } - SECTION("Test mutualInformation") + SECTION("Test Mutual Information") { - bayesnet::Metrics metrics(XDisc, featuresDisc, classNameDisc, classNumStates); - torch::Tensor weights = torch::full({ nSamples }, 1.0 / nSamples, torch::kDouble); auto result = metrics.mutualInformation(dataset.index({ 1, "..." }), dataset.index({ 2, "..." }), weights); - REQUIRE(result == 0.87); + REQUIRE(result == Catch::Approx(resultsMI.at(file_name)).epsilon(epsilon)); + } + + SECTION("Test Maximum Spanning Tree") + { + auto weights_matrix = metrics.conditionalEdge(weights); + auto result = metrics.maximumSpanningTree(featuresDisc, weights_matrix, 0); + REQUIRE(result == resultsMST.at(file_name)); } } \ No newline at end of file diff --git a/tests/TestBayesModels.cc b/tests/TestBayesModels.cc index 5da2cfc..c0d9b25 100644 --- a/tests/TestBayesModels.cc +++ b/tests/TestBayesModels.cc @@ -116,7 +116,7 @@ TEST_CASE("Test Bayesian Classifiers score", "[BayesNet]") // cout << "{{\"" << scores.first.first << "\", \"" << scores.first.second << "\"}, " << scores.second << "}, "; // } } -TEST_CASE("Models featuresDisc") +TEST_CASE("Models features", "[BayesNet]") { auto graph = vector({ "digraph BayesNet {\nlabel=\nfontsize=30\nfontcolor=blue\nlabelloc=t\nlayout=circo\n", "class [shape=circle, fontcolor=red, fillcolor=lightblue, style=filled ] \n", @@ -134,7 +134,7 @@ TEST_CASE("Models featuresDisc") REQUIRE(clf.show() == vector{"class -> sepallength, sepalwidth, petallength, petalwidth, ", "petallength -> sepallength, ", "petalwidth -> ", "sepallength -> sepalwidth, ", "sepalwidth -> petalwidth, "}); REQUIRE(clf.graph("Test") == graph); } -TEST_CASE("Get num featuresDisc & num edges") +TEST_CASE("Get num features & num edges", "[BayesNet]") { auto [XDisc, yDisc, featuresDisc, classNameDisc, statesDisc] = loadFile("iris"); auto clf = bayesnet::KDB(2); diff --git a/tests/TestBayesNetwork.cc b/tests/TestBayesNetwork.cc index f9aa705..0a31ca8 100644 --- a/tests/TestBayesNetwork.cc +++ b/tests/TestBayesNetwork.cc @@ -5,7 +5,7 @@ #include "TestUtils.h" #include "KDB.h" -TEST_CASE("Test Bayesian Network") +TEST_CASE("Test Bayesian Network", "[BayesNet]") { auto [Xd, y, features, className, states] = loadFile("iris");