Skip to content

Commit

Permalink
✅ Introduces passing tests for new functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
amarrerod committed Oct 23, 2023
1 parent 7ff3aa4 commit bca414b
Show file tree
Hide file tree
Showing 15 changed files with 204 additions and 44 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ jobs:
make
make digneaTestCoverage
mkdir ${{github.workspace}}/coverage
lcov --remove digneaTestCoverage.info "/usr/*" "*/build/_deps/*" "*/examples/*" "*/lib/*" "*/test/" "*/algorithms/kp_heuristics/Combo*" "*/algorithms/kp_heuristics/ExpKnap*" "*/algorithms/kp_heuristics/MinKnap*" -o ${{github.workspace}}/coverage/lcov.info
lcov --remove digneaTestCoverage.info "/usr/*" "*/build/_deps/*" "*/examples/*" "*/lib/*" "*/test/" "*/algorithms/kp_heuristics/Combo*" "*/algorithms/kp_heuristics/ExpKnap*" "*/algorithms/kp_heuristics/MinKnap*" "*/utilities/PCA*" -o ${{github.workspace}}/coverage/lcov.info
- name: Send to Coveralls
uses: coverallsapp/github-action@master
Expand Down
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,8 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR INCLUDE_TESTS)
test/experiment/ExperimentTest.cpp
test/generator/evaluations/EasyInstancesTest.cpp
test/generator/evaluations/WeightedTest.cpp
test/generator/evaluations/PisPerformanceTest.cpp

test/generator/EIGTest.cpp

# test/generator/MOEIGTest.cpp
Expand Down Expand Up @@ -376,6 +378,8 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR INCLUDE_TESTS)
test/distances/ManhattanTest.cpp
test/distances/HammingTest.cpp
test/searches/NSFeaturesTest.cpp
test/searches/NSPerformanceTest.cpp

