0
点赞
收藏
分享

微信扫一扫

多目标遗传算法 ------ NSGA-II (部分源码解析) 非支配排序、分层 rank.c

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


举报

相关推荐

0 条评论