MTO Jmetal IGD计算BUG

时间:2022-07-23
本文章向大家介绍MTO Jmetal IGD计算BUG,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

  • 大家知道只要有种群的目标函数值和PF前沿,按道理将是可以计算IGD的

错误分析

  • 遇到以下错误:
  • 追踪错误后发现,错误来源于:
  • 这里的front[i]越界了,在MTO中,计算IGD时,max和min应该是target任务的obj维度,而不是总的维度。举例,一般情况下MTO中一个任务的IGD根据skillfactor的不同应该是inf,inf,0.1,0.1这种,所以是四维的。但是单个问题的PF其实是2维的或者3维的,也就是说min和max都是二维和三维的因此,当j迭代到2的时候,但是maxmumvalue数组的最大索引是1,所以这个时候会出现数组的越界。

证实猜想

  • 经过单步调试,可以看见front[i]的维度是4,max和min的维度都是2,这样j到2时,表示遍历第三个维度,就会越界!
  • 这是因为在初始化solution时,我们使用的是Problemset,这个参数默认的是统一空间的维度,即问题的最大维度Solution sol = new Solution(problemSet);
  • 这种方式是initialize 种群的时候是可取的,但是计算IGD时是不可取的。

解决方案

  • 可以通过departpopulation()函数按照skillfactor将种群重新分成两组,并且每组的obj的数目和其skillfactor的保持一致。
//用于将整个大种群划分为分配给不同任务的子种群
void departpopulation() {
    // resPopulation 是一个Solution的集合数组
    resPopulation = new SolutionSet[problemSet_.size()];
    for (int i = 0; i < problemSet_.size(); i++)
        resPopulation[i] = new SolutionSet();
    for (int i = 0; i < population.size(); i++) {
        // 因为优化后后的种群中每个个体有一个Skill_factors,必须要将每个个体按照其skill_factor分类
        Solution sol = population.get(i);

        int pid = sol.getSkillFactor();
        //start 和 end 时目标函数在Problemset中的索引
        int start = problemSet_.get(pid).getStartObjPos();
        int end = problemSet_.get(pid).getEndObjPos();

        Solution newSolution = new Solution(end - start + 1);

        for (int k = start; k <= end; k++) {
            //复制个体目标值
            newSolution.setObjective(k - start, sol.getObjective(k));
            //别忘了复制个体决策变量函数值
            newSolution.setDecisionVariables(sol.getDecisionVariables());

        }

        resPopulation[pid].add(newSolution);
    }
}

特别注意其中new solution 时候的方式Solution newSolution = new Solution(end - start + 1); ,以及对目标进行赋值时的方式,只根据特定任务赋值, newSolution.setObjective(k - start, sol.getObjective(k)) ,因此此时其目标函数是end-start+1,而不是统一空间的4.

下图是此解决方案用于三目标问题时的调试结果

证明提出的方法可以解决这个问题!

最终代码

  • 最终,我们的IGD代码修改为:
void getIGD(SolutionSet pop) {
    SolutionSet resPopulation = new SolutionSet();
 for (int i = 0; i < pop.size(); i++) {
        Solution sol = pop.get(i);
 int pid = sol.getSkillFactor();
 //start 和 end 时目标函数在Problemset中的索引
 int start = problemSet.get(pid).getStartObjPos();
 int end = problemSet.get(pid).getEndObjPos();
 //最关键的是这里,需要对目标值修改为当前任务目标个数
 //否则会出bug,因为统一空间的目标个数是一定的
        Solution newSolution = new Solution(end - start + 1);//
 for (int k = start; k <= end; k++) {
 //复制个体目标值
            newSolution.setObjective(k - start, sol.getObjective(k));
 //别忘了复制个体决策变量函数值
            newSolution.setDecisionVariables(sol.getDecisionVariables());
        }
        resPopulation.add(newSolution);
    }
    String pf1 = "PF/" + problemSet.get(1).getHType() + ".pf";
    QualityIndicator indicator1 = new QualityIndicator(problemSet.get(1), pf1);
 double igd1 = indicator1.getIGD(resPopulation);
    System.out.println("IGD" + form.format(igd1));
}