我正在尝试制作一个使用Ford-Fulkerson方法查找图内最大流量的应用程序。我面临的问题是,单击窗口右侧的MaxFlow
按钮后,我无法显示图形。
我已经设置好图形,最大流量算法有效。
from tkinter import *
import networkx as nx
from pandas import DataFrame
from digraph import ford_fulkerson
import matplotlib
matplotlib.use("TkAgg")
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
window = Tk()
window.title("Graphs")
graph = nx.DiGraph()
graph.add_nodes_from('ABCDEFGH')
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}),
])
layout = {
'A': [0, 1], 'B': [1, 2], 'C': [1, 1], 'D': [1, 0],
'E': [2, 2], 'F': [2, 1], 'G': [2, 0], 'H': [3, 1],
}
def draw_graph():
f = plt.Figure(figsize=(5, 5), dpi=100)
a = f.add_subplot(111)
a.plot()
a.draw_networkx_nodes(graph, layout, node_color='steelblue', node_size=600)
a.draw_networkx_edges(graph, layout, edge_color='gray')
a.draw_networkx_labels(graph, layout, font_color='white')
for u, v, e in graph.edges(data=True):
label = '{}/{}'.format(e['flow'], e['capacity'])
color = 'green' if e['flow'] < e['capacity'] else 'red'
x = layout[u][0] * .6 + layout[v][0] * .4
y = layout[u][1] * .6 + layout[v][1] * .4
t = plt.text(x, y, label, size=16, color=color,
horizontalalignment='center', verticalalignment='center')
plt.show()
def flow_debug(graph, path, reserve, flow):
print('flow increased by', reserve,
'at path', path,
'; current flow', flow)
draw_graph()
def plot_max_flow():
ford_fulkerson(graph, 'A', 'H', flow_debug)
VertexData = Entry(window)
VertexData.grid(row = 0, column = 0)
Button(window, text = "Insert Vertex").grid(sticky = W, row = 0, column = 1, padx = 4)
Button(window, text = "Delete Vertex").grid(sticky = W, row = 0, column = 2, padx = 4)
Button(window, text = "MaxFlow").grid(sticky = W, row = 0, column = 3, padx = 4, command = ford_fulkerson(graph, 'A', 'H', flow_debug))
df3 = DataFrame()
window.mainloop()
DFS和Ford-Fulkerson算法,以防万一:
def ford_fulkerson(graph, source, sink, debug=None):
flow, path = 0, True
while path:
# search for path with flow reserve
path, reserve = depth_first_search(graph, source, sink)
flow += reserve
# increase flow along the path
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
# show intermediate results
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
# search the next neighbour
while neighbours:
u, e = neighbours.popitem()
if u not in explored:
break
else:
stack.pop()
continue
# current flow and capacity
in_direction = graph.has_edge(v, u)
capacity = e['capacity']
flow = e['flow']
neighbours = dict(undirected[u])
# increase or redirect flow at the edge
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)
# (source, sink) path and its flow reserve
reserve = min((f for _, f, _ in stack[1:]), default=0)
path = [v for v, _, _ in stack]
return path, reserve
我希望绘制的图形将显示在窗口的右侧,但我不知道如何实现。
答案 0 :(得分:0)
您有窗口
window = Tk()
和图中的networkx
f = plt.Figure(figsize=(5, 5), dpi=100)
所以你需要
# create matplotlib canvas using figure `f` and assign to widget `window`
canvas = FigureCanvasTkAgg(f, window)
# get canvas as tkinter's widget and `gird` in widget `window`
canvas.get_tk_widget().grid(row=..., column=...)
我无法测试它,但是我有一个自己的示例,put matplot figure in tkinter window