Clique问题算法设计

时间:2009-02-04 01:57:08

标签: algorithm graph-theory clique-problem

我的算法类中的一个任务是设计一个详尽的搜索算法来解决clique问题。也就是说,给定大小 n 的图表,该算法应该确定是否存在大小 k 的完整子图。我想我已经得到了答案,但我不禁想到它可以改进。这就是我所拥有的:

版本1

输入:由数组A [0,... n -1]表示的图形,子图的大小 k 找到。

输出:如果存在子图,则为True,否则为False

算法(在类似python的伪代码中):

def clique(A, k):
    P = A x A x A //Cartesian product
    for tuple in P:
        if connected(tuple):
            return true
    return false

def connected(tuple):
    unconnected = tuple
    for vertex in tuple:
        for test_vertex in unconnected:
            if vertex is linked to test_vertex:
                remove test_vertex from unconnected
    if unconnected is empty:
        return true
    else:
        return false

版本2

输入:大小为n乘n的邻接矩阵,k为要查找的子图的大小

输出:A中大小为k的所有完整子图。

算法(这次是在函数/ Python伪代码中):

//Base case:  return all vertices in a list since each
//one is a 1-clique
def clique(A, 1):
    S = new list
    for i in range(0 to n-1):
        add i to S
    return S

//Get a tuple representing all the cliques where
//k = k - 1, then find any cliques for k
def clique(A,k):
    C = clique(A, k-1)
    S = new list
    for tuple in C:
        for i in range(0 to n-1):
            //make sure the ith vertex is linked to each
            //vertex in tuple
            for j in tuple:
                if A[i,j] != 1:
                    break
            //This means that vertex i makes a clique
            if j is the last element:
                newtuple = (i | tuple) //make a new tuple with i added
                add newtuple to S
    //Return the list of k-cliques
    return S

有人有任何想法,意见或建议吗?这包括我可能错过的错误以及使其更具可读性的方法(我不习惯使用很多伪代码)。

版本3

幸运的是,在提交作业之前,我和我的教授谈过了。当我向他展示我写的伪代码时,他微笑着告诉我,我做了太多的工作 way 。首先,我没有提交伪代码;我只需证明我理解了这个问题。还有两个,他想要蛮力解决方案。所以我上交的内容看起来像这样:

输入:图表G =(V,E),要找到的集团的大小 k

输出:如果clique确实存在则为True,否则为false

算法

  1. 找到笛卡尔积V k
  2. 对于结果中的每个元组,测试每个顶点是否彼此连接。如果全部已连接,则返回true并退出。
  3. 返回false并退出。
  4. 更新:添加了第二个版本。虽然我没有添加任何花哨的动态编程(我知道),但我认为这会越来越好。

    更新2 :添加了更多评论和文档,以使版本2更具可读性。这可能是我今天转的版本。谢谢大家的帮助!我希望我能接受不止一个答案,但我接受了最能帮助我的人的答案。我会让你们知道我的教授的想法。

5 个答案:

答案 0 :(得分:8)

一些意见:

  • 你只需要考虑n-choose-k顶点组合,而不是所有k元组(n ^ k)。
  • connected(tuple)看起来不正确。你不需要在循环中重置unconnected吗?
  • 正如其他人所建议的那样,有更好的方法可以强制执行此操作。考虑以下递归关系:如果前k个顶点形成一个clique并且顶点(k + 1)与每个前k个顶点相邻,则A(k + 1) - 子图是一个集团。您可以在两个方向上应用此方法:
    • 从1-clique开始,逐渐扩大集团,直到获得所需的大小。例如,如果m是当前clique中的最大顶点,请尝试添加顶点{m + 1,m + 2,...,n-1}以获得一个顶点更大的clique。 (这类似于深度优先树遍历,其中树节点的子节点是大于当前集团中最大顶点的顶点。)
    • 从所需大小的子图开始,并使用递归关系检查它是否为clique。设置memoization表以存储结果。
  • (实现建议)使用邻接矩阵(0-1)表示图中的边。
  • (初始修剪)丢弃程度小于k的所有顶点。

答案 1 :(得分:2)

我曾经使用算法来查找图表中的所有最大派系,这与您的问题类似。我这样做的方式是基于这篇论文:http://portal.acm.org/citation.cfm?doid=362342.362367 - 它描述了一个回溯解决方案,我发现它非常有用作为指南,尽管我从那篇论文中做了很多改变。虽然你需要订阅才能获得,但我认为你的大学将有一个可用。

关于那篇论文的一件事是,我真的认为他们应该将“未设置”命名为“已经考虑过的设置”,因为它太混乱了。

答案 2 :(得分:2)

算法“对于每个k元组的顶点,如果它是一个集团,那么返回true”肯定是有效的。然而,这是一种蛮力,这可能不是算法课程所寻求的。相反,请考虑以下事项:

  1. 每个顶点都是1-clique。
  2. 对于每个1-clique,连接到1-clique中的顶点的每个顶点都有助于2-clique。
  3. 对于每个2-clique,连接到2-clique中每个顶点的每个顶点都会产生3-clique。
  4. ...
  5. 对于每个(k-1)-clique,连接到(k-1)clique中每个顶点的每个顶点都有助于k-clique。
  6. 这个想法可能会带来更好的方法。

答案 3 :(得分:1)

答案 4 :(得分:0)

令人惊讶的是,输入内容的问题将向您展示您刚刚撰写的内容。这一行:

P = A x A x A  //Cartesian product

应该是这样的:

P = A k //笛卡儿积

  

你是什么意思A ^ k?你正在服用基质产品吗?如果是这样,A是一个邻接矩阵(你说它是一个n + 1个元素的数组)?

在setbuilder表示法中,它看起来像这样:

  

P = {(x0,x1,... xk)| x0∈A和x1∈A......和xk∈A}

它基本上只是A的笛卡尔乘积k次。在纸面上,我写下来,因为k是A的上标(我刚才想到如何使用降价来做到这一点)。

另外,A只是每个顶点的数组而不考虑邻接。