Python 生成所有可能的3连通图
有一个由Tutte和Thomassen(有限和无限图的平面性和对偶性,1979)提出的猜想是这样的 可以得到一个3连通图 通过成功地添加 边并将顶点拆分为两个 至少度的相邻顶点 三个这样的边缘连接他们 不包含在3个循环中。如果我们 应用更一般的拆分 操作(即,我们允许边缘 将两个新的顶点合并为 包含在3个循环中)然后我们可以 从K4开始,我们只需要 拆分操作,以便 生成所有3连通图 我正在尝试使用带有Python的iGraph实现最后一个声明的操作 我想定义一个函数splitVertex(g,v),取一个图g和一个顶点v,然后让它按照操作定义的所有可能方式分割v。然后我想要一个所有这些新图表的列表,我将对它们做进一步的工作 在这一点上,我有下面的函数创建两个新的顶点x和y,这将是分割后新创建的顶点Python 生成所有可能的3连通图,python,algorithm,graph,graph-theory,igraph,Python,Algorithm,Graph,Graph Theory,Igraph,有一个由Tutte和Thomassen(有限和无限图的平面性和对偶性,1979)提出的猜想是这样的 可以得到一个3连通图 通过成功地添加 边并将顶点拆分为两个 至少度的相邻顶点 三个这样的边缘连接他们 不包含在3个循环中。如果我们 应用更一般的拆分 操作(即,我们允许边缘 将两个新的顶点合并为 包含在3个循环中)然后我们可以 从K4开始,我们只需要 拆分操作,以便 生成所有3连通图 我正在尝试使用带有Python的iGraph实现最后一个声明的操作 我想定义一个函数splitVertex(g,v
def splitVertex(g,v):
numver = g.vcount()
g.add_vertices(2)
x = numver
y = numver+1
g.add_edges([(x,y)])
有人能帮我想出一个好办法来实现这个吗?我知道这会产生大量数据,但没关系,我有足够的时间;)
编辑:当然,这必须以某种方式加以控制,因为3-连通图的数量是无限的,但这不是这个问题所关心的。您的拆分操作应该更复杂一些。您需要修改用于连接到
v
的所有边,以连接到x
或y
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
def拆分顶点(g,v):
numver=g.vcount()
g、 添加_顶点(2)
x=numver
y=numver+1
g、 添加_边([(x,y)])
邻居=g.邻居(v)
g、 删除_顶点([v])
新的_图=[]
对于集合分割(邻域)中的(邻域x的邻域,邻域y的邻域):
如果len(_x的邻域_)<2:继续
如果len(y的邻域)小于2:继续
g2=g.copy()
g2.添加_边(映射(lambda邻居_of_x:[邻居_of_x,x],邻居_of_x))
g2.添加_边(映射(lambda neighbor_of_y:[neighbor_of_y,y],neighbor_of_y))
新增_图。添加(g2)
返回新的_图
其中,set\u split
应生成将邻居
拆分为两个集合的所有可能方式
然后,您需要为v
生成所有可能的选择,并将它们应用于每个图形
你可能会得到很多同构图。我想有一个更好的方法来完成这一切,我想不出有什么好办法。基于。这是完全未经测试的,但我想总的想法是可以的。此版本生成拆分,而不是一次返回所有拆分
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
来自itertools导入链,组合
def动力装置(iterable):
“返回给定iterable中元素的所有可能子集”
s=列表(iterable)
返回链。从_iterable(范围(len(s)+1)内r的组合(s,r))
def分区(iterable):
“返回将集合划分为两个子集的所有可能方法”
s=设定值(iterable)
对于动力装置中的s1:
屈服s1,s-s1
def split_顶点(图形,v1):
#请注意,您只需要一个额外的顶点,其他顶点可以使用v
v2=graph.vcount()
图.添加顶点(1)
#找到v1的邻居
neis=集合(图形邻域(v1))
#删除v1上的所有边-其中一些边将被重新添加
g、 删除_边(例如事件(v1))
#迭代neis的powerset以查找所有可能的拆分
对于分区(neis)中的set1和set2:
如果len(set1)<2或len(set2)<2:
持续
#复制原始图形
g2=g.copy()
#在v1和集合1的成员之间添加边
g2.添加_边([(v1,v3)表示集合1中的v3])
#在v2和集合2的成员之间添加边
g2.添加_边([(v2,v3)表示集合2中的v3])
#返回结果
产量g2
你听起来好像认为3连通图的数目是有限的,但实际上不是,所以你不能生成所有的。证明:取两个3连通图,在它们之间添加3条合适的边,就得到了一个新的3连通图。重复ad infinum。@THC4k:好的,是的;但是对于给定的具有n个节点的3连通图,如何生成所有3连通n+1节点的子体呢?我一直在纸上画草图,我也有点挠头!我不认为3-连通图的数目是有限的,但是n个顶点上的3-连通图的数目肯定是有限的。这能从K_4生成5个顶点上的轮图吗?K_4是一个三次图,邻域数始终为3,在这种情况下,分区将始终导致某些集合小于2,这将导致函数不返回任何内容。