多目標優化擁擠距離計算
覺得有用的話,歡迎一起討論相互學習~
-
擁擠距離主要是維持種群中個體的多樣性。具體而言,一般來說是指種群按照支配關系進行非支配排序后,單個Rank層中個體的密集程度。常用於支配關系的多目標算法中,例如NSGA-II.
-
主要步驟如下:
- 取單個前沿中個體按照一個目標上的值從小到大排序
- 將最大目標值作為max,最小目標值保留作為min。並且這兩個極值點的擁擠距離都被設置為inf即無窮大。 因此注意,一個層中可能有多個具有inf的點,即如果層中有多個點在至少一個目標上相等,並且最大或最小,那么這些點的擁擠距離都是無窮大!!因為目標上呈現垂直的關系也是屬於非支配的關系!!如果出現這種情況,說明你算法的多樣性很爛!~或者在某些算法早期可能出現這種情況
- 在這個目標上計算每個個體最相鄰個體之間的距離,即i-1和i+1的目標值的差。並使用max和min對次值進行歸一化。
- 遍歷目標,將目標上已經歸一化的擁擠距離相加。
- 進入下一層front前沿
- 擁擠距離越大越好,最后按照擁擠距離重新排序各層,進而排序種群
matlab
function CrowdDis = CrowdingDistance(PopObj)
% Calculate the crowding distance of each solution in the same front
[N,M] = size(PopObj);
CrowdDis = zeros(1,N);
Fmax = max(PopObj,[],1);
Fmin = min(PopObj,[],1);
for i = 1 : M
[~,rank] = sortrows(PopObj(:,i));
CrowdDis(rank(1)) = inf;
CrowdDis(rank(end)) = inf;
for j = 2 : N-1
CrowdDis(rank(j)) = CrowdDis(rank(j))+(PopObj(rank(j+1),i)-PopObj(rank(j-1),i))/(Fmax(i)-Fmin(i));
end
end
end
jmetal
public void crowdingDistanceAssignment(SolutionSet solutionSet, int nObjs) {
int size = solutionSet.size();
if (size == 0)
return;
if (size == 1) {
solutionSet.get(0).setCrowdingDistance(Double.POSITIVE_INFINITY);
return;
} // if
if (size == 2) {
solutionSet.get(0).setCrowdingDistance(Double.POSITIVE_INFINITY);
solutionSet.get(1).setCrowdingDistance(Double.POSITIVE_INFINITY);
return;
} // if
// Use a new SolutionSet to evite alter original solutionSet
SolutionSet front = new SolutionSet(size);
for (int i = 0; i < size; i++) {
front.add(solutionSet.get(i));
}
for (int i = 0; i < size; i++)
front.get(i).setCrowdingDistance(0.0);
double objetiveMaxn;
double objetiveMinn;
double distance;
for (int i = 0; i < nObjs; i++) {
// Sort the population by Obj n
front.sort(new ObjectiveComparator(i));
objetiveMinn = front.get(0).getObjective(i);
objetiveMaxn = front.get(front.size() - 1).getObjective(i);
// Set de crowding distance
front.get(0).setCrowdingDistance(Double.POSITIVE_INFINITY);
front.get(size - 1).setCrowdingDistance(Double.POSITIVE_INFINITY);
for (int j = 1; j < size - 1; j++) {
distance = front.get(j + 1).getObjective(i) - front.get(j - 1).getObjective(i);
distance = distance / (objetiveMaxn - objetiveMinn);
distance += front.get(j).getCrowdingDistance();
front.get(j).setCrowdingDistance(distance);
} // for
} // for
} // crowdingDistanceAssing