Лабораторная работа № 1. Введение в NetworkX Работа выполняется в Anaconda, или Google Colab. Цель работы – освоить базовые приемы работы с графами, с использованием пакета NetworkX. Протокол должен содержать скриншот результата выполнения примера, код для выполнения общего и индивидуального заданий, включая полученные результаты, а также ответы на контрольные вопросы. NetworkX - это программный пакет на языке Python для создания, управления и изучения структуры, динамики и функций сложных сетей. Он используется для изучения больших сложных сетей, представленных в виде графов с вершинами (их ещё называют узлами, и далее будут использоваться оба эти понятия) и ребрами. Используя networkx, мы можем загружать и хранить сложные сети. Мы можем генерировать много типов случайных и классических сетей, анализировать сетевую структуру, строить сетевые модели, разрабатывать новые сетевые алгоритмы и рисовать сети. Основной целью пакета NetworkX является работа с графами, и их визуальное отображение вторично, но реализовано, так-как является важным инструментом анализа. Предоставлены удобные методы для отображения графов с использованием Python пакета Matplotlib. Пакеты NetworkX и Matplotlib установлены, как в Anaconda, так и Google Colab, поэтому пропустим процедуру их установки. Импорт NetworkX и Matplotlib Для начала работы с пакетами их нужно импортировать в рабочую среду: # импорт networkx import networkx as nx # импорт matplotlib.pyplot import matplotlib.pyplot as plt Создание графа Далее нужно создать пустой граф без узлов и ребер: G = nx.Graph() Создание вершин Вершины могут добавятся в граф по одной, например, так: G.add_node(1) или в виде их списка: G.add_nodes_from([2, 3, 4, 7, 9]) Теперь визуализируем их, используя функцию draw(), используя её без параметров: nx.draw(G) Получилось не очень наглядно. Добавив ключевые параметры, мы можем добавить нумерацию вершин (with_labels=True), цвет вершин (node_color='red'), их размер (node_size=1000) и т.д. nx.draw(G node_color='red', node_size=1000, with_labels=True) Теперь это выглядит так: Создание ребер Аналогично вершинам, ребра в граф можно добавлять по одному за раз, например, так: G.add_edge(1, 2) или добавив список ребер: G.add_edges_from([(3,1), (2,4), (4,1), (9,1), (1,7), (2,9)]) Вновь произведём визуализацию: nx.draw(G node_color='red', node_size=1000, with_labels=True) Теперь это выглядит так: Альтернативный вариант генерации графа может выглядеть так (т.к. Python регистрозависимый, то нижесозданный граф будет другим экземпляром класса Graph): g = nx.Graph() g.add_edges_from([(1,2), (3,1), (2,4), (4,1), (9,1), (1,7), (2,9)]) Удаление вершин и ребер Удаление вершин и ребер, аналогично созданию, можно производить как по одному, так и списком, используя следующие функции: Graph.remove_node(), Graph.remove_nodes_from(), Graph.remove_edge() and Graph.remove_edges_from() Удалим узел 3 из графа G и визуализируем результат G.remove_node(3) nx.draw(G, node_color='red', node_size=1000, with_labels=True) Удалим ребро (1,2) G.remove_edge(1, 2) nx.draw(G, node_color='red', node_size=1000, with_labels=True) Функции для нахождения основных характеристик графа # Найти количество вершин G.number_of_nodes() # Найти количество ребер G.number_of_edges() # Найти степень вершины # например, степень вершины 2 d = G.degree(2) # Найти все смежные вершины для вершины # например, смежные вершины для вершины 2 list(G.neighbors(2)) Подведем итог (пример) # Импортируем необходимые для работы пакеты # импорт networkx import networkx as nx # импорт matplotlib.pyplot import matplotlib.pyplot as plt # Создаем пустой неориентированный граф G = nx.Graph() # Добавляем вершины G.add_nodes_from([1, 2, 3, 4, 7, 9]) # Добавляем ребро # Примечание граф не является направленным # Следовательно, порядок узлов в ребре не имеет значения G.add_edge(2,1) # Добавляем остальные ребра G.add_edges_from([(3,1), (2,4), (4,1), (9,1), (1,7), (2,9)]) # Получаем все вершины графа в виде списка node_list = G.nodes() # И выводим их print("#1 список вершин исходного графа") print(node_list) # Получаем список всех ребер графа edge_list = G.edges() # И выводим их print("#2 список ребер исходного графа ") print(edge_list) # Удаляем вершину графа с номером 3 G.remove_node(3) node_list = G.nodes() print("#3 список вершин графа после удаления вершины 3") print(node_list) edge_list = G.edges() print("#4 список ребер графа после удаления вершины 3") print(edge_list) # Удаляем ребро графа (1,2) G.remove_edge(1,2) edge_list = G.edges() print("#5 список ребер графа после удаления ребра (1,2)") print(edge_list) # Найдем количество вершин этого графа n = G.number_of_nodes() print("#6 количество вершин графа после удаления ребра (1,2)") print(n) # Найдем количество ребер m = G.number_of_edges() print("#7 количество ребер графа после удаления ребра (1,2)") print(m) # Найдем степень вершины 2 # d будет хранить степень вершины 2 d = G.degree(2) print("#8 степень вершины 2") print(d) # Найдем все смежные вершины для вершины 2 neighbor_list = list(G.neighbors(2)) print("#9 смежные вершины для вершины 2") print(neighbor_list) # Визуализируем этот граф nx.draw(G, node_color='red', node_size=1000, with_labels=True) # Удаляем все узлы и ребра G.clear() !!! Скриншот результатов выполнения этого кода должен быть вставлен в отчет!!! Задание Создайте граф, показанный на рисунке. 1. Визуализируйте его без параметров. 2. Выведите количество его вершин и ребер. 3. Выведите степень вершины 1 и смежные с ней вершины. Сделайте скриншот полученных результатов и вставьте их в протокол. 4. Удалите вершину 1. 5. Подсчитайте количество вершин и ребер получившегося графа. 6. Визуализируйте получившийся граф с размером узлов 1000 и их нумерацией. 7. Выведите количество вершин и ребер получившегося графа. 8. Выведите степень вершины 2 и смежные с ней вершины. Сделайте скриншот полученных результатов и вставьте их в протокол. 9. Удалите ребро (2, 3). 10. Выведите количество вершин и ребер получившегося графа. 11. Выведите степень вершины 2 и смежные с ней вершины. 12. Визуализируйте получившийся граф с узлами красного цвета размером 1000 и их нумерацией. Сделайте скриншот полученных результатов и вставьте их в протокол. 13. Удалите ребро (2, 4). 14. Выведите количество вершин и ребер получившегося графа. 15. Выведите степень вершины 2 и смежные с ней вершины. 16. Выведите степень вершины 3 и смежные с ней вершины. 17. Визуализируйте получившийся граф с зелеными ребрами, узлами красного цвета размером 1500 и их нумерацией. Сделайте скриншот полученных результатов и вставьте их в протокол. Выполните индивидуальное задание из приложения к работе (номер задания совпадает с Вашим номером в списке группы). Сохраните файл с результатами под именем GraphTask1 Контрольные вопросы 1. Является ли исходный граф общего задания полным? Обоснуйте результат. 2. Будет ли этот граф полным после удаления вершины 1? 3. Как изменился бы ответ, если вместо неё была удалена любая из других вершин? 4. Является ли граф из Вашего индивидуального задания полным? Если нет, то какие ребра нужно добавить? Приложение 1. Создайте и визуализируйте граф из Вашего варианта. 2. Выведите для него количество вершин и ребер. 3. Запишите для Вашего графа подграфы, являющиеся полными графами на 3-х и 4-х вершинах. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33