
- •Напишем подпрограмму для построения списка ребер по заданной матрицы смежности.
- •Визуализируем заданный граф. Убедимся в том, что он совпадает с исходным графом.
- •Напишем подпрограмму, позволяющую представить граф в виде массива записей, основываясь на заданной матрице смежности. Каждой вершине графа соответствует запись.
- •Для каждого из представлений (матрица смежности, список ребер, массив записей) напишем подпрограммы поиска и вывода на экран:
- •Для каждого из представлений (матрица смежности, список ребер, массив записей) вывести на экран размер содержащего их объекта в байтах.
- •Приложение а. Код программы
Напишем подпрограмму, позволяющую представить граф в виде массива записей, основываясь на заданной матрице смежности. Каждой вершине графа соответствует запись.
Вывел полученный массив записей в понятном пользователю виде таблицы. Для создания таблицы записей использовали пакет pandas (в коде pd). Код подпрограммы в соответствии с листингом 5, список использованных переменных в соответствии с таблицей 4. Результат работы в соответствии с рисунком 4.
Таблица 4 - Список переменных подпрограммы из Листинга 5
-
Название
Значение
adj_mat
Список значений матрицы смежности
peaks
Список названий вершин
info
Временный массив с информацией о графе
row
Итератор по строкам матрицы смежности
children
Список кортежей с номерами вершин и весами ребер детей
конкретной вершины
parents
Список кортежей с номерами вершин и весами ребер
родителей конкретной вершины
neighbours
Список кортежей с номерами вершин и весами ребер соседней
(инцидентных вершин) конкретной вершины
col_name
Список названий столбцов вершины
g_info
Датафрейм хранящий массив записей о графе
Листинг 5 – Подпрограмма представления графа в виде массива записей
# представление графа в виде МАССИВА ЗАПИСЕЙ def get_array_of_graph_information(adj_mat, peaks): info = [] for row in range(len(adj_mat)): # находим по матрице смежности № и веса вершин детей, родителей и соседей children = [(i, adj_mat[row][i]) for i in range(len(adj_mat[row])) if adj_mat[row][i] != 0] parents = [(i, adj_mat[i][row]) for i in range(len(adj_mat)) if adj_mat[i][row] != 0] neighbours = tuple(set(children + parents)) # находим необходимые значения по полученным спискам вершин info.append([ row, peaks[row], *tuple(len(i) for i in [children, parents, neighbours]), *tuple(tuple([j[0] for j in i]) for i in [children, parents, neighbours]), *tuple(tuple([j[1] for j in i]) for i in [children, parents, neighbours]) ]) col_name = [ '№ вершины', 'Подпись вершины', 'Кол-во детей', 'Кол-во родителей', 'Кол-во соседей', '№ вершин детей', '№ вершин родителей', '№ вершин соседей', 'Веса исходящих', 'Веса входящих', 'Веса инцидентных ребер' ] g_info = pd.DataFrame(info, columns=col_name) return g_info
Рисунок 4 - Результат работы подпрограммы, представляющей граф в виде массива записей
Для каждого из представлений (матрица смежности, список ребер, массив записей) напишем подпрограммы поиска и вывода на экран:
всех соседей заданной вершины графа;
ответа, образует ли заданная последовательность вершин цепь;
номеров вершин, сумма весов инцидентных ребер которых больше заданной величины;
количества ребер в графе.
Для каждой подпрограммы организовал диалог с пользователем (запрос параметра – вывод результата). Данные для представления результатов выполнения данных подпрограмм подобрал самостоятельно.
Функция search_in_views для выбора представления графа для поиска.
Список использованных переменных в соответствии с таблицей 5, код в
соответствии с листингом 6. Результат работы функций представлен на
рисунке 5.
Таблица 5 - Список переменных подпрограммы из Листинга 6
-
Название
Значение
adj_mat
Список значений матрицы смежности
peaks
Список названий вершин
l_edg
Список ребер графа
g_info
Массив записей графа
num
Номер вида представления графа
Листинг 6 – Подпрограмма выбора представления графа
def search_in_views(adj_mat, peaks, l_edg=[], g_info=[]): while 1: num = input('''\nВыберете представление для поиска: 1 - матрица смежности; 2 - список ребер; 3 - массив записей; W - Выход. Введите номер: ''') if num.upper() == '1': print('\n', pd.DataFrame(adj_mat, columns=peaks, index=peaks), sep='\n') search_in_views_by_adj_mat(adj_mat, peaks) elif num.upper() == '2': if l_edg == [] or isinstance(l_edg[0], str): l_edg = get_list_edges_by_adjacency_matrix(adj_mat, peaks) print('\n', *l_edg, sep='\n') search_in_views_by_list_edges(l_edg, peaks) elif num.upper() == '3': if g_info == []: g_info = get_array_of_graph_information(adj_mat, peaks) print('\n', g_info) search_in_views_by_graph_mat(g_info, peaks) elif num.upper() == 'W': break else: print('\n!Команда не найдена! Повторите ввод.') return -2
Рисунок 5 - Результат работы функции search_in_views
Функции search_in_views_by_adj_mat, search_in_views_by_list_edges, search_in_views_by_graph_mat для выбора и вызова функций для определенных вопросов. Список использованных переменных в соответствии с таблицей 6, код в соответствии с листингом 7. Результат работы функций на рисунке 6.
Таблица 6 - Список переменных подпрограммы из Листинга 7
-
Название
Значение
adj_mat
Список значений матрицы смежности
peaks
Список названий вершин
l_edg
Список ребер графа
g_info
Массив записей графа
question
Номер вопроса
Листинг 7 – Подпрограмма вызова функций по заданным вопросам для
представлений графа (матрица смежности, список ребер, массив записей)
# Поиск в МАТРИЦЕ СМЕЖНОСТИ def search_in_views_by_adj_mat(adj_mat, peaks): while 1: question = get_question_number() if question == 1: # 1 - всех соседей заданной вершины графа top = get_peaks_for_search(peaks) if top == -1: continue print('\nСоседи вершины №', top, '(', peaks[top], '):', get_neighbours_by_adj_mat(adj_mat, peaks, top)) elif question == 2: # 2 - ответ, образует ли заданная последовательность вершин цепь peaks_num = get_peaks_for_chain(peaks) if peaks_num == -1: continue chain_answer = get_chain_answer_by_adj_mat(adj_mat, peaks_num) if chain_answer: print('\nЗаданная последовательность вершин образует цепь.') else: print('\nЗаданная последовательность вершин не образует цепь.') elif question == 3: # 3 - номера вершин, сумма весов инцидентных рёбер которых больше заданной величины value = get_value_for_search() if value == -1: continue print('\nНомера вершин, сумма весов инцидентных рёбер, которых больше', value, ':', *get_peaks_weight_more_value_by_adj_mat(adj_mat, value)) elif question == 4: # 4 - количество рёбер в графе print('\nВ графе', get_edge_count_by_adj_mat(adj_mat), 'ребер.') elif question == -1: return -1 return -2 # Поиск в СПИСКЕ РЕБЕР def search_in_views_by_list_edges(l_edg, peaks): while 1: question = get_question_number() if question == 1: # 1 - всех соседей заданной вершины графа top = get_peaks_for_search(peaks) if top == -1: continue print('\nСоседи вершины №', top, '(', peaks[top], '):', get_neighbours_by_l_edg(top, l_edg)) elif question == 2: # 2 - ответ, образует ли заданная последовательность вершин цепь peaks_num = get_peaks_for_chain(peaks) if peaks_num == -1: continue chain_answer = get_chain_answer_by_l_edg(l_edg, peaks_num) if chain_answer: print('\nЗаданная последовательность вершин образует цепь.') else: print('\nЗаданная последовательность вершин не образует цепь.') elif question == 3: # 3 - номера вершин, сумма весов инцидентных рёбер которых больше заданной величины value = get_value_for_search() if value == -1: continue print('\nНомера вершин, сумма весов инцидентных рёбер, которых больше', value, ':', *get_peaks_weight_more_value_by_l_edg(peaks, l_edg, value)) elif question == 4: # 4 - количество рёбер в графе print('\nВ графе', get_edge_count_by_l_edg(l_edg), 'ребер.') elif question == -1: return -1 return -2 # Поиск в МАССИВ ЗАПИСЕЙ def search_in_views_by_graph_mat(g_info, peaks): while 1: question = get_question_number() if question == 1: # 1 - всех соседей заданной вершины графа top = get_peaks_for_search(peaks) if top == -1: continue print('\nСоседи вершины №', top, '(', peaks[top], '):', get_neighbours_by_graph_info(top, g_info, peaks)) elif question == 2: # 2 - ответ, образует ли заданная последовательность вершин цепь peaks_num = get_peaks_for_chain(peaks) if peaks_num == -1: continue chain_answer = get_chain_answer_by_graph_info(g_info, peaks_num) if chain_answer: print('\nЗаданная последовательность вершин образует цепь.') else: print('\nЗаданная последовательность вершин не образует цепь.') elif question == 3: # 3 - номера вершин, сумма весов инцидентных рёбер которых больше заданной величины value = get_value_for_search() if value == -1: continue print('\nНомера вершин, сумма весов инцидентных рёбер, которых больше', value, ':', *get_peaks_weight_more_value_by_graph_info(peaks, g_info, value)) elif question == 4: # 4 - количество рёбер в графе print('\nВ графе', get_edge_count_by_graph_info(g_info), 'ребер.') elif question == -1: return -1 return -2
Рисунок 6 - Результат работы функции search_in_views_by_adj_mat
Функции get_question_number, get_peaks_for_search, get_peaks_for_chain, get_value_for_search для запроса параметров функций из листинга 6. Список использованных переменных в соответствии с таблицей 7, код в соответствии с листингом 8. Результат работы функций отображен на рисунках 7-10. Таблица 7 – Список переменных подпрограммы из Листинга 8
Таблица 7 - Список переменных подпрограммы из Листинга 8
-
Название
Значение
question
Номер вопроса
peaks_up
Список вершин графа в верхнем регистре
top
Номер вершины графа
chain_peaks
Список вершин
value
Целое число для сравнения с весами сумм инцидентных
вершин
Листинг 8 – Подпрограмма запроса параметров через диалог с пользователем
# Запрос номера вопроса def get_question_number(): while 1: question = input('''\nНайти: 1 - всех соседей заданной вершины графа; 2 - ответ, образует ли заданная последовательность вершин цепь; 3 - номера вершин, сумма весов инцидентных ребер которых больше заданной величины; 4 - количество ребер в графе; W - Выход. Введите номер: ''') if question.isdigit(): question = int(question) if question in range(1, 5): return question else: print('\n!Указан не существующий номер вопроса! Повторите ввод.') elif question.upper() == 'W': return -1 else: print('\n!Команда не найдена! Повторите ввод.') # Запрос и проверка корректности ввода вершины для поиска def get_peaks_for_search(peaks): peaks_up = [i.upper() for i in peaks] while 1: top = input('\nЗадайте вершину для поиска соседей:\n\t- из списка: (' + ', '.join(str(i) for i in peaks) + ')\n\t- по номеру: от 0 до ' + str(len(peaks) - 1) + '\n\t- W для выхода' + '\nВведите вершину: ').upper() if top in peaks_up: top = peaks_up.index(top) break if top.isdigit(): top = int(top) if top in range(len(peaks)): break else: print('\n!Вершины с указанным номером не существует! Повторите ввод.') elif top == 'W': return -1 else: print('\n!Вершины с указанным названием не существует! Повторите ввод.') return top # Запрос списка вершин графа def get_peaks_for_chain(peaks): while 1: chain_peaks = input('\nЗадайте список вершин (по номерам от 0 до ' + str(len(peaks) - 1) + ' через пробел) для проверки, образует ли заданная последовательность вершин цепь.' + '\n\t- W для выхода' + '\nВведите вершины: ').split() if all(map(lambda x: x.isdigit(), chain_peaks)): chain_peaks = list(map(int, chain_peaks)) if set(chain_peaks).issubset(range(len(peaks))): break elif chain_peaks[0].upper() == 'W': return -1 print('\n!Указаны не существующие номера вершин! Повторите ввод.') return chain_peaks # Запрос и проверка корректности ввода вершины для поиска def get_value_for_search(): while 1: value = input('\nЗадайте значение для сравнения: ').upper() if value.isdigit(): return int(value) elif value == 'W': return -1 else: print('\n!Введено неверное значение! Повторите ввод.')
Рисунок 7 - Результат работы функции get_question_number
Рисунок 8 - Результат работы функции get_peaks_for_search
Рисунок 9 - Результат работы функции get_peaks_for_chain
Рисунок 10 - Результат работы функции get_value_for_search
Функции get_neighbours_by_adj_mat, get_neighbours_by_l_edg, get_neighbours_by_graph_info для поиска соседей указанной вершины. Список использованных переменных в соответствии с таблицей 8, код в соответствии с листингом 9. Результат работы функций представлен на рисунке 11.
Таблица 8 - Список переменных подпрограммы из Листинга 9
-
Название
Значение
adj_mat
Список значений матрицы смежности
peaks
Список названий вершин
l_edg
Список ребер графа
g_info
Массив записей графа
top
Номер вершины графа
Листинг 9 – Подпрограмма поиск соседей указанной вершины в представлениях графа (матрица смежности, список ребер, массив записей)
# Возвращает соседей указанной вершины по заданной МАТРИЦЕ СМЕЖНОСТИ def get_neighbours_by_adj_mat(adj_mat, peaks, top): children = [(i, peaks[i]) for i in range(len(adj_mat)) if adj_mat[top][i] != 0] parents = [(i, peaks[i]) for i in range(len(adj_mat)) if adj_mat[i][top] != 0] return tuple(set(children + parents)) # Возвращает соседей указанной вершины по заданному СПИСКУ РЕБЕР def get_neighbours_by_l_edg(top, l_edg): return tuple(set(i[0][1] if i[0][0][0] == top else i[0][0] for i in l_edg if i[0][0][0] == top or i[0][1][0] == top)) # Возвращает соседей указанной вершины по заданному МАССИВУ ЗАПИСЕЙ def get_neighbours_by_graph_info(top, g_info, peaks): return tuple((i, peaks[i]) for i in g_info['№ вершин соседей'][top])
Рисунок 11 - Результат работы функции get_neighbours_by_adj_mat
Функции get_chain_answer_by_adj_mat, get_chain_answer_by_l_edg, get_chain_answer_by_graph_info для проверки последовательности вершин на цепь. Список использованных переменных в соответствии с таблицей 9, код в соответствии с листингом 10. Результат работы функций на рисунке 12.
Таблица 9 - Список переменных подпрограммы из Листинга 10
-
Название
Значение
adj_mat
Список значений матрицы смежности
peaks
Список названий вершин
l_edg
Список ребер графа
g_info
Массив записей графа
peaks_num
Номер вершин
Листинг 10 – Подпрограмма проверки последовательности вершин на цепь в представлениях графа (матрица смежности, список ребер, массив записей)
# Проверка вершин на цепь в представлении графа МАТРИЦА СМЕЖНОСТИ def get_chain_answer_by_adj_mat(adj, peaks_num): if len(peaks_num) == 1: return True for i in range(1, len(peaks_num)): if adj[peaks_num[i-1]][peaks_num[i]] == 0: return False return True # Проверка вершин на цепь в представлении графа СПИСОК РЕБЕР def get_chain_answer_by_l_edg(l_edg, peaks_num): if len(peaks_num) == 1: return True temp_l_edg = [[j[0][1][0] for j in l_edg if j[0][0][0] == i] for i in peaks_num] for i in range(1, len(peaks_num)): if peaks_num[i] not in temp_l_edg[i-1]: return False return True # Проверка вершин на цепь в МАССИВ ЗАПИСЕЙ def get_chain_answer_by_graph_info(g_info, peaks_num): if len(peaks_num) == 1: return True for i in range(1, len(peaks_num)): if peaks_num[i] not in g_info['№ вершин детей'][peaks_num[i-1]]: return False return True
Рисунок 12 - Результат работы функции get_chain_answer_by_adj_mat
Функции get_peaks_weight_more_value_by_adj_mat, get_peaks_weight_more_value_by_l_edg, get_peaks_weight_more_value_by_graph_info для поиска номеров вершин, сумма весов инцидентных ребер которых больше заданной величины. Список использованных переменных в соответствии с таблицей 10, код в соответствии с листингом 11. Результат работы функций представлен на рисунке 13.
Таблица 10 - Список переменных подпрограммы из Листинга 11
-
Название
Значение
adj_mat
Список значений матрицы смежности
peaks
Список названий вершин
l_edg
Список ребер графа
g_info
Массив записей графа
value
Число для сравнения
Листинг 11 – Подпрограмма поиска номеров вершин, сумма весов инцидентных ребер которых больше заданной величины в представлениях графа (матрица смежности, список ребер, массив записей)
# Номера вершин, сумма весов инцидентных ребер которых больше заданной величины в представлении графа МАТРИЦА СМЕЖНОСТИ def get_peaks_weight_more_value_by_adj_mat(adj_mat, value): return [i for i in range(len(adj_mat)) if sum([col for col in adj_mat[i]] + [row[i] for row in adj_mat]) > value] # Номера вершин, сумма весов инцидентных ребер которых больше заданной величины в представлении графа СПИСКОТ РЕБЕР def get_peaks_weight_more_value_by_l_edg(peaks, l_edg, value): return [i for i in range(len(peaks)) if sum([j[1] for j in l_edg if j[0][0][0] == i or j[0][1][0] == i]) > value] # номера вершин, сумма весов инцидентных ребер которых больше заданной величины в представлении графа МАССИВ ЗАПИСЕЙ def get_peaks_weight_more_value_by_graph_info(peaks, g_info, value): return [i for i in range(len(peaks)) if sum(g_info['Веса инцидентных ребер'][i]) > value]
Рисунок 13 - Результат работы функции get_peaks_weight_more_value_by_adj_mat
Функции get_edge_count_by_adj_mat, get_edge_count_by_l_edg, get_edge_count_by_graph_info для поиска количества ребер графа. Список использованных переменных в соответствии с таблицей 11, код в соответствии с листингом 12. Результат работы функций на рисунке 14.
Таблица 11 - Список переменных подпрограммы из Листинга 12
-
Название
Значение
adj_mat
Список значений матрицы смежности
l_edg
Список ребер графа
g_info
Массив записей графа
Листинг 12 – Подпрограмма определения кол-ва ребер в представлениях графа (матрица смежности, список ребер, массив записей)
# Определение количества ребер в представлении графа МАТРИЦА СМЕЖНОСТИ def get_edge_count_by_adj_mat(adj_mat): return sum([sum([1 for j in i if j != 0]) for i in adj_mat]) # Определение количества ребер в представлении графа СПИСКОТ РЕБЕР def get_edge_count_by_l_edg(l_edg): return len(l_edg) # Определение количества ребер в представлении графа МАССИВ ЗАПИСЕЙ def get_edge_count_by_graph_info(g_info): return g_info['Кол-во детей'].sum()
Рисунок 14 - Результат работы функции get_edge_count_by_adj_mat
Приведены результаты работы функций для поиска в матрице смежности, функции для представлений графа список ребер и массив записей дают такие же результаты для таких же входных параметров.