人工智能-遗传算法的实现
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
//计算适应度
total+=species1[i].adapt; //将每个个体的适应度加到总适应度里
}
else
//标记不是0,则求最大值
for(int i=0;i<species1.size();i++)
{
//计算种群中所有个体的适应度
species1[i].adapt=200+(3*species1[i].elem*species1[i].elem*species1[i].elem *species1[i].elem-17*species1[i].elem*species1[i].elem*species1[i].elem);//计算 适应度
//格式化输出函数头文件
//N为种群数,T为遗传代数 //交叉概率;变异概率
typedef struct {
int a[7]; int elem; double adapt; float select; float total_prob; }node;
//模拟生物个体的结构体
//数据的二进制 //数据的十进制 //数据的适应度 //数据的选择概率 //数据的累积概率
{
cout<<std::left<<setw(7)<<species1[i].elem;//输出个体代表的数值
if(i%10==9)
//每行输出10个元素
cout<<endl;
}
cout<<endl;
return true;
}
int main() {
srand((unsigned)time(0)); cout<<"请输入种群数:"<<endl; cin>>N; cout<<"请输入交叉率:"<<endl; cin>>cross_chance; cout<<"请输入变异率:"<<endl; cin>>change_chance; cout<<"请输入经历的代数:"<<endl;
//交叉函数
{
int cross_num=(int)N*cross_chance;//计算需要交叉的个体数量
ຫໍສະໝຸດ Baidu
if(cross_num%2==1)
//如果交叉的个体数量不是偶数
cross_num--;
//强制转化为偶数
int deliver;
//实现交叉的中转变量
for(int i=0;i<cross_num-1;i+=2)
vector<node> species1,species2;
//物种1;物种2
int build() {
node n; int elem=rand()%100+1; for(int i=0;i<7;i++)
n.a[i]=0; n.elem=elem; int remainder; int i=0; while(elem) {
int value=1;
//重新计算时用到的权值
for(int j=0;j<7;j++)
//从二进制最低位开始计算至最高位
{
species1[a1].elem+=species1[a1].a[j]*value;
value*=2;
}
}
return true;
}
int display()
//输出函数
{
for(int i=0;i<species1.size();i++)//输出种群中的所有个体
//将该个体存入种群中
int calculate(int flag)
//计算适应度、选择概率、累积概率的函数
{
double total=0;
//总适应度
if(flag==0)
//如果标记为0,求最小值
for(int i=0;i<species1.size();i++)
{
//计算种群中所有个体的适应度
for(int j=0;j<7;j++)
//从二进制最低位开始计算至最高位
{
species1[i].elem+=species1[i].a[j]*value;
species1[i+1].elem+=species1[i+1].a[j]*value; value*=2; } } return true; }
total+=species1[i].adapt; //将每个个体的适应度加到总适应度里
}
for(int i=0;i<species1.size();i++)//计算种群中所有个体的选择概率
{
species1[i].select=species1[i].adapt/total;//计算选择概率
species1[i].total_prob=species1[i].select;//选择概率作为累积概率
//需要选择N次,作为新的种群
{
float rand_num=((float)(rand()%100))/100;//产生0-1间的选择数
int j;
for(j=0;j<species1.size();j++)//对所有个体比较
if(species1[j].total_prob>=rand_num)//选择数在该个体的累积概率区间
int change()
//变异的函数
{
int change_num=(int)species1.size()*7*change_chance;//计算要变异的基因个数
for(int i=0;i<change_num;i++) //变异change_num次
{
int a1=rand()%species1.size();//随机选择变异个体
int a2=rand()%7;
//随机选择变异个体的变异基因
if(species1[a1].a[a2]==1) //将变异个体的变异基因变异
species1[a1].a[a2]=0;
else
species1[a1].a[a2]=1;
species1[a1].elem=0;
//重新计算该个体代表的数值
break;
//说明选中此个体,不用继续比较
species2.push_back(species1[j]);//将选中的个体保存
}
species1=species2;
//新的种群代替原来的种群
species2.clear();
//保存选中个体的种群清空
return true;
}
int cross()
species1[i].adapt=800000000-(3*species1[i].elem*species1[i].elem*species1[i
].elem*species1[i].elem-17*species1[i].elem*species1[i].elem*species1[i].elem);
{
int n=rand()%5;
//随机产生交叉位数
deliver=species1[i].a[n]; //交换第一个基因
species1[i].a[n]=species1[i+1].a[n];
species1[i+1].a[n]=deliver;
deliver=species1[i].a[n+1]; //交换第二个基因
姓名:吕文庆
实验二、遗传算法
学号:E21314056
实验完成日期:2015-11-20
题目:
利用遗传算法求3������5 − 17������4的最大值与最小值,取值范围0~100之间。
算法分析:
1.取值范围 根据遗传算法的特点,将������=100 转换成二进制,得到110 0100,所以,存储结构应该采
用 7 位二进制模拟,即������的染色体上有 7 个基因。根据生物遗传的特点,所有的基因都可能 产生变异,所有的基因都可以表达,则 7 个基因可能出现111 1111的情况,即最大数可以 是 127,而这是合法的,因此,修改题目中������的取值范围为0~127。 2.适应度
原适应度函数的最大值为3 ∗ 1275 − 17 ∗ 1274 = 9.4693������ + 10,采用 double 型变量存 储适应度,double 型变量共 8 个字节,有8 ∗ 8 = 64位,26 = 9.2234������ + 18。理论上,计 算结果是不会产生溢出的,然而在实际实验验证过程中,产生了溢出,导致部分数据的适应 度为负数,故改适应度函数为3������4 − 17������ 。
为了防止适应度出现负数,需要对适应度函数进行适当的修改。根据计算,最小值在 ������ = 2.8333处取得,而3 ∗ 2.83334 − 17 ∗ 2.8333 = −193.3356,因此,将适应度函数改为 200 + 3������4 − 17������ ,保证适应度不会出现负数。
在求最小值的时候,只要对适应度函数取反,得−(3������4 − 17������ ),就可以把最大值的适 应度变为最小,把最小值的适应度变为最大。此时最小值在������ = 127处取得,而3 ∗ 1274 − 17 ∗ 127 = 7 4561 1412,故修改适应度函数为:8 0000 0000 − (3������4 − 17������ ),保证适应 度不会出现负数。
if(i!=0)
//如果这个个体不是种群的第一个
{
//累积概率=上个个体累积概率+自身选择概率
species1[i].total_prob+=species1[i-1].total_prob;
}
}
return true;
}
int select_copy()
//选择-复制函数
{
for(int i=0;i<N;i++)
现同一个个体的同一位基因变异多次的情况,导致变异的优秀基因被变回原来的基因。
实验源代码:
#include<iostream> #include<vector> #include<ctime> #include<iomanip> #define MAX 1 #define MIN 0 using namespace std; int N,T; float cross_chance,change_chance;
species1[i].a[n+1]=species1[i+1].a[n+1];
species1[i+1].a[n+1]=deliver;
species1[i].elem=0;
//两个交叉个体代表的数置0,重新计算
species1[i+1].elem=0;
int value=1;
//重新计算时用到的权值
3.选择-复制 采用传统的遗传算法的选择-复制方式。产生一个0~1间的随机数,随机数落在哪个数
的累积概率区间,则选择这个数作为下一代的一个个体。按照此方法,选择 N(N 为种群中 个体数)次。
4.交叉 根据交叉率,计算出要交叉的个体数,并向下取偶,对相邻的两个个体进行交叉处理。
因为不同的父母双亲的交叉的基因段不同,所以在交叉函数中,使用随机数产生随机的交叉 基因段 2 位,交换父母双亲的 2 位交叉基因段作为新的个体。这种算法的优点是:交叉的位
//随机数种子,多次调用产生的随机数不同
cin>>T;
getchar();
//输入任意字符开始计算
cout<<"开始求最大值:"<<endl;
for(int i=0;i<N;i++)
//根据种群的大小创建种群
build();
for(int i=0;i<T;i++)
//根据代数进行遗传算法求最大值
{
置是可变的,因此交叉产生优秀基因的概率很大。缺点是:交叉双亲是固定的,交叉的基因 个数是固定的,有一定的局限性。
5.变异 根据变异率,计算出需要变异的基因个数 n。然后变异 n 次,每次随机选择一个个体,
对该个体的随机的基因位进行变异。这种算法的优点是:变异是无规律的,变异出最优基因 的概率大。同时,这种算法的缺陷比较大:1.会出现一个个体变异多个基因的情况;2.会出
cout<<"第"<<i+1<<"代:"<<endl;
display();
calculate(MAX);
//求最大值
select_copy();
//选择-复制
cross();
//交叉
change();
//变异
}
getchar();
//输入任意字符开始计算
cout<<"开始求最小值:"<<endl;
species1.clear();
remainder=elem%2; n.a[i]=remainder; elem=elem/2; i++; } species1.push_back(n); return true; }
//创建生物个体的函数
//随机产生1-100内的一个数,作为起始个体 //对该数值的二进制初始化 //存储该数值 //余数,转换为二进制用 //转换为二进制 //对2取余,获得余数 //存储余数,作为二进制 //除以2