Skip to content

Commit

Permalink
Merge pull request #2 from DIGNEA/develop
Browse files Browse the repository at this point in the history
Introduces a number of new test cases to evaluate the proper functionality of the new features.
  • Loading branch information
amarrerod authored Oct 23, 2023
2 parents c9c8749 + bca414b commit 20a3be8
Show file tree
Hide file tree
Showing 23 changed files with 453 additions and 120 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/" -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
6 changes: 5 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ FetchContent_MakeAvailable(Catch2)

FetchContent_Declare(NumCpp
GIT_REPOSITORY https://github.com/dpilger26/NumCpp
GIT_TAG Version_2.10.1)
GIT_TAG Version_2.12.1)
FetchContent_MakeAvailable(NumCpp)

add_subdirectory(lib/fmt)
Expand Down 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 README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
[![Build](https://github.com/DIGNEA/dignea/actions/workflows/cmake.yml/badge.svg)](https://github.com/DIGNEA/dignea/actions/workflows/cmake.yml/badge.svg)
[![Test](https://github.com/DIGNEA/dignea/actions/workflows/catch.yml/badge.svg)](https://github.com/DIGNEA/dignea/actions/workflows/catch.yml//badge.svg)
[![Cpp-check](https://github.com/DIGNEA/dignea/actions/workflows/cppcheck.yml/badge.svg)](https://github.com/DIGNEA/dignea/actions/workflows/cppcheck.yml//badge.svg)
[![Coverage Status](https://coveralls.io/repos/github/DIGNEA/dignea/badge.svg?branch=master)](https://coveralls.io/github/DIGNEA/dignea?branch=master)
[![Coverage Status](https://coveralls.io/repos/github/DIGNEA/dignea/badge.svg?branch=main)](https://coveralls.io/github/DIGNEA/dignea?branch=main)
[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
[![Documentation](https://github.com/DIGNEA/dignea/actions/workflows/pages/pages-build-deployment/badge.svg)](https://github.com/DIGNEA/dignea/actions/workflows/pages/pages-build-deployment//badge.svg)
</center>
Expand Down
27 changes: 0 additions & 27 deletions include/dignea/core/Solution.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ class Solution {

bool operator==(const Solution &other) const;

virtual unique_ptr<Solution<V, O>> clone();

/**
* @brief Returns the objective values of the solution
*
Expand Down Expand Up @@ -358,31 +356,6 @@ Solution<V, O>::~Solution() {
constraints.shrink_to_fit();
}

/**\deprecated Clones the solution and returns a new unique_ptr with the exact
* same information.
*
*
* @tparam V
* @tparam O
* @return unique_ptr<Solution<V, O>>
*/
template <typename V, typename O>
unique_ptr<Solution<V, O>> Solution<V, O>::clone() {
auto solution = make_unique<Solution<V, O>>(nVars, nObjs, nCons);
solution->fitness = this->fitness;
solution->constraintCoeff = this->constraintCoeff;
for (int i = 0; i < this->nVars; i++) {
solution->variables[i] = this->variables[i];
}
for (int i = 0; i < this->nObjs; i++) {
solution->objectives[i] = this->objectives[i];
}
for (int i = 0; i < this->nCons; i++) {
solution->constraints[i] = this->constraints[i];
}
return solution;
}

/**
* @brief Updates the ith variable of the solution with the value v
*
Expand Down
2 changes: 2 additions & 0 deletions include/dignea/evolution/Evolution.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ class Evolution {

virtual map<int, float> results();

virtual inline bool empty() { return solutions.empty(); }

protected:
vector<float> solutions;
vector<int> checkpoints;
Expand Down
5 changes: 2 additions & 3 deletions include/dignea/generator/MapElites.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@
#include <vector>

#include "NumCpp.hpp"
#include "NumCpp/Functions/unique.hpp"
#include "NumCpp/NdArray.hpp"

using namespace std;
/**
* @brief FeatureInfo defines the information for a specific feature.
Expand Down Expand Up @@ -227,7 +226,7 @@ void MapElites<IP, IS, OP, OS>::setFeaturesInfo(const Features &f) {
// Calculate the bins
for (int i = 0; i < 8; i++) {
auto [start, stop, num] = this->features[i];
bins[i] = nc::linspace(start, stop, num, true);
bins[i] = nc::linspace(start, stop, num);
}
}

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
31 changes: 28 additions & 3 deletions test/algorithms/multiobjective/NSGA2Test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,11 @@
#include <dignea/problems/DoubleSphere.h>
#include <dignea/selections/BinaryTournamentSelection.h>

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

#include <catch2/catch_all.hpp>

using namespace std;
using json = nlohmann::json;

Expand All @@ -43,12 +42,18 @@ TEST_CASE("Non-Dominated Sorting Genetic Algorith II Tests", "[NSGA-II]") {
REQUIRE(ga->getSelection() == nullptr);
}

SECTION("Getting NSGA-II") {
SECTION("Getting NSGA-II ID") {
unique_ptr<AbstractGA<FloatSolution>> ga =
make_unique<NSGA2<FloatSolution>>();
REQUIRE(ga->getID() == "NSGA-II");
}

SECTION("Getting NSGA-II name") {
unique_ptr<AbstractGA<FloatSolution>> ga =
make_unique<NSGA2<FloatSolution>>();
REQUIRE(ga->getName() == "Non-dominated Sorting Genetic Algorithm II");
}

SECTION("Setting maxEvaluations") {
unique_ptr<AbstractGA<FloatSolution>> ga =
make_unique<NSGA2<FloatSolution>>();
Expand Down Expand Up @@ -117,4 +122,24 @@ TEST_CASE("Non-Dominated Sorting Genetic Algorith II Tests", "[NSGA-II]") {
.runDuring(evals);
REQUIRE(ga);
}

SECTION("NSGA2 run to solve Double Sphere") {
unique_ptr<AbstractGA<FloatSolution>> ga =
GABuilder<FloatSolution>::create(GAType::NSGA2)
.toSolve(make_unique<DoubleSphere>(dimension))
.with()
.populationOf(populationSize)
.with()
.mutation(MutType::UniformAll)
.crossover(CXType::Uniform)
.selection(SelType::Binary)
.withMutRate(0.05)
.withCrossRate(0.8)
.runDuring(evals);
REQUIRE_NOTHROW(ga->run());
Front result = ga->getResults();
REQUIRE_FALSE(result.empty());
vector bestObjs = result.getSolutions()[0].getObjectives();
REQUIRE(bestObjs[0] == bestObjs[1]);
}
}
21 changes: 19 additions & 2 deletions test/algorithms/singleobjective/SteadyGATest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@
#include <dignea/problems/Sphere.h>
#include <dignea/selections/BinaryTournamentSelection.h>

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

#include <catch2/catch_all.hpp>

using namespace std;

TEST_CASE("Steady Genetic Algorithm Tests", "[SteadyGA]") {
Expand Down Expand Up @@ -115,4 +114,22 @@ TEST_CASE("Steady Genetic Algorithm Tests", "[SteadyGA]") {
Front<FloatSolution> solutions = ga->getResults();
REQUIRE_FALSE(solutions.getNumOfSolutions() == 0);
}

SECTION("SteadyGA checks evolution") {
unique_ptr<AbstractGA<FloatSolution>> ga =
GABuilder<FloatSolution>::create(GAType::Steady)
.toSolve(make_unique<Sphere>(dimension))
.with()
.populationOf(populationSize)
.with()
.mutation(MutType::UniformAll)
.crossover(CXType::Uniform)
.selection(SelType::Binary)
.withMutRate(mutationRate)
.withCrossRate(crossoverRate)
.runDuring(evals);
ga->run();
auto evolution = ga->getEvolution();
REQUIRE_FALSE(evolution.empty());
}
}
100 changes: 100 additions & 0 deletions test/builders/EIGBuilderTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ TEST_CASE("EIGBuilder tests", "[EIGBuilder]") {
const int upperBound = 1000;
const int nIterationsEIG = 1000;
const int reps = 10;

SECTION("Creates a EIG for KNP") {
// configurations
vector<unique_ptr<EA>> algorithms;
Expand Down Expand Up @@ -86,6 +87,105 @@ TEST_CASE("EIGBuilder tests", "[EIGBuilder]") {
REQUIRE(generator->getPortfolio().size() == 3);
}

SECTION("Creates a MAP-Elites generator for KNP") {
// configurations
vector<unique_ptr<EA>> algorithms;
auto instKP = make_unique<KPDomain>(instanceSize, 1, nInstances, 1,
upperBound, 1, upperBound);
for (const float cRate : crossRates) {
unique_ptr<ParallelGeneticAlgorithm<OS>> algorithm =
ParGABuilder<OS>::create()
.usingCores(32)
.with()
.mutation(MutType::UniformOne)
.crossover(CXType::Uniform)
.selection(SelType::Binary)
.populationOf(popSize)
.withMutRate(mutationRate)
.withCrossRate(cRate)
.runDuring(maxEvals);
// Two configurations for EIG
algorithms.push_back(move(algorithm));
}
unique_ptr<InstanceFitness> easyEvaluator =
make_unique<EasyInstances>();

unique_ptr<EIG<IP, IS, OP, OS>> generator =
EIGBuilder<IP, IS, OP, OS>::create(GeneratorType::MapElites)
.toSolve(move(instKP))
.with()
.portfolio(algorithms)
.evalWith(move(easyEvaluator))
.repeating(reps)
.withSearch(NSType::Features, make_unique<Euclidean<float>>(),
3.0, 3.0, 15)
.with()
.crossover(CXType::Uniform)
.mutation(MutType::UniformOne)
.selection(SelType::Binary)
.withMutRate(mutationRate)
.withCrossRate(meaCXRate)
.populationOf(nInstances)
.runDuring(nIterationsEIG);
REQUIRE(generator);
REQUIRE(generator->getName() == "MapElites");
REQUIRE(generator->getSelection()->getName() ==
"Binary Tournament Selection");
REQUIRE(generator->getCrossover()->getName() ==
"Uniform One Crossover");
REQUIRE(generator->getMutation()->getName() == "Uniform One Mutation");
REQUIRE(generator->getPopulationSize() == nInstances);
REQUIRE(generator->getGenerations() == nIterationsEIG);
REQUIRE(generator->getMutationRate() == mutationRate);
REQUIRE(generator->getCrossoverRate() == meaCXRate);
REQUIRE(generator->getRepetitions() == reps);
REQUIRE(generator->getPortfolio().size() == 3);
}

SECTION("Creates a EIG when unknown type") {
// configurations
vector<unique_ptr<EA>> algorithms;
auto instKP = make_unique<KPDomain>(instanceSize, 1, nInstances, 1,
upperBound, 1, upperBound);
for (const float cRate : crossRates) {
unique_ptr<ParallelGeneticAlgorithm<OS>> algorithm =
ParGABuilder<OS>::create()
.usingCores(32)
.with()
.mutation(MutType::UniformOne)
.crossover(CXType::Uniform)
.selection(SelType::Binary)
.populationOf(popSize)
.withMutRate(mutationRate)
.withCrossRate(cRate)
.runDuring(maxEvals);
// Two configurations for EIG
algorithms.push_back(move(algorithm));
}
unique_ptr<InstanceFitness> easyEvaluator =
make_unique<EasyInstances>();

unique_ptr<EIG<IP, IS, OP, OS>> generator =
EIGBuilder<IP, IS, OP, OS>::create(GeneratorType::MultiObjective)
.toSolve(move(instKP))
.with()
.portfolio(algorithms)
.evalWith(move(easyEvaluator))
.repeating(reps)
.withSearch(NSType::Features, make_unique<Euclidean<float>>(),
3.0, 3.0, 15)
.with()
.crossover(CXType::Uniform)
.mutation(MutType::UniformOne)
.selection(SelType::Binary)
.withMutRate(mutationRate)
.withCrossRate(meaCXRate)
.populationOf(nInstances)
.runDuring(nIterationsEIG);
REQUIRE(generator);
REQUIRE(generator->getName() == "EIG");
}

SECTION("Throws exception if component is missing") {
// configurations
vector<unique_ptr<EA>> algorithms;
Expand Down
Loading

0 comments on commit 20a3be8

Please sign in to comment.