遺傳演算法

weixin_30639719發表於2018-05-27

遺傳演算法是解決搜尋問題的一種通用演算法。

模擬自然界優勝劣汰的進化現象,把搜尋問題轉化為遺傳問題,把可能的解轉為成一個向量——染色體,向量的每個元素稱為基因。通過不斷計算各染色體的適應值,選擇最好的染色體,獲得最優解。
基本概念 (以下均以二進位制串 a=<1000101110110101000111> 為例)
1. 遺傳:子代和父代具有相同或相似的性狀,保證物種的穩定性;
2. 變異:子代與父代,子代不同個體之間總有差異,是生命多樣性的根源;
3. 生存鬥爭和適者生存:具有適應性變異的個體被保留,不具適應性變異的個體被淘汰。
自然選擇過程是長期的、緩慢的、連續的過程。
4. 個體與種群
個體就是模擬生物個體而對問題中的物件(一般就是問題的解)的一種稱呼,一個個體也就是搜尋空間中的一個點。
種群就是模擬生物種群而由若干個體組成的群體, 它一般是整個搜尋空間的一個很小的子集。
5. 適應度與適應度函式
適應度就是借鑑生物個體對環境的適應程度,而對問題中的個體物件所設計的表徵其優劣的一種測度。
適應度函式就是問題中的全體個體與其適應度之間的一個對應關係。它一般是一個實值函式。該函式就是遺傳演算法中指導搜尋的評價函式,數值越接近目標值則說明適應度越高。
6. 染色體與基因
染色體(chromosome)就是問題中個體的某種字串形式的編碼表示。字串中的字元也就稱為基因。
7. 遺傳操作
  亦稱遺傳運算元(genetic operator),就是關於染色體的運算。遺傳演算法中有三種遺傳操作:
選擇 (selection)
交叉(crossover,亦稱交換、交配或雜交)
變異(mutation,亦稱突變)

這裡寫圖片描述


現在寫個簡單的例子:設 f(x) = -x2 + 2x + 0.5,求 max f(x), x在[-1, 2]之間。

對於二進位制串 a=<1000101110110101000111> ;

1.先將其轉為十進位制數:ve=2288967

2.將其轉化為[-1,2]內的實數為:
X=-1+ve*(2-(-1))/((2^22)-1)=0.631797

3.隨機的產生一個初始群體(這裡假設初始群體的個體數為 4)
pop1={
<1101011101001100011110>, % a1
<1000011001010001000010>, % a2
<0001100111010110000000>, % a3
<0110101001101110010101>} % a4

4.轉化成 [-1, 2] 之間的十進位制數即為
pop1={ 1.523032,0.574022,-0.697235,0.247238}

5.定義適應函式和求適應值

由於目標函式 f(x)[-1, 2] 內的值有正有負,所以必須通過建立適應函式與目標函式的對映關係,保證對映後的適應值非負,而且目標函式的優化方向應對應於適應值增大的方向,也為以後計算各個體的入選概率打下基礎。

最後假設得到適應值:
g(pop1)={2.226437,2.318543, 0,1.933350}

6.算出入選下一代的概率:
p(pop1)=g(pop1)/sum(g(pop1))
={0.343675, 0.357892, 0, 0.298433}

7.產生種群
newpop1={
<110101110 1001100011110>, % a1
<100001100 1010001000010>, % a2
<10000110010100 01000010>, % a2
<01101010011011 10010101>} % a4
8.交叉:
將第七步的加粗部分交換,(a1與a2,a3與a4)得到如下結果:
<1101011101010001000010>, % a1
<1000011001001100011110>, % a2
<10000110 0 1010010010101>, % a2
<0110101001101101000010>} % a4

9.變異:將a3中加粗基因變異:

<1101011101010001000010>, % a1
<1000011001001100011110>, % a2
<10000110 1 1010010010101>, % a2
<0110101001101101000010>} % a4

10.終止:我們可以採用遺傳指定代數的方法進行停止程式的執行,但是精確度較低,亦可以根據個體的差異來判斷,通過計算種群中基因多樣性測度,即所有基因位相似程度來進行控制


