7 Commits

Author SHA1 Message Date
Ricardo Montañana Gómez
ac235e92e6 Merge a2ba5ee7e0 into 7b0673fd4b 2024-07-04 07:34:50 +00:00
a2ba5ee7e0 Fix sonar github action 2024-07-04 09:34:39 +02:00
d6276b46cd Update sonar github action 2024-07-04 01:27:00 +02:00
d9bd689a10 Fix mistake in github sonar action 2024-07-04 00:19:29 +02:00
6f8f535b40 Update sonarqube github action 2024-07-04 00:13:38 +02:00
872385e3ee Update sonar github action 2024-07-04 00:02:00 +02:00
cb3659b225 Add coypright header to sources
Fix coverage report
Add coverage badge to README
2024-07-03 23:43:08 +02:00
26 changed files with 222 additions and 46 deletions

View File

@@ -13,7 +13,7 @@ jobs:
env:
BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed
steps:
- uses: actions/checkout@v4.1.6
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- name: Install sonar-scanner and build-wrapper
@@ -28,17 +28,16 @@ jobs:
unzip libtorch-cxx11-abi-shared-with-deps-2.3.1+cpu.zip
- name: Tests & build-wrapper
run: |
cmake -S . -B build -Wno-dev -DCMAKE_PREFIX_PATH=$(pwd)/libtorch -DENABLE_TESTING=ON
build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} cmake --build build/ --config Release
cmake -S . -B build -Wno-dev -DCMAKE_PREFIX_PATH=$(pwd)/libtorch -DCMAKE_BUILD_TYPE=Debug -DENABLE_TESTING=ON
build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} cmake --build build/ --config Debug
cmake --build build -j 4
cd build
make
ctest -C Release --output-on-failure --test-dir tests
cd ..
gcovr -f CPPFImdlp.cpp -f Metrics.cpp -f BinDisc.cpp -f Discretizer.cpp --txt --sonarqube=coverage.xml
ctest -C Debug --output-on-failure -j 4
gcovr -f ../CPPFImdlp.cpp -f ../Metrics.cpp -f ../BinDisc.cpp -f ../Discretizer.cpp --txt --sonarqube=coverage.xml
- name: Run sonar-scanner
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: |
sonar-scanner --define sonar.cfamily.build-wrapper-output="${{ env.BUILD_WRAPPER_OUT_DIR }}" \
--define sonar.coverageReportPaths=coverage.xml
--define sonar.coverageReportPaths=build/coverage.xml

View File

@@ -1,3 +1,9 @@
// ****************************************************************
// SPDX - FileCopyrightText: Copyright 2024 Ricardo Montañana Gómez
// SPDX - FileType: SOURCE
// SPDX - License - Identifier: MIT
// ****************************************************************
#include <algorithm>
#include <cmath>
#include "BinDisc.h"

View File

@@ -1,3 +1,9 @@
// ****************************************************************
// SPDX - FileCopyrightText: Copyright 2024 Ricardo Montañana Gómez
// SPDX - FileType: SOURCE
// SPDX - License - Identifier: MIT
// ****************************************************************
#ifndef BINDISC_H
#define BINDISC_H

View File

@@ -6,6 +6,15 @@ include_directories(${TORCH_INCLUDE_DIRS})
add_library(mdlp CPPFImdlp.cpp Metrics.cpp BinDisc.cpp Discretizer.cpp)
target_link_libraries(mdlp "${TORCH_LIBRARIES}")
add_subdirectory(sample)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-elide-constructors")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3")
if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-default-inline")
endif()
if (ENABLE_TESTING)
MESSAGE("Debug mode")
enable_testing()
set(CODE_COVERAGE ON)
SET(GCC_COVERAGE_LINK_FLAGS " ${GCC_COVERAGE_LINK_FLAGS} -lgcov --coverage")
add_subdirectory(tests)
endif(ENABLE_TESTING)
endif(ENABLE_TESTING)

