说明:在学习生活中,经常会遇到各种各样的最优问题,其中最常见的就是求某个多维(多个自变量)函数在各个自变量各取何值时的最大值或最小值;例如求函数 f(x) = (x-5)2+(y-6)2+(z-7)2 的最小值,当然,这个函数很简单,很容易看出来,该函数的最小值为0,分别在三个自变量取5,6,7时取得最小值。但日常学习中的函数都是很复杂的,就算通过大量的计算,也不一定能准确地算出目标值以及在何时取得该目标值,因此,本文介绍一种基于单目标的遗传算法来解决此类问题。

注意:由于封装函数较多,为了清晰,函数名一般为其英文名,因此比较长,强烈建议电脑阅读。

1.遗传算法代码实现

遗传算法的相关概念,这里不多说,网上一大堆,这里只介绍本程序的实现过程,代码如下:

a.第一部分为主函数

 #include <iostream>
#include <genetic.h>
using namespace std; int main()
{
Genetic M;
int Iteration = 0;
//种群及重要参数初始化
M.initiallize(M.Initialpop,Populationsize);
cout<<"\n\t\t\t\t The Genetic Algrithm System\n"<<endl;
cout<<"\n\t\t\t\t\tThe Initial Pop:\n"<<endl;
cout<<setw(20)<<"x"<<setw(20)<<"y"<<setw(20)<<"z"<<setw(20)<<"Fitness"<<endl<<endl;
//获取种群适应度
M.getfitnessofpop(M.Initialpop,Populationsize);
//根据适应度排序
M.sortpopbyfitness(M.Initialpop,Populationsize);
//打印初始种群
M.printpop(M.Initialpop,Populationsize);
cout<<"\n\n\t\t\t\t\tThe Iteration Begins:\n"<<endl;
while(Iteration <= M.Iterationtimes)
{
//交叉
M.crossover(M.Initialpop,M.Offspring,Populationsize);
//求取种群适应度
M.getfitnessofpop(M.Offspring,Populationsize);
//根据适应度排序
M.sortpopbyfitness(M.Offspring,Populationsize);
//父子代结合
M.combinationpop(M.Initialpop,M.Offspring,M.Combinationpop,Populationsize);
//变异
M.mutation(M.Combinationpop,Populationsize*2);
//求取结合种群适应度
M.getfitnessofpop(M.Combinationpop,Populationsize*2);
//对结合种群排序
M.sortpopbyfitness(M.Combinationpop,Populationsize*2);
//选择较优个体
M.selectbestpop(M.Combinationpop,M.Initialpop,Populationsize);
//结果微调,精确算子
M.getAccurateResult(M.Initialpop,Populationsize);
//打印迭代过程中出现的最优个体
M.printbestindivil(M.Initialpop,Populationsize,Iteration);
Iteration++;
}
cout<<"\n\n"<<"The Last Population : \n\n"<<endl;
//打印最后一代的所有个体成员及其目标值
M.printpop(M.Initialpop,Populationsize);
cout<<"\n\n\n";
return 0;
}

b.第二部分为基因操作头文件

 #ifndef GENETIC_H
#define GENETIC_H
#include <time.h>
#include <stdlib.h>
#include <iomanip>
#include <iostream>
#include <math.h>
using namespace std;
#define Populationsize 16
#define pi 3.1415926
#define Accurate 0.001
#define NumOfParameters 10
//精度越高要求迭代次数越大 class Genetic
{
public:
Genetic();
typedef struct Individual
{
double parameter[Populationsize];
double fitness;
}Individuals;
Individuals Initialpop[Populationsize];
Individuals Offspring[Populationsize];
Individuals Combinationpop[Populationsize*2];
Individuals Bestindividual;
double downlimit[NumOfParameters];
double uplimit[NumOfParameters];
double crossoverability;
double mutationproability;
int NumOfParameter;
int Iterationtimes; void initiallize(Individuals *Initialpop,int Populationsiz);
void printpop(Individuals *Initialpop, int Populationsiz);
double getfitnessofindiv(Individuals Indiv);
void getfitnessofpop(Individuals *Initialpop,int Populationsiz);
void sortpopbyfitness(Individuals *Initialpop,int Populationsiz);
void crossover(Individuals *Initialpop,Individuals *offspring,int Populationsiz);
void combinationpop(Individuals *Initialpop,Individuals *offspring,Individuals* Combinationpop,int populationsize);
void mutation(Individuals *Initialpop,int population);
void selectbestpop(Individuals* Combinationpo,Individuals *Initialpop,int population);
void printbestindivil(Individuals* Initialpop,int populationsize, int Iteration);
void getAccurateResult(Individuals* Initialpop,int population);
}; #endif // GENETIC_H

