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