用Java实现简单的遗传算法

遗传算法是解决复杂问题的一种搜索策略,是一种智能计算。他模拟自然界中的种群进化。从这点看,它和神经网络这些算法的起源很像,都是使用计算机去模拟一些自然法则和运作规律。同样,和神经网络一样,遗传算法也是一种基于概率的算法。当然,在现代启发式算法中,很多算法都都是基于概率的,比如神经网络,粒子群算法,模拟退火等。这类方法的要解决的一个问题就是NP问题,要求得结果是满意解,而非最优解。理解这点,我觉得很重要。
本文中的GA实现的例子来自于http://www.theprojectspot.com/tutorial-post/creating-a-genetic-algorithm-for-beginners/3 一文。有兴趣的读者,也可以参考原文的实现。
遗传算法工作的时候,可以分为以下几个步骤:
1.初始化:首先需要初始化一个种群,大小可以根据需要随意,几个个体或者几千个个体都可以。种群的中个体的产生是随机的。
2.评估:每一个种群成员需要计算他们的适应度,就和自然界里的生物对自然环境的适应度一样。这里的适应度计算是一个关键,一个基本原则是,把对解决当前问题有意义的个体的适应度应该设置得比较高,否则应该给一个低的适应度。适应度计算函数很影响遗传算法性能。因为每一次进化,每一次迭代,每一个个体都要不停得被评估,如果这个方法很慢,搜索性能就会比较差。
3.选择:选择适应度比较高的个体进入下一个进化阶段。适应度低的可以抛弃。
4.交叉:将选中的个体进行基因交叉,产生下一代种群。这个过程就和自然界中生物体有性生殖一样,做DNA的交叉。
5.变异:和自然界一样,DNA是会变异的,变异操作可以帮助我们跳出局部最优。
6.重复:不停重复以上评估、选择、交叉、变异,直到找到一个满意的个体作为算法的最终解。
下面来看一个实现,首先看一下个体:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package  simpleGa ;

public  class Individual  {

     static  int defaultGeneLength  =  64 ;
     private  byte [ ] genes  =  new  byte [defaultGeneLength ] ;
     private  int fitness  =  0 ;

     // 随机的个体
     public  void generateIndividual ( )  {
         for  ( int i  =  0 ; i  < size ( ) ; i ++ )  {
             byte gene  =  ( byte )  Math. round ( Math. random ( ) ) ;
            genes [i ]  = gene ;
         }
     }

     // Use this if you want to create individuals with different gene lengths
     public  static  void setDefaultGeneLength ( int length )  {
        defaultGeneLength  = length ;
     }
    
     public  byte getGene ( int index )  {
         return genes [index ] ;
     }

     public  void setGene ( int index,  byte value )  {
        genes [index ]  = value ;
        fitness  =  0 ;
     }

     public  int size ( )  {
         return genes. length ;
     }

     public  int getFitness ( )  {
         if  (fitness  ==  0 )  {
            fitness  = FitnessCalc. getFitness ( this ) ;
         }
         return fitness ;
     }

    @Override
     public  String toString ( )  {
         String geneString  =  “” ;
         for  ( int i  =  0 ; i  < size ( ) ; i ++ )  {
            geneString  += getGene (i ) ;
         }
         return geneString ;
     }
}

每一个个体需要计算它的适应度:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package  simpleGa ;

public  class FitnessCalc  {

     static  byte [ ] solution  =  new  byte [ 64 ] ;

     // 设置一个候选解
     public  static  void setSolution ( byte [ ] newSolution )  {
        solution  = newSolution ;
     }

     // 设置一个候选解 就是参数类型不一样,这里做个转换
     static  void setSolution ( String newSolution )  {
        solution  =  new  byte [newSolution. length ( ) ] ;
         // Loop through each character of our string and save it in our byte 
         // array
         for  ( int i  =  0 ; i  < newSolution. length ( ) ; i ++ )  {
             String character  = newSolution. substring (i, i  +  1 ) ;
             if  (character. contains ( “0” )  || character. contains ( “1” ) )  {
                solution [i ]  =  Byte. parseByte (character ) ;
             }  else  {
                solution [i ]  =  0 ;
             }
         }
     }

     // 计算某一个个体的适应度
     static  int getFitness (Individual individual )  {
         int fitness  =  0 ;
         // 个体和候选解比较,约接近候选集,适应度越高
         for  ( int i  =  0 ; i  < individual. size ( )  && i  < solution. length ; i ++ )  {
             if  (individual. getGene (i )  == solution [i ] )  {
                fitness ++;
             }
         }
         return fitness ;
     }
    