c.第三部分为基因操作头文件相应的 cpp 文件

 #include "genetic.h"
Genetic::Genetic()
{ }
void Genetic::initiallize(Genetic::Individuals *Initialpop, int Populationsiz)
{
cout<<"Welcome To The Genetic Algrithm System......\n";
cout<<"\nPls Follow The Steps To Complete Your Compution.....\n\n";
cout<<"\nStep 0: Pls Make Sure The Marked Function Have Been Modefied.....\n";
cout<<"\nStep 1: Now Pls Input The Num Of Variations :";
cin>>NumOfParameter;
for(int i = 0;i<NumOfParameter;i++)
{
cout<<"\nStep "<<2*i+2<<" : Pls Input The Downlimit Of Variation "<<i+1<<" :";
cin>>downlimit[i];
cout<<"\nStep "<<2*i+3<<" : Pls Input The Uplimit Of Variation "<<i+1<<" :";
cin>>uplimit[i];
}
cout<<"\nStep "<<2*NumOfParameter+2<<" :Pls Input The Iteration Times:";
cin>>Iterationtimes;
srand(time(NULL));
crossoverability = 0.8;
mutationproability = 0.01;
for(int i=0; i<Populationsiz; i++)
{
for(int j = 0;j<NumOfParameter;j++)
{
Initialpop[i].parameter[j] = downlimit[j] + (rand()%50)/50.0*(uplimit[j]-downlimit[j]);
}
}
} void Genetic::printpop(Genetic::Individuals *Initialpop, int Populationsiz)
{
for(int i =0;i<Populationsiz;i++)
{
for(int j = 0;j<NumOfParameter;j++)
{
cout<<setw(20)<<setprecision(5)<<Initialpop[i].parameter[j];
}
cout<<setw(20)<<fixed<<setprecision(7)<<Initialpop[i].fitness<<endl;
}
} // Function 目标函数根据所求实际问题进行修改
double Genetic::getfitnessofindiv(Individuals Indiv)
{
double result;
result = -(Indiv.parameter[0]+12.5)*(Indiv.parameter[0]+12.5)-(Indiv.parameter[1]+7.6)*(Indiv.parameter[1]+7.6)
-(Indiv.parameter[2]+10.3)*(Indiv.parameter[2]+10.3);
return result;
}
//修改 void Genetic::getfitnessofpop(Genetic::Individuals *Initialpop, int Populationsiz)
{
for(int i = 0;i<Populationsiz;i++)
{
Initialpop[i].fitness = getfitnessofindiv(Initialpop[i]);
}
} void Genetic::sortpopbyfitness(Genetic::Individuals *Initialpop, int Populationsiz)
{
for(int i = 0;i<Populationsiz;i++)
{
int idx = i;
for(int j = i+1;j<Populationsiz;j++)
{
if(Initialpop[idx].fitness > Initialpop[j].fitness)
idx = j;
}
if(idx != i)
{
Individual temp = Initialpop[i];
Initialpop[i] = Initialpop[idx];
Initialpop[idx] = temp;
}
}
Bestindividual = Initialpop[0];
} void Genetic::crossover(Individuals *Initialpop,Individuals *offspring, int Populationsiz)
{
for(int i = 1;i<=Populationsiz;i++)
{
//保证适值为正
Initialpop[Populationsiz-i].fitness += -Initialpop[0].fitness;
}
srand(time(NULL));
Individuals parent[2];
double temp = 0;
double totalfitness = 0;
double gradient[Populationsiz] = {0};
for(int i = 0;i<Populationsiz;i++)
{
totalfitness += Initialpop[i].fitness;
}
for(int i = 0;i<Populationsiz;i++)
{
temp += Initialpop[i].fitness;
gradient[i] = temp/totalfitness;
}
for(int i = 0;i<Populationsiz/2;i++)
{
for(int j = 0;j<2;j++)
{
double randgradient = rand()%1000/1000.0;
for(int k = 0;k<Populationsiz;k++)
{
if(k == 0)
{
if(randgradient < gradient[0])
{
parent[j] = Initialpop[k];
}
}
else
{
if(randgradient >= gradient[k-1] && randgradient < gradient[k])
{
parent[j] = Initialpop[k];
}
}
}
}
double Probability = rand()%1000/1000.0;
if(Probability < crossoverability)
{
double b = rand()%100/100.0;
if(b <= 0.5)
{
double a = pow(2*b,1/21.0);
for(int j = 0;j<NumOfParameter;j++)
{
offspring[2*i].parameter[j] = ((1+a)*parent[0].parameter[j]+(1-a)*parent[1].parameter[j])/2.0;
offspring[2*i+1].parameter[j] = ((1-a)*parent[0].parameter[j]+(1+a)*parent[1].parameter[j])/2.0;
}
for(int j = 0;j<NumOfParameter;j++)
{
if(offspring[2*i].parameter[j] < downlimit[j] || offspring[2*i].parameter[j] > uplimit[j]
|| offspring[2*i+1].parameter[j] < downlimit[j] || offspring[2*i+1].parameter[j] >
uplimit[j])
{
i--;
break;
}
}
}
else
{
double a = pow(2*(1-b),-1/21.0);
for(int j = 0;j<NumOfParameter;j++)
{
offspring[2*i].parameter[j] = ((1+a)*parent[0].parameter[j]+(1-a)*parent[1].parameter[j])/2.0;
offspring[2*i+1].parameter[j] = ((1-a)*parent[0].parameter[j]+(1+a)*parent[1].parameter[j])/2.0;
}
for(int j = 0;j<NumOfParameter;j++)
{
if(offspring[2*i].parameter[j] < downlimit[j] || offspring[2*i].parameter[j] > uplimit[j]
|| offspring[2*i+1].parameter[j] < downlimit[j] || offspring[2*i+1].parameter[j] >
uplimit[j])
{
i--;
break;
}
}
}
}
else
{
for(int j = 0;j<NumOfParameter;j++)
{
offspring[2*i].parameter[j] = downlimit[j] + (rand()%50)/50.0*(uplimit[j]-downlimit[j]);
offspring[2*i+1].parameter[j] = downlimit[j] + (rand()%50)/50.0*(uplimit[j]-downlimit[j]);
}
}
}
} void Genetic::combinationpop(Individuals *Initialpop,Individuals *offspring,Individuals *Combinationpop,int populationsize)
{
for(int i = 0;i<populationsize*2;i++)
{
if(i < populationsize)
Combinationpop[i] = Initialpop[i];
else
Combinationpop[i] = offspring[i-populationsize];
}
} void Genetic::mutation(Genetic::Individuals *Initialpop, int population)
{
srand(time(NULL));
for(int i = 0;i<population;i++)
{
double a = rand()%100/100.0; if(a <= mutationproability)
{
for(int j = 0;j<NumOfParameter;j++)
{
Initialpop[i].parameter[j] = downlimit[j] + (rand()%50)/50.0*(uplimit[j]-downlimit[j]);
}
}
}
} void Genetic::selectbestpop(Individuals *Combinationpo,Individuals *Initialpop, int population)
{
for(int i = 0;i<population;i++)
Initialpop[i] = Combinationpo[population+i];
} void Genetic::printbestindivil(Genetic::Individuals *Initialpop, int populationsize,int Iteration)
{
cout<<"\r";
cout<<""<<Iteration;
for(int j = 0;j<NumOfParameter;j++)
{
cout<<setw(20)<<Initialpop[populationsize-1].parameter[j];
}
cout<<setw(20)<<Initialpop[populationsize-1].fitness;
} void Genetic::getAccurateResult(Genetic::Individuals *Initialpop, int population)
{
for(int j = 0;j<population;j++)
{
for(int i = 0;i<NumOfParameter;i++)
{
Individuals temp = Initialpop[j];
Individuals temp1 = Initialpop[j];
temp.parameter[i] = temp.parameter[i]*(1+Accurate);
if(getfitnessofindiv(temp) > getfitnessofindiv(Initialpop[i]) && temp.parameter[i] <= uplimit[i] &&
temp.parameter[i] >= downlimit[i])
{
Initialpop[j] = temp;
}
temp1.parameter[i] = temp1.parameter[i]*(1-Accurate);
if(getfitnessofindiv(temp1) > getfitnessofindiv(Initialpop[i]) && temp1.parameter[i] <= uplimit[i] &&
temp1.parameter[i] >= downlimit[i])
{
Initialpop[j] = temp1;
}
}
}
}

