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.

139 lines
3.3 KiB

#pragma once
#include "search_function.h"
class harmony : public search_function {
public:
harmony(function f) : search_function(f) {};
double search(int permutations, int dimensionality) {
this->dimensionality = dimensionality;
// Set up random start population
for (int p = 0; p < population_size; p++) {
std::vector<double> tmp;
for (int i = 0; i < dimensionality; i++){
tmp.push_back(fmod(randomMT(), (func.upper_bound * 2)) + func.lower_bound);
}
population.push_back(tmp);
}
double best_fitness = func.compute(population.at(0));
// Do a thousand iterations
int r = 0;
while (r < 1000){
// The rng to determine which of the 3 we chose
double rng = rand_between(0, 1);
// Accept up the the specified percentage, re init the rest
if (rng > r_accept) {
accept_and_generate();
}
// Harmonize
else if (rng > r_pa) {
for (int p = 0; p < population.size(); p++) {
for (int d = 0; d < dimensionality; d++) {
population.at(p).at(d) = population.at(p).at(d) + rand_between(1, 2) * rand_between(-1, 1);
}
}
}
// Introduce some stochasticity
else{
population.clear();
for (int p = 0; p < population_size; p++) {
std::vector<double> tmp;
for (int i = 0; i < dimensionality; i++){
tmp.push_back(fmod(randomMT(), (func.upper_bound * 2)) + func.lower_bound);
}
population.push_back(tmp);
}
}
// Sort the array and find the best fitness, record
std::sort(population.begin(), population.end(), [this](std::vector<double> a, std::vector<double> b){
return this->func.compute(a) < this->func.compute(b);
});
if (func.compute(population.at(0)) < best_fitness)
best_fitness = func.compute(population.at(0));
r++;
}
return func.compute(population.at(0));
};
private:
double r_accept = 0.8;
double r_pa = 0.1;
int population_size = 50;
int dimensionality = 0;
void accept_and_generate(){
// Resort the population so the best will be at(0)
std::sort(population.begin(), population.end(), [this](std::vector<double> a, std::vector<double> b){
return this->func.compute(a) < this->func.compute(b);
});
// Keep up to the accept rate
std::vector<std::vector<double>> tmp_pop;
for (int i = 0; (1.0 * i / population.size()) < r_accept; i++){
tmp_pop.push_back(population.at(i));
}
// Repopulate with random values
for (int p = 0; p < population_size - tmp_pop.size(); p++) {
std::vector<double> tmp;
for (int i = 0; i < dimensionality; i++){
tmp.push_back(fmod(randomMT(), (func.upper_bound * 2)) + func.lower_bound);
}
tmp_pop.push_back(tmp);
}
population = tmp_pop;
}
std::vector<std::vector<double>> population;
};