差分算法

算法描述:

根据某种规则随机产生初始化种群,根据变异规则产生变异后的种群,根据交叉规则产生交叉后的种群,然后执行选择函数,对交叉变异后的种群和原种群进行比较选择。对择优后的种群进行排序,选出Top N条种群向量。

算法参数:

种群大小、迭代次数、变异权值、交叉率、种群向量值范围

遗传算法&差分算法(个人理解):

1:遗传算法交叉后即择优,变异后即择优;差分算法交叉变异操作后择优一次。

2:遗传算法需要对种群进行初始编码;差分算法根据规则初始化种群。

3:都可以进行设定参数范围和停止准则

4:都属于种群进化算法

遗传算法示例(C++实现):

https://github.com/Consck/genetic-algorithm

代码示例:

import java.util.*;

/**
 * There steps in differential evolution:
 * 		1. mutation
 * 		2. cross
 * 		3. selection
 *  差分算法代码示例
 * @author JunH (email: junh_cs@126.com)
 *
 */
public class DifferentialEvolution4SeachParam {
    private int population_size;
    private int iter_num;
    private int param_num;
    private double param_bottom_bound;
    private double param_upper_bound;
    private double F = 0.5; 		// mutation factor [0, 1], range from 0 to 1
    private double CR = 0.5; 		// cross rate (0, 1)

    // tmp
    private double[][] population;
    private double[] scores;
    private Random rand;

    // output
    private double[] final_individual;

    public static void main(String[] args) {
        DifferentialEvolution4SeachParam de = new DifferentialEvolution4SeachParam(10, 500, 5, -1, 1);
        double[] params = de.getTheFinalParams();

        System.out.println();
        for (int j = 0; j < params.length-1; j++)
            System.out.print(params[j]+", ");
        System.out.println(params[params.length-1]+")");
        System.out.println("HAVE A GOOD DAY!");
    }

    public DifferentialEvolution4SeachParam(int population_size, int iter_num,
                                            int param_num, double param_bottom_bound, double param_upper_bound){
        this.population_size = population_size;
        this.iter_num = iter_num;
        this.param_num = param_num;
        this.param_bottom_bound = param_bottom_bound;
        this.param_upper_bound = param_upper_bound;

        final_individual = run();
    }

    public double[] getTheFinalParams(){
        return final_individual;
    }

    private double[] run(){
        this.init();

        double[] final_best_individual = null;
        /**
         * 共迭代iter_num次,择优选择
         */
        for (int iter = 0; iter < iter_num; iter++){
            double[][] mutated_population = this.mutate(); //获得变异后的种群
            double[][] crossed_population = this.cross(mutated_population); //在变异后的种群基础上进行交叉操作
            this.select(crossed_population); //对变异 交叉后的种群进行择优
            //根据适应度值对种群向量进行排序,返回适应度值最大的向量编号。若sortTopN设定为2,则返回适应度值最大的前两个向量编号
            int[] index = insertDescendSortIndex(scores, 1);
            //打印log
            StringBuffer sb = new StringBuffer();
            sb.append("The "+(iter+1)+"-th iter's score is "+scores[index[0]]+" (");
            for (int j = 0; j < param_num-1; j++)
                sb.append(this.population[index[0]][j]+", ");
            sb.append(this.population[index[0]][param_num-1]+")");

            System.out.println(sb.toString());
            //保存适应度函数值最大的向量
            final_best_individual = this.population[index[0]];
        }

        return final_best_individual;
    }

    private int[] insertDescendSortIndex(final double[] arr, int sortTopN){
        int[] indexes = new int[arr.length];
        //初始化数组
        for (int i = 0; i < indexes.length; i++)
            indexes[i] = i;
        //根据适应度值进行排序,indexes存储种群向量编号
        for (int i = 1; i < indexes.length; i++){
            for (int j = 0; j < i && j < sortTopN; j++){
                if (arr[indexes[i]] > arr[indexes[j]]){
                    int tmp = indexes[i];
                    indexes[i] = indexes[j];
                    indexes[j] = tmp;
                }
            }
        }
        //根据需要返回适应度排名前N个种群向量编号
        if (indexes.length > sortTopN){
            int[] ans = new int[sortTopN];
            for (int i = 0; i < sortTopN; i++){
                ans[i] = indexes[i];
            }

            return ans;
        }

        return indexes;
    }