使用注意事项:

a.根据具体的目标函数修改评价函数方程,

b.按照程序运行提示傻瓜式的输入相应的参数即可,

c.Accurate 参数用于当目标函数趋于稳定状态时的优化,即探测此时自变量该精度变化范围内的目标函数变化情况,从而获得更为优越的目标值。应注意的是,当要求精度越高时,该参数要求尽量小,同时迭代次数应该尽可能地高。

d.本例中涉及一个任意维的单目标测试函数,使用源代码直接按照提示步骤输入相应的各个变量上下限及迭代次数即可。

(C/C++学习)20.基于C++改进的单目标遗传算法的更多相关文章

  1. (C/C++学习)19.单目标遗传算法的C程序实现

    说明:在学习生活中,经常会遇到各种各样的最优问题,其中最常见的就是求某个多维(多个自变量)函数在各个自变量各取何值时的最大值或最小值:例如求函数 f(x) = (x-5)2+(y-6)2+(z-7)2 ...

  2. 爬虫学习之基于Scrapy的爬虫自动登录

    ###概述 在前面两篇(爬虫学习之基于Scrapy的网络爬虫和爬虫学习之简单的网络爬虫)文章中我们通过两个实际的案例,采用不同的方式进行了内容提取.我们对网络爬虫有了一个比较初级的认识,只要发起请求获 ...

  3. OpenCV学习(20) grabcut分割算法

    http://www.cnblogs.com/mikewolf2002/p/3330390.html OpenCV学习(20) grabcut分割算法 在OpenCV中,实现了grabcut分割算法, ...

  4. Linux学习笔记——基于鸟哥的Linux私房菜

    Linux学习笔记--基于鸟哥的Linux私房菜 ***** ARM与嵌入式linux的入门建议 (1) 学习基本的裸机编程:ARM7或ARM9,理解硬件架构和控制原理 (这一步是绝对的根基) (2) ...

  5. Spark学习之基于MLlib的机器学习

    Spark学习之基于MLlib的机器学习 1. 机器学习算法尝试根据训练数据(training data)使得表示算法行为的数学目标最大化,并以此来进行预测或作出决定. 2. MLlib完成文本分类任 ...

  6. Qt学习虚拟机--基于MSYS2-MinGW环境并带有各种开源的软件库!

    Qt学习虚拟机--基于MSYS2-MinGW环境并带有各种开源的软件库!虚拟机地址,VM10和以上:http://pan.baidu.com/s/1slcTA49包含两个分卷压缩包,加起来5GB多. ...

  7. 六、Django学习之基于下划线的跨表查询

    六.Django学习之基于下划线的跨表查询 一对一 正向查询的例子为 已知用户名,查询用户的电话号码.反向查询例子反之. 正向查询 其中下划线前的表示表名,无下划线的表示的是Author表 resul ...

  8. 五、Django学习之基于对象的跨表查询

    五.Django学习之基于对象的跨表查询 正向与反向查询 关键在于ForeignKey字段写的位置.例如下面这段代码, 关系属性(字段)写在哪个类(表)里面,从当前类(表)的数据去查询它关联类(表)的 ...

  9. PyTorch专栏(八):微调基于torchvision 0.3的目标检测模型

    专栏目录: 第一章:PyTorch之简介与下载 PyTorch简介 PyTorch环境搭建 第二章:PyTorch之60分钟入门 PyTorch入门 PyTorch自动微分 PyTorch神经网络 P ...

