1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
|
#include "Genetic.h"
Genetic::Genetic(std::string s) {
this->text = s;
this->lenght = s.length();
this->population = 0;
this->max_rate = 0;
this->average_suc_rate = 0;
this->passed = false;
this->generation = 0;
this->popGenes.resize(Genetic::POPULATION_SIZE);
this->best.clear();
}
Genetic::Genetic(const Genetic& orig) {
}
Genetic::~Genetic() {
}
// imposta la popolazione e avvia l'evoluzione
std::vector<Genetic::Gene> Genetic::execute() {
// creo la prima popolazioni di geni
this->firstPopulation();
cout << "PARTE L'EVOLUZIONE" << endl;
return this->evolution(this->popGenes);
}
// avvia il processo di evoluzione
std::vector<Genetic::Gene> Genetic::evolution(std::vector<Gene> genes_data) {
if (genes_data[0].rate >= Genetic::SUCCESS_RATE) {
cout << "PAROLA TROVATA DOPO: " << this->population << endl;
return genes_data;
} else {
if (this->best.size() > this->popGenes.size()) {
for (int i = this->best.size() - 1; i < this->popGenes.size(); i++) {
this->best.pop_back();
}
}
std::copy(this->best.begin(), this->best.end(), this->popGenes.begin());
return this->evolution(this->populate());
}
}
std::vector<Genetic::Gene> Genetic::populate() {
this->generation++;
//cout << "INIZIO DELLA GENERAZIONE: " << this->generation << endl;
Gene son1, son2;
bool mutation = false;
for (int k = 0; k < Genetic::CHILDREN; k++) {
for (int i = 0; i < this->popGenes.size(); i++) {
if (this->generation % Genetic::MUTATION_SIZE == 0) {
mutation = true;
}
if (this->popGenes[i].rate >= this->max_rate) {
son1 = this->generate(this->popGenes[i].code, true);
} else {
if (this->popGenes[i].code != this->popGenes[i + 1].code && i < this->popGenes.size() - 1)
son1 = this->generate(this->cross(this->popGenes[i].code, this->popGenes[i + 1].code), mutation);
else if (this->popGenes[i].code != this->popGenes[i + 2].code && i < this->popGenes.size() - 2)
son1 = this->generate(this->cross(this->popGenes[i].code, this->popGenes[i + 2].code), mutation);
}
if (son1.rate > this->max_rate && !(this->in_array(son1))) {
cout << "TROVATO BEST: " << son1.word << endl;
this->max_rate = son1.rate;
this->best.push_back(son1);
}
}
}
std::sort(this->best.begin(), this->best.end(), this->sortByRate);
std::sort(this->popGenes.begin(), this->popGenes.end(), this->sortByRate);
return this->popGenes;
}
void Genetic::firstPopulation() {
//cout << "CREO LA PRIMA POPOLAZIONE" << endl;
Gene new_ind;
for (int i = 0; i < this->popGenes.size(); i++) {
this->population++;
bool mutation = true; // è la prima popolazione quindi muto tutti
// completo la generazione del Gene
new_ind = this->generate(this->genCode(), mutation);
this->popGenes[i].code = new_ind.code;
this->popGenes[i].rate = new_ind.rate;
this->popGenes[i].word = new_ind.word;
//cout << setw(2) << i << setw(this->lenght + 1) << this->popGenes[i].rate
//<< setw(this->lenght + 1) << this->popGenes[i].word << endl;
}
cout << "CREATA LA PRIMA POPOLAZIONE" << endl;
}
// crea un Gene con una parola random
Genetic::Gene Genetic::generate(int *gene_code, bool mutation) {
if (mutation) {
// applico una mutazione al gene
gene_code = this->mutate(gene_code);
}
std::string new_word = "";
for (int i = 0; i < this->lenght; i++) {
// prendo la lettera di posizione gene_code[i]
std::string letter = this->LETTERS.substr(gene_code[i], 1);
// creo la parola
new_word.append(letter);
}
Gene new_ind;
new_ind.code = gene_code;
new_ind.word = new_word;
// controllo se la parola creata è quella giusta
new_ind.rate = this->check_success(new_word);
return new_ind;
}
// genera un array di numeri da 0 a lenght
int *Genetic::genCode() {
// il numero indica la lettera dell'alfabeto
int *code = (int*) malloc(sizeof (int) * this->lenght);
for (int i = 0; i < this->lenght; i++) {
// creo un numero da zero alla lunghezza della parola da trovare -1
code[i] = rand() % Genetic::LETTERS.size();
}
return code;
}
// funzione per applicare una mutazione ad un gene
int *Genetic::mutate(int *code) {
// quante lettere devo mutare
int mutate_letter_num = floor(Genetic::MUTATION_RATE * this->lenght / 100);
int index;
// creo un nuovo codice
for (int i = 0; i < mutate_letter_num; i++) {
// l'indirizzo della lettera da mutare
index = rand() % this->lenght;
// eseguo la mutazione
code[index] = rand() % this->LETTERS.size();
}
return code;
}
// funzione che esegue il crossover su due Geni
int *Genetic::cross(int *g1, int *g2) {
int *code = (int*) malloc(sizeof (int) * this->lenght);
for (int i = 0; i < this->lenght; i++) {
int r = rand() % 2;
if (r > 0) {
code[i] = g1[i];
} else {
code[i] = g2[i];
}
}
return code;
}
// controlla la fitness della stringa
double Genetic::check_success(std::string word) {
double rate = 0.0;
//cout << word << endl;
// controllo carattere per carattere se ci sono lettere uguali
for (int i = 0; i < this->lenght; i++) {
if (this->text.at(i) == word.at(i))
rate++;
}
// calcolo la fitness
return (rate / this->lenght);
}
// funzione per controllare se un Gene è nel vettore best
bool Genetic::in_array(Genetic::Gene needle) {
int max = this->best.size();
if (max == 0) return false;
// se ha code, rate e word uguali allora sono uguali
for (int i = 0; i < max; i++)
if (this->best[i].code == needle.code && this->best[i].rate == needle.rate && this->best[i].word == needle.word)
return true;
return false;
}
// funzione di ordinamento dei geni per rate
bool Genetic::sortByRate(const Genetic::Gene &lhs, const Genetic::Gene &rhs) {
return lhs.rate > rhs.rate;
}
|