From 67c28693230c2ea928ce2fc6604517c1eb9475f4 Mon Sep 17 00:00:00 2001 From: qasw-987 <143506929+qasw-987@users.noreply.github.com> Date: Mon, 3 Jun 2024 16:20:04 +0800 Subject: [PATCH] commit lab1 --- oop.py | 134 ++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 85 insertions(+), 49 deletions(-) diff --git a/oop.py b/oop.py index 9605ca9..c2bf89d 100644 --- a/oop.py +++ b/oop.py @@ -1,11 +1,14 @@ import copy import heapq import re -from math import isinf,inf +import sys +import time +from math import isinf, inf + import matplotlib.patches import networkx as nx import matplotlib.pyplot as plt -from typing import Dict, Generator, List, Optional, cast +from typing import Dict, Generator, List, Optional, cast, Tuple import random import os @@ -14,11 +17,12 @@ def main(): # print("Welcome to Lab1") print("功能5中输入@停止功能") tu = None + while True: i = input("请输入操作(q:退出, 0:读入文件, 1:展示图形, 2:查找桥接词, 3:生成新文本, 4:计算最短路径, 5:随机游走):") if i == "q" : - exit(0) + sys.exit() if i == "0": #shengchengTu tu=Tu() @@ -63,7 +67,7 @@ class Tu : def read_text_file(self,filename): try: - with open(filename, 'r') as file: + with open(filename, 'r',"UTF-8") as file: text = file.read() # 用正则表达式将非字母字符替换为空格,并将换行符也替换为空格 text = re.sub(r'[^a-zA-Z\n]+', ' ', text) @@ -109,9 +113,10 @@ class Tu : def draw_directed_graph(self): G=self.graph pos = nx.spring_layout(G) - - nx.draw_networkx(G, pos, with_labels=True, node_size=1000, node_color="skyblue",edge_color="black", font_size=10, font_weight="bold", - arrows=True, connectionstyle='arc3,rad=0.2') + plt.rcParams['figure.figsize'] = (12.8, 7.2) + nx.draw_networkx(G, pos, with_labels=True, node_size=1000, + node_color="skyblue",edge_color="black", font_size=10, + font_weight="bold",arrows=True, connectionstyle='arc3,rad=0.2') edge_labels = nx.get_edge_attributes(G, 'weight') # 调整箭头位置 for edge, weight in edge_labels.items(): @@ -119,9 +124,11 @@ class Tu : dx = pos[edge[0]][0] - pos[edge[1]][0] dy = pos[edge[0]][1] - pos[edge[1]][1] plt.annotate(weight, ( - (pos[edge[0]][0] + pos[edge[1]][0]) / 2 + dy * 0.1, (pos[edge[0]][1] + pos[edge[1]][1]) / 2 - dx * 0.1)) + (pos[edge[0]][0] + pos[edge[1]][0]) / 2 + dy * 0.1, + (pos[edge[0]][1] + pos[edge[1]][1]) / 2 - dx * 0.1)) else: # 反向边不存在 - plt.annotate(weight, ((pos[edge[0]][0] + pos[edge[1]][0]) / 2, (pos[edge[0]][1] + pos[edge[1]][1]) / 2)) + plt.annotate(weight, ((pos[edge[0]][0] + pos[edge[1]][0]) / 2, + (pos[edge[0]][1] + pos[edge[1]][1]) / 2)) plt.show() def drawDirectedGraph(self): @@ -134,23 +141,10 @@ class Tu : print("No", word1, "or", word2, "in the graph!") return [] - bridge_words = [] - bridge_words_origin = [] - for bridge_word in graph: - if word1 == bridge_word: - bridge_words = list(graph[bridge_word].keys()) - bridge_words_origin = copy.deepcopy(bridge_words) - - for wordi in bridge_words_origin: - - - if graph.get(wordi) != None: - - if word2 not in graph[wordi].keys(): - bridge_words.remove(wordi) - - else: - bridge_words.remove(wordi) + bridge_words = [ + word for word in graph[word1] + if word2 in graph.get(word, {}) + ] return bridge_words @@ -202,24 +196,42 @@ class Tu : print("There are upper characters in your input") print(self.insert_bridge_words(text_re)) + def find_shortest_path_old(self,word1, word2): + + graph=self.graph + try: + shortest_path_generator = ( + nx.all_shortest_paths(graph, source=word1, target=word2, weight='weight')) + shortest_length = ( + nx.shortest_path_length(graph, source=word1, target=word2, weight='weight')) + return shortest_path_generator, shortest_length + except nx.NetworkXNoPath: + return None, None def find_shortest_path(self,word1, word2): - graph=self.graph try: - shortest_path_generator = nx.all_shortest_paths(graph, source=word1, target=word2, weight='weight') - shortest_length = nx.shortest_path_length(graph, source=word1, target=word2, weight='weight') - return shortest_path_generator, shortest_length - except nx.NetworkXNoPath: - return None, None - def find_shortest_path_re(self,word1, word2): - graph=self.graph - try: - shortest_path_generator = self.all_simple_paths_graph(word1, word2) - shortest_length=self.calc_shortest_path_len(word1,word2) - return shortest_path_generator, shortest_length - except nx.NetworkXNoPath: - return None, None + (shortest_path_list,shortest_length)=self.calc_shortest_path_len(word1,word2) + return shortest_path_list, shortest_length + except nx.NetworkXNoPath: + return None, None + def find_shortest_path_ex(self,word1, word2): + + try: + shortest_path_generator=self.all_simple_paths_graph(word1,word2) + shortest_length=self.calc_shortest_path_len(word1,word2) + + shortest_path_list = [] + + for shortest_path in shortest_path_generator: + + if shortest_path.__len__()==shortest_length: + shortest_path_list.append(shortest_path) + return(shortest_path_list,shortest_length) + + + except nx.NetworkXNoPath: + return None, None def draw_shortest_path(self, shortest_path_list): graph=self.graph @@ -242,17 +254,22 @@ class Tu : #print(shortest_path) - if edge in zip(shortest_path[:-1], shortest_path[1:]) or edge in zip(shortest_path[1:], shortest_path[:-1]): + if (edge in zip(shortest_path[:-1], shortest_path[1:]) or + edge in zip(shortest_path[1:], shortest_path[:-1])): - nx.draw_networkx_edges(graph, pos, edgelist=[edge], width=2.0, edge_color=num, arrows=True,arrowstyle="->",arrowsize=30 + nx.draw_networkx_edges(graph, pos, edgelist=[edge], width=2.0, edge_color=num, + arrows=True,arrowstyle="->",arrowsize=30 ,connectionstyle='arc3,rad=0.2') else: - nx.draw_networkx_edges(graph, pos, edgelist=[edge], width=1.0, edge_color="black", arrows=True,arrowstyle="->",arrowsize=30 + nx.draw_networkx_edges(graph, pos, edgelist=[edge], width=1.0, + edge_color="black", + arrows=True,arrowstyle="->",arrowsize=30 ,connectionstyle='arc3,rad=0.2') plt.show() + time.sleep(1) def calcShortestPath(self,word1, word2): @@ -272,9 +289,9 @@ class Tu : pass - def calc_shortest_path(self,word1, word2): + def calc_shortest_path_old(self,word1, word2): - shortest_path_generator, shortest_length = self.find_shortest_path_re(word1, word2) + shortest_path_generator, shortest_length = self.find_shortest_path_old(word1, word2) shortest_path_list=[] for shortest_path in shortest_path_generator: @@ -288,6 +305,24 @@ class Tu : else: print("No path exists between", word1, "and", word2) + + def calc_shortest_path(self,word1, word2): + + shortest_path_list, shortest_length = self.find_shortest_path_ex(word1, word2) + + + + for shortest_path in shortest_path_list: + + if shortest_path: + print("Shortest path:", '→'.join(shortest_path)) + print("Length of shortest path:", shortest_length) + + if shortest_path_list.__len__()>0: + self.draw_shortest_path(shortest_path_list) + else: + print("No path exists between", word1, "and", word2) + def random_traversal(self): # 用户输入文件名 @@ -374,12 +409,13 @@ class Tu : stack.pop() visited.popitem() - def calc_shortest_path_len(self, word1: str, word2: str) -> str: + def calc_shortest_path_len(self, word1: str, word2: str) -> str | tuple[str, int]: if word1 not in self.graph.nodes or word2 not in self.graph.nodes: return "" - distances = {node: inf for node in self.graph.nodes} # 存储word1到所有结点的距离,初始化为无穷大 + distances = {node: inf for node in self.graph.nodes} + # 存储word1到所有结点的距离,初始化为无穷大 previous_nodes: Dict[str, Optional[str]] = {node: None for node in self.graph.nodes} # 存储每个节点最短路径中的前一个节点,初始化为None distances[word1] = 0 # 距离初始化为0 priority_queue = [(0, word1)] # 优先级队列,用于按照从小到大获取节点 @@ -412,9 +448,9 @@ class Tu : path.insert(0, current_node) if isinf(distances[word2]): # 目标节点不可达 - return "" + return ("",0) return path.__len__() - return ' '.join(path) + #return (' '.join(path),path.__len__()) if __name__ == '__main__':