题目:y=x^5-6x^4+14x^3-2x^2+1 x属于1到20
手动计算一下:
x属于0到19
y=(x+1)^5-6(x+1)^4+14(x+1)^3-2(x+1)^2+1
=x^5-x^4+14x^2+19x+7
发现如果是16到19那么变异算法编码就很麻烦了。先不考虑这部分的问题
中文表述:
编码是L=4,依然采用2进制编码,自然数编码太复杂。我不懂。 所以群体规模我还
是取4,关于编码长度和群体规模的取值我查了一下文档,不知道这个怎么办。就按
照《遗传算法群体规模的研究》来看我还是取4.
然后随机取值。还是4个。既然是随机就用随机数生成函数来搞定。我用均匀分布,
然后在区间里面搞定。[0,3][4,7][8,11][12,15]然后四个区间,慢慢取。
下面进入自动的环节。前面全部都是人工干预的。
step1,计算适应度。即
yi=f(xi) 适应度 Y=yi/Εyi
step2,删除最低适应度的,将最高适应度的复制入最低适应度的。(这个就不算除法
了,反正y也是线性的,直接算极大值吧。)
step3,几个位交换x1和x4,x2和x3 0.5~0.8的概率 第一次玩0.65吧。
step4,变异,每个位,都可能变异吧。0.1的概率。
step5,还是长相完全一样就停止。
下面因为是未付费,而且是学术探讨所以具体代码不给出。超过100行和较难的编码一概不公开。
测试案例,后面给出了完备性算法的结果。结果发现最优解是x=3,y=109,而我算来算去都是x=4,y=108也算是差不多了,哪怕开始选择的时候也有x=3。遗传算法果然是非完备性算法。
- package 遗传算法;
- public class test {
- /**
- * @param args
- */
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- Genetic gen=new Genetic();
- Fuction fun=new Fuction();
- gen.Geneticmain();
- System.out.println("下面是测试案例");
- for(int i=0;i<15;i++){
- System.out.println("x="+i+";y="+fun.fuctionValue(i));
- }
- }
- }
- package 遗传算法;
- public class Genetic {
- private static final double semaphore = 0.65;
- public int []cx={-1,-1,-1,-1};
- public int []bix={-1,-1,-1,-1};
- public int []cy={0,0,0,0};
- public int ty=0;//total y 没啥用
- Fuction fun=new Fuction();//调用
- //主函数
- public void Geneticmain(){
- //初始化
- init();
- while(true){
- //计算适应度
- for(int i=0;i<cx.length;i++)
- cy[i]=fun.fuctionValue(cx[i]);
- //选取最高值
- maxToMin();
- //杂交
- swap(bix[0],0,bix[3],3);
- swap(bix[2],2,bix[1],1);
- //变异
- variaty();
- //判定函数
- if(cx[0]==cx[1]&&cx[2]==cx[3]&&cx[3]==cx[1]) break;
- }
- //打印结果
- System.out.print("x="+cx[1]+";y="+cy[1]);
- }
- //变异函数
- private void variaty() {
- 。。
- }
- //变异
- private void vary(int i, int j) {
- 。。
- }
- //是否变异
- private boolean isVary() {
- boolean flag=false;
- if(Math.random()<=0.1) flag=true;
- return flag;
- }
- //杂交函数
- private void swap(int x, int j, int y, int k) {
- 。。
- }
- //位交换
- private void swapbit(int x, int y, int i) {
- 。。
- }
- }
- //是否交换
- private boolean isswap() {
- 。。
- }
- //最大值复制到最小值里面
- void maxToMin(){
- 。。
- }
- //单个适应度计算
- int sufficient(int i){
- int flag=0;
- flag=cy[i]/ty;
- return flag;
- }
- //初始化x
- void init()
- {。。
- }
- int TenToTwo(int x){
- int flag=0;
- if(x>=8){
- flag+=1000;x-=8;
- }else if(x>=4){
- flag+=100;x-=4;
- }else if(x>=2){
- flag+=10;x-=2;
- }else if(x>=1)
- flag+=1;
- return flag;
- }
- int TwoToTen(int x){
- int flag=0;
- if(x>=1000){
- flag+=8;x-=1000;
- }else if(x>=100){
- flag+=4;x-=100;
- }else if(x>=2){
- flag+=2;x-=10;
- }else if(x>=1)
- flag+=1;
- return flag;
- }
- }
上面公开的有遗传算法的主函数,伪二进制转化成十进制,伪十进制转化成二进制。
下面是关于函数部分。这个有可能是要手动调整的。
- package 遗传算法;
- public class Fuction {
- public int[] x={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
- //{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
- public int fuctionValue(int x){
- int flag=0;
- int y=0;
- y=x^5-x^4+14*x^2+19*x+7;
- flag=y;
- return flag;
- }
- }
一共代码250行。写了大概7小时。如果有探讨欢迎探讨。伸手党我也准备了伪的2~10进制相互转化。