upload tsp project

master
bettleChen 1 year ago
parent 375c0440ec
commit 7b16abeee3

@ -0,0 +1,487 @@
# -*- encoding: utf-8 -*-
from head import *
from NODE import *
N = Node()
class Edge:
def __init__(self):
self.mark = []
# 记录已标记的节点数目(连接操作)
self.user_cur = 0
# 记录用户所在点
def node_edge(self, no, n1, n2): # 根据节点返回编号
if n1 > n2:
n = n1
n1 = n2
n2 = n
for e in d.Edges:
if e[1] == n1 and e[2] == n2 and e[8] == no:
return e[0]
return -1
def edge_mark_display(self):
for w in frame_right.winfo_children():
w.destroy()
# 清除右侧组件
cura = ""
cur1 = -1
curb = ""
cur2 = -1
lab = tk.Label(frame_right, text="连接操作", bg=RED, fg=BLACK, font=('微软雅黑', 20))
lab.place(relx=0.18, rely=0.02, width=200, height=30)
for i in d.Nodes:
if i[2] == 1:
cura = str(i[1])
cur1 = i[0]
if i[2] == 2:
curb = str(i[1])
cur2 = i[0]
E = 0
for e in d.Edges:
if ((cur1 == e[1] and cur2 == e[2]) or (cur2 == e[1] and cur1 == e[2])):
if e[8] == 1 and e[3] == 1 and E < 1:
E = 1
elif e[8] == 2 and e[3] == 1 and E < 2:
E = 2
elif e[8] == 3 and e[3] == 1 and E < 3:
E = 3
y0 = 0.1
B = tk.Button(frame_right, text="建立为完全图", command=lambda: self.edge_addall())
B.place(relx=0.15, rely=y0 - 0.02, width=80, height=30)
B = tk.Button(frame_right, text="删除所有链接", command=lambda: self.edge_delall())
B.place(relx=0.65, rely=y0 - 0.02, width=80, height=30)
# 当前两个节点信息
laba1 = tk.Label(frame_right, text="当前节点1:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
laba2 = tk.Label(frame_right, text=f"{cura}", bg=BLUE, fg=BLACK, font=('微软雅黑', 8))
laba1.place(relx=0.05, rely=0.02 + y0, width=80, height=30)
laba2.place(relx=0.35, rely=0.02 + y0, width=50, height=30)
labb1 = tk.Label(frame_right, text="当前节点2:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
labb2 = tk.Label(frame_right, text=f"{curb}", bg=BLUE, fg=BLACK, font=('微软雅黑', 8))
labb1.place(relx=0.52, rely=0.02 + y0, width=80, height=30)
labb2.place(relx=0.82, rely=0.02 + y0, width=50, height=30)
# 当前链接信息
cur = -1
for edge in d.Edges:
if edge[8] == 1 and edge[3] == 1 and d.Nodes[edge[1]][2] + d.Nodes[edge[2]][2] == 3:
cur = edge[0]
if E == 0:
text = "两点间不存在链接"
else:
text = "两点间存在" + str(E) + "条链接"
lab1 = tk.Label(frame_right, text=f"{text}", bg=RED, fg=BLACK, font=('微软雅黑', 15))
lab1.place(relx=0.05, rely=0.08 + y0, width=200, height=30)
if E == 0:
B = tk.Button(frame_right, text="建立链接", command=lambda: self.edge_add())
B.place(relx=0.7, rely=0.08 + y0, width=80, height=30)
elif E == 1:
B = tk.Button(frame_right, text="删除链接", command=lambda: self.edge_del())
B.place(relx=0.7, rely=0.08 + y0, width=80, height=30)
if not E == 0:
y0 += 0.1
lab = tk.Label(frame_right, text="链接一", bg=RED, fg=BLACK, font=('微软雅黑', 15))
lab.place(relx=0.1, rely=0.08 + y0, width=150, height=30)
lab1 = tk.Label(frame_right, text="当前链接", bg=RED, fg=BLACK, font=('微软雅黑', 12))
if cur == -1:
text = ""
else:
text = str(d.Edges[cur][5])
lab2 = tk.Label(frame_right, text=f"{text}", bg=BLUE, fg=BLACK, font=('微软雅黑', 8))
B = tk.Button(frame_right, text="设置标签", command=lambda: self.edge_rename())
lab1.place(relx=0.1, rely=0.13 + y0, width=80, height=30)
lab2.place(relx=0.4, rely=0.13 + y0, width=80, height=30)
B.place(relx=0.7, rely=0.13 + y0, width=80, height=30)
lab1 = tk.Label(frame_right, text="链接成本", bg=RED, fg=BLACK, font=('微软雅黑', 12))
if cur == -1:
text = ""
else:
text = str(d.Edges[cur][6])
lab2 = tk.Label(frame_right, text=f"{text}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12))
B = tk.Button(frame_right, text="设置成本", command=lambda: self.edge_recost())
lab1.place(relx=0.1, rely=0.18 + y0, width=80, height=30)
lab2.place(relx=0.4, rely=0.18 + y0, width=80, height=30)
B.place(relx=0.7, rely=0.18 + y0, width=80, height=30)
lab1 = tk.Label(frame_right, text="链接时间", bg=RED, fg=BLACK, font=('微软雅黑', 12))
if cur == -1:
text = ""
else:
text = str(d.Edges[cur][7])
lab2 = tk.Label(frame_right, text=f"{text}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12))
B = tk.Button(frame_right, text="设置时间", command=lambda: self.edge_retime())
lab1.place(relx=0.1, rely=0.23 + y0, width=80, height=30)
lab2.place(relx=0.4, rely=0.23 + y0, width=80, height=30)
B.place(relx=0.7, rely=0.23 + y0, width=80, height=30)
# print ("cur",cur1,cur2)
# print (E)
if E == 1:
B = tk.Button(frame_right, text="增加一条连接", command=lambda: self.newedge_add(2, cur1, cur2))
B.place(relx=0.1, rely=0.3 + y0, width=150, height=30)
elif E >= 2:
cur = self.node_edge(2, cur1, cur2)
lab = tk.Label(frame_right, text="链接二", bg=RED, fg=BLACK, font=('微软雅黑', 15))
lab.place(relx=0.1, rely=0.28 + y0, width=150, height=30)
lab1 = tk.Label(frame_right, text="当前链接", bg=RED, fg=BLACK, font=('微软雅黑', 12))
if cur == -1:
text = ""
else:
text = str(d.Edges[cur][5])
lab2 = tk.Label(frame_right, text=f"{text}", bg=BLUE, fg=BLACK, font=('微软雅黑', 8))
B = tk.Button(frame_right, text="设置标签", command=lambda n=cur: self.newedge_rename(n))
lab1.place(relx=0.1, rely=0.33 + y0, width=80, height=30)
lab2.place(relx=0.4, rely=0.33 + y0, width=80, height=30)
B.place(relx=0.7, rely=0.33 + y0, width=80, height=30)
lab1 = tk.Label(frame_right, text="链接成本", bg=RED, fg=BLACK, font=('微软雅黑', 12))
if cur == -1:
text = ""
else:
text = str(d.Edges[cur][6])
lab2 = tk.Label(frame_right, text=f"{text}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12))
B = tk.Button(frame_right, text="设置成本", command=lambda n=cur: self.newedge_recost(n))
lab1.place(relx=0.1, rely=0.38 + y0, width=80, height=30)
lab2.place(relx=0.4, rely=0.38 + y0, width=80, height=30)
B.place(relx=0.7, rely=0.38 + y0, width=80, height=30)
lab1 = tk.Label(frame_right, text="链接时间", bg=RED, fg=BLACK, font=('微软雅黑', 12))
if cur == -1:
text = ""
else:
text = str(d.Edges[cur][7])
lab2 = tk.Label(frame_right, text=f"{text}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12))
B = tk.Button(frame_right, text="设置时间", command=lambda n=cur: self.newedge_retime(n))
lab1.place(relx=0.1, rely=0.43 + y0, width=80, height=30)
lab2.place(relx=0.4, rely=0.43 + y0, width=80, height=30)
B.place(relx=0.7, rely=0.43 + y0, width=80, height=30)
if E == 2:
B = tk.Button(frame_right, text="增加一条连接", command=lambda: self.newedge_add(3, cur1, cur2))
B.place(relx=0.1, rely=0.5 + y0, width=150, height=30)
B = tk.Button(frame_right, text="删除一条连接", command=lambda: self.newedge_del(2, cur1, cur2))
B.place(relx=0.1, rely=0.55 + y0, width=150, height=30)
B = tk.Button(frame_right, text="删除多余连接", command=lambda: self.newedge_del_all(1))
B.place(relx=0.1, rely=0.6 + y0, width=150, height=30)
elif E == 3:
cur = self.node_edge(3, cur1, cur2)
y0 += 0.2
lab = tk.Label(frame_right, text="链接三", bg=RED, fg=BLACK, font=('微软雅黑', 15))
lab.place(relx=0.1, rely=0.28 + y0, width=150, height=30)
lab1 = tk.Label(frame_right, text="当前链接", bg=RED, fg=BLACK, font=('微软雅黑', 12))
if cur == -1:
text = ""
else:
text = str(d.Edges[cur][5])
lab2 = tk.Label(frame_right, text=f"{text}", bg=BLUE, fg=BLACK, font=('微软雅黑', 8))
B = tk.Button(frame_right, text="设置标签", command=lambda n=cur: self.newedge_rename(n))
lab1.place(relx=0.1, rely=0.33 + y0, width=80, height=30)
lab2.place(relx=0.4, rely=0.33 + y0, width=80, height=30)
B.place(relx=0.7, rely=0.33 + y0, width=80, height=30)
lab1 = tk.Label(frame_right, text="链接成本", bg=RED, fg=BLACK, font=('微软雅黑', 12))
if cur == -1:
text = ""
else:
text = str(d.Edges[cur][6])
lab2 = tk.Label(frame_right, text=f"{text}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12))
B = tk.Button(frame_right, text="设置成本", command=lambda n=cur: self.newedge_recost(n))
lab1.place(relx=0.1, rely=0.38 + y0, width=80, height=30)
lab2.place(relx=0.4, rely=0.38 + y0, width=80, height=30)
B.place(relx=0.7, rely=0.38 + y0, width=80, height=30)
lab1 = tk.Label(frame_right, text="链接时间", bg=RED, fg=BLACK, font=('微软雅黑', 12))
if cur == -1:
text = ""
else:
text = str(d.Edges[cur][7])
lab2 = tk.Label(frame_right, text=f"{text}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12))
B = tk.Button(frame_right, text="设置时间", command=lambda n=cur: self.newedge_retime(n))
lab1.place(relx=0.1, rely=0.43 + y0, width=80, height=30)
lab2.place(relx=0.4, rely=0.43 + y0, width=80, height=30)
B.place(relx=0.7, rely=0.43 + y0, width=80, height=30)
B = tk.Button(frame_right, text="删除一条连接", command=lambda: self.newedge_del(3, cur1, cur2))
B.place(relx=0.1, rely=0.5 + y0, width=150, height=30)
B = tk.Button(frame_right, text="删除多余连接", command=lambda: self.newedge_del_all(1))
B.place(relx=0.1, rely=0.55 + y0, width=150, height=30)
def edge_merge_cost(self, n1, n2):
cur1 = node_edge(n1, n2)# 初始化三条可能的边的编号
cur2 = node_edge(n1, n2, 2)# 初始化三条可能的边的编号
cur3 = node_edge(n1, n2, 3)# 初始化三条可能的边的编号
edges = [(cur1, d.Edges[cur1][6]), (cur2, d.Edges[cur2][6]), (cur3, d.Edges[cur3][6])]#提出编号与路径花费
valid_edges = [(edge, cost) for edge, cost in edges if d.Edges[edge][3] == 1]# 过滤出存在的边
valid_edges.sort(key=lambda x: x[1])# 按照 cost 排序,保留 cost 最小的边
for idx, (edge, _) in enumerate(valid_edges):
d.Edges[edge][8] = idx + 1 # 设置边的优先级
d.Edges[edge][0] = edge # 确保边的索引正确
for edge, _ in valid_edges[1:]:# 对于非最优边,设置其为不显示
d.Edges[edge][3] = 0
# def edge_merge_cost(self, n1, n2):
# # 保留cost最小的一条其他路径都不显示
# cur1 = G.node_edge(n1, n2)
# cur2 = self.node_edge(2, n1, n2)
# cur3 = self.node_edge(3, n1, n2)
# # print(d.Edges[cur1])
# # print(d.Edges[cur2])
# # print(d.Edges[cur3])
# if d.Edges[cur2][3] == 1 and d.Edges[cur2][6] < d.Edges[cur1][6]:
# e = d.Edges[cur1].copy()
# d.Edges[cur1] = d.Edges[cur2].copy()
# d.Edges[cur2] = e.copy()
# d.Edges[cur1][8] = 1
# d.Edges[cur2][8] = 2
# if d.Edges[cur2][3] == 1 and d.Edges[cur3][6] < d.Edges[cur1][6]:
# e = d.Edges[cur1].copy()
# d.Edges[cur1] = d.Edges[cur3].copy()
# d.Edges[cur3] = e.copy()
# d.Edges[cur1][8] = 1
# d.Edges[cur3][8] = 3
# if d.Edges[cur2][3] == 1 and d.Edges[cur3][3] == 1 and d.Edges[cur3][6] < d.Edges[cur2][6]:
# e = d.Edges[cur2].copy()
# d.Edges[cur2] = d.Edges[cur3].copy()
# d.Edges[cur3] = e.copy()
# d.Edges[cur2][8] = 2
# d.Edges[cur3][8] = 3
# d.Edges[cur2][3] = 0
# d.Edges[cur3][3] = 0
# d.Edges[cur1][0] = cur1
# d.Edges[cur2][0] = cur2
# d.Edges[cur3][0] = cur3
def edge_merge_time(self, n1, n2):
cur1 = node_edge(n1, n2)# 初始化三条可能的边的编号
cur2 = node_edge(n1, n2, 2)# 初始化三条可能的边的编号
cur3 = node_edge(n1, n2, 3)# 初始化三条可能的边的编号
edges = [(cur1, d.Edges[cur1][7]), (cur2, d.Edges[cur2][7]), (cur3, d.Edges[cur3][7])]#提出编号与路径花费
valid_edges = [(edge, cost) for edge, cost in edges if d.Edges[edge][3] == 1]# 过滤出存在的边
valid_edges.sort(key=lambda x: x[1])# 按照 cost 排序,保留 cost 最小的边
for idx, (edge, _) in enumerate(valid_edges):
d.Edges[edge][8] = idx + 1 # 设置边的优先级
d.Edges[edge][0] = edge # 确保边的索引正确
for edge, _ in valid_edges[1:]:# 对于非最优边,设置其为不显示
d.Edges[edge][3] = 0
def edge_del_all(self, mode):
# mode = 1:优先最短路径
# mode = 2:优先最短时间
# cur1 = node_edge()
if mode == 1:
for e in d.Edges:
if (e[8] == 2 and e[3] == 1) or (e[8] == 3 and e[3] == 1):
self.edge_merge_cost(e[1], e[2])
else:
for e in d.Edges:
if (e[8] == 2 and e[3] == 1) or (e[8] == 3 and e[3] == 1):
self.edge_merge_time(e[1], e[2])
G.draw()
def newedge_del_all(self, mode):
self.edge_del_all(mode)
self.edge_mark_display()
def newedge_recost(self, no):
edge = d.Edges[no]
if not edge:
tk.messagebox.askokcancel(title='错误', message='链接不合法')
result = tkinter.simpledialog.askinteger(title='修改连接花费', prompt='请输入修改后的时间:',
initialvalue=edge[7])
if result:
edge[6] = result
G.draw()
self.edge_mark_display()
def newedge_retime(self, no):
edge = d.Edges[no]
if not edge:
tk.messagebox.askokcancel(title='错误', message='链接不合法')
result = tkinter.simpledialog.askinteger(title='修改连接时间', prompt='请输入修改后的时间:',
initialvalue=edge[7])
if result:
edge[7] = result
G.draw()
self.edge_mark_display()
def newedge_rename(self, no):
edge = d.Edges[no]
if not edge:
tk.messagebox.askokcancel(title='错误', message='链接不合法')
result = tkinter.simpledialog.askstring(title='修改连接标签', prompt='请输入修改后的标签:',
initialvalue=edge[5])
if result:
edge[5] = result
G.draw()
self.edge_mark_display()
def newedge_add(self, no, na, nb):
e = self.node_edge(no, na, nb)
d.Edges[e][3] = 1
G.draw()
self.edge_mark_display()
def newedge_del(self, no, na, nb):
e = self.node_edge(no, na, nb)
d.Edges[e][3] = 0
# print(d.Edges[e])
G.draw()
self.edge_mark_display()
def node_mark1(self, name):
if name >= len(d.Nodes):
N.node_404(name)
return
for node in d.Nodes:
if node[0] == name:
node[2] = 1
elif node[2] == 1:
node[2] = 0
G.draw()
self.edge_mark_display()
def node_mark2(self, name):
if name >= len(d.Nodes):
N.node_404(name)
return
for node in d.Nodes:
if node[0] == name:
node[2] = 2
elif node[2] == 2:
node[2] = 0
G.draw()
self.edge_mark_display()
def edge_add(self):
for edge in d.Edges:
if d.Nodes[edge[1]][2] + d.Nodes[edge[2]][2] == 3:
if edge[8] == 1 and edge[3] == 1:
tk.messagebox.askokcancel(title='错误', message='已存在连线')
return
else:
edge[3] = 1
G.draw()
self.edge_mark_display()
return
tk.messagebox.askokcancel(title='错误', message='请选择两个节点')
def edge_del(self):
for edge in d.Edges:
if d.Nodes[edge[1]][2] + d.Nodes[edge[2]][2] == 3:
edge[3] = 0
G.draw()
self.edge_mark_display()
return
tk.messagebox.askokcancel(title='错误', message='请选择两个节点')
def edge_delall(self):
for edge in d.Edges:
edge[3] = 0
G.draw()
self.edge_mark_display()
def edge_addall(self):
for edge in d.Edges :
if edge[8] == 1:
edge[3] = 1
G.draw()
self.edge_mark_display()
def edge_rename(self):
for edge in d.Edges:
if d.Nodes[edge[1]][2] + d.Nodes[edge[2]][2] == 3:
if edge[3] == 0:
tk.messagebox.askokcancel(title='错误', message='不存在连线')
return
else:
result = tkinter.simpledialog.askstring(title='修改连接标签', prompt='请输入修改后的标签:',
initialvalue=edge[5])
if(result):
edge[5] = result
G.draw()
self.edge_mark_display()
return
tk.messagebox.askokcancel(title='错误', message='请选择两个节点')
def edge_recost(self):
for edge in d.Edges:
if d.Nodes[edge[1]][2] + d.Nodes[edge[2]][2] == 3:
if edge[3] == 0:
tk.messagebox.askokcancel(title='错误', message='不存在连线')
return
else:
result = tkinter.simpledialog.askinteger(title='修改连接成本', prompt='请输入修改后的成本:',
initialvalue=edge[6])
if result:
edge[6] = result
G.draw()
self.edge_mark_display()
return
tk.messagebox.askokcancel(title='错误', message='请选择两个节点')
def edge_retime(self):
for edge in d.Edges:
if d.Nodes[edge[1]][2] + d.Nodes[edge[2]][2] == 3:
if edge[3] == 0:
tk.messagebox.askokcancel(title='错误', message='不存在连线')
return
else:
result = tkinter.simpledialog.askinteger(title='修改连接时间', prompt='请输入修改后的时间:',
initialvalue=edge[7])
if result:
edge[7] = result
G.draw()
self.edge_mark_display()
return
tk.messagebox.askokcancel(title='错误', message='请选择两个节点')
def edge_mark(self):
for i in d.Edges:
if d.Nodes[i[1]][2] == True and d.Nodes[i[2]][2] == True:
i[4] = True
def edge_nmark(self):
for i in d.Edges:
if d.Nodes[i[1]][2] == True and d.Nodes[i[2]][2] == True:
i[4] = False
def edge_clear(self):
for edge in d.Edges:
edge[4] = False
G.draw()
if __name__ == '__main__':
G.draw()
E = Edge()
E.edge_mark_display()
mainloop()

@ -0,0 +1,230 @@
# -*- encoding: utf-8 -*-
from head import *
class Node:
# 标记节点按钮
def node_mark_display(self):
for w in frame_right.winfo_children():
w.destroy()
# 清除右侧组件
curx = -1
y0 = 0.1
for i in d.Nodes:
if i[2] == 1:
curx = i[0]
lab = tk.Label(frame_right, text="节点操作", bg=RED, fg=BLACK, font=('微软雅黑', 20))
lab.place(relx=0.18, rely=0.02, width=200, height=30)
lab1 = tk.Label(frame_right, text=f"当前共有{len(d.Nodes)}个节点", bg=RED, fg=BLACK, font=('微软雅黑', 15))
lab1.place(relx=0.1, rely=0.0 + y0, width=200, height=30)
lab1 = tk.Label(frame_right, text="当前节点:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
if curx == -1:
text = "未选择"
else:
text = f"{d.Nodes[curx][1]}"
lab2 = tk.Label(frame_right, text=text, bg=BLUE, fg=BLACK, font=('微软雅黑', 12))
lab1.place(relx=0.1, rely=0.05 + y0, width=80, height=30)
lab2.place(relx=0.4, rely=0.05 + y0, width=80, height=30)
B = tk.Button(frame_right, text="设置标签", command=lambda: self.node_rename())
B.place(relx=0.7, rely=0.05 + y0, width=80, height=30)
B = tk.Button(frame_right, text="删除当前节点", command=lambda: self.node_del_exact())
B.place(relx=0.1, rely=0.1 + y0, width=150, height=30)
if d.Nodes[curx][4] == 1:
text = '设为非必经节点'
else:
text = '设为必经节点'
B = tk.Button(frame_right, text=text, command=lambda: self.dominator(curx))
B.place(relx=0.1, rely=0.15 + y0, width=150, height=30)
B = tk.Button(frame_right, text="增加一个节点", command=lambda: self.node_add())
B.place(relx=0.1, rely=0.25 + y0, width=150, height=30)
B = tk.Button(frame_right, text="减少一个节点", command=lambda: self.node_del())
B.place(relx=0.1, rely=0.3 + y0, width=150, height=30)
def dominator(self, x):
d.Nodes[x][4] ^= 1
G.draw()
self.node_mark_display()
def node_mark(self, name):
if name >= len(d.Nodes):
self.node_404(name)
return
for node in d.Nodes:
if node[0] == name:
node[2] = 1
else:
node[2] = 0
G.draw()
self.node_mark_display()
def node_del_exact(self):
if d.nodes_num <= 2:# 若删除节点以后节点过少,则直接返回并警告
tk.messagebox.askokcancel(title='错误', message='节点过少')
return
flag = 0
cur = -1
for node in d.Nodes:# 寻找当前选定的节点
if node[2] == 1:
cur = node[0]
flag = 1
if flag == 0:
tk.messagebox.askokcancel(title='错误', message='未选择节点')
return
if d.source == 1:# 如果是均匀分布,则重新计算点的坐标
d.nodes_num -= 1#节点数目减一
d.ang = 360 / d.nodes_num#重新计算圆心角
nodes = d.Nodes.copy()#复制节点
d.Nodes.clear()#清除Data中的节点
num = 0
for n in nodes:#逐个复制节点
if n[0] == cur:#若是删除的节点,则不复制
continue
n[0] = num#重新编号
rad = math.radians(num * d.ang)#计算当前角度
x = int(math.cos(rad) * d.R)#计算当前点x坐标相对
y = int(math.sin(rad) * d.R)#计算当前点y坐标相对
n[3] = (d.center[0] + x, d.center[1] + y)#计算绝对坐标
d.Nodes.append(n)#将当前点加入点集合中
num += 1
edges = d.Edges.copy()#将原有边集复制出来
d.Edges.clear()#删除Data中的边集
num = 0
for e in edges:#复制边
if e[1] == cur or e[2] == cur:#删除的边不复制
continue
if e[1] > cur:#修改边对应的点的编号
e[1] -= 1
if e[2] > cur:#修改边对应的点的编号
e[2] -= 1
e[0] = num#重新编号
d.Edges.append(e)#将边加入边集中
num += 1
# 如果是按照经纬度分布,则重新计算比例尺
elif d.source == 2:
name = []
for i in range(len(d.name)):
if not i == cur:
name.append(d.name[i])
d.name = name.copy()
d.nodes_num -= 1
d.coordinate = d.coord_creat() # 纯节点坐标
d.Nodes = d.JI_nodes_creat() # 节点列表
d.Edges = d.JI_edges_creat()
d.JI_edge_add(2)
d.JI_edge_add(3)
elif d.source == 3:
name = []
for i in range(len(d.name)):
if not i == cur:
name.append(d.name[i])
d.name = name.copy()
d.nodes_num -= 1
d.coordinate = d.coord_creat() # 纯节点坐标
d.Nodes = d.LIAO_nodes_creat() # 节点列表
d.Edges = d.LIAO_edges_creat()
d.LIAO_edge_add(2)
d.LIAO_edge_add(3)
G.draw()
self.node_mark_display()
def node_rename(self):
flag = 0
for node in d.Nodes:
if node[2] == 1:
cur = node
flag = 1
if flag == 1:
result = tkinter.simpledialog.askstring(title='修改节点标签', prompt='请输入修改后的标签:', initialvalue=cur[1])
else:
tk.messagebox.askokcancel(title='错误', message='未选择节点')
return
for node in d.Nodes: # 检查新的名称是否已经存在
if node[1] == result:
return "Error: name already exists"
if result:
cur[1] = result
G.draw()
self.node_mark_display()
def node_clear(self):
for node in d.Nodes:
node[2] = False
G.draw()
def node_add(self):
# 增加一个节点
nodes = len(d.Nodes) + 1
# 如果节点数目大于五,则将连接详细信息改为不显示
if nodes > 5:
d.edgeinfo = 0
self.node_init(nodes)
G.draw()
self.node_mark_display()
def node_set(self):
node = tkinter.simpledialog.askinteger(title='修改节点数目', prompt='请输入修改后的节点数目:',
initialvalue=str(len(d.Nodes)))
if node:
self.node_init(node)
G.draw()
def node_del(self):
if d.nodes_num <= 2:
tk.messagebox.askokcancel(title='错误', message='节点过少')
return
nodes = len(d.Nodes) - 1
if nodes < 6:
d.edgeinfo = 1
self.node_init(nodes)
G.draw()
self.node_mark_display()
def node_init(self, node):
if not node:
return
if d.source == 1:
d.data(node)
elif d.source == 2:
if node > 13:
tk.messagebox.askokcancel(title='错误', message='节点过多')
return
d.HEI_data(node)
else:
if node > 13:
tk.messagebox.askokcancel(title='错误', message='节点过多')
return
d.LIAO_data(node)
if node > 5:
d.edgeinfo = 0
else:
d.edgeinfo = 1
def graph_del(self):
global d
del d
def node_refresh(self):
nodes = len(d.Nodes)
self.node_init(nodes)
G.draw()
self.node_mark_display()
def node_404(self, name):
# 弹出对话框
tk.messagebox.askokcancel(title='错误', message='该节点不存在')
# print(result)
if __name__ == '__main__':
G.draw()
node = Node()
node.node_mark_display()
mainloop()

@ -0,0 +1,878 @@
# -*- encoding: utf-8 -*-
from head import *
from NODE import *
from EDGE import *
N = Node()
E = Edge()
class Solve:
def __init__(self):
self.ans = [] # 记录答案
self.mutians = [] # 若有多个最短路则保存在mutians中
self.way_sum = 0 # 记录遍历的路径数目
self.minn = float("inf")#初始化最小值为正无穷
self.start = 0 # 起始点
self.end = 0 # 终点
self.mark = [] # 记录该点是否已经经过
self.user_cur = 0 # 记录用户所在点
self.cura = -1 # 记录用户选择的第一个点
self.curb = -1 # 记录用户选择的第二个点
self.con = 0 # 记录必经的节点数目
def Edge_mark_clear(self):
for edge in d.Edges:
edge[4] = 0
G.draw()
def Solve_display(self):
for w in frame_right.winfo_children():
w.destroy()
# 清除右侧组件
self.Edge_mark_clear()
cura = ""
cur1 = -1
curb = ""
cur2 = -1
lab = tk.Label(frame_right, text="自动判断相关", bg=RED, fg=BLACK, font=('微软雅黑', 20))
lab.place(relx=0.18, rely=0.02, width=200, height=30)
for i in d.Nodes:
if i[2] == 1:
cura = str(i[1])
cur1 = i[0]
if i[2] == 2:
curb = str(i[1])
cur2 = i[0]
y0 = 0.1
B = tk.Button(frame_right, text="查询该图是否联通", command=lambda: self.check())
B.place(relx=0.1, rely=0.0 + y0, width=150, height=30)
B = tk.Button(frame_right, text="自动求解最优路径-遍历", command=lambda: self.dfs_panel())
B.place(relx=0.1, rely=0.1 + y0, width=200, height=30)
B = tk.Button(frame_right, text="自动求解最优路径-贪心", command=lambda: self.greedy_panel())
B.place(relx=0.1, rely=0.15 + y0, width=200, height=30)
# B.place(relx=0.1, rely=0.0 + y0, width=150, height=30)
B = tk.Button(frame_right, text="自动求解最优路径(包含非必经点)", command=lambda: self.dfs_panel_condition())
B.place(relx=0.1, rely=0.2 + y0, width=200, height=30)
# 当前两个节点信息
y0 = 0.4
laba1 = tk.Label(frame_right, text="当前节点1:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
laba2 = tk.Label(frame_right, text=f"{cura}", bg=BLUE, fg=BLACK, font=('微软雅黑', 8))
laba1.place(relx=0.05, rely=0.02 + y0, width=80, height=30)
laba2.place(relx=0.35, rely=0.02 + y0, width=50, height=30)
labb1 = tk.Label(frame_right, text="当前节点2:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
labb2 = tk.Label(frame_right, text=f"{curb}", bg=BLUE, fg=BLACK, font=('微软雅黑', 8))
labb1.place(relx=0.52, rely=0.02 + y0, width=80, height=30)
labb2.place(relx=0.82, rely=0.02 + y0, width=50, height=30)
B = tk.Button(frame_right, text="查询两节点是否联通", command=lambda: self.run_graph_check())
B.place(relx=0.1, rely=0.1 + y0, width=250, height=30)
B = tk.Button(frame_right, text="查询两节点之间最优路径(时间)", command=lambda: self.auto_lowest_time())
B.place(relx=0.1, rely=0.15 + y0, width=250, height=30)
B = tk.Button(frame_right, text="查询两节点之间最优路径(距离)", command=lambda: self.auto_lowest_cost())
B.place(relx=0.1, rely=0.2 + y0, width=250, height=30)
B = tk.Button(frame_right, text="查询两节点之间最优路径(含必经节点)", command=lambda: self.auto_lowest_cost_condition())
B.place(relx=0.1, rely=0.25 + y0, width=250, height=30)
def run_graph_check(self):
a = -1
b = -1
# 根据已有数据获得ab点的编号
for node in d.Nodes:
if node[2] == 1:
a = node[0]
if node[2] == 2:
b = node[0]
if a == -1 or b == -1:
tk.messagebox.askokcancel(title='错误', message='未选择节点')
return
self.graph_check(a, b)
def graph_check(self, a, b): # 检查A点B点是否互通
find = []# 使用并查集来检测ab点是否互通
for i in range(len(d.Nodes)):# 初始化并查集
find.append(i)#使得find[i]=i
for edge in d.Edges:#根据已有的边来更新并查集
if (edge[8] == 1 and edge[3] == 0):
continue
x = edge[1]
y = edge[2]
while not x == find[x]:
x = find[x]
while not y == find[y]:
y = find[y]
if x < y:
find[y] = x
else:
find[x] = y
x = a
y = b
while not x == find[x]:#查询a点所在集合
x = find[x]
while not y == find[y]:#查询b点所在集合
y = find[y]
if find[x] == find[y]:# 输出检查结果
tk.messagebox.askokcancel(title='结果',
message='节点 ' + str(a + 1) + '与节点 ' + str(b + 1) + '互通')
else:
tk.messagebox.askokcancel(title='结果',
message='节点 ' + str(a + 1) + '与节点 ' + str(b + 1) + '不互通')
def node_mark1(self, name):
if name >= len(d.Nodes):
N.node_404(name)
return
for node in d.Nodes:
if node[0] == name:
node[2] = 1
elif node[2] == 1:
node[2] = 0
G.draw()
self.Solve_display()
def node_mark2(self, name):
if name >= len(d.Nodes):
N.node_404(name)
return
for node in d.Nodes:
if node[0] == name:
node[2] = 2
elif node[2] == 2:
node[2] = 0
G.draw()
self.Solve_display()
def auto_lowest_time(self): # 标记遍历路径
for w in frame_right.winfo_children():
w.destroy()
# 清除右侧组件
a = -1
b = -1
for node in d.Nodes:
if node[2] == 1:
a = node[0]
if node[2] == 2:
b = node[0]
if a == -1 or b == -1:
tk.messagebox.askokcancel(title='错误', message='未选择节点')
return
self.cura = a
self.curb = b
y0 = 0.1
self.lowest_time_dfs()
# print(self.ans)
laba1 = tk.Label(frame_right, text="起点:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
laba2 = tk.Label(frame_right, text=f"{d.Nodes[self.cura][1]}", bg=BLUE, fg=BLACK, font=('微软雅黑', 8))
laba1.place(relx=0.05, rely=0.02 + y0, width=80, height=30)
laba2.place(relx=0.35, rely=0.02 + y0, width=50, height=30)
labb1 = tk.Label(frame_right, text="终点:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
labb2 = tk.Label(frame_right, text=f"{d.Nodes[self.curb][1]}", bg=BLUE, fg=BLACK, font=('微软雅黑', 8))
labb1.place(relx=0.52, rely=0.02 + y0, width=80, height=30)
labb2.place(relx=0.82, rely=0.02 + y0, width=50, height=30)
y0 += 0.1
lab1 = tk.Label(frame_right, text="遍历路径数目:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
lab2 = tk.Label(frame_right, text=f"{self.way_sum}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12))
lab1.place(relx=0.1, rely=0.05 + y0, width=100, height=30)
lab2.place(relx=0.5, rely=0.05 + y0, width=100, height=30)
lab1 = tk.Label(frame_right, text="求解花费时间:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
lab2 = tk.Label(frame_right, text=f'{self.end - self.start:.4f} s', bg=BLUE, fg=BLACK, font=('微软雅黑', 12))
lab1.place(relx=0.1, rely=0.10 + y0, width=100, height=30)
lab2.place(relx=0.5, rely=0.10 + y0, width=100, height=30)
lab = tk.Label(frame_right, text="自动求解时间最短路径", bg=RED, fg=BLACK, font=('微软雅黑', 20))
lab.place(rely=0.02, width=300, height=30)
B = tk.Button(frame_right, text="返回", command=lambda: self.Solve_display())
B.place(relx=0.1, rely=y0, width=50, height=30)
lab1 = tk.Label(frame_right, text="时间最短路径:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
f = 0
way = ''
for a in self.ans:
if f == 0:
f = 1
else:
way += "->"
way += d.Nodes[a][1]
# way += d.Nodes[0][1]
# print(ans, "444", way)
# print (ans)
lab2 = tk.Label(frame_right, text=f"{way}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12), wraplength=200,
justify='left')
tim = 0
cost = 0
for i in range(len(self.ans) - 1):
tim += d.Edges[G.node_edge(self.ans[i], self.ans[i + 1])][7]
cost += d.Edges[G.node_edge(self.ans[i], self.ans[i + 1])][6]
lab1.place(relx=0.1, rely=0.2 + y0, width=100, height=30)
lab2.place(relx=0.1, rely=0.25 + y0, width=200, height=100)
lab1 = tk.Label(frame_right, text="该路径时间:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
lab2 = tk.Label(frame_right, text=f"{tim} min", bg=BLUE, fg=BLACK, font=('微软雅黑', 12))
lab1.place(relx=0.1, rely=0.5 + y0, width=100, height=30)
lab2.place(relx=0.5, rely=0.5 + y0, width=100, height=30)
lab1 = tk.Label(frame_right, text="该路径距离:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
lab2 = tk.Label(frame_right, text=f'{cost} km', bg=BLUE, fg=BLACK, font=('微软雅黑', 12))
lab1.place(relx=0.1, rely=0.55 + y0, width=100, height=30)
lab2.place(relx=0.5, rely=0.55 + y0, width=100, height=30)
def auto_lowest_cost_condition(self): # 标记遍历路径(必经)
for w in frame_right.winfo_children():
w.destroy()
# 清除右侧组件
a = -1
b = -1
for node in d.Nodes:
if node[2] == 1:
a = node[0]
if node[2] == 2:
b = node[0]
if a == -1 or b == -1:
tk.messagebox.askokcancel(title='错误', message='未选择节点')
return
self.cura = a
self.curb = b
y0 = 0.1
self.start = time.time()
self.lowest_cost_dfs_condition()
self.end = time.time()
# print(self.ans)
laba1 = tk.Label(frame_right, text="起点:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
laba2 = tk.Label(frame_right, text=f"{d.Nodes[self.cura][1]}", bg=BLUE, fg=BLACK, font=('微软雅黑', 8))
laba1.place(relx=0.05, rely=0.02 + y0, width=80, height=30)
laba2.place(relx=0.35, rely=0.02 + y0, width=50, height=30)
labb1 = tk.Label(frame_right, text="终点:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
labb2 = tk.Label(frame_right, text=f"{d.Nodes[self.curb][1]}", bg=BLUE, fg=BLACK, font=('微软雅黑', 8))
labb1.place(relx=0.52, rely=0.02 + y0, width=80, height=30)
labb2.place(relx=0.82, rely=0.02 + y0, width=50, height=30)
y0 += 0.1
lab1 = tk.Label(frame_right, text="遍历路径数目:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
lab2 = tk.Label(frame_right, text=f"{self.way_sum}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12))
lab1.place(relx=0.1, rely=0.05 + y0, width=100, height=30)
lab2.place(relx=0.5, rely=0.05 + y0, width=100, height=30)
lab1 = tk.Label(frame_right, text="求解花费时间:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
lab2 = tk.Label(frame_right, text=f'{self.end - self.start:.4f} s', bg=BLUE, fg=BLACK, font=('微软雅黑', 12))
lab1.place(relx=0.1, rely=0.10 + y0, width=100, height=30)
lab2.place(relx=0.5, rely=0.10 + y0, width=100, height=30)
lab = tk.Label(frame_right, text="求解最短路径(含必经点)", bg=RED, fg=BLACK, font=('微软雅黑', 18))
lab.place(rely=0.02, width=300, height=30)
B = tk.Button(frame_right, text="返回", command=lambda: self.Solve_display())
B.place(relx=0.1, rely=y0, width=50, height=30)
lab1 = tk.Label(frame_right, text="距离最短路径:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
if not self.check_condition(self.ans):
way = '未找到合法路径'
else:
f = 0
way = ''
for a in self.ans:
if f == 0:
f = 1
else:
way += "->"
way += d.Nodes[a][1]
lab2 = tk.Label(frame_right, text=f"{way}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12), wraplength=200,
justify='left')
tim = 0
cost = 0
for i in range(len(self.ans) - 1):
tim += d.Edges[G.node_edge(self.ans[i], self.ans[i + 1])][7]
cost += d.Edges[G.node_edge(self.ans[i], self.ans[i + 1])][6]
lab1.place(relx=0.1, rely=0.2 + y0, width=100, height=30)
lab2.place(relx=0.1, rely=0.25 + y0, width=200, height=100)
lab1 = tk.Label(frame_right, text="该路径时间:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
lab2 = tk.Label(frame_right, text=f"{tim} min", bg=BLUE, fg=BLACK, font=('微软雅黑', 12))
lab1.place(relx=0.1, rely=0.55 + y0, width=100, height=30)
lab2.place(relx=0.5, rely=0.55 + y0, width=100, height=30)
lab1 = tk.Label(frame_right, text="该路径距离:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
lab2 = tk.Label(frame_right, text=f'{cost} km', bg=BLUE, fg=BLACK, font=('微软雅黑', 12))
lab1.place(relx=0.1, rely=0.5 + y0, width=100, height=30)
lab2.place(relx=0.5, rely=0.5 + y0, width=100, height=30)
def auto_lowest_cost(self): # 标记遍历路径
for w in frame_right.winfo_children():
w.destroy()
# 清除右侧组件
a = -1
b = -1
for node in d.Nodes:
if node[2] == 1:
a = node[0]
if node[2] == 2:
b = node[0]
if a == -1 or b == -1:
tk.messagebox.askokcancel(title='错误', message='未选择节点')
return
self.cura = a
self.curb = b
y0 = 0.1
self.start = time.time()
self.lowest_cost_dfs()
self.end = time.time()
# print(self.ans)
laba1 = tk.Label(frame_right, text="起点:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
laba2 = tk.Label(frame_right, text=f"{d.Nodes[self.cura][1]}", bg=BLUE, fg=BLACK, font=('微软雅黑', 8))
laba1.place(relx=0.05, rely=0.02 + y0, width=80, height=30)
laba2.place(relx=0.35, rely=0.02 + y0, width=50, height=30)
labb1 = tk.Label(frame_right, text="终点:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
labb2 = tk.Label(frame_right, text=f"{d.Nodes[self.curb][1]}", bg=BLUE, fg=BLACK, font=('微软雅黑', 8))
labb1.place(relx=0.52, rely=0.02 + y0, width=80, height=30)
labb2.place(relx=0.82, rely=0.02 + y0, width=50, height=30)
y0 += 0.1
lab1 = tk.Label(frame_right, text="遍历路径数目:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
lab2 = tk.Label(frame_right, text=f"{self.way_sum}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12))
lab1.place(relx=0.1, rely=0.05 + y0, width=100, height=30)
lab2.place(relx=0.5, rely=0.05 + y0, width=100, height=30)
lab1 = tk.Label(frame_right, text="求解花费时间:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
lab2 = tk.Label(frame_right, text=f'{self.end - self.start:.4f} s', bg=BLUE, fg=BLACK, font=('微软雅黑', 12))
lab1.place(relx=0.1, rely=0.10 + y0, width=100, height=30)
lab2.place(relx=0.5, rely=0.10 + y0, width=100, height=30)
lab = tk.Label(frame_right, text="自动求解距离最短路径", bg=RED, fg=BLACK, font=('微软雅黑', 20))
lab.place(rely=0.02, width=300, height=30)
B = tk.Button(frame_right, text="返回", command=lambda: self.Solve_display())
B.place(relx=0.1, rely=y0, width=50, height=30)
lab1 = tk.Label(frame_right, text="距离最短路径:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
f = 0
way = ''
for a in self.ans:
if f == 0:
f = 1
else:
way += "->"
way += d.Nodes[a][1]
# way += d.Nodes[0][1]
# print(ans, "444", way)
# print (ans)
lab2 = tk.Label(frame_right, text=f"{way}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12), wraplength=200,
justify='left')
tim = 0
cost = 0
for i in range(len(self.ans) - 1):
tim += d.Edges[G.node_edge(self.ans[i], self.ans[i + 1])][7]
cost += d.Edges[G.node_edge(self.ans[i], self.ans[i + 1])][6]
lab1.place(relx=0.1, rely=0.2 + y0, width=100, height=30)
lab2.place(relx=0.1, rely=0.25 + y0, width=200, height=100)
lab1 = tk.Label(frame_right, text="该路径时间:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
lab2 = tk.Label(frame_right, text=f"{tim} min", bg=BLUE, fg=BLACK, font=('微软雅黑', 12))
lab1.place(relx=0.1, rely=0.55 + y0, width=100, height=30)
lab2.place(relx=0.5, rely=0.55 + y0, width=100, height=30)
lab1 = tk.Label(frame_right, text="该路径距离:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
lab2 = tk.Label(frame_right, text=f'{cost} km', bg=BLUE, fg=BLACK, font=('微软雅黑', 12))
lab1.place(relx=0.1, rely=0.5 + y0, width=100, height=30)
lab2.place(relx=0.5, rely=0.5 + y0, width=100, height=30)
def dfs_panel_condition(self):
# 标记遍历路径(区分必经/非必经)
for w in frame_right.winfo_children():
w.destroy()
# 清除右侧组件
y0 = 0.1
self.start = time.time()
self.node_dfs_condition()
self.end = time.time()
lab1 = tk.Label(frame_right, text="遍历路径数目:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
lab2 = tk.Label(frame_right, text=f"{self.way_sum}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12))
lab1.place(relx=0.1, rely=0.05 + y0, width=100, height=30)
lab2.place(relx=0.5, rely=0.05 + y0, width=100, height=30)
lab1 = tk.Label(frame_right, text="求解花费时间:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
lab2 = tk.Label(frame_right, text=f'{self.end - self.start:.4f} s', bg=BLUE, fg=BLACK, font=('微软雅黑', 12))
lab1.place(relx=0.1, rely=0.10 + y0, width=100, height=30)
lab2.place(relx=0.5, rely=0.10 + y0, width=100, height=30)
lab = tk.Label(frame_right, text="求解路径(区分必经点)", bg=RED, fg=BLACK, font=('微软雅黑', 20))
lab.place(rely=0.02, width=300, height=30)
B = tk.Button(frame_right, text="返回", command=lambda: self.Solve_display())
B.place(relx=0.1, rely=y0, width=50, height=30)
lab1 = tk.Label(frame_right, text="最短路径:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
# 根据遍历结果输出最短路径
way = ""
for a in self.ans:
way += d.Nodes[a][1]
way += "->"
way += d.Nodes[0][1]
if not self.check_condition(self.ans):
way = "未找到联通路径"
lab2 = tk.Label(frame_right, text=f"{way}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12), wraplength=200,
justify='left')
lab1.place(relx=0.1, rely=0.2 + y0, width=80, height=30)
lab2.place(relx=0.1, rely=0.25 + y0, width=200, height=100)
more = 0
way = ''
for moreans in self.mutians:
more += 1
if more > 1:
way += '\n'
way += str(more) + ': '
for a in moreans:
way += d.Nodes[a][1]
way += "->"
way += d.Nodes[0][1]
if more:
lab1 = tk.Label(frame_right, text="其他最短路径:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
lab2 = scrolledtext.ScrolledText(frame_right, width=50, height=5, bg=BLUE, fg=BLACK, font=('微软雅黑', 12))
lab2.insert('end', way)
lab2.configure(state=DISABLED)
lab1.place(relx=0.1, rely=0.2 + y0 + 0.2, width=120, height=30)
lab2.place(relx=0.1, rely=0.25 + y0 + 0.2, width=240, height=200)
def dfs_panel(self): # dfs面板显示
for w in frame_right.winfo_children():
w.destroy()# 清除右侧组件
y0 = 0.1
self.start = time.time()#记录开始时间
self.node_dfs()#执行dfs搜索算法
self.end = time.time()#记录结束时间
lab1 = tk.Label(frame_right, text="遍历路径数目:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
lab2 = tk.Label(frame_right, text=f"{self.way_sum}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12))
lab1.place(relx=0.1, rely=0.05 + y0, width=100, height=30)
lab2.place(relx=0.5, rely=0.05 + y0, width=100, height=30)
lab1 = tk.Label(frame_right, text="求解花费时间:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
lab2 = tk.Label(frame_right, text=f'{self.end - self.start:.4f} s', bg=BLUE, fg=BLACK, font=('微软雅黑', 12))
lab1.place(relx=0.1, rely=0.10 + y0, width=100, height=30)
lab2.place(relx=0.5, rely=0.10 + y0, width=100, height=30)
lab = tk.Label(frame_right, text="自动求解优化路径-遍历", bg=RED, fg=BLACK, font=('微软雅黑', 20))
lab.place(rely=0.02, width=300, height=30)
B = tk.Button(frame_right, text="返回", command=lambda: self.Solve_display())
B.place(relx=0.1, rely=y0, width=50, height=30)
lab1 = tk.Label(frame_right, text="最短路径:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
# 根据遍历结果输出最短路径
way = ""
for a in self.ans:
way += d.Nodes[a][1]
way += "->"
way += d.Nodes[0][1]
if not len(self.ans) == len(d.Nodes):
way = "未找到联通路径"
lab2 = tk.Label(frame_right, text=f"{way}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12), wraplength=200,
justify='left')
lab1.place(relx=0.1, rely=0.2 + y0, width=80, height=30)
lab2.place(relx=0.1, rely=0.25 + y0, width=200, height=100)
# 如果有多条最短路径,则根据遍历结果依次输出
more = 0
way = ''
for moreans in self.mutians:
more += 1
if more > 1:
way += '\n'
way += str(more) + ': '
for a in moreans:
way += d.Nodes[a][1]
way += "->"
way += d.Nodes[0][1]
if more:
lab1 = tk.Label(frame_right, text="其他最短路径:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
lab2 = scrolledtext.ScrolledText(frame_right, width=50, height=5,bg=BLUE, fg=BLACK, font=('微软雅黑', 12))
lab2.insert('end', way)
lab2.configure(state=DISABLED)
lab1.place(relx=0.1, rely=0.2 + y0 + 0.2, width=120, height=30)
lab2.place(relx=0.1, rely=0.25 + y0 + 0.2, width=240, height=200)
def greedy_panel(self): # 标记贪心路径
for w in frame_right.winfo_children():
w.destroy()
# 清除右侧组件
lab = tk.Label(frame_right, text="自动求解贪心路径", bg=RED, fg=BLACK, font=('微软雅黑', 20))
lab.place(rely=0.02, width=300, height=30)
y0 = 0.1
B = tk.Button(frame_right, text="返回", command=lambda: self.Solve_display())
B.place(relx=0.1, rely=y0, width=50, height=30)
lab1 = tk.Label(frame_right, text="贪心法求得路径:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
lab1.place(relx=0.1, rely=0.2 + y0, width=150, height=30)
# 求解贪心路径
self.node_greedy()
lab1 = tk.Label(frame_right, text="求解花费时间:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
lab1.place(relx=0.1, rely=0.10 + y0, width=100, height=30)
lab2 = tk.Label(frame_right, text=f'{self.end - self.start:.4f} s', bg=BLUE, fg=BLACK, font=('微软雅黑', 12))
lab2.place(relx=0.5, rely=0.10 + y0, width=100, height=30)
# 显示求解获得的贪心路径
way = ""
for a in self.ans:
way += d.Nodes[a][1]
way += "->"
way += d.Nodes[0][1]
if not len(self.ans) == len(d.Nodes):
way = "贪心法无法找到通路"
lab2 = tk.Label(frame_right, text=f"{way}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12), wraplength=200,
justify='left')
lab2.place(relx=0.1, rely=0.25 + y0, width=200, height=100)
# 显示当前路径消耗的总成本与总时间
dis = 0
tim = 0
for edge in d.Edges:
if edge[4] == True:
dis += edge[6]
tim += edge[7]
lab1 = tk.Label(frame_right, text="路径距离/成本:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
lab2 = tk.Label(frame_right, text=f'{dis}', bg=BLUE, fg=BLACK, font=('微软雅黑', 12))
lab1.place(relx=0.1, rely=0.40 + y0, width=130, height=30)
lab2.place(relx=0.5, rely=0.40 + y0, width=100, height=30)
lab1 = tk.Label(frame_right, text="路径时间:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
lab2 = tk.Label(frame_right, text=f'{tim}', bg=BLUE, fg=BLACK, font=('微软雅黑', 12))
lab1.place(relx=0.1, rely=0.45 + y0, width=130, height=30)
lab2.place(relx=0.5, rely=0.45 + y0, width=100, height=30)
def check_condition(self, ways):
con = 0
for w in ways:
if d.Nodes[w][4] == 1:
con += 1
if con == self.con:
return 1
return 0
def dfs_condition(self, i, ways, sum, flag):
if self.check_condition(ways) and d.Edges[G.node_edge(i, 0)][8] == 1 and d.Edges[G.node_edge(i, 0)][3] == 1:
# 如果遍历的必经节点数目符合要求,则说明这是一条符合要求的路径
self.way_sum += 1#增加一个已搜索路径
sum += d.Edges[G.node_edge(i, 0)][6]#更新路径花费
if sum < self.minn:# 如果该路径的cost小于minn则更新最短路径
self.ans.clear()#清除原答案
self.mutians.clear()#清除其他答案
self.ans = ways.copy()#将当前路径加入到答案中
self.minn = sum#更新最短路径
elif sum == self.minn:# 如果该路径的cost等于minn则记录在mutians中
self.mutians.append(ways.copy())#将当前路径加入到其他路径数组中
for j in d.Edges:# 遍历该节点的所有路径,并且对所有可能路径进行尝试
if j[1] == i and flag[j[2]] == 0 and j[8] == 1 and j[3] == 1:
ways.append(j[2])# 如果存在一节点还没被访问过,则将其加入搜索队列
flag[j[2]] = 1
self.dfs_condition(j[2], ways, sum + j[6], flag)
flag[j[2]] = 0
ways.pop()
if j[2] == i and flag[j[1]] == 0 and j[8] == 1 and j[3] == 1:
flag[j[1]] = 1
ways.append(j[1])
self.dfs_condition(j[1], ways, sum + j[6], flag)
ways.pop()
flag[j[1]] = 0
return
way_flag = 0#标记问题是否解决
def random_way(self, i, ways, sum, flag):
if self.way_flag:#若已找到一条路径,则直接返回
return
if len(ways) == len(d.Nodes) and d.Edges[G.node_edge(i, 0)][8] == 1\
and d.Edges[node_edge(i, 0)][3] == 1: # 如果遍历的节点数目符合要求,则说明这是一条符合要求的路径
sum += d.Edges[node_edge(i, 0)][6] # 更新当前路径长度
self.way_flag = 1#将问题标记为已解决
for way in ways: # 输出当前答案
print(way, end=' ')
return
cur_Edges = d.Edges.copy()# 随机打乱该点能接触到的路径
random.shuffle(cur_Edges)
for j in cur_Edges:
# 遍历该节点的所有路径,并且对所有可能路径进行尝试
if j[1] == i and flag[j[2]] == 0 and j[8] == 1 and j[3] == 1:
# 如果存在一条路径,且对面节点还没被访问过,则将其加入搜索队列
ways.append(j[2])#将该点加入路径
flag[j[2]] = 1#将该点标记为已探索
self.random_way(j[2], ways, sum + j[6], flag)# 递归搜索路径
flag[j[2]] = 0#将该点标记为未探索
ways.pop()#将该点移除路径
if j[2] == i and flag[j[1]] == 0 and j[8] == 1 and j[3] == 1:
flag[j[1]] = 1#将该点加入路径
ways.append(j[1])#将该点标记为已探索
self.random_way(j[1], ways, sum + j[6], flag)# 递归搜索路径
ways.pop()#将该点标记为未探索#将该点移除路径
flag[j[1]] = 0#将该点标记为未探索
return
def dfs(self, i, ways, sum, flag):
if len(ways) == len(d.Nodes) and d.Edges[node_edge(i, 0)][8] == 1\
and d.Edges[node_edge(i, 0)][3] == 1: # 如果遍历的节点数目符合要求,则符合要求
self.way_sum += 1 # 遍历路径的数目加一
sum += d.Edges[node_edge(i, 0)][6] # 更新当前路径长度
if sum < self.minn: # 如果该路径的cost小于minn则更新最短路径
self.ans.clear() # 清除ans数组
self.mutians.clear() # 清除其他答案数组
self.ans = ways.copy()
self.minn = sum # 更新最短路径
elif sum == self.minn: # 如果该路径的cost等于minn则记录在mutians中
moreans = []#用于记录这条路径node_dfs_condition
for way in ways:#将路径途径节点逐个加入
moreans.append(way)
self.mutians.append(moreans)# 将该路径加入答案中
cur_Edges = d.Edges.copy()# 随机打乱该点能接触到的路径
random.shuffle(cur_Edges)
for j in cur_Edges:# 遍历该节点的所有路径,并且对所有可能路径进行尝试
if j[1] == i and flag[j[2]] == 0 and j[8] == 1 and j[3] == 1:
# 如果存在一条路径,且对面节点还没被访问过,则将其加入搜索队列
ways.append(j[2])#将该点加入路径
flag[j[2]] = 1#将该点标记为已探索
self.dfs(j[2], ways, sum + j[6], flag)# 递归搜索路径
flag[j[2]] = 0#将该点标记为未探索
ways.pop()#将该点移除路径
if j[2] == i and flag[j[1]] == 0 and j[8] == 1 and j[3] == 1:
flag[j[1]] = 1#将该点加入路径
ways.append(j[1])#将该点标记为已探索
self.dfs(j[1], ways, sum + j[6], flag)# 递归搜索路径
ways.pop()#将该点标记为未探索#将该点移除路径
flag[j[1]] = 0#将该点标记为未探索
return
def lcost_dfs_condition(self, i, ways, sum, flag):
if i == self.curb:# 若该节点为目标节点
self.way_sum += 1#遍历路径数加一
if self.check_condition(ways):# 若遍历节点数符合要求
if sum < self.minn:#若路径花费更短,则更新答案
self.ans = ways.copy()#更新答案
self.minn = sum#更新最短路径
return
for j in d.Edges:#遍历该点能到达的所有节点
if j[1] == i and flag[j[2]] == 0 and j[8] == 1 and j[3] == 1:#若该点未访问,则尝试访问
ways.append(j[2])#将该点加入路径
flag[j[2]] = 1#将该点标记为访问
self.lcost_dfs_condition(j[2], ways, sum + j[6], flag)#递归搜索路径
flag[j[2]] = 0#将该点移除路径
ways.pop()#将该点移除路径
if j[2] == i and flag[j[1]] == 0 and j[8] == 1 and j[3] == 1:
flag[j[1]] = 1#将该点标记为访问
ways.append(j[1])#将该点加入路径
self.lcost_dfs_condition(j[1], ways, sum + j[6], flag)#递归搜索路径
ways.pop()#将该点移除路径
flag[j[1]] = 0#将该点标记为未访问
return
def lcost_dfs(self, i, ways, sum, flag):
# print(i)
if i == self.curb:
self.way_sum += 1
# print(ways, sum, self.minn)
if sum < self.minn:
self.ans = ways.copy()
self.minn = sum
return
for j in d.Edges:
if j[1] == i and flag[j[2]] == 0 and j[8] == 1 and j[3] == 1:
ways.append(j[2])
flag[j[2]] = 1
self.lcost_dfs(j[2], ways, sum + j[6], flag)
flag[j[2]] = 0
ways.pop()
if j[2] == i and flag[j[1]] == 0 and j[8] == 1 and j[3] == 1:
flag[j[1]] = 1
ways.append(j[1])
self.lcost_dfs(j[1], ways, sum + j[6], flag)
ways.pop()
flag[j[1]] = 0
return
def ltime_dfs(self, i, ways, sum, flag):
if i == self.curb:#若已经到达目标点,则结束搜索
self.way_sum += 1#遍历路径加一
if sum < self.minn:#若耗时少于最短时间
self.ans = ways.copy()#更新答案
self.minn = sum#更新最短时间
return
for j in d.Edges:#遍历当前节点能到达的所有节点
if j[1] == i and flag[j[2]] == 0 and j[8] == 1 and j[3] == 1:#若该节点未遍历则尝试该条路径
ways.append(j[2])#将该节点加入路径
flag[j[2]] = 1#将该节点标记为已经过
self.ltime_dfs(j[2], ways, sum + j[7], flag)#进行递归搜索
flag[j[2]] = 0#将该节点标记为未经过
ways.pop()
if j[2] == i and flag[j[1]] == 0 and j[8] == 1 and j[3] == 1:
flag[j[1]] = 1#将该节点加入路径
ways.append(j[1])#将该节点标记为已经过
self.ltime_dfs(j[1], ways, sum + j[7], flag)#进行递归搜索
ways.pop()#将该节点移除路径
flag[j[1]] = 0#将该节点标记为未经过
def lowest_cost_dfs_condition(self): # 遍历
# 每两个点之间只保留最短路径
E.edge_del_all(1)
self.ans.clear()
self.way_sum = 0
self.con = 0
for n in d.Nodes:
if n[4]:
self.con += 1
for edge in d.Edges:
edge[4] = False
# for i in range(len(d.Nodes)):
i = self.cura
self.minn = float("inf")
flag = [0] * len(d.Nodes)
flag[i] = 1
self.lcost_dfs_condition(i, [i], 0, flag)
for way in range(len(self.ans) - 1):
d.Edges[G.node_edge(self.ans[way], self.ans[way + 1])][4] = True
G.draw()
def lowest_cost_dfs(self): # 遍历
# 每两个点之间只保留最短路径
E.edge_del_all(1)
# E.newedge_del_all()
self.way_sum = 0
self.ans = []
for edge in d.Edges:
edge[4] = False
# for i in range(len(d.Nodes)):
i = self.cura
self.minn = float("inf")
flag = [0] * len(d.Nodes)
flag[i] = 1
self.lcost_dfs(i, [i], 0, flag)
for way in range(len(self.ans) - 1):
d.Edges[G.node_edge(self.ans[way], self.ans[way + 1])][4] = True
G.draw()
def lowest_time_dfs(self): # 遍历
self.start = time.time()#记录开始时间
E.edge_del_all(2)#每两条边只保留时间最短路径(剪枝)
self.way_sum = 0#初始化路径数目
self.ans = []#清空答案
for edge in d.Edges:
edge[4] = False#清空标记
i = self.cura#初始化出发点
self.minn = float("inf")#初始化最短路径为无穷
flag = [0] * len(d.Nodes)#初始化已到达点
flag[i] = 1#将出发点标记为已到达
self.ltime_dfs(i, [i], 0, flag)#深度优先搜索确定答案
for way in range(len(self.ans) - 1):#标记途径路径
d.Edges[G.node_edge(self.ans[way], self.ans[way + 1])][4] = True
self.end = time.time()#记录结束时间
G.draw()#重新绘图
def node_dfs_condition(self):# 遍历
E.edge_del_all(1)# 每两个节点之间只保留距离最短的一条
self.con = 0#初始化经过的必经点数目
self.way_sum = 0# 初始化遍历的节点数目
self.ans.clear()#清除答案数组
for node in d.Nodes:#计算必经点数量
if node[4] == 1:
self.con += 1
for edge in d.Edges:#清空标记
edge[4] = False
i = 0
self.minn = float("inf")#初始化最短路径为无穷
flag = [0] * len(d.Nodes)#初始化已经过数组
flag[i] = 1#将初始点标记为已经过
self.dfs_condition(i, [0], 0, flag)#开始遍历搜索合法路径
if not self.check_condition(self.ans):#若没找到合法路径在进行报告
tk.messagebox.askokcancel(title='结果', message='未找到联通路径')
G.draw()
return
for way in range(len(self.ans) - 1):#逐个标记答案路径
d.Edges[G.node_edge(self.ans[way], self.ans[way + 1])][4] = True
last = self.ans.pop()#弹出最后一个点
d.Edges[G.node_edge(last, i)][4] = True#链接首位形成环线
self.ans.append(last)#重新加入该点
G.draw()#绘图
def node_dfs(self): # 遍历
self.start = time.time() # 记录开始时间
E.edge_del_all(1)# 每两个节点之间只保留距离最短的一条
self.way_sum = 0# 初始化遍历的节点数目
for edge in d.Edges:#清空标记
edge[4] = False
i = 0#起始点
self.minn = float("inf")#初始化最小值为正无穷
flag = [0] * len(d.Nodes)#初始化已经过点
flag[i] = 1#将起点标记为已经过
self.dfs(i, [0], 0, flag)#使用dfs算法搜索路径
if not len(self.ans) == len(d.Nodes):#若找不到符合要求的路径,则输出信息
tk.messagebox.askokcancel(title='结果', message='未找到联通路径')
G.draw()
return
for way in range(len(self.ans) - 1):#标记一条路径
d.Edges[G.node_edge(self.ans[way], self.ans[way + 1])][4] = True
last = self.ans.pop()#取出最后一个点
d.Edges[G.node_edge(last, i)][4] = True#将起始点与最终点链接形成环线
self.ans.append(last)#将最终点加回ans中
self.end = time.time() # 记录结束时间
G.draw()
def node_greedy(self): # 贪心
self.start = time.time()#记录开始时间
self.ans.clear()#初始化答案列表
E.edge_del_all(1)# 两点间仅保留距离最短路径
for edge in d.Edges:#清空标记
edge[4] = False
i = 0 # 起始点
ways = [i]
flag = [0] * len(d.Nodes) # 初始化已经过点
cur = i#初始化起始点
sum = 0#初始化路径长度
flag[cur] = 1#将起始点标记为已经过
nxt = cur
for ii in range(len(d.Nodes)):
minn = float("inf")# 初始化最小值
for j in d.Edges:# 每一步选择当前最短的链接加到路径中去
if j[1] == cur and flag[j[2]] == 0 and j[6] < minn and j[8] == 1 and j[3] == 1:
nxt = j[2]
minn = j[6]
if j[2] == cur and flag[j[1]] == 0 and j[6] < minn and j[8] == 1 and j[3] == 1:
nxt = j[1]
minn = j[6]
if nxt != cur:#只要找到了新的路径,则加入路径中
ways.append(nxt)
flag[nxt] = 1
sum += minn
cur = nxt
self.ans = ways.copy()
# 如果找到的路径不合法,则表示贪心法无法求解得到合法路径
if (not len(self.ans) == len(d.Nodes)) or (d.Edges[G.node_edge(0, ways[len(ways) - 1])][3] == 0):
tk.messagebox.askokcancel(title='结果', message='贪心法无法找到合法路径')
self.ans.clear()
return -1
for way in range(len(ways) - 1):#标记一条路径
d.Edges[G.node_edge(ways[way], ways[way + 1])][4] = True
d.Edges[G.node_edge(ways[len(ways) - 1], i)][4] = True#标记起点终点形成环线
self.end = time.time()#记录结束时间
G.draw()
# root.update()
def check(self): # 检查是否存在最短路
find = []
for i in range(len(d.Nodes)):
find.append(i)
for edge in d.Edges:
if edge[8] == 1 and edge[3] == 0:
continue
x = edge[1]
y = edge[2]
while not x == find[x]:
x = find[x]
while not y == find[y]:
y = find[y]
if x < y:
find[y] = x
else:
find[x] = y
flag = 1
for i in range(len(d.Nodes)):
if not find[i] == find[0]:
flag = 0
if flag:
tk.messagebox.askokcancel(title='结果', message='该图存在最短路')
else:
tk.messagebox.askokcancel(title='结果', message='该图不能完全互通')
if __name__ == '__main__':
G.draw()
solve = Solve()
solve.Solve_display()
mainloop()

@ -0,0 +1,271 @@
# -*- encoding: utf-8 -*-
from head import *
from NODE import *
from SOLVE import *
solve = Solve()
N = Node()
class Ways:
def __init__(self):
self.user_way = []#记录用户路径
self.user_cur = 0#记录用户所在点
self.user_flag = set()#记录用户已经过的点
def clear(self):
self.user_flag.clear()
self.user_way.clear()
self.user_cur = 0
self.auto_ways()
def check_user_best2(self): # 检查用户路径是不是最佳路径
solve.node_dfs()#遍历计算最优路径
if not len(self.user_way) == len(solve.ans):# 节点个数不一样肯定不匹配
return 0
dis_user = 0
dis_ans = 0
num = len(self.user_way)
for i in range(num - 1):#计算两条路径的长度
dis_user += d.Edges[G.node_edge(self.user_way[i], self.user_way[i + 1])][6]
dis_ans += d.Edges[G.node_edge(solve.ans[i], solve.ans[i + 1])][6]
if dis_ans == dis_user: # 用户路径长度与最短路径长度相同,用户路径是最短路
return 1
return 0# 匹配失败,不是最短路
def check_user_best(self): # 检查用户路径是不是最佳路径
# global user_way
# global ans
solve.node_dfs()
# 长度不一样肯定不匹配
if not len(self.user_way) == len(solve.ans):
return 0
dis_user = 0
dis_ans = 0
# print(user_way)
# print(ans)
num = len(self.user_way)
for i in range(num - 1):
dis_user += d.Edges[G.node_edge(self.user_way[i], self.user_way[i + 1])][6]
dis_ans += d.Edges[G.node_edge(solve.ans[i], solve.ans[i + 1])][6]
return dis_ans, dis_user
# if dis_ans == dis_user: # 匹配成功,用户路径是最短路
# return 1
# # 匹配失败,不是最短路
# return 0
def show_best_ans(self, top, best, user):
lab1 = tk.Label(top, text="最短路径:", fg=BLACK, font=('微软雅黑', 20))
b_way = ""
for a in solve.ans:
b_way += d.Nodes[a][1]
b_way += "->"
b_way += d.Nodes[0][1]
y0 = 0.05
lab2 = tk.Label(top, text=f"{b_way}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12), wraplength=200, justify='left')
lab1.place(relx=0.1, rely=0.50 + y0, width=150, height=30)
lab2.place(relx=0.4, rely=0.45 + y0, width=200, height=100)
lab2 = tk.Label(top, text=f"最佳路径总成本:{best}\n用户路径总成本:{user}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12), wraplength=200, justify='left')
lab2.place(relx=0.4, rely=0.7 + y0, width=200, height=100)
def show_BEST(self):
top = Toplevel(root, width=500, height=500)
top.title('判断路径是否为最短路径')# 弹出一个新的窗口来显示判断结果
lab1 = tk.Label(top, text="用户路径:", fg=BLACK, font=('微软雅黑', 20))# 显示当前用户路径信息
u_way = ""#生成用户路径
for a in self.user_way:
u_way += d.Nodes[a][1]
u_way += "->"
u_way += d.Nodes[0][1]#回到起始点
y0 = 0.05
lab2 = tk.Label(top, text=f"{u_way}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12), wraplength=200,justify='left')
lab1.place(relx=0.1, rely=0.10 + y0, width=150, height=30)
lab2.place(relx=0.4, rely=0.05 + y0, width=200, height=100)
best, user = self.check_user_best()# 计算最优路径与用户路径的总花费
if best == user:# 如果最优路径与用户路径的总花费相等,则说明用户路径是最短路径
result = "用户路径是最短路径"
else:#否则说明用户路径不是最短路径
result = "用户路径不是最短路径"
# 如果用户路径不是最短路径,则增加一个"显示最佳路径"的按钮
B = tk.Button(top, text="显示最佳路径", command=lambda: self.show_best_ans(top, best, user))
B.place(relx=0.6, rely=0.30 + y0, width=100, height=50)
lab = tk.Label(top, text=f"{result}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12), wraplength=200, justify='left')
lab.place(relx=0.1, rely=0.3 + y0, width=200, height=50)
def check_user_greey(self): # 检查用户路径是不是贪心路径,不是的话返回错误点
solve.node_greedy()# 计算贪心路径
if not len(self.user_way) == len(solve.ans):# 路径长度不一样肯定不匹配,直接返回
self.auto_ways()
return
num = len(self.user_way)
for i in range(num):#逐个节点进行匹配
if not self.user_way[i] == solve.ans[i]:# 若第i位匹配失败则返回i
return i
return -1#-1表示是贪心路径
def show_greddy_ans(self, top):
lab1 = tk.Label(top, text="最短路径:", fg=BLACK, font=('微软雅黑', 20))
b_way = ""
for a in solve.ans:
b_way += d.Nodes[a][1]
b_way += "->"
b_way += d.Nodes[0][1]
y0 = 0.05
lab2 = tk.Label(top, text=f"{b_way}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12), wraplength=200, justify='left')
lab1.place(relx=0.1, rely=0.50 + y0, width=150, height=30)
lab2.place(relx=0.4, rely=0.45 + y0, width=200, height=100)
def show_GREDDY(self):
top = Toplevel(root, width = 500, height = 500)
top.title('判断路径是否为贪心路径')# 新建一个窗口来显示判断路径是否为贪心路径的结果
lab1 = tk.Label(top, text="用户路径:", fg=BLACK, font=('微软雅黑', 20))
u_way = ""# 显示用户路径
for a in self.user_way:
u_way += d.Nodes[a][1]
u_way += "->"
u_way += d.Nodes[0][1]
y0 = 0.05
lab2 = tk.Label(top, text=f"{u_way}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12), wraplength=200,justify='left')
lab1.place(relx=0.1, rely=0.10 + y0, width=150, height=30)
lab2.place(relx=0.4, rely=0.05 + y0, width=200, height=100)
# 逐个节点比较用户路径是否为贪心路径
g = self.check_user_greey()
if g == -1:#如果用户路径是贪心路径则显示
result = '用户路径是贪心路径'
else:# 若用户路径不是贪心路径,则显示在第几步时选择出错,并将该次选择的正确选择与用户实际选择显示出来
result = '用户路径不是贪心路径'
result2 = '用户路径'+d.Nodes[self.user_way[g-1]][1]+'->'+d.Nodes[self.user_way[g]][1]+' 成本为%d\n'%d.Edges[G.node_edge(self.user_way[g-1],self.user_way[g])][6]
result2 += '贪心路径' + d.Nodes[solve.ans[g - 1]][1] + '->' + d.Nodes[solve.ans[g]][1] + ' 成本为%d\n' % d.Edges[G.node_edge(solve.ans[g-1],solve.ans[g])][6]
lab = tk.Label(top, text=result2, bg=BLUE, fg=BLACK, font=('微软雅黑', 12), wraplength=200, justify='left')
lab.place(relx=0.1, rely=0.5 + y0, width=250, height=100)
lab = tk.Label(top, text=result, bg=BLUE, fg=BLACK, font=('微软雅黑', 12), wraplength=250, justify='left')
lab.place(relx=0.1, rely=0.3 + y0, width=200, height=50)
self.auto_ways()#将结果输出到输出框
# 记录用户路径(路径操作)
def way_mark_display(self): # 用户路径显示
E.newedge_del_all(1)
for w in frame_right.winfo_children():
w.destroy()
# 清除右侧组件
lab = tk.Label(frame_right, text="路径操作", bg=RED, fg=BLACK, font=('微软雅黑', 20))
lab.place(relx=0.05, rely=0.02, width=300, height=30)
y0 = 0.1
lab1 = tk.Label(frame_right, text="用户路径:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
self.auto_ways()
way = ""
for a in self.user_way:
way += d.Nodes[a][1]
way += "->"
way += d.Nodes[0][1]
lab2 = tk.Label(frame_right, text=f"{way}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12), wraplength=200,
justify='left')
lab1.place(relx=0.1, rely=0.05 + y0, width=80, height=30)
lab2.place(relx=0.1, rely=0.15 + y0, width=200, height=100)
B = tk.Button(frame_right, text="清除路径", command=lambda: self.user_way_clear())
B.place(relx=0.8, rely=0.15 + y0, width=50, height=30)
B = tk.Button(frame_right, text="撤销", command=lambda: self.user_way_del())
B.place(relx=0.8, rely=0.20 + y0, width=50, height=30)
B = tk.Button(frame_right, text="检查路径", command=lambda: self.user_way_check())
B.place(relx=0.8, rely=0.25 + y0, width=50, height=30)
B = tk.Button(frame_right, text="判断路径是否为最短路径", command=lambda: self.user_way_best())
B.place(relx=0.1, rely=0.30 + y0, width=200, height=30)
B = tk.Button(frame_right, text="判断路径是否为贪心路径", command=lambda: self.user_way_greedy())
B.place(relx=0.1, rely=0.35 + y0, width=200, height=30)
def auto_ways(self): # 标记用户路径
for w in d.Edges:#清空路径标记
w[4] = 0
for N in d.Nodes:#清空节点标记
N[2] = 0
for w in self.user_way:# 标记用户已选的点
d.Nodes[w][2] = 5
for w in range(len(self.user_way) - 1):# 标记用户经过的路径
d.Edges[G.node_edge(self.user_way[w], self.user_way[w + 1])][4] = 1
if len(set(self.user_way)) == len(d.Nodes):# 如果已经访问所有节点,自动回到初始节点
d.Edges[G.node_edge(self.user_way[len(self.user_way) - 1], 0)][4] = 1
G.draw()# 按照标记重新绘制图形
def user_way_clear(self):
self.user_flag.clear()
self.user_flag.add(0)
self.user_way.clear()
self.user_cur = 0
self.user_way.append(0)
self.auto_ways()
self.way_mark_display()
def user_way_del(self): # 删除路径最后一步
if len(self.user_way) <= 1:
return
cur = self.user_way.pop()
self.user_cur = self.user_way[len(self.user_way) - 1]
self.user_flag.discard(cur)
self.auto_ways()
self.way_mark_display()
def way_check(self): # 检查路径是否合法
if not len(self.user_way) == len(d.Nodes):# 若用户路径没有遍历所有节点,则不合法
return "Error: not all nodes are traversed in the user path"
for w in range(len(self.user_way) - 1):# 若用户路径不连通,则不合法
if not d.Edges[G.node_edge(self.user_way[w], self.user_way[w + 1])][3] == 1:
return "Error: user path is not connected between node {} and node {}".format(self.user_way[w], self.user_way[w + 1])
if d.Edges[G.node_edge(0, self.user_way[len(self.user_way) - 1])][3] == 1:
return "Valid path"
else:# 若用户路径无法回到出发点,则不合法
return "Error: user path does not return to the starting point"
def user_way_check(self): # 检查路径是否合法并弹窗
check = self.way_check()
if not check == "Valid path":
result = tk.messagebox.askokcancel(title='结果', message = check)
else:
result = tk.messagebox.askokcancel(title='结果', message ='该路径合法')
def user_way_add(self, nxt): # 用户路径操作
# print(nxt)
if nxt in self.user_flag:
return
# 看用户选择的路径是否存在
if d.Edges[G.node_edge(self.user_cur, nxt)][3] == 1:
# 将该点加入用户路径
self.user_way.append(nxt)
self.user_flag.add(nxt)
self.user_cur = nxt
self.way_mark_display()
# print(user_way)
def user_way_greedy(self): # 检查路径是否为最短路径并显示
check = self.way_check()
if not check == "Valid path":
result = tk.messagebox.askokcancel(title='错误', message = check)
return 0
# 若路径不合法,直接弹窗并返回
if solve.node_greedy() == -1:
return 0
self.show_GREDDY()
def user_way_best(self): # 检查路径是否为最短路径并显示
check = self.way_check()
if not check == "Valid path":# 如果用户路径不合法,则直接返回
tk.messagebox.askokcancel(title='错误', message = check)
return 0
# 若路径不合法,直接弹窗并返回
self.show_BEST()
if __name__ == '__main__':
G.draw()
# userG = USER_GREEDY()
# userB = USER_BSET()
W = Ways()
W.way_mark_display()
mainloop()

205
X3.py

@ -0,0 +1,205 @@
# -*- encoding: utf-8 -*-
"""
@Author: packy945
@FileName: X3.py
@DateTime: 2023/7/12 14:07
@SoftWare: PyCharm
"""
# -*- encoding: utf-8 -*-
from head import *
class Node:
# 标记节点按钮
def node_mark_display(self):
for w in frame_right.winfo_children():
w.destroy()
# 清除右侧组件
curx = -1
y0 = 0.1
for i in d.Nodes:
if i[2] == 1:
curx = i[0]
lab = tk.Label(frame_right, text="节点操作", bg=RED, fg=BLACK, font=('微软雅黑', 20))
lab.place(relx=0.18, rely=0.02, width=200, height=30)
lab1 = tk.Label(frame_right, text=f"当前共有{len(d.Nodes)}个节点", bg=RED, fg=BLACK, font=('微软雅黑', 15))
lab1.place(relx=0.1, rely=0.0 + y0, width=200, height=30)
lab1 = tk.Label(frame_right, text="当前节点:", bg=RED, fg=BLACK, font=('微软雅黑', 12))
if curx == -1:
text = "未选择"
else:
text = f"{d.Nodes[curx][1]}"
lab2 = tk.Label(frame_right, text=text, bg=BLUE, fg=BLACK, font=('微软雅黑', 12))
lab1.place(relx=0.1, rely=0.05 + y0, width=80, height=30)
lab2.place(relx=0.4, rely=0.05 + y0, width=80, height=30)
B = tk.Button(frame_right, text="设置标签", command=lambda: self.node_rename())
B.place(relx=0.7, rely=0.05 + y0, width=80, height=30)
B = tk.Button(frame_right, text="删除当前节点", command=lambda: self.node_del_exact())
B.place(relx=0.1, rely=0.1 + y0, width=150, height=30)
if d.Nodes[curx][4] == 1:
text = '设为非必经节点'
else:
text = '设为必经节点'
B = tk.Button(frame_right, text=text, command=lambda: self.dominator(curx))
B.place(relx=0.1, rely=0.15 + y0, width=150, height=30)
B = tk.Button(frame_right, text="增加一个节点", command=lambda: self.node_add())
B.place(relx=0.1, rely=0.25 + y0, width=150, height=30)
B = tk.Button(frame_right, text="减少一个节点", command=lambda: self.node_del())
B.place(relx=0.1, rely=0.3 + y0, width=150, height=30)
def dominator(self, x):
d.Nodes[x][4] ^= 1
G.draw()
self.node_mark_display()
def node_mark(self, name):
if name >= len(d.Nodes):
self.node_404(name)
return
for node in d.Nodes:
if node[0] == name:
node[2] = 1
else:
node[2] = 0
G.draw()
self.node_mark_display()
def node_del_exact(self):
if d.nodes_num <= 2:# 若删除节点以后节点过少,则直接返回并警告
tk.messagebox.askokcancel(title='错误', message='节点过少')
return
flag = 0
cur = -1
for node in d.Nodes:# 寻找当前选定的节点
if node[2] == 1:
cur = node[0]
flag = 1
if flag == 0:
tk.messagebox.askokcancel(title='错误', message='未选择节点')
return
d.nodes_num -= 1#节点数目减一
d.ang = 360 / d.nodes_num#重新计算圆心角
nodes = d.Nodes.copy()#复制节点
d.Nodes.clear()#清除Data中的节点
num = 0
for n in nodes:#逐个复制节点
if n[0] == cur:#若是删除的节点,则不复制
continue
n[0] = num#重新编号
rad = math.radians(num * d.ang)#计算当前角度
x = int(math.cos(rad) * d.R)#计算当前点x坐标相对
y = int(math.sin(rad) * d.R)#计算当前点y坐标相对
n[3] = (d.center[0] + x, d.center[1] + y)#计算绝对坐标
d.Nodes.append(n)#将当前点加入点集合中
num += 1
edges = d.Edges.copy()#将原有边集复制出来
d.Edges.clear()#删除Data中的边集
num = 0
for e in edges:#复制边
if e[1] == cur or e[2] == cur:#删除的边不复制
continue
if e[1] > cur:#修改边对应的点的编号
e[1] -= 1
if e[2] > cur:#修改边对应的点的编号
e[2] -= 1
e[0] = num#重新编号
d.Edges.append(e)#将边加入边集中
num += 1
G.draw()#重新绘图
self.node_mark_display()
def node_rename(self):
flag = 0
for node in d.Nodes:
if node[2] == 1:
cur = node
flag = 1
if flag == 1:
result = tkinter.simpledialog.askstring(title='修改节点标签', prompt='请输入修改后的标签:',
initialvalue=cur[1])
else:
tk.messagebox.askokcancel(title='错误', message='未选择节点')
return
if result:
cur[1] = result
G.draw()
self.node_mark_display()
def node_clear(self):
for node in d.Nodes:
node[2] = False
G.draw()
def node_add(self):
# 增加一个节点
nodes = len(d.Nodes) + 1
# 如果节点数目大于五,则将连接详细信息改为不显示
if nodes > 5:
d.edgeinfo = 0
self.node_init(nodes)
G.draw()
self.node_mark_display()
def node_set(self):
node = tkinter.simpledialog.askinteger(title='修改节点数目', prompt='请输入修改后的节点数目:',
initialvalue=str(len(d.Nodes)))
if node:
self.node_init(node)
G.draw()
def node_del(self):
if d.nodes_num <= 2:
tk.messagebox.askokcancel(title='错误', message='节点过少')
return
nodes = len(d.Nodes) - 1
if nodes < 6:
d.edgeinfo = 1
self.node_init(nodes)
G.draw()
self.node_mark_display()
def node_init(self, node):
if not node:
return
if d.source == 1:
d.data(node)
elif d.source == 2:
if node > 13:
tk.messagebox.askokcancel(title='错误', message='节点过多')
return
d.HEI_data(node)
else:
if node > 13:
tk.messagebox.askokcancel(title='错误', message='节点过多')
return
d.LIAO_data(node)
if node > 5:
d.edgeinfo = 0
else:
d.edgeinfo = 1
def graph_del(self):
global d
del d
def node_refresh(self):
nodes = len(d.Nodes)
self.node_init(nodes)
G.draw()
self.node_mark_display()
def node_404(self, name):
# 弹出对话框
tk.messagebox.askokcancel(title='错误', message='该节点不存在')
# print(result)
if __name__ == '__main__':
G.draw()
node = Node()
node.node_mark_display()
mainloop()

@ -0,0 +1,197 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
#获取城市之间的驾车距离/时间并且存入到excel表格中
import requests, json, os, time, xlwt, sys
flush_time = 6000 # 刷新间隔,单位秒
file_name1 = "两地之间的开车时间.xlsx"
file_name2 = "两地之间的开车距离.xlsx"
# 预置地点列表
address_list = [
# "沈阳市", "大连市", "鞍山市", "抚顺市", "本溪市", "丹东市", "锦州市", "营口市", "阜新市", "辽阳市", "盘锦市", "铁岭市", "朝阳市", "葫芦岛市",
'哈尔滨市', '齐齐哈尔市', '鸡西市', '鹤岗市', '双鸭山市', '大庆市', '伊春市', '佳木斯市', '七台河市', '牡丹江市', '黑河市', '绥化市', '大兴安岭地区',
]
workdir = os.path.dirname(os.path.realpath(sys.argv[0]))
file_path1 = os.path.join(workdir, file_name1)
file_path2 = os.path.join(workdir, file_name2)
AK = "9AfjsK2CXGuESwSb4sF3LsGhWh999Rdd" # 百度地图API认证码
# 获取地址的经纬度
def getPosition(address, AK):
url = "http://api.map.baidu.com/place/v2/search"
params = {
"query": address,
"region": "全国",
"output": "json",
"ak": AK,
}
try:
res = requests.get(url, params=params)
res.raise_for_status() # 如果响应状态码不是200, 则抛出异常
json_data = res.json()
if json_data["status"] == 0:
lat = json_data["results"][0]["location"]["lat"] # 纬度
lng = json_data["results"][0]["location"]["lng"] # 经度
return (lat, lng), json_data["status"]
else:
print(json_data["message"])
return (0, 0), json_data["status"]
except requests.RequestException as e:
print(f"Request error: {e}")
return (0, 0), -1
except ValueError as e:
print(f"Response parsing error: {e}")
return (0, 0), -1
# 获取两地开车的时间
def getTime(start, end, AK):
url = "https://api.map.baidu.com/directionlite/v1/driving"
params = {
"origin": start,
"destination": end,
"ak": AK,
}
try:
res = requests.get(url, params=params)
res.raise_for_status() # 如果响应状态码不是200, 则抛出异常
json_data = json.loads(res.text)
if json_data["status"] == 0:
return int(json_data['result']['routes'][0]['duration']) # 获取时间,单位s
else:
print(json_data["message"])
return -1
except requests.RequestException as e:
print(f"Request error: {e}")
return -1
except ValueError as e:
print(f"Response parsing error: {e}")
return -1
def getDis(start, end, AK):
url = "https://api.map.baidu.com/directionlite/v1/driving"
params = {
"origin": start,
"destination": end,
"ak": AK,
}
try:
res = requests.get(url, params=params)
res.raise_for_status() # 如果响应状态码不是200, 则抛出异常
json_data = json.loads(res.text)
if json_data["status"] == 0:
return int(json_data["result"]["routes"][0]["distance"])
else:
print(json_data["message"])
return -1
except requests.RequestException as e:
print(f"Request error: {e}")
return -1
except ValueError as e:
print(f"Response parsing error: {e}")
return -1
def calcTime(startName, endName):
start, status1 = getPosition(startName)
end, status2 = getPosition(endName)
if status1 == 0 and status2 == 0:
return round(getTime(start, end)/60, 1) # 将时间转换为分钟
else:
return -1
def calcDistance(startName, endName):
start, status1 = getPosition(startName)
end, status2 = getPosition(endName)
if status1 == 0 and status2 == 0:
return round(getDis(start, end),1)
else:
return -1
# 设置标题样式
def set_title_style(blod=False, underline=False):
style = xlwt.XFStyle() # 初始化样式
font = xlwt.Font() # 为样式创建字体
font.name = "Calibri" # 字体类型
font.height = 20 * 11 # 20为衡量单位,11为字号
font.bold = blod # 是否加粗
font.underline = underline # 是否添加下划线
style.font = font
return style
# 生成Excel文件
def createExcelDis(data,file_path):
workboot = xlwt.Workbook(encoding='utf-8')# 创建workbook和sheet对象
worksheet = workboot.add_sheet('计算两点间开车距离') # 设置工作表的名字
for i in range(len(address_list)+1):
worksheet.col(i).width = 256 * 30 # 设置每列宽, 256为衡量单位30表示30个字符宽度
row0 = ["两点间开车距离(单位千米)"]+address_list# 写入Excel标题
for i in range(len(row0)):
worksheet.write(0, i, row0[i], set_title_style(True))
for i, line in enumerate(data):
for j, drive_dis in enumerate(line):
worksheet.write(i+1, j, str(drive_dis), set_title_style())
workboot.save(file_path)
print("[INFO] 成功创建%s" % file_path)
def createExcelTime(data,file_path):
# 创建workbook和sheet对象
workboot = xlwt.Workbook(encoding='utf-8')
worksheet = workboot.add_sheet('计算两点间开车时间') # 设置工作表的名字
for i in range(len(address_list)+1):
worksheet.col(i).width = 256 * 30 # 设置每列宽, 256为衡量单位30表示30个字符宽度
# 写入Excel标题
row0 = ["两点间开车时间(单位分钟)"]+address_list
for i in range(len(row0)):
worksheet.write(0, i, row0[i], set_title_style(True))
# 写入查询百度地图api获取的数据
for i,line in enumerate(data):
for j,drive_time in enumerate(line):
worksheet.write(i+1, j, str(drive_time), set_title_style())
workboot.save(file_path)
print("[INFO] 成功创建%s" % file_path)
# 生成开车时间矩阵信息
def generateTimeMatrix(flush_time,file_path):
while True:
matrix_list = [] # 以矩阵的方式来存放两地之间的开车时间
alist = [] # 存放横坐标的值
print("[INFO] 开始计算两地之间的开车时间,每隔%s秒刷新一次..." % flush_time)
for start in address_list: # 起始位置作为纵坐标
alist.append(start)
for end in address_list: # 终点位置作为横坐标
dt = calcTime(start, end)
alist.append(dt)
matrix_list.append(alist)
alist = []
createExcelTime(matrix_list,file_path)
time.sleep(flush_time)
# 生成开车时间矩阵信息
def generateDistanceMatrix(flush_time,file_path):
while True:
matrix_list = [] # 以矩阵的方式来存放两地之间的开车距离
alist = [] # 存放横坐标的值
print("[INFO] 开始计算两地之间的开车距离,每隔%s秒刷新一次..." % flush_time)
for start in address_list: # 起始位置作为纵坐标
alist.append(start)
for end in address_list: # 终点位置作为横坐标
dt = calcDistance(start, end)
alist.append(dt)
matrix_list.append(alist)
alist = []
createExcelDis(matrix_list,file_path)
time.sleep(flush_time)
if __name__ == "__main__":
try:
# 时间
generateTimeMatrix(flush_time, file_path1)
# 距离
generateTimeMatrix(flush_time, file_path2)
except Exception as e:
print('ERROR:%s' % e)

@ -0,0 +1,428 @@
# -*- encoding: utf-8 -*-
import math
import random
import pandas as pd
from collections import Counter
def _init():
global _global_dict
_global_dict={}
class Data():
def __init__(self, source :int, num: int):
self.source = source
# 数据来源
# 1随机 2黑龙江省 3辽宁省
# 默认为1
self.edgeinfo = 1
# 是否显示详情
# 1显示 0不显示
# 默认为1
self.heidata = pd.read_excel("hei/data.xlsx") # 黑龙江省各市信息
self.heitime = pd.read_excel("hei/time.xlsx") # 黑龙江省各市通行时间
self.heidis = pd.read_excel("hei/distance.xlsx") # 黑龙江省各市通行距离
self.liaodata = pd.read_excel("liao/data.xlsx") # 辽宁省各市信息
self.liaotime = pd.read_excel("liao/time.xlsx") # 辽宁省各市通行时间
self.liaodis = pd.read_excel("liao/distance.xlsx") # 辽宁省各市通行距离
if self.source == 1:
self.data(num)
elif self.source == 2:
self.HEI_data(num)
elif self.source == 3:
self.LIAO_data(num)
def get_liaotime(self, i, j):
# print(self.heidata.iloc[i, 0])
# print(self.heidata.iloc[j, 0])
# print(self.heitime.iloc[i, j + 1])
return math.floor(self.liaotime.iloc[i, j + 1])
def get_liaodis(self, i, j):
# print(self.heidata.iloc[i, 0])
# print(self.heidata.iloc[j, 0])
# print(self.heidis.iloc[i, j + 1])
return math.floor(self.liaodis.iloc[i, j + 1] / 1000)
def get_heitime(self, i, j):
# print(self.heidata.iloc[i, 0])
# print(self.heidata.iloc[j, 0])
# print(self.heitime.iloc[i, j + 1])
return math.floor(self.heitime.iloc[i, j + 1])
def get_heidis(self, i, j):
# print(self.heidata.iloc[i, 0])
# print(self.heidata.iloc[j, 0])
# print(self.heidis.iloc[i, j + 1])
return math.floor(self.heidis.iloc[i, j + 1] / 1000)
def data(self, num: int):
if num <= 0:
raise ValueError("num must be a positive integer")
self.edgeinfo = 1
# 是否显示详情
# 1显示 0不显示
# 默认为1
self.nodes_num = num # 节点个数
self.ang = 360 / self.nodes_num # 圆心顶点角度
self.R = 300 # 外接圆半径
self.bc = 2 * self.R * math.sin(math.pi / self.nodes_num) # 节点之间的正多边形距离
self.canvas_len = int(2 * self.R + 80) # 画布边长
self.center = (self.canvas_len // 2, self.canvas_len // 2) # 画布中心点坐标
self.coordinate = self.coord_creat() # 纯节点坐标
self.Nodes = self.nodes_creat() # 创建节点列表
self.Edges = self.edges_creat() # 创建第一条连接
self.edge_add(2) # 创建第2条连接
self.edge_add(3) # 创建第3条连接
def HEI_data(self, num: int):
self.edgeinfo = 1
# 是否显示详情
# 1显示 0不显示
# 默认为1
self.number = []
for i in range(13):
self.number.append(i)
self.name = random.sample(self.number, num)
self.nodes_num = num # 节点个数
self.ang = 360 / self.nodes_num # 圆心顶点角度
self.R = 300 # 外接圆半径
self.bc = 2 * self.R * math.sin(math.pi / self.nodes_num) # 节点之间的正多边形距离
self.canvas_len = int(2 * self.R + 80) # 画布边长
self.center = (self.canvas_len // 2, self.canvas_len // 2) # 画布中心点
self.coordinate = self.coord_creat() # 纯节点坐标
self.Nodes = self.JI_nodes_creat() # 节点列表
self.Edges = self.JI_edges_creat()
self.JI_edge_add(2)
self.JI_edge_add(3)
def LIAO_data(self, num: int):
self.edgeinfo = 1
# 是否显示详情
# 1显示 0不显示
# 默认为1
self.number = []
for i in range(13):
self.number.append(i)
self.name = random.sample(self.number, num)
self.nodes_num = num # 节点个数
self.ang = 360 / self.nodes_num # 圆心顶点角度
self.R = 300 # 外接圆半径
self.bc = 2 * self.R * math.sin(math.pi / self.nodes_num) # 节点之间的正多边形距离
self.canvas_len = int(2 * self.R + 80) # 画布边长
self.center = (self.canvas_len // 2, self.canvas_len // 2) # 画布中心点
self.coordinate = self.coord_creat() # 纯节点坐标
self.Nodes = self.LIAO_nodes_creat() # 节点列表
self.Edges = self.LIAO_edges_creat()
self.LIAO_edge_add(2)
self.LIAO_edge_add(3)
def LIAO_nodes_creat(self, n_sum=None):
"""Nodes[]={<节点对象编号,节点标签,节点类别,节点坐标, 是否为必经节点(默认必经)>}"""
if n_sum == None:
n_sum = self.nodes_num
nodes = []
miny = float("inf")
minx = float("inf")
maxx = 0
maxy = 0
for i in self.name:
maxx = max(maxx, self.liaodata.iloc[i, 2])
minx = min(minx, self.liaodata.iloc[i, 2])
maxy = max(maxy, self.liaodata.iloc[i, 1])
miny = min(miny, self.liaodata.iloc[i, 1])
lenx = maxx - minx
leny = maxy - miny
Ox = (maxx + minx) / 2
Oy = (maxy + miny) / 2
x0 = self.center[0]
y0 = self.center[1]
for i in range(n_sum):
ix = self.liaodata.iloc[self.name[i], 2]
iy = self.liaodata.iloc[self.name[i], 1]
x = int(((ix - Ox) / lenx) * 550)
y = -int(((iy - Oy) / leny) * 550)
name = self.liaodata.iloc[self.name[i], 0]
# name=''+str(i+1)
mark = 0
dominator = 1
nodes.append([i, name, mark, (x0+x, y0+y), dominator])
return nodes
def LIAO_edges_creat(self):
'''
路径创建
Edges[] = { < 连接对象编号节点对象1编号节点对象2编号连接序号连接是否可用连接标签连接的距离 / 成本连接的时间 >}
'''
edges = [] # 所有链接集合
ser = 0 # 链接对象编号
nodes = self.Nodes.copy() # 复制节点对象
nodes1 = self.Nodes.copy() # 复制节点对象
for node in nodes: # 遍历节点对象
if node in nodes1: # 删除nodes1中当期遍历的节点信息
nodes1.remove(node)
for node1 in nodes1: # 遍历删除后的节点信息
# Edges[] = { < 连接序号节点对象1编号节点对象2编号链接是否可用序号大于1连接是否标记连接标签连接的距离 / 成本,连接的时间,连接序号 >}
n1 = node[0] # 节点对象编号1
n2 = node1[0] # 节点对象编号2
seq = 1 # 链接序号
mark = False # 连接是否标记
tag = self.liaodis.iloc[self.name[n1], 0] + '-' + self.liaodis.iloc[self.name[n2], 0]
# tag = f"{n1+1}-{n2+1}" # 链接标签
dist_c = self.get_liaodis(n1, n2)
# dist_c = random.randint(30,120) # 距离成本
time_c = self.get_liaotime(n1, n2)
# time_c = random.randint(1,30) # 链接的时间
enable = 1 # 连接是否可用
edges.append([ser, n1, n2, enable, mark, tag, dist_c, time_c, seq])
ser += 1
return edges
def LIAO_edge_add(self, no):
nodes = self.Nodes.copy() # 复制节点对象
nodes1 = self.Nodes.copy() # 复制节点对象
for node in nodes: # 遍历节点对象
if node in nodes1: # 删除nodes1中当期遍历的节点信息
nodes1.remove(node)
for node1 in nodes1: # 遍历删除后的节点信息
# Edges[] = { < 连接序号节点对象1编号节点对象2编号链接是否显示序号大于1连接是否标记连接标签连接的距离 / 成本,连接的时间,连接序号 >}
ser = len(self.Edges) # 链接序号
n1 = node[0] # 节点对象编号1
n2 = node1[0] # 节点对象编号2
show = 0
mark = False # 连接是否标记
tag = f"{self.liaodis.iloc[self.name[n1], 0]}-{self.liaodis.iloc[self.name[n2], 0]}-{no}" # 链接标签
# tag = f"{n1 + 1}-{n2 + 1}-{no}" # 链接标签
dist_c = self.get_liaodis(n1, n2)
# dist_c = random.randint(30,120) # 距离成本
time_c = self.get_liaotime(n1, n2)
# time_c = random.randint(1,30) # 链接的时间
seq = no # 连接序号
self.Edges.append([ser, n1, n2, show, mark, tag, dist_c, time_c, seq])
def JI_nodes_creat(self, n_sum=None):
"""Nodes[]={<节点对象编号,节点标签,节点类别,节点坐标, 是否为必经节点(默认必经)>>}"""
if n_sum == None:
n_sum = self.nodes_num
nodes = []
miny = float("inf")
minx = float("inf")
maxx = 0
maxy = 0
for i in self.name:
# print(i, self.heidis.iloc[i, 0])
# print(self.heidata.iloc[i, 0], self.heidata.iloc[i, 1], self.heidata.iloc[i, 2])
maxx = max(maxx, self.heidata.iloc[i, 2])
minx = min(minx, self.heidata.iloc[i, 2])
maxy = max(maxy, self.heidata.iloc[i, 1])
miny = min(miny, self.heidata.iloc[i, 1])
# print(maxx, maxy, minx, miny)
lenx = maxx - minx
leny = maxy - miny
Ox = (maxx + minx) / 2
Oy = (maxy + miny) / 2
R = self.R
x0 = self.center[0]
y0 = self.center[1]
for i in range(n_sum):
# rad = math.radians(i*self.ang)
# x = int(math.cos(rad)*R)
# y = int(math.sin(rad)*R)
ix = self.heidata.iloc[self.name[i], 2]
iy = self.heidata.iloc[self.name[i], 1]
# print(int(math.cos(rad)*R))
# print(((ix - Ox) / lenx) * 300)
x = int(((ix - Ox) / lenx) * 550)
y = -int(((iy - Oy) / leny) * 550)
name = self.heidata.iloc[self.name[i], 0]
# name=''+str(i+1)
mark = 0
dominator = 1
nodes.append([i, name, mark, (x0+x, y0+y), dominator])
return nodes
def JI_edges_creat(self):
'''
路径创建
Edges[] = { < 连接对象编号节点对象1编号节点对象2编号连接序号连接是否可用连接标签连接的距离 / 成本连接的时间 >}
'''
edges = [] # 所有链接集合
ser = 0 # 链接对象编号
nodes = self.Nodes.copy() # 复制节点对象
nodes1 = self.Nodes.copy() # 复制节点对象
for node in nodes: # 遍历节点对象
if node in nodes1: # 删除nodes1中当期遍历的节点信息
nodes1.remove(node)
for node1 in nodes1: # 遍历删除后的节点信息
for i in range(random.randint(1,1)):
# Edges[] = { < 连接序号节点对象1编号节点对象2编号链接是否可用序号大于1连接是否标记连接标签连接的距离 / 成本,连接的时间,连接序号 >}
n1 = node[0] # 节点对象编号1
n2 = node1[0] # 节点对象编号2
seq = 1 # 链接序号
mark = False # 连接是否标记
tag = self.heidis.iloc[self.name[n1], 0] + '-' + self.heidis.iloc[self.name[n2], 0]
# tag = f"{n1+1}-{n2+1}" # 链接标签
dist_c = self.get_heidis(n1, n2)
# dist_c = random.randint(30,120) # 距离成本
time_c = self.get_heitime(n1, n2)
# time_c = random.randint(1,30) # 链接的时间
enable = 1 # 连接是否可用
edges.append([ser, n1, n2, enable, mark, tag, dist_c, time_c, seq])
ser += 1
return edges
def JI_edge_add(self, no):
nodes = self.Nodes.copy() # 复制节点对象
nodes1 = self.Nodes.copy() # 复制节点对象
for node in nodes: # 遍历节点对象
if node in nodes1: # 删除nodes1中当期遍历的节点信息
nodes1.remove(node)
for node1 in nodes1: # 遍历删除后的节点信息
# Edges[] = { < 连接序号节点对象1编号节点对象2编号链接是否显示序号大于1连接是否标记连接标签连接的距离 / 成本,连接的时间,连接序号 >}
ser = len(self.Edges) # 链接序号
n1 = node[0] # 节点对象编号1
n2 = node1[0] # 节点对象编号2
show = 0
mark = False # 连接是否标记
tag = f"{self.heidis.iloc[self.name[n1], 0]}-{self.heidis.iloc[self.name[n2], 0]}-{no}" # 链接标签
# tag = f"{n1 + 1}-{n2 + 1}-{no}" # 链接标签
dist_c = self.get_heidis(n1, n2)
# dist_c = random.randint(30,120) # 距离成本
time_c = self.get_heitime(n1, n2)
# time_c = random.randint(1,30) # 链接的时间
seq = no # 连接序号
self.Edges.append([ser, n1, n2, show, mark, tag, dist_c, time_c, seq])
def coord_creat(self):
'''返回每个节点的坐标'''
coordinate = []
x0 = self.center[0]
y0 = self.center[1]
for i in range(self.nodes_num):
rad = math.radians(i*self.ang)
x = int(math.cos(rad)*self.R)
y = int(math.sin(rad)*self.R)
coordinate.append((x0+x,y0+y))
return coordinate
def nodes_creat(self, n_sum= None):
"""Nodes[]={<节点对象编号,节点标签,节点类别,节点坐标, 是否为必经节点(默认必经)>}"""
if n_sum == None:
n_sum = self.nodes_num
nodes = []#初始化node表
# 设置画布中心点坐标x0,y0
x0 = self.center[0]
y0 = self.center[1]
for i in range(n_sum):# 通过几何运算得到多边形各个顶点坐标
rad = math.radians(i * self.ang)# 计算第i个点的弧度
x = int(math.cos(rad) * self.R)# 计算第i个顶点x坐标
y = int(math.sin(rad) * self.R)# 计算第i个顶点y坐标
name = '' + str(i + 1)# 给第i个顶点命名
mark = 0#节点为未标记
dominator = 1#设置为必经节点
nodes.append([i, name, mark, (x0 + x, y0 + y), dominator])#将当前节点加入node中
return nodes
def edges_creat(self):
'''
路径创建
Edges[] = { < 连接对象编号节点对象1编号节点对象2编号连接是否存在连接是否标记连接标签连接的距离 / 成本连接的时间连接序号 >}
'''
edges = [] # 初始化所有链接集合
ser = 0 # 初始化链接对象编号
nodes = self.Nodes.copy() # 复制节点对象
nodes1 = self.Nodes.copy() # 复制节点对象
for node in nodes: # 遍历节点对象
if node in nodes1: # 删除nodes1中当期遍历的节点信息
nodes1.remove(node)
for node1 in nodes1: # 遍历删除后的节点信息
# Edges[] = { < 连接序号节点对象1编号节点对象2编号链接是否可用序号大于1连接是否标记连接标签连接的距离 / 成本,连接的时间,连接序号 >}
n1 = node[0] # 节点对象编号1
n2 = node1[0] # 节点对象编号2
seq = 1 # 链接序号
mark = False # 连接是否标记
tag = f"{n1+1}-{n2+1}" # 链接标签
dist_c = random.randint(10, 120) # 随机生成距离成本
time_c = random.randint(10, 120) # 随机生成链接的时间
enable = 1 # 连接是否可用
if dist_c >= 100 or time_c >= 100: # 设置某些节点为不显示
enable = 0
edges.append([ser, n1, n2, enable, mark, tag, dist_c, time_c, seq]) # 将连接加入到边的集合中
ser+=1# 计数加一
return edges
def node_count(self, node_num:tuple, node_co:list):
for node in node_num:
node_co.append(node)
def path_creat(self):
node_co = {} # 节点统计,
for node in self.Nodes:
node_co[node[0]] = 0
print(node_co)
for edge in self.Edges:
for num in node_co.keys():
if node_co[num] <=1:
if edge[1] == num or edge[2]== num:
node_co[num]+=1
print((edge[1],edge[2]))
print(node_co) # 每个节点出现的次数
def node_co(self,key): # 通过节点编号返回编号的坐标
"""通过节点编号返回编号的坐标"""
nodes = self.Nodes
for n in nodes:
if n[0] == key:
return n[3]
def edge_add(self, no):
nodes = self.Nodes.copy() # 复制节点对象
nodes1 = self.Nodes.copy() # 复制节点对象
for node in nodes: # 遍历节点对象
if node in nodes1: # 删除nodes1中当期遍历的节点信息
nodes1.remove(node)
for node1 in nodes1: # 遍历删除后的节点信息
# Edges[] = { < 连接序号节点对象1编号节点对象2编号链接是否显示序号大于1连接是否标记连接标签连接的距离 / 成本,连接的时间,连接序号 >}
ser = len(self.Edges) # 链接序号
n1 = node[0] # 节点对象编号1
n2 = node1[0] # 节点对象编号2
show = 0
mark = False # 连接是否标记
tag = f"{n1 + 1}-{n2 + 1}-{no}" # 链接标签
dist_c = random.randint(30, 100) # 距离成本
time_c = random.randint(1, 30) # 链接的时间
enable = no # 连接是否可用
self.Edges.append([ser, n1, n2, show, mark, tag, dist_c, time_c, enable])
if __name__ == '__main__':
d = Data(1, 5)
d.path_creat()
#print(d.Edges)

@ -0,0 +1,238 @@
# -*- encoding: utf-8 -*-
import math
import queue
import time
import tkinter as tk
from tkinter import *
from tkinter import scrolledtext
import tkinter.messagebox
import tkinter.simpledialog
from data import *
BLUE = "#0080FF"
BLACK = "#000000"
RED = "#FFAAAA"
YELLOW = "#FFFACD"
LINE = '#c8d2c8'
GREY = '#070b19'
GREEN = '#5ba585'
NODE = '#33a8cd'
ZERO = 'gold'
nodes = 6#设置初始节点数量
d = Data(1, nodes)
root = tk.Tk() #设置主界面
root.title("旅行商问题") # 设置标题
root.geometry(f"{d.canvas_len + 370}x{d.canvas_len + 100}") # 设置大小
root.resizable(0,0) # 设置不能调整显示边框
frame = tk.Frame(root, padx=20, pady=20, width=d.canvas_len, height=d.canvas_len + 50)
frame.grid() # 绘制显示框
frame_top = tk.Frame(frame, width=d.canvas_len, height=50)
frame_top.grid(row=0, column=0) # 绘制信息输出栏
cv = canvas = tk.Canvas(frame, bg='white', bd=2, relief="sunken", width=d.canvas_len, height=d.canvas_len)
canvas.grid(row=1, column=0)#放置绘图Canvas画布
frame_right = tk.Frame(root, bg=RED, width=300, height=d.canvas_len + 50)# 右边栏
frame_right.grid(row=0, column=1) # 右边栏
def dir2(x, y): # 计算两点间距离
return (x[0] - y[0]) * (x[0] - y[0]) + (x[1] - y[1]) * (x[1] - y[1])
main_menu = tk.Menu(root)
root.config(menu=main_menu)
def node_edge(n1, n2, no=1): # 根据点的编号找边的编号
if n1 > n2:#为了防止充分编号让n1小于n2
n1, n2 = n2, n1
for e in d.Edges:#遍历所有路径,找到符合要求的返回
if e[1] == n1 and e[2] == n2 and e[8] == no:
return e[0]
return -1#若找不到,则返回-1
class Graph:
def draw(self):
cv.delete('all')#清空画布
dis, tim = self.edges_show(cv, d.Edges)#绘制边
self.lab_show(frame_top, len(d.Nodes), tim, dis)#显示边信息
self.nodes_show(cv)#绘制点
cv.update()#更新画布
def lab_show(self, frame: tk.Frame, nodes: int, time: int, distance: int):
labs = ["节点数目", "时间", "距离(成本)"]
x0 = d.canvas_len // 3
for i in range(len(labs)):
lab1 = tk.Label(frame, text=labs[i], fg=BLACK, font=('微软雅黑', 12))
if i == 0:
lab2 = tk.Label(frame, text=f"{nodes}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12))
elif i == 1:
lab2 = tk.Label(frame, text=f"{time}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12))
else:
lab2 = tk.Label(frame, text=f"{distance}", bg=BLUE, fg=BLACK, font=('微软雅黑', 12))
lab1.place(x=10 + x0 * i, y=10, width=80, height=30)
lab2.place(x=10 + x0 * i + 80, y=10, width=80, height=30)
lab1 = tk.Label(frame, text='分钟', fg=BLACK, font=('微软雅黑', 12))
lab1.place(x=170 + x0, y=10, width=50, height=30)
lab1 = tk.Label(frame, text='千米', fg=BLACK, font=('微软雅黑', 12))
lab1.place(x=170 + x0 * 2, y=10, width=50, height=30)
def nodes_show(self, cv: tk.Canvas):
"""
显示节点
:param cv: tkcanvas对象
:return:
"""
COL = NODE# 初始化节点颜色
for i in d.Nodes:# 遍历每一个节点
x, y = i[3] #记录该节点坐标
if i[2] == 1 or i[2] == 2:# 如果节点被标记,则将节点标为红色
COL = RED
elif i[0] == 0:# 如果节点为起始节点,则将节点标记为特殊颜色
COL = ZERO
elif i[2] == 5:# 如果节点已经被访问,则将节点标记(用户路径功能)
COL = 'gold'
else:#否则则使用初始颜色
COL = NODE
if i[4] == 1:# 如果是必经节点,则加黑色边框
w = 1
else:# 如果是非必经节点,则没有边框
w = 0
# 根据坐标,圆的颜色与是否有边框绘制圆圈来表示节点
cv.create_oval(x - 20, y - 20, x + 20, y + 20, fill=COL, width=w,)# outline='#ee28a3')
if d.source == 1:# 根据节点信息将节点的标签显示在节点上
cv.create_text(x, y, text=f'{i[1]}', fill=GREY, font=('华文楷体', 24))
else:
cv.create_text(x, y, text=f'{i[1]}', fill=GREY, font=('华文楷体', 18))
cv.update()
def edges_show(self, cv: tk.Canvas, edges: d.Edges):
"""
显示链接
:param cv: tkcanvas对象
:return:
"""
distance = 0 # 初始化被标记的线的总路径
time1 = 0 # 初始化被标记的线的总时间
for edge in edges:
node_1 = d.node_co(edge[1]) # 链接线编号对应的坐标1
node_2 = d.node_co(edge[2]) # 链接线编号对应的坐标2
if edge[8] == 2 and edge[3] == 1: # 若该链接为两点间第二条连线
self.more_edge_show(2, edge)
elif edge[8] == 3 and edge[3] == 1: # 若为两点间第3条连线
self.more_edge_show(3, edge)
if edge[8] == 1 and edge[3] == 1:# 若为两点间第1条连线且该连接存在
self.edge_info(cv, f'{edge[5]} {edge[6]} {edge[7]}', node_1, node_2)
point = [node_1, node_2]
if edge[4] == 1 and edge[8] == 1 and edge[3] == 1:# 如果路径被标记,则用绿色绘制
cv.create_line(point, fill=GREEN, width=4)
distance += edge[6]# 更新总路径
time1 += edge[7]# 更新总时间
elif edge[8] == 1 and edge[3] == 1:# 如果是节点之间的第一条线,则用正常颜色标记
cv.create_line(point, fill=LINE, width=2)
if d.Nodes[edge[1]][2] + d.Nodes[edge[2]][2] == 3:# 若该线被用户选中,则用蓝色虚线标记
cv.create_line(point, fill=BLUE, width=5, dash=(4, 14))
return (distance, time1)# 返回标记路径的总时间与路程
def more_edge_show(self, no, E):
# print(n1,n2)
n1 = E[1]
n2 = E[2]
node_1 = d.node_co(n1)
node_2 = d.node_co(n2)
(n1x, n1y) = node_1
(n2x, n2y) = node_2
n0x = (n1x + n2x) / 2
n0y = (n1y + n2y) / 2
(Ox, Oy) = d.center
x = 30 # 新路径距原路径距离
if no == 2:
if not Ox - n0x == 0:
k = (Oy - n0y) / (Ox - n0x)
n3x = n0x + x * math.cos(math.atan(k))
n3y = n0y + x * math.sin(math.atan(k))
else:
n3x = n0x
n3y = n0y + x
elif no == 3:
if not Ox - n0x == 0:
k = (Oy - n0y) / (Ox - n0x)
n3x = n0x - x * math.cos(math.atan(k))
n3y = n0y - x * math.sin(math.atan(k))
else:
n3x = n0x
n3y = n0y - x
self.moreedge_info(cv, f'{E[5]} {E[6]} {E[7]}', node_1, node_2, (n3x, n3y), no)
cv.create_line((n1x, n1y), (n3x, n3y), fill=LINE, width=2)
cv.create_line((n2x, n2y), (n3x, n3y), fill=LINE, width=2)
def node_edge(self, a, b): # 根据点的编号找边的编号
if a > b:
x = a
a = b
b = x
return int(a * (2 * len(d.Nodes) - a - 3) / 2 + b - 1)
def moreedge_info(self, cv: tk.Canvas, info: str, n1: tuple, n2: tuple, n3: tuple, no):
if d.edgeinfo == 0:
return
if no == 2:
flag = 1
else:
flag = -1
x = n3[0]
y = n3[1]
if (n2[1] - n1[1]) != 0: # 斜率为非0度时的显示
reat = math.atan((n2[0] - n1[0]) / (n2[1] - n1[1])) # 根据斜率计算弧度
ang = round(math.degrees(reat)) + 90 # 根据弧度转角度
if ang > 89: # 斜度大于90度调整坐标
cv.create_text(x + 15 * flag, y, text=f'{info}', fill="black", font=('微软雅黑', 12), angle=ang)
# cv.create_text(x, y, text=f'{i[1]}', fill="red", font=('微软雅黑', 24))
else:
cv.create_text(x, y + 15 * flag, text=f'{info}', fill="black", font=('微软雅黑', 12), angle=ang)
else:
ang = round(math.degrees(0)) # 根据弧度转角度
cv.create_text(x - 30 * flag, y + 10 * flag, text=f'{info}', fill="black", font=('微软雅黑', 12), angle=ang)
def edge_info(self, cv: tk.Canvas, info: str, n1: tuple, n2: tuple):
'''
取连线中点坐标显示info的信息
:param info: 连线信息
:param center: 画布中心点
:param n1: 连线端点1
:param n2: 连线端点2
:return: None
'''
if d.edgeinfo == 0: #若设置为不显示则直接返回
return
x = (n1[0] - n2[0]) // 2 + n2[0]#计算中点x坐标
y = (n1[1] - n2[1]) // 2 + n2[1]#计算中点y坐标
if (n2[1] - n1[1]) != 0: # 斜率为非0度时的显示
reat = math.atan((n2[0] - n1[0]) / (n2[1] - n1[1])) # 根据斜率计算弧度
ang = round(math.degrees(reat)) + 90 # 根据弧度转角度
if ang > 89: # 斜度大于90度调整坐标
text_x, text_y = x + 15, y
else:# 斜度大于90度调整坐标
text_x, text_y = x, y + 15
else:# 斜率为0度时的显示
ang = round(math.degrees(0)) # 根据弧度转角度
text_x, text_y = x - 30, y + 10
cv.create_text(text_x, text_y, text=f'{info}', fill="black", font=('微软雅黑', 12), angle=ang)#根据信息显示文字
G = Graph()
if __name__ == '__main__':
# G = Graph()
G.draw()
mainloop()

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -0,0 +1,248 @@
# -*- encoding: utf-8 -*-
from NODE import *
from SOLVE import *
from EDGE import *
from WAYS import *
N = Node()
E = Edge()
W = Ways()
mode = tk.IntVar(value=1)
# 目前的操作状态:
# 1为节点操作
# 2为链接操作
# 3为路径操作
# 默认为1
RIGHT = -1
B = tk.Button(frame, text="修改", command=lambda: N.node_set())
B.place(x=180, y=10, width=50, height=30)
def left1(event):
# 查找鼠标左键按下时位置是否在某个节点内
n = -1
for node in d.Nodes:
if dir2([event.x, event.y], [node[3][0], node[3][1]]) < 20 * 20:
n = node[0]
# n为点击的节点若没有则为-1
m = mode.get() # 查看现在操作类型
if m == 1 and not n == -1:
# 节点操作
N.node_mark(n)
elif m == 2 and not n == -1:
# 链接操作
if len(E.mark) == 0:
E.mark.append(n)
E.node_mark1(E.mark[0])
elif len(E.mark) == 1:
E.mark.append(n)
E.node_mark1(E.mark[0])
E.node_mark2(E.mark[1])
elif not n == E.mark[1]:
n1 = E.mark[1]
E.mark.clear()
E.mark.append(n1)
E.mark.append(n)
E.node_mark1(E.mark[0])
E.node_mark2(E.mark[1])
# 路径操作
elif m == 3 and not n == -1:
W.user_way_add(n)
# 自动判断操作
elif m == 4 and not n == -1:
if len(solve.mark) == 0:
solve.mark.append(n)
solve.node_mark1(solve.mark[0])
elif len(solve.mark) == 1:
solve.mark.append(n)
solve.node_mark1(solve.mark[0])
solve.node_mark2(solve.mark[1])
elif not n == solve.mark[1]:
n1 = solve.mark[1]
solve.mark.clear()
solve.mark.append(n1)
solve.mark.append(n)
solve.node_mark1(solve.mark[0])
solve.node_mark2(solve.mark[1])
def onRightButtonUp(event):
global RIGHT
# 查找鼠标右键按下时位置是否在某个节点内
n = -1
for node in d.Nodes:
if dir2([event.x, event.y], [node[3][0], node[3][1]]) < 20 * 20:
n = node[0]
if n == -1:
menu.post(event.x_root, event.y_root)
else:
RIGHT = n
menu_node.post(event.x_root, event.y_root)
# 右键菜单
def m_node():
mode.set(1)
W.clear()
N.node_mark_display()
def m_edge():
mode.set(2)
W.clear()
E.edge_mark_display()
def m_ways():
mode.set(3)
W.user_way_clear()
W.way_mark_display()
def m_info():
d.edgeinfo ^= 1
G.draw()
def m_solve():
W.clear()
mode.set(4)
solve.Solve_display()
def graph_init():
nodes = random.randint(4, 10)
N.node_init(nodes)
G.draw()
N.node_mark_display()
def sourc_set(num):
W.clear()
d.source = num
N.node_init(nodes)
G.draw()
def node_del(num):
N.node_mark(num)
N.node_del_exact()
def node_name(num):
N.node_mark(num)
N.node_rename()
def node_condition(num):
d.Nodes[num][4] ^= 1
G.draw()
menu = tk.Menu(root, tearoff=0)
menu.add_command(label='节点操作', command=m_node)
menu.add_command(label='连接操作', command=m_edge)
menu.add_command(label='路径操作', command=m_ways)
menu.add_command(label='显示/隐藏链接信息', command=m_info)
menu.add_command(label='自动判断相关', command=m_solve)
fmenu1 = Menu(menu, tearoff=False)
fmenu1.add_command(label='使用模拟数据', command=lambda: sourc_set(1))
fmenu1.add_command(label='使用黑龙江省数据', command=lambda: sourc_set(2))
fmenu1.add_command(label='使用辽宁省数据', command=lambda: sourc_set(3))
menu.add_cascade(label="切换数据源", menu=fmenu1)
menu_node = tk.Menu(root, tearoff=0)
menu_node.add_command(label='删除节点', command=lambda: node_del(RIGHT))
menu_node.add_command(label='切换必经/非必经', command=lambda: node_condition(RIGHT))
menu_node.add_command(label='重命名节点', command=lambda: node_name(RIGHT))
# menu_node.add_command(label='显示/隐藏链接信息', command=m_info)
cv.bind('<Button-1>', left1)
cv.bind('<ButtonRelease-3>', onRightButtonUp)
# 释放右键时打开菜单
def auto_opera_mu(menu: tk.Menu):
"""TSP问题自动生成与自动求解相关"""
menu_node = Menu(menu, tearoff=False)
menu_node.add_command(label="自动随机产生一个TSP问题", command=lambda: graph_init())
menu_node.add_command(label="重新生成", command=lambda: N.node_refresh())
menu_node.add_command(label="自动求解最优路径-遍历", command=lambda: solve.dfs_panel())
menu_node.add_command(label="自动求解优化路径-贪心", command=lambda: solve.greedy_panel())
menu_node.add_command(label="检查是否存在路径", command=lambda: solve.check())
# 在主目录菜单上新增"文件"选项并通过menu参数与下拉菜单绑定
menu.add_cascade(label="TSP问题自动生成与自动求解相关", menu=menu_node)
def node_opera_mu(menu: tk.Menu):
"""节点操作"""
# fmenu1 = Menu(menu, tearoff=False)
# for i in range(10):
# fmenu1.add_command(label='选择节点 ' + str(i + 1), command=lambda num=i: node_mark(num))
menu_node = Menu(menu, tearoff=False)
menu_node.add_command(label="添加一个节点", command=lambda: N.node_add())
menu_node.add_command(label="删除一个节点", command=lambda: N.node_del())
# menu_node.add_cascade(label="选择一个节点", menu=fmenu1)
menu_node.add_command(label="选择一个节点", command=lambda: N.node_mark_display())
# menu_node.add_command(label="停止标记一个节点", command=lambda: node_mark_display1())
# menu_node.add_command(label="设置节点标签", command=lambda:node_rename())
# 在主目录菜单上新增"文件"选项并通过menu参数与下拉菜单绑定
menu.add_cascade(label="节点操作", menu=menu_node)
def edge_opera_mu(menu: tk.Menu):
"""连接操作"""
# fmenu1 = Menu(menu, tearoff=False)
# for i in range(10):
# fmenu1.add_command(label='选择另一个节点 ' + str(i + 1), command=lambda num=i: node_mark2(num))
#
menu_node = Menu(menu, tearoff=False)
# menu_node.add_cascade(label="选择另一个节点", menu=fmenu1)
menu_node.add_command(label="选择一个连接", command=lambda: E.edge_mark_display())
# menu_node.add_command(label="建立一个连接",command=lambda :edge_add())
menu_node.add_command(label="删除所有连接", command=lambda: E.edge_delall())
menu_node.add_command(label="删除所有多余连接", command=lambda: E.newedge_del_all(1))
# menu_node.add_command(label="设置连接标签", command=lambda: edge_rename())
# 在主目录菜单上新增"文件"选项并通过menu参数与下拉菜单绑定
menu.add_cascade(label="连接操作", menu=menu_node)
def path_opera_mu(menu: tk.Menu):
"""路径操作"""
menu_node = Menu(menu, tearoff=False)
menu_node.add_command(label="开始标记路径", command=lambda: W.way_mark_display())
menu_node.add_command(label="撤销一步路径", command=lambda: W.user_way_del())
menu_node.add_command(label="取消所有路径标记", command=lambda: W.user_way_clear())
# 在主目录菜单上新增"文件"选项并通过menu参数与下拉菜单绑定
menu.add_cascade(label="路径操作", menu=menu_node, )
auto_opera_mu(main_menu)
node_opera_mu(main_menu)
edge_opera_mu(main_menu)
path_opera_mu(main_menu)
def main():
G = Graph()
G.draw()
sourc_set(2)
mainloop()
if __name__ == '__main__':
main()

@ -0,0 +1,41 @@
# -*- encoding: utf-8 -*-
# 查询城市的经纬度并存入excel中
# 本次整体的源代码
AK = "9AfjsK2CXGuESwSb4sF3LsGhWh999Rdd"
import pandas as pd
import requests
import json
def getPosition(address):
url = r"http://api.map.baidu.com/place/v2/search?query={}&region=全国&output=json&ak={}".format(
address,
AK # 这里是一开始截图用红色圈起来的部分,无需修改
)
res = requests.get(url)
json_data = json.loads(res.text)
if json_data["status"] == 0:
lat = json_data["results"][0]["location"]["lat"] # 纬度
lng = json_data["results"][0]["location"]["lng"] # 经度
else:
print(json_data["message"])
return "0,0", json_data["status"]
return lat,lng
if __name__ == "__main__":
res = []
maps = ['哈尔滨市', '齐齐哈尔市', '鸡西市', '鹤岗市', '双鸭山市', '大庆市', '伊春市', '佳木斯市', '七台河市', '牡丹江市', '黑河市', '绥化市', '大兴安岭地区']
for i in range(len(maps)):
Name = maps[i]
P1 = getPosition(Name)
res.append([Name, P1[0], P1[1]])
pd.DataFrame(res).to_excel(
"data.xlsx",
header=["地点", "纬度", "经度"],
index=None,
encoding="utf-8"
)
Loading…
Cancel
Save