
Цель работы: реализовать и проверить на тестовом примере базовый алгоритм на графе. Сравнить быстродействие реализованного алгоритма на специальных графах.
Индивидуальный вариант:
Вариант № 21
На рисунке 1-2 представлены алгоритм и тип графа согласно индивидуальному варианту.
Рисунок 1- Название алгоритма
Рисунок 2- Тип графа
Ход работы
Создан граф в представлении списка ребер (Рисунок 1).
Листинг 1. Создание графа
import networkx as nx
import matplotlib.pyplot as plt
G = nx.Graph()
edges = [(1, 3), (1, 2), (3, 4),
(3, 6), (2, 4), (5,8),
(5, 6), (6, 7), (7, 3),(7,8)]
G.add_edges_from(edges)
pos = nx.spring_layout(G)
nx.draw(G, pos, with_labels=True, node_size=700, node_color="skyblue", font_size=10, font_weight="bold", edge_color='gray')
plt.show()
Рисунок 1- Созданный граф
Затем создана функция для реализации алгоритма поиска кратчайшего пути в глубину. (Рисунок 2).
При поиске в глубину посещается первая вершина, затем необходимо идти вдоль ребер графа, до попадания в тупик. Вершина графа является тупиком, если все смежные с ней вершины уже посещены. После попадания в тупик нужно возвращаться назад вдоль пройденного пути, пока не будет обнаружена вершина, которая еще не посещена.
Листинг 2- Алгоритм поиска кратчайшего пути в глубину
def dfs(graph, current_node, goal, path=None, shortest=None):
#Если текущий путь path не определен, он инициализируется списком, содержащим только текущую вершину.
if path is None:
path = [current_node]
#Проверяется является ли текущий путь кратчайшим
if shortest is None or len(path) < len(shortest):
print("Текущий путь:", path)
if current_node == goal:
print("Достигнута целевая вершина!")
shortest = path
for node in graph.neighbors(current_node):
if node not in path:
print("Переход к вершине", node)
new_path = dfs(graph, node, goal, path + [node], shortest)
if new_path:
shortest = new_path if not shortest or len(new_path) < len(shortest) else shortest
return shortest
# Начальная и конечная вершины для поиска кратчайшего пути
start_node = 1
goal_node = 8
shortest_path = dfs(G, start_node, goal_node)
print("Кратчайший путь от вершины", start_node, "к вершине", goal_node, ":", shortest_path)
Рисунок 3- Результат работы алгоритма поиска кратчайшего пути в глубину
Создается функция для формирования графа в виде правильной шестиугольной решетки. Затем выполняется реализация графа (Рисунок 4-5).
Листинг 4- Представление графа в виде правильной шестиугольной решетки
import numpy as np
Import networkx as nx
Import matplotlib.Pyplot as plt
def create_hexagonal_grid(M):
if M < 2:
return np.array([])
# Создание пустой матрицы смежности размером M x M
matrix_size = M * M
matrix = np.zeros((matrix_size, matrix_size), dtype=int)
# Заполнение матрицы смежности
for v in range(matrix_size):
R = v // M
C = v % M
if (R % 4 == 0 and C % 2 == 1) or (R % 4 == 2 and C % 2 == 0):
if R > 0:
matrix[v][v - M] = matrix[v - M][v] = 1# Соединяем с вершиной выше
if R < (M - 1) and C < (M - 1):
matrix[v][v + M + 1] = matrix[v + M + 1][v] = 1 # Соединяем с вершиной справа ниже
if R < (M - 1) and C > 0:
matrix[v][v + M - 1] = matrix[v + M - 1][v] = 1 # Соединяем с вершиной слева ниже
# Удаление лишних вершин (те, у которых меньше 2 связей)
non_isolated = np.array([i for i in range(matrix_size) if np.sum(matrix[i]) > 1], dtype=int)
matrix = matrix[non_isolated][:, non_isolated]
return matrix
M = 6 # Размер решетки M на M
matrix = create_hexagonal_grid(M)
print("Матрица смежности созданной решетки:")
print(matrix)
G = nx.from_numpy_array(matrix)
pos = nx.spring_layout(G, iterations=100000, seed=1000)
nx.draw(G, pos, with_labels=True, node_size=500, node_color="skyblue", font_size=10, font_weight="bold")
plt.title("Шестиугольная решетка")
plt.show()
Рисунок 4- Матрица смежности созданной решетки
Рисунок 5- Визуализация графа типа правильной шестиугольной решетки
Рисунок 6- Кратчайший путь для графа правильной шестиугольной решетки от вершины 1 до 14
Определяется среднее время выполнения алгоритма поиска в глубину в зависимости от размерности графа правильной шестиугольной решетки, выводится график данной зависимости (Рисунок 7).
Рисунок 7- График зависимости времени выполнения алгоритма DFS от количества узлов
График показывает, что с увеличением количества узлов в решетке время выполнения алгоритма возрастает. Можно заметить, что увеличение времени не всегда происходит равномерно; например, прыжок между размерами решетки 5 и 6 больше, чем между другими размерами. Это может быть связано с топологическими особенностями шестиугольной решетки, где добавление дополнительного ряда узлов ведёт к более значительному увеличению количества возможных путей для анализа.
Вывод:
В процессе выполнения работы была написана программа для реализации графа типа правильной шестиугольной решетки и алгоритма поиска в глубину. Так же построен график среднего времени выполнения функции поиска в глубину от размерности графа шестиугольной решетки.
Приложение
Import networkx as nx
import numpy as np
Import matplotlib.Pyplot as plt
import time
#реализация графа
G = nx.Graph()
edges = [(1, 3), (1, 2), (3, 4),
(3, 6), (2, 4), (5,8),
(5, 6), (6, 7), (7, 3),(7,8)]
G.add_edges_from(edges)
pos = nx.spring_layout(G)
nx.draw(G, pos, with_labels=True, node_size=700, node_color="skyblue", font_size=10, font_weight="bold", edge_color='gray')
plt.show()
# Алгоритм
def dfs(graph, current_node, goal, path=None, shortest=None):
#Если текущий путь path не определен, он инициализируется списком, содержащим только текущую вершину.