diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 47af50d..ff5ea4a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -20,8 +20,8 @@ include_directories( # b_best add_executable( b_best commands/b_best.cpp best/Statistics.cpp - best/BestResultsExcel.cpp best/BestResults.cpp - common/Datasets.cpp common/Dataset.cpp common/Discretization.cpp + best/BestResultsExcel.cpp best/BestResultsTex.cpp best/BestResults.cpp + common/Datasets.cpp common/Dataset.cpp common/Discretization.cpp main/Models.cpp main/Scores.cpp reports/ReportExcel.cpp reports/ReportBase.cpp reports/ExcelFile.cpp results/Result.cpp diff --git a/src/best/BestResults.cpp b/src/best/BestResults.cpp index a90adde..8123661 100644 --- a/src/best/BestResults.cpp +++ b/src/best/BestResults.cpp @@ -7,8 +7,10 @@ #include "common/Colors.h" #include "common/CLocale.h" #include "common/Paths.h" +#include "common/Utils.h" // compute_std #include "results/Result.h" #include "BestResultsExcel.h" +#include "BestResultsTex.h" #include "best/Statistics.h" #include "BestResults.h" @@ -210,56 +212,20 @@ namespace platform { table["dateTable"] = ftime_to_string(maxDate); return table; } - double compute_std(std::vector values, double mean) - { - // Compute standard devation of the values - double sum = 0.0; - for (const auto& value : values) { - sum += std::pow(value - mean, 2); - } - double variance = sum / values.size(); - return std::sqrt(variance); - } + void BestResults::printTableResults(std::vector models, json table, bool tex) { std::stringstream oss; oss << Colors::GREEN() << "Best results for " << score << " as of " << table.at("dateTable").get() << std::endl; - std::FILE* output_tex; std::cout << oss.str(); std::cout << std::string(oss.str().size() - 8, '-') << std::endl; std::cout << Colors::GREEN() << " # " << std::setw(maxDatasetName + 1) << std::left << std::string("Dataset"); + auto bestResultsTex = BestResultsTex(models, table.at("dateTable").get()); if (tex) { - auto file_name = Paths::tex_output(); - output_tex = fopen(file_name.c_str(), "w"); - if (output_tex == NULL) { - std::cerr << "Error opening file "<< file_name << std::endl; - exit(1); - } - fprintf(output_tex, "%% This file has been generated by the platform program\n"); - fprintf(output_tex, "%% Date: %s\n", table.at("dateTable").get().c_str()); - fprintf(output_tex, "%%\n"); - fprintf(output_tex, "%% Table of results\n"); - fprintf(output_tex, "%%\n"); - fprintf(output_tex, "\\begin{table}[htbp] \n"); - fprintf(output_tex, "\\centering \n"); - fprintf(output_tex, "\\tiny \n"); - fprintf(output_tex, "\\renewcommand{\\arraystretch }{1.2} \n"); - fprintf(output_tex, "\\renewcommand{\\tabcolsep }{0.07cm} \n"); - fprintf(output_tex, "\\caption{Accuracy results(mean ± std) for all the algorithms and datasets} \n"); - fprintf(output_tex, "\\label{tab:results_accuracy}\n"); - fprintf(output_tex, "\\begin{tabular} {{r%s}}\n", std::string(models.size(), 'c').c_str()); - fprintf(output_tex, "\\hline \n"); - fprintf(output_tex, "Id"); + bestResultsTex.results_header(); } for (const auto& model : models) { std::cout << std::setw(maxModelName) << std::left << model << " "; - if (tex) { - fprintf(output_tex, "& %s ", model.c_str()); - } - } - if (tex) { - fprintf(output_tex, "\\\\ \n"); - fprintf(output_tex, "\\hline \n"); } std::cout << std::endl; std::cout << "=== " << std::string(maxDatasetName, '=') << " "; @@ -271,7 +237,9 @@ namespace platform { std::map> totals; int nDatasets = table.begin().value().size(); auto datasets = getDatasets(table.begin().value()); - + if (tex) { + bestResultsTex.results_body(datasets, table); + } for (auto const& dataset_ : datasets) { auto color = (i % 2) ? Colors::BLUE() : Colors::CYAN(); std::cout << color << std::setw(3) << std::fixed << std::right << i++ << " "; @@ -290,9 +258,6 @@ namespace platform { maxValue = value; } } - if (tex) { - fprintf(output_tex, "%d ", i); - } // Print the row with red colors on max values for (const auto& model : models) { std::string efectiveColor = color; @@ -312,16 +277,8 @@ namespace platform { totals[model].push_back(value); std::cout << efectiveColor << std::setw(maxModelName) << std::setprecision(maxModelName - 2) << std::fixed << value << " "; } - if (tex) { - auto std_value = table[model].at(dataset_).at(3).get(); - const char* bold = value == maxValue ? "\\bfseries" : ""; - fprintf(output_tex, "& %s %0.4f±%0.3f", bold, value, std_value); - } } std::cout << std::endl; - if (tex) { - fprintf(output_tex, "\\\\\n"); - } } std::cout << Colors::GREEN() << "=== " << std::string(maxDatasetName, '=') << " "; for (const auto& model : models) { @@ -339,23 +296,14 @@ namespace platform { } } if (tex) { - fprintf(output_tex, "\\hline \n"); - fprintf(output_tex, "Average "); + bestResultsTex.results_footer(totals, best_model); } for (const auto& model : models) { std::string efectiveColor = model == best_model ? Colors::RED() : Colors::GREEN(); double value = std::reduce(totals[model].begin(), totals[model].end()) / nDatasets; double std_value = compute_std(totals[model], value); std::cout << efectiveColor << std::right << std::setw(maxModelName) << std::setprecision(maxModelName - 4) << std::fixed << value << " "; - if (tex) { - const char* bold = model == best_model ? "\\bfseries" : ""; - fprintf(output_tex, "& %s %0.4f±%0.3f", bold, value, std_value); - } - } - if (tex) { - // Footer for TeX - fprintf(output_tex, "\\ \n\\hline \n\\end{tabular}\n\\end{table}\n"); - fclose(output_tex); + } std::cout << std::endl; } @@ -389,7 +337,7 @@ namespace platform { ranksModels = stats.getRanks(); } if (tex) { - messageOutputFile("TeX", Paths::tex_output()); + messageOutputFile("TeX", Paths::tex() + Paths::tex_output()); } if (excel) { BestResultsExcel excel(score, datasets); diff --git a/src/best/BestResultsTex.cpp b/src/best/BestResultsTex.cpp new file mode 100644 index 0000000..24bd334 --- /dev/null +++ b/src/best/BestResultsTex.cpp @@ -0,0 +1,85 @@ +#include +#include "BestResultsTex.h" +#include "common/Utils.h" // compute_std + +namespace platform { + using json = nlohmann::ordered_json; + BestResultsTex::BestResultsTex(const std::vector& models, const std::string& date) : models(models), date(date) + { + } + void BestResultsTex::results_header() + { + auto file_name = Paths::tex() + Paths::tex_output(); + output_tex = fopen(file_name.c_str(), "w"); + if (output_tex == NULL) { + std::cerr << "Error opening file " << file_name << std::endl; + exit(1); + } + fprintf(output_tex, "%% This file has been generated by the platform program\n"); + fprintf(output_tex, "%% Date: %s\n", date.c_str()); + fprintf(output_tex, "%%\n"); + fprintf(output_tex, "%% Table of results\n"); + fprintf(output_tex, "%%\n"); + fprintf(output_tex, "\\begin{table}[htbp] \n"); + fprintf(output_tex, "\\centering \n"); + fprintf(output_tex, "\\tiny \n"); + fprintf(output_tex, "\\renewcommand{\\arraystretch }{1.2} \n"); + fprintf(output_tex, "\\renewcommand{\\tabcolsep }{0.07cm} \n"); + fprintf(output_tex, "\\caption{Accuracy results(mean ± std) for all the algorithms and datasets} \n"); + fprintf(output_tex, "\\label{tab:results_accuracy}\n"); + fprintf(output_tex, "\\begin{tabular} {{r%s}}\n", std::string(models.size(), 'c').c_str()); + fprintf(output_tex, "\\hline \n"); + fprintf(output_tex, "Id"); + for (const auto& model : models) { + fprintf(output_tex, "& %s ", model.c_str()); + } + fprintf(output_tex, "\\\\ \n"); + fprintf(output_tex, "\\hline \n"); + } + void BestResultsTex::results_body(const std::vector& datasets, json& table) + { + int i = 0; + for (auto const& dataset : datasets) { + // Find out max value for this dataset + double max_value = 0; + // Find out the max value for this dataset + for (const auto& model : models) { + double value; + try { + value = table[model].at(dataset).at(0).get(); + } + catch (nlohmann::json_abi_v3_11_3::detail::out_of_range err) { + value = -1.0; + } + if (value > max_value) { + max_value = value; + } + } + fprintf(output_tex, "%d ", i); + for (const auto& model : models) { + double value = table[model].at(dataset).at(0).get(); + double std_value = table[model].at(dataset).at(3).get(); + const char* bold = value == max_value ? "\\bfseries" : ""; + fprintf(output_tex, "& %s %0.4f±%0.3f", bold, value, std_value); + } + fprintf(output_tex, "\\\\\n"); + } + } + void BestResultsTex::results_footer(const std::map>& totals, const std::string& best_model) + { + fprintf(output_tex, "\\hline \n"); + fprintf(output_tex, "Average "); + int nDatasets = totals.begin()->second.size(); + for (const auto& model : models) { + double value = std::reduce(totals.at(model).begin(), totals.at(model).end()) / nDatasets; + double std_value = compute_std(totals.at(model), value); + const char* bold = model == best_model ? "\\bfseries" : ""; + fprintf(output_tex, "& %s %0.4f±%0.3f", bold, value, std_value); + } + fprintf(output_tex, "\\ \n"); + fprintf(output_tex, "\\hline \n"); + fprintf(output_tex, "\\end{tabular}\n"); + fprintf(output_tex, "\\end{table}\n"); + fclose(output_tex); + } +} diff --git a/src/best/BestResultsTex.h b/src/best/BestResultsTex.h new file mode 100644 index 0000000..011291d --- /dev/null +++ b/src/best/BestResultsTex.h @@ -0,0 +1,22 @@ +#ifndef BEST_RESULTS_TEX_H +#define BEST_RESULTS_TEX_H +#include +#include +#include +#include "common/Paths.h" +namespace platform { + using json = nlohmann::ordered_json; + class BestResultsTex { + public: + BestResultsTex(const std::vector& models, const std::string& date); + ~BestResultsTex() = default; + void results_header(); + void results_body(const std::vector& datasets, json& table); + void results_footer(const std::map>& totals, const std::string& best_model); + private: + std::FILE* output_tex; + std::vector models; + std::string date; + }; +} +#endif \ No newline at end of file diff --git a/src/common/Paths.h b/src/common/Paths.h index 9e8fcc6..47b17d9 100644 --- a/src/common/Paths.h +++ b/src/common/Paths.h @@ -6,12 +6,19 @@ namespace platform { class Paths { public: - static std::string results() { return "results/"; } - static std::string hiddenResults() { return "hidden_results/"; } - static std::string excel() { return "excel/"; } - static std::string grid() { return "grid/"; } - static std::string graphs() { return "graphs/"; } - static std::string tex() { return "tex/"; } + static std::string createIfNotExists(const std::string& folder) + { + if (!std::filesystem::exists(folder)) { + std::filesystem::create_directory(folder); + } + return folder; + } + static std::string results() { return createIfNotExists("results/"); } + static std::string hiddenResults() { return createIfNotExists("hidden_results/"); } + static std::string excel() { return createIfNotExists("excel/"); } + static std::string grid() { return createIfNotExists("grid/"); } + static std::string graphs() { return createIfNotExists("graphs/"); } + static std::string tex() { return createIfNotExists("tex/"); } static std::string datasets() { auto env = platform::DotEnv(); diff --git a/src/common/Utils.h b/src/common/Utils.h index b62b783..7b9a1c9 100644 --- a/src/common/Utils.h +++ b/src/common/Utils.h @@ -36,5 +36,15 @@ namespace platform { } return result; } + double compute_std(std::vector values, double mean) + { + // Compute standard devation of the values + double sum = 0.0; + for (const auto& value : values) { + sum += std::pow(value - mean, 2); + } + double variance = sum / values.size(); + return std::sqrt(variance); + } } #endif \ No newline at end of file