MTO Jmetal IGD計算BUG

MTO Jmetal IGD計算BUG

覺得有用的話,歡迎一起討論相互學習~

我的微博我的github我的B站

  • 大家知道只要有種羣的目標函數值和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));
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章