You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

170 lines
5.6 KiB

#pragma once
#include "search_function.h"
class differential_evolution : public search_function {
public:
differential_evolution(function f) : search_function(f) {};
double search(int permutations, int dimensionality) {
// Set up random start
std::vector<std::vector<double>> population = generate_population(50, dimensionality);
for (int g = 0; g < maximum_generation_number; g++) {
for (int i = 0; i < population.size(); i++) {
// Create the U, temp vector to hold values
std::vector<double> u(dimensionality, 0);
// select a random dimension
int j_rand = rand() % dimensionality;
for (int j = j_rand; j < dimensionality; j++){
// Accept changes if rng returns < 0.9
if (randomMT() * 1.0 / RAND_MAX < 0.9)
u.at(j) = check_bounds(compute_with_strategy(&population, j, i));
else
u.at(j) = population.at(i).at(j);
}
// If the new population has a better fitness, replace it
if (func.compute(population.at(i)) > func.compute(u))
population.at(i) = u;
}
}
// Generation is done, return the best value from the population
std::sort(population.begin(), population.end(), [this](std::vector<double> a, std::vector<double> b){
return this->func.compute(a) < this->func.compute(b);
});
return func.compute(population[0]);
};
void set_strategy(int strategy){
this->strategy = strategy;
}
private:
// G
int maximum_generation_number = 30;
// Tuning variable
double tuning_variable_f = 0.8;
double tuning_variable_lambda = 1.0;
int strategy = 0;
// Compute using different strategies
double compute_with_strategy(std::vector<std::vector<double>> *population, int j, int i){
// Setup and find the best solution in the population that was passed in
std::vector<double> best_solution;
double best_fitness = 999999999999;
for (auto p: *population){
double val = func.compute(p);
if (val < best_fitness){
best_fitness = val;
best_solution = p;
}
}
// Depending on the strategy, determine the new solution at J
switch(strategy){
case 1: {
std::vector<int> r = distinct_indices(2, population[0].size());
return best_solution[j] + tuning_variable_f * (population->at(r[0]).at(j) - population->at(r[1]).at(j));
}
case 2: {
std::vector<int> r = distinct_indices(3, population[0].size());
return population->at(r[0]).at(j) + tuning_variable_f * (population->at(r[1]).at(j) - population->at(r[2]).at(j));
}
case 3:{
std::vector<int> r = distinct_indices(2, population[0].size());
return population->at(i).at(j) + tuning_variable_lambda * (best_solution.at(j) - population->at(i).at(j)) + tuning_variable_f * (population->at(r[0]).at(j) - population->at(r[1]).at(j));
}
case 4:{
std::vector<int> r = distinct_indices(4, population[0].size());
return best_solution.at(j) + tuning_variable_f * (population->at(r[0]).at(j) + population->at(r[1]).at(j) - population->at(r[2]).at(j) - population->at(r[3]).at(j));
}
case 5:{
std::vector<int> r = distinct_indices(5, population[0].size());
return population->at(r[4]).at(j) + tuning_variable_f * (population->at(r[0]).at(j) + population->at(r[1]).at(j) - population->at(r[2]).at(j) - population->at(r[3]).at(j));
}
case 6:{
std::vector<int> r = distinct_indices(2, population[0].size());
return best_solution.at(j) + tuning_variable_f * (population->at(r[0]).at(j) - population->at(r[1]).at(j));
}
case 7:{
std::vector<int> r = distinct_indices(3, population[0].size());
return population->at(r[0]).at(j) + tuning_variable_f * (population->at(r[1]).at(j) - population->at(r[2]).at(j));
}
case 8:{
std::vector<int> r = distinct_indices(2, population[0].size());
return population->at(i).at(j) + tuning_variable_lambda * (best_solution.at(j) - population->at(i).at(j)) + tuning_variable_f * (population->at(r[0]).at(j) - population->at(r[1]).at(j));
}
case 9:{
std::vector<int> r = distinct_indices(4, population[0].size());
return best_solution.at(j) + tuning_variable_f * (population->at(r[0]).at(j) + population->at(r[1]).at(j) - population->at(r[2]).at(j) - population->at(r[3]).at(j));
}
case 10:{
std::vector<int> r = distinct_indices(5, population[0].size());
return population->at(r[4]).at(j) + tuning_variable_f * (population->at(r[0]).at(j) + population->at(r[1]).at(j) - population->at(r[2]).at(j) - population->at(r[3]).at(j));
}
}
}
std::vector<int> distinct_indices(int count, int max){
std::vector<int> indices;
for (int q = 0; q < count; q++) {
int val = 1 + (rand() % (max - 1));
while (std::count(indices.begin(), indices.end(), val) != 0)
val = randomMT() % max;
indices.push_back(val);
}
return indices;
}
};