-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathranking.m
85 lines (71 loc) · 2.81 KB
/
ranking.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
function FitnV = ranking(ObjV, RFun, SUBPOP);
% Identify the vector size (Nind)
[Nind,ans] = size(ObjV);
if nargin < 2, RFun = []; end
if nargin > 1, if isnan(RFun), RFun = []; end, end
if prod(size(RFun)) == 2,
if RFun(2) == 1, NonLin = 1;
elseif RFun(2) == 0, NonLin = 0;
else error('Parameter for ranking method must be 0 or 1'); end
RFun = RFun(1);
if isnan(RFun), RFun = 2; end
elseif prod(size(RFun)) > 2,
if prod(size(RFun)) ~= Nind, error('ObjV and RFun disagree'); end
end
if nargin < 3, SUBPOP = 1; end
if nargin > 2,
if isempty(SUBPOP), SUBPOP = 1;
elseif isnan(SUBPOP), SUBPOP = 1;
elseif length(SUBPOP) ~= 1, error('SUBPOP must be a scalar'); end
end
if (Nind/SUBPOP) ~= fix(Nind/SUBPOP), error('ObjV and SUBPOP disagree'); end
Nind = Nind/SUBPOP; % Compute number of individuals per subpopulation
% Check ranking function and use default values if necessary
if isempty(RFun),
% linear ranking with selective pressure 2
RFun = 2*[0:Nind-1]'/(Nind-1);
elseif prod(size(RFun)) == 1
if NonLin == 1,
% non-linear ranking
if RFun(1) < 1, error('Selective pressure must be greater than 1');
elseif RFun(1) > Nind-2, error('Selective pressure too big'); end
Root1 = roots([RFun(1)-Nind [RFun(1)*ones(1,Nind-1)]]);
RFun = (abs(Root1(1)) * ones(Nind,1)) .^ [(0:Nind-1)'];
RFun = RFun / sum(RFun) * Nind;
else
% linear ranking with SP between 1 and 2
if (RFun(1) < 1 | RFun(1) > 2),
error('Selective pressure for linear ranking must be between 1 and 2');
end
RFun = 2-RFun + 2*(RFun-1)*[0:Nind-1]'/(Nind-1);
end
end;
FitnV = [];
% loop over all subpopulations
for irun = 1:SUBPOP,
% Copy objective values of actual subpopulation
ObjVSub = ObjV((irun-1)*Nind+1:irun*Nind);
% Sort does not handle NaN values as required. So, find those...
NaNix = isnan(ObjVSub);
Validix = find(~NaNix);
% ... and sort only numeric values (smaller is better).
[ans,ix] = sort(-ObjVSub(Validix));
% Now build indexing vector assuming NaN are worse than numbers,
% (including Inf!)...
ix = [find(NaNix) ; Validix(ix)];
% ... and obtain a sorted version of ObjV
Sorted = ObjVSub(ix);
% Assign fitness according to RFun.
i = 1;
FitnVSub = zeros(Nind,1);
for j = [find(Sorted(1:Nind-1) ~= Sorted(2:Nind)); Nind]',
FitnVSub(i:j) = sum(RFun(i:j)) * ones(j-i+1,1) / (j-i+1);
i =j+1;
end
% Finally, return unsorted vector.
[ans,uix] = sort(ix);
FitnVSub = FitnVSub(uix);
% Add FitnVSub to FitnV
FitnV = [FitnV; FitnVSub];
end
% End of function