Files
ensmallen/tests/moead_test.cpp
T
2021-06-08 10:20:45 +05:30

255 lines
7.1 KiB
C++

/**
* @file moead_test.cpp
* @author Sayan Goswami
* @author Utkarsh Rai
*
* ensmallen is free software; you may redistribute it and/or modify it under
* the terms of the 3-clause BSD license. You should have received a copy of
* the 3-clause BSD license along with ensmallen. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#include <ensmallen.hpp>
#include "catch.hpp"
#include "test_function_tools.hpp"
using namespace ens;
using namespace ens::test;
using namespace std;
/**
* Checks if low <= value <= high. Used by MOEADFonsecaFlemingTest.
*
* @param value The value being checked.
* @param low The lower bound.
* @param high The upper bound.
* @return true if value lies in the range [low, high].
* @return false if value does not lie in the range [low, high].
*/
bool InBounds(const double& value, const double& low, const double& high)
{
return !(value < low) && !(high < value);
}
/**
* Optimize for the Schaffer N.1 function using MOEA/D-DE optimizer.
*/
TEST_CASE("MOEADSchafferN1Test", "[MOEADTest]")
{
SchafferFunctionN1<arma::mat> SCH;
double lowerBound = -1000;
const double upperBound = 1000;
const double strength = 1e-3;
MOEAD opt(150, // population size
2000, // num generations
0.6, // cross over prob
0.7, // mutation prob
strength, // mutation strength
10, //neighbor size
0.5, //distribution index
0.5, //neighbor prob
0.8, //differential weight
10, //maxreplace,
lowerBound, //lower bound
upperBound //upper bound
);
typedef decltype(SCH.objectiveA) ObjectiveTypeA;
typedef decltype(SCH.objectiveB) ObjectiveTypeB;
// We allow a few trials in case of poor convergence.
bool success = false;
for (size_t trial = 0; trial < 3; ++trial)
{
arma::mat coords = SCH.GetInitialPoint();
std::tuple<ObjectiveTypeA, ObjectiveTypeB> objectives = SCH.GetObjectives();
opt.Optimize(objectives, coords);
std::vector<arma::mat> bestFront = opt.Front();
bool allInRange = true;
double minimumPositive = 1000;
for (arma::mat solution: bestFront)
{
double val = arma::as_scalar(solution);
if(val >= 0.0)
minimumPositive = std::min(minimumPositive, val);
if ((val < 0.0 && std::abs(val) >= minimumPositive) || val > 2.0)
{
allInRange = false;
break;
}
}
if (allInRange)
{
success = true;
break;
}
}
REQUIRE(success == true);
}
/**
* Optimize for the Schaffer N.1 function using MOEA/D-DE optimizer.
*/
TEST_CASE("MOEADSchafferN1VectorBoundsTest", "[MOEADTest]")
{
SchafferFunctionN1<arma::mat> SCH;
arma::vec lowerBound = {-1000};
arma::vec upperBound = {1000};
const double strength = 1e-3;
MOEAD opt(150, // population size
2000, // num generations
0.6, // cross over prob
0.7, // mutation prob
strength, // mutation strength
10, //neighbor size
0.5, //distribution index
0.5, //neighbor prob
0.8, //differential weight
10, //maxreplace,
lowerBound, //lower bound
upperBound //upper bound
);
typedef decltype(SCH.objectiveA) ObjectiveTypeA;
typedef decltype(SCH.objectiveB) ObjectiveTypeB;
bool success = false;
for (size_t trial = 0; trial < 3; ++trial)
{
arma::mat coords = SCH.GetInitialPoint();
std::tuple<ObjectiveTypeA, ObjectiveTypeB> objectives = SCH.GetObjectives();
opt.Optimize(objectives, coords);
std::vector<arma::mat> bestFront = opt.Front();
bool allInRange = true;
for (arma::mat solution: bestFront)
{
double val = arma::as_scalar(solution);
if (val < 0.0 || val > 2.0)
{
allInRange = false;
break;
}
}
if (allInRange)
{
success = true;
break;
}
}
REQUIRE(success == true);
}
/**
* Optimize for the Fonseca Fleming function using MOEA/D-DE optimizer.
*/
TEST_CASE("MOEADFonsecaFlemingTest", "[MOEADTest]")
{
FonsecaFlemingFunction<arma::mat> FON;
const double lowerBound = -4;
const double upperBound = 4;
const double strength = 1e-3;
const double expectedLowerBound = -1.0 / sqrt(3);
const double expectedUpperBound = 1.0 / sqrt(3);
MOEAD opt(150, // population size
2000, // num generations
0.6, // cross over prob
0.7, // mutation prob
strength, // mutation strength
10, //neighbor size
0.5, //distribution index
0.5, //neighbor prob
0.8, //differential weight
10, //maxreplace,
lowerBound, //lower bound
upperBound //upper bound
);
typedef decltype(FON.objectiveA) ObjectiveTypeA;
typedef decltype(FON.objectiveB) ObjectiveTypeB;
arma::mat coords = FON.GetInitialPoint();
std::tuple<ObjectiveTypeA, ObjectiveTypeB> objectives = FON.GetObjectives();
opt.Optimize(objectives, coords);
std::vector<arma::mat> bestFront = opt.Front();
bool allInRange = true;
for (size_t i = 0; i < bestFront.size(); i++)
{
const arma::mat solution = bestFront[i];
double valX = arma::as_scalar(solution(0));
double valY = arma::as_scalar(solution(1));
double valZ = arma::as_scalar(solution(2));
if (!InBounds(valX, expectedLowerBound, expectedUpperBound) ||
!InBounds(valY, expectedLowerBound, expectedUpperBound) ||
!InBounds(valZ, expectedLowerBound, expectedUpperBound))
{
allInRange = false;
break;
}
}
REQUIRE(allInRange);
}
/**
* Optimize for the Fonseca Fleming function using MOEA/D-DE optimizer.
*/
TEST_CASE("MOEADFonsecaFlemingVectorBoundsTest", "[MOEADTest]")
{
FonsecaFlemingFunction<arma::mat> FON;
const arma::vec lowerBound("-4 -4 -4");
const arma::vec upperBound("4 4 4");
const double strength = 1e-3;
const double expectedLowerBound = -1.0 / sqrt(3);
const double expectedUpperBound = 1.0 / sqrt(3);
MOEAD opt(150, // population size
2000, // num generations
0.6, // cross over prob
0.7, // mutation prob
strength, // mutation strength
10, //neighbor size
0.5, //distribution index
0.5, //neighbor prob
0.8, //differential weight
10, //maxreplace,
lowerBound, //lower bound
upperBound //upper bound
);
typedef decltype(FON.objectiveA) ObjectiveTypeA;
typedef decltype(FON.objectiveB) ObjectiveTypeB;
arma::mat coords = FON.GetInitialPoint();
std::tuple<ObjectiveTypeA, ObjectiveTypeB> objectives = FON.GetObjectives();
opt.Optimize(objectives, coords);
std::vector<arma::mat> bestFront = opt.Front();
bool allInRange = true;
for (size_t i = 0; i < bestFront.size(); i++)
{
const arma::mat solution = bestFront[i];
double valX = arma::as_scalar(solution(0));
double valY = arma::as_scalar(solution(1));
double valZ = arma::as_scalar(solution(2));
if (!InBounds(valX, expectedLowerBound, expectedUpperBound) ||
!InBounds(valY, expectedLowerBound, expectedUpperBound) ||
!InBounds(valZ, expectedLowerBound, expectedUpperBound))
{
allInRange = false;
break;
}
}
REQUIRE(allInRange);
}