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 = new SolutionSet[problemSet_.size()];
for (int i = 0; i < problemSet_.size(); i++)
resPopulation[i] = new SolutionSet();
for (int i = 0; i < population.size(); i++) {
Solution sol = population.get(i);
int pid = sol.getSkillFactor();
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.
- 下圖是此解決方案用於三目標問題時的調試結果
- 證明提出的方法可以解決這個問題!
最終代碼
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();
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.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));
}