Java遗传算法(GA)简单例子


前言

Java遗传算法(GA)简单例子
采用的是实数编码

一、解决的函数

f(x) = x1²+x2²+x3²

    //计算适应度,函数式的解
    public static double fitness(double[] individual, int N) {
        double f = 0;
        for (int i = 0; i < N; i++) {
            f += individual[i] * individual[i];
        }
        return f;
    }

想要解决别的函数只需要改变适应度函数
列如求
在这里插入图片描述

只需要把函数改为

//计算适应度,函数式的解
    public static double fitness(double[] individual, int N) {
        double f = 0, f1 = 0, f2 = 0;
        for (int i = 0; i < N - 1; i++) {
            f1 = (individual[i + 1] - individual[i] * individual[i]) * (individual[i + 1] - individual[i] * individual[i]) * 100;
            f2 = (individual[i] - 1) * (individual[i] - 1);
            f += f1 + f2;
        }
        return f;
    }

二、遗传和变异算子

1.交叉

随机交换父类和母类的基因组成子类

//3.交叉
            for (int i = 0; i < NP; i++) {
                double cr = Math.random();
                if (cr < CR) {//交叉
                    //与哪个个体交叉,随机生成一个个体
                    int indiv = random.nextInt(10);
                    //从那个位置交叉,随机生成一个位置
                    int index = random.nextInt(SIZE);
                    for (int j = 0; j < SIZE; j++) {
                        if (j == index) {//发生交叉的片段
                            cr_population[i][j] = select_population[indiv][j];
                        } else { //不发生交叉的片段
                            cr_population[i][j] = select_population[i][j];
                        }
                    }
                } else {//不交叉
                    for (int j = 0; j < SIZE; j++) {
                        cr_population[i][j] = select_population[i][j];
                    }
                }
            }

2.变异

变异通过在父类的基础上随机减去一个random.nextDouble()

//4.变异
            for (int i = 0; i < NP; i++) {
                double mu = Math.random();
                if (mu < MU) {//变异
                    //在那个位置变异
                    int index = random.nextInt(SIZE);
                    for (int j = 0; j < SIZE; j++) {
                        if (j == index) {
                            mu_population[i][j] = mu_population[i][j] - random.nextDouble();
                        } else {
                            mu_population[i][j] = cr_population[i][j];
                        }
                    }
                } else {//不变异
                    for (int j = 0; j < SIZE; j++) {
                        mu_population[i][j] = select_population[i][j];
                    }
                }
            }

源代码

package GA;

import java.util.Random;

class GA1 {
    public static void main(String[] args) {

        //开始时间
        long startTime = System.currentTimeMillis();

        int N = 3;//维度
        int NP = 500;//种群规模
        int SIZE = 3; //因为找三个所以数基因数为3
        int maxGen = 100;//迭代次数
        double CR = 0.8;//交叉概率
        double MU = 0.02;//变异概率
        double MAX = 10;//上限
        double MIN = -10;//下限
        double[][] init_population = new double[NP][SIZE];//初始化种群
        double[][] select_population = new double[NP][SIZE];//选择后的优质种群
        double[][] cr_population = new double[NP][SIZE];//交叉后种群
        double[][] mu_population = new double[NP][SIZE];//变异后种群
        double best_Y = Integer.MAX_VALUE;
        double[] best = new double[maxGen];//最优解

        double[] Y = new double[NP]; //对应种群中每个个体的适应度
        double[] addSumP = new double[NP];//每个个体被选中的概率累加和
        Random random = new Random();

        //1.初始化种群
        for (int i = 0; i < NP; i++) {
            for (int j = 0; j < SIZE; j++) {
                init_population[i][j] = MIN + random.nextDouble() * (MAX - MIN);//随机生成解
            }
        }

        //迭代
        for (int G = 0; G < maxGen; G++) {

            //2.选择优质个体,根据轮盘赌的形式挑选个体
            double sumY = 0;
            for (int i = 0; i < NP; i++) {//计算每个个体的适应度及全部适应度和
                Y[i] = fitness(init_population[i], N);
                sumY += Y[i];
            }
            double addSum = 0;
            for (int i = 0; i < NP; i++) {//记录每个个体别选中的累加和
                addSum += Y[i] / sumY;//当前个体概率
                addSumP[i] = addSum;//累加和
            }
            //根据累加和概率,判断轮盘指针是向那个个体
            for (int i = 0; i < NP; i++) {
                double r = Math.random();
                int index = 0;
                for (int k = 0; k < NP; k++) {
                    if (r < addSumP[k]) {
                        index = k;
                        break;//选择了一个个体下标是index
                    }
                }
                select_population[i] = init_population[index];//选择之后的种群
            }

            //3.交叉
            for (int i = 0; i < NP; i++) {
                double cr = Math.random();
                if (cr < CR) {//交叉
                    //与哪个个体交叉,随机生成一个个体
                    int indiv = random.nextInt(10);
                    //从那个位置交叉,随机生成一个位置
                    int index = random.nextInt(SIZE);
                    for (int j = 0; j < SIZE; j++) {
                        if (j == index) {//发生交叉的片段
                            cr_population[i][j] = select_population[indiv][j];
                        } else { //不发生交叉的片段
                            cr_population[i][j] = select_population[i][j];
                        }
                    }
                } else {//不交叉
                    for (int j = 0; j < SIZE; j++) {
                        cr_population[i][j] = select_population[i][j];
                    }
                }
            }

            //4.变异
            for (int i = 0; i < NP; i++) {
                double mu = Math.random();
                if (mu < MU) {//变异
                    //在那个位置变异
                    int index = random.nextInt(SIZE);
                    for (int j = 0; j < SIZE; j++) {
                        if (j == index) {
                            mu_population[i][j] = mu_population[i][j] - random.nextDouble();
                        } else {
                            mu_population[i][j] = cr_population[i][j];
                        }
                    }
                } else {//不变异
                    for (int j = 0; j < SIZE; j++) {
                        mu_population[i][j] = select_population[i][j];
                    }
                }
            }

            //5.当前最优解
            for (int i = 0; i < NP; i++) {
                best_Y = fitness(mu_population[i], N);
                if (best_Y > fitness(mu_population[i], N)) {
                    best_Y = fitness(mu_population[i], N);
                }
            }
            best[G] = best_Y;
            System.out.println("第" + (G + 1) + "代,最大适应度为:" + best_Y);

            //6.保留优质个体
            for (int i = 0; i < NP; i++) {
                if (fitness(init_population[i], N) > fitness(mu_population[i], N)) {
                    for (int j = 0; j < SIZE; j++) {
                        init_population[i][j] = mu_population[i][j];
                    }
                }
            }
        }//迭代结束

        //7.打印结果
        System.out.println("最优解为:");
        Best(best);

        //结束时间
        long endTime = System.currentTimeMillis();
        System.out.println("程序运行时间: " + (endTime - startTime) + "ms");
    }

    //打印最优解
    public static void Best(double[] best) {
        double a = 65535;
        int temp = 0;
        for (int i = 0; i < best.length; i++) {
            if (best[i] < a) {
                a = best[i];
                temp = i;
            }
        }
        System.out.println("最优解:" + a + "第一次出现代数: " + (temp + 1));
    }

    //计算适应度,函数式的解
    public static double fitness(double[] individual, int N) {
        double f = 0;
        for (int i = 0; i < N; i++) {
            f += individual[i] * individual[i];
        }
        return f;
    }

}

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值