src/dignea/problems/TSP.cpp
test/problems/TSPTest.cpp
test/mutations/SwapMutationTest.cpp
Expand Down
2 changes: 1 addition & 1 deletion include/dignea/searches/NoveltySearch.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ class NoveltySearch : public Search<S> {

float getK() const { return this->k; }

float getFinalThresh() const { return this->finalThresh; }
float getFinalThresh() const { return this->finalSThreshold; }

protected:
virtual vector<Descriptor> beforeRun(const vector<S> &population);
Expand Down
3 changes: 0 additions & 3 deletions include/dignea/utilities/KNN.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,6 @@ class KNN {

neighMatrix run(const vector<Descriptor> &population,
Distance<float> *metric, const int &k = 3);

neighMatrix inverse(const vector<Descriptor> &population,
Distance<float> *metric, const int &k = 3);
};

/**
Expand Down
34 changes: 0 additions & 34 deletions src/dignea/utilities/KNN.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,40 +66,6 @@ neighMatrix KNN::run(const vector<Descriptor> &population,
return nearest;
}

/**
* @brief Computes the inverse of KNN
*
* @tparam S
* @tparam T
* @param population
* @param metric
* @param k
* @return neighMatrix<T>
*/
neighMatrix KNN::inverse(const vector<Descriptor> &population,
Distance<float> *metric, const int &k) {
if ((unsigned int)k > population.size()) {
throw runtime_error(
"K is " + to_string(k) +
" and population are only: " + to_string(population.size()));
}
neighMatrix nearest;
nearest.reserve(population.size());
for (unsigned int i = 0; i < population.size(); i++) {
neighVector distances = {};
distances.reserve(population.size() - 1);
for (unsigned int j = 0; j < population.size(); j++) {
if (i == j) continue;
float dist = metric->compute(population[i], population[j]);
distances.push_back({dist, j});
}
// Ordenamos los vecinos de I por su distancia a I
sort(distances.rbegin(), distances.rend());
nearest.push_back({distances.begin(), distances.begin() + k});
}
return nearest;
}

/**
* @brief Computes the sparseness of all individuals in the population vector
* Based on the Novelty Search from Exploiting Open-Endedness to Solve Problems
Expand Down
2 changes: 2 additions & 0 deletions test/core/FrontTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
using namespace std;

TEST_CASE("Front tests", "[Front]") {
std::cout.setstate(std::ios_base::failbit);
std::cerr.setstate(std::ios_base::failbit);
const int nSolutions = 30;
const int nVars = 10;
const int nObjs = 2;
Expand Down
2 changes: 2 additions & 0 deletions test/core/SolutionTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
using json = nlohmann::json;

TEST_CASE("Solutions can be created", "[Solution]") {
std::cout.setstate(std::ios_base::failbit);
std::cerr.setstate(std::ios_base::failbit);
int nVars = 30;
int nObjs = 1;
int nCons = 2;
Expand Down
3 changes: 1 addition & 2 deletions test/generator/evaluations/EasyInstancesTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@

#include <dignea/generator/evaluations/EasyInstances.h>

#include <vector>

#include <catch2/catch_all.hpp>
#include <vector>

using namespace std;

Expand Down
37 changes: 37 additions & 0 deletions test/generator/evaluations/PisPerformanceTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* @file PisPerformanceTest.cpp
* @author Alejandro Marrero (amarrerd@ull.edu.es)
* @brief
* @version 0.1
* @date 2023-10-23
*
* @copyright Copyright (c) 2023
*
*/

#include <dignea/generator/evaluations/PisPerformance.h>

#include <algorithm>
#include <catch2/catch_all.hpp>
#include <random>
#include <vector>

using namespace std;

TEST_CASE("Pisinger Performance evaluator tests", "[PisPerformance]") {
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<> dis(1.0, 15.0);
vector<float> runtimes(100);
std::generate(runtimes.begin(), runtimes.end(), [&]() { return dis(gen); });
runtimes[0] = 0.05f; // Best runtime

SECTION("Compute fitness of PisPerormance data") {
auto minRuntime =
*std::min_element(runtimes.begin() + 1, runtimes.end());
auto difference = minRuntime - runtimes[0];
PisPerformance evaluator;
float result = evaluator.compute(runtimes);
REQUIRE(result == difference);
}
}
74 changes: 74 additions & 0 deletions test/searches/NSPerformanceTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
//
// Created by amarrero on 5/7/21.
//

#include <dignea/distances/Euclidean.h>
#include <dignea/generator/domains/KPDomain.h>
#include <dignea/generator/instances/KPInstance.h>
#include <dignea/searches/NSPerformance.h>

#include <algorithm>
#include <catch2/catch_all.hpp>
#include <nlohmann/json.hpp>
#include <random>
#include <vector>

TEST_CASE("NSPerformance Searchs tests", "[NSPerformance Search]") {
auto threshold = 30;
auto pSize = 50;
auto nVars = 100;
auto portfolioSize = 4;
auto problem = make_unique<KPDomain>(nVars);
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<> dis(0.0, 500.0);

auto inds = std::vector<KPInstance>{};
for (int i = 0; i < pSize; i++) {
auto solution = problem->createSolution();
vector<float> fitness(portfolioSize);
std::generate(fitness.begin(), fitness.end(),
[&]() { return dis(gen); });
solution.setAvgConfigFitness(fitness);
inds.push_back(solution);
}

SECTION("Check NSp-EIG run can calculate diversity") {
auto dist = make_unique<Euclidean<float>>();
auto ns =
make_unique<NSPerformance<KPInstance>>(move(dist), threshold, 3);
vector result = ns->run(inds, problem.get());
REQUIRE(result == inds);
long unsigned int inserted = 0;
for (auto &ind : inds) {
REQUIRE(ind.getDiversity() != 0);
if (ind.getDiversity() > threshold) {
ns->insertIntoArchive(ind);
inserted++;
}
}
REQUIRE(ns->getArchive().size() ==
inserted); // Some solutions should've been
// inserted into the archive
}

SECTION("Check NSp-EIG inserts") {
auto dist = make_unique<Euclidean<float>>();
auto ns =
make_unique<NSPerformance<KPInstance>>(move(dist), threshold, 1);
auto solution = KPInstance{100};
solution.setAvgConfigFitness({100, 0, 10, 0});
ns->insertIntoArchive(solution);
REQUIRE(1 == ns->getArchive().size());
}

SECTION("Check NSp-EIG to_json") {
auto dist = make_unique<Euclidean<float>>();
auto ns = make_unique<NSPerformance<KPInstance>>(move(dist));
using json = nlohmann::json;
json data = ns->to_json();
REQUIRE("NSPerformance" == data["name"]);
REQUIRE(2000 == data["threshold"]);
REQUIRE(15 == data["k"]);
}
}
26 changes: 24 additions & 2 deletions test/searches/NoveltySearchTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ TEST_CASE("Novelty Searchs tests", "[Novelty Search]") {
auto dist = make_unique<Euclidean<float>>();
auto ns = make_unique<NoveltySearch<KPInstance>>(move(dist));

SECTION("NS default parameters") {
REQUIRE(ns->getK() == 15);
REQUIRE(ns->getThreshold() == 2000);
REQUIRE(ns->getFinalThresh() == 0.0001f);
}

SECTION("Check NS run") {
auto pSize = 50;
auto defaultNS = -1.0f;
Expand Down Expand Up @@ -49,9 +55,25 @@ TEST_CASE("Novelty Searchs tests", "[Novelty Search]") {
}

SECTION("Check NS compare final throws") {
vector<KPInstance> emptySols(0);
vector<KPInstance> emptySols;
REQUIRE_THROWS(ns->cmpFinals(emptySols));
}

// TODO REQUIRE_THROWS(ns->cmpFinals(emptySols));
SECTION("Check NS insertFinal works") {
auto pSize = 50;
auto nVars = 100;
auto problem = make_unique<KPDomain>(nVars);
auto inds = std::vector<KPInstance>{};
// FinalsS should be empty
// so at least the first solution should be inserted
for (int i = 0; i < pSize; i++) {
KPInstance ind = problem->createSolution();
ind.setFitness(1.0f);
ind.setBiasedFitness(1.0f);
inds.push_back(ind);
}
REQUIRE_NOTHROW(ns->cmpFinals(inds));
REQUIRE(ns->getResults().getNumOfSolutions() >= 1);
}

SECTION("Check NS to_json") {
Expand Down
12 changes: 12 additions & 0 deletions test/utilities/KNNTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,16 @@ TEST_CASE("KNN tests", "[KNN]") {
// sparseness throws runtime error
REQUIRE_THROWS(sparseness(solutions, hamming.get(), k * 10));
}

SECTION("KNN throws when the number of solutions is less than k") {
const int k = 15;
vector<vector<float>> descriptors = {{1, 2, 3, 4, 5, 6, 7, 8, 9},
{1, 2, 3, 4, 5, 6, 7, 8, 9},
{1, 2, 3, 4, 5, 6, 7, 8, 9}};

auto euclidean = make_unique<Euclidean<float>>();
auto knn = make_unique<KNN>();
REQUIRE_THROWS(
knn->run(descriptors[0], descriptors, euclidean.get(), k));
}
}
22 changes: 22 additions & 0 deletions test/utilities/StatisticsTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,4 +119,26 @@ TEST_CASE("Statistics tests", "[Statistics]") {
vector expected = {-0.2672612419f, 0.5345224838f, -0.8017837257f};
REQUIRE(areEqual(normalized, expected));
}

SECTION("Median function returns NaN if the vector is empty") {
vector<float> data = {};
auto result = median(data);
REQUIRE(std::numeric_limits<int>::quiet_NaN() == result);
}

SECTION("Median works on vector [1, 3, 5, 7] -> 4") {
vector data = {1, 3, 5, 7};
auto expected = 4;
auto result = median(data);
REQUIRE(expected == result);
}

SECTION(
"Median works with negative numbers ([-5, -5, -3, -4, 0, -1]) -> "
"-3.0") {
vector<float> data = {-5.0, -5.0, -3.0, -4.0, 0.0, -1.0};
auto expected = -3.0;
auto result = median(data);
REQUIRE(expected == result);
}
}
23 changes: 23 additions & 0 deletions test/utilities/comparator/ComparatorTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <dignea/problems/DoubleSphere.h>
#include <dignea/problems/SampleProblem.h>
#include <dignea/problems/Sphere.h>
#include <dignea/types/SolutionTypes.h>
#include <dignea/utilities/Comparator.h>

Expand Down Expand Up @@ -126,6 +127,28 @@ TEST_CASE("Comparator can be created", "[Comparator]") {
NON_DOMINANCES_EQUALS);
}

SECTION("Dominance Test of two single-objective solutions- Throws") {
int dimension = 30;
auto problem = make_unique<Sphere>(dimension);
FloatSolution solution1 = problem->createSolution();
FloatSolution solution2 = problem->createSolution();

REQUIRE_THROWS(dominanceTest(solution1, solution2, problem.get()) ==
NON_DOMINANCES_EQUALS);
}

SECTION(
"Dominance Test of multi-objective solutions with different "
"objectives- Throws") {
int dimension = 30;
auto problem = make_unique<DoubleSphere>(dimension);
FloatSolution solution1(100, 2, 0);
FloatSolution solution2(100, 3, 0);

REQUIRE_THROWS(dominanceTest(solution1, solution2, problem.get()) ==
NON_DOMINANCES_EQUALS);
}

SECTION("Comparing a population") {
auto numOfSolutions = 10;
vector<FloatSolution> population{};
Expand Down
2 changes: 1 addition & 1 deletion test/utilities/printer/JSONPrinterTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@
#include <dignea/experiment/AnalysisData.h>
#include <dignea/utilities/printer/JSONPrinter.h>

#include <catch2/catch_all.hpp>
#include <filesystem>
#include <string>

#include <catch2/catch_all.hpp>
#include "nlohmann/json.hpp"

using json = nlohmann::json;
Expand Down

0 comments on commit bca414b

Please sign in to comment.