NSGA2代码分析——rank.c

    该源文件中就包含一个函数assign_rank_and_crowding_distance (population *new_pop), 主要功能是对种群new_pop里的个体进行Pareto分级排序,同时计算出每个个体的拥挤距离。
    该函数的具体算法流程如下:
1。初始化一个双向链表orig,含有pop_num个节点。每个节点包含三个域:索引、前续节点指针、后续节点指针。每个节点的索引(index)对应着new_pop的第index个个体。
2。从orig中找出所有的非支配个体,并存储在cur链表中。
    (1).取orig中对应的第一个节点,插入到cur链表中。i = 1+1。
    (2).对orig中的第i个节点对应的个体同cur链表中所有节点对应的个体进行Pareto比较,并根据比较结果调整orig和cur链表中的节点。
    (3).如果没有到达orig的最后一个节点,则转入(2)。
3。对cur链表中的个体计算其拥挤距离。(调用assign_crowding_distance_list ()函数,定义在crowdist.c文件中)
4。删除cur链表中所有的节点,即清除当前的所有非支配个体。
5。如果orig还有节点,则转入2。
void  assign_rank_and_crowding_distance (population  * new_pop)
{
    
int  flag;                                 // 两个个体的Pareto比较结果
     int  i;                                     // 计数变量
     int  end;                                 // 一轮个体的Pareto级别比较结束标志
     int  front_size;                             // 记录当前Pareot级别的集合中的个体数目
     int  rank = 1 ;                                 // 记录当前的Pareto级别
    list  * orig;                                 // 记录种群中所有未排序的个体
    list  * cur;                                 // 记录当前个体集中所有非支配个体
    list  * temp1,  * temp2;                     // 临时节点指针,指向当前需要操作的节点
    orig  =  (list  * )malloc( sizeof (list));     // orig链表的头节点
    cur  =  (list  * )malloc( sizeof (list));         // cur链表的头节点
    front_size  =   0 ;
    orig
-> index  =   - 1 ;
    orig
-> parent  =  NULL;
    orig
-> child  =  NULL;
    cur
-> index  =   - 1 ;
    cur
-> parent  =  NULL;
    cur
-> child  =  NULL;
    temp1 
=  orig;

    
// 初始化orig链表,链表中的节点的index对应于new_pop中的个体下标
     for  (i = 0 ; i < popsize; i ++ )
    {
        insert (temp1,i);
        temp1 
=  temp1 -> child;
    }

    
// 对new_pop中的所有个体进行Pareto级别排序
     do
    {
        
// 如果orig中未排序的个体只有一个,则把这个个体的拥挤距离设置为INF。
         if  (orig -> child -> child  ==  NULL)
        {
            new_pop
-> ind[orig -> child -> index].rank  =  rank;
            new_pop
-> ind[orig -> child -> index].crowd_dist  =  INF;
            
break ;
        }
        temp1 
=  orig -> child;
        insert (cur, temp1
-> index);
        front_size 
=   1 ;
        temp2 
=  cur -> child;
        temp1 
=  del (temp1);
        temp1 
=  temp1 -> child;

        
// 以下的do_while对应于步骤2。即找到当前所有未排序个体集合中的非支配个体
         do
        {
            temp2 
=  cur -> child;
            
do
            {
                end 
=   0 ;

                
// 判断temp2和temp1对应个体的Pareto比较结果,并修改orig和cur链表
                flag  =  check_dominance ( & (new_pop -> ind[temp1 -> index]),  & (new_pop -> ind[temp2 -> index]));
                
if  (flag  ==   1 )
                {
                    insert (orig, temp2
-> index);
                    temp2 
=  del (temp2);
                    front_size
-- ;
                    temp2 
=  temp2 -> child;
                }
                
if  (flag  ==   0 )
                {
                    temp2 
=  temp2 -> child;
                }
                
if  (flag  ==   - 1 )
                {
                    end 
=   1 ;
                }
            }
            
while  (end != 1   &&  temp2 != NULL);
            
if  (flag  ==   0   ||  flag  ==   1 )
            {
                insert (cur, temp1
-> index);
                front_size
++ ;
                temp1 
=  del (temp1);
            }
            temp1 
=  temp1 -> child;
        }
        
while  (temp1  !=  NULL);

        
// 对cur链表所有当前的非支配个体的Pareto级别进行赋值
        temp2  =  cur -> child;
        
do
        {
            new_pop
-> ind[temp2 -> index].rank  =  rank;
            temp2 
=  temp2 -> child;
        }
        
while  (temp2  !=  NULL);

        
// 对当前Pareto级别的所有个体进行拥挤距离计算
        assign_crowding_distance_list (new_pop, cur -> child, front_size);
        temp2 
=  cur -> child;

        
// 清除cur链表中的所有当前的非支配个体
         do
        {
            temp2 
=  del (temp2);
            temp2 
=  temp2 -> child;
        }
        
while  (cur -> child  != NULL);
        rank
+= 1 ;
    }
while  (orig -> child != NULL);
    free (orig);
    free (cur);
    
return ;
}

你可能感兴趣的:(算法,list,null,insert,代码分析,distance)