14 #include "DifferentialEvolution.h"
15 #include "utils/Utilities.h"
23 unsigned int populationSize,
27 bool shouldCheckConstraints,
31 m_populationSize(populationSize),
35 m_minCost(-std::numeric_limits<double>::infinity()),
36 m_shouldCheckConstraints(shouldCheckConstraints),
38 m_terminationCondition(terminationCondition)
42 MPI_Initialized(&mpi_init);
44 MPI_Init(
nullptr,
nullptr);
47 MPI_Comm_rank(MPI_COMM_WORLD, &d_rank);
49 m_generator.seed(randomSeed);
50 CAROM_VERIFY(m_populationSize >= 4);
54 m_population.resize(populationSize);
55 for (
auto& agent : m_population)
57 agent.resize(m_numberOfParameters);
60 m_minCostPerAgent.resize(m_populationSize);
67 double cost_tolerance,
bool verbose)
69 CAROM_VERIFY(min_iterations <= max_iterations);
70 CAROM_VERIFY(min_iterations >= 0 && max_iterations > 0);
72 std::vector<double> optimal_parameters(m_numberOfParameters);
79 for (
int i = 0; i < max_iterations; i++)
82 prevMinCost = m_minCost;
83 SelectionAndCrossing();
85 if (d_rank == 0 && verbose)
87 std::cout <<
"Iteration: " << i <<
"\t\t";
88 std::cout <<
"Current minimal cost: " << m_minCost <<
"\t\t";
89 std::cout <<
"Best agent: ";
90 for (
int j = 0; j < m_numberOfParameters; j++)
92 std::cout << m_population[m_bestAgentIndex][j] <<
" ";
94 std::cout << std::endl;
97 for (
int j = 0; j < m_numberOfParameters; j++)
99 optimal_parameters[j] = m_population[m_bestAgentIndex][j];
102 if (i >= min_iterations && prevMinCost - m_minCost <= cost_tolerance)
104 if (d_rank == 0 && verbose)
107 "Terminated due to cost tolerance condition being met." <<
110 return optimal_parameters;
118 if (m_terminationCondition)
120 if (m_terminationCondition(*
this))
122 if (d_rank == 0 && verbose)
125 "Terminated due to positive evaluation of the termination condition." <<
128 return optimal_parameters;
133 if (d_rank == 0 && verbose)
135 std::cout <<
"Terminated due to exceeding total number of generations." <<
139 return optimal_parameters;
143 DifferentialEvolution::CheckConstraints(std::vector<double> agent)
145 for (
int i = 0; i < agent.size(); i++)
147 if (!m_constraints[i].Check(agent[i]))
157 DifferentialEvolution::InitPopulation()
160 std::shared_ptr<std::uniform_real_distribution<double>> distribution;
162 for (
auto& agent : m_population)
164 for (
int i = 0; i < m_numberOfParameters; i++)
166 if (m_constraints[i].isConstrained)
168 distribution = std::make_shared<std::uniform_real_distribution<double>>
169 (std::uniform_real_distribution<double>(m_constraints[i].lower,
170 m_constraints[i].upper));
174 distribution = std::make_shared<std::uniform_real_distribution<double>>
175 (std::uniform_real_distribution<double>(g_defaultLowerConstraint,
176 g_defaultUpperConstraint));
179 agent[i] = (*distribution)(m_generator);
184 for (
int i = 0; i < m_populationSize; i++)
186 m_minCostPerAgent[i] = m_cost.
EvaluateCost(m_population[i]);
188 if (m_minCostPerAgent[i] < m_minCost)
190 m_minCost = m_minCostPerAgent[i];
191 m_bestAgentIndex = i;
197 DifferentialEvolution::SelectionAndCrossing()
199 std::uniform_real_distribution<double> distribution(0, m_populationSize);
201 double minCost = m_minCostPerAgent[0];
202 int bestAgentIndex = 0;
204 for (
int x = 0; x < m_populationSize; x++)
212 while (a == x || b == x || c == x || a == b || a == c || b == c)
214 a = distribution(m_generator);
215 b = distribution(m_generator);
216 c = distribution(m_generator);
220 std::vector<double> z(m_numberOfParameters);
221 for (
int i = 0; i < m_numberOfParameters; i ++)
223 z[i] = m_population[a][i] + m_F * (m_population[b][i] - m_population[c][i]);
227 std::uniform_real_distribution<double> distributionParam(0,
228 m_numberOfParameters);
229 int R = distributionParam(m_generator);
232 std::vector<double> r(m_numberOfParameters);
233 std::uniform_real_distribution<double> distributionPerX(0, 1);
236 var = distributionPerX(m_generator);
239 std::vector<double> newX(m_numberOfParameters);
242 for (
int i = 0; i < m_numberOfParameters; i++)
244 if (r[i] < m_CR || i == R)
250 newX[i] = m_population[x][i];
257 if (m_shouldCheckConstraints && !CheckConstraints(newX))
265 if (newCost < m_minCostPerAgent[x])
267 m_population[x] = newX;
268 m_minCostPerAgent[x] = newCost;
272 if (m_minCostPerAgent[x] < minCost)
274 minCost = m_minCostPerAgent[x];
280 m_bestAgentIndex = bestAgentIndex;
284 DifferentialEvolution::GetBestAgent()
const
286 return m_population[m_bestAgentIndex];
290 DifferentialEvolution::GetBestCost()
const
292 return m_minCostPerAgent[m_bestAgentIndex];
295 std::vector<std::pair<std::vector<double>,
double>>
296 DifferentialEvolution::GetPopulationWithCosts()
const
298 std::vector<std::pair<std::vector<double>,
double>> toRet;
299 for (
int i = 0; i < m_populationSize; i++)
301 toRet.push_back(std::make_pair(m_population[i], m_minCostPerAgent[i]));
308 DifferentialEvolution::PrintPopulation()
const
312 for (
auto agent : m_population)
314 for (
auto& var : agent)
316 std::cout << var <<
" ";
318 std::cout << std::endl;
DifferentialEvolution(const IOptimizable &costFunction, unsigned int populationSize, double F=0.8, double CR=0.9, int randomSeed=1, bool shouldCheckConstraints=true, std::function< void(const DifferentialEvolution &)> callback=nullptr, std::function< bool(const DifferentialEvolution &)> terminationCondition=nullptr)
Constructor.
std::vector< double > Optimize(int min_iterations, int max_iterations, double cost_tolerance, bool verbose=true)
Constructor.
virtual unsigned int NumberOfParameters() const =0
Return the number of parameters.
virtual double EvaluateCost(std::vector< double > &inputs) const =0
Evaluate the cost function with the current set of inputs.
virtual std::vector< Constraints > GetConstraints() const =0
Return the list of constraints.