随机推荐

  1. 关于Web API中使用ajax发送请求方式的问题

    参见以下文章 http://www.west-wind.com/weblog/posts/2012/May/08/Passing-multiple-POST-parameters-to-Web-API ...

  2. android简易双屏支持【转】

    本文转载自:http://blog.csdn.net/sfrysh/article/details/7463339 抱歉,之前说xorg的exa更新的时候恐怕一直不会更新了,没有做xorg开发了.转向 ...

  3. YTU 2506: 切面条

    2506: 切面条 时间限制: 1 Sec  内存限制: 128 MB 提交: 382  解决: 223 题目描述 一根高筋拉面,中间切一刀,可以得到2根面条.      如果先对折1次,中间切一刀, ...

  4. [Jsoi2015]字符串树

    https://www.zybuluo.com/ysner/note/1298148 题面 字符串树本质上还是一棵树,即\(N\)个节点\(N-1\)条边的连通无向无环图,节点 从\(1\)到\(N\ ...

  5. 洛谷 P1328 生活大爆炸版石头剪刀布 —— 模拟

    题目:https://www.luogu.org/problemnew/show/P1328 直接模拟即可. 代码如下: #include<iostream> #include<cs ...

  6. 0623-TP框架整理一(下载、入口文件、路由、创建控制器、调用模板、系统常量、命名空间)

    一.下载解压后用ThinkPHP(核心)文件 核心文件夹(ThinkPHP)不要改,是作用于全局的,有需要可以改应用目录(Application) 二.创建入口文件: 运行后出现欢迎界面,在说明系统自 ...

  7. uva 11292 The Dragon of Loowater(贪心)

    题目大意:   你的王国里有一条n个头的恶龙,你希望雇一些骑士把它杀死(即砍掉所有头).村里有m个骑士可以雇佣,一个能力值为x的骑士可以砍掉恶龙一个直径不超过x的头,且需要支付x个金币.如何雇佣骑士才 ...

  8. 洛谷P3698 [CQOI2017]小Q的棋盘

    传送门 考虑一个贪心,先在根节点周围转一圈,然后再往下走最长链肯定是最优的 然后设最长链的长度为$d$,如果$m\leq d$,那么答案为$m+1$ 否则的话还剩下$m-d+1$步,又得保证能走回来, ...

  9. StackOverflow 创始人关于如何高效编程的清单

    这是 StackOverflow 联合创始人 Jeff Atwood 注释的十戒.程序员普遍有很强的自尊心,都应该看看本文,打印下来时刻提醒自己. “无我编程”发生在开发阶段,表现为技术团队经常通过同 ...

  10. Visual Studio Code 扩展工具集,记录

    编码 提高效率及校验 Auto Close Tag 自动闭合标签 Auto Rename Tag 自动更改HTML/XML标签,不需要再进行二次修改,减少50%的工作量! Path Intellise ...