遗传算法 练习
来源:互联网 发布:怎么查看mac运行程序 编辑:程序博客网 时间:2024/06/10 03:13
一、 实验目的
1. 熟悉和掌握遗传算法的原理、实质。
2. 学会使用遗传算法解决问题。
3. 学会编写遗传算法程序寻找函数最值。
二、 实验内容
1. 用遗传算法解决下面函数的极大值问题。
参数设定可参考如下:
种群大小M=10
交叉概率 pc=0.6
变异概率 pm=0.02
迭代次数最多为100。
三、 算法实现
#include<bits/stdc++.h>
#define de(x) cout<<#x<<"="<<x<<endl
#define rep(i,a,b) for(int i=a;i<b;i++)
using namespace std;
const int M=10;
const double pc=0.6;
const double pm=0.02;
const int MAXT=100;
const int gn=5;
struct unit
{
int bit[gn];
int suit;
} gen[MAXT+5][M];
int gennum=0;
int maxx;
int maxgen;
unit tmp;
unit encode(int x)
{
int i=gn-1;
while(x)
{
tmp.bit[i--]=x%2;
x>>=1;
}
return tmp;
}
int decode(unit tmp)
{
int ans=0;
int i=0;
while(i!=gn) ans=ans*2+tmp.bit[i++];
return ans;
}
int fixable(unit u)
{
int s=decode(u);
return s*s;
}
void choose(int oldgen)//给出一个老一代的群体 选择出M个返回新一代群体的id
{
double p[M];
double sumf=0;
double sump[M];
int tmp=0;
memset(p,0,sizeof(p));
memset(sump,0,sizeof(sump));
rep(i,0,M) {
tmp=decode(gen[oldgen][i]);
sumf+=tmp;
if(tmp>maxx){maxx=tmp;maxgen=oldgen;}
}
de(sumf);
for(int i=0;i<M;i++) {p[i]=decode(gen[oldgen][i])*1./sumf;}
sump[0]=p[0];
for(int i=1;i<M;i++) sump[i]=sump[i-1]+p[i];
// for(int i=0;i<M;i++) cout<<sump[i]<<" ";cout<<endl;
rep(k,0,M){
double ran=rand()/double(RAND_MAX);
if(ran<=sump[0])
rep(j,0,gn) gen[oldgen+1][k].bit[j]=gen[oldgen][0].bit[j];
else
rep(i,0,M) {//M个个体 如果这个个体满足条件 插入并
if(sump[i]>=ran)
{/* cout<<"ran="<<ran<" ";
cout<<"选择了"<<decode(gen[oldgen][i])<<endl;*/
rep(j,0,gn) gen[oldgen+1][k].bit[j]=gen[oldgen][i].bit[j];
break;
}
}
}
gennum++;
}
void cross(int nowgen)
{
for(int k=0;k*2<M*pc;k++)
{
int a=rand()%M;
int b=rand()%M;
int pos=rand()%gn;
for(int i=0;i<=pos;i++) swap(gen[nowgen][a].bit[i],gen[nowgen][b].bit[i]);
}
}
int vary(int nowgen)
{
int k=M*gn*pm;
for(int i=0;i*2<k;i++)
{
int n=rand()%M;//变异个体
int m=rand()%gn;//变异基因编号
gen[nowgen][n].bit[m]=1-gen[nowgen][n].bit[m];
}
}
void show(int i)
{
cout<<"第"<<i<<"代:"<<endl;
for(int j=0;j<M;j++) cout<<decode(gen[i][j])<<" ";
cout<<endl;
}
void init()
{
srand((unsigned)time(0));
gennum=0;
for(int i=0;i<M;i++)
{
for(int j=0;j<gn;j++)
gen[0][i].bit[j]=(rand()/double(RAND_MAX))>0.5?1:0;
}
show(0);
}
int main ()
{
init();
maxx=0;
for(int i=0;i<MAXT;i++)
{
choose(i);
cross(i+1); //交叉
vary(i+1);// 变异
show(i+1); //显示
}
cout<<"近似最优解是来自第"<<maxgen<<"代的"<<maxx<<endl;
return 0;
}
四、 实验结果
当参数为:
时;
五、 实验体会
本次实验主要学习了遗传算法的简单应用。遗传算法主要是模拟
->群体->环境选择->产生下一代群体->环境选择...的过程。
算法设计方面:
1. 要设计编码函数,解码函数用来将直观个体和字符编码(基因)相互转义。
2. 设计合理的选择函数,本次实现中用了常用的赌轮法,将个体的适应度对应为选择该个体的几率。
3. 设计交叉变异函数,用来将字符编码进行相互交配,产生下一代群体。
4. 对于每一代,在交叉产生下一代时是否同时把父母替代,是否保留最优的N个,是否淘汰最差等等有不同的实现方法。
代码实现方面:
1. 设计合理的数据结构存储基因串,可以降低时间复杂度。
2. 利用预定义和宏扩大程序的适用范围。
本次实验的收获:
1. 学到了基于估计计算确定需要交叉(变异)的个体(基因)数量的方法。
2. 大概学习了C++中srand() rand()的原理。
【Rand()是一个伪随机函数,srand()用来设置rand()函数中的seed种子,如果seed是一个定值的话,得到的序列是确定的,如果seed是一个time(0)等其他动态变化的参数的话就可以模拟随机函数】
3. 第一次用代码实现赌轮法。
4. BUGS
a) 又一次被sum[i]+=p[i]这个我的经典错误代码坑到了
b) 脑子一抽写出了i!=i这样的取反函数...
c) 边界条件错了一发,调了挺久才发现。比如赌轮法中如果有若干个0取值需要注意不能取到0的上一个或下一个(如果是连续的0则还会取到0),应该用> <跳过0的情况。
- 遗传算法 练习
- 遗传算法
- 遗传算法
- 遗传算法
- 遗传算法
- 遗传算法
- 遗传算法
- 遗传算法
- 遗传算法
- 遗传算法
- 遗传算法
- 遗传算法
- 遗传算法
- 遗传算法
- 遗传算法
- 遗传算法
- 遗传算法
- 遗传算法
- I2C上拉电阻的选择(最小值)
- leetcode解题方案--058--Length of Last Word
- 排序算法的总结(插入排序、冒泡排序、选择排序)
- 调试笔记 — Redis 消息队列发布信息被消费者重复订阅多次牵扯到的 Tomcat 配置问题 [#00001]
- Hibernate: cannot simultaneously fetch multiple bags 问题的解决办法
- 遗传算法 练习
- 第一次asp链接数据库成功
- 【JavaScript】方法属性的匿名函数是匿名函数么(附:获取当前执行函数名称的方法)
- 【arudino】RosBot 开发日记(1)------控制两个步进电机
- 使用FormData上传文件
- 文章标题
- iOS开发中静态库制作 之.a静态库制作及使用篇
- centos 6.5下安装、配置并启动SSH远程访问
- Intellij IDEA 2017 使用maven创建javaweb入门