多目标遗传算法 ------ NSGA-II (部分源码解析) 拥挤距离计算 crowddist.c

复制代码
 1 /* Crowding distance computation routines */
 2 
 3 # include <stdio.h>
 4 # include <stdlib.h>
 5 # include <math.h>
 6 
 7 # include "global.h"
 8 # include "rand.h"
 9 
10 /* Routine to compute crowding distance based on ojbective function values when the population in in the form of a list */
11 void assign_crowding_distance_list (population *pop, list *lst, int front_size)
12 {
13     int **obj_array;
14     int *dist;
15     int i, j;
16     list *temp;
17     temp = lst;
18     if (front_size==1)
19     {
20         pop->ind[lst->index].crowd_dist = INF;
21         return;
22     }
23     if (front_size==2)
24     {
25         pop->ind[lst->index].crowd_dist = INF;
26         pop->ind[lst->child->index].crowd_dist = INF;
27         return;
28     }
29     obj_array = (int **)malloc(nobj*sizeof(int));
30     dist = (int *)malloc(front_size*sizeof(int));
31     for (i=0; i<nobj; i++)
32     {
33         obj_array[i] = (int *)malloc(front_size*sizeof(int));
34     }
35     for (j=0; j<front_size; j++)
36     {
37         dist[j] = temp->index;
38         temp = temp->child;
39     }
40     assign_crowding_distance (pop, dist, obj_array, front_size);
41     free (dist);
42     for (i=0; i<nobj; i++)
43     {
44         free (obj_array[i]);
45     }
46     free (obj_array);
47     return;
48 }
49 
50 /* Routine to compute crowding distance based on objective function values when the population in in the form of an array */
51 void assign_crowding_distance_indices (population *pop, int c1, int c2)
52 {
53     int **obj_array;
54     int *dist;
55     int i, j;
56     int front_size;
57     front_size = c2-c1+1;
58     if (front_size==1)
59     {
60         pop->ind[c1].crowd_dist = INF;
61         return;
62     }
63     if (front_size==2)
64     {
65         pop->ind[c1].crowd_dist = INF;
66         pop->ind[c2].crowd_dist = INF;
67         return;
68     }
69     obj_array = (int **)malloc(nobj*sizeof(int));
70     dist = (int *)malloc(front_size*sizeof(int));
71     for (i=0; i<nobj; i++)
72     {
73         obj_array[i] = (int *)malloc(front_size*sizeof(int));
74     }
75     for (j=0; j<front_size; j++)
76     {
77         dist[j] = c1++;
78     }
79     assign_crowding_distance (pop, dist, obj_array, front_size);
80     free (dist);
81     for (i=0; i<nobj; i++)
82     {
83         free (obj_array[i]);
84     }
85     free (obj_array);
86     return;
87 }
复制代码

以上代码里的两个函数都为包装函数,最终的计算都是需要调用下面的函数

assign_crowding_distance (population *pop, int *dist, int **obj_array, int front_size)  。

其中,加入一定的判断过程,对一个层里面只有两个个体的情况直接对这两个个体的拥挤距离设定为无穷。

 

 

 

 

 

距离计算的核心代码,如下:

复制代码
 1 /* Routine to compute crowding distances */
 2 void assign_crowding_distance (population *pop, int *dist, int **obj_array, int front_size)
 3 {
 4     int i, j;
 5     for (i=0; i<nobj; i++)
 6     {
 7         for (j=0; j<front_size; j++)
 8         {
 9             obj_array[i][j] = dist[j];
10         }
11         quicksort_front_obj (pop, i, obj_array[i], front_size);
12     }
13     for (j=0; j<front_size; j++)
14     {
15         pop->ind[dist[j]].crowd_dist = 0.0;
16     }
17 
18     for (i=0; i<nobj; i++)
19     {
20         pop->ind[obj_array[i][0]].crowd_dist = INF;
21     }
22 
23     for (i=0; i<nobj; i++)
24     {
25         for (j=1; j<front_size-1; j++)
26         {
27             if (pop->ind[obj_array[i][j]].crowd_dist != INF)
28             {
29                 if (pop->ind[obj_array[i][front_size-1]].obj[i] == pop->ind[obj_array[i][0]].obj[i])
30                 {
31                     pop->ind[obj_array[i][j]].crowd_dist += 0.0;
32                 }
33                 else
34                 {
35                     pop->ind[obj_array[i][j]].crowd_dist += (pop->ind[obj_array[i][j+1]].obj[i] - pop->ind[obj_array[i][j-1]].obj[i])/(pop->ind[obj_array[i][front_size-1]].obj[i] - pop->ind[obj_array[i][0]].obj[i]);
36                 }
37             }
38         }
39     }
40 
41     for (j=0; j<front_size; j++)
42     {
43         if (pop->ind[dist[j]].crowd_dist != INF)
44         {
45             pop->ind[dist[j]].crowd_dist = (pop->ind[dist[j]].crowd_dist)/nobj;
46         }
47     }
48     return;
49 }
复制代码

5 行 到  12行,  初始化  多目标索引矩阵,并对其不同目标列进行索引排序(按照目标函数值的大小)。

13行 到 16行, 个体的拥挤距离初始化。

18行 到 21行, 对按照某目标函数排序后最小的个体的拥挤距离赋值为无穷(并没有对两端赋值无穷,而是最小端的个体)。

 

27行,如果一个个体的拥挤距离已经被赋值为无穷,则对其不再计算。

29行 到  32行,如果某目标函数的排序后所有个体的该目标函数值相同,则该目标函数贡献的距离为 0  。

 

 

pop->ind[obj_array[i][j]].crowd_dist += (pop->ind[obj_array[i][j+1]].obj[i] - pop->ind[obj_array[i][j-1]].obj[i])/(pop->ind[obj_array[i][front_size-1]].obj[i] - pop->ind[obj_array[i][0]].obj[i]);

 

35行代码,  某个个体在某一个目标函数上的拥挤距离  为 该个体在该目标函数上前后个体距离之差除以该层该目标的最大最小值之差。

 

41 行  到   47行,  将拥挤距离不为无穷的所有个体的拥挤距离除以目标函数值个数(归一化操作)  。 

 

posted on   Angry_Panda  阅读(5568)  评论(0编辑  收藏  举报

编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示