1. 程式人生 > >採用遺傳演算法求解函式最優值

採用遺傳演算法求解函式最優值

一、實驗要求

遺傳演算法(Genetic AlgorithmsGA)是一種基於自然選擇和自然遺傳機制的搜尋演算法,它是一種有效的解決最優化問題的方法,屬於一種進化演算法。本實驗要求採用簡單遺傳演算法求解如下一元函式的最大值:

二、遺傳演算法基本流程

遺傳演算法由美國Michigan大學的John Holland和他的同事及學生提出的。類似於自然界演化的基本法則,適者生存是遺傳演算法的核心機制:複製(reproduce)、雜交(crossover)、變異(mutation)等自然界的生物演化規則在遺傳演算法中都得到類似的體現。遺傳演算法是從代表問題可能潛在解集的一個種群開始的。初代種群產生之後,按照適者生存、優勝劣汰的原理,逐代進化產生出越來越好的近似種群在每一代中,根據問題域中個體適應度大小挑選個體,並藉助自然遺傳學的遺傳運算元進行組合交叉和變異,產生出代表解的解集的種群。這個過程將導致種群像自然進化一樣的後生代種群比前代更加適應於環境,末代種群中的最優個體經過解碼可以作為問題近似最優解。

遺傳演算法的流程框圖大體如下:

三、遺傳演算法求解詳細過程

1)編碼

變數x作為實數,可以視為遺傳演算法的表現形式。從表現型到基因型的對映稱為編碼。二進位制編碼將某個變數值代表的個體表示為一個[0,1]二進位制串(遺傳演算法最簡單、最經典的編碼方法)。若設定求解精確到6位小數,由於區間長度為2-(-1)=3,必須將區間[-1,2]分為3*10^6等份。因為2097152=2^21<3*10^6<=2^22=4194304,所以編碼的二進位制串長至少需要22位。

2)產生初始種群

個體由串長為22的隨機產生的二進位制串組成染色體的基因碼,產生一定數目的個體組成種群,種群的大小(規模)就是指種群中的個體數目。

3)計算適應度

適應度大的個體其存活和被選中的概率大。適應度的計算就是對個體的計算,本例求函式最大值,目標函式值大的個體適應度大,所以直接引用目標函式作為適應度函式f(s)=f(x)。例如x1=0.637197通過編碼得到的二進位制串是s1=[1000101110110101000111],這個串就是個體。此個體的適應度就是:

假設選擇種群數量為3 ,每個個體為s1=[1000101110110101000111],s2=[0000001110000000010000],s3=[1110000000111111000101],分別對應於數量值x1=0.637197,x2=-0.958973, x3=1.627888,另兩個個體的適應度計算如下:

4)選擇

採用輪盤賭選擇法,f(s1)=2.286345

f(s2)=1.078878f(s3)=3.250650,把三個適應度依比例畫在輪盤上,轉動輪盤,最後停在哪裡,就選擇誰,適應度大的被選中概率大。

選擇方法的實現:產生[0,1]間的隨機數,以隨機數落在那個範圍進行選擇:

[0,0.16)[0.16,0.51)[0.51,1]

5)遺傳操作

下面是經過選擇操作後的兩個個體:

s2=[00000 01110000000010000] 

s3=[11100 00000111111000101]

首先執行單點交叉,隨機隨機選擇交叉點,將之後的串交叉,得到新的兩個個體為:

s2'=[00000 00000111111000101] 
s3'=[11100 01110000000010000]

這兩個個體的適應度分別為:

6)變異操作

假定以一小概率選擇S3的第5個遺傳因子(第5位)變異,遺傳因子由原來的0變為1,產生新個體:s3'=[1110100000111111000101],該個體適應度為:

個體的適應度比它的父個體的適應度減小了。

但如果選中第11個遺傳因子變異,產生新個體為s3''= [11100000001111111000101],適應度,又發現s3''的適應度比其父個體的適應度改善了,這說明變異操作的擾動作用(全域性搜尋)。

CODE:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
//import java.util.Scanner;

