1. 程式人生 > >遺傳算法解決排序問題

遺傳算法解決排序問題

mes sca pairs clas 逆序 sso back || 初始化

遺傳算法最重要的幾個步驟

 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

遺傳算法解決排序問題