多目标遗传算法 ------ 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 中个体便是此时的非支配解。

 

    原文作者:遗传算法
    原文地址: https://www.cnblogs.com/devilmaycry812839668/p/6264790.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