public class GA {
static int geneLength = 22;
static int individualSize = 16;
static int maxEvolve = 50;
static double crossoverProbability = 0.7;
static double mutationProbablility = 0.2;
static double sumFitness = 0.0;
static class individual implements Cloneable{
double fitness;
double Pl;
double Pr;
int[] gene;


public individual(double fitness, double pl, double pr, int[] gene) {
super();
this.fitness = fitness;
Pl = pl;
Pr = pr;
this.gene = gene;
}


@Override
public String toString() {
return "individual [fitness=" + fitness + ", Pl=" + Pl + ", Pr=" + Pr + ", gene=" + Arrays.toString(gene)
+ "]";
}




public Object clone(){
individual idd = null;
try {
idd = (individual) super.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
idd.gene = this.gene.clone();
return idd;
}
}

static List<individual> initPop(){
List<individual> population = new ArrayList<individual>();
int ca = 0;
while(ca < individualSize){
int[] gene = new int[geneLength];
for(int i=0; i<geneLength; i++){
gene[i] = (int)(Math.random()*100)%2;
}
population.add(new individual(0.0, 0.0, 0.0, gene));
ca++;
}
return population;
}

static void updateFitness(List<individual> population){
int constant = 4194103;
for(int i=0; i<individualSize; i++){
StringBuffer sb = new  StringBuffer();
for(int j=0; j<geneLength; j++){
sb.append(population.get(i).gene[j]);
}
int H = Integer.valueOf(sb.toString(), 2);
double x = -1.0 + 3.0*(H*1.0/constant*1.0);
population.get(i).fitness = x*Math.sin(10*Math.PI*x)+2.0;
sumFitness += population.get(i).fitness;
}
}


static individual bestIndividual(List<individual> population){
individual best = (individual) population.get(0).clone();
for(int i=1; i<individualSize; i++){
if(population.get(i).fitness > best.fitness){
best = (individual) population.get(i).clone();
}
}
return best;
}

static List<individual> selectPop(List<individual> population){
int ca = 0;
List<individual> newPopulation = new ArrayList<individual>();
double start = 0.0;
for(int i=0; i<individualSize; i++){
double p = population.get(i).fitness/sumFitness;
population.get(i).Pl = start;
population.get(i).Pr = p + start;
start = population.get(i).Pr;

}
while(ca < individualSize){
boolean flag = false;
double P = Math.random();
for(int j=0; j<individualSize; j++){
if(P>population.get(j).Pl && P<population.get(j).Pr){
newPopulation.add(population.get(j));
flag = true;
break;
}
}
if(!flag){
newPopulation.add(bestIndividual(population));
}
ca++;
}
return newPopulation;
}

static void crossover(List<individual> population){
boolean flag = false;
int father = 0;
int mother = 0;

for(int i=0; i<individualSize; i++){
double P = Math.random();
if(P < crossoverProbability){
if(flag){
mother = i;
int l = (int) (Math.random()*geneLength);
int r = (int) (Math.random()*geneLength);
if(l>r){
int t = l;
l = r;
r = t;
}
int t[] = new int[geneLength];
for(int f=l; f<r; f++){
t[f] = population.get(father).gene[f];
population.get(father).gene[f] = population.get(mother).gene[f];
population.get(mother).gene[f] = t[f];
}
flag = false;
}
else{
father = i;
flag = true;
}
}
}
}

static void mutation(List<individual> population){
for(int i=0; i<individualSize; i++){
double p = Math.random();
if(p<mutationProbablility){
int cnt = (int) (Math.random()*geneLength);
while(cnt>0){
int point = (int) (Math.random()*(geneLength-1));
population.get(i).gene[point] = 1-population.get(i).gene[point];
cnt -= 1;
}
}
}


for(int i=0; i<geneLength; i++){
int count = 0;
for(int j=0; j<individualSize; j++){
count += population.get(j).gene[i];
}


if(count<3 || count>(individualSize-3)){
int cn = (int) (Math.random()*individualSize);
population.get(cn).gene[i] = 1-population.get(cn).gene[i];
int cn1 = (int) (Math.random()*individualSize);
while(cn1==cn){
cn1 = (int) (Math.random()*individualSize);
}
population.get(cn1).gene[i] = 1-population.get(cn1).gene[i];
}
}


}

public static void main(String[] args) {
//Scanner in = new Scanner(System.in);
int ca = 0;
List<individual> population = initPop();
updateFitness(population);
List<individual> bestList = new ArrayList<individual>();
while(ca < maxEvolve){
List<individual> newP = selectPop(population);
crossover(newP);
mutation(newP);
population = newP;
updateFitness(population);
bestList.add(bestIndividual(population));
ca++;
System.out.println();
for(int i=0; i<individualSize; i++){
System.out.print("基因:"+Arrays.toString(population.get(i).gene)+" ");
System.out.println("函式值:"+population.get(i).fitness);
}
}
System.out.println("---------------結果---------------");
individual P = bestIndividual(population);
System.out.print("基因:"+Arrays.toString(P.gene)+" ");
System.out.println("函式值:"+P.fitness);
}
}

輸出:


問題函式影象:


演算法進化影象: