【Jaya算法解决柔性作业车间调度问题(附代码)】

前言

本文的内容为作者摘自自己以前写的论文,希望能为大家的论文写作带来一点帮助,哪怕只是一点点。
由于距离写作时间较长,另外作者自身水平有限,不到之处,还请海涵。
最后,祝大家牛逼。

生产调度问题概述

排产问题又称为调度问题,指在满足一定约束的条件下,基于某个或多个优化指标,为多个生产任务分配生产资源的过程,生产资源通常有机器、工人等。生产调度问题是一种复杂的组合优化问题,由于其在生产中的重要意义。生产调度问题有多种类型,不同的类型对应了不同的生产环境及要求。

单机调度问题

单机调度问题(Single Machine Scheduling Problem, SMP)指的是生产过程中只有一台机器,待加工的工件有且仅有一道工序,所有工件都在该机床上进行加工,这一类调度问题对生产车间中出现瓶颈机床的情况具有重要的参照意义。

并行机调度问题

并行机调度问题(Parallel Machine Scheduling Problem, PMP),与SMP不同的是,PMP中的拥有多台设备且完全相同,工件可以选择在任意一台机床上进行加工。

开放车间调度问题

开放车间调度问题(Open Shop Scheduling Problem, OSP)可以描述为有一组n个作业必须在一组m台机器上进行处理。每个作业由m个操作组成,每个操作都必须在给定的时间内在不同的机器上进行,OSP最大的特点是加工系统中每个工件的加工工艺顺序是任意的,没有工序上先后关系的约束。

流水车间调度问题

流水车间调度问题(Flow Shop Scheduling Problem, FSP)。FSP描述为一系列不同的设备组成流水线,待加工的工件包含多道工序,每道工序在一台设备上加工,所有工件的加工路线都是相同的,每个工件工序之间有先后顺序约束。

作业车间调度问题

作业车间调度问题(Job Shop Scheduling Problem, JSP),JSP是针对某一可分解的多工序的任务(如产品制造、加工等),在尽可能满足其约束条件的前提下,对该任务的工序安排资源、操作时间和操作顺序,并对某一目标进行优化。JSP通常描述为有n个工艺不同的工件,每个工件按照其工艺路线在m台机器上进行加工,求每个机器上进行的工艺序列。

柔性作业车间调度问题

柔性作业车间调度问题(Flexible Job Shop Scheduling Problem, FJSP)是JSP的一个推广,被加工工件的工序可以选择在一组机器中的任意一台机器上加工。基于生产过程中的柔性和生产能力的考虑,FJSP在某些生产实际中更能反映生产状况。

Jaya算法

传统Jaya算法

针对有约束和无约束优化问题,Rao[80]提出了一种简单而强大的优化算法——Jaya算法。该算法的主要思想是,给定问题的解决方案应该朝着最佳解决方案移动,并且应该远离最坏的解决方案。该算法只需要通用的控制参数,不需要任何特定于算法的控制参数,Jaya算法是一种简单的优化算法。Jaya算法的核心是其迭代进化公式,
X j , k , i + 1 ′ = X j , k , i + r 1 , j , i ( X j , b e s t , i − ∣ X j , k , i ∣ ) − r 2 , j , i ( X j , w o r s t , i − ∣ X j , k , i ∣ ) X'_{j,k,i+1} = X_{j,k,i} + r_{1,j,i}(X_{j,best,i} - |X_{j,k,i}|) - r_{2,j,i}(X_{j,worst,i} - |X_{j,k,i}|) Xj,k,i+1=Xj,k,i+r1,j,i(Xj,best,iXj,k,i)r2,j,i(Xj,worst,iXj,k,i)
式中, i i i表示迭代次数, k k k表示种群中的个体, j j j表示个体中的第 j j j维变量。 X j , k , i X_{j,k,i} Xj,k,i是第 i i i代个体 k k k中变量 j j j的值, X j , k , i + 1 ′ X_{j,k,i+1}' Xj,k,i+1是其更新后的值, X j , b e s t , i X_{j,best,i} Xj,best,i是第 i i i代最优的个体中变量 j j j的值, X j , w o r s t , i X_{j,worst,i} Xj,worst,i 第 i 第i i代最劣个体中变量 j j j的值, r 1 , j , i r_{1,j,i} r1,j,i r 2 , j , i r_{2,j,i} r2,j,i为两个在 [ 0 , 1 ] [0,1] [0,1]范围内的随机数。式中 r 1 , j , i ( X j , b e s t , i − ∣ X j , k , i ∣ ) r_{1,j,i}(X_{j,best,i} - |X_{j,k,i}|) r1,j,i(Xj,best,iXj,k,i)表示个体趋向于最优个体,而 − r 2 , j , i ( X j , w o r s t , i − ∣ X j , k , i ∣ ) -r_{2,j,i}(X_{j,worst,i} - |X_{j,k,i}|) r2,j,i(Xj,worst,iXj,k,i)则表示个体具有原理最劣个体的趋势。如果 X j , k , i ′ X_{j,k,i}' Xj,k,i优于 X j , k , i X_{j,k,i} Xj,k,i,则替换 X j , k , i X_{j,k,i} Xj,k,i,否则不变。

传统Jaya算法的执行流程如下图所示,
在这里插入图片描述

该算法是一种比较简单的群进化算法,且该算法是应用于连续函数进行优化的。其优点之一是没有任何特定于算法的参数,这些参数会对结果解产生影响,因此,无需额外的计算工作来调整参数以获得最优解。另外一个优点是算法过程简单,群进化算法的核心基本都是种群进化机制,而Jaya算法的进化机制简单明了,通常来说,简单的进化过程会导致更快的求解速度。这些优点使得Jaya算法比其他启发式算法更容易理解和实现。但是其缺点也不难发现,该算法只能应用于连续函数优化问题,因此,要将Jaya算法应用于柔性作业车间调度问题,需要设计针对离散问题的解的表示方法和种群进化机制。

改进的Jaya算法

针对上文指出的Jaya算法在解决柔性作业车间调度问题中的不足,接下来对算法进行改进来求解柔性作业车间调度问题。

编码与解码

基于遗传算法的设计思想,将问题解空间中的解进行编码,编码后的解称为个体,将个体还原为解的过程称为解码。
介绍一种两段式编码方法,如下图所示
在这里插入图片描述
该染色体由机器选择部分和工序排序部分两段组成,工序排序部分编码同基于工序的编码。在机器选择部分编码中,如第一个基因“2”,表示工序 p 11 p_{11} p11选择其对应的机器中的第二台,第五个基因“1”,表示工序 p 22 p_{22} p22所选择的机器,该工序可选择的机器有两台,在该调度方案中选择了其中的第一台。

种群初始化

由于采用了两段式的编码方案,因此初始化时也需要考虑染色体两部分的初始化。对于机器选择部分,采用启发式机器选择和随机生成的初始化方式,对于工序排序部分,仅采用随机生成的方式。

对于机器选择部分,如图下图所示,利用启发式机器选择方法生成初始化机器选择部分染色体的步骤为:
步骤1 生成一个数组,称为机器时间数组,数组长度等于机器数量,数组的索引(从1开始)对应着机器的顺序编号,数组中的值表示对应机器的负载,将数组所有的值设置为0;
步骤2 随机选择一个工件,并将其第一道工序设置为当前工序;
步骤3 列出当前工序的可选择机器及对应机器的加工时间,将加工时间与机器时间数组中对应的数相加,并从中选择最小的加工时间及对应的机器,此处表示该工序选择该机器进行加工,并更新加工时间数组,同时,对机器选择部分染色体进行编码。
在这里插入图片描述
随机初始化的目的是保证初始化种群的多样性,使初始化解更均匀地分布在解空间中,其执行步骤为:
步骤1 选取第一个工件的第一个工序作为当前工序;
步骤2 从当前工序对应可选择的加工机器中任选一个机器,将其编号(表示该机器在可选机器中的编号)填入机器选择部分编码的相应基因位置。从第一个工件的第一个工序到该工件的最后一个工序,从第一个工件到最后一个工件,重复执行上述步骤,直到机器选择编码全部被填充。
对于两个初始化种群方法的混合使用策略,可以采用启发式方法生成种群数量20%的个体,其余个体均由随机方法生成。
对于工序排序部分,仅采用随机生成的方式,该方式执行步骤如下。
步骤1 首先生成一个长度等于所有工序数量的数组,
步骤2 对于第一个工件的第一个工序,取工件编号——数字“1”,在数组没有被填充的位置中随机选择一个位置,将该数字填入该位置,
对于所有工件的所有工序,都执行步骤2,即可得到随机初始化的工序排序部分的染色体。

种群进化机制

机器选择部分是工序对机器的选择,每个基因位对应的工序是固定的。根据趋利避害的思想,每个个体中工序对机器的选择趋向于与最优个体相同,且与最劣个体不同,根据这一思想,机器选择部分进化机制的执行步骤如下。
步骤1 找出当前个体和最劣个体机器选择编码部分编码值相同的码位,并清空该码位上的编码
步骤2 对于当前个体机器选择编码为空的码位,将最优个体相同码位上的编码复制到空码位中。如下图所示
在这里插入图片描述
工序排序部分的重点是工序的排列顺序,其思想是当前个体尽可能保证与最优个体工序排序的相似而避免与最劣个体工序排序的相似,如下图所示,该部分进化机制的执行步骤如下。
步骤1 标记当前个体 x x x与最劣个体 w o r s t worst worst工序排序编码中相同的码位,并且将 x x x中其它码位的编码复制到 x 1 x_1 x1中。
步骤2 从最优个体 b e s t best best工序排序编码中从头开始找与 x 1 x_1 x1中编码相同的码位,进行标记,将其它码位的编码复制到 b e s t 1 best_1 best1中。
步骤3 将 x 1 x_1 x1的编码复制到 x 2 x_2 x2中,将 b e s t 1 best_1 best1中非空码位的编码依次填入 x 2 x_2 x2中空码位处,得到 x 2 x_2 x2即为进化后的个体。
在这里插入图片描述

Pareto非支配排序和拥挤距离

在Jaya算法中,个体评估用于种群中最优、最劣个体的确定和进化前后个体的可接受准则。由于所研究的问题是多目标的,而且多个目标之间往往具有互斥性,即一个目标的优化会导致其它目标的恶化,因此无法简单的根据某一个目标值的大小来评估个体的好坏。接下来介绍Pareto非支配排序来解决多目标的问题。
在使用Pareto非支配排序之前,首先需要了解Pareto支配的定义。以最小化目标值为优化目标,Pareto支配关系是指对于多个目标 f i ( x ) , i = 1 , 2 , . . . , n f_{i}(x), i=1, 2, ... , n fi(x),i=1,2,...,n,任意两个自变量 x 1 , x 2 x_1, x_2 x1,x2,满足以下两个条件,
条件1 ,对于所有 i = 1 , 2 , . . . , n , f i ( x 1 ) ≤ f i ( x 2 ) i = 1, 2,..., n, f_i(x_1)\le f_i(x_2) i=1,2,...,n,fi(x1)fi(x2)
条件2 ,存在 i = 1 , 2 , . . . , n , f i ( x 1 ) < f i ( x 2 ) i = 1, 2,..., n, f_i(x_1) < f_i(x_2) i=1,2,...,n,fi(x1)<fi(x2)
则可以说 x 1 x_1 x1支配 x 2 x_2 x2。对于自变量 x x x,当解空间中没有其它自变量可以支配 x x x,则称 x x x为Pareto最优解,也叫非支配解。
非支配排序对一组解按照优劣程度进行分层。其思想为,定义一个解的集合 X X X,对于其中每一个解,如果满足所有其它解都无法支配该解,则将该解划分入第一层,划分入这一层的解从 X X X中移除,然后对其余解也执行此操作划分入下一层,不断分层直到 X X X中没有解。这样,就对一组解进行了分层,第一层中的解是最优的,最后一层中的解是最劣的。这种方法的算法复杂度较高,感兴趣的可以了解一下Pareto快速非支配排序方法,原理是相同的,只不过对算法进行了改进。
快速非支配排序方法可以将种群中的个体按照支配关系分层,可以认为,第一层中的个体为整个种群的非支配解,为整个种群的最优群体,最后一层中的个体则是最劣个体。每一层都可能会有多个个体,并且可以认为这些个体在考虑各调度目标的情况下是同等优劣的,然而,Jaya算法中需要获得种群中的最优解和最劣解来进行后续的进化操作,需要的是单个解而不是多个解,因此需要再对每一层的个体进行评估和比较。
出于对种群多样性和搜索效率的考虑,本文采用拥挤距离来比较同一层级个体的好坏。拥挤距离反映一个解在解空间中的拥挤程度,一个解的拥挤距离越大,表示其周围的解分布越稀疏。
f m f_m fm为第 m m m个目标,拥挤距离的计算步骤如下
步骤1 对同一层级的个体按照目标 f m f_m fm排列,其中第一个和最后一个个体的拥挤距离均为无限大。
步骤2 对于个体 x i x_i xi的拥挤距离 d i d_i di d i = f m ( i + 1 ) − f m ( i − 1 ) f m m a x − f m m i n d_i = \frac{f_m(i+1)-f_m(i-1)}{f_m^{max} - f_m^{min}} di=fmmaxfmminfm(i+1)fm(i1),其中 f m ( i + 1 ) f_m(i+1) fm(i+1),为种群按第 m m m个目标值排序后第 i + 1 i+1 i+1个个体关于该目标的目标值,同理, f m ( i − 1 ) f_m(i-1) fm(i1)为种群按第 m m m个目标值排序后第 i − 1 i-1 i1个个体关于该目标的目标值, f m m a x f_m^{max} fmmax为当前种群中的个体在第 m m m个目标上的最优值, f m m i n f_m^{min} fmmin为当前种群中的个体在第 m m m个目标上的最劣值。 f m m a x − f m m i n f_m^{max}-f_m^{min} fmmaxfmmin的目的是对数值进行归一化处理。
步骤3 对所有目标进行步骤2的操作,每个个体将会得到 m m m d i d_i di,将每个个体的 m m m d i d_i di相加,就可以得到每个个体的拥挤距离。

接受准则

接受准则用于个体进化前后的取舍,这里用一个简单的方法,如果进化后的个体可以支配进化前的个体,则采用进化后的个体,舍弃原个体,否则不进行操作。

终止条件

以种群进化迭代次数为终止条件。

算法代码

采用Java语言实现上述设计的算法。

个体类

public class Individual {

    private int[] machineCode;
    private int[] processCode;
    private int codeLength;


    private int[][] processTime;
    private int[][][] processDetailTime;
    private int[] machineTime;

    private RawData rawData;

    private int[] processNum;


    private int finishTime = -1;
    private int freeTime = 0;



    /**
     * 构造函数,同时完成各个字段以及个体基因序列的初始化
     * @param rawData
     */
    public Individual(RawData rawData){
        this.rawData = rawData;
        this.codeLength = this.rawData.getTotalProcessNum();
        this.machineCode = new int[this.codeLength];
        this.processCode = new int[this.codeLength];
        this.processTime = new int[this.rawData.getJobNum()][];
        this.processDetailTime = new int[this.rawData.getJobNum()][][];
        this.machineTime = new int[this.rawData.getMachineNum()];
        this.processNum = new int[rawData.getJobNum()];
        // 初始化基因序列
        processCodeInit();
        machineCodeInit();
        arrInit();
        fillTime();
    }

    /**
     * 构造函数
     * @param machineCode
     * @param processCode
     */
    public Individual(int[] machineCode, int[] processCode, RawData rawData){
        this.rawData = rawData;
        this.codeLength = this.rawData.getTotalProcessNum();
        this.processTime = new int[this.rawData.getJobNum()][];
        this.processDetailTime = new int[this.rawData.getJobNum()][][];
        this.machineTime = new int[this.rawData.getMachineNum()];
        this.processNum = new int[this.rawData.getJobNum()];
        this.machineCode = machineCode;
        this.processCode = processCode;
        arrInit();
        fillTime();
    }

    public int getCodeLength() {
        return codeLength;
    }

    public RawData getRawData() {
        return rawData;
    }

    public int getFreeTime() {
        return freeTime;
    }

    public int getFinishTime() {
        if(this.finishTime==-1){
            setFinishTime();
        }
        return this.finishTime;
    }

    private void setFinishTime() {
        int max = this.machineTime[0];
        for (int i : machineTime) {
            max = i>max?i:max;
        }
        this.finishTime = max;
    }

    public int[] getMachineCode() {
        return machineCode;
    }

    public int[] getProcessCode() {
        return processCode;
    }

    public void setMachineCode(int[] machineCode) {
        this.machineCode = machineCode;
    }

    public void setProcessCode(int[] processCode) {
        this.processCode = processCode;
    }

    public void setGene(int type, int offset, int gene){
        if(type == 0){
            this.machineCode[offset] = gene;
        }
        if(type == 1){
            this.processCode[offset] = gene;
        }
    }

    public int getGene(int type, int offset){
        if(type == 0) return this.machineCode[offset];
        if(type == 1) return this.processCode[offset];
        return -1;
    }
    /**
     * 支配关系判断
     * @param individual
     * @return
     */
    public boolean dominate(Individual individual){
        return (this.getFinishTime()<= individual.getFinishTime() && this.getFreeTime()<=individual.getFreeTime())
                && ((this.getFinishTime()!= individual.getFinishTime()) || (this.getFreeTime()!=individual.getFreeTime()));
    }
    /**
     * 填充机器时间和工序时间两个数组
     */
    private void fillTime(){
        int[][][][] data = this.rawData.getData();
        int[][] machineCode1 = convertMachineCode();
        int[] processAdjust = new int[machineCode1.length];

        for (int i = 0; i < this.processCode.length; i++) {
            int job = this.processCode[i]-1;//工件号,下标0开始 2
            int process = processAdjust[job]++;//第几道工序,下标0开始 0
            int machine = data[job][process][machineCode1[job][process]-1][0]-1; //机器编号 下标从0开始 1
            int doTime = data[job][process][machineCode1[job][process]-1][1]; // 该工序的加工时间 6

            int[] ints = new int[3];// 0表示当前工序的开始时间,1表示当前工序的结束时间,2表示机器选择
            ints[2] = machine+1;
            if(process==0){
                // 无工序紧前的关系,直接考虑当前机器
                ints[0] = this.machineTime[machine];  this.machineTime[machine] += doTime;
                ints[1] = this.machineTime[machine];
                this.processTime[job][process] = this.machineTime[machine];
                this.processDetailTime[job][process] = ints;
            }else{
                int rightTime = Math.max(this.machineTime[machine],this.processTime[job][process-1]);
                ints[0] = rightTime;
                this.freeTime += this.machineTime[machine]<this.processTime[job][process-1]?
                        (this.processTime[job][process-1]-this.machineTime[machine]) :0;

                this.machineTime[machine] =rightTime+doTime;
                ints[1] = this.machineTime[machine];
                this.processTime[job][process] = this.machineTime[machine];
                this.processDetailTime[job][process] = ints;
            }
        }
        int ft = getFinishTime();
        for (int i = 0; i < machineTime.length; i++) {
            this.freeTime += ft-machineTime[i];
        }
    }

    /**
     * 将机器码转换为二维形式,方便解码
     * @return
     */
    private int[][] convertMachineCode(){
        int[][] res = new int[this.rawData.getJobNum()][];

        for(int i=0;i<res.length;i++){
            res[i] = new int[this.processNum[i]];
        }
        int index1 = 0;
        int index2 = 0;
        for (int i = 0; i < this.machineCode.length; i++) {
            res[index1][index2] = this.machineCode[i];
            index2++;
            if(index2>=this.processNum[index1]){
                index1++;
                index2 = 0;
            }
        }
        return res;
    }

    /**
     * 机器编码初始化,包含启发式初始化(20%概率)和随机初始化(80概率)
     */
    private void machineCodeInit(){
        int[][][][] data = this.rawData.getData();
        int[] genes = new int[this.codeLength];
        double pointer = Math.random();
        Random rnd = new Random();
        int index = 0;
        if(pointer<0.2){
            // 启发式方法
            int[] machineTime = new int[this.rawData.getMachineNum()];
            for(int i= 1;i<=this.rawData.getJobNum();i++){
                for(int j=0;j<data[i-1].length;j++){
                    int[] t = new int[this.rawData.getMachineNum()];
                    int[][] optionalMachine = data[i-1][j];
                    for (int i1 = 0; i1 < optionalMachine.length; i1++) {
                        t[optionalMachine[i1][0]-1] = machineTime[optionalMachine[i1][0]-1]+optionalMachine[i1][1];

                    }

                    int minIndex = 0;
                    for(int a = 0;a<t.length;a++){
                        if(t[a]!=0){
                            if(t[minIndex]==0) {
                                minIndex = a;
                                continue;
                            }
                            minIndex = t[minIndex]<=t[a]?minIndex:a;
                        }
                    }

                    machineTime[minIndex] = t[minIndex];
                    int gene = 0;
                    for(int a=0;a< optionalMachine.length;a++){
                        if(optionalMachine[a][0]==minIndex+1){
                            gene = a+1;
                            break;
                        }
                    }
                    genes[index] = gene;
                    index++;
                }
            }
        }else{
            // 随机方法
            for(int i= 1;i<=this.rawData.getJobNum();i++){
                for(int j=0;j<data[i-1].length;j++){
                    //genes[index] = rnd.nextInt(optionalMachine[i-1][j].length+1);
                    genes[index] = rnd.nextInt(data[i-1][j].length)+1;
                    index++;
                }
            }
        }
        this.machineCode = genes;
    }

    /**
     * 工序编码初始化,采用随机方法
     */
    private void processCodeInit(){
        int length = this.codeLength;
        int[] genes = new int[length];
        Random rnd = new Random();
        int[] indexes = new int[length];

        for(int i=0;i<length;i++){
            indexes[i] = i;
        }

        int right = length;
        for(int i=1;i<=this.rawData.getJobNum();i++){
            for(int j=0;j<this.rawData.getData()[i-1].length;j++){
                int rndIndex = rnd.nextInt(right);
                genes[indexes[rndIndex]] = i;

                int t = indexes[right-1];
                indexes[right-1] = indexes[rndIndex];
                indexes[rndIndex] = t;
                right--;
            }
        }
        this.processCode = genes;
    }

    /**
     * 初始化几个数组,防止出现空指针
     */
    private void arrInit(){
        for (int i = 0; i < this.rawData.getJobNum(); i++) {
            this.processNum[i] = this.rawData.getData()[i].length;// 填充工序数量的数组,主要是为解码做准备
            this.processTime[i] = new int[this.rawData.getData()[i].length];// 初始化数组
            this.processDetailTime[i] = new int[this.rawData.getData()[i].length][];
        }
    }

    @Override
    public String toString() {
        return "Individual{machineCode="+Arrays.toString(this.machineCode)+";processCode="+Arrays.toString(this.processCode)+"}";
    }

    public void printDetailTime(){
        int[][][] detailTime = this.processDetailTime;

        for (int i = 0; i < detailTime.length; i++) {
            System.out.println("=========================");
            System.out.println("第"+(i+1)+"个工件");
            for (int j = 0; j < detailTime[i].length; j++) {
                System.out.println("第"+(j+1)+"个工序:开始时间为"+detailTime[i][j][0]
                        +";结束时间为"+detailTime[i][j][1]+";选择的机器为"+detailTime[i][j][2]);
            }
        }
    }

    public int[][][] decode(){
        return this.processDetailTime;
    }
}

种群类

public class Population {

    private Individual[] population;

    private Individual best;
    private Individual worst;

    public Individual getBest() {
        return this.best;
    }

    private void setBest() {
        this.best = this.getFittest(0);
    }

    public void setBest1(Individual best){
        this.best = best;
    }

    public Individual getWorst() {
        return this.worst;
    }

    private void setWorst() {
        this.worst = this.getFittest(this.size()-1);
    }

    public void setWorst1(Individual worst){
        this.worst = worst;
    }

    public Individual[] getIndividuals(){
        return this.population;
    }

    public void setIndividual(int offset, Individual individual){
        this.population[offset] = individual;
    }

    public Individual getIndividual(int offset){
        return this.population[offset];
    }

    public Population(int popNum){
        population = new Individual[popNum];
    }

    public Population(RawData rawData, int popNum){
        this(popNum);
        for (int i = 0; i < popNum; i++) {
            population[i] = new Individual(rawData);
        }
    }

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

    public Individual getFittest(int offset){
        Arrays.sort(this.population, (o1, o2) -> o1.getFinishTime()-o2.getFinishTime());
        return this.population[offset];
    }
}

数据类

public class RawData {
    private int[][][][] data;
    private int jobNum;
    private int totalProcessNum;
    private int machineNum;

    public static final int[][][][] INSTANCE8= new int[][][][]{
            {{{1,5},{2,3},{3,5},{4,3},{5,3},{7,10},{8,9}},{{1,10},{3,5},{4,8},{5,3},{6,9},{7,9},{8,6}},{{2,10},{4,5},{5,6},{6,2},{7,4},{8,5}}},
            {{{1,5},{2,7},{3,3},{4,9},{5,8},{7,9}},{{2,8},{3,5},{4,2},{5,6},{6,7},{7,10},{8,9}},{{2,10},{4,5},{5,6},{6,4},{7,1},{8,7}},{{1,10},{2,8},{3,9},{4,6},{5,4},{6,7}}},
            {{{1,10},{4,7},{5,6},{6,5},{7,2},{8,4}},{{2,10},{3,6},{4,4},{5,8},{6,9},{7,10}},{{1,1},{2,4},{3,5},{4,6},{6,10},{8,7}}},
            {{{1,3},{2,1},{3,6},{4,5},{5,9},{6,7},{7,8},{8,4}},{{1,12},{2,11},{3,7},{4,8},{5,10},{6,5},{7,6},{8,9}},{{1,4},{2,3},{3,2},{4,10},{5,3},{6,9},{7,5},{8,7}}},
            {{{1,3},{2,6},{3,7},{4,8},{5,9},{7,10}},{{1,10},{3,7},{4,4},{5,9},{6,8},{7,6}},{{2,9},{3,8},{4,7},{5,4},{6,2},{7,7}},{{1,11},{2,9},{4,6},{5,7},{6,5},{7,3},{8,6}}},
            {{{1,6},{2,7},{3,1},{4,4},{5,6},{6,9},{8,10}},{{1,11},{3,9},{4,9},{5,9},{6,7},{7,8},{8,4}},{{1,10},{2,5},{3,9},{4,10},{5,11},{7,10}}},
            {{{1,5},{2,4},{3,2},{4,6},{5,7},{7,10}},{{2,9},{4,9},{5,11},{6,9},{7,10},{8,5}},{{2,8},{3,9},{4,3},{5,8},{6,6},{8,10}}},
            {{{1,2},{2,8},{3,5},{4,9},{6,4},{8,10}},{{1,7},{2,4},{3,7},{4,8},{5,9},{7,10}},{{1,9},{2,9},{4,8},{5,5},{6,6},{7,7},{8,1}},{{1,9},{3,3},{4,7},{5,1},{6,5},{7,8}}}
    };

    public static final int INSTANCE8_MACHINE_NUM = 8;

    public static final int[][][][] INSTANCE10 = new int[][][][]{
            {{{1,1},{2,4},{3,6},{4,9},{5,3},{6,5},{7,2},{8,8},{9,9},{10,5}},{{1,4},{2,1},{3,1},{4,3},{5,4},{6,8},{7,10},{8,6},{9,11},{10,4}},{{1,3},{2,2},{3,5},{4,1},{5,5},{6,6},{7,9},{8,5},{9,10},{10,3}}},
            {{{1,2},{2,10},{3,4},{4,5},{5,9},{6,8},{7,4},{8,15},{9,8},{10,4},},{{1,4},{2,8},{3,7},{4,1},{5,9},{6,6},{7,1},{8,10},{9,7},{10,1}},{{1,6},{2,11},{3,2},{4,7},{5,5},{6,3},{7,5},{8,14},{9,9},{10,2}}},
            {{{1,8},{2,5},{3,8},{4,9},{5,4},{6,3},{7,5},{8,3},{9,8},{10,1}},{{1,9},{2,3},{3,6},{4,1},{5,2},{6,6},{7,4},{8,1},{9,7},{10,2}},{{1,7},{2,1},{3,8},{4,5},{5,4},{6,9},{7,1},{8,2},{9,3},{10,4}}},
            {{{1,5},{2,10},{3,6},{4,4},{5,9},{6,5},{7,1},{8,7},{9,1},{10,6}},{{1,4},{2,2},{3,3},{4,8},{5,7},{6,4},{7,6},{8,9},{9,8},{10,4}},{{1,7},{2,3},{3,12},{4,1},{5,6},{6,5},{7,8},{8,3},{9,5},{10,2}}},
            {{{1,7},{2,10},{3,4},{4,5},{5,6},{6,3},{7,5},{8,15},{9,2},{10,6}},{{1,5},{2,6},{3,3},{4,9},{5,8},{6,2},{7,8},{8,6},{9,1},{10,7}},{{1,6},{2,1},{3,4},{4,1},{5,10},{6,4},{7,3},{8,11},{9,13},{10,9}}},
            {{{1,8},{2,9},{3,10},{4,8},{5,4},{6,2},{7,7},{8,8},{9,3},{10,10}},{{1,7},{2,3},{3,12},{4,5},{5,4},{6,3},{7,6},{8,9},{9,2},{10,15}},{{1,4},{2,7},{3,3},{4,6},{5,3},{6,4},{7,1},{8,5},{9,1},{10,11}}},
            {{{1,1},{2,7},{3,8},{4,3},{5,4},{6,9},{7,4},{8,13},{9,10},{10,7}},{{1,3},{2,8},{3,1},{4,2},{5,3},{6,6},{7,11},{8,2},{9,13},{10,3}},{{1,5},{2,4},{3,2},{4,1},{5,2},{6,1},{7,8},{8,14},{9,5},{10,7}}},
            {{{1,5},{2,7},{3,11},{4,3},{5,2},{6,9},{7,8},{8,5},{9,12},{10,8}},{{1,8},{2,3},{3,10},{4,7},{5,5},{6,13},{7,4},{8,6},{9,8},{10,4}},{{1,2},{2,2},{3,13},{4,5},{5,4},{6,3},{7,5},{8,7},{9,9},{10,5}}},
            {{{1,3},{2,9},{3,1},{4,3},{5,8},{6,1},{7,6},{8,7},{9,5},{10,4}},{{1,4},{2,6},{3,2},{4,5},{5,7},{6,3},{7,1},{8,9},{9,6},{10,7}},{{1,8},{2,5},{3,4},{4,8},{5,6},{6,1},{7,2},{8,3},{9,10},{10,12}}},
            {{{1,4},{2,3},{3,1},{4,6},{5,7},{6,1},{7,2},{8,6},{9,20},{10,6}},{{1,3},{2,1},{3,8},{4,1},{5,9},{6,4},{7,1},{8,4},{9,17},{10,15}},{{1,9},{2,2},{3,4},{4,2},{5,3},{6,5},{7,2},{8,4},{9,10},{10,23}}}
    };

    public static final int  INSTANCE10_MACHINE_NUM = 10;

    public static final int[][][][] INSTANCE15 = new int[][][][]{
            {{{1,1},{2,4},{3,6},{4,9},{5,3},{6,5},{7,2},{8,8},{9,9},{10,4}},{{1,1},{2,1},{3,3},{4,4},{5,8},{6,10},{7,4},{8,11},{9,4},{10,3}},{{1,2},{2,5},{3,1},{4,5},{5,6},{6,9},{7,5},{8,10},{9,3},{10,2}},{{1,10},{2,4},{3,5},{4,9},{5,8},{6,4},{7,15},{8,8},{9,4},{10,4}}},
            {{{1,4},{2,8},{3,7},{4,1},{5,9},{6,6},{7,1},{8,10},{9,7},{10,1}},{{1,6},{2,11},{3,2},{4,7},{5,5},{6,3},{7,5},{8,14},{9,9},{10,2}},{{1,8},{2,5},{3,8},{4,9},{5,4},{6,3},{7,5},{8,3},{9,8},{10,1}},{{1,9},{2,3},{3,6},{4,1},{5,2},{6,6},{7,4},{8,1},{9,7},{10,2}}},
            {{{1,7},{2,1},{3,8},{4,5},{5,4},{6,9},{7,1},{8,2},{9,3},{10,4}},{{1,5},{2,10},{3,6},{4,4},{5,9},{6,5},{7,1},{8,7},{9,1},{10,6}},{{1,4},{2,2},{3,3},{4,8},{5,7},{6,4},{7,6},{8,9},{9,8},{10,4}},{{1,7},{2,3},{3,12},{4,1},{5,6},{6,5},{7,8},{8,3},{9,5},{10,2}},},
            {{{1,6},{2,2},{3,5},{4,4},{5,1},{6,2},{7,3},{8,6},{9,5},{10,4}},{{1,8},{2,5},{3,7},{4,4},{5,1},{6,2},{7,36},{8,5},{9,8},{10,5}},{{1,9},{2,6},{3,2},{4,4},{5,5},{6,1},{7,3},{8,6},{9,5},{10,2}},{{1,11},{2,4},{3,5},{4,6},{5,2},{6,7},{7,5},{8,4},{9,2},{10,1}},},
            {{{1,6},{2,9},{3,2},{4,3},{5,5},{6,8},{7,7},{8,4},{9,1},{10,2}},{{1,5},{2,4},{3,6},{4,3},{5,5},{6,2},{7,28},{8,7},{9,4},{10,5}},{{1,6},{2,2},{3,4},{4,3},{5,6},{6,5},{7,2},{8,4},{9,7},{10,9}},{{1,6},{2,5},{3,4},{4,2},{5,3},{6,2},{7,5},{8,4},{9,7},{10,5}}},
            {{{1,4},{2,1},{3,3},{4,2},{5,6},{6,9},{7,8},{8,5},{9,4},{10,2}},{{1,1},{2,3},{3,6},{4,5},{5,4},{6,7},{7,5},{8,4},{9,6},{10,5}}},
            {{{1,1},{2,4},{3,2},{4,5},{5,3},{6,6},{7,9},{8,8},{9,5},{10,4}},{{1,2},{2,1},{3,4},{4,5},{5,2},{6,3},{7,5},{8,4},{9,2},{10,5}}},
            {{{1,2},{2,3},{3,6},{4,2},{5,5},{6,4},{7,1},{8,5},{9,8},{10,7}},{{1,4},{2,5},{3,6},{4,2},{5,3},{6,5},{7,4},{8,1},{9,2},{10,5}},{{1,3},{2,5},{3,4},{4,2},{5,5},{6,49},{7,8},{8,5},{9,4},{10,5}},{{1,1},{2,2},{3,36},{4,5},{5,2},{6,3},{7,6},{8,4},{9,1},{10,2}}},
            {{{1,6},{2,3},{3,2},{4,22},{5,44},{6,11},{7,10},{8,23},{9,5},{10,1}},{{1,2},{2,3},{3,2},{4,12},{5,15},{6,10},{7,12},{8,14},{9,18},{10,16}},{{1,20},{2,17},{3,12},{4,5},{5,9},{6,6},{7,4},{8,7},{9,5},{10,6}},{{1,9},{2,8},{3,7},{4,4},{5,5},{6,8},{7,7},{8,4},{9,56},{10,2}}},
            {{{1,5},{2,8},{3,7},{4,4},{5,56},{6,3},{7,2},{8,5},{9,4},{10,1}},{{1,2},{2,5},{3,6},{4,9},{5,8},{6,5},{7,4},{8,2},{9,5},{10,4}},{{1,6},{2,3},{3,2},{4,5},{5,4},{6,7},{7,4},{8,5},{9,2},{10,1}},{{1,3},{2,2},{3,5},{4,6},{5,5},{6,8},{7,7},{8,4},{9,5},{10,2}}},
            {{{1,1},{2,2},{3,3},{4,6},{5,5},{6,2},{7,1},{8,4},{9,2},{10,1}},{{1,2},{2,3},{3,6},{4,3},{5,2},{6,1},{7,4},{8,10},{9,12},{10,1}},{{1,3},{2,6},{3,2},{4,5},{5,8},{6,4},{7,6},{8,3},{9,2},{10,5}},{{1,4},{2,1},{3,45},{4,6},{5,2},{6,4},{7,1},{8,25},{9,2},{10,4}}},
            {{{1,9},{2,8},{3,5},{4,6},{5,3},{6,6},{7,5},{8,2},{9,4},{10,2}},{{1,5},{2,8},{3,9},{4,5},{5,4},{6,75},{7,63},{8,6},{9,5},{10,21}},{{1,12},{2,5},{3,4},{4,6},{5,3},{6,2},{7,5},{8,4},{9,2},{10,5}},{{1,8},{2,7},{3,9},{4,5},{5,6},{6,3},{7,2},{8,5},{9,8},{10,4}}},
            {{{1,4},{2,2},{3,5},{4,6},{5,8},{6,5},{7,6},{8,4},{9,6},{10,2}},{{1,3},{2,5},{3,4},{4,7},{5,5},{6,8},{7,6},{8,6},{9,3},{10,2}},{{1,5},{2,4},{3,5},{4,8},{5,5},{6,4},{7,6},{8,5},{9,4},{10,2}},{{1,3},{2,2},{3,5},{4,6},{5,5},{6,4},{7,8},{8,5},{9,6},{10,4}}},
            {{{1,2},{2,3},{3,5},{4,4},{5,6},{6,5},{7,4},{8,85},{9,4},{10,5}},{{1,6},{2,2},{3,4},{4,5},{5,8},{6,6},{7,5},{8,4},{9,2},{10,6}},{{1,3},{2,25},{3,4},{4,8},{5,5},{6,6},{7,3},{8,2},{9,5},{10,4}},{{1,8},{2,5},{3,6},{4,4},{5,2},{6,3},{7,6},{8,8},{9,5},{10,4}}},
            {{{1,2},{2,5},{3,6},{4,8},{5,5},{6,6},{7,3},{8,2},{9,5},{10,4}},{{1,5},{2,6},{3,2},{4,5},{5,4},{6,2},{7,5},{8,3},{9,2},{10,5}},{{1,4},{2,5},{3,2},{4,3},{5,5},{6,2},{7,8},{8,4},{9,7},{10,5}},{{1,6},{2,2},{3,11},{4,14},{5,2},{6,3},{7,6},{8,5},{9,4},{10,8}}}
    };
            public static final int  INSTANCE15_MACHINE_NUM = 10;


            public static final int[][][][] XUGONG =  {
                    {{{1,13800}},{{3,63360}},{{5,30400}},{{7,22280}},{{9,58080},{10,58080}},{{11,45920}},{{13,27040}},{{15,300}}},
                    {{{1,15200},{2,17640}},{{3,70560},{4,58800}},{{5,51960},{6,35280}},{{7,34320},{8,35280}},{{9,64680},{10,64680}},{{11,50320},{12,56200}},{{13,29840},{14,29840}},{{15,300}}},
                    {{{1,17360},{2,20160}},{{3,80640},{4,67200}},{{5,39200},{6,40320}},{{7,73600},{8,40320}},{{9,56480},{10,56480}},{{11,56480},{12,63200}},{{13,33760},{14,33760}},{{15,300}}},
                    {{{2,16560}},{{4,27600}},{{6,16560}},{{8,16560}},{{9,30360},{10,30360}},{{12,26600}},{{14,14080}},{{15,300}}}
            };

    public static final int XUGONG_MACHINE_NUM = 15;
    /**
     * 构造函数,初始化相关数据
     */
    public RawData(){
        data = INSTANCE8;
        // 设置工件数量的值
        this.jobNum = data.length;
        // 设置总工序数量的值
        for(int i=0;i<data.length;i++){
            this.totalProcessNum+=data[i].length;
        }
        // 设置机器数量的值,该值应该为已知条件
        this.machineNum = INSTANCE8_MACHINE_NUM;
    }

    public int[][][][] getData() {
        return data;
    }

    public int getJobNum() {
        return jobNum;
    }

    public int getTotalProcessNum() {
        return totalProcessNum;
    }

    public int getMachineNum() {
        return machineNum;
    }

    public static RawData getInstance(Order... orders){
        return new RawData();
    }
}

算法类

public class JayaAlgorithm {
    private int popNum;
    private int iterateNum;
    private RawData rawData;

    public Individual getResult() {
        Population population = init(); // 初始化种群

        for (int i = 0; i < this.iterateNum; i++) { // 算法迭代
            // 对种群进行Pareto快速非支配排序
            LinkedList<List<Individual>> lists = fastNonDominatedSort(population);
            // 通过拥挤距离获取种群中的最优与最劣个体
            Individual[] bestAndWorst = calCrowding(lists);
            population.setBest1(bestAndWorst[0]);
            population.setWorst1(bestAndWorst[1]);
            // 种群进化
            population = evolvePopulaiton(population);
        }
        // 对种群进行非支配排序、计算拥挤距离,以获得最终结果
        LinkedList<List<Individual>> lists = fastNonDominatedSort(population);
        Individual[] bestAndWorst = calCrowding(lists);
        return bestAndWorst[0];
    }

    public JayaAlgorithm(int popNum, int iterateNum, RawData rawData) {
        this.popNum = popNum;
        this.iterateNum = iterateNum;
        this.rawData = rawData;
    }

    public JayaAlgorithm(RawData data,JayaConfig config){

    }

    public Population init() {
        return new Population(this.rawData, this.popNum);
    }

    /**
     * 种群进化
     *
     * @return
     */
    private Population evolvePopulaiton(Population population) {
        Population newPopulation = new Population(popNum);
        Individual best = population.getBest();
        Individual worst = population.getWorst();
        newPopulation.setIndividual(0, best);
        for (int i = 1; i < population.size(); i++) {
            Individual individual = population.getIndividual(i);
            Individual newIndividual = evolveIndividual(individual, best, worst);
            if (newIndividual.dominate(individual)) newPopulation.setIndividual(i, newIndividual);
            else newPopulation.setIndividual(i, individual);
        }
        return newPopulation;
    }

    /**
     * 对个体进行进化
     *
     * @param individual 当前个体
     * @param best       最优个体
     * @param worst      最劣个体
     * @return 进化后的个体
     */
    private Individual evolveIndividual(Individual individual, Individual best, Individual worst) {
        // 机器编码部分
        int[] machine = new int[individual.getCodeLength()];
        for (int i = 0; i < machine.length; i++) {
            if (individual.getGene(0, i) == worst.getGene(0, i)) {
                machine[i] = best.getGene(0, i);
                continue;
            }
            machine[i] = individual.getGene(0, i);
        }
        // 工序编码部分
        int[] process = new int[individual.getCodeLength()];
        for (int i = 0; i < process.length; i++) {
            if (individual.getGene(1, i) != worst.getGene(1, i))
                process[i] = individual.getGene(1, i);
        }
        Map<Integer, Integer> map = new HashMap<>();
        for (int p : process) {
            if (p != 0) map.put(p, map.getOrDefault(p, 0) + 1);
        }

        List<Integer> list = new ArrayList<>();
        for (int j = 0; j < best.getCodeLength(); j++) {
            int gene = best.getGene(1, j);
            if (map.getOrDefault(gene, 0) == 0) list.add(gene);
            else map.put(gene, map.get(gene) - 1);
        }
        int index = 0;
        if (list.size() != 0) {
            for (int i = 0; i < process.length; i++) {
                if (process[i] == 0) process[i] = list.get(index++);
            }
        }
        return new Individual(machine, process, individual.getRawData());
    }

