遗传算法解决排序问题

遗传算法最重要的几个步骤

 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