commit lab1

This commit is contained in:
qasw-987 2024-06-03 16:20:04 +08:00
parent bf5842d489
commit 67c2869323
1 changed files with 85 additions and 49 deletions

134
oop.py
View File

@ -1,11 +1,14 @@
import copy import copy
import heapq import heapq
import re import re
from math import isinf,inf import sys
import time
from math import isinf, inf
import matplotlib.patches import matplotlib.patches
import networkx as nx import networkx as nx
import matplotlib.pyplot as plt 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 random
import os import os
@ -14,11 +17,12 @@ def main():
# print("Welcome to Lab1") # print("Welcome to Lab1")
print("功能5中输入@停止功能") print("功能5中输入@停止功能")
tu = None tu = None
while True: while True:
i = input("请输入操作q:退出, 0:读入文件, 1:展示图形, 2:查找桥接词, 3:生成新文本, 4:计算最短路径, 5:随机游走):") i = input("请输入操作q:退出, 0:读入文件, 1:展示图形, 2:查找桥接词, 3:生成新文本, 4:计算最短路径, 5:随机游走):")
if i == "q" : if i == "q" :
exit(0) sys.exit()
if i == "0": #shengchengTu if i == "0": #shengchengTu
tu=Tu() tu=Tu()
@ -63,7 +67,7 @@ class Tu :
def read_text_file(self,filename): def read_text_file(self,filename):
try: try:
with open(filename, 'r') as file: with open(filename, 'r',"UTF-8") as file:
text = file.read() text = file.read()
# 用正则表达式将非字母字符替换为空格,并将换行符也替换为空格 # 用正则表达式将非字母字符替换为空格,并将换行符也替换为空格
text = re.sub(r'[^a-zA-Z\n]+', ' ', text) text = re.sub(r'[^a-zA-Z\n]+', ' ', text)
@ -109,9 +113,10 @@ class Tu :
def draw_directed_graph(self): def draw_directed_graph(self):
G=self.graph G=self.graph
pos = nx.spring_layout(G) 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", nx.draw_networkx(G, pos, with_labels=True, node_size=1000,
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') edge_labels = nx.get_edge_attributes(G, 'weight')
# 调整箭头位置 # 调整箭头位置
for edge, weight in edge_labels.items(): for edge, weight in edge_labels.items():
@ -119,9 +124,11 @@ class Tu :
dx = pos[edge[0]][0] - pos[edge[1]][0] dx = pos[edge[0]][0] - pos[edge[1]][0]
dy = pos[edge[0]][1] - pos[edge[1]][1] dy = pos[edge[0]][1] - pos[edge[1]][1]
plt.annotate(weight, ( 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: # 反向边不存在 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() plt.show()
def drawDirectedGraph(self): def drawDirectedGraph(self):
@ -134,23 +141,10 @@ class Tu :
print("No", word1, "or", word2, "in the graph!") print("No", word1, "or", word2, "in the graph!")
return [] return []
bridge_words = [] bridge_words = [
bridge_words_origin = [] word for word in graph[word1]
for bridge_word in graph: if word2 in graph.get(word, {})
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)
return bridge_words return bridge_words
@ -202,24 +196,42 @@ class Tu :
print("There are upper characters in your input") print("There are upper characters in your input")
print(self.insert_bridge_words(text_re)) 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): def find_shortest_path(self,word1, word2):
graph=self.graph
try: 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): def draw_shortest_path(self, shortest_path_list):
graph=self.graph graph=self.graph
@ -242,17 +254,22 @@ class Tu :
#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]): 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') ,connectionstyle='arc3,rad=0.2')
else: 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') ,connectionstyle='arc3,rad=0.2')
plt.show() plt.show()
time.sleep(1)
def calcShortestPath(self,word1, word2): def calcShortestPath(self,word1, word2):
@ -272,9 +289,9 @@ class Tu :
pass 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=[] shortest_path_list=[]
for shortest_path in shortest_path_generator: for shortest_path in shortest_path_generator:
@ -288,6 +305,24 @@ class Tu :
else: else:
print("No path exists between", word1, "and", word2) 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): def random_traversal(self):
# 用户输入文件名 # 用户输入文件名
@ -374,12 +409,13 @@ class Tu :
stack.pop() stack.pop()
visited.popitem() 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: if word1 not in self.graph.nodes or word2 not in self.graph.nodes:
return "" 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 previous_nodes: Dict[str, Optional[str]] = {node: None for node in self.graph.nodes} # 存储每个节点最短路径中的前一个节点初始化为None
distances[word1] = 0 # 距离初始化为0 distances[word1] = 0 # 距离初始化为0
priority_queue = [(0, word1)] # 优先级队列,用于按照从小到大获取节点 priority_queue = [(0, word1)] # 优先级队列,用于按照从小到大获取节点
@ -412,9 +448,9 @@ class Tu :
path.insert(0, current_node) path.insert(0, current_node)
if isinf(distances[word2]): # 目标节点不可达 if isinf(distances[word2]): # 目标节点不可达
return "" return ("",0)
return path.__len__() return path.__len__()
return ' '.join(path) #return (' '.join(path),path.__len__())
if __name__ == '__main__': if __name__ == '__main__':