如何在Python中重塑networkx图形?

如何在Python中重塑networkx图形?,python,matplotlib,nodes,shape,networkx,Python,Matplotlib,Nodes,Shape,Networkx,因此,我创建了一种生成hasse图的非常简单(可能效率低下)的方法 问题: 我有四个维度pqrs 我想统一显示它(tesseract),但我不知道如何重塑它如何在Python中重塑networkx图形? 我见过一些人使用spring\u layout()和draw\u circular()的例子,但它的形状与我所寻找的不一样,因为它们不统一 是否有办法重塑我的图形并使其统一?(即,将我的哈斯图重塑为一个tesseract形状(最好使用nx.draw()) 下面是我目前的样子: 下面是生成N维哈

因此,我创建了一种生成hasse图的非常简单(可能效率低下)的方法

问题:

我有四个维度
p
q
r
s

我想统一显示它(tesseract),但我不知道如何重塑它如何在Python中重塑networkx图形?

我见过一些人使用
spring\u layout()
draw\u circular()
的例子,但它的形状与我所寻找的不一样,因为它们不统一

是否有办法重塑我的图形并使其统一?(即,将我的哈斯图重塑为一个tesseract形状(最好使用
nx.draw()

下面是我目前的样子:

下面是生成N维哈斯图的代码

#!/usr/bin/python

import networkx as nx
import matplotlib.pyplot as plt
import itertools

H = nx.DiGraph()

axis_labels = ['p','q','r','s']

D_len_node = {}

#Iterate through axis labels
for i in xrange(0,len(axis_labels)+1):
    #Create edge from empty set
    if i == 0:
        for ax in axis_labels:
            H.add_edge('O',ax)
    else:
        #Create all non-overlapping combinations
        combinations = [c for c in itertools.combinations(axis_labels,i)]
        D_len_node[i] = combinations
    #Create edge from len(i-1) to len(i) #eg. pq >>> pqr, pq >>> pqs
    if i > 1:
        for node in D_len_node[i]:
            for p_node in D_len_node[i-1]:
                #if set.intersection(set(p_node),set(node)): Oops
                if all(p in node for p in p_node) == True: #should be this!
                    H.add_edge(''.join(p_node),''.join(node))

#Show Plot
nx.draw(H,with_labels = True,node_shape = 'o')
plt.show() 
我想把它改造成这样:


如果有人知道制作哈斯图的简单方法,请分享一些智慧,但这不是本文的主要目的。

这是一个实用的答案,而不是纯粹的数学答案

我认为你有两个问题——一个是布局问题,另一个是网络问题

1.网络
您的网络中有太多的边,无法表示单位细分。注意我不是这里的数学专家-只是从绘图角度(matplotlib标记)得出这个结论。如果我错了,请解释

您所需的投影,例如,n=4的Hasse图页面只有4条边连接所有节点,而2位节点有6条边,3位节点有7条边。您的图形完全连接每个“级别”,即具有0
1
值的四维向量连接到具有1
1
值的所有向量,然后连接到具有2
1
值的所有向量,依此类推。这在基于维基百科答案的投影中最为明显(下图2)

2.预测 我找不到一个预先编写的算法或库来自动将4D tesseract投影到2D平面上,但我找到了几个示例。从中,您可以计算出适合您的坐标集,并将其传递到
nx.draw()
调用中

这里是一个例子——我已经包括了两个坐标集,一个看起来像上面显示的投影,一个匹配

注意-除非你改变我在上面1.中提到的内容,否则它们仍然有你的边缘结构,因此看起来与web上的示例不完全相同。以下是现有网络生成代码的外观-如果你将其与示例进行比较,你可以看到额外的边缘(例如,我不认为此
pr
应连接到
pqs

“两个立方体”投影

维基媒体示例投影


注 如果你想进入做你自己的预测的数学(并建立数学上的
pos
),你可以看看


编辑: 好奇心征服了我,我不得不寻找一种数学方法来做到这一点。我发现-主要结果是投影矩阵:

这使我开发了用于投影每个标签的函数,将包含“p”的标签视为点在“p”轴上的值为1,即我们处理的是单位细分。因此:

def construct_projection(label):
    r1 = r2 = 0.5
    theta = math.pi / 6
    phi = math.pi / 3
    x = int( 'p' in label) + r1 * math.cos(theta) * int('r' in label) - r2 * math.cos(phi) * int('s' in label)
    y = int( 'q' in label) + r1 * math.sin(theta) * int('r' in label) + r2 * math.sin(phi) * int('s' in label)
    return (x,y)
给出了一个很好的投影到一个规则的二维八角形,所有点都是不同的

这将在上面的程序中运行,只需替换

 pos[label] = example_projection_coords[i]

结果如下:


尽情地玩
r1
r2
theta
phi

通过调整
k
shell_layout
可以得到一个堆叠较少的图形。值为.48的结果是可读的,但与您的期望值不太接近。嗨@cyrbil我认为必须有一种方法来获得N维2D投影的坐标,因为nx.hype基本上就是这样rcube_图(3)如果您还有什么需要/我的答案中有什么不清楚的地方,请在评论中告诉我。否则-享受可视化的乐趣-请接受:)哇,这真是太有帮助了!这就是我一直在寻找的东西,我非常感谢你花了这么多时间。我真的认为这对社区会有难以置信的价值。“你的网络中有太多的边缘”我没注意到!只是修复了错误。应该使用all()而不是set.intersect()
 pos[label] = example_projection_coords[i]
pos[label] = construct_projection(label)