摘要: 转载请注明来自stanlysheng——talk is cheap, show me your code。http://www.cnblogs.com/stanly/ 。谢谢。此文我也在CSDN发过。

最近在学习子图同构算法。什么是子图同构,看这里-->图论。在图论的维基百科中有子图同构的描述。

子图同构一直是图论中比较重要的一个问题,经过各位大牛长时间的学习和研究,发现求解子图同构是一个NP完全问题。什么是NP完全问题,可以戳这里--->NP完全。

在经过不断地搜索和阅读论文,发现了不少论文都在讨论子图同构算法。出现得比较多并且很多人都知道并认可的,有这么几种算法:Ullmann算法、Nauty算法、SD算法、VF算法以及在VF算法上进行改进的VF2算法。其中Ullmann算法应该是最早提出的可以找到子图同构的算法。因此现在学习图论如果设计到同构,虽然不会用ullmann算法,但是一般都会以其作为对子图同构的基础进行了解和学习。中间三种算法尚未研究,以后可能会看,因为时间和研究原因我的重点在第一个ullmann和最后的公认最好的VF2算法。

在最坏情况下,ullmann算法的时间复杂度与图中节点数目的指数成正比。ullmann算法以深度优先的方式进行搜索,搜索过程表示为一个布尔矩阵。当节点不匹配时则回溯到最近匹配的节点,寻找其他的搜索方向。同时,算法还会检查匹配点对的邻接点的匹配情况,尽可能早的识别出不可匹配的节点。提高算法的效率。

先介绍深度优先的简单穷举方法,这个阶段不包含上面说的检查匹配点对的邻接点的匹配情况(即refine procedure),将在后面我写好代码之后再发。

此搜索方法其实是深度优先遍历两图的关联矩阵,来找到满足其子图同构的关联矩阵。

对于给定的两个图,是从节点数目大的那个图中寻找部分节点和边,和节点数目小的图是同构的。

图G1=<V1,E1>,G2=<V1,E1>,G1 和G2 的节点数分别为p1和p2。他们的邻接矩阵表示分别为A=[aij]和B=[bij]。

该算法要寻找的同构关系表现为寻找两图的一个关联矩阵M,这是一个p1*p2的矩阵,其元素mij表示G1的第 i 个节点和G2的第 j 个节点是否对应。因此这个矩阵的限制为:每行只有一个1,而每列最多只有一个1 。因此mij==1表示G1的第 i 个节点和G2的第 j 个节点对应。否则不对应。

条件(1)判定:当找到这样一个M`的时候我们进行如下操作得到另一个p1*p1的矩阵C,定义C为:C=M`(M`B)T,后面的T表示(M`B)做转置。即M`乘以[(M`B)的转置]得到C,如果对于每一个i , j 都属于(1,p1)都满足当aij == 1 时 有cij == 1。那么我们就称此时的矩阵M`标识了G1 到G2子图的一个同构。

初始化M的时候,遵循下面的原则:

如果G2的第 j 个节点的度大于或者等于G1的第 i 个节点的度(表示可能匹配但是不一定),则mij = 1。否则等于0。(此原则是针对无向图,如果是对于有向图则有出度和入度均要大于等于,对于节点可能有其他属性的情况也是类似,保证G2的属性或者条件强于G1即可)。

所以深度优先搜索的就是将M0深度遍历找到所有的满足条件(1)判定的矩阵。

深度优先搜索中,使用d来表示搜索中的层(第几行),使用一个大小为p2的向量F{F1,F2,…F(x)…,F(p2)}(数组表示)来表示哪一列被使用了。比如F[2]==1表示在搜索中第二列被使用了,如果F[2]==0则表示没被使用。同样还使用一个大小为p1的向量H{H1,H2,……,H(p1)}来表示在哪一层使用了哪一列。H[d] = k表示在层d中使用了第k列。

除此之外,还需要一个三维矩阵来记录每层变化过的M`,保证回溯的时候可以回到上一层。第一维长度和d大小一样。二维三维即为M的维度。

Ullmann算法的提出者Ullmann的论文,比较早论文写得挺难懂的。他的伪代码有些需要改动。伪代码如下:

step1

construct  M0,M=M0,d=0, H[0] = 0;

for element in F set element = 0

if  m has a row that all zero  return; (这一步可以放在refine里面)

step2

if there are no value of j such  that  m[d][j] && F[j] = 0  then goto step7

matrixlist[d] = M

if d = 0 then k = H[0] else k = 0

step3

if  matrixlist[d][d][k] = 0 or F[k] == 1

then  if k < p2-1 then k+=1 and goto step3 else goto step7

else  for all j != k set m[d][j] = 0;

step4      if d < p1 then goto step6 else   ( H[d] = k and use condition(1) and giveoutput if an isomorphism is found )

step5

if there is no j > k such that m[d][j] = 1 and F[j] = 0 then k += 1 and  goto step7

else k += 1 and goto step3

step6

H[d] = k

F[k] = 1

d +=1

goto step2

step7

if d ==0 then terminate algorithm

if k < p2-1 then copy matrixlist[d]  to M and goto step5

else  d= d-1     k = H[d]    F[k]=0 copy matrixlist[d]  to M and goto step5

以上就是算法程序的伪代码。具体实现还是需要自己动手。主要流程就是这样的,缺少的就是condition(1)的判断(包含矩阵的转置和两矩阵的乘法)。很简单,自己加上。之后学习完refine procedure之后会再加上。暂时就这么多。

国内真心很少有这个问题的资料,一些论文都是应用子图同构算法,极少有详细讲这些算法的。

