使用newwork绘制环状发散式知识图谱的算法

算法主要在这个函数中。这个算法也是从外网上抄的。

这个算法的输出是一个布局字典,画出图后是一个树。

 例子:

布局字典通过一个数学方法处理后将其变成环状发散图。

    def hierarchy_pos(self,G, root=None, width=1., vert_gap=0.2, vert_loc=0, xcenter=0.5):
        """
        分散树型画法
        :param G:
        :param root:
        :param width:
        :param vert_gap:
        :param vert_loc:
        :param xcenter:
        :return:
        """
        '''
        From Joel's answer at https://stackoverflow.com/a/29597209/2966723.
        Licensed under Creative Commons Attribution-Share Alike

        If the graph is a tree this will return the positions to plot this in a
        hierarchical layout.

        G: the graph (must be a tree)

        root: the root node of current branch
        - if the tree is directed and this is not given,
          the root will be found and used
        - if the tree is directed and this is given, then
          the positions will be just for the descendants of this node.
        - if the tree is undirected and not given,
          then a random choice will be used.

        width: horizontal space allocated for this branch - avoids overlap with other branches

        vert_gap: gap between levels of hierarchy

        vert_loc: vertical location of root

        xcenter: horizontal location of root
        '''
        # if not nx.is_tree(G):
        #     raise TypeError('cannot use hierarchy_pos on a graph that is not a tree')

        if root is None:
            if isinstance(G, nx.DiGraph):
                # for i in iter(nx.topological_sort(G)):
                #     print(i)
                # print(nx.topological_sort(G))
                root = next(iter(nx.topological_sort(G)))  # allows back compatibility with nx version 1.11
            else:
                root = random.choice(list(G.nodes))
        print(root)
        def _hierarchy_pos(G, root, width=1, vert_gap=0.2, vert_loc=0, xcenter=0.5, pos=None, parent=None):
            '''
            see hierarchy_pos docstring for most arguments

            pos: a dict saying where all nodes go if they have been assigned
            parent: parent of this branch. - only affects it if non-directed

            '''

            if pos is None:
                pos = {root: (xcenter, vert_loc)}

            else:
                pos[root] = (xcenter, vert_loc)
            print(pos)
            children = list(G.neighbors(root))
            if not isinstance(G, nx.DiGraph) and parent is not None:
                children.remove(parent)
            if len(children) != 0:
                dx = width / len(children)
                #原 nextx = xcenter - width / 2 - dx /4
                nextx = xcenter - width / 2 - dx /2
                for child in children:
                    nextx += dx
                    #xcenter水平
                    #vert_loc竖直
                    pos = _hierarchy_pos(G, child, width=dx, vert_gap=vert_gap,
                                         vert_loc=vert_loc - vert_gap, xcenter=nextx,
                                         pos=pos, parent=root)
            return pos

        return _hierarchy_pos(G, root, width, vert_gap, vert_loc, xcenter)

这是源地址:可以使用python 3从networkx获取分层图吗?- 堆栈溢出 (stackoverflow.com)

这个函数是一个布局函数。也就是说要先将图的节点和边都添加进去,再把图交给这个函数处理。

1.newwork布局逻辑

为了解释这个函数,首先要解释newwork的布局逻辑:

network的节点布局的底层很简单,整个图上的节点位置用一个字典表示。

字典中项的格式为:

key:点的名字(注意在network中点的名字是add_node()时设置的名字,在图上显示时默认显示点的label的名字。但如果没有设置label,label默认为点的名字。当然,你可以在draw()时用 with_labels设定是否显示label)

value:value为一个2元元组。元组为点的坐标。(注意在newwork中的点的坐标是相对坐标,即在图中初始不存在坐标系,点的坐标虽然也是坐标系的形式,但更多的是表示点的相对位置,即如果点的相对位置没有变,点的坐标无论如何变(比如从(0,0)到(100,100)),对图像显示没有任何影响)

每个点占用一个键值对。用一个字典将每个点的位置表示出来。

{'32': (0.0, 0.0), '3203': (0.1414213562373095, 0.14142135623730953), '3204': (-0.14142135623730953, 0.14142135623730953), '3201': (-0.14142135623730953, -0.14142135623730953), '3202': (0.1414213562373095, -0.14142135623730953)}

这个字典其实就是draw中的pos。把这个字典穿给draw()或其他draw系列的函数就可以画出图了。

2.算法原理

下面是对这个算法的分析。

2.1hierarchy_pos函数

hierarchy_pos函数的输入有这些东西。

G:图

root:根节点的位置

width:分配给这个分支的水平空间——避免与其他分支重叠。(即父节点的子节点的这一行所占的水平宽度)

vert_gap:父节点和子节点之间的竖直距离。

vert_loc:根节点的竖直位置

xcenter:根节点的水平位置

hierarchy_pos的作用:如果图是有向图且没有给root,会自动找到root。如果是无向图且没有给root,会随机选择一个点作为root。选定root后调用_hierarchy_pos()函数。

hierarchy_pos函数的输出:图的布局字典。

2.2 _hierarchy_pos函数

这是个递归函数。

_hierarchy_pos()函数的输入有这些东西:

G,root,width,vert_gap,vert_loc,xcenter与上面一样

pos:图的布局字典,作为参数的原因是使函数在分配点的位置时都是对同一个字典修改

parent:告知当前root的父节点是哪个,主要用于无向图。

hierarchy_pos函数的输出:图的布局字典。

3._hierarchy_pos函数的作用详解

第一步:

先定下根节点的坐标

第二步:

找到根节点的所有子节点。注意:对于无向图,G.neighbors(root)是找所有和root相连的节点,这也是为什么要删去root的父节点。对于有向图,是找的被指向的节点。

第三步:

 安排每个子节点的位置,dx是按子节点个数将width分开的一份的长度。

nextx是子节点开始的位置,从开始位置放一个加dx的码过去。

而水平位置为根节点位置减高度差。

然后不断的递归。

4.数学处理

由于我的width设置为2pi。 所以我在下一行用cos转化时,生成的位置一定是在根节点的周围一圈。

 而乘r是为了将根节点周围的一圈的点扩散出去。这样就完成了发散,并且每次扩散都是相对于父节点的扩散。当然,由于乘的特殊性,不要把根节点y坐标设为在减几次(比树的级数小)vert_gap后会到0的值。

显示个处理结果:

 

 当然这个算法有很多可以改进的地方,很多地方可以设置为手动设置,并以此建立一个图谱绘制程序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值