rnm算法
A. 模糊数学在塔里木盆地圈闭评价中的应用
袁丽珍王英吕媛娥虎北辰
(西北石油局规划设计研究院,乌鲁木齐830011)
摘要圈闭评价的目的是为了降低油气勘探风险,提高钻探成功率。圈闭评价的方法很多,归纳起来有如下几种:综合定性排队法、评分法、概率统计法、多信息叠合评价法、灰色系统理论和模糊数学评价法等。应用“模糊数学评价法”对塔里木盆地圈闭进行的综合评价,收到了较好的效果。
关键词塔里木盆地模糊数学权重模糊评判值圈闭圈闭评价
1方法原理
1.1模糊数学的概念
美国控制专家乍得(L.A.Zaden)于1965年首先提出“模糊数学”的概念,它是研究和处理模糊体系规律性的理论和方法,也就是把普遍集合论只取0或1两个值的特征函数推广到[0,1]区间上取值的隶属函数。圈闭评价中常用“好”、“较好”、“中等”、“较差”、“差”这一评价方法,更适合用模糊数学的方法对圈闭含油气性进行综合评价。
1.2模糊综合评判的基本概念及方法原理
所谓模糊综合评判,是指用多个因素的评价结果,综合处理最终得出一个属于哪一类的隶属度,以供决策使用。
决定圈闭(局部构造)是否成藏的地质因素很多,如储层、盖层、油源等等。考虑μ1,μ2,…,μ。这n个评价圈闭因素,由此就构成了因素集合 U:
U={μ1,μ2…μm}
在评价中我们可把参评的因素分为 V1,V2,…,Vm这m个级别(如评价中常用的级别Ⅰ、Ⅱ、Ⅲ或好、中、差等),由此构成评语集合 V:
V={V1,V2…Vm}
因素集中 U中各个因素对圈闭(局部构造)成藏所起的作用是不同的,因此在圈闭(局部构造)评价中应根据我们对圈闭(局部构造)成藏规律的认识对各评价因素赋予不同权系数,由此构成权重分配集合 A:
A={A1,A2…An}
在这里
塔里木盆地北部油气田勘探与开发论文集
应用各因素综合判定圈闭(局部构造)的含油气性,也就是属于评语集合 V中的哪一个级别,这就要求建立因素集中 U与评语集合V的一个模糊变换关系R:
塔里木盆地北部油气田勘探与开发论文集
其中R就是某个对象(这里指圈闭或局部构造)的某个因素关于各类的得分,即隶属度。因此,R又称单因素评价矩阵。
权重A与模糊变换矩阵R的合成,构成了圈闭的综合评判矩阵 B:
B=AR
最后用下面公式求得每个圈闭(局部构造)的综合评价值D:
D=BC
式中C为等级矩阵的转置矩阵,评价级别分为好、较好等级别。C取值为(-2,-1,0,1,2),Rnm可按表1来确定。当评价级别分为好、中、差三个级别时,C取值为(-1,0,1),R。可按表2来确定。
表1五个级别的评语Table1The comments of five ranks in the table
表2三个级别的评语Table2The comments of three ranks in the table
求出每个圈闭的综合评价值D之后,再按D值的大小对所评圈闭(局部构造)进行排队,得到优选圈闭(局部构造),以供勘探部署。1.3关于模糊运算
模糊数学中定义的算法有很多种,其反映的意义是不同的。根据圈闭(局部构造)评价特点,本次采用如下4种:
①取小取大法:
取小取大法分别简记为(∨,∧),合成矩阵B中的元素bj的算法如下:
塔里木盆地北部油气田勘探与开发论文集
②取小求和法
取小求和法分别简记为(∧,⊕),合成矩阵B中的元素bj的算法如下:
塔里木盆地北部油气田勘探与开发论文集
③乘积取大法
乘积取大法分别简记为(·,v),合成矩阵B中的元素bj的算法如下:
塔里木盆地北部油气田勘探与开发论文集
④乘积求和法
乘积求和法为评价重点考虑的算法,分别简记为(·,⊕),合成矩阵B中的元素bj的算法如下:
塔里木盆地北部油气田勘探与开发论文集
2圈闭评价参数及评分标准
影响圈闭的含油气性的地质因素很多,结合塔里木盆地实际勘探情况,主要考虑圈闭的落实程度、储集条件、盖条件、油源条件、油气大量生成期与构造形成期的配制关系(圈排关系)等五个地质因素,根据区内油气成藏规律,确定各地质因素的权重系数见表3。
表3圈闭评价地质因素及权重系数Table3Geological factor and tentative crucial coefficient of trap evaluation
在评价圈闭含油气级别时,分为好、较好、中等、较差、差五个级别,根据各项目组提供的数据确定各地质因素评估赋值标准。
2.1圈闭落实程度
主要用地震资料进行落实,如是否有三维控制、圈闭的二维地震测线数以及对圈闭的闭合幅度等进行评价(见表4)。
2.2储集条件
表4圈闭落实程度评语Table4The comments of practicable level for trap
碳酸盐岩储层非均质性极为明显,雅克拉—轮台地区主要为寒武系、奥陶系白云岩,且经历了长期古岩溶作用,储集性一般为中等—较好。在塔河油区主要为奥陶系灰岩,储层的岩块物性较差。由于孔、缝、洞的发育,储层的总体物性特征明显改善,其划分表见表5。
碎屑岩主要用孔隙度、渗透率指标对储层进行评价,不同区带其划分标准略有差异,结果见表6。
2.3盖层条件
表5碳酸盐岩储层评语Table5The comments for carbonate reservoir
表6碎屑岩储层划分评语Table6The partition comments of clastic reservior
雅轮与巴麦工业区带区内盖层分析参数不全,本次主要以区带内综合研究成果为依据对圈闭盖层进行评价,对于仅靠断裂作为侧向封堵的圈闭(断鼻、断块等),要考虑断裂两盘的对接岩性,若断裂两侧储层与盖层对接,评价为好,与砂泥岩互层对接为较好—中等,与储层对接为较差—差。艾桑工区带盖层划分标准见表7。
2.4油源条件
表7艾-桑工业区带盖层条件评语Table7The comments of cap condition in Aixieke-Sangtamu instrial estate
主要考虑圈闭距生油坳陷的距离和油气的运移通道两个因素。
对于陆相油气主要考虑圈闭距生油坳陷区的距离和断裂发育与储层的关系,若断裂下断至不整合面,上断至储层,则以断裂的断距为评价标准(表8)。
表8陆相油气油源条件评语表Table8The comment table of land oil-gas origin
对于海相油气,除考虑断裂是否将源岩与储集岩沟通外,主要还要考虑油气资源丰度以及构造带是否处于油气运移指向区,其评价标准见表9。
表9海相油气油源条件评语Table9The comment table of marine oil-gas origin
2.5圈排关系
圈排关系是指圈闭形成期与生油高峰期的配置关系,构造形成期早于生油高峰期评价为好,两者相同评为较好—中等,构造形成期晚于生油高峰期则评为较差—差。
3圈闭评价结果与排队
我们对未上钻的184个圈闭按上面的评语标准对某个地质评价因素进行赋值评价,然后对赋值圈闭利用模糊数学方法对其含油气性进行综合评判,根据模糊评判值D将圈闭的含油气性分为Ⅰ(D≥1)、Ⅱ(0.5<D<1)、Ⅲ(D≤0.5)类。对筛选出的Ⅰ类圈闭,适当考虑一些能反映经济效益的有关因素,如勘探中的探井成本和影响收益的重要参数资源量等,具体参数见表10。
表10局部构造综合评判参数与标准Table10The synthetical judge parameters and standards of local structure
对各圈闭层及各评价因素结合区内目前勘探实际情况赋予不同的权重系数(表11、12)。
表11圈闭层系权重系数Table11Tentatively crucial coefficient of trap layer
表12局部构造评价因素权重系数分配表Table12Distribution table of tentative crucial coefficients for the judge of local structure
构造评价值由下式确定
塔里木盆地北部油气田勘探与开发论文集
其中D构造为构造评价模糊值,E为圈闭层权重系数,
利用模糊数学的方法对赋值后的局部构造含油气性进行综合评判,得出局部构造综合评判值D综合,由 D综合值将局部构造的含油气性划分为Ⅰ(D综合≥0.28)、Ⅱ(0.17<D综合<0.28)、Ⅲ(D综合<0.17)类。将评定出的工类局部构造25个,选定为近期勘探目标,主要分布在艾协克-桑塔木工业区带,近期已在艾协克北(沙73井三叠系)、桑塔木2号构造高点(沙60井)、艾协克2号构造西翼(沙65井)、牧场北3号构造(沙66井)、牧场北7号构造(沙67井)、桑塔木2号构造西高点(沙69井)、艾协克南构造(TK203井) 7口钻井在下奥陶系碳酸盐岩获油气突破,钻探成功率为75%以上。实践证明该圈闭评价方法是有一定的参考和使用价值。
参考文献
[1]张跃等.模糊数学方法及其应用.北京:煤炭工业出版社,1992
[2]赵旭车.石油数学地质概论.北京:石油工业出版社,1992
Application of Fuzzy Mathematics to Evaluate the Traps in Tarim Basin
Yuan LizhenWang YingLu Yua n'eHu Beichen
(Academy of planning and designing,Northwest Bureau of Petroleum Geology,Ürümqi83001 1)
Abstract:The goal of evaluating trap isfor rection the risk of the oil and gas prospecting and increases the successful ratio of the drilling.There are six kinds of methods for evaluating trap:multiple determination queuing method,comparing and assessing method,probability statistical method,multiple information evaluation method,grap system theory,fuzzy mathematic evaluation method, etc.We have got satisfactory results in the course of the evaluation of the traps in Tarim basin using the fuzzy mathematic evaluation method.
Key words:Tarim Basinfuzzy Mathematics methodEvaluation the Traps
B. 求助:人工智能“遗传算法求解f(x)=xcosx+2的最大值”
为了方便我只求了-3.14到3.14之间的最大值,你可以自己改一下,不过范围大了之后,种群也因该扩大,我的种群只有66个
结果:极值点(-3.141593,5.141593)
我又算了一下-100到100之间的极大值
结果:极值点(-97.399473,99.394504)
-1000到1000之间的极大值
结果:(999,1001)
-2000到2000之间的极大值
结果:(1998.053550,2000.053163)
以上结果我用matlab画图验证了,没问题。
希望再给加点分,呵呵
//中国电子科技集团公司
//第一研究室
//呼文韬
//[email protected]
//随机初始种群
//编码方式为格雷码
//选择方法为随机遍历
//采用了精英保存策略
//采用了自适应的交叉率和变异率
//采用了与模拟退火算法相结合的尺度变换
//采用了均匀交叉法
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <iostream.h>
#include <iomanip.h>
#include <time.h>
#include <windows.h>
#define IM1 2147483563
#define IM2 2147483399
#define AM (1.0/IM1)
#define IMM1 (IM1-1)
#define IA1 40014
#define IA2 40692
#define IQ1 53668
#define IQ2 52774
#define IR1 12211
#define IR2 3791
#define NTAB 32
#define NDIV (1+IMM1/NTAB)
#define EPS 1.2e-7
#define RNMX (1.0-EPS)
#define zhenjuli 0.005
#define PI 3.14159265358
#define T0 100000//温度要取得很高才行。
#define zhongqunshu1 200
#define zuobianjie -2000
#define youbianjie 2000
unsigned int seed=0; //seed 为种子,要设为全局变量
void mysrand(long int i) //初始化种子
{
seed = -i;
}
long a[1];
//double hunn;
//double c=4;
//设置全局变量
struct indivial
{
unsigned *chrom; //染色体;
double geti;//变量值
double shiying; //目标函数的值;
double fitness; //变换后的适应度值;
};
indivial *zuiyougeti;//精英保存策略
int zhongqunshu; //种群大小
indivial *nowpop;//当前代
indivial *newpop;//新一代
double sumfitness;//当代的总适应度fitness
double sumshiying;//当代的总适应度shiying
double maxfitness;//最大适应度
double avefitness;//平均适应度
double maxshiying;//最大适应度
double avgshiying;//平均适应度
float pc;//交叉概率
float pm;//变异概率
int lchrom;//染色体长度
int maxgen;//最大遗传代数
int gen;//遗传代数
//函数
int flipc(double ,double );//判断是否交叉
int flipm(double );//判断是否变异
int rnd(int low,int high);//产生low与high之间的任意数
void initialize();//遗传算法初始化
void preselectfitness(); //计算sumfiness,avefitness,maxfitness
void generation();
double suijibianli();//产生随机遍历指针
int fu(float );//选择要复制的个体
void crossover(indivial ,indivial ,indivial &,indivial &);//交叉
void bianyi(indivial &);//变异
void mubiaohanshu(indivial &);//计算适应度
void chibianhuan(indivial &);//对shiying进行尺度变换赋给fitness
double ran1(long *);//随机数初始
void bianma(double bianliang,unsigned *p);//编码
double yima(unsigned *p);
void guanjiancanshujisuan();//计算shiying,根据shiying计算sumshiying,对shiying进行尺度变换变成fitness,根据fitness计算sumfitness,avefitness,maxfitness
void jingyingbaoliu();
void glp(int n,int s,int *,int (*)[1],float (*)[1]);//glp生成函数
BOOL Exist(int Val, int Num, int *Array);//判断一个数在前面是否出现过
int cmpfitness(const void *p1,const void *p2)
{
float i=((indivial *)p1)->shiying;//现在是按照"适应度"排序,改成"个体"的话就是按照"个体"排序
float j=((indivial *)p2)->shiying;
return i<j ? -1:(i==j ? 0:1);//现在是按升序牌排列,将1和-1互换后就是按降序排列
}
void main()
{
initialize();
cout<<zuiyougeti->geti<<" "<<zuiyougeti->shiying<<endl;/////////////
for(gen=1;gen<maxgen;gen++)
{ generation();
}
jingyingbaoliu();
cout<<setiosflags(ios::fixed)<<setprecision(6)<<zuiyougeti->geti<<" "<<setiosflags(ios::fixed)<<setprecision(6)<<(zuiyougeti->shiying)<<endl;////////////////
delete [] newpop;
delete [] nowpop;
delete [] zuiyougeti;
system("pause");
}
void initialize()
{
int q[zhongqunshu1][1],s=1;
float xx[zhongqunshu1][1];//生成的glp用x储存
int h[1]={1};//生成向量
zuiyougeti=new indivial;//最优个体的生成
zhongqunshu=200;//种群数量
nowpop=new indivial[zhongqunshu1];//当代
newpop=new indivial[zhongqunshu1];//新一代
maxgen=150;//最大代数
gen=0;//起始代
lchrom=22;//基因数量的初始化
mysrand(time(0));//随机数种子
a[0]=seed;//随机数种子
//对最优个体的初始化
zuiyougeti->geti=0;
zuiyougeti->fitness=0;
zuiyougeti->shiying=0;
//
glp(zhongqunshu,s,h,q,xx);
//for(int i=0;i<zhongqunshu1;i++)//产生初始种群
//{
// for(int j=0;j<s;j++)
// {
// nowpop[i].geti=zuobianjie+(youbianjie-zuobianjie)*xx[i][j];
// }
//}
for(int i=0;i<zhongqunshu1;i++)//产生初始种群
{
nowpop[i].geti=zuobianjie+(youbianjie-(zuobianjie))*ran1(a);
}
//nowpop[0].geti=999;//////////////////////////
guanjiancanshujisuan();
jingyingbaoliu(); //精英保留的实现
guanjiancanshujisuan();//计算shiying,根据shiying计算sumshiying,对shiying进行尺度变换变成fitness,根据fitness计算sumfitness,avefitness,maxfitness
}
void jingyingbaoliu() //精英保留的实现
{
indivial *zuiyougetiguo;
zuiyougetiguo=new indivial[zhongqunshu1];//建立一个过渡数组
for(int i=0;i<zhongqunshu;i++)//将当代个体复制到过渡数组中
zuiyougetiguo[i]=nowpop[i];
qsort(zuiyougetiguo,zhongqunshu1,sizeof(indivial),&cmpfitness);//按fitness升序排序
// cout<<"zuiyougetiguo适应度:"<<zuiyougetiguo[zhongqunshu1-1].shiying<<endl;///////////
// cout<<"zuiyougeti适应度:"<<zuiyougeti->shiying<<endl;///////////////////
//system("pause");
if(zuiyougetiguo[zhongqunshu-1].shiying>zuiyougeti->shiying)
{
*zuiyougeti=zuiyougetiguo[zhongqunshu1-1];//如果最优个体的fitness比当代最大的fitness小则用当代的代替之
//cout<<"zuiyougetiguo个体:"<<zuiyougetiguo[zhongqunshu1-1].geti<<endl;/////////////
//cout<<"zuiyougeti个体:"<<zuiyougeti->geti<<endl;/////////////
}
else
nowpop[rnd(0,(zhongqunshu1-1))]=*zuiyougeti;//否则的话从当代中随机挑选一个用最优个体代替之
delete [] zuiyougetiguo;//释放过渡数组
}
void guanjiancanshujisuan()//计算shiying,根据shiying计算sumshiying,对shiying进行尺度变换变成fitness,根据fitness计算sumfitness,avefitness,maxfitness
{
for(int i=0;i<zhongqunshu;i++)//计算shiying
mubiaohanshu(nowpop[i]);
for(i=0;i<zhongqunshu;i++)//对shiying进行尺度变换变成fitness
chibianhuan(nowpop[i]);
preselectfitness();//根据fitness计算sumfitness,avefitness,maxfitness
}
void mubiaohanshu(indivial &bianliang)//计算shiying
{
bianliang.shiying=(bianliang.geti*cos(bianliang.geti)+2.0);//目标函数
}
void chibianhuan(indivial &bianliang)//对shiying进行尺度变换变成fitness
{
double T;//退火温度
T=T0*(pow(0.99,(gen+1-1)));
double sum=0;
for(int j=0;j<zhongqunshu;j++)
sum+=exp(nowpop[j].shiying/T);
bianliang.fitness=exp(bianliang.shiying/T)/sum;//算出fitness
}
void preselectfitness()//根据fitness计算sumfitness,avefitness,maxfitness
{
int j;
sumfitness=0;
for(j=0;j<zhongqunshu;j++)
sumfitness+=nowpop[j].fitness;
indivial *guo;
guo=new indivial[zhongqunshu1];
for(j=0;j<zhongqunshu;j++)
guo[j]=nowpop[j];
qsort(guo,zhongqunshu1,sizeof(indivial),&cmpfitness);
maxfitness=guo[zhongqunshu1-1].fitness;
avefitness=sumfitness/zhongqunshu1;
delete [] guo;
}
void generation()
{
indivial fuqin1,fuqin2,*pipeiguo,*pipeichi;
int *peiishuzu;//用来存放产生的随机配对
pipeiguo=new indivial[zhongqunshu1];
pipeichi=new indivial[zhongqunshu1];
peiishuzu=new int[zhongqunshu1];
int member1,member2,j=0,fujishu=0,i=0,temp=0,tt=0;
float zhen;
//随机遍历的实现
for(zhen=suijibianli();zhen<1;(zhen=zhen+zhenjuli))//设定指针1/66
{
pipeichi[fujishu]=nowpop[fu(zhen)];
fujishu++;
}
//交叉与变异的实现
//交叉
for(i=0;i<zhongqunshu1;i++)
{
peiishuzu[i]=-1;
}
for (i=0; i<zhongqunshu1; i++)
{
temp =rnd(0,zhongqunshu1-1); //产生值在0-zhongqunshu1-1的随机数
while(Exist(temp, i, peiishuzu))//判断产生的随机数是否已经产生过,如果是,则再产生一个随机数
{
temp =rnd(0,zhongqunshu1-1);
}
//如果没有的话,则把产生的随机数放在peiishuzu中
*(peiishuzu+i) = temp;
}
for(i=0;i<zhongqunshu1-1;i=i+2)
{
fuqin1=pipeichi[peiishuzu[i]];
fuqin2=pipeichi[peiishuzu[i+1]];
crossover(fuqin1,fuqin2,newpop[i],newpop[i+1]);
}
for(j=0;j<zhongqunshu1;j++)
{
//if(newpop[j].geti<-1000)
//cout<<"个体数值小于下界了";
nowpop[j].geti=newpop[j].geti;
}
//
guanjiancanshujisuan();
//变异的实现
for(j=0;j<zhongqunshu;j++)
{
bianyi(nowpop[j]);
}
//
guanjiancanshujisuan();
//精英保留的实现
jingyingbaoliu();
//
guanjiancanshujisuan();
delete [] peiishuzu;
delete [] pipeichi;
delete [] pipeiguo;
}
void crossover(indivial parent1,indivial parent2,indivial &child1,indivial &child2)//交叉
{
int j;
unsigned *panan;
panan=new unsigned[lchrom];
parent1.chrom=new unsigned[lchrom];
parent2.chrom=new unsigned[lchrom];
child1.chrom=new unsigned[lchrom];
child2.chrom=new unsigned[lchrom];
//cout<<"jiaocha"<<endl;///////////////////////
bianma(parent1.geti,parent1.chrom);
bianma(parent2.geti,parent2.chrom);
if(flipc(parent1.fitness,parent2.fitness))
{
for(j=0;j<lchrom;j++)
panan[j]=rnd(0,1);
//for(j=0;j<lchrom;j++)////////////////
// {
// cout<<panan[j];/////////////
// }
// cout<<endl;////////////////
// system("pause");////////////////
for(j=0;j<lchrom;j++)
{
if(panan[j]==1)
child1.chrom[j]=parent1.chrom[j];
else
child1.chrom[j]=parent2.chrom[j];
}
for(j=0;j<lchrom;j++)
{
if(panan[j]==0)
child2.chrom[j]=parent1.chrom[j];
else
child2.chrom[j]=parent2.chrom[j];
}
//for(j=0;j<lchrom;j++)////////////////
//{
// cout<<child1.chrom[j];/////////////
// }
//cout<<endl;////////////////
// system("pause");////////////////
child1.geti=yima(child1.chrom);
child2.geti=yima(child2.chrom);
delete [] child2.chrom;
delete [] child1.chrom;
delete [] parent2.chrom;
delete [] parent1.chrom;
delete [] panan;
}
else
{
for(j=0;j<lchrom;j++)
{
child1.chrom[j]=parent1.chrom[j];
child2.chrom[j]=parent2.chrom[j];
}
child1.geti=yima(child1.chrom);
child2.geti=yima(child2.chrom);
delete [] child2.chrom;
delete [] child1.chrom;
delete [] parent2.chrom;
delete [] parent1.chrom;
delete [] panan;
}
}
void bianyi(indivial &child)//变异
{
child.chrom=new unsigned[lchrom];
//cout<<"变异"<<endl;
bianma(child.geti,child.chrom);
for(int i=0;i<lchrom;i++)
if(flipm(child.fitness))
{
if(child.chrom[i]=0)
child.chrom[i]=1;
else
child.chrom[i]=0;
}
child.geti=yima(child.chrom);
delete [] child.chrom;
}
void bianma(double bianliang,unsigned *p)//编码
{
unsigned *q;
unsigned *gray;
q=new unsigned[lchrom];
gray=new unsigned[lchrom];
int x=0;
int i=0,j=0;
if(bianliang<zuobianjie)///////////////////
{
cout<<"bianliang:"<<bianliang<<endl;/////////
system("pause");
}
//cout<<youbianjie-(zuobianjie)<<endl;
//system("pause");
x=(bianliang-(zuobianjie))*((pow(2,lchrom)-1)/(youbianjie-(zuobianjie)));
//cout<<x<<endl;///////////
if(x<0)
system("pause");///////////
for(i=0;i<lchrom;i++)
{
q[i]=0;
p[i]=0;
}
i=0;
while (x!=0&&(i!=lchrom))
{
q[i]=(unsigned)(x%2);
x=x/2;
i++;
}
// for(i=0;i<lchrom;i++)//////////////////
// cout<<q[i];///////////////
// cout<<endl;///////////
int w=lchrom-1;
if(q[w]!=0&&q[w]!=1)
system("pause");
for(j=0;j<lchrom&&w>0;j++)
{
p[j]=q[w];
w--;
}
//cout<<"yuanma"<<endl;
//for(j=0;j<lchrom;j++)///////////
// cout<<p[j];////////
//cout<<endl;////////////////////
gray[0]=p[0];
for(j=1;j<lchrom;j++)
{
if(p[j-1]==p[j])
gray[j]=0;
else if(p[j-1]!=p[j])
gray[j]=1;
}
for(j=0;j<lchrom;j++)
p[j]=gray[j];
//cout<<"geleima"<<endl;
//for(j=0;j<lchrom;j++)///////////
// cout<<p[j];////////
//cout<<endl;////////////////////
//system("pause");///////////
delete [] gray;
delete [] q;
}
double yima(unsigned *p) //译码
{
int i=0;
// for(i=0;i<lchrom;i++)/////////
// {
// cout<<p[i];//////
// }
// cout<<endl;/////////
// system("pause");//////////
int x=0;
unsigned *q;
q=new unsigned[lchrom];
q[0]=p[0];
// cout<<q[0]<<endl;//////////////////
// system("pause");//////////
for(int j=1;j<lchrom;j++)
{
if(q[j-1]==p[j])
q[j]=0;
else if(q[j-1]!=p[j])
q[j]=1;
}
// for(i=0;i<lchrom;i++)//////
// {
// cout<<q[i];//////////
// if(q[i]!=0&&q[i]!=1)
// {
// cout<<q[i];
// system("pause");
// }
// }
// cout<<endl;////////
// system("pause");///////////////////
for(i=0;i<lchrom;i++)
x=x+q[i]*pow(2,(lchrom-i-1));
if(x<0)
{
cout<<"译码出错1"<<endl;
system("pause");
}
//cout<<"x:"<<x<<endl;
double bianliang;
//cout<<pow(2,22)<<endl;
//cout<<2000*x<<endl;
//cout<<(x*(2000/(pow(2,22)-1)))<<endl;
bianliang=(x*((youbianjie-(zuobianjie))/(pow(2,lchrom)-1)))+zuobianjie;
if(bianliang<zuobianjie)
{
cout<<"译码出错2"<<endl;
system("pause");
}
delete [] q;
return bianliang;
}
double ran1(long *im)
{
int j;
long k;
static long im2=123456789;
static long iy=0;
static long iv[NTAB];
float temp;
if (*im <= 0)
{
if (-(*im) < 1) *im=1;
else *im = -(*im);
im2=(*im);
for (j=NTAB+7;j>=0;j--)
{
k=(*im)/IQ1;
*im=IA1*(*im-k*IQ1)-k*IR1;
if (*im < 0) *im += IM1;
if (j < NTAB) iv[j] = *im;
}
iy=iv[0];
}
k=(*im)/IQ1;
*im=IA1*(*im-k*IQ1)-k*IR1;
if (*im < 0) *im += IM1;
k=im2/IQ2;
im2=IA2*(im2-k*IQ2)-k*IR2;
if (im2 < 0) im2 += IM2;
j=iy/NDIV;
iy=iv[j]-im2;
iv[j] = *im;
if (iy < 1) iy += IMM1;
if ((temp=AM*iy) > RNMX) return RNMX;
else return temp;
}
double suijibianli()//随机遍历
{
double i=ran1(a);
while(i>zhenjuli)
{
i=ran1(a);
}
//cout<<i<<endl;//////////////
return i;
}
int fu(float p)//复制
{
int i;
double sum=0;
if(sumfitness!=0)
{
for(i=0;(sum<p)&&(i<zhongqunshu);i++)
sum+=nowpop[i].fitness/sumfitness;
}
else
i=rnd(1,zhongqunshu1);
return(i-1);
}
int rnd(int low, int high) /*在整数low和high之间产生一个随机整数*/
{
int i;
if(low >= high)
i = low;
else
{
i =(int)((ran1(a) * (high - low + 1)) + low);
if(i > high) i = high;
}
return(i);
}
int flipc(double p,double q)//判断是否交叉
{
double pc1=0.9,pc2=0.6;
if((p-q)>0)
{
if(p>=avefitness)
{
pc=pc1-(pc1-pc2)*(p-avefitness)/(maxfitness-avefitness);
}
else
pc=pc1;
}
else
{
if(q>=avefitness)
{
pc=pc1-(pc1-pc2)*(q-avefitness)/(maxfitness-avefitness);
}
else
pc=pc1;
}
if(ran1(a)<=pc)
return(1);
else
return(0);
}
int flipm(double p)//判断是否变异
{
double pm1=0.001,pm2=0.0001;
if(p>=avefitness)
{
pm=(pm1-(pm1-pm2)*(maxfitness-p)/(maxfitness-avefitness));
}
else
pm=pm1;
if(ran1(a)<=pm)
return(1);
else
return(0);
}
void glp(int n,int s,int *h,int (*q)[1],float (*xx)[1])//glp
{
int i=0,j=0;
//求解q
for(i=0;i<n;i++)
{
for(j=0;j<s;j++)
{
*(*(q+i)+j)=((i+1)*(*(h+j)))%n;
}
}
i=n-1;
for(j=0;j<s;j++)
{
*(*(q+i)+j)=n;
}
//求解x
for(i=0;i<n;i++)
{
for(j=0;j<s;j++)
{
*(*(xx+i)+j)=(float)(2*(*(*(q+i)+j))-1)/(2*n);
}
}
}
BOOL Exist(int Val, int Num, int *Array)//判断一个数是否在一个数组的前Num个数中
{
BOOL FLAG = FALSE;
int i;
for (i=0; i<Num; i++)
if (Val == *(Array + i))
{
FLAG = TRUE;
break;
}
return FLAG;
}
C. 遗传算法中如何实现长度可变的编码
看来也没人回答了,把积分送给我吧!
附送模拟退火遗传算法的源程序
遗传算法求解f(x)=xcosx+2的最大值
其中在尺度变换部分应用到了类似模拟退火算法部分,所有变量均使用汉语拼音很好懂
//中国电子科技集团公司
//第一研究室
//呼文韬
//[email protected]
//随机初始种群
//编码方式为格雷码
//选择方法为随机遍历
//采用了精英保存策略
//采用了自适应的交叉率和变异率
//采用了与模拟退火算法相结合的尺度变换
//采用了均匀交叉法
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <iostream.h>
#include <iomanip.h>
#include <time.h>
#include <windows.h>
#define IM1 2147483563
#define IM2 2147483399
#define AM (1.0/IM1)
#define IMM1 (IM1-1)
#define IA1 40014
#define IA2 40692
#define IQ1 53668
#define IQ2 52774
#define IR1 12211
#define IR2 3791
#define NTAB 32
#define NDIV (1+IMM1/NTAB)
#define EPS 1.2e-7
#define RNMX (1.0-EPS)
#define zhenjuli 0.005
#define PI 3.14159265358
#define T0 100000//温度要取得很高才行。
#define zhongqunshu1 200
#define zuobianjie -2000
#define youbianjie 2000
unsigned int seed=0; //seed 为种子,要设为全局变量
void mysrand(long int i) //初始化种子
{
seed = -i;
}
long a[1];
//double hunn;
//double c=4;
//设置全局变量
struct indivial
{
unsigned *chrom; //染色体;
double geti;//变量值
double shiying; //目标函数的值;
double fitness; //变换后的适应度值;
};
indivial *zuiyougeti;//精英保存策略
int zhongqunshu; //种群大小
indivial *nowpop;//当前代
indivial *newpop;//新一代
double sumfitness;//当代的总适应度fitness
double sumshiying;//当代的总适应度shiying
double maxfitness;//最大适应度
double avefitness;//平均适应度
double maxshiying;//最大适应度
double avgshiying;//平均适应度
float pc;//交叉概率
float pm;//变异概率
int lchrom;//染色体长度
int maxgen;//最大遗传代数
int gen;//遗传代数
//函数
int flipc(double ,double );//判断是否交叉
int flipm(double );//判断是否变异
int rnd(int low,int high);//产生low与high之间的任意数
void initialize();//遗传算法初始化
void preselectfitness(); //计算sumfiness,avefitness,maxfitness
void generation();
double suijibianli();//产生随机遍历指针
int fu(float );//选择要复制的个体
void crossover(indivial ,indivial ,indivial &,indivial &);//交叉
void bianyi(indivial &);//变异
void mubiaohanshu(indivial &);//计算适应度
void chibianhuan(indivial &);//对shiying进行尺度变换赋给fitness
double ran1(long *);//随机数初始
void bianma(double bianliang,unsigned *p);//编码
double yima(unsigned *p);
void guanjiancanshujisuan();//计算shiying,根据shiying计算sumshiying,对shiying进行尺度变换变成fitness,根据fitness计算sumfitness,avefitness,maxfitness
void jingyingbaoliu();
void glp(int n,int s,int *,int (*)[1],float (*)[1]);//glp生成函数
BOOL Exist(int Val, int Num, int *Array);//判断一个数在前面是否出现过
int cmpfitness(const void *p1,const void *p2)
{
float i=((indivial *)p1)->shiying;//现在是按照"适应度"排序,改成"个体"的话就是按照"个体"排序
float j=((indivial *)p2)->shiying;
return i<j ? -1:(i==j ? 0:1);//现在是按升序牌排列,将1和-1互换后就是按降序排列
}
void main()
{
initialize();
cout<<zuiyougeti->geti<<" "<<zuiyougeti->shiying<<endl;/////////////
for(gen=1;gen<maxgen;gen++)
{ generation();
}
jingyingbaoliu();
cout<<setiosflags(ios::fixed)<<setprecision(6)<<zuiyougeti->geti<<" "<<setiosflags(ios::fixed)<<setprecision(6)<<(zuiyougeti->shiying)<<endl;////////////////
delete [] newpop;
delete [] nowpop;
delete [] zuiyougeti;
system("pause");
}
void initialize()
{
int q[zhongqunshu1][1],s=1;
float xx[zhongqunshu1][1];//生成的glp用x储存
int h[1]={1};//生成向量
zuiyougeti=new indivial;//最优个体的生成
zhongqunshu=200;//种群数量
nowpop=new indivial[zhongqunshu1];//当代
newpop=new indivial[zhongqunshu1];//新一代
maxgen=150;//最大代数
gen=0;//起始代
lchrom=22;//基因数量的初始化
mysrand(time(0));//随机数种子
a[0]=seed;//随机数种子
//对最优个体的初始化
zuiyougeti->geti=0;
zuiyougeti->fitness=0;
zuiyougeti->shiying=0;
//
glp(zhongqunshu,s,h,q,xx);
//for(int i=0;i<zhongqunshu1;i++)//产生初始种群
//{
// for(int j=0;j<s;j++)
// {
// nowpop[i].geti=zuobianjie+(youbianjie-zuobianjie)*xx[i][j];
// }
//}
for(int i=0;i<zhongqunshu1;i++)//产生初始种群
{
nowpop[i].geti=zuobianjie+(youbianjie-(zuobianjie))*ran1(a);
}
//nowpop[0].geti=999;//////////////////////////
guanjiancanshujisuan();
jingyingbaoliu(); //精英保留的实现
guanjiancanshujisuan();//计算shiying,根据shiying计算sumshiying,对shiying进行尺度变换变成fitness,根据fitness计算sumfitness,avefitness,maxfitness
}
void jingyingbaoliu() //精英保留的实现
{
indivial *zuiyougetiguo;
zuiyougetiguo=new indivial[zhongqunshu1];//建立一个过渡数组
for(int i=0;i<zhongqunshu;i++)//将当代个体复制到过渡数组中
zuiyougetiguo[i]=nowpop[i];
qsort(zuiyougetiguo,zhongqunshu1,sizeof(indivial),&cmpfitness);//按fitness升序排序
// cout<<"zuiyougetiguo适应度:"<<zuiyougetiguo[zhongqunshu1-1].shiying<<endl;///////////
// cout<<"zuiyougeti适应度:"<<zuiyougeti->shiying<<endl;///////////////////
//system("pause");
if(zuiyougetiguo[zhongqunshu-1].shiying>zuiyougeti->shiying)
{
*zuiyougeti=zuiyougetiguo[zhongqunshu1-1];//如果最优个体的fitness比当代最大的fitness小则用当代的代替之
//cout<<"zuiyougetiguo个体:"<<zuiyougetiguo[zhongqunshu1-1].geti<<endl;/////////////
//cout<<"zuiyougeti个体:"<<zuiyougeti->geti<<endl;/////////////
}
else
nowpop[rnd(0,(zhongqunshu1-1))]=*zuiyougeti;//否则的话从当代中随机挑选一个用最优个体代替之
delete [] zuiyougetiguo;//释放过渡数组
}
void guanjiancanshujisuan()//计算shiying,根据shiying计算sumshiying,对shiying进行尺度变换变成fitness,根据fitness计算sumfitness,avefitness,maxfitness
{
for(int i=0;i<zhongqunshu;i++)//计算shiying
mubiaohanshu(nowpop[i]);
for(i=0;i<zhongqunshu;i++)//对shiying进行尺度变换变成fitness
chibianhuan(nowpop[i]);
preselectfitness();//根据fitness计算sumfitness,avefitness,maxfitness
}
void mubiaohanshu(indivial &bianliang)//计算shiying
{
bianliang.shiying=(bianliang.geti*cos(bianliang.geti)+2.0);//目标函数
}
void chibianhuan(indivial &bianliang)//对shiying进行尺度变换变成fitness
{
double T;//退火温度
T=T0*(pow(0.99,(gen+1-1)));
double sum=0;
for(int j=0;j<zhongqunshu;j++)
sum+=exp(nowpop[j].shiying/T);
bianliang.fitness=exp(bianliang.shiying/T)/sum;//算出fitness
}
void preselectfitness()//根据fitness计算sumfitness,avefitness,maxfitness
{
int j;
sumfitness=0;
for(j=0;j<zhongqunshu;j++)
sumfitness+=nowpop[j].fitness;
indivial *guo;
guo=new indivial[zhongqunshu1];
for(j=0;j<zhongqunshu;j++)
guo[j]=nowpop[j];
qsort(guo,zhongqunshu1,sizeof(indivial),&cmpfitness);
maxfitness=guo[zhongqunshu1-1].fitness;
avefitness=sumfitness/zhongqunshu1;
delete [] guo;
}
void generation()
{
indivial fuqin1,fuqin2,*pipeiguo,*pipeichi;
int *peiishuzu;//用来存放产生的随机配对
pipeiguo=new indivial[zhongqunshu1];
pipeichi=new indivial[zhongqunshu1];
peiishuzu=new int[zhongqunshu1];
int member1,member2,j=0,fujishu=0,i=0,temp=0,tt=0;
float zhen;
//随机遍历的实现
for(zhen=suijibianli();zhen<1;(zhen=zhen+zhenjuli))//设定指针1/66
{
pipeichi[fujishu]=nowpop[fu(zhen)];
fujishu++;
}
//交叉与变异的实现
//交叉
for(i=0;i<zhongqunshu1;i++)
{
peiishuzu[i]=-1;
}
for (i=0; i<zhongqunshu1; i++)
{
temp =rnd(0,zhongqunshu1-1); //产生值在0-zhongqunshu1-1的随机数
while(Exist(temp, i, peiishuzu))//判断产生的随机数是否已经产生过,如果是,则再产生一个随机数
{
temp =rnd(0,zhongqunshu1-1);
}
//如果没有的话,则把产生的随机数放在peiishuzu中
*(peiishuzu+i) = temp;
}
for(i=0;i<zhongqunshu1-1;i=i+2)
{
fuqin1=pipeichi[peiishuzu[i]];
fuqin2=pipeichi[peiishuzu[i+1]];
crossover(fuqin1,fuqin2,newpop[i],newpop[i+1]);
}
for(j=0;j<zhongqunshu1;j++)
{
//if(newpop[j].geti<-1000)
//cout<<"个体数值小于下界了";
nowpop[j].geti=newpop[j].geti;
}
//
guanjiancanshujisuan();
//变异的实现
for(j=0;j<zhongqunshu;j++)
{
bianyi(nowpop[j]);
}
//
guanjiancanshujisuan();
//精英保留的实现
jingyingbaoliu();
//
guanjiancanshujisuan();
delete [] peiishuzu;
delete [] pipeichi;
delete [] pipeiguo;
}
void crossover(indivial parent1,indivial parent2,indivial &child1,indivial &child2)//交叉
{
int j;
unsigned *panan;
panan=new unsigned[lchrom];
parent1.chrom=new unsigned[lchrom];
parent2.chrom=new unsigned[lchrom];
child1.chrom=new unsigned[lchrom];
child2.chrom=new unsigned[lchrom];
//cout<<"jiaocha"<<endl;///////////////////////
bianma(parent1.geti,parent1.chrom);
bianma(parent2.geti,parent2.chrom);
if(flipc(parent1.fitness,parent2.fitness))
{
for(j=0;j<lchrom;j++)
panan[j]=rnd(0,1);
//for(j=0;j<lchrom;j++)////////////////
// {
// cout<<panan[j];/////////////
// }
// cout<<endl;////////////////
// system("pause");////////////////
for(j=0;j<lchrom;j++)
{
if(panan[j]==1)
child1.chrom[j]=parent1.chrom[j];
else
child1.chrom[j]=parent2.chrom[j];
}
for(j=0;j<lchrom;j++)
{
if(panan[j]==0)
child2.chrom[j]=parent1.chrom[j];
else
child2.chrom[j]=parent2.chrom[j];
}
//for(j=0;j<lchrom;j++)////////////////
//{
// cout<<child1.chrom[j];/////////////
// }
//cout<<endl;////////////////
// system("pause");////////////////
child1.geti=yima(child1.chrom);
child2.geti=yima(child2.chrom);
delete [] child2.chrom;
delete [] child1.chrom;
delete [] parent2.chrom;
delete [] parent1.chrom;
delete [] panan;
}
else
{
for(j=0;j<lchrom;j++)
{
child1.chrom[j]=parent1.chrom[j];
child2.chrom[j]=parent2.chrom[j];
}
child1.geti=yima(child1.chrom);
child2.geti=yima(child2.chrom);
delete [] child2.chrom;
delete [] child1.chrom;
delete [] parent2.chrom;
delete [] parent1.chrom;
delete [] panan;
}
}
void bianyi(indivial &child)//变异
{
child.chrom=new unsigned[lchrom];
//cout<<"变异"<<endl;
bianma(child.geti,child.chrom);
for(int i=0;i<lchrom;i++)
if(flipm(child.fitness))
{
if(child.chrom[i]=0)
child.chrom[i]=1;
else
child.chrom[i]=0;
}
child.geti=yima(child.chrom);
delete [] child.chrom;
}
void bianma(double bianliang,unsigned *p)//编码
{
unsigned *q;
unsigned *gray;
q=new unsigned[lchrom];
gray=new unsigned[lchrom];
int x=0;
int i=0,j=0;
if(bianliang<zuobianjie)///////////////////
{
cout<<"bianliang:"<<bianliang<<endl;/////////
system("pause");
}
//cout<<youbianjie-(zuobianjie)<<endl;
//system("pause");
x=(bianliang-(zuobianjie))*((pow(2,lchrom)-1)/(youbianjie-(zuobianjie)));
//cout<<x<<endl;///////////
if(x<0)
system("pause");///////////
for(i=0;i<lchrom;i++)
{
q[i]=0;
p[i]=0;
}
i=0;
while (x!=0&&(i!=lchrom))
{
q[i]=(unsigned)(x%2);
x=x/2;
i++;
}
// for(i=0;i<lchrom;i++)//////////////////
// cout<<q[i];///////////////
// cout<<endl;///////////
int w=lchrom-1;
if(q[w]!=0&&q[w]!=1)
system("pause");
for(j=0;j<lchrom&&w>0;j++)
{
p[j]=q[w];
w--;
}
//cout<<"yuanma"<<endl;
//for(j=0;j<lchrom;j++)///////////
// cout<<p[j];////////
//cout<<endl;////////////////////
gray[0]=p[0];
for(j=1;j<lchrom;j++)
{
if(p[j-1]==p[j])
gray[j]=0;
else if(p[j-1]!=p[j])
gray[j]=1;
}
for(j=0;j<lchrom;j++)
p[j]=gray[j];
//cout<<"geleima"<<endl;
//for(j=0;j<lchrom;j++)///////////
// cout<<p[j];////////
//cout<<endl;////////////////////
//system("pause");///////////
delete [] gray;
delete [] q;
}
double yima(unsigned *p) //译码
{
int i=0;
// for(i=0;i<lchrom;i++)/////////
// {
// cout<<p[i];//////
// }
// cout<<endl;/////////
// system("pause");//////////
int x=0;
unsigned *q;
q=new unsigned[lchrom];
q[0]=p[0];
// cout<<q[0]<<endl;//////////////////
// system("pause");//////////
for(int j=1;j<lchrom;j++)
{
if(q[j-1]==p[j])
q[j]=0;
else if(q[j-1]!=p[j])
q[j]=1;
}
// for(i=0;i<lchrom;i++)//////
// {
// cout<<q[i];//////////
// if(q[i]!=0&&q[i]!=1)
// {
// cout<<q[i];
// system("pause");
// }
// }
// cout<<endl;////////
// system("pause");///////////////////
for(i=0;i<lchrom;i++)
x=x+q[i]*pow(2,(lchrom-i-1));
if(x<0)
{
cout<<"译码出错1"<<endl;
system("pause");
}
//cout<<"x:"<<x<<endl;
double bianliang;
//cout<<pow(2,22)<<endl;
//cout<<2000*x<<endl;
//cout<<(x*(2000/(pow(2,22)-1)))<<endl;
bianliang=(x*((youbianjie-(zuobianjie))/(pow(2,lchrom)-1)))+zuobianjie;
if(bianliang<zuobianjie)
{
cout<<"译码出错2"<<endl;
system("pause");
}
delete [] q;
return bianliang;
}
double ran1(long *im)
{
int j;
long k;
static long im2=123456789;
static long iy=0;
static long iv[NTAB];
float temp;
if (*im <= 0)
{
if (-(*im) < 1) *im=1;
else *im = -(*im);
im2=(*im);
for (j=NTAB+7;j>=0;j--)
{
k=(*im)/IQ1;
*im=IA1*(*im-k*IQ1)-k*IR1;
if (*im < 0) *im += IM1;
if (j < NTAB) iv[j] = *im;
}
iy=iv[0];
}
k=(*im)/IQ1;
*im=IA1*(*im-k*IQ1)-k*IR1;
if (*im < 0) *im += IM1;
k=im2/IQ2;
im2=IA2*(im2-k*IQ2)-k*IR2;
if (im2 < 0) im2 += IM2;
j=iy/NDIV;
iy=iv[j]-im2;
iv[j] = *im;
if (iy < 1) iy += IMM1;
if ((temp=AM*iy) > RNMX) return RNMX;
else return temp;
}
double suijibianli()//随机遍历
{
double i=ran1(a);
while(i>zhenjuli)
{
i=ran1(a);
}
//cout<<i<<endl;//////////////
return i;
}
int fu(float p)//复制
{
int i;
double sum=0;
if(sumfitness!=0)
{
for(i=0;(sum<p)&&(i<zhongqunshu);i++)
sum+=nowpop[i].fitness/sumfitness;
}
else
i=rnd(1,zhongqunshu1);
return(i-1);
}
int rnd(int low, int high) /*在整数low和high之间产生一个随机整数*/
{
int i;
if(low >= high)
i = low;
else
{
i =(int)((ran1(a) * (high - low + 1)) + low);
if(i > high) i = high;
}
return(i);
}
int flipc(double p,double q)//判断是否交叉
{
double pc1=0.9,pc2=0.6;
if((p-q)>0)
{
if(p>=avefitness)
{
pc=pc1-(pc1-pc2)*(p-avefitness)/(maxfitness-avefitness);
}
else
pc=pc1;
}
else
{
if(q>=avefitness)
{
pc=pc1-(pc1-pc2)*(q-avefitness)/(maxfitness-avefitness);
}
else
pc=pc1;
}
if(ran1(a)<=pc)
return(1);
else
return(0);
}
int flipm(double p)//判断是否变异
{
double pm1=0.001,pm2=0.0001;
if(p>=avefitness)
{
pm=(pm1-(pm1-pm2)*(maxfitness-p)/(maxfitness-avefitness));
}
else
pm=pm1;
if(ran1(a)<=pm)
return(1);
else
return(0);
}
void glp(int n,int s,int *h,int (*q)[1],float (*xx)[1])//glp
{
int i=0,j=0;
//求解q
for(i=0;i<n;i++)
{
for(j=0;j<s;j++)
{
*(*(q+i)+j)=((i+1)*(*(h+j)))%n;
}
}
i=n-1;
for(j=0;j<s;j++)
{
*(*(q+i)+j)=n;
}
//求解x
for(i=0;i<n;i++)
{
for(j=0;j<s;j++)
{
*(*(xx+i)+j)=(float)(2*(*(*(q+i)+j))-1)/(2*n);
}
}
}
BOOL Exist(int Val, int Num, int *Array)//判断一个数是否在一个数组的前Num个数中
{
BOOL FLAG = FALSE;
int i;
for (i=0; i<Num; i++)
if (Val == *(Array + i))
{
FLAG = TRUE;
break;
}
return FLAG;
}