     // 适应度的最大值
     static  int getMaxFitness ( )  {
         int maxFitness  = solution. length ;
         return maxFitness ;
     }
}

基于个体而产生的种群:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package  simpleGa ;

public  class Population  {

    Individual [ ] individuals ;
     // 建立一个总群
     public Population ( int populationSize,  boolean initialise )  {
        individuals  =  new Individual [populationSize ] ;
         // 初始化种群
         if  (initialise )  {
             // 建立每一个个体
             for  ( int i  =  0 ; i  < size ( ) ; i ++ )  {
                Individual newIndividual  =  new Individual ( ) ;
                newIndividual. generateIndividual ( ) ;
                saveIndividual (i, newIndividual ) ;
             }
         }
     }

     public Individual getIndividual ( int index )  {
         return individuals [index ] ;
     }

     public Individual getFittest ( )  {
        Individual fittest  = individuals [ 0 ] ;
         // 取得适应度最高的个体作为种群的适应度
         for  ( int i  =  0 ; i  < size ( ) ; i ++ )  {
             if  (fittest. getFitness ( )  <= getIndividual (i ). getFitness ( ) )  {
                fittest  = getIndividual (i ) ;
             }
         }
         return fittest ;
     }

     // Get population size
     public  int size ( )  {
         return individuals. length ;
     }

     // Save individual
     public  void saveIndividual ( int index, Individual indiv )  {
        individuals [index ]  = indiv ;
     }
}

基于以上的个体和种群,就可以进行遗传算法的主要工作,交叉,变异等等。来看一下核心的算法实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
package  simpleGa ;

public  class Algorithm  {

     private  static  final  double uniformRate  =  0.5 ;
     private  static  final  double mutationRate  =  0.015 ;
     private  static  final  int tournamentSize  =  5 ;
     private  static  final  boolean elitism  =  true ;
    
     // 进化一个种群
     public  static Population evolvePopulation (Population pop )  {
        Population newPopulation  =  new Population (pop. size ( )false ) ;

         // 保留最优秀的个体
         if  (elitism )  {
            newPopulation. saveIndividual ( 0, pop. getFittest ( ) ) ;
         }
         // 交叉种群
         int elitismOffset ;
         if  (elitism )  {
            elitismOffset  =  1 ;
         }  else  {
            elitismOffset  =  0 ;
         }
         // 交叉产生新的个体
         for  ( int i  = elitismOffset ; i  < pop. size ( ) ; i ++ )  {
         //确保不要把最差的个体选进来
            Individual indiv1  = tournamentSelection (pop ) ;
            Individual indiv2  = tournamentSelection (pop ) ;
            Individual newIndiv  = crossover (indiv1, indiv2 ) ;
            newPopulation. saveIndividual (i, newIndiv ) ;
         }

         // 变异
         for  ( int i  = elitismOffset ; i  < newPopulation. size ( ) ; i ++ )  {
            mutate (newPopulation. getIndividual (i ) ) ;
         }

         return newPopulation ;
     }

     // 交叉
     private  static Individual crossover (Individual indiv1, Individual indiv2 )  {
        Individual newSol  =  new Individual ( ) ;
         // Loop through genes
         for  ( int i  =  0 ; i  < indiv1. size ( ) ; i ++ )  {
             // 以一定概率交叉
             if  ( Math. random ( )  <= uniformRate )  {
                newSol. setGene (i, indiv1. getGene (i ) ) ;
             }  else  {
                newSol. setGene (i, indiv2. getGene (i ) ) ;
             }
         }
         return newSol ;
     }

     // 变异
     private  static  void mutate (Individual indiv )  {
         // Loop through genes
         for  ( int i  =  0 ; i  < indiv. size ( ) ; i ++ )  {
             if  ( Math. random ( )  <= mutationRate )  {
                 // 以一定概率变异
                 byte gene  =  ( byte )  Math. round ( Math. random ( ) ) ;
                indiv. setGene (i, gene ) ;
             }
         }
     }

     // 选择用于交叉的个体,确保最差的个体不会进来
     private  static Individual tournamentSelection (Population pop )  {
        Population tournament  =  new Population (tournamentSize,  false ) ;
         for  ( int i  =  0 ; i  < tournamentSize ; i ++ )  {
             int randomId  =  ( int )  ( Math. random ( )  * pop. size ( ) ) ;
            tournament. saveIndividual (i, pop. getIndividual (randomId ) ) ;
         }
        Individual fittest  = tournament. getFittest ( ) ;
         return fittest ;
     }
}

以上就是全部的实现,最后,测试这些代码

    原文作者:遗传算法
    原文地址: https://blog.csdn.net/wanglha/article/details/44920653
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