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

  • 相关阅读:
    MPLab X 配置字的设置
    System.Windows.Forms.Timer定时器的“自毁”
    单片机部分缩写对照
    我的艰辛之路——2012年个人总结之三
    浏览器IE6不支持的CSS样式的选择符[转]
    SVN 用户权限管理[转]
    VC++ 随机数生成方案选择[转]
    GB/T 77142005参考文献规范[转]
    正则表达式备忘[转]
    文档、视图、框架窗口、文档模板之间的相互关系【转】
  • 原文地址:https://www.cnblogs.com/devilmaycry812839668/p/6264790.html
Copyright © 2020-2023  润新知