View File

@@ -1,3 +1,9 @@
// ****************************************************************
// SPDX - FileCopyrightText: Copyright 2024 Ricardo Montañana Gómez
// SPDX - FileType: SOURCE
// SPDX - License - Identifier: MIT
// ****************************************************************
#include <numeric>
#include <algorithm>
#include <set>

View File

@@ -1,3 +1,9 @@
// ****************************************************************
// SPDX - FileCopyrightText: Copyright 2024 Ricardo Montañana Gómez
// SPDX - FileType: SOURCE
// SPDX - License - Identifier: MIT
// ****************************************************************
#ifndef CPPFIMDLP_H
#define CPPFIMDLP_H

View File

@@ -1,3 +1,9 @@
// ****************************************************************
// SPDX - FileCopyrightText: Copyright 2024 Ricardo Montañana Gómez
// SPDX - FileType: SOURCE
// SPDX - License - Identifier: MIT
// ****************************************************************
#include "Discretizer.h"
namespace mdlp {
@@ -14,11 +20,6 @@ namespace mdlp {
for (const precision_t& item : data) {
auto pos = bound(first, last, item);
int number = pos - first;
/*
OJO
*/
if (number < 0)
throw std::runtime_error("number is less than 0 in discretizer::transform");
discretizedData.push_back(number);
}
return discretizedData;

View File

@@ -1,3 +1,9 @@
// ****************************************************************
// SPDX - FileCopyrightText: Copyright 2024 Ricardo Montañana Gómez
// SPDX - FileType: SOURCE
// SPDX - License - Identifier: MIT
// ****************************************************************
#ifndef DISCRETIZER_H
#define DISCRETIZER_H
@@ -24,7 +30,6 @@ namespace mdlp {
torch::Tensor fit_transform_t(torch::Tensor& X_, torch::Tensor& y_);
static inline std::string version() { return "1.2.3"; };
protected:
void normalize_cutpoints();
labels_t discretizedData = labels_t();
cutPoints_t cutPoints; // At least two cutpoints must be provided, the first and the last will be ignored in transform
bound_dir_t direction; // used in transform

View File

@@ -1,13 +1,32 @@
SHELL := /bin/bash
.DEFAULT_GOAL := build
.PHONY: build test
lcov := lcov
build:
@if [ -d build_release ]; then rm -fr build_release; fi
@mkdir build_release
@cmake -B build_release -S . -DCMAKE_BUILD_TYPE=Release -DENABLE_TESTING=OFF
@cmake --build build_release
@cmake --build build_release -j 8
test:
@echo "Testing..."
@cd tests && ./test
@if [ -d build_debug ]; then rm -fr build_debug; fi
@mkdir build_debug
@cmake -B build_debug -S . -DCMAKE_BUILD_TYPE=Debug -DENABLE_TESTING=ON
@cmake --build build_debug -j 8
@cd build_debug/tests && ctest --output-on-failure -j 8
@cd build_debug/tests && $(lcov) --capture --directory ../ --demangle-cpp --ignore-errors source,source --ignore-errors mismatch --output-file coverage.info >/dev/null 2>&1; \
$(lcov) --remove coverage.info '/usr/*' --output-file coverage.info >/dev/null 2>&1; \
$(lcov) --remove coverage.info 'lib/*' --output-file coverage.info >/dev/null 2>&1; \
$(lcov) --remove coverage.info 'libtorch/*' --output-file coverage.info >/dev/null 2>&1; \
$(lcov) --remove coverage.info 'tests/*' --output-file coverage.info >/dev/null 2>&1; \
$(lcov) --remove coverage.info 'gtest/*' --output-file coverage.info >/dev/null 2>&1;
@genhtml build_debug/tests/coverage.info --demangle-cpp --output-directory build_debug/tests/coverage --title "Discretizer mdlp Coverage Report" -s -k -f --legend
@echo "* Coverage report is generated at build_debug/tests/coverage/index.html"
@which python || (echo ">>> Please install python"; exit 1)
@if [ ! -f build_debug/tests/coverage.info ]; then \
echo ">>> No coverage.info file found!"; \
exit 1; \
fi
@echo ">>> Updating coverage badge..."
@env python update_coverage.py build_debug/tests

View File

@@ -1,3 +1,9 @@
// ****************************************************************
// SPDX - FileCopyrightText: Copyright 2024 Ricardo Montañana Gómez
// SPDX - FileType: SOURCE
// SPDX - License - Identifier: MIT
// ****************************************************************
#include "Metrics.h"
#include <set>
#include <cmath>

View File

@@ -1,3 +1,9 @@
// ****************************************************************
// SPDX - FileCopyrightText: Copyright 2024 Ricardo Montañana Gómez
// SPDX - FileType: SOURCE
// SPDX - License - Identifier: MIT
// ****************************************************************
#ifndef CCMETRICS_H
#define CCMETRICS_H

View File

@@ -1,6 +1,7 @@
[![Build](https://github.com/rmontanana/mdlp/actions/workflows/build.yml/badge.svg)](https://github.com/rmontanana/mdlp/actions/workflows/build.yml)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=rmontanana_mdlp&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=rmontanana_mdlp)
[![Reliability Rating](https://sonarcloud.io/api/project_badges/measure?project=rmontanana_mdlp&metric=reliability_rating)](https://sonarcloud.io/summary/new_code?id=rmontanana_mdlp)
[![Coverage Badge](https://img.shields.io/badge/Coverage-100,0%25-green)](html/index.html)
# <img src="logo.png" alt="logo" width="50"/> mdlp
@@ -31,15 +32,14 @@ Other features:
To run the sample, just execute the following commands:
```bash
cmake -B build -S .
cmake --build build
build/sample/sample -f iris -m 2
build/sample/sample -h
make build
build_release/sample/sample -f iris -m 2
build_release/sample/sample -h
```
## Test
To run the tests and see coverage (llvm & gcovr have to be installed), execute the following commands:
To run the tests and see coverage (llvm with lcov and genhtml have to be installed), execute the following commands:
```bash
make test

View File

@@ -1,3 +1,9 @@
// ****************************************************************
// SPDX - FileCopyrightText: Copyright 2024 Ricardo Montañana Gómez
// SPDX - FileType: SOURCE
// SPDX - License - Identifier: MIT
// ****************************************************************
#include <iostream>
#include <vector>
#include <iomanip>

View File

@@ -3,7 +3,7 @@ sonar.organization=rmontanana
# This is the name and version displayed in the SonarCloud UI.
sonar.projectName=mdlp
sonar.projectVersion=1.2.1
sonar.projectVersion=2.0.0
# sonar.test.exclusions=tests/**
# sonar.tests=tests/
# sonar.coverage.exclusions=tests/**,sample/**
@@ -12,3 +12,4 @@ sonar.projectVersion=1.2.1
# Encoding of the source code. Default is default system encoding
sonar.sourceEncoding=UTF-8
sonar.cfamily.compile-commands

View File

@@ -1,3 +1,9 @@
// ****************************************************************
// SPDX - FileCopyrightText: Copyright 2024 Ricardo Montañana Gómez
// SPDX - FileType: SOURCE
// SPDX - License - Identifier: MIT
// ****************************************************************
#include "ArffFiles.h"
#include <fstream>
#include <sstream>

View File

@@ -1,3 +1,9 @@
// ****************************************************************
// SPDX - FileCopyrightText: Copyright 2024 Ricardo Montañana Gómez
// SPDX - FileType: SOURCE
// SPDX - License - Identifier: MIT
// ****************************************************************
#ifndef ARFFFILES_H
#define ARFFFILES_H

View File

@@ -1,3 +1,9 @@
// ****************************************************************
// SPDX - FileCopyrightText: Copyright 2024 Ricardo Montañana Gómez
// SPDX - FileType: SOURCE
// SPDX - License - Identifier: MIT
// ****************************************************************
#include <fstream>
#include <string>
#include <iostream>

View File

@@ -1,3 +1,9 @@
// ****************************************************************
// SPDX - FileCopyrightText: Copyright 2024 Ricardo Montañana Gómez
// SPDX - FileType: SOURCE
// SPDX - License - Identifier: MIT
// ****************************************************************
#include <fstream>
#include <string>
#include <iostream>
@@ -20,7 +26,7 @@ namespace mdlp {
return "../../tests/datasets/";
}
const std::string data_path = set_data_path();
const labels_t iris_quantile = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 3, 3, 3, 1, 3, 1, 2, 0, 3, 1, 0, 2, 2, 2, 1, 3, 1, 2, 2, 1, 2, 2, 2, 2, 3, 3, 3, 3, 2, 1, 1, 1, 2, 2, 1, 2, 3, 2, 1, 1, 1, 2, 2, 0, 1, 1, 1, 2, 1, 1, 2, 2, 3, 2, 3, 3, 0, 3, 3, 3, 3, 3, 3, 1, 2, 3, 3, 3, 3, 2, 3, 1, 3, 2, 3, 3, 2, 2, 3, 3, 3, 3, 3, 2, 2, 3, 2, 3, 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 2, 2 };
TEST(Discretizer, Version)
{
Discretizer* disc = new BinDisc(4, strategy_t::UNIFORM);
@@ -51,9 +57,42 @@ namespace mdlp {
auto y = labels_t();
disc->fit(X[0], y);
auto Xt = disc->transform(X[0]);
labels_t expected = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 3, 3, 3, 1, 3, 1, 2, 0, 3, 1, 0, 2, 2, 2, 1, 3, 1, 2, 2, 1, 2, 2, 2, 2, 3, 3, 3, 3, 2, 1, 1, 1, 2, 2, 1, 2, 3, 2, 1, 1, 1, 2, 2, 0, 1, 1, 1, 2, 1, 1, 2, 2, 3, 2, 3, 3, 0, 3, 3, 3, 3, 3, 3, 1, 2, 3, 3, 3, 3, 2, 3, 1, 3, 2, 3, 3, 2, 2, 3, 3, 3, 3, 3, 2, 2, 3, 2, 3, 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 2, 2 };
delete disc;
EXPECT_EQ(expected, Xt);
EXPECT_EQ(iris_quantile, Xt);
}
TEST(Discretizer, BinIrisQuantileTorch)
{
ArffFiles file;
Discretizer* disc = new BinDisc(4, strategy_t::QUANTILE);
file.load(data_path + "iris.arff", true);
auto X = file.getX();
auto y = file.getY();
auto X_torch = torch::tensor(X[0], torch::kFloat32);
auto yt = torch::tensor(y, torch::kInt32);
disc->fit_t(X_torch, yt);
torch::Tensor Xt = disc->transform_t(X_torch);
delete disc;
EXPECT_EQ(iris_quantile.size(), Xt.size(0));
for (int i = 0; i < iris_quantile.size(); ++i) {
EXPECT_EQ(iris_quantile.at(i), Xt[i].item<int>());
}
}
TEST(Discretizer, BinIrisQuantileTorchFit_transform)
{
ArffFiles file;
Discretizer* disc = new BinDisc(4, strategy_t::QUANTILE);
file.load(data_path + "iris.arff", true);
auto X = file.getX();
auto y = file.getY();
auto X_torch = torch::tensor(X[0], torch::kFloat32);
auto yt = torch::tensor(y, torch::kInt32);
torch::Tensor Xt = disc->fit_transform_t(X_torch, yt);
delete disc;
EXPECT_EQ(iris_quantile.size(), Xt.size(0));
for (int i = 0; i < iris_quantile.size(); ++i) {
EXPECT_EQ(iris_quantile.at(i), Xt[i].item<int>());
}
}
TEST(Discretizer, FImdlpIris)

View File

@@ -1,3 +1,9 @@
// ****************************************************************
// SPDX - FileCopyrightText: Copyright 2024 Ricardo Montañana Gómez
// SPDX - FileType: SOURCE
// SPDX - License - Identifier: MIT
// ****************************************************************
#ifndef EXPERIMENTS_HPP
#define EXPERIMENTS_HPP
#include<sstream>

View File

@@ -1,3 +1,9 @@
// ****************************************************************
// SPDX - FileCopyrightText: Copyright 2024 Ricardo Montañana Gómez
// SPDX - FileType: SOURCE
// SPDX - License - Identifier: MIT
// ****************************************************************
#include "gtest/gtest.h"
#include "../Metrics.h"
#include "../CPPFImdlp.h"

View File

@@ -1,3 +1,9 @@
// ****************************************************************
// SPDX - FileCopyrightText: Copyright 2024 Ricardo Montañana Gómez
// SPDX - FileType: SOURCE
// SPDX - License - Identifier: MIT
// ****************************************************************
#include "gtest/gtest.h"
#include "../Metrics.h"

View File

@@ -1 +0,0 @@
---

View File

@@ -1,3 +0,0 @@
Start testing: Jul 03 18:09 CEST
----------------------------------------------------------
End testing: Jul 03 18:09 CEST

View File

@@ -1,15 +0,0 @@
#!/bin/bash
if [ -d build ] && [ "$1" != "run" ]; then
rm -fr build
fi
if [ -d gcovr-report ] ; then
rm -fr gcovr-report
fi
cmake -S . -B build -Wno-dev -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="--coverage" -DCMAKE_C_FLAGS="--coverage"
cmake --build build
cd build
ctest --output-on-failure -j 8
cd ..
mkdir gcovr-report
cd ..
gcovr --gcov-filter "CPPFImdlp.cpp" --gcov-filter "Metrics.cpp" --gcov-filter "BinDisc.cpp" --gcov-filter "Discretizer.cpp" --txt --sonarqube=tests/gcovr-report/coverage.xml --exclude-noncode-lines

View File

@@ -1,3 +1,9 @@
# ***************************************************************
# SPDX-FileCopyrightText: Copyright 2024 Ricardo Montañana Gómez
# SPDX-FileType: SOURCE
# SPDX-License-Identifier: MIT
# ***************************************************************
import json
from sklearn.preprocessing import KBinsDiscretizer

38
update_coverage.py Normal file
View File

@@ -0,0 +1,38 @@
# ***************************************************************
# SPDX-FileCopyrightText: Copyright 2024 Ricardo Montañana Gómez
# SPDX-FileType: SOURCE
# SPDX-License-Identifier: MIT
# ***************************************************************
import subprocess
import sys
readme_file = "README.md"
print("Updating coverage...")
# Generate badge line
output = subprocess.check_output(
"lcov --summary " + sys.argv[1] + "/coverage.info",
shell=True,
)
value = output.decode("utf-8").strip()
percentage = 0
for line in value.splitlines():
if "lines" in line:
percentage = float(line.split(":")[1].split("%")[0])
break
print(f"Coverage: {percentage}%")
if percentage < 90:
print("⛔Coverage is less than 90%. I won't update the badge.")
sys.exit(1)
percentage_label = str(percentage).replace(".", ",")
coverage_line = f"[![Coverage Badge](https://img.shields.io/badge/Coverage-{percentage_label}%25-green)](html/index.html)"
# Update README.md
with open(readme_file, "r") as f:
lines = f.readlines()
with open(readme_file, "w") as f:
for line in lines:
if "img.shields.io/badge/Coverage" in line:
f.write(coverage_line + "\n")
else:
f.write(line)
print(f"✅Coverage updated with value: {percentage}")