摘要: 转载请注明来自stanlysheng——talk is cheap, show me your code。http://www.cnblogs.com/stanly/ 。谢谢。

转载于:https://www.cnblogs.com/stanly/p/ullmann_algorithm.html

子图同构算法——Ullmann算法(1)不包含refine procedure的简单穷举算法。相关推荐

  1. 旅行商问题穷举算法c语言,什么是旅行商问题——算法NP、P、NPC知识

    旅行商问题 旅行商问题所描述的是这样一个场景: 有一个商品推销员,要去若干个城市推销商品.该推销员从一个城市出发,需要经过所有城市后,回到出发地.每个城市之间都有道路连通,且距离各不相同,推销员应该如 ...

  2. 百钱百鸡php穷举法,PHP经典题:百钱百鸡问题(穷举算法)

    PHP经典题:百钱百鸡问题(穷举算法) 百钱百鸡问题: 已知:公鸡5元一只,母鸡3元一只,小鸡一元3只 现用100元钱买了100只鸡,问:公鸡母鸡小鸡各几只? --请考虑尽可能高效的方法 思路: 如果 ...

  3. 穷举算法——奶牛碑文(cow)

    - 穷举算法--奶牛碑文(cow) 题目描述 小伟暑假期间到大草原漫游,在一块石头上发现了一些有趣的碑文.碑文似乎是一个神秘古老的语言,只包括三个大写字母 C.O 和W. 尽管小伟看不懂,但是令他高兴 ...

  4. 简析穷举算法,及其简单应用

    简析穷举算法,及其简单应用 穷举概述 穷举法又称列举法,其基本思想是逐一列举问题所涉及的所有情况. 穷举法常用于解决"是否存在"或"有多少种可能"等问题. 应用 ...

  5. 3388=24及24点游戏的穷举算法

    偶尔看到一题:用3 3 8 8 四个数和加减乘除组合得出24,前提是用完这四个数,几年没好好思考了,偶算了半天没答案,就写了个穷举算法,呵呵,貌似结果只有一种啊,各位兄台还有其它答案么? packag ...

  6. java穷举密码_穷举算法和递推算法(Java)

    穷举算法 概念: 最简单算法,依赖计算机的强大计算能力穷尽每一种可能的情况.穷举算法效率不高,但是适合一些没有明显规律可循的场合. 思想: 在使用穷举算法时,需要明确问题答案的范围,这样才可能在指定范 ...

  7. 穷举算法(鸡兔同笼问题)

    穷举算法的基本思想就是从所有可能的情况中搜索正确的答案,其执行步骤如下: (1)对于一种可能的情况,计算其结果. (2)判断结果是否满足要求,如果不满足则进行执行第(1)步来搜索下一个可能的情况:如果 ...

  8. lru算法实现 redis_使用数组与双向链表实现一个简单的LRU算法

    什么是LRU算法? redis大家都玩过吧,你们好奇redis内存数据存满之后会发生什么吗?抛出异常?禁止使用?还是删除数据?其实redis设计了一种内润淘汰机制. noeviction(默认策略): ...

  9. 【算法学习】找素数的几种算法: 简单穷举, 埃氏筛法, 欧氏筛法, 从O(n2)到O(n)

    文章简介 本文记录寻找素数的几种算法, 本文中的O()没有指明默认表示时间复杂度 代码使用Java 目录 文章简介 正文 穷举计数法(判断O(n)) 优化: 布尔+break(判断 小于O(n)) 优 ...

最新文章

  1. jmeter提取多个变量的多个值_jmeter用一个正则提取器提取多个值的两种方法
  2. scrapy-redis组件写分布式爬虫实战
  3. IOS-Core Data的使用
  4. JAVA数据库编程(JDBC技术)-入门笔记
  5. wether.html5.qq.com,weather.html
  6. 这一次,腾讯用AI让手语“发声”
  7. mybatis多个foreach_使用 Mybatis 的 foreach 批量模糊 like 查询及批量插入
  8. 学完之后,有什么证书发吗?要另外收费吗?收费多少? 学员每天的上课时间是怎样安排的?...
  9. 儿童节教你用 Python 画出童年回忆
  10. NoiseAsh Rule Tec All Collection for Mac - 无源均衡器
  11. Unity GC垃圾回收
  12. python复数类型输出实部和虚部_python 获取复数的实部虚部
  13. SAP中通过历史记录查询追溯BOM工程变更处理物料升级未生效问题实例
  14. 查看网页最后修改时间方法以及原理简介
  15. U8字符串(u8前缀)的作用
  16. 软件测试之——性能测试(超级详细)这些你都知道吗?
  17. 对口计算机平面设计考纲,云南体育运动职业技术学院2014年对口招生专业技能测试工作方案...
  18. 最全的软件测试面试题(含答案)
  19. 报童、钱包和迪米特法则(设计模式迪米特原则经典论文翻译)
  20. CS、DS、SS、ES

热门文章

  1. 【Linux】一步一步学Linux——free命令(80)
  2. pro android学习笔记,Pro Android学习笔记(六八):HTTP服务(2):HTTP POST-Go语言中文社区...
  3. jmeter聚合报告如何添加单位_JMeter聚合报告(Aggregate Report)理解
  4. 新疆大学OJ(ACM) 1099: 数列有序!
  5. 51nod 1270 数组的最大代价 思路:简单动态规划
  6. 最长上升子序列—leetcode300
  7. linux中fork和exec
  8. Linux中的进程组及会话
  9. github生成密钥
  10. 第四章MPU6000传感器驱动解析