    /**
     * 快速非支配排序
     *
     * @param pop 需要进行排序的种群
     * @return 使用LinkedList方便获取最优层和最劣层
     */
    private LinkedList<List<Individual>> fastNonDominatedSort(Population pop) {
        Individual[] individuals = pop.getIndividuals();
        Map<Individual, Integer> isDominateNum = new HashMap<>();
        Map<Individual, List<Individual>> dominate = new HashMap<>();

        for (int i = 0; i < individuals.length; i++) {
            int n = 0;
            List<Individual> list = new ArrayList<>();
            for (int j = 0; j < individuals.length; j++) {
                if (i == j) continue;
                if (individuals[i].dominate(individuals[j])) {
                    list.add(individuals[j]);
                }
                if (individuals[j].dominate(individuals[i])) {
                    n++;
                }
            }

            isDominateNum.put(individuals[i], n);
            dominate.put(individuals[i], list);
        }

        LinkedList<List<Individual>> res = new LinkedList<>();


        // 此处容易陷入死循环
        while (isDominateNum.size() != 0) {
            List<Individual> list = new ArrayList<>();
            for (Map.Entry<Individual, Integer> individualIntegerEntry : isDominateNum.entrySet()) {
                if (individualIntegerEntry.getValue() == 0) list.add(individualIntegerEntry.getKey());
            }

            res.add(list);
            if (list.size() == 0) {
                for (Map.Entry<Individual, Integer> individualIntegerEntry : isDominateNum.entrySet()) {
                    list.add(individualIntegerEntry.getKey());
                }
                break;
            }

            for (Individual individual : list) {
                isDominateNum.remove(individual);
                for (Individual individual1 : dominate.get(individual)) {
                    try {
                        // isDominateNum.get(individual1) - 1可能造成空指针
                        isDominateNum.put(individual1, isDominateNum.get(individual1) - 1);
                    } catch (NullPointerException e) {
                        e.printStackTrace();
                        e.getMessage();
                    }

                }
            }
        }
        return res;
    }

    /**
     * 计算拥距离
     *
     * @param fastSort 经过快速非支配排序得到的结果
     * @return 个体数组,第一个表示最优个体,第二个表示最劣个体
     */
    private Individual[] calCrowding(LinkedList<List<Individual>> fastSort) {
        Individual[] res = new Individual[2];
        List<Individual> first = fastSort.getFirst(); List<Individual> last = fastSort.getLast();
        Random rnd = new Random();
        if (first.size() < 3) {
            res[0] = first.get(rnd.nextInt(first.size()));
        } else {
            Map<Individual, Integer> map = new HashMap<>();
            Individual[] individuals = first.toArray(new Individual[first.size()]);

            Arrays.sort(individuals, (o1, o2) -> o1.getFinishTime() - o2.getFinishTime());

            map.put(individuals[0], Integer.MAX_VALUE / 2);
            map.put(individuals[individuals.length - 1], Integer.MAX_VALUE / 2);

            for (int i = 1; i < individuals.length - 1; i++) {
                int num = Math.abs(individuals[i].getFinishTime() - individuals[i + 1].getFinishTime()) +
                        Math.abs(individuals[i].getFinishTime() - individuals[i - 1].getFinishTime());
                map.put(individuals[i], num);
            }

            Arrays.sort(individuals, (o1, o2) -> o1.getFreeTime() - o2.getFreeTime());

            map.put(individuals[0], map.get(individuals[0]) + Integer.MAX_VALUE / 2);
            map.put(individuals[individuals.length - 1], map.get(individuals[individuals.length - 1]) + Integer.MAX_VALUE / 2);

            for (int i = 1; i < individuals.length - 1; i++) {
                int num = Math.abs(individuals[i].getFreeTime() - individuals[i + 1].getFreeTime()) +
                        Math.abs(individuals[i].getFreeTime() - individuals[i - 1].getFreeTime());
                map.put(individuals[i], map.get(individuals[i]) + num);
            }

            int max = -1;
            Individual best = null;
            for (Map.Entry<Individual, Integer> individualIntegerEntry : map.entrySet()) {
                if (individualIntegerEntry.getValue() > max) {
                    max = individualIntegerEntry.getValue();
                    best = individualIntegerEntry.getKey();
                }
            }
            res[0] = best;
        }

        if (last.size() < 3) {
            res[1] = last.get(rnd.nextInt(last.size()));
        } else {
            Map<Individual, Integer> map = new HashMap<>();
            Individual[] individuals = last.toArray(new Individual[last.size()]);

            Arrays.sort(individuals, (o1, o2) -> o1.getFinishTime() - o2.getFinishTime());

            map.put(individuals[0], Integer.MAX_VALUE / 2);
            map.put(individuals[individuals.length - 1], Integer.MAX_VALUE / 2);

            for (int i = 1; i < individuals.length - 1; i++) {
                int num = Math.abs(individuals[i].getFinishTime() - individuals[i + 1].getFinishTime()) +
                        Math.abs(individuals[i].getFinishTime() - individuals[i - 1].getFinishTime());
                map.put(individuals[i], num);
            }

            Arrays.sort(individuals, (o1, o2) -> o1.getFreeTime() - o2.getFreeTime());

            map.put(individuals[0], map.get(individuals[0]) + Integer.MAX_VALUE / 2);
            map.put(individuals[individuals.length - 1], map.get(individuals[individuals.length - 1]) + Integer.MAX_VALUE / 2);

            for (int i = 1; i < individuals.length - 1; i++) {
                int num = Math.abs(individuals[i].getFreeTime() - individuals[i + 1].getFreeTime()) +
                        Math.abs(individuals[i].getFreeTime() - individuals[i - 1].getFreeTime());
                map.put(individuals[i], map.get(individuals[i]) + num);
            }

            int min = Integer.MAX_VALUE;
            Individual worst = null;
            for (Map.Entry<Individual, Integer> individualIntegerEntry : map.entrySet()) {
                if (individualIntegerEntry.getValue() < min) {
                    min = individualIntegerEntry.getValue();
                    worst = individualIntegerEntry.getKey();
                }
            }
            res[1] = worst;
        }
        return res;
    }

    LinkedList<List<Individual>> nonDominateSort(Population population){
        LinkedList<List<Individual>> result = new LinkedList<>(); // 最终结果
        while(population.size()>1){
            List<Individual> list = new ArrayList<>(); // 一个Pareto前沿
            out:for(int i=0;i<population.size();i++){
                Individual i1 = population.getIndividual(i);
                for(int j=0;j<population.size();j++){
                    Individual i2 = population.getIndividual(j);
                    if(i1.equals(i2)) continue;
                    if(i2.dominate(i1)) continue out;
                }
                // 如果种群中其它所有个体都无法支配i1,则将i1添加至当前Pareto前沿
                list.add(i1);
            }
            result.add(list); // 将当前Pareto前沿添加至结果集中
            population.remove(list); // 从population中移除存在于list中的individual
        }
        // ...
        return result;
    }
}

测试类

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

        RawData rawData = new RawData();
        JayaAlgorithm jaya = new JayaAlgorithm(200, 100, rawData);
        Date date1 = new Date();
        Individual result = jaya.getResult();
        Date date2 = new Date();
        Long time = (date2.getTime()-date1.getTime());
        System.out.println("计算时间为"+time+"ms");
        System.out.println("最终结果为:"+result);
        System.out.println("finishTime = "+result.getFinishTime()+"; freeTime = "+result.getFreeTime());

        result.printDetailTime();        
    }
}
  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值