贪心算法求解最大独立集

目录

前言

1. 最大独立集、极大独立集

2. 贪心算法1

3. 贪心算法2

4. 贪心算法3


前言

最大独立集是一个Np-hard问题,当问题规模比较小时我们完全可以借助枚举法(是一种精确算法)求得问题的精确解。但是随着问题规模的增大,问题复杂度随着问题规模的增加呈现指数级增长,精确算法很难在可接受的时间内求得问题的解,目前有很多的启发式算法来求解Np-hard问题,其中贪心算法、局部搜索算法、禁忌搜索算法,当然还有智能优化算法(蚁群算法、进化算法、遗传算法等),本篇文章记录一下最近看的两篇中文论文中利用贪心算法求解最大独立集问题的算法思想。

首先需要说明的是,上述提及的启发式算法得到的往往是问题的近似解,我们关注的是得到解的质量(比如说得到解所需要的运行时间、迭代次数或者近似比等)。虽然利用贪心算法可以求得独立集,但是求得的独立集的质量不一定好,不过后续可以再借助局部搜索算法扩大当前独立集或者对当前的独立集(可行解)内的元素进行SWAP或者Delete 等操作找到更多的可行解(后续操作的主要目的是保持、探索可行解空间)。

1. 最大独立集、极大独立集

图G = (V,E),其中V是图G的顶点集合,E是图G的边集。如果顶点子集内任意两点之间都不相邻(相邻:两顶点之间有边),那么当前的顶点子集就是独立集

最大独立集就是所有独立集中顶点个数最多的集合。需要说明的是对于图G,它的最大独立集不一定是唯一的,但是独立数(最大独立集中的顶点个数)是一定的。

极大独立集首先要求是一个独立集,极大的意思是除去当前顶点子集A内的顶点,其余任意一个顶点加入到当前顶点子集A都会破坏它的独立性,那么这个顶点子集A就是极大独立集。最大独立集一定是极大独立集,但反之不一定成立。

2. 贪心算法1

此算法主要是根据顶点的(顶点的邻居节点个数)来构造一个可行解(独立集)。当前的图G若是一个零图(只有点,没有边的图),那么顶点集合V便是图G的最大独立集。根据这个想法,此算法通过不断从图G内删除度最大的顶点以及相关联的边来更新图G,直到图G内的点度为0,算法停止。

总结一下:

(1) 确定图G内度最大的顶点,当存在多个顶点度相同时,随机选择一个顶点,记为顶点a;

(2) 从图G中删除顶点a,以及与顶点a相关的边,更新图G;

(3) 重复(1) - (2),直到图G为零图,迭代停止,此时零图内的顶点构成一个独立集。

之所以每次迭代过程中删除的都是度最大的点,是因为最大独立集目标是最大化顶点子集内的顶点个数,一个度大的顶点在独立集内,意味着有较多的邻居节点不能加入到当前的独立集内,因此为了尽可能的实现最大独立集的目标,首先要舍弃的就是度数最大的顶点。

但上述算法,每次从顶点集合内删除的都是一个点,算法的运行时间随着顶点个数的增加而增加,可以考虑一次性的删除多个点,这是贪心算法2的思想。

3. 贪心算法2

和贪心算法1有所不同的是,此算法一次操作删除的是度数最大的点以及其邻居节点。同样的,当且仅当图G为零图时,迭代停止。虽然相比于上述算法,这个算法的运行时间会减少,但是一次性的删除多个顶点,删除的顶点中可能存在并不相邻的顶点,很可能最终得到的独立集中的顶点个数也会减少。

不过上述两种算法可以并行,比较哪一个独立集中顶点个数多,从而保留哪一个。举一反三,上述两个算法是从顶点集合内删除度数最大的顶点,逐步构造零图。同样的道理,也可以逐步向空集内添加度最小的顶点,直到任意顶点加入到当前顶点子集内,都会破坏其独立性,此时我们得到了极大独立集,由此也可以看出,这类算法虽然思想简单,但很容易陷入局部解。

4. 贪心算法3

此算法初始化顶点子集I为空集,逐步向顶点子集I内添加度最小的顶点,当存在多个度最小的顶点时,具体处理如下。

(1) 初始化顶点子集I为空集;

(2) 寻找图G内度数最小的顶点,当存在多个符合要求的顶点时,选择顶点支撑(顶点i的支撑为顶点i邻居节点的度之和)最大的顶点加入I中,若有多个最小度,最大支撑的顶点,则从中随机选择一个;

(3) 从图G内删除加入到顶点子集I内的顶点a的邻居节点以及顶点a,以及相关联的边,更新图G;

(4)  重复步骤2和3,直到当前图G内边集为空集,迭代停止,将零图内的点加入到I内,此时得到的顶点子集I是一个极大独立集;

不难理解,当一个顶点的度越大,当这个顶点加入到I中,那么此顶点的邻居节点便不能加入到I内,为了使得每次选择一个点加入到I中,同时尽可能放弃更少的点,所以会选择度最小的点。这里顶点i的支撑s(i)大小,意味着后续可以选择的顶点数目,所以选择一个顶点加入到顶点子集I内,同时也要考虑后续可供选择的顶点数目,所以这里会选择支撑大的顶点。

通过贪心算法可以得到问题的可行解,但是可行解和最优解之间的差异我们不得而知。可以借助局部搜索算法,对于可行解进行进一步的处理,在本文中局部搜索算法内有ADD以及SWAP两个操作。

若I的补集S内有顶点j满足:顶点j和I内的任意顶点均不相邻,那么可以将顶点j加入到I内,这是ADD操作。当然在一次遍历过程中可能会存在多个满足要求的顶点j,此时顶点j的选择会影响到后续可选顶点的数目。这是一个可以考虑的地方,是否能够引入其它什么度量来降低顶点j选择的随机性。

若I的补集内存在顶点k,顶点k和I内的顶点i相邻,但和I内的其余顶点均不相邻,此时可以将顶点k和顶点i进行SWAP操作,SWAP操作是为了获得更多其它的可行解。

上述ADD和SWAP操作的核心思想就是在保持可行解空间的情况下,探索更多的可行解。我个人想的是,可以有Delete操作,如果删除I内的1个顶点,顶点补集S内有两个或者更多的点可以加入到I内,那么本次Delete操作是正收益,若只是有一个顶点可加入到I内,其实就是进行了一次SWAP操作,这应该可以看作是基于交换的局部搜索算法了。

(思考:若删除I内的一个顶点,S内有两个点可以加入到I内,这一次Delete操作其实就等同于一次SWAP操作和一次ADD操作)

需要说明的是ADD和SWAP操作不是无限制地进行,此算法需要设定操作次数,如果操作了T后,解的质量没有得到提升,说明在局部搜索过程中选择的顶点j和顶点k不是很好,需要重新进行局部搜索。

你可能感兴趣的:(图论,启发式算法,贪心算法,最大独立集)