不多说直接上代码:
//------------------------------------------------------------------------------
#pragma hdrstop
#include “ZzfGaBpNetUnit1.h”
#include “DLtShoWmhUnit1.h”
#include “ShoWmhUnit3.h”
//------------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------
ZzfGaBpNet::~ZzfGaBpNet()
{
}
void ZzfGaBpNet::free()
{
}
//产生[low, high)之间的随机数
double randval(double low, double high)
{
double val;
// dvect[i] += (5e-3*rand() / RAND_MAX - 2.5e-3);
val = ((double)(rand() % RAND_MAX)/(double)RAND_MAX) * (high - low) + low;
return(val);
}
//------------------------------------------------------------------------------
void winit(double w[], int n) //权值初始化
{
for(int i=0; i<n; i++)w[i] = randval(-0.001, 0.001);
}
// 神经网络初始化
//
void ZzfGaBpNet::BpInit()
{
error=1.0;
e=0.0;
rate_w = 0.01; //权值学习率(输入层–隐含层)
rate_w1 = 0.01; //权值学习率 (隐含层–输出层)
rate_b1 = 0.01; //隐含层阀值学习率
rate_b2 = 0.01; //输出层阀值学习率
winit((double*)w, nInputm * nHidem);
winit((double*)w1, nHidem * nOutputm);
winit(b1, nHidem);
winit(b2, nOutputm);
}
//------------------------------------------------------------------------------
//训练
void ZzfGaBpNet::train()//Bp训练
{
double pp[nHidem]; //隐含结点的校正误差
double qq[nOutputm]; //希望输出值与实际输出值的偏差
double yd[nOutputm]; //希望输出值
double x[nInputm]; //输入向量
double x1[nHidem]; //隐含结点状态值
double x2[nOutputm]; //输出结点状态值
double o1[nHidem]; //隐含层激活值
double o2[nHidem]; //输出层激活值
for(int isamp=0; isamp<SampleSizem; isamp++) //循环训练一次样品
{
int i, j, k;
for(i=0; i<nInputm; i++)x[i] = inputn[isamp][i]; //输入的样本
for(i=0; i<nOutputm; i++)yd[i] = outputn[isamp][i]; //希望输出的样本
//正向传播
//构造每个样品的输入和输出标准
for(j=0; j<nHidem; j++)
{
o1[j] = 0.0;
for(i=0; i< nInputm; i++)o1[j] += w[i][j] * x[i]; //隐含层各单元输入激活值
x1[j] = 1.0 / (1.0 + exp(-o1[j] - b1[j])); //隐含层各单元的输出
}
for(k=0; k<nOutputm; k++)
{
o2[k] = 0.0;
for(int j=0; j<nHidem; j++)o2[k] += w1[j][k] * x1[j]; //输出层各单元输入激活值
x2[k] = 1.0 / (1.0 + exp(-o2[k] - b2[k])); //输出层各单元输出
}
//误差反向传播
for(k=0; k<nOutputm; k++) //对于网络中每个输出单元,计算误差项,并更新权值
{
qq[k] = (yd[k] - x2[k]) * x2[k] * (1-x2[k]); //希望输出与实际输出的偏差
for(j=0; j<nHidem; j++)w1[j][k] += rate_w1 * qq[k] * x1[j]; //更新隐含层和输出层之间的连接权
}
for(j=0; j<nHidem; j++) //对于网络中每个隐藏单元,计算误差项,并更新权值
{
pp[j] = 0.0;
for(k=0; k<nOutputm; k++)pp[j] += qq[k] * w1[j][k];
pp[j] = pp[j] * x1[j] * (1 - x1[j]); //隐含层的校正误差
for(i=0; i<nInputm; i++)w[i][j] += rate_w * pp[j] * x[i]; //更新输入层和隐含层之间的连接权}for(k=0; k<nOutputm; k++){e += pow(yd[k] - x2[k], 2); //计算均方差}error = e/2.0;for(k=0; k<nOutputm; k++)b2[k] += rate_b2 * qq[k]; //更新隐含层和输出层之间的阈值for(j=0; j<nHidem; j++)b1[j] += rate_b1 * pp[j]; //更新输入层和隐含层之间的阈值
}
}
//------------------------------------------------------------------------------
//识别
double *ZzfGaBpNet::recognize(double *p)
{
double x[nInputm]; //输入向量
double x1[nHidem]; //隐含结点状态值
double x2[nOutputm]; //输出结点状态值
double o1[nHidem]; //隐含层激活值
double o2[nHidem]; //输出层激活值
int i, j, k;
for(i=0; i<nInputm; i++)x[i] = p[i];
for(j=0; j<nHidem; j++)
{
o1[j] = 0.0;
for(i=0; i<nInputm; i++)o1[j] = o1[j] + w[i][j] * x[i]; //隐含层各单元激活值
x1[j] = 1.0 / (1.0 + exp(-o1[j] - b1[j])); //隐含层各单元输出
}
for(k=0; k<nOutputm; k++)
{
o2[k] = 0.0;
for(j=0; j<nHidem; j++)o2[k] = o2[k] + w1[j][k] * x1[j]; //输出层各单元激活值
x2[k] = 1.0 / (1.0 + exp(-o2[k] - b2[k])); //输出层各单元输出
}
for(k=0; k<nOutputm; k++)
{
result[k] = x2[k];
}
return result;
}
//-------------------------------
/*
//转入BP学习算法
void BP()
{
int i,j,l,k,s;
double EITA=0.6;
double APHA=0.4;
double u_h_i[HN][IN+1],v_h_i[HN][IN+1];
double u_o_h[HN+1][OUT],v_o_h[HN+1][OUT];
double net,o_h[SIZE][HN];
double delta_o,delta_h[HN];
double MaxError,sumdelta;
int MiddleNum,Step,ReCount; //为了随机排列样本的顺序
int NotEnd,t;
double avdelta[SIZE];
for(s=0;s<JD;s++)
DecodeNum[s]=decodechromosome(currentbest.chrom,length*s,length);
GetW();
for(i=0;i<=IN;i++)
for(j=0;j<HN;j++)
{
v_h_i[j][i]=w_h_i[j][i];
}
for(j=0;j<=HN;j++)
for(i=0;i<OUT;i++)
{
v_o_h[j][i]=w_o_h[j][i];
}
for(t=0;t<3000;t++)
{
randomize();
MiddleNum=random(SIZE);
k=MiddleNum;
Step=1;
NotEnd=1;
ReCount=0;
while (NotEnd==1)
{
i=k;
for(l=0;l<=IN;l++)
for(j=0;j<HN;j++)
{
u_h_i[j][l]=v_h_i[j][l];
v_h_i[j][l]=w_h_i[j][l];
}
for(j=0;j<=HN;j++)
for(l=0;l<OUT;l++)
{
u_o_h[j][l]=v_o_h[j][l];
v_o_h[j][l]=w_o_h[j][l];
}
//compute the mid_layer output
for(j=0;j<HN;j++)
{ net=0.0;
net += samp[i].in_sign[0]*v_h_i[j][0];
net += samp[i].in_sign[1]*v_h_i[j][1];
net=net+v_h_i[j][IN];
o_h[i][j]=1.0/(1.0+exp(-net));
}
//compute the output_layer output
net=0;
for(l=0;l<OUT;l++)
{ for(j=0;j<HN;j++)
net=net+o_h[i][j]*v_o_h[j][l];
net=net+v_o_h[HN][l];
o_o[i][l]=1.0/(1.0+exp(-net));
}
//compute the outlayer erroravdelta[i]=samp[i].tch_sign-o_o[i][0];delta_o=o_o[i][0]*(1-o_o[i][0])*avdelta[i];//compute the midlayer errorfor(j=0;j<HN;j++)delta_h[j]=delta_o*v_o_h[j][0]*o_h[i][j]*(1-o_h[i][j]);//modify the mid_out powerfor(l=0;l<OUT;l++){ for(j=0;j<HN;j++)w_o_h[j][l]=v_o_h[j][l]+EITA*delta_o*o_h[i][j]+APHA*(v_o_h[j][l]-u_o_h[j][l]);w_o_h[HN][l]=v_o_h[HN][l]+EITA*delta_o+APHA*(v_o_h[HN][l]-u_o_h[HN][l]);}//modify the input_midlayer powerfor(j=0;j<HN;j++){ for(l=0;l<IN;l++)w_h_i[j][l]=v_h_i[j][l]+EITA*delta_h[j]*samp[i].in_sign[l]+APHA*(v_h_i[j][l]-u_h_i[j][l]);w_h_i[j][2]=v_h_i[j][2]+EITA*delta_h[j]+APHA*(v_h_i[j][2]-u_h_i[j][2]);}//修改iif(MiddleNum ==0){ k=k+1;if(k==SIZE) NotEnd=0;}elseif(MiddleNum ==(SIZE-1)){ k=k-1;if(k == -1) NotEnd=0;}elseif(MiddleNum>0&&MiddleNum<(SIZE-1)){if (k == 0)ReCount=1;elsek=k-1;if (ReCount==1){k=MiddleNum+Step;Step=Step+1;if(k==SIZE) NotEnd=0;}}}printf("t = %d\t",t);MaxError=0.0;sumdelta=MaxError;for(i=0;i<SIZE;i++){//MaxError=fabs(avdelta[i]);if(MaxError>sumdelta) sumdelta=MaxError;sumdelta += fabs(avdelta[i]);}sumdelta /= SIZE;if(sumdelta<0.00193) break;printf("sumdelta=%4.6f\t",sumdelta);time2=time(NULL);passtime=difftime(time2,time1);printf("passtime: %3.2f minutes\n",passtime/60);}
}
*/
//------------------------------------------------------------------------------
//函数:种群初始化
//输入是数组的引用
//调用时,只需输入数组名
void ZzfGaBpNet::population_initialize(chromosome (&population_current)[Population_size])
{
int i = 0, j = 0;
//产生随机数种子
srand((unsigned)time(NULL));
//遍历种群中的每个染色体
for (j = 0; j<Population_size; j++)
{
//随机初始化染色体的每一位
for (i = 0; i<Chromosome_length; i++)
{
// 随机产生染色体上每一个基因位的值,0或1
population_current[j].bit[i] = rand()% 2;
}
}
}
// 函数:将二进制换算为十进制
void ZzfGaBpNet::decode(chromosome &population_current)
{//此处的染色体长度为,其中个表示符号位
int i = 0;
population_current.value = 0;
//地位在前,高位再后
for( i = 0 ; i < Chromosome_length -1; i++ )
population_current.value += (double)pow(2.0, i) * (double)population_current.bit[i]; //遍历染色体二进制编码,
//最高位为符号位,如果是1代表负数
if (population_current.bit[Chromosome_length - 1] == 1)
population_current.value = 0 - population_current.value;
}
//获取适度函数
double ZzfGaBpNet::GetFun()
{
double refun=0,k=0,m=0.1;
for(int i=0;i<SampleSizem;i++)
{
//m+=i1/SampleSizem;
recognize(inputn[i]);
for(int j=0;j<nOutputm;j++)net_output[i][j]=result[j];
for(int j=0;j<nOutputm;j++)k+=(outputn[i][j]-net_output[i][j])(outputn[i][j]-net_output[i][j])/2;
}
refun=1/(1+m*k);
return(refun);
}
//函数:计算适应度
double ZzfGaBpNet::objective_function(double x)
{
double y;
// 目标函数:y= - ( (x-1)^ 2 ) +5
//y = -((x - 1) *(x - 1)) + 5;
y=GetFun();
return(y);
}
//函数:更新种群内个体的属性值
//说明:当种群中个体的二进制串确定后,就可以计算每个个体fitness、value、rate_fit 、cumu_fit
//输入:
//chromosome (&population_current)[Population_size] 当前代种群的引用
void ZzfGaBpNet::fresh_property(chromosome (&population_current)[Population_size])
{
int j = 0;
double sum = 0;
for (j = 0; j < Population_size; j++)
{
//染色体解码,将二进制换算为十进制,得到一个整数值
//计算二进制串对应的10进制数值
decode(population_current[j]);
//计算染色体的适应度
population_current[j].fitness = objective_function(population_current[j].value);
sum = sum + population_current[j].fitness;
}
//计算每条染色体的适应值百分比及累计适应度值的百分比,在轮盘赌选择法时用它选择染色体
population_current[0].rate_fit = population_current[0].fitness / sum;
population_current[0].cumu_fit = population_current[0].rate_fit;
for (j = 1; j < Population_size; j++)
{
population_current[j].rate_fit = population_current[j].fitness / sum;
population_current[j].cumu_fit = population_current[j].rate_fit + population_current[j-1].cumu_fit;
}
}
//函数:基于轮盘赌选择方法,对种群中的染色体进行选择
//输入:
//chromosome (&population_current)[Population_size] 当前代种群的引用
//chromosome (&population_next_generation)[Population_size] 选择出的下一代种群的引用
//chromosome &best_individual 当前代种群中的最优个体
void ZzfGaBpNet::seletc_prw(chromosome (&population_current)[Population_size],chromosome (&population_next_generation)[Population_size],chromosome &best_individual)
{
int i = 0, j = 0;
double rate_rand = 0.0;
best_individual = population_current[0];
//产生随机数种子
srand((unsigned)time(NULL));
for (i = 0; i < Population_size; i++)
{
rate_rand = (float)rand() / (RAND_MAX);
if (rate_rand < population_current[0].cumu_fit)
population_next_generation[i] = population_current[0];
else
{
for (j = 0; j < Population_size; j++)
{
if (population_current[j].cumu_fit <= rate_rand && rate_rand < population_current[j + 1].cumu_fit)
{
population_next_generation[i] = population_current[j + 1];
break;
}
}
}
//如果当前个体比目前的最有个体还要优秀,则将当前个体设为最优个体
if(population_current[i].fitness > best_individual.fitness)
best_individual = population_current[i];
}
}
// 函数:交叉操作
void ZzfGaBpNet::crossover(chromosome (&population_next_generation)[Population_size])
{
int i = 0,j = 0;
double rate_rand = 0.0;
short int bit_temp = 0;
int num1_rand = 0, num2_rand = 0, position_rand = 0;
//产生随机数种子
srand((unsigned)time(NULL));
//应当交叉变异多少次呢?先设定为种群数量
for (j = 0; j<Population_size; j++)
{
rate_rand = (float)rand()/(RAND_MAX);
//如果大于交叉概率就进行交叉操作
if(rate_rand <= rate_crossover)
{
//随机产生两个染色体
num1_rand = (int)rand()%(Population_size);
num2_rand = (int)rand()%(Population_size);
//随机产生两个染色体的交叉位置
position_rand = (int)rand()%(Chromosome_length - 1);
//采用单点交叉,交叉点之后的位数交换
for (i = position_rand; i<Chromosome_length; i++)
{
bit_temp = population_next_generation[num1_rand].bit[i];
population_next_generation[num1_rand].bit[i] = population_next_generation[num2_rand].bit[i];
population_next_generation[num2_rand].bit[i] = bit_temp;
}
}
}
}
// 函数:变异操作
void ZzfGaBpNet::mutation(chromosome (&population_next_generation)[Population_size])
{
int position_rand = 0;
int i = 0;
double rate_rand = 0.0;
//产生随机数种子
srand((unsigned)time(NULL));
//变异次数设定为种群数量
for (i = 0; i<Population_size; i++)
{
rate_rand = (float)rand()/(RAND_MAX);
//如果大于交叉概率就进行变异操作
if(rate_rand <= rate_mutation)
{
//随机产生突变位置
position_rand = (int)rand()%(Chromosome_length);
//突变
if (population_next_generation[i].bit[position_rand] == 0)
population_next_generation[i].bit[position_rand] = 1;
else
population_next_generation[i].bit[position_rand] = 0;
}
}
}
bool ZzfGaBpNet::GaBp(int iteration_num) //遗传操作
{
int i = 0,j = 0;//循环变量
//初始化定义的种群和个体
//首先初始化zeros_chromosome,后使用之初始化其他个体
for (i = 0; i < Chromosome_length; i++)zeros_chromosome.bit[i] = 0;
zeros_chromosome.fitness = 0.0;
zeros_chromosome.value = 0.0;
zeros_chromosome.rate_fit = 0.0;
zeros_chromosome.cumu_fit = 0.0;
best_individual = zeros_chromosome;
for (i = 0; i < Population_size; i++)
{
population_current[i] = zeros_chromosome;
population_next_generation[i] = zeros_chromosome;
}
// printf("\nWelcome to the Genetic Algorithm!\n"); //
// printf(“The Algorithm is based on the function y = -x^2 + 5 to find the maximum value of the function.\n”);
//enter:printf("\nPlease enter the no. of iterations\n请输入您要设定的迭代数 : “);
// 输入迭代次数,传送给参数 iteration_num
//scanf_s(”%d", &iteration_num);
// 判断输入的迭代次数是否为负或零,是的话重新输入
// if (iteration_num <1)
// goto enter;
//种群初始化,得到个体的二进制字符串
population_initialize(population_current);
//更新种群内个体的属性值
fresh_property(population_current);
// 开始迭代
for (i = 0; i< iteration_num; i++)
{
// 输出当前迭代次数
//printf("\ni = %d\n", i);
//挑选优秀个体组成新的种群
seletc_prw(population_current,population_next_generation,best_individual);
//对选择后的种群进行交叉操作
crossover(population_next_generation);
//对交叉后的种群进行变异操作
mutation(population_next_generation);
//更新种群内个体的属性值
fresh_property(population_next_generation);
//将population_next_generation的值赋给population_current,并清除population_next_generation的值
for (i = 0; i < Population_size; i++)
{
population_current[i] = population_next_generation[i];
population_next_generation[i] = zeros_chromosome;
}
}
}
/*
// 主函数
void main()
{
//初始化定义的种群和个体
clock_t start, end;//开始计时,精确到秒
start = clock();
//初始化定义的种群和个体
chromosome population_current[Population_size]; //当前种群
chromosome population_next_generation[Population_size]; //产生的下一代的种群
chromosome best_individual; //记录适应度的最大值
chromosome zeros_chromosome; //定义一个全为0的个体,用于群体中某个个体的重置int i = 0,j = 0;//循环变量//*****初始化定义的种群和个体*****
//首先初始化zeros_chromosome,后使用之初始化其他个体
for (i = 0; i < Chromosome_length; i++)zeros_chromosome.bit[i] = 0;
zeros_chromosome.fitness = 0.0;
zeros_chromosome.value = 0.0;
zeros_chromosome.rate_fit = 0.0;
zeros_chromosome.cumu_fit = 0.0;best_individual = zeros_chromosome;
for (i = 0; i < Population_size; i++)
{population_current[i] = zeros_chromosome;population_next_generation[i] = zeros_chromosome;
}printf("\nWelcome to the Genetic Algorithm!\n"); //
printf("The Algorithm is based on the function y = -x^2 + 5 to find the maximum value of the function.\n");
enter:printf("\nPlease enter the no. of iterations\n请输入您要设定的迭代数 : “);
// 输入迭代次数,传送给参数 iteration_num
scanf_s(”%d", &iteration_num);
// 判断输入的迭代次数是否为负或零,是的话重新输入
if (iteration_num <1)goto enter;//种群初始化,得到个体的二进制字符串
population_initialize(population_current);
//更新种群内个体的属性值
fresh_property(population_current);
// 开始迭代
for (i = 0; i< iteration_num; i++)
{// 输出当前迭代次数//printf("\ni = %d\n", i); //挑选优秀个体组成新的种群seletc_prw(population_current,population_next_generation,best_individual); //对选择后的种群进行交叉操作crossover(population_next_generation); //对交叉后的种群进行变异操作mutation(population_next_generation); //更新种群内个体的属性值fresh_property(population_next_generation);//将population_next_generation的值赋给population_current,并清除population_next_generation的值for (i = 0; i < Population_size; i++){population_current[i] = population_next_generation[i];population_next_generation[i] = zeros_chromosome;}//检验时间是否到90send = clock();if (double(end - start) / CLK_TCK> 89)break;
}
//输出所用时间
printf("\n 迭代%d次所用时间为: %f\n", iteration_num, double(end - start) / CLK_TCK);//输出结果
printf("\n 函数得到最大值为: %f ,适应度为:%f \n", best_individual.value, best_individual.fitness);for (i = 0; i<Population_size; i++)
{printf(" population_current[%d]=", i);for (j = 0; j < Chromosome_length; j++)printf(" %d", population_current[i].bit[j]);printf(" value=%f fitness = %f\n", population_current[i].value, population_current[i].fitness);
}
printf("\nPress any key to end ! ");// 清除所有缓冲区
// flushall();
system(“pause”);
}
*/
预测效果