/*
程序功能:实现nsga2算法,测试函数为ZDT1,ZDT2,ZDT3,ZDT4,ZDT6,DTLZ1,DTLZ2
说明:遗传算子为二进制竞赛选择,模拟二进制交叉和多项式变异
作者:(晓风)
email: 18821709267@163.com
参考论文:
A fast and Elitist Multiobjective Genetic Algorithm:NSGA-Ⅱ
Kalyanmoy Deb,Associate Member, IEEE, Amrit Pratap, Sameer Agarwal, and T.Meyarivan
IEEE TRANSACTIONS ON EVOLUTIONARY COMPUTATION
最初建立时间:2018.10.12
最近修改时间:2018.10.19
*/
/*
算法使用说明:
1.本算法为NSGA2,实验采用的测试函数为ZDT1,ZDT2,ZDT3,ZDT4,ZDT6,DTLZ1,DTLZ2,要选择哪个函数请修改第123行。
2.文件输出路径请修改中127行的a数组,格式必须与a保持相同,第125行设置路径中的实验次数(做几次实验就设到几,比如设置十次实验就1-10,最大实验次数为10,增加最大实验次数还需修改213行之后,增加与上述相同的随机种子选项即可)。
3.采用新的测试函数请修改input.h(13行开始是函数的约束条件)和func.h(41行开始是函数编写的部分)两个文件。
4.本算法默认采用实数编码,但迭代过程中进行了二进制编码,二进制编码采用了两种交叉类型,单点交叉和均匀交叉,选择那个修改input.h的11行。如果要使用二进制编码,请将func.h中的33-38行注释变成代码,29-32行加上注释,即得到二进制编码的结果。
5.本实验可修改的参数(input.h中)有popsize(种群大小),gener(迭代次数),pcross(交叉概率),di(SBX交叉参数),dim(多项式变异参数),pmut_r(实数编码的变异概率),pmut_b(二进制编码的变异概率)
6.实验的最大种群数为500,最大染色体长度为300,最大变量数目为30,最大函数数目为10,pi定义为3.1415926
7.实验输出结果有三个文件:1)output.txt 包含参数设置,每代的自变量值(实数编码,二进制编码),函数值,等级和拥挤度。2)fun.txt包含最后一代输出的函数值 3)time.txt包含程序运行时间
8.本实验没有实现约束问题,得再次算法的基础上进行修改。
*/
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>
#include <string.h>
#define square(x) ((x)*(x))
#define maxpop 500//最大种群数
#define maxchrom 300/*最大染色体长度*/
#define maxvar 30 //最大变量数目
#define maxfun 10 //最大函数数目
#define PI 3.1415926
int gener,//迭代数目
nvar,nchrom,//变量数目,染色体数目(二进制)
vlen[maxvar],//储存每个变量的位的个数的数组(二进制)
optype,//交叉类型:1为单点交叉和2为均匀交叉(二进制)
nfunc,//函数数目
nmut,//变异的个数
ncross;//交叉的次数
float seed,//随机种子
pcross,//交叉概率
pmut_b,pmut_r,//变异概率
lim_b[maxvar][2],lim_r[maxvar][2],//数组中变量的限制
di,//交叉的分布指数
dim;//变异的分布指数
static int popsize,//种群数目
chrom;//染色体总长度
double coef[maxvar];//解码使用的变量
/*个体*/
typedef struct
{
int genes[maxchrom],//二进制染色体
rank, //个体等级
flag; //等级标志
float xreal[maxvar],//实变量的集合
xbin[maxvar];//染色体解码之后的集合
float fitness[maxfun],//适应度函数
crowd; //拥挤距离
}individual;
/*种群*/
typedef struct
{
int maxrank;//当前种群的最大等级
int rankno[maxpop];//个体的等级
individual ind[maxpop],//个体的集合
*ind_str;
}population;
#include "input.h" /*输入条件*/
#include "random.h" /*随机数量的算子*/
#include "realinit.h" /*随机初始化种群*/
#include "init.h" /*随机初始化种群*/
#include "decode.h" /*解码二进制串*/
#include "ranking.h" /*产生pareto前端*/
#include "func.h" /*函数设置*/
#include "select.h" /*二进制锦标赛*/
#include "bincross.h" /*二进制交叉*/
#include "uniformxr.h" /*均匀交叉*/
#include "realcross.h" /*实数交叉*/
#include "binmut.h" /*二进制变异*/
#include "realmut.h" /*实数变异*/
#include "keepaliven.h" /*精英选择和共享机制*/
#include "report.h" /*打印输出报告*/
population old_pop,
new_pop,
mate_pop,
*old_pop_ptr,
*new_pop_ptr,
*mate_pop_ptr;
//定义种群结构
//计算程序运行时间
clock_t start, stop;
// clock_t 是 clock() 函数返回的变量类型
double duration;
// 纪录被测函数运行的时间, 单位为秒
//测试函数类型
int fun_input= 1;//1-ZDT1,2-ZDT2,3-ZDT3,4-ZDT4,5-ZDT6,6-DTLZ1,7-DTLZ2
char ex_number[]="1";//设置路径中的实验次数(做几次实验就设到几,比如设置十次实验就1-10)
// 存储路径定义
char a[]="E:\\\\GA\\\\NSGA2\\\\C++\\\\result\\\\";//末尾的\\请勿忘记
char b[]={0};
char c[]="exp";
char d[]="\\\\output.txt";
char e[]="\\\\fun.txt";
char ff[]="\\\\time.txt";
char loc[100]={0};
char loc1[100]={0};
char loc2[100]={0};
char loc3[100]={0};
int main()
{
////计时间-------------------------------------------------------------------------------------------------
start = clock();
////局部变量(计数器和指针)和文件读写-----------------------------------------------------------------------
int i,j,l,f;
float *ptr,tot;
FILE
*rep_ptr,
*lastit,
*time_time;
////文件指针-------------------------------------------------------------------------------------------------
strcat(loc,a);
if(fun_input == 1)
{
strcat(b,"ZDT1\\\\");
}
if(fun_input == 2)
{
strcat(b,"ZDT2\\\\");
}
if(fun_input == 3)
{
strcat(b,"ZDT3\\\\");
}
if(fun_input == 4)
{
strcat(b,"ZDT4\\\\");
}
if(fun_input == 5)
{
strcat(b,"ZDT6\\\\");
}
if(fun_input == 6)
{
strcat(b,"DTLZ1\\\\");
}
if(fun_input == 7)
{
strcat(b,"DTLZ2\\\\");
}
strcat(loc,b);
strcat(loc,c);
strcat(loc,ex_number);
strcat(loc1,loc);
strcat(loc2,loc);
strcat(loc3,loc);
strcat(loc1,d);
strcat(loc2,e);
strcat(loc3,ff);
rep_ptr = fopen(loc1,"w");
lastit = fopen(loc2,"w");
time_time = fopen(loc3,"w");
////---------------------------------初始化--------------------------------------------------------------
///随机种子赋初始值(0~1)
if(strcmp(ex_number,"1") == 0)
seed = 0.1;
if(strcmp(ex_number,"2") == 0)
seed = 0.2;
if(strcmp(ex_number,"3") == 0)
seed = 0.3;
if(strcmp(ex_number,"4") == 0)
seed = 0.4;
if(strcmp(ex_number,"5") == 0)
seed = 0.5;
if(strcmp(ex_number,"6") == 0)
seed = 0.6;
if(strcmp(ex_number,"7") == 0)
seed = 0.7;
if(strcmp(ex_number,"8") == 0)
seed = 0.8;
if(strcmp(ex_number,"9") == 0)
seed = 0.9;
if(strcmp(ex_number,"10") == 0)
seed = 1;
old_pop_ptr=&(old_pop);
nmut = 0;///变异次数初始化为0
ncross = 0;///交叉次数初始化为0
///从input.h得到输入
input(rep_ptr,fun_input);
///随机初始化迭代器的数目
warmup_random(seed);
///实数初始化
realinit(old_pop_ptr);
///二进制初始化
init(old_pop_ptr);
old_pop_ptr=&(old_pop);
decode(old_pop_ptr);
old_pop_ptr = &(old_pop);
new_pop_ptr = &(new_pop);
///等级初始化
for(j=0;j<popsize;j++)
{
old_pop_ptr->r