【问题标题】:Generating all possible 3-connected graphs生成所有可能的 3 连通图
【发布时间】:2011-05-30 18:21:18
【问题描述】:

Tutte 和 Thomassen 有一个猜想(有限和无限图的平面性和对偶性,1979 年)这样说

可以得到一个3-连通图 通过连续添加一个轮子 边并将一个顶点一分为二 至少有度数的相邻顶点 三个这样的边缘连接它们 不包含在 3 个循环中。要是我们 应用更一般的拆分 操作(即,我们允许边缘 加入两个新顶点 包含在 3 个循环中),那么我们可以 从 K_4 开始,我们只需要 分裂操作,以 生成所有 3 连通图。

我正在尝试使用 iGraph 和 Python 来实现最后陈述的操作。

我想定义一个函数 splitVertex(g,v),获取一个图 g 和一个顶点 v,然后让它以操作定义的所有可能方式拆分 v。然后我想要一个所有这些新图表的列表,我会在它们上做一些进一步的工作。

此时,我有以下函数创建两个新顶点x和y,这将是分割后新创建的顶点。

def splitVertex(g,v):
    numver = g.vcount()

    g.add_vertices(2)

   x = numver
    y = numver+1

    g.add_edges([(x,y)])

有人可以帮我用一个很好的方法来实现它吗?我知道这会产生大量数据,但没关系,我有足够的时间;)

编辑:当然,这必须以某种方式控制,因为 3 连通图的数量是无限的,但这不是这个问题所关心的。

【问题讨论】:

  • 您听起来好像认为 3 连通图的数量是有限的,但事实并非如此,因此您无法生成 all。证明:取两个 3 连通图,在它们之间添加 3 条合适的边,你就有了一个新的 3 连通图。无限重复。
  • @THC4k:嗯,是的;但是对于给定的具有 n 个节点的 3 连通图,如何生成所有 3 连通的 n+1 节点后代?我一直在纸上画出来,我也有点摸不着头脑!
  • 我不认为3-连通图的数量是有限的,但是n个顶点上的3-连通图的数量肯定是有限的。

标签: python algorithm graph graph-theory igraph


【解决方案1】:

您的拆分操作应该更复杂一些。您需要将所有用于连接到v 的边修改为连接到xy

def splitVertex(g,v):
  numver = g.vcount()
  g.add_vertices(2)
  x = numver
  y = numver+1
  g.add_edges([(x,y)])

  neighbors = g.neighbors(v)
  g.delete_vertices([v])

  new_graphs = []
  for (neighbors_of_x, neighbors_of_y) in set_split(neighbors):
    if len(neighbors_of_x) < 2: continue
    if len(neighbors_of_y) < 2: continue
    g2 = g.copy()
    g2.add_edges(map(lambda neighbor_of_x: [neighbor_of_x, x], neighbors_of_x))
    g2.add_edges(map(lambda neighbor_of_y: [neighbor_of_y, y], neighbors_of_y))
    new_graphs.add(g2)
  return new_graphs

set_split 应该生成将neighbors 分成两组的所有可能方式。

然后您需要为v 生成所有可能的选择并将它们应用到每个图表。

您可能会得到很多同构图。我想有一个更好的方法来做这一切,我想不出它。

【讨论】:

    【解决方案2】:

    基于Keith's solution。这是完全未经测试的,但我想一般的想法是可以的。此版本生成拆分而不是一次返回所有拆分。

    from itertools import chain, combinations
    
    def powerset(iterable):
        "Returns all the possible subsets of the elements in a given iterable"
        s = list(iterable)
        return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
    
    def partition(iterable):
        "Returns all the possible ways to partition a set into two subsets"
        s = set(iterable)
        for s1 in powerset(s):
            yield s1, s-s1
    
    def split_vertex(graph, v1):
        # Note that you only need one extra vertex, you can use v for the other
        v2 = graph.vcount()
        graph.add_vertices(1)
    
        # Find the neighbors of v1
        neis = set(graph.neighbors(v1))
    
        # Delete all the edges incident on v1 - some of them will be re-added
        g.delete_edges(g.incident(v1))
    
        # Iterate over the powerset of neis to find all possible splits
        for set1, set2 in partition(neis):
            if len(set1) < 2 or len(set2) < 2:
                continue
    
            # Copy the original graph
            g2 = g.copy()
    
            # Add edges between v1 and members of set1
            g2.add_edges([(v1, v3) for v3 in set1])
    
            # Add edges between v2 and members of set2
            g2.add_edges([(v2, v3) for v3 in set2])
    
            # Return the result
            yield g2
    

    【讨论】:

    • 这是否能够在 K_4 的 5 个顶点上生成轮图? K_4 是一个三次图,邻居数总是 3,这种情况下的分区总是会导致某些集合小于 2,这会导致函数不返回任何东西。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-07
    • 1970-01-01
    相关资源
    最近更新 更多