    /**
     * 迭代前的种群初始化
     */
    private void init(){
        rand = new Random(new Date().getTime());

        population = new double[population_size][param_num];
        scores = new double[population_size];
        for (int i = 0; i < population_size; i++){
            for (int j = 0; j < param_num; j++){
                //初始化规则
                population[i][j] = param_bottom_bound + rand.nextDouble() * (param_upper_bound - param_bottom_bound);
            }
            //计算初始化种群的向量适应度
            scores[i] = scorefunc(population[i]);
        }
    }

    private double[][] mutate(){
        double[][] mutated_population = new double[population_size][param_num];
        for (int i = 0; i < population_size; i++){ //变异后种群大小不变
            /**
             * 随机产生3个不超过10的变量,作为变异随机选择的个体向量
             */
            int ind1 = rand.nextInt(population_size);
            int ind2 = rand.nextInt(population_size);
            int ind3 = rand.nextInt(population_size);
            /**
             * 3条不同的种群个体向量,且不是当前向量
             */
            while (ind1 == i || ind2 == i || ind3 == i
                    || ind1 == ind2 || ind1 == ind3 || ind2 == ind3){
                ind1 = rand.nextInt(population_size);
                ind2 = rand.nextInt(population_size);
                ind3 = rand.nextInt(population_size);
            }
            /**
             * 变异规则:随机选择两个不同的个体向量相减产生差分向量,将差分向量赋予权值后与第三个随机选择的个体向量相加,产生变异向量
             */
            for (int j = 0; j < param_num; j++){
                mutated_population[i][j] = population[ind1][j] + F * (population[ind2][j] - population[ind3][j]);
            }
        }
        //返回变异后的种群
        return mutated_population;
    }

    private double[][] cross(double[][] mutated_population){
        double[][] crossed_population = new double[population_size][param_num];
        for (int i = 0; i < population_size; i++){  //交叉后种群大小不变
            int Jrand = rand.nextInt(param_num); //随机选择向量中的某个固定位置
            for (int j = 0; j < param_num; j++){
                /**
                 * 交叉规则:如果当前向量j为产生的固定位置或随机变量小于初始化设定的交叉率,则交叉后向量值取变异操作后的向量值;
                 *         否则,交叉后向量值取原种群中的向量值,即不交叉
                 */
                if (j == Jrand || rand.nextDouble() < CR)
                    crossed_population[i][j] = mutated_population[i][j];
                else crossed_population[i][j] = population[i][j];
                /**
                 * 对交叉后的值进行判断,若超出设定的范围,则重新初始化
                 */
                if (crossed_population[i][j] > this.param_upper_bound
                        || crossed_population[i][j] < this.param_bottom_bound){
                    crossed_population[i][j] = param_bottom_bound + rand.nextDouble() * (param_upper_bound - param_bottom_bound);
                }
            }
        }

        return crossed_population;
    }

    private void select(double[][] crossed_population){
        for (int i = 0; i < population_size; i++){
            //计算当前向量适应度
            double new_sco = scorefunc(crossed_population[i]);
            /**
             * 若交叉变异后的向量适应度大于原种群向量适应度,则替换
             */
            if (new_sco > scores[i]){
                population[i] = crossed_population[i];
                scores[i] = new_sco;
            }
        }
    }

    /**
     * 适应度计算规则:向量值相加结果即为当前向量适应度值
     * @param individual
     * @return
     */
    private double scorefunc(double[] individual){	// TODO the higher, the better.
        double sco = 0.0;
        for (int i = 0; i < param_num; i++)
            sco += individual[i];

        return sco;
    }
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值