子图同构算法——Ullmann算法(1)不包含refine procedure的简单穷举算法。
摘要: 转载请注明来自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的简单穷举算法。相关推荐
- 旅行商问题穷举算法c语言,什么是旅行商问题——算法NP、P、NPC知识
旅行商问题 旅行商问题所描述的是这样一个场景: 有一个商品推销员,要去若干个城市推销商品.该推销员从一个城市出发,需要经过所有城市后,回到出发地.每个城市之间都有道路连通,且距离各不相同,推销员应该如 ...
- 百钱百鸡php穷举法,PHP经典题:百钱百鸡问题(穷举算法)
PHP经典题:百钱百鸡问题(穷举算法) 百钱百鸡问题: 已知:公鸡5元一只,母鸡3元一只,小鸡一元3只 现用100元钱买了100只鸡,问:公鸡母鸡小鸡各几只? --请考虑尽可能高效的方法 思路: 如果 ...
- 穷举算法——奶牛碑文(cow)
- 穷举算法--奶牛碑文(cow) 题目描述 小伟暑假期间到大草原漫游,在一块石头上发现了一些有趣的碑文.碑文似乎是一个神秘古老的语言,只包括三个大写字母 C.O 和W. 尽管小伟看不懂,但是令他高兴 ...
- 简析穷举算法,及其简单应用
简析穷举算法,及其简单应用 穷举概述 穷举法又称列举法,其基本思想是逐一列举问题所涉及的所有情况. 穷举法常用于解决"是否存在"或"有多少种可能"等问题. 应用 ...
- 3388=24及24点游戏的穷举算法
偶尔看到一题:用3 3 8 8 四个数和加减乘除组合得出24,前提是用完这四个数,几年没好好思考了,偶算了半天没答案,就写了个穷举算法,呵呵,貌似结果只有一种啊,各位兄台还有其它答案么? packag ...
- java穷举密码_穷举算法和递推算法(Java)
穷举算法 概念: 最简单算法,依赖计算机的强大计算能力穷尽每一种可能的情况.穷举算法效率不高,但是适合一些没有明显规律可循的场合. 思想: 在使用穷举算法时,需要明确问题答案的范围,这样才可能在指定范 ...
- 穷举算法(鸡兔同笼问题)
穷举算法的基本思想就是从所有可能的情况中搜索正确的答案,其执行步骤如下: (1)对于一种可能的情况,计算其结果. (2)判断结果是否满足要求,如果不满足则进行执行第(1)步来搜索下一个可能的情况:如果 ...
- lru算法实现 redis_使用数组与双向链表实现一个简单的LRU算法
什么是LRU算法? redis大家都玩过吧,你们好奇redis内存数据存满之后会发生什么吗?抛出异常?禁止使用?还是删除数据?其实redis设计了一种内润淘汰机制. noeviction(默认策略): ...
- 【算法学习】找素数的几种算法: 简单穷举, 埃氏筛法, 欧氏筛法, 从O(n2)到O(n)
文章简介 本文记录寻找素数的几种算法, 本文中的O()没有指明默认表示时间复杂度 代码使用Java 目录 文章简介 正文 穷举计数法(判断O(n)) 优化: 布尔+break(判断 小于O(n)) 优 ...
最新文章
- jmeter提取多个变量的多个值_jmeter用一个正则提取器提取多个值的两种方法
- scrapy-redis组件写分布式爬虫实战
- IOS-Core Data的使用
- JAVA数据库编程(JDBC技术)-入门笔记
- wether.html5.qq.com,weather.html
- 这一次,腾讯用AI让手语“发声”
- mybatis多个foreach_使用 Mybatis 的 foreach 批量模糊 like 查询及批量插入
- 学完之后,有什么证书发吗?要另外收费吗?收费多少? 学员每天的上课时间是怎样安排的?...
- 儿童节教你用 Python 画出童年回忆
- NoiseAsh Rule Tec All Collection for Mac - 无源均衡器
- Unity GC垃圾回收
- python复数类型输出实部和虚部_python 获取复数的实部虚部
- SAP中通过历史记录查询追溯BOM工程变更处理物料升级未生效问题实例
- 查看网页最后修改时间方法以及原理简介
- U8字符串(u8前缀)的作用
- 软件测试之——性能测试(超级详细)这些你都知道吗?
- 对口计算机平面设计考纲,云南体育运动职业技术学院2014年对口招生专业技能测试工作方案...
- 最全的软件测试面试题(含答案)
- 报童、钱包和迪米特法则(设计模式迪米特原则经典论文翻译)
- CS、DS、SS、ES
热门文章
- 【Linux】一步一步学Linux——free命令(80)
- pro android学习笔记,Pro Android学习笔记(六八):HTTP服务(2):HTTP POST-Go语言中文社区...
- jmeter聚合报告如何添加单位_JMeter聚合报告(Aggregate Report)理解
- 新疆大学OJ(ACM) 1099: 数列有序!
- 51nod 1270 数组的最大代价 思路:简单动态规划
- 最长上升子序列—leetcode300
- linux中fork和exec
- Linux中的进程组及会话
- github生成密钥
- 第四章MPU6000传感器驱动解析