解决图着色问题 python代码实现

  一、前言

  关于本文中用到的这种图着色解决方法,不知道有没前人提出过。如果说没人提出过,那么就算是一个新的解决方法吧,具体性能对比没深入研究,但是求出的解基本是和Graph Coloring Instances网站里面的最优解一样的。

  我们都知道,很多问题都可以转化成图着色问题来进行解决,所以本文的例子直接是无向图。

  二、解决思路  

  不太成熟的想法:

  要使得相邻点的颜色不同,着色方案有很多种,那么究竟哪种着色方案使用的颜色最少呢?

  首先最开始看到这个问题时,我最开始的思路是每次用尽量少的颜色给尽量多的点上色。

  

->->->->->

  以上是个简单的图,我选用的步骤为:

  1、找出度最大的顶点2、3、5(度均为4)。

  2、对2着色C1,然后遍历相邻点

  3、给1着色C2

  4、给3着色C2,和1冲突,着色C3

  5、给5着色C2,不冲突

  6、给4着色C2,与5冲突,着色C3

  7、给4着色C1,不冲突

  从一次性上完一种颜色入手:

  本来是想实现上一个想法的,但是在梳理的过程中,有一个新的想法,即是通过与以前运筹学课程上学过的方法结合,较为高效且高质量地解决问题。

  步骤如下:

  步骤一、给未上色点集中度最大的顶点上色Ci,生成可同色点集,为与该顶点不相邻且未上色的点的集合

  步骤二、遍历可同色点集,给点集中的点上色Ci,每上完一个点就生成一次可同色点集,为与上Ci点不相邻且未上色的点的集合,直到可同色点集为空

  步骤三、更新未上色点集,i=i+1,回到步骤一

  例:以下是myciel3.col数据的图,求最少能上几种颜色。

  

  邻接矩阵为

  

   每个顶点的度为4、4、4、4、4、3、3、3、3、3、5,度最大的顶点为第11个顶点。

  1、给V11上色C1,可同色集为{V1,V2,V3,V4,V5}

  2、给V1上色C1,可同色集为{V3,V5}

   3、给V3上色C1,可同色集为{}

  4、给V2上色C2,可同色集为{V4,V7,V9,V10}  

   5、给V4上色C2,可同色集为{V7,V9}

  6、给V7上色C2,可同色集为{V9}

  7、给V9上色C2,可同色集为{}

   8、给V5上色C3,可同色集为{V6,V8,V10}

  9、给V6上色C3,可同色集为{V10}

  10、给V10上色C3,可同色集为{}

  11、给V8上色C4,可同色集为{}

  上色后的图:

  

  颜色使用了4种,和已知最优解一样。

 

  三、python代码实现

  

 1 def getAdjMatrix(path):
 2     edge = []
 3     pointNum = 0
 4     with open(path, 'r') as fp:
 5         for line in fp.readlines():
 6             if line.startswith('p'):
 7                 pointNum = int(line.split()[2])
 8                 for i in range(pointNum):
 9                     edge.append([0 for i in range(pointNum)])
10             if line.startswith('e') and pointNum > 0:
11                 edge[int(line.split()[1]) - 1][int(line.split()[2]) - 1] = 1
12                 edge[int(line.split()[2]) - 1][int(line.split()[1]) - 1] = 1
13     return edge, pointNum
14 
15 
16 def main():
17     edge, pointNum = getAdjMatrix(r'F:\timFilm\test.txt')
18     print('')
19     for i in edge:
20         print('    ', end='')
21         for j in i:
22             print(j, end='\t\t')
23         print('\n')
24     colorNum = 0
25     disabled = []
26 
27     # 初始化color列表,用以记录每个顶点的着色情况
28     color = []
29     for i in range(pointNum):
30         color.append(0)
31     edgeNum = [sum(e) for e in edge]
32     for k in range(pointNum):
33         # 获取顶点最大度的索引值
34         maxEdgePoint = [i for i in range(pointNum) if edgeNum[i] == max(edgeNum) and edgeNum[i] != 0]
35         # 遍历最大度
36         for p in maxEdgePoint:
37             if p not in disabled:
38                 # 选取还未着色且度最大的点p开始着色
39                 color[p] = colorNum + 1
40                 disabled.append(p)
41                 edgeNum[p] = 0
42                 # temp用于查找该颜色可用来着色的下一个顶点
43                 temp = edge[p]
44                 for i in range(pointNum):
45                     if i not in disabled:
46                         if temp[i] == 0:
47                             # 为不冲突的顶点着色
48                             color[i] = colorNum + 1
49                             disabled.append(i)
50                             edgeNum[i] = 0
51                             # 增加当前颜色的禁忌点
52                             temp = [x + y for (x, y) in zip(edge[i], temp)]
53                 # 需要新颜色
54                 colorNum = colorNum + 1
55 
56         # 每个顶点都已经着色
57         if 0 not in color:
58             break
59     print(color)
60     print(colorNum)
61 
62 
63 main()

 

 

   

posted on 2019-05-10 17:01  桩子101  阅读(8802)  评论(10编辑  收藏  举报