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 中个体便是此时的非支配解。