1 /* Rank assignment routine */ 2 3 # include <stdio.h> 4 # include <stdlib.h> 5 # include <math.h> 6 7 # include "global.h" 8 # include "rand.h" 9 10 /* Function to assign rank and crowding distance to a population of size pop_size*/ 11 void assign_rank_and_crowding_distance (population *new_pop) 12 { 13 int flag; 14 int i; 15 int end; 16 int front_size; 17 int rank=1; 18 list *orig; 19 list *cur; 20 list *temp1, *temp2; 21 orig = (list *)malloc(sizeof(list)); 22 cur = (list *)malloc(sizeof(list)); 23 front_size = 0; 24 orig->index = -1; 25 orig->parent = NULL; 26 orig->child = NULL; 27 cur->index = -1; 28 cur->parent = NULL; 29 cur->child = NULL; 30 temp1 = orig; 31 32 /* 對orig 鏈表中的個體進行初始化,元素賦值相對的個體序號 */ 33 for (i=0; i<popsize; i++) 34 { 35 insert (temp1,i); 36 temp1 = temp1->child; 37 } 38 39 40 /* 支配關系分層的主循環函數 */ 41 do 42 { 43 /* 44 如果orig鏈表中只有一個個體,則直接對其分層賦值, 45 因為該層只有一個個體對其擁擠度直接賦值為無窮,並break主循環 46 */ 47 if (orig->child->child == NULL) 48 { 49 new_pop->ind[orig->child->index].rank = rank; 50 new_pop->ind[orig->child->index].crowd_dist = INF; 51 break; 52 } 53 54 /* 55 orig 中的元素為待分層的元素, 此時 cur 鏈表為空。 56 57 取出 orig 鏈表中的頭一個個體插入到 cur 鏈表中,該操作相當於對以下內循環的初始化 58 此時,cur鏈表中只有一個元素 59 */ 60 temp1 = orig->child; 61 insert (cur, temp1->index); 62 front_size = 1; 63 temp2 = cur->child; 64 temp1 = del (temp1); 65 temp1 = temp1->child; 66 67 68 do 69 { 70 /*temp2 指向cur鏈表的第一個節點*/ 71 temp2 = cur->child; 72 do 73 { 74 /*結束標志位 歸0 */ 75 end = 0; 76 /*判斷 orig 和 cur 鏈表中 temp1, temp2 指針指向的節點元素所對應的個體支配關系 */ 77 flag = check_dominance (&(new_pop->ind[temp1->index]), &(new_pop->ind[temp2->index])); 78 79 /*若 a支配b ,在orig中插入a,在cur中刪除b */ 80 if (flag == 1) 81 { 82 insert (orig, temp2->index); 83 temp2 = del (temp2); 84 front_size--; 85 temp2 = temp2->child; 86 87 88 /*個體a b互不支配, cur鏈表指針下移一位*/ 89 if (flag == 0) 90 { 91 temp2 = temp2->child; 92 } 93 94 /*個體b 支配 個體a , 結束該次循環*/ 95 if (flag == -1) 96 { 97 end = 1; 98 } 99 } 100 /* 101 個體b 被 個體a 支配即 flag==-1, 將該層循環結束位 end置1,結束該層循環。 102 cur 鏈表中 所有個體均已遍歷,沒有b個體,結束循環。 103 */ 104 while (end!=1 && temp2!=NULL); 105 106 107 108 /* 109 個體a 支配 個體b 或者 互不支配 110 將個體a 插入到 cur鏈表最前端,同時移除orig鏈表中的a個體 111 */ 112 if (flag == 0 || flag == 1) 113 { 114 insert (cur, temp1->index); 115 front_size++; 116 temp1 = del (temp1); 117 } 118 119 /*orig鏈表中所指向個體的指針后移一位*/ 120 temp1 = temp1->child; 121 } 122 /*temp1指針指向NULL意味着orig鏈表中所有元素對應的個體均被 cur鏈表中對應的個體 支配*/ 123 while (temp1 != NULL); 124 125 126 127 128 129 /* 130 temp2重新指向 cur 列表中第一個元素,cur列表中的元素為當前已分層的元素 131 */ 132 temp2 = cur->child; 133 do 134 { 135 new_pop->ind[temp2->index].rank = rank; 136 temp2 = temp2->child; 137 } 138 while (temp2 != NULL); 139 /* 對當前層的個體進行擁擠度判斷 */ 140 assign_crowding_distance_list (new_pop, cur->child, front_size); 141 142 143 /* 對 cur 鏈表中的個體釋放內存空間 */ 144 temp2 = cur->child; 145 do 146 { 147 temp2 = del (temp2); 148 temp2 = temp2->child; 149 } 150 while (cur->child !=NULL); 151 /* 分層的排序值 加1 */ 152 rank+=1; 153 } 154 /* 循環判斷,直到orig鏈表中出頭節點外為空,即所有個體全部分層 */ 155 while (orig->child!=NULL); 156 157 158 /* 將鏈表orig cur的頭結點內存空間釋放掉 */ 159 free (orig); 160 free (cur); 161 return; 162 }
該非支配分層基本思想是設置兩個雙向鏈表(orig cur),orig 鏈表里面存放所有待分層排序的個體索引,cur鏈表中的元素為分層結束后該層的個體索引。
每次在orig 中取出的元素對應的個體為 a, cur 中取出的元素對應的個體為 b 。
若 b支配於 a ,則取 orig 中對應的下一個個體作為 a ,
若 a b 互不支配 ,則依次取 cur 中對應的下一個個體作為 b , 遍歷cur 中所有個體(cur 中的個體為待分層的個體,其互不支配),若a 與 cur 中所有個體互不支配則將個體a移除orig鏈表並插入到cur鏈表的最前端。
若a 支配於 b, 則將b 個體移除cur 鏈表並插入到 orig 鏈表的最前端,同時取cur 中的下一個個體作為 b 。
當遍歷orig 中的所有元素,此時 cur 中個體便是此時的非支配解。
