Skip to content

Commit

Permalink
✅ Includes more tests to new functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
amarrerod committed Oct 23, 2023
1 parent 52ef12e commit 7bbcc8d
Show file tree
Hide file tree
Showing 9 changed files with 246 additions and 72 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*" -o ${{github.workspace}}/coverage/lcov.info
- name: Send to Coveralls
uses: coverallsapp/github-action@master
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
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
28 changes: 26 additions & 2 deletions test/core/FrontTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@

#include <dignea/core/Front.h>
#include <dignea/problems/DoubleSphere.h>
#include <dignea/problems/ZDT.h>
#include <dignea/types/SolutionTypes.h>

#include <vector>

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

using namespace std;

Expand Down Expand Up @@ -80,4 +80,28 @@ TEST_CASE("Front tests", "[Front]") {
REQUIRE(front->getNumOfSolutions() == copyFront->getNumOfSolutions());
REQUIRE(front->getSolutions() == copyFront->getSolutions());
}

SECTION("Adding a 2D solution") {
auto front = make_unique<Front<FloatSolution>>(solutions);
REQUIRE_THROWS(front->addSolution(solutions[0]));
}

SECTION("Adding a 1D solution using addSolution with problem") {
auto front = make_unique<Front<FloatSolution>>(solutions);
auto problem = make_unique<ZDT>(ZDT_MODE::ZDT1, 30);
FloatSolution newSolution(nVars, 1, constraints);
newSolution.setVariables(vars);
newSolution.setObjectives({10.0});
REQUIRE_NOTHROW(front->addSolution(newSolution, problem.get()));
}

SECTION("Adding a 2D solution using addSolution with problem") {
auto front = make_unique<Front<FloatSolution>>(0);
auto problem = make_unique<ZDT>(ZDT_MODE::ZDT1, 30);
for (const FloatSolution &solution : solutions) {
REQUIRE_NOTHROW(front->addSolution(solution, problem.get()));
}
// They should be the same
REQUIRE(front->getNumOfSolutions() == 1);
}
}
Loading

0 comments on commit 7bbcc8d

Please sign in to comment.