遗传算法最重要的几个步骤
1.编码。
一般可采用二进制编码。本题使用和tsp相同的符号编码(可使用一个数组保存)
2.选择。根据个体的评分进行选择,涉及到累计概率。
3.交叉。通过互换基因,从而产生新的个体。
4.变异。产生新的个体。
1 #include <stdio.h> 2 #include <vector> 3 #include <time.h> 4 #include <stdlib.h> 5 #include <algorithm> 6 7 using namespace std; 8 9 vector<vector<int>> population; 10 vector<int> best_body; 11 int min_pair = INT_MAX;//最小的逆序对 12 13 int scale;//种群规模 14 int arrNum;//基因个数 15 16 int MAX_ROUND;//循环次数 17 int mutation_times; 18 19 float crossover_p;//交叉概率 20 float mutation_p;//变异概率 21 22 23 //初始化 24 void init() { 25 for (int i = 0; i < arrNum; ++i) { 26 best_body.push_back(0); 27 } 28 srand(time(NULL)); 29 for (int i = 0; i < scale; ++i) { 30 vector<int> temp; 31 for (int j = 0; j < arrNum;) { 32 int p = int(((double) rand() / RAND_MAX) * arrNum); 33 if (find(temp.begin(), temp.end(), p) == temp.end()) {//不存在 34 temp.push_back(p); 35 ++j; 36 } 37 } 38 population.push_back(temp); 39 } 40 41 } 42 43 44 //逆序对 45 int reverse_order_pair(vector<int> &vec) { 46 int sz = vec.size(); 47 int sm = 0; 48 for (int i = 0; i < sz; ++i) { 49 for (int j = i + 1; j < sz; ++j) { 50 if (vec[i] > vec[j]) { 51 ++sm; 52 } 53 } 54 } 55 return sm; 56 } 57 58 59 void copy(vector<int> &v1, vector<int> &v2) { 60 for (int i = 0; i < arrNum; ++i) { 61 v1[i] = v2[i]; 62 } 63 } 64 65 //计算评分 基于逆序对 66 vector<int> score(vector<vector<int>> &vec) { 67 vector<int> res; 68 int temp = INT_MAX; 69 int index = 0; 70 for (int i = 0; i < scale; ++i) { 71 int pairs = reverse_order_pair(vec[i]); 72 if (pairs < temp) { 73 temp = pairs; 74 index = i; 75 } 76 res.push_back(pairs); 77 } 78 79 if (temp < min_pair) { 80 min_pair = temp; 81 copy(best_body, vec[index]); 82 } 83 return res; 84 } 85 86 //计算积累概率 87 vector<double> cumulatePro(vector<int> &score) { 88 vector<double> res(scale); 89 double sm = 0; 90 for (double p:score) { 91 sm += 1 / (double) p; 92 } 93 res[0] = 1 / (double) score[0] / sm; 94 95 for (int i = 1; i < scale; ++i) { 96 res[i] = 1 / (double) score[i] / sm + res[i - 1]; 97 } 98 return res; 99 } 100 101 //选择 102 vector<vector<int>> choose(vector<double> &cumPro) { 103 vector<vector<int>> res; 104 for (int i = 0; i < scale; ++i) { 105 res.push_back(vector<int>(arrNum)); 106 } 107 for (int i = 0; i < scale - 1; ++i) { 108 double temp = (double) rand() / RAND_MAX; 109 110 if (cumPro[0] >= temp) { 111 copy(res[i], population[0]); 112 } else { 113 for (int j = 1; j < scale; ++j) { 114 if (cumPro[j - 1] < temp && temp <= cumPro[j]) { 115 copy(res[i], population[j]); 116 break; 117 } 118 } 119 } 120 } 121 copy(res[scale - 1], best_body); 122 return res; 123 } 124 125 126 //交叉 127 //交替位置交叉法 128 void crossover(vector<int> &v1, vector<int> &v2) { 129 vector<int> t1; 130 vector<int> t2; 131 int i = 0, j = 0; 132 while (i < v1.size() || j < v2.size()) { 133 if (find(t1.begin(), t1.end(), v1[i]) == t1.end()) { 134 t1.push_back(v1[i]); 135 ++i; 136 } else if (i < v1.size()) { 137 t2.push_back(v1[i]); 138 ++i; 139 } 140 141 if (find(t1.begin(), t1.end(), v2[j]) == t1.end()) { 142 t1.push_back(v2[j]); 143 ++j; 144 } else if (j < v2.size()) { 145 t2.push_back(v2[j]); 146 ++j; 147 } 148 } 149 copy(v1, t1); 150 copy(v2, t2); 151 } 152 153 //变异 154 void mutation(vector<int> &body) { 155 srand(time(NULL)); 156 for (int i = 0; i < mutation_times; ++i) { 157 int r1 = (int) ((double) rand() / RAND_MAX * arrNum); 158 int r2 = (int) ((double) rand() / RAND_MAX * arrNum); 159 while (r1 == r2) { 160 r2 = (int) ((double) rand() / RAND_MAX * arrNum); 161 } 162 swap(body[r1], body[r2]); 163 } 164 } 165 166 167 void crossAndMutation(vector<vector<int>> &newPop) { 168 srand(time(NULL)); 169 for (int i = 0; i < scale - 1; i += 2) { 170 float p1 = (float) rand() / RAND_MAX; 171 if (p1 > crossover_p) {//交叉 172 crossover(newPop[i], newPop[i + 1]); 173 } 174 } 175 //变异 176 for (int i = 0; i < scale; ++i) { 177 float p1 = (float) rand() / RAND_MAX; 178 if (p1 > mutation_p) { 179 mutation(newPop[i]); 180 } 181 } 182 } 183 184 //修正 将上一代最优的替换新一代最差的 185 void fixUp(vector<vector<int>> &newPop) { 186 int index = 0; 187 int pairs = 0; 188 for (int i = 0; i < scale; ++i) { 189 if (reverse_order_pair(newPop[i]) > pairs) { 190 pairs = reverse_order_pair(newPop[i]); 191 index = i; 192 } 193 } 194 copy(newPop[index], best_body); 195 } 196 197 198 int main() { 199 scale = 50;//种群规模 200 arrNum = 7;//基因个数 201 MAX_ROUND = 100;//循环次数 202 mutation_times = 4;//变异次数 203 crossover_p = 0.6;//交叉概率 204 mutation_p = 0.4;//变异概率 205 init(); 206 for (int i = 0; i < MAX_ROUND; ++i) { 207 vector<int> scoreVec = score(population);//评分 208 vector<double> pArr = cumulatePro(scoreVec);//积累概率 209 vector<vector<int>> newPop = choose(pArr);//选择 210 crossAndMutation(newPop);//交叉和变异 211 fixUp(newPop);//修正 212 population = newPop; 213 } 214 for (int temp:best_body) { 215 printf("%d ", temp); 216 } 217 return 0; 218 }
最开始没有精英策略,算法很不稳定,加入精英策略之后,算法变得比较稳定。
实例代码执行结果:
0 1 2 3 4 5 6
原文地址:https://www.cnblogs.com/oldBook/p/9866734.html
时间: 2024-11-07 03:09:25