You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

271 lines
12 KiB

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