如何在 Python 中重塑 networkx 图? [英] How to reshape a networkx graph in Python?

查看:68
本文介绍了如何在 Python 中重塑 networkx 图?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

问题:

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

我想均匀地显示它(tesseract),但是我不知道如何重塑它.如何在Python中重塑networkx图?

我见过一些人使用 spring_layout()draw_circular() 的例子,但它并没有按照我正在寻找的方式进行塑造,因为它们是不统一.

有没有办法重塑我的图形并使其统一?(即将我的哈斯图重塑为正方体形状(最好使用 nx.draw() )

这是我目前的样子:

这是我的代码,用于生成N维的哈希图

#!/usr/bin/python将networkx导入为nx导入matplotlib.pyplot作为plt导入迭代工具H = nx.DiGraph()axis_labels = ['p','q','r','s']D_len_node = {}#遍历轴标签对于我在xrange(0,len(axis_labels)+1)中:#从空集创建边缘如果我 == 0:对于axis_labels中的ax:H.add_edge('O',ax)别的:#创建所有不重叠的组合组合 = [c for c in itertools.combinations(axis_labels,i)]D_len_node[i] = 组合#创建从len(i-1)到len(i)的边线#eg.pq>>pqr,pq>>>pqs如果我>1:对于D_len_node [i]中的节点:对于 D_len_node[i-1] 中的 p_node:#if set.intersection(set(p_node),set(node)):糟糕如果全部(p_node中p中的p中节点中的p)==真:#应该是这个!H.add_edge(''.join(p_node),''.join(node))#显示情节nx.draw(H,with_labels = True,node_shape = 'o')plt.show()

我想像这样重塑它:

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

解决方案

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

我认为您有两个问题 - 一个与布局有关,另一个与您的网络有关.

1.网络

您的网络中的边太多,无法代表单位正方体.警告 我不是这里的数学专家 - 只是从绘图角度(matplotlib 标签)来到这里.如果我错了,请解释.

您想要的投影,例如,.


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

这导致我开发了此功能来投影每个标签,使包含"p"的标签表示该点在"p"轴上的值为1,即我们正在处理单位tesseract.因此:

  def Construct_projection(label):r1 = r2 = 0.5theta = math.pi/6phi = math.pi/3x = int(标签中的'p')+ r1 * math.cos(theta)* int(标签中的'r')-r2 * math.cos(phi)* int(标签中的')y = int('q' in label) + r1 * math.sin(theta) * int('r' in label) + r2 * math.sin(phi) * int('s' in label)返回 (x,y)

在所有点都不同的规则 2D 八边形中给出一个很好的投影.

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

  pos [label] = example_projection_coords [i]

使用

  pos [label] = Construct_projection(标签)

结果如下:

玩转r1r2thetaphi,尽情享受吧:)

So I created a really naive (probably inefficient) way of generating hasse diagrams.

Question:

I have 4 dimensions... p q r s .

I want to display it uniformly (tesseract) but I have no idea how to reshape it. How can one reshape a networkx graph in Python?

I've seen some examples of people using spring_layout() and draw_circular() but it doesn't shape in the way I'm looking for because they aren't uniform.

Is there a way to reshape my graph and make it uniform? (i.e. reshape my hasse diagram into a tesseract shape (preferably using nx.draw() )

Here's what mine currently look like:

Here's my code to generate the hasse diagram of N dimensions

#!/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() 

I want to reshape it like this:

If anyone knows of an easier way to make Hasse Diagrams, please share some wisdom but that's not the main aim of this post.

解决方案

This is a pragmatic, rather than purely mathematical answer.

I think you have two issues - one with layout, the other with your network.

1. Network

You have too many edges in your network for it to represent the unit tesseract. Caveat I'm not an expert on the maths here - just came to this from the plotting angle (matplotlib tag). Please explain if I'm wrong.

Your desired projection and, for instance, the wolfram mathworld page for a Hasse diagram for n=4 has only 4 edges connected all nodes, whereas you have 6 edges to the 2 and 7 edges to the 3 bit nodes. Your graph fully connects each "level", i.e. 4-D vectors with 0 1 values connect to all vectors with 1 1 value, which then connect to all vectors with 2 1 values and so on. This is most obvious in the projection based on the Wikipedia answer (2nd image below)

2. Projection

I couldn't find a pre-written algorithm or library to automatically project the 4D tesseract onto a 2D plane, but I did find a couple of examples, e.g. Wikipedia. From this, you can work out a co-ordinate set that would suit you and pass that into the nx.draw() call.

Here is an example - I've included two co-ordinate sets, one that looks like the projection you show above, one that matches this one from wikipedia.

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() 

Note - unless you change what I've mentioned in 1. above, they still have your edge structure, so won't look exactly the same as the examples from the web. Here is what it looks like with your existing network generation code - you can see the extra edges if you compare it to your example (e.g. I don't this pr should be connected to pqs:

'Two cube' projection

Wikimedia example projection


Note

If you want to get into the maths of doing your own projections (and building up pos mathematically), you might look at this research paper.


EDIT:

Curiosity got the better of me and I had to search for a mathematical way to do this. I found this blog - the main result of which being the projection matrix:

This led me to develop this function for projecting each label, taking the label containing 'p' to mean the point has value 1 on the 'p' axis, i.e. we are dealing with the unit tesseract. Thus:

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)

Gives a nice projection into a regular 2D octagon with all points distinct.

This will run in the above program, just replace

 pos[label] = example_projection_coords[i]

with

pos[label] = construct_projection(label)

This gives the result:

play with r1,r2,theta and phi to your heart's content :)

这篇关于如何在 Python 中重塑 networkx 图?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