來一個實際的例子加程式碼(本人也正在學習java,如有不足之處歡迎指出)

用遺傳演算法( GA )求如下問題的最優解, x1, x2精確到小數點後2位。 (採用二進位制編碼方法)
max f (x1, x2) = 2x1·sin(8p x2) +x2·cos(13p x1)
x1:[-3,7]
x2:[-4,10]

程式碼如下:


class chromasome{//染色體
    public static final int DNAsize1=10;
    public static final int DNAsize2=11;
    int []DNA1=new int[DNAsize1];
    int []DNA2=new int[DNAsize2];
    chromasome(){
        int a,b;

        for(int i=0;i<DNAsize1;i++){
            a=(int)(0+Math.random()*(1-0+1));
            DNA1[i]=a;
        }
        for(int i=0;i<DNAsize2;i++){
            b=(int)(0+Math.random()*(1-0+1));
            DNA2[i]=b;
        }
    }
    double twoToten1(){
        String a ;
        a=moeth.velueTostr(this.DNA1);
        int d = Integer.parseInt(a, 2); // 2進位制
        double b=Math.pow(2, this.DNAsize1);
        return -3+(d*(7+3)/(b-1));
    }
    double twoToten2(){
        String a ;
        a=moeth.velueTostr(this.DNA2);
        int d = Integer.parseInt(a, 2); // 2進位制
        double b=Math.pow(2, this.DNAsize2);
        return -4+(d*(10+4)/(b-1));
    }
    void variation(){//變異函式

    }
    void getChromasome(){//輸出看看染色體
        System.out.println("-------------------");
        for(int i=0;i<this.DNAsize1;i++){
            System.out.print(this.DNA1[i]);
        }
        System.out.println();
        for(int i=0;i<this.DNAsize2;i++){
            System.out.print(this.DNA2[i]);
        }
        System.out.println();
        System.out.println(this.adapt()-20);
    }
    double adapt(){//求適應值

        //2x1·sin(8p x2) +x2·cos(13p x1)
        double x1=this.twoToten1();
        //System.out.println("x1="+x1);
        double x2=this.twoToten2();
        //System.out.println("x2="+x2);
        double value=2*x1*Math.sin(8*Math.PI*x2)+x2*Math.cos(13*Math.PI*x1);    
        //System.out.println("value="+value);
        return value+20;
    }
}
public class genetic {
    /**
     * @param args
     */
    int TEXT=1;//除錯用的
    static final int DNAnum=220;
    chromasome[] DNAarr=new chromasome[DNAnum];
    double []adapt_arr=new double[DNAnum];
    double []select_rate=new double [DNAnum];
    static final double copulationRate=0.5;//交配概率
    static final double variationRate=0.01;//變異概率
    static int generationNum=0;//遺傳代數
    genetic(){
        this.initDNA();
        if(TEXT==1){

        }
    }
    //--------------------------------------------------------------------------
    void TEXToutput(){
        for(int i=0;i<DNAnum;i++){
            DNAarr[i].getChromasome();
            }
        System.out.println();

    }
    //--------------------------------------------------------------------------
    void initDNA(){//隨機生成多條染色體
        for(int i=0;i<DNAnum;i++){
            DNAarr[i]=new chromasome();
        }
    }
    void formDNA(){
        int a=this.DNAnum/6;
        DNAarr[DNAnum-1]=DNAarr[0];
        //DNAarr[DNAnum-3]=DNAarr[0];
        //DNAarr[DNAnum-5]=DNAarr[0];
        //DNAarr[DNAnum-7]=DNAarr[0];
        //DNAarr[DNAnum-2]=DNAarr[1];
        //DNAarr[DNAnum-4]=DNAarr[1];
//      for(int i=0;i<a;i++){
//          DNAarr[DNAnum-i-1]=DNAarr[i];
//      }
        //DNAarr[DNAnum-2]=DNAarr[0];
        //DNAarr[DNAnum-3]=DNAarr[0];
        //DNAarr[DNAnum-4]=DNAarr[1];
    }
//  int chance(){//計算概率
//      return 1;
//  }
    void select(){
        double num=0;
        for(int i=0;i<this.DNAnum;i++){
            //System.out.println("------------------------"+i+1+"---------------");
            //DNAarr[i].getChromasome();
            adapt_arr[i]=DNAarr[i].adapt();
            num+=adapt_arr[i];
            //System.out.println("-----------------------------------------------");
        }
        for(int i=0;i<this.DNAnum;i++){
            select_rate[i]=adapt_arr[i]/num;
            //System.out.println("------------------------"+i+1+"---------------");
            //System.out.println("select_rate="+select_rate[i]);
            //System.out.println("----------------------------------------------");
        }
    }
    void paixu(){
        for(int i=1;i<select_rate.length;i++){
            double m=select_rate[i];
            chromasome n=DNAarr[i];
            int k=i;
            for(int j=i-1;j>=0&&select_rate[j]<m;j--){
                select_rate[j+1]=select_rate[j];
                DNAarr[j+1]=DNAarr[j];
                k--;
            }
            select_rate[k]=m;
            DNAarr[k]=n;
        }
    }
    void copulation(){//交配函式
        int a;
        for(int j=1;j<DNAnum;j++){
            a=(int)(1+Math.random()*(DNAarr[0].DNAsize1-1-1+1));
            for(int i=a;i<DNAarr[j].DNAsize1;i++){
                int b=DNAarr[j-1].DNA1[i];
                this.DNAarr[j-1].DNA1[i]=DNAarr[j].DNA1[i];
                this.DNAarr[j].DNA1[i]=b;
            }
            j++;
        }

        for(int j=1;j<DNAnum;j++){
            a=(int)(1+Math.random()*(DNAarr[0].DNAsize2-1-1+1));
            for(int i=a;i<DNAarr[j].DNAsize2;i++){
                int l=DNAarr[j-1].DNA2[i];
                this.DNAarr[j-1].DNA2[i]=DNAarr[j].DNA2[i];
                this.DNAarr[j].DNA2[i]=l;
            }
            j++;
        }

    }
    void getDNA(){
        for(int i=0;i<DNAnum;i++){
            DNAarr[i].getChromasome();
        }
    }
    void variation(){
        //int m=(int)(1+Math.random()*(5-1+1));
        //System.out.println(m);
        int m=3;
        while(m--!=0){
        for(int a=0;a<DNAnum;a++){
            int b=a;
            int a_1=(int)(0+Math.random()*(DNAarr[0].DNAsize1-1-0+1));
            //int b=(int)(0+Math.random()*(DNAnum-1-0+1));
            int b_1=(int)(0+Math.random()*(DNAarr[0].DNAsize2-1-0+1));
            //System.out.println("$$$$$$$$$$$$$$$$$$$$$$$$$"+"a="+a+"b="+b+"a_1="+a_1+"b_1="+b_1);
            if(DNAarr[a].DNA1[a_1]==1){
                DNAarr[a].DNA1[a_1]=0;
            }else{
                DNAarr[a].DNA1[a_1]=1;
            }
            if(DNAarr[b].DNA2[b_1]==1){
                DNAarr[b].DNA2[b_1]=0;
            }else{
                DNAarr[b].DNA2[b_1]=1;
            }
        }
        }

    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int nn=20 ;
        while(nn--!=0){

        int m=200;
        genetic g=new genetic();
        g.select();
        g.paixu();
        int oo=0;
        while(m--!=0){
            //System.out.println("##################################");

            //g.getDNA();
            //g.select();
            g.copulation();
            //System.out.println("--------------------交配-------------------");
            //g.getDNA();

            g.variation();
            //System.out.println("-------------------變異------------------");
            //g.getDNA();
            g.select();
            //System.out.println("--------------------選擇-------------------");
            //g.getDNA();

            g.paixu();
            //System.out.println("-------------------形成-------------------");
            g.formDNA();

            //g.select();
            //g.getDNA();
        }
        //g.getDNA();
        //System.out.println(g.DNAarr[0].twoToten1());
        //System.out.println(g.DNAarr[0].twoToten2());
        System.out.println(g.DNAarr[0].adapt()-20);

    }
    }
}

結果:
這裡寫圖片描述

 

轉載於:https://www.cnblogs.com/leishitou/p/5436191.html

相關文章