如何在Python中重塑网络图?

O.r*_*rka 25 python shape matplotlib nodes networkx

因此,我创建了一种非常天真(可能效率低下)的生成哈希图的方法.

题:

我有4个维度... .p q r s

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

我见过的人使用一些例子spring_layout()draw_circular(),但它不能在我要找的,因为他们不是统一的方式塑造.

有没有办法重塑我的图形并使其统一?(即将我的hasse图重塑为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() 
Run Code Online (Sandbox Code Playgroud)

我想像这样重塑它: 在此输入图像描述

如果有人知道更简单的方法制作Hasse Diagrams,请分享一些智慧,但这不是这篇文章的主要目的.

J R*_*ape 15

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

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

1.网络

您的网络中有太多边缘,因此它代表单位tesseract.警告我不是这里的数学专家 - 只是从绘图角度(matplotlib标签)来到这里.请解释我是不是错了.

您想要的投影,例如,n = 4的Hasse图的wolfram mathworld页面只有4个边连接所有节点,而2个边和7个边有6个边到3个节点.您的图形完全连接每个"级别",即具有0 1值的4-D向量连接到具有1个1值的所有向量,然后连接到具有2个1值的所有向量,依此类推.这在基于维基百科答案的投影中最为明显(下面的第2张图片)

2.投影

我找不到预先编写的算法或库来自动将4D tesseract投影到2D平面上,但我确实找到了几个例子,例如维基百科.由此,您可以设计出适合您的坐标集并将其传递给nx.draw()呼叫.

这是一个例子 - 我已经包含了两个坐标集,一个看起来像你在上面展示的投影,一个与维基百科上的投影相匹配.

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)):
                    H.add_edge(''.join(p_node),''.join(node))

#This is manual two options to project tesseract onto 2D plane 
# - many projections are available!!
wikipedia_projection_coords = [(0.5,0),(0.85,0.25),(0.625,0.25),(0.375,0.25),
                                (0.15,0.25),(1,0.5),(0.8,0.5),(0.6,0.5),
                                (0.4,0.5),(0.2,0.5),(0,0.5),(0.85,0.75),
                                (0.625,0.75),(0.375,0.75),(0.15,0.75),(0.5,1)]

#Build the "two cubes" type example projection co-ordinates
half_coords = [(0,0.15),(0,0.6),(0.3,0.15),(0.15,0),
               (0.55,0.6),(0.3,0.6),(0.15,0.4),(0.55,1)]
#make the coords symmetric
example_projection_coords = half_coords + [(1-x,1-y) for (x,y) in half_coords][::-1]

print example_projection_coords


def powerset(s):
    ch = itertools.chain.from_iterable(itertools.combinations(s, r) for r in range(len(s)+1))
    return [''.join(t) for t in ch]

pos={}
for i,label in enumerate(powerset(axis_labels)):
    if label == '':
       label = 'O'
    pos[label]= example_projection_coords[i]

#Show Plot
nx.draw(H,pos,with_labels = True,node_shape = 'o')
plt.show() 
Run Code Online (Sandbox Code Playgroud)

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

'两个立方体'投影

代码生成的tesseract的投影

维基媒体示例投影

由提供的代码生成的tesseract的替代投影


注意

如果你想进行自己的预测(并在pos数学上建立)的数学,你可能会看看这篇研究论文.


编辑:

好奇心越来越好,我不得不寻找一种数学方法来做到这一点.我找到了这个博客 - 其主要结果是投影矩阵:

4D到2D投影矩阵

这导致我开发了这个用于投影每个标签的功能,将包含'p'的标签表示该点在'p'轴上具有值1,即我们正在处理单元tesseract.从而:

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)
Run Code Online (Sandbox Code Playgroud)

为常规2D八边形提供了一个很好的投影,所有点都不同.

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

 pos[label] = example_projection_coords[i]
Run Code Online (Sandbox Code Playgroud)

pos[label] = construct_projection(label)
Run Code Online (Sandbox Code Playgroud)

这给出了结果:

投射到八角形

一起玩r1,r2,thetaphi你的心脏的内容:)