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

摘要:
距离计算的核心代码如下:1/*Routintocomputerrowdingdistance*/2voidassign_crowdingdistance 3{4inti,j;5for6{7for8{9obj_array[i][j]=dist[j];10}11quicksort_front_obj;12} 13for14{15pop-˃ind[dist[j]]。crowd_dist=0.0;16}1718 for 19{20pop-˃ind[obj_array[i][0]。crowd-dist=INF;21}2223 for 24{25for26{27if(pop-˃ind[obj_array[i][j]])。crowd_dist!
 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行,  将拥挤距离不为无穷的所有个体的拥挤距离除以目标函数值个数(归一化操作)  。 

免责声明:文章转载自《多目标遗传算法 ------ NSGA-II (部分源码解析) 拥挤距离计算 crowddist.c》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇解决 Idea 下 Lombok 无法使用线性代数的本质(干货!)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

netcore3.0 IHost 源码解析(一)

Nuget包:以Microsoft.Extensins.Hosting开头的Nuget包 Github地址:https://github.com/dotnet/extensions/tree/master/src/Hosting 先看下几个重要的接口  IHostBuilder的实现类HostBuilder /// <summary>...

Netty之EventLoop-netty学习笔记(11)-20210813

线程模型概述 基本的线程池化模式可以描述为: 从池的空闲线程列表中选择一个 Thread,并且指派它去运行一个已提交的任务(一个Runnable 的实现);当任务完成时,将该 Thread 返回给该列表,使其可被重用。 虽然池化和重用线程相对于简单地为每个任务都创建和销毁线程是一种进步,但是它并不能 消除由上下文切换所带来的开销,其将随着线程数量的增加很快...

【MyBatis源码分析】Configuration加载(下篇)

元素设置 继续MyBatis的Configuration加载源码分析: 1 private void parseConfiguration(XNode root) { 2 try { 3 Properties settings = settingsAsPropertiess(root.evalNode("settings"))...

带精英策略的快速非支配排序遗传算法 NSGA-II 算法

NSGAII(带精英策略的非支配排序的遗传算法),是基于遗传算法的多目标优化算法,是基于pareto最优解讨论的多目标优化,下面介绍pareto(帕累托)最优解的相关概念。 Paerot支配关系 Pareto最优解定义 多目标优化问题与单目标优化问题有很大差异。当只有一个目标函数时,人们寻找最好的解,这个解优于其他所有解,通常是全局最大或最小,即全局最优...

你真的了解python的with语句吗?通过分析contextlib源码让你彻底掌握with的用法

楔子 下面我们来聊一下Python中的上下文管理,Python中的上下文管理我们可以通过with语句实现。在Python中使用with语句最多的情况,莫过于操作文件了,比如我们在打开一个文件的时候会通过类似于with open("test.txt", encoding="utf-8") as f: 这种形式打开,这种方式的好处就在于with语句结束后会自动...

Linux进程调度与源码分析(三)——do_fork()的实现原理

        用户层的fork(),vfork(),clone()API函数在执行时,会触发系统调用完成从用户态陷入到内核态的过程,而上述函数的系统调用,最终实现都是通过内核函数do_fork()完成,本篇着重分析do_forkI()函数的实现过程。         Linux操作系统中,产生一个新的进程和产生一个新的线程对于内核来说,最为本质的区别在于...