Advertisement
vatman

бмо графы 1

Dec 20th, 2023
776
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.11 KB | None | 0 0
  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. from mpl_toolkits.mplot3d import Axes3D
  4. import networkx as nx
  5. from scipy.spatial import distance
  6. from scipy.spatial import distance_matrix
  7. import itertools
  8.  
  9.  
  10. vertex_k = 100 # Замените на ваше значение для коэффициента аппроксимации вершин
  11. edge_k =1  # Замените на ваше значение для коэффициента растяжения ребер
  12. wedge_k = 1 # Замените на ваше значение для коэффициента изгиба клиньев
  13. np.random.seed(12)  
  14. vectors = [np.random.randint(-6, 7, 3) for _ in range(100)]
  15.  
  16.  
  17. # Выбираем три случайные точки (вектора)
  18. indices = np.random.choice(len(vectors),10, replace=False)
  19. selected_vectors = [vectors[i] for i in indices]
  20. #print(indices)
  21.  
  22. # Вычисляем матрицу расстояний между всеми векторами
  23. distances = distance_matrix(selected_vectors, selected_vectors)
  24.  
  25. # Заменяем диагональные элементы на бесконечность
  26. np.fill_diagonal(distances, np.inf)
  27. #print(distances)
  28. # Создаем список пар (расстояние, вектор)
  29. dist_vector_pairs = [(np.min(dist), vec) for dist, vec in zip(distances, selected_vectors)]
  30. #print(dist_vector_pairs)
  31. # Сортируем список пар по расстоянию
  32. dist_vector_pairs.sort(key=lambda x: x[0])
  33. #print(dist_vector_pairs)
  34. # Извлекаем отсортированные векторы
  35. sorted_vectors = [pair[1] for pair in dist_vector_pairs]
  36. #print(sorted_vectors)
  37. selected_vectors =sorted_vectors
  38. # Создаем граф
  39. # Вычисляем матрицу расстояний между всеми векторами
  40. distances = distance_matrix(selected_vectors, selected_vectors)
  41. # Заменяем диагональные элементы на бесконечность
  42. np.fill_diagonal(distances, np.inf)
  43. #print(distances)
  44. G = nx.Graph()
  45.  
  46. #Добавляем вершины в граф
  47. for i in range(len(selected_vectors)):
  48.     G.add_node(i)
  49.    
  50. visited = set()  # Создаем множество для хранения посещенных вершин
  51.  
  52. for i in range(len(selected_vectors)):
  53.     # Находим ближайшую вершину к текущей вершине
  54.     nearest_vertex = np.argmin(distances[i])
  55.     print("ближайшие вершины")
  56.     print(i, nearest_vertex)
  57.  
  58.     # Проверяем, была ли уже посещена ближайшая вершина
  59.     if i not in visited:
  60.         # Если вершина не была посещена, добавляем ребро
  61.         G.add_edge(i, nearest_vertex)
  62.         # Добавляем вершину в множество посещенных вершин
  63.         visited.add(nearest_vertex)
  64.         print(visited)
  65.     else:
  66.         # Если вершина уже была посещена, пропускаем ее
  67.         print("пропуск вершины")
  68.         print(i, nearest_vertex)
  69.         continue
  70.  
  71.  
  72. def DFS(graph, start, visited=None):
  73.     if visited is None:
  74.         visited = set()
  75.     visited.add(start)
  76.     for next_node in set(graph[start]) - visited:
  77.         DFS(graph, next_node, visited)
  78.     return visited
  79.  
  80. # Проверяем, является ли граф связным
  81. connected = len(DFS(G, 0)) == len(G)
  82.  
  83. if not connected:
  84.     # Граф не связный, находим несвязанные компоненты
  85.     components = [list(c) for c in nx.connected_components(G)]
  86.     # Соединяем компоненты, добавляя ребра между их вершинами
  87.     for i in range(len(components) - 1):
  88.         G.add_edge(components[i][0], components[i+1][0])
  89.  
  90.  
  91.  
  92.  
  93. # Расчет энергии вершины
  94. def calculate_vertex_energy(vertex, vectors, k):
  95.     energy = 0
  96.     for vector in vectors:
  97.         energy += np.linalg.norm(vertex - vector)**2
  98.     return k * energy
  99.  
  100. # Расчет энергии ребра
  101. def calculate_edge_energy(edge, vectors, k):
  102.     v1, v2 = vectors[edge[0]], vectors[edge[1]]
  103.     return k * np.linalg.norm(v1 - v2)**2
  104.  
  105. # Расчет энергии клина
  106. def calculate_wedge_energy(wedge, vectors, k):
  107.     v1, v2, v3 = vectors[wedge[0]], vectors[wedge[1]], vectors[wedge[2]]
  108.     return k * np.linalg.norm(v1 + v3 - 2*v2)**2
  109.  
  110. #global max_wedge_energy
  111. #max_wedge_energy=-np.inf# Инициализируем максимальную энергию клина как минус бесконечность
  112. max_energy_wedge = None  # Инициализируем клин с максимальной энергией как None
  113. edge_combination=0
  114.  
  115. # Расчет энергии графа
  116. def calculate_energy(graph, vectors):
  117.     #vertex_k = 0.5 # Замените на ваше значение для коэффициента аппроксимации вершин
  118.     #edge_k = 0.5 # Замените на ваше значение для коэффициента растяжения ребер
  119.     #wedge_k = 0.5 # Замените на ваше значение для коэффициента изгиба клиньев
  120.     global max_wedge_energy
  121.     max_wedge_energy=-np.inf
  122.    
  123.     energy = 0
  124.     for node in graph.nodes:
  125.         energy += calculate_vertex_energy(vectors[int(node)], vectors, vertex_k)
  126.     for edge in graph.edges:
  127.         energy += calculate_edge_energy(edge, vectors, edge_k)
  128.        
  129.     # Добавляем энергию клина для всех подграфов из трех вершин
  130.     for nodes in itertools.combinations(graph.nodes, 3):
  131.         #print(nodes)
  132.         if graph.has_edge(nodes[0], nodes[1]) and graph.has_edge(nodes[0], nodes[2]):
  133.             wedge_energy = calculate_wedge_energy(nodes, vectors, wedge_k)
  134.             #print("Энергия клина:")
  135.             #print(p1)
  136.             if wedge_energy > max_wedge_energy:
  137.                 max_wedge_energy = wedge_energy
  138.                 max_energy_wedge = nodes
  139.                 edge_combination=1
  140.             energy += wedge_energy
  141.         elif graph.has_edge(nodes[0], nodes[1]) and graph.has_edge(nodes[1], nodes[2]):
  142.             wedge_energy = calculate_wedge_energy(nodes, vectors, wedge_k)            
  143.             if wedge_energy > max_wedge_energy:
  144.                 max_wedge_energy = wedge_energy
  145.                 max_energy_wedge = nodes
  146.                 edge_combination=2
  147.                 #print("Энергия клина:")
  148.             #print(p1)
  149.             energy +=wedge_energy
  150.         elif graph.has_edge(nodes[0], nodes[2]) and graph.has_edge(nodes[1], nodes[2]):
  151.             wedge_energy = calculate_wedge_energy(nodes, vectors, wedge_k)
  152.             if wedge_energy > max_wedge_energy:
  153.                 max_wedge_energy = wedge_energy
  154.                 max_energy_wedge = nodes
  155.                 edge_combination=3
  156.             #print("Энергия клина:")
  157.             #print(p1)
  158.             energy += wedge_energy        
  159.     return energy
  160.  
  161. energy = calculate_energy(G, selected_vectors)
  162. print(f'Энергия графа: {energy}')
  163.    
  164.    
  165. # Визуализация проекции графа и векторов
  166. fig = plt.figure()
  167. ax = fig.add_subplot(111, projection='3d')
  168.  
  169. # Отображаем все векторы на графике
  170. for vector in vectors:
  171.     ax.scatter(vector[0], vector[1], vector[2], color='b')
  172.  
  173. # Отображаем выбранные векторы на графике
  174. for vector in selected_vectors:
  175.     ax.scatter(vector[0], vector[1], vector[2], color='r')
  176.  
  177. # Добавляем ребра между вершинами
  178. for edge in G.edges:    
  179.     ax.plot([selected_vectors[edge[0]][0], selected_vectors[edge[1]][0]],
  180.             [selected_vectors[edge[0]][1], selected_vectors[edge[1]][1]],
  181.             [selected_vectors[edge[0]][2], selected_vectors[edge[1]][2]], 'r-')
  182. #for edges in G.edges:
  183. #    print(edges)
  184.    
  185. # Добавляем оси
  186. ax.set_xlabel('X')
  187. ax.set_ylabel('Y')
  188. ax.set_zlabel('Z')
  189. plt.show()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement