算法 003. 一个例子介绍遗传算法及例子的 Java 代码实现

1. 简介

-. 遗传算法 是受达尔文自然选择进化论的激发下,提出的一个 寻找最优解 的算法。该算法反映了自然选择的过程,即选择最合适的个体进行繁殖,以产生下一代的后代。

在这里插入图片描述

2. 自然选择的概念

  • 自然选择的过程开始于从一个种群中寻找最优个体,他们产生的后代继承了父母的特性,并将这些特性遗传给下一代。如果他们的父母有更好的特性,他们的后代将有比他们父母更好的特性以便他们有更大的机会生存下去。这个过程会不断地迭代直至最后找到一个最适合生存地个体。

这个概念能够应用到一个寻找问题。我们考虑一个问题的一组解决方法并从中选择最好的一组解决方案。

在遗传算法中考虑了 5 个步骤:

  1. 初始化种群 (Initial population
  2. 最优函数 (Fitness function
  3. 选择 (Selection
  4. 交换 (父母的特性(基因)交换 Crossover
  5. 突变 (Mutation

3. 初始化种群 (Initial population

这个过程开始于一个称为种群 Population 的一组个体的集合。其中每一个个体是对这个问题你想要的解决办法。

一个个体的特性用一组参数(变量)来表征,也就是我们所知的基因 (Genes),基因被连成一串来组成一条染色体(Chmorosome),也就是解决方案(Solution)。

在一个遗传算法中,一个个体的基因组合使用一个字符串来表示,比方说字母表——“CGGTTAGGTTAGCAATAACATCTAAGAGAAAAA”。然而很多时候,二进制数值会被使用来表示这个字符串(01)。我们说在这个染色体中编码(encode)基因。

在这里插入图片描述

4. 适应度函数 (Fitness Function

这个适应度函数(Fitness Function)决定了这个个体的适应能力(一个个体跟另外的个体比较后得出的能力高低)。它给出了每个个体的健康评估(fitness score)。个体被选择作为繁衍下一代的可能性是取决于对个体的健康评估(fitness score)。

5. 选择 (Selection

选择阶段的概念是指选择最优的基因的个体并让他们把基因传给下一代。

一对个体(父母 parents)被选择是基于他们的健康评估(fitness score),高评估值的个体有更大的机会被选作为繁衍后代。

6. 交换 (父母的特性(基因)交换 Crossover

Crossover 在遗传算法里是最重要的一个阶段。每一对父母都需要交配(mate),一个基因交换点(crossver point)会在基因中随机选定。

比如:考虑到 crossover point3,那么如下图所示:

在这里插入图片描述

后代是通过交换父母(A1 A2)之间的基因产生的,直到达到 crossver point

在这里插入图片描述

新的后(A5 A6)能够加进后代中:

new offspring

7. 突变 (mutation

在某些新形成的后代中,它们的一些基因会以低随机概率发生突变(mutation)。这意味着位串中的一些位可以被翻转。

在这里插入图片描述
突变 (mutation) 的发生是为了保持种群内的多样性并防止过早收敛 (convergence)。

8. 终止 (Termination

如果种群已经收敛 (不会产生与上一代显著不同的后代),算法将终止。那么,就说遗传算法为我们的问题提供了一套解决方案。

9. 解释 (Comments

  • 人口的规模是固定的。随着新一代的形成,最不适合的个体死亡,为新的后代提供空间。

  • 重复这个阶段的序列,在每一代中产生比上一代更好的个体。

10. 伪代码 (Pseudocode

START
Generate the initial population
Compute fitness
REPEAT
    Selection
    Crossover
    Mutation
    Compute fitness
UNTIL population has converged
STOP

11. 一个例子的应用,使用 Java 实现

  • 下面是一个用Java实现遗传算法的例子。您可以随意使用这些代码。
  • 给定一组5个基因,每个基因可以保存一个二进制值0和1。
  • 适应度值 (fitness value) 是根据基因组中存在的 1 的数量来计算的。如果有五个 1,那么它拥有最大的适合度 (maximum fitness)。如果没有 1,那么它的适合度最小 (minimum fitness)。
  • 该遗传算法试图最大化适应度函数 (fitness function),以提供一个由最适个体组成的种群,比如说:个体的基因有 5 个 1
  • 注:在本例中,在交叉 (crossover)和变异 (mutation) 之后,最不适合的个体从新的最适合的后代 (offspring) 中被取代。
import java.util.Random;

/**
 *
 * @author Vijini
 */

//Main class
public class SimpleDemoGA {

    Population population = new Population();
    Individual fittest;
    Individual secondFittest;
    int generationCount = 0;

    public static void main(String[] args) {

        Random rn = new Random();

        SimpleDemoGA demo = new SimpleDemoGA();

        //Initialize population
        demo.population.initializePopulation(10);

        //Calculate fitness of each individual
        demo.population.calculateFitness();

        System.out.println("Generation: " + demo.generationCount + " Fittest: " + demo.population.fittest);

        //While population gets an individual with maximum fitness
        while (demo.population.fittest < 10) {
            ++demo.generationCount;

            //Do selection
            demo.selection();

            //Do crossover
            demo.crossover();

            //Do mutation under a random probability
            if (rn.nextInt()%11 < 10) {
                demo.mutation();
            }

            //Add fittest offspring to population
            demo.addFittestOffspring();

            //Calculate new fitness value
            demo.population.calculateFitness();

            System.out.println("Generation: " + demo.generationCount + " Fittest: " + demo.population.fittest);
        }

        System.out.println("\nSolution found in generation " + demo.generationCount);
        System.out.println("Fitness: "+demo.population.getFittest().fitness);
        System.out.print("Genes: ");
        for (int i = 0; i < 5; i++) {
            System.out.print(demo.population.getFittest().genes[i]);
        }

        System.out.println("");

    }

    //Selection
    void selection() {

        //Select the most fittest individual
        fittest = population.getFittest();

        //Select the second most fittest individual
        secondFittest = population.getSecondFittest();
    }

    //Crossover
    void crossover() {
        Random rn = new Random();

        //Select a random crossover point
        int crossOverPoint = rn.nextInt(population.individuals[0].geneLength);

        //Swap values among parents
        for (int i = 0; i < crossOverPoint; i++) {
            int temp = fittest.genes[i];
            fittest.genes[i] = secondFittest.genes[i];
            secondFittest.genes[i] = temp;

        }

    }

    //Mutation
    void mutation() {
        Random rn = new Random();

        //Select a random mutation point
        int mutationPoint = rn.nextInt(population.individuals[0].geneLength);

        //Flip values at the mutation point
        if (fittest.genes[mutationPoint] == 0) {
            fittest.genes[mutationPoint] = 1;
        } else {
            fittest.genes[mutationPoint] = 0;
        }

        mutationPoint = rn.nextInt(population.individuals[0].geneLength);

        if (secondFittest.genes[mutationPoint] == 0) {
            secondFittest.genes[mutationPoint] = 1;
        } else {
            secondFittest.genes[mutationPoint] = 0;
        }
    }

    //Get fittest offspring
    Individual getFittestOffspring() {
        if (fittest.fitness > secondFittest.fitness) {
            return fittest;
        }
        return secondFittest;
    }


    //Replace least fittest individual from most fittest offspring
    void addFittestOffspring() {

        //Update fitness values of offspring
        fittest.calcFitness();
        secondFittest.calcFitness();

        //Get index of least fit individual
        int leastFittestIndex = population.getLeastFittestIndex();

        //Replace least fittest individual from most fittest offspring
        population.individuals[leastFittestIndex] = getFittestOffspring();
    }

}


//Individual class
class Individual {

    int fitness = 0;
    int[] genes = new int[10];
    int geneLength = 10;

    public Individual() {
        Random rn = new Random();

        //Set genes randomly for each individual
        for (int i = 0; i < genes.length; i++) {
            genes[i] = Math.abs(rn.nextInt() % 2);
        }

        fitness = 0;
    }

    //Calculate fitness
    public void calcFitness() {

        fitness = 0;
        for (int i = 0; i < geneLength; i++) {
            if (genes[i] == 1) {
                ++fitness;
            }
        }
    }

}

//Population class
class Population {

    int popSize = 10;
    Individual[] individuals = new Individual[10];
    int fittest = 0;

    //Initialize population
    public void initializePopulation(int size) {
        for (int i = 0; i < individuals.length; i++) {
            individuals[i] = new Individual();
        }
    }

    //Get the fittest individual
    public Individual getFittest() {
        int maxFit = Integer.MIN_VALUE;
        int maxFitIndex = 0;
        for (int i = 0; i < individuals.length; i++) {
            if (maxFit <= individuals[i].fitness) {
                maxFit = individuals[i].fitness;
                maxFitIndex = i;
            }
        }
        fittest = individuals[maxFitIndex].fitness;
        return individuals[maxFitIndex];
    }

    //Get the second most fittest individual
    public Individual getSecondFittest() {
        int maxFit1 = 0;
        int maxFit2 = 0;
        for (int i = 0; i < individuals.length; i++) {
            if (individuals[i].fitness > individuals[maxFit1].fitness) {
                maxFit2 = maxFit1;
                maxFit1 = i;
            } else if (individuals[i].fitness > individuals[maxFit2].fitness) {
                maxFit2 = i;
            }
        }
        return individuals[maxFit2];
    }

    //Get index of least fittest individual
    public int getLeastFittestIndex() {
        int minFitVal = Integer.MAX_VALUE;
        int minFitIndex = 0;
        for (int i = 0; i < individuals.length; i++) {
            if (minFitVal >= individuals[i].fitness) {
                minFitVal = individuals[i].fitness;
                minFitIndex = i;
            }
        }
        return minFitIndex;
    }

    //Calculate fitness of each individual
    public void calculateFitness() {

        for (int i = 0; i < individuals.length; i++) {
            individuals[i].calcFitness();
        }
        getFittest();
    }

}

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

Solution found in generation 44
Fitness: 10
Genes: 1111111111
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值