【问题标题】:Python, networkx [closed]Python,networkx [关闭]
【发布时间】:2012-02-07 09:04:16
【问题描述】:

我需要帮助,因为我不是编程专家。

对于具有 n 个节点和 E 个边的给定图,我如何绘制平面图(如果可以在平面中绘制且没有边交叉的图,则称该图是平面图)。然后翻转边缘以获得另一个平面图。(for循环,直到我们获得所有可能性)。

提前致谢,感谢您的帮助。

一年


>>>#visualize with pygraphviz
    A=pgv.AGraph()
    File "<stdin>", line 6
    A=pgv.AGraph()
    ^
    SyntaxError: invalid syntax
>>> A.add_edges_from(G.edges())
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    NameError: name 'A' is not defined
>>> A.layout(prog='dot')
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    NameError: name 'A' is not defined
>>> A.draw('planar.png')
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    NameError: name 'A' is not defined

【问题讨论】:

标签: python graph networkx


【解决方案1】:

您的问题涉及几个计算难题。

首先,一些理论。如果图 G 是平面的,则 G 的每个子图都是平面的。从 G 翻转边缘(具有e 边缘)将给出2^e-1 平面子图(如果我们不关心连通性),这是指数的(即巨大的和“坏的”)。可能,您希望找到“最大”平面子图。

如果您想绘制看起来也像平面的平面图,则为 computationally hard,即知道存在边不交叉的图形表示是一回事,而找到这样的表示则是另一回事。

实施。似乎 networkx 没有检查图形是否为平面的功能。其他一些使用图表的包有(例如,sageg.is_planar() 函数,其中g 是一个图表对象)。下面,我基于Kuratowski theorem,用networkx写了一个“朴素”(肯定有更高效的方法)平面性检查。

import pygraphviz as pgv
import networkx as nx
import itertools as it
from networkx.algorithms import bipartite

def is_planar(G):
    """
    function checks if graph G has K(5) or K(3,3) as minors,
    returns True /False on planarity and nodes of "bad_minor"
    """
    result=True
    bad_minor=[]
    n=len(G.nodes())
    if n>5:
        for subnodes in it.combinations(G.nodes(),6):
            subG=G.subgraph(subnodes)
            if bipartite.is_bipartite(G):# check if the graph G has a subgraph K(3,3)
                X, Y = bipartite.sets(G)
                if len(X)==3:
                    result=False
                    bad_minor=subnodes
    if n>4 and result:
        for subnodes in it.combinations(G.nodes(),5):
            subG=G.subgraph(subnodes)
            if len(subG.edges())==10:# check if the graph G has a subgraph K(5)
                result=False
                bad_minor=subnodes
    return result,bad_minor

#create random planar graph with n nodes and p probability of growing
n=8
p=0.6
while True:
    G=nx.gnp_random_graph(n,p)
    if is_planar(G)[0]:
        break
#visualize with pygraphviz
A=pgv.AGraph()
A.add_edges_from(G.edges())
A.layout(prog='dot')
A.draw('planar.png')

编辑2如果你在使用 pygraphviz 时遇到问题,尝试使用 networkx 进行绘制,也许你会发现结果还可以。因此,不要尝试“使用 pygraphviz 进行可视化”块,而是尝试以下操作

import matplotlib.pyplot as plt
nx.draw(G)
# comment the line above and uncomment one of the 3 lines below (try each of them):
#nx.draw_random(G)
#nx.draw_circular(G)
#nx.draw_spectral(G)
plt.show()

编辑结束

结果如下所示。

你看到图片上有一个交叉点(但图形是平面的),它实际上是一个很好的结果(不要忘记这个问题在计算上很困难),pygraphviz 是Graphviz 的包装器,它使用启发式算法。在A.layout(prog='dot') 行中,您可以尝试将 'dot' 替换为 'twopi'、'neato'、'circo' 等,看看是否能获得更好的可视化效果。

编辑。让我们也考虑一下您关于平面子图的问题。 让我们生成一个非平面图:

while True:
    J=nx.gnp_random_graph(n,p)
    if is_planar(J)[0]==False:
        break

我认为找到平面子图的最有效方法是从“坏小调”(即 K(5) 或 K(3,3))中消除节点。这是我的实现:

def find_planar_subgraph(G):
    if len(G)<3:
        return G
    else:
        is_planar_boolean,bad_minor=is_planar(G)
        if is_planar_boolean:
            return G
        else:
            G.remove_node(bad_minor[0])
            return find_planar_subgraph(G)

行动:

L=find_planar_subgraph(J)
is_planar(L)[0]
>> True

现在您有了非平面图 G 的平面子图 L(networkx 图对象)。

【讨论】:

  • Planarity testing 并不难。
  • Max 是对的,NetworkX 不包含用于平面测试和绘图的代码。但是有一个用于 Boyer 的 C 平面代码的包装器,它可以与 NetworkX 顺利互操作,并包含 is_planar() 和绘图函数。代码见bitbucket.org/hagberg/nxtools-planarity,尤其是bitbucket.org/hagberg/nxtools-planarity/src/ee97b7dc9807/…的示例
  • 可能是我见过的最好的 SO 答案之一……干得好
  • 计算平面图的嵌入可以在线性时间内完成。参见例如Hopcroft, Tarjan '74。困难的是嵌入一个非平面图,以使边缘交叉的数量最小化。
  • 对不起,但这个答案是完全错误的,我不明白很多赞成票。首先,正如其他人已经指出的那样,找到平面嵌入可以在线性时间内完成,而且计算起来并不困难。第二,正如其他人已经指出的那样,您的算法仅检查 K5 和 K3,3 子图,但不检查平面性所需的 K5 和 K3,3 次要子图。请编辑您的答案,以免混淆未来的读者!!!
猜你喜欢
  • 2014-05-09
  • 2011-08-06
  • 2021-05-14
  • 2019-07-13
  • 1970-01-01
  • 1970-01-01
  • 2013-03-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多