如何将节点放置在特定位置-networkx

时间:2019-04-26 01:07:17

标签: python graph networkx

我正在做一个福特-富克森方法,该方法在每个阶段绘制图形。我想将接收器放在特定位置(我希望源位于图的最左侧,接收器位于最右侧)。我已经在pos函数中尝试过spring_layout参数,但这似乎不起作用。

这是我的图

graph.add_edges_from([
    ('A', 'B', {'capacity': 4, 'flow': 0}),
    ('A', 'C', {'capacity': 5, 'flow': 0}),
    ('A', 'D', {'capacity': 7, 'flow': 0}),
    ('B', 'E', {'capacity': 7, 'flow': 0}),
    ('C', 'E', {'capacity': 6, 'flow': 0}),
    ('C', 'F', {'capacity': 4, 'flow': 0}),
    ('C', 'G', {'capacity': 1, 'flow': 0}),
    ('D', 'F', {'capacity': 8, 'flow': 0}),
    ('D', 'G', {'capacity': 1, 'flow': 0}),
    ('E', 'H', {'capacity': 7, 'flow': 0}),
    ('F', 'H', {'capacity': 6, 'flow': 0}),
    ('G', 'H', {'capacity': 4, 'flow': 0}),

])

Ford-Fulkerson算法:

def ford_fulkerson(graph, source, sink, debug=None):
    flow, path = 0, True

    while path:
        path, reserve = depth_first_search(graph, source, sink)
        flow += reserve

        for v, u in zip(path, path[1:]):
            if graph.has_edge(v, u):
                graph[v][u]['flow'] += reserve
            else:
                graph[u][v]['flow'] -= reserve

        if callable(debug):
            debug(graph, path, reserve, flow)


def depth_first_search(graph, source, sink):
    undirected = graph.to_undirected()
    explored = {source}
    stack = [(source, 0, dict(undirected[source]))]

    while stack:
        v, _, neighbours = stack[-1]
        if v == sink:
            break

        while neighbours:
            u, e = neighbours.popitem()
            if u not in explored:
                break
        else:
            stack.pop()
            continue

        in_direction = graph.has_edge(v, u)
        capacity = e['capacity']
        flow = e['flow']
        neighbours = dict(undirected[u])

        if in_direction and flow < capacity:
            stack.append((u, capacity - flow, neighbours))
            explored.add(u)
        elif not in_direction and flow:
            stack.append((u, flow, neighbours))
            explored.add(u)

    reserve = min((f for _, f, _ in stack[1:]), default=0)
    path = [v for v, _, _ in stack]

    return path, reserve
ford_fulkerson(graph, 'A', 'H', flow_debug)

这是我使用的布局:

layout = nx.spring_layout(graph, weight='capacity', dim=2, k=20, pos={'A': [-3, -3], 'H': [5, 1]})

这是我得到的结果:

Result

我希望“ A”节点位于最左侧,而“ H”节点位于最右侧。

3 个答案:

答案 0 :(得分:1)

检查documentation中是否有spring_layout,它显示:

  

pos (dict或None可选(默认值= None))–节点的初始位置作为字典,节点作为键,值作为坐标列表或元组。如果为None,则使用随机的初始位置。

因此,您已经设置了节点的初始位置,但是该算法从起始位置开始移动节点,因此这些更改不足为奇。

看看下一个参数:

  

固定(列表或“无”可选,默认为“无”)–固定在初始位置的节点。

因此,您需要使用此可选参数指定将哪些节点固定在其初始位置。

答案 1 :(得分:0)

我建议您使用具有DOT可视化功能的图片中的graphviz layout

char decrypt_ltr(char alpha, int key) 
{
  if (alpha >= 'A' && alpha <= 'Z')
  {
      alpha = ((alpha-'A') - key + 26) % 26 + 'A'; // the 26 ensures that the value
                                                   // is positive before the modulo
                                                   // operator is applied and is
                                                   // removed by the modulo operator
  }
  else if(alpha >= 'a' && alpha <= 'z')
  {
      alpha = ((alpha-'a') - key + 26) % 26 + 'a';
  }

  return alpha;
}

它强制 pos=nx.drawing.nx_agraph.graphviz_layout( graph, prog='dot', args='-Grankdir=LR' ) 调用DOT程序以获取图形布局。 DOT设计用于有向图(尤其是非循环图)。在这里,您可以看到此布局的用法(请注意,必须安装nx.drawgraphviz-Python连接器)

agraph

enter image description here

答案 2 :(得分:0)

完成节点布局后,您将获得dict对象(此处为layout)中所有节点的位置。您随时可以根据需要重新定位其中的一些。 在这里,我设置了图中心(0,0)左右两侧的节点AH的位置。

# fix positions of some nodes
layout['A'] = [-3, -3]   # position at left
layout['H'] = [5, 1]     # position at right

在这个阶段,如果您想将它们移动到离图形中心更远的地方,此简单的代码可以解决这个问题。

# reposition the nodes further away from center
# need: import numpy as np
xmult = 1.2    # use value greater than 1.0
layout['A'] = layout['A']*np.array([xmult, 1])   # move left
layout['H'] = layout['H']*np.array([xmult, 1])   # move right

最后,当您使用绘制网络时

nx.draw_networkx(graph, pos=layout)

您应该获得类似于以下内容的情节:

enter image description here