遗传算法解决排序问题

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

 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

遗传算法解决排序问题的相关文章

线程基础:多任务处理(13)——Fork/Join框架(解决排序问题)

============== 接上文< 线程基础:多任务处理(12)--Fork/Join框架(基本使用)> 3. 使用Fork/Join解决实际问题 之前文章讲解Fork/Join框架的基本使用时,所举的的例子是使用Fork/Join框架完成1-1000的整数累加.这个示例如果只是演示Fork/Join框架的使用,那还行,但这种例子和实际工作中所面对的问题还有一定差距.本篇文章我们使用Fork/Join框架解决一个实际问题,就是高效排序的问题. 3-1. 使用归并算法解决排序问题 排序问题是

【高级算法】遗传算法解决3SAT问题(C++实现)

转载请注明出处:http://blog.csdn.net/zhoubin1992/article/details/46910079 1 SAT问题描写叙述 命题逻辑中合取范式 (CNF) 的可满足性问题 (SAT)是当代理论计算机科学的核心问题, 是一典型的NP 全然问题.在定义可满足性问题SAT之前,先引进一些逻辑符号. 一个 SAT 问题是指: 对于给定的 CNF 是否存在一组关于命题变元的真值指派使A为真. 显然,如A为真,则CNF的每一个子句中必有一个命题变元为1(真). 2 遗传算法

tsp问题——遗传算法解决

TSP问题最简单的求解方法是枚举法.它的解是多维的.多局部极值的.趋于无穷大的复杂解的空间,搜索空间是n个点的所有排列的集合,大小为(n-1)!.可以形象地把解空间看成是一个无穷大的丘陵地带,各山峰或山谷的高度即是问题的极值.求解TSP,则是在此不能穷尽的丘陵地带中攀登以达到山顶或谷底的过程. 这一篇将用遗传算法解决TSP问题. 1)评价.这个评价算法应该比较简单了,就是找计算总距离,小的为优.目标函数转化为适应度函数可以取倒数. 2)突变.为了防止重复访问,不能随机的进行突变.因为每个城市只能

遗传算法解决3SAT问题(C++实现代码)

1 SAT问题描述 命题逻辑中合取范式 (CNF) 的可满足性问题 (SAT)是当代理论计算机科学的核心问题, 是一典型的NP 完全问题.在定义可满足性问题SAT之前,先引进一些逻辑符号. 一个 SAT 问题是指: 对于给定的 CNF 是否存在一组关于命题变元的真值指派使A为真. 显然,如A为真,则CNF的每个子句中必有一个命题变元为1(真). 2 遗传算法 遗传算法类似于自然进化,通过作用于染色体上的基因寻找好的染色体来求解问题.与自然界相似,遗传算法对求解问题的本身一无所知,它所需要的仅是对

遗传算法解决0-1背包问题

1 import numpy 2 import matplotlib.pyplot as plt 3 4 5 data = numpy.array([[77, 92], 6 [22, 22], 7 [29, 87], 8 [50, 46], 9 [99, 90]]) 10 11 12 class GA(object): 13 """ 14 遗传算法解决0-1背包问题 15 """ 16 17 def __init__(self, length,

遗传算法解决TSP问题

1实验环境 实验环境:CPU [email protected],内存6G,windows7 64位操作系统 实现语言:java (JDK1.8) 实验数据:TSPLIB,TSP采样实例库中的att48数据源 数据地址:http://comopt.ifi.uni-heidelberg.de/software/TSPLIB95/tsp/att48.tsp.gz TSPLIB是一个从各种来源和各种类型中产生的TSP及其相关问题的采样实例库,这里选取TSP采样实例库中的att48数据源,最优值为106

人工智能-遗传算法解决推箱子问题现实

原创作品,出自 "晓风残月xj" 博客,欢迎转载,转载时请务必注明出处(http://blog.csdn.net/xiaofengcanyuexj). 由于各种原因,可能存在诸多不足,欢迎斧正! 一.研究背景 推箱子游戏中的路径查找问题-给定一方格,求两点最短距离. 传统求两点最短路径的算法有: 1.通用的搜索算法 2.解决无负权边的带权有向图的单源最短路问题的Dijkstra算法 3.求解含负权边的带权有向图的单源最短路径问题的Bellman-Ford算法 4.Bellman-for

用遗传算法解决TSP问题

浅谈遗传算法:https://www.cnblogs.com/AKMer/p/9479890.html Description \(mzf\)在踏上寻找\(oxy\)的路程之后不小心碰到了大魔王\(fater\). 大魔王看了看\(mzf\)的命运,心生怜悯,便给\(mzf\)和自己做一个交换的机会. 这个交换是这样的: 由于\(oxy\)不知在天涯海角,\(mzf\)的要找到实在是太难了.所以大魔王愿意把\(mzf\)和\(oxy\)同时扔到一个迷宫(\(n\)个点的完全无向图)里,但是\(o

遗传算法解决旅行商问题GA_TSP

心血来潮把GA_TSP问题用C++封装起来搞了一遍,期间真是收益不小. 主要是用STL中的vector和list,结构体赋值中遇到了一些难点,原谅我自己是一棵白菜. 选择方法:用种群前面最优的20%代替后面的20%进行淘汰(当然这个比例可以自己拟定,修改代码中得pm_即可). 变异方法:交换一个路径上随机产生的两个城市. 交叉方法:三交换启发交叉(THGA). genticTsp.h 代码如下: 1 #ifndef GENTIC_TSP_H_ 2 #define GENTIC_TSP_H_ 3