#include <cstdio>
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 10; ///初始族群大小
const int limitGen = 500; ///最多迭代代数
const double limitFitValue = 0.5; ///至少族群个体达到最大值的占比
int num[maxn]; ///每个族群个体的具体值
int bionum[maxn][5]; ///每个族群个体的二进制代码
int gen = 1; ///当前代数
int fitValue[maxn]; ///每个族群适应度的值
int maxValue = 0, maxValueNum = 0; ///该函数可求出的最大值及所其对应个体值
int totalFitValue = 0; ///各族群个体的总适应度
void initial(){ ///初始化族群
srand(time(0));
for(int i = 0;i < maxn;i++){
num[i] = rand() % 31;
}
}
void toBinary(int id){ ///将特定数转化为二进制数,参数为其id
int tmp = num[id];
for(int j = 4;j >= 0;j--){
if(tmp % 2 == 1) bionum[id][j] = 1;
tmp /= 2;
}
}
void toAllBinary(){
memset(bionum, 0, sizeof(bionum)); ///将整个族群值转为二进制
for(int i = 0;i < maxn;i++){
toBinary(i);
}
}
int getFitValue(int x){ ///得到每个族群个体的适应度
return x*x*x - 60*x*x + 900*x + 100;
}
void getAllFitValue(){ ///得到所有个体的适应度
for(int i = 0;i < maxn;i++){
fitValue[i] = getFitValue(num[i]);
}
}
int getTotalFitValue(){ ///求总适应度
int tmp = 0;
for(int i = 0;i < maxn;i++){
tmp += fitValue[i];
}
return tmp;
}
void select(){
totalFitValue = getTotalFitValue();
int tmp[maxn]; ///每个族群个体被选中的概率
for(int i = 0;i < maxn;i++){
tmp[i] = (int)(fitValue[i] * 100.0 / totalFitValue );
}
for(int i = 1;i < maxn - 1;i++){
tmp[i] = tmp[i] + tmp[i-1];
}
tmp[maxn-1] = 100;
/*printf("Test :\n");
for(int i = 0;i < maxn;i++){
printf("%d ",tmp[i]);
}
printf("\n");*/
srand(time(0));
int selectId[6]; ///待交叉的族群个体的下标
for(int i = 0;i < 6;i++){
int index = rand() % 100;
for(int j = 0;j < maxn;j++){
if(j == 0 && index >= 0 && index < tmp[0]){
selectId[i] = 0;
break;
}else if(index >= tmp[j-1] && index < tmp[j]){
selectId[i] = j;
break;
}
}
}
/*printf("Test :\n");
for(int i = 0;i < 6;i++){
printf("%d ",selectId[i]);
}
printf("\n");*/
///下面将选出来的个体进行单点交叉
int tmpNum[3] = {0,0,0}; ///存储每个子代的十进制数值
srand(time(0));
for(int i = 0;i < 3;i++){
int point = rand() % 5; ///此处求出交叉点
int tmpBio[5];
for(int j = 0;j < point;j++){
tmpBio[j] = bionum[selectId[i]][j];
}
for(int j = point;j < 5;j++){
tmpBio[j] = bionum[selectId[i] + 3][j];
}
///下面将交叉得到的子代解码成十进制数并保存在临时空间里
int x = 1;
for(int j = 4;j >= 0;j--){
if(tmpBio[j]) tmpNum[i] += x;
x *= 2;
}
tmpNum[i] %= 31;
}
/*printf("Test :\n");
for(int i = 0;i < 3;i++){
printf("%d ",tmpNum[i]);
}
printf("\n");*/
///下面将交叉得到的新个体加入原族群中并淘汰掉适应度更差的族群
int mintmp = 1e7, minid[3] = {7,8,9};
for(int i = 0;i < maxn;i++){
if(fitValue[i] < mintmp){
mintmp = fitValue[i];
minid[0] = i;
}
}
num[minid[0]] = tmpNum[0];
for(int i = 0;i < maxn;i++){
if(fitValue[i] < mintmp && i != minid[0]){
mintmp = fitValue[i];
minid[1] = i;
}
}
num[minid[1]] = tmpNum[1];
for(int i = 0;i < maxn;i++){
if(fitValue[i] < mintmp && i != minid[0] && i != minid[1]){
mintmp = fitValue[i];
minid[2] = i;
}
}
num[minid[2]] = tmpNum[2];
toAllBinary();
getAllFitValue();
/*printf("Test:\n");
for(int i = 0;i < maxn;i++){
for(int j = 0;j < 5;j++){
printf("%d",bionum[i][j]);
}
printf(" %d %d\n",num[i],fitValue[i]);
}*/
}
///以下为变异部分,采取互换变异的方法
void mutate(int id){
srand(time(0));
int a = rand() % 5;
int b = rand() % 5;
int tmp = bionum[id][a];
bionum[id][a] = bionum[id][b];
bionum[id][b] = tmp;
}
int main(){
initial();
toAllBinary();
getAllFitValue();
printf("第一代初始化值:\n");
for(int i = 0;i < maxn;i++){
for(int j = 0;j < 5;j++){
printf("%d",bionum[i][j]);
}
printf(" %d %d\n",num[i],fitValue[i]);
if(fitValue[i] > maxValue){
maxValue = fitValue[i];
maxValueNum = num[i];
}
}
double maxFitRate = 0.1; ///最大适应度个体在当前族群中的占比
while(maxFitRate <= limitFitValue && gen <= limitGen){ ///设定退出条件,即最大适应度在候选族群中占比超过七成或者遗传代数超过500代
printf("第%d代:目前出现过的最大值为%d 及其个体值为 %d\n",gen, maxValue, maxValueNum);
///选择、交叉,交叉概率设为0.6
select();
///变异,变异概率设为0.01
srand(time(0));
int tmp = rand() % 100;
if(0 <= tmp && tmp < 10){
mutate(tmp);
toAllBinary();
getAllFitValue();
}
///下面找出出现过的最大值及其个体值
for(int i = 0;i < maxn;i++){
if(fitValue[i] > maxValue){
maxValue = fitValue[i];
maxValueNum = num[i];
}
}
int tmp1 = 0;
//printf("Test:\n");
for(int i = 0;i < maxn;i++){
printf("%d ", num[i]);
if(num[i] == maxValueNum) tmp1++;
}
printf("tmp1 is %d\n", tmp1);
maxFitRate = tmp1 / 10.0;
gen++;
}
printf("当前确认最大值为%d 及其个体值为%d\n", maxValue, maxValueNum);
}
遗传算法实现对表达式求最大值的优化
猜你喜欢
转载自blog.csdn.net/m0_38073011/article/details/78924416
今日推荐
周排行