diff --git a/oop.py b/oop.py index c2bf89d..7d1c754 100644 --- a/oop.py +++ b/oop.py @@ -4,13 +4,10 @@ import re 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, Tuple +from typing import Dict, Generator, List, Optional import random -import os def main(): @@ -21,53 +18,53 @@ def main(): while True: i = input("请输入操作(q:退出, 0:读入文件, 1:展示图形, 2:查找桥接词, 3:生成新文本, 4:计算最短路径, 5:随机游走):") - if i == "q" : + if i == "q": sys.exit() - if i == "0": #shengchengTu - tu=Tu() + if i == "0": + tu = Tu() - file_name=input("请输入文件名称:") + file_name = input("请输入文件名称:") tu.generate_directed_dict(tu.read_text_file(file_name)) tu.generate_directed_graph() continue - if tu is None : + if tu is None: print("未找到有效的图") continue if i == "1": tu.drawDirectedGraph() - elif i == "2" : + elif i == "2": word1 = input("Enter the word1:") word2 = input("Enter the word2:") - tu.queryBridgeWords(word1,word2) - elif i == "3" : + tu.queryBridgeWords(word1, word2) + elif i == "3": text = input("Enter the text:") tu.generateNewText(text) - elif i== "4" : + elif i == "4": word1 = input("Enter the word1:") word2 = input("Enter the word2,just '' is all") - tu.calcShortestPath(word1,word2) + tu.calcShortestPath(word1, word2) - elif i == "5" : + elif i == "5": tu.randomWalk() else: print("Invalid input") - -class Tu : +class Tu: def __init__(self): - self.dict={} - self.graph=nx.MultiDiGraph() + self.dict = {} + self.graph = nx.MultiDiGraph() - def read_text_file(self,filename): + @staticmethod + def read_text_file(filename): try: - with open(filename, 'r',"UTF-8") as file: + with open(filename, 'r', encoding="utf-8") as file: text = file.read() # 用正则表达式将非字母字符替换为空格,并将换行符也替换为空格 text = re.sub(r'[^a-zA-Z\n]+', ' ', text) @@ -79,8 +76,8 @@ class Tu : print("File not found.") return [] - def generate_directed_dict(self,word_sequence): - graph = self.dict #chunfuzhi,yiqigai + def generate_directed_dict(self, word_sequence): + graph = self.dict for i in range(len(word_sequence) - 1): current_word = word_sequence[i] next_word = word_sequence[i + 1] @@ -99,7 +96,7 @@ class Tu : return graph def generate_directed_graph(self): - G = self.graph #wufuzhi,yiqigai + G = self.graph # wufuzhi,yiqigai graph = self.dict # 添加节点和边 for node, neighbors in graph.items(): @@ -111,12 +108,12 @@ class Tu : return G def draw_directed_graph(self): - G=self.graph + G = self.graph pos = nx.spring_layout(G) 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') + 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(): @@ -124,9 +121,9 @@ 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)) - else: # 反向边不存在 + (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.show() @@ -148,7 +145,8 @@ class Tu : return bridge_words - def print_bridge_words(self,bridge_words,word1,word2): + @staticmethod + def print_bridge_words(bridge_words, word1, word2): if not bridge_words: print("No bridge words from", word1, "to", word2, "!") @@ -159,11 +157,11 @@ class Tu : return bridge_words - def queryBridgeWords(self,word1, word2): + def queryBridgeWords(self, word1, word2): word1 = self.input_check(word1) word2 = self.input_check(word2) bridge_words = self.find_bridge_words(word1, word2) - self.print_bridge_words(bridge_words,word1,word2) + self.print_bridge_words(bridge_words, word1, word2) def insert_bridge_words(self, text): @@ -177,7 +175,7 @@ class Tu : word2 = words[i + 1].lower() new_text.append(words[i]) - bridge_words = self.find_bridge_words( word1, word2) + bridge_words = self.find_bridge_words(word1, word2) if len(bridge_words) > 0: random_bridge_word = random.choice(bridge_words) @@ -187,18 +185,18 @@ class Tu : return ' '.join(new_text) - def generateNewText(self,text): + def generateNewText(self, text): - (text_re,text_ren)=re.subn(r'[^a-zA-Z\n]+', ' ', text) - if text_ren>0 : + (text_re, text_ren) = re.subn(r'[^a-zA-Z\n]+', ' ', text) + if text_ren > 0: print("There are illegal signs in your input") if not text_re.islower(): print("There are upper characters in your input") print(self.insert_bridge_words(text_re)) - def find_shortest_path_old(self,word1, word2): + def find_shortest_path_old(self, word1, word2): - graph=self.graph + graph = self.graph try: shortest_path_generator = ( nx.all_shortest_paths(graph, source=word1, target=word2, weight='weight')) @@ -207,39 +205,38 @@ class Tu : return shortest_path_generator, shortest_length except nx.NetworkXNoPath: return None, None - def find_shortest_path(self,word1, word2): + + def find_shortest_path(self, word1, word2): try: - (shortest_path_list,shortest_length)=self.calc_shortest_path_len(word1,word2) + (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): + + 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_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: + if shortest_path.__len__() == shortest_length: shortest_path_list.append(shortest_path) - return(shortest_path_list,shortest_length) - - + return shortest_path_list, shortest_length except nx.NetworkXNoPath: return None, None def draw_shortest_path(self, shortest_path_list): - graph=self.graph + graph = self.graph plt.figure(figsize=(10, 6)) # !!! HUATU ROLL YANSE - pos = nx.spring_layout(graph) nx.draw_networkx_nodes(graph, pos, node_size=1000, node_color="skyblue") nx.draw_networkx_labels(graph, pos, font_size=10, font_weight="bold") @@ -252,47 +249,42 @@ class Tu : for edge in graph.edges(): - #print(shortest_path) + # print(shortest_path) 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 - ,connectionstyle='arc3,rad=0.2') + 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 - ,connectionstyle='arc3,rad=0.2') + arrows=True, arrowstyle="->", arrowsize=30, + connectionstyle='arc3,rad=0.2') plt.show() time.sleep(1) - - def calcShortestPath(self,word1, word2): + def calcShortestPath(self, word1, word2): if word2 == "": word1 = self.input_check(word1) - for wordtmp in self.dict : - if wordtmp == word1 : + for wordtmp in self.dict: + if wordtmp == word1: continue else: - self.calc_shortest_path(word1,wordtmp) + self.calc_shortest_path(word1, wordtmp) pass else: word1 = self.input_check(word1) word2 = self.input_check(word2) - self.calc_shortest_path(word1,word2) + self.calc_shortest_path(word1, word2) pass - - def calc_shortest_path_old(self,word1, word2): + def calc_shortest_path_old(self, word1, word2): shortest_path_generator, shortest_length = self.find_shortest_path_old(word1, word2) - shortest_path_list=[] + shortest_path_list = [] for shortest_path in shortest_path_generator: @@ -300,25 +292,22 @@ class Tu : print("Shortest path:", '→'.join(shortest_path)) print("Length of shortest path:", shortest_length) shortest_path_list.append(shortest_path) - if shortest_path_list.__len__()>0: + if shortest_path_list.__len__() > 0: self.draw_shortest_path(shortest_path_list) else: print("No path exists between", word1, "and", word2) - - def calc_shortest_path(self,word1, 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: + if shortest_path_list.__len__() > 0: self.draw_shortest_path(shortest_path_list) else: print("No path exists between", word1, "and", word2) @@ -327,10 +316,9 @@ class Tu : # 用户输入文件名 filename = input("Enter the filename to save traversal results: ") - filename+=".txt" + filename += ".txt" - - graph=copy.deepcopy(self.dict) + graph = copy.deepcopy(self.dict) start_node = random.choice(list(graph.keys())) visited_nodes = set() visited_edges = [] @@ -341,10 +329,10 @@ class Tu : visited_nodes.add(current_node) file.write(current_node + '\n') print(current_node) - if input()=="@": + if input() == "@": file.close() break - if graph.get(current_node) != None: + if graph.get(current_node) is not None: pass else: break @@ -364,23 +352,21 @@ class Tu : def randomWalk(self): self.random_traversal() + @staticmethod + def input_check(input_word): + (input_word_re, input_word_ren) = re.subn(r'[^a-zA-Z\n]', ' ', input_word) - def input_check(self, input_word): - (input_word_re,input_word_ren)=re.subn(r'[^a-zA-Z\n]', ' ', input_word) - - - if input_word_ren>0 : - print("There are illegal signs in your input,the amount is "+str(input_word_ren)) + if input_word_ren > 0: + print("There are illegal signs in your input,the amount is " + str(input_word_ren)) if not input_word_re.islower(): print("There are upper characters in your input") - tmp=input_word_re.lower().split() - if len(tmp)>1 : + tmp = input_word_re.lower().split() + if len(tmp) > 1: print("There are more than one word in your input") return tmp[0] - def all_simple_paths_graph(self, source: str, targets: str) -> Generator[List[str], None, None]: G = self.graph cutoff = len(G) - 1 # 设置路径的最大深度,防止无限循环。 @@ -409,14 +395,15 @@ class Tu : stack.pop() visited.popitem() - def calc_shortest_path_len(self, word1: str, word2: str) -> str | tuple[str, int]: + def calc_shortest_path_len(self, word1: str, word2: str) -> int: if word1 not in self.graph.nodes or word2 not in self.graph.nodes: - return "" + return 0 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 + previous_nodes: Dict[str, Optional[str]] = {node: None for node in + self.graph.nodes} # 存储每个节点最短路径中的前一个节点,初始化为None distances[word1] = 0 # 距离初始化为0 priority_queue = [(0, word1)] # 优先级队列,用于按照从小到大获取节点 @@ -448,9 +435,9 @@ class Tu : path.insert(0, current_node) if isinf(distances[word2]): # 目标节点不可达 - return ("",0) + return 0 return path.__len__() - #return (' '.join(path),path.__len__()) + # return (' '.join(path),path.__len__()) if __name__ == '__main__':