Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

ЛР / ЛР1 / ПиАГМ ЛР1

.pdf
Скачиваний:
16
Добавлен:
25.06.2023
Размер:
839.52 Кб
Скачать

Список использованных источников

1)Методические указания по практической работе 1,

«Представление графов в ЭВМ» – СПб: ГУАП, 2022

31

ПРИЛОЖЕНИЕ A. Код программы

import igraph as ig import pandas as pd import sys

import time

#проверка ввода матрицы смежност def adjacency_matrix_check(adj_mat):

if len(adj_mat)**2 != sum([len(row) for row in adj_mat]): return 'Ошибка: !Кол-во строк и столбцов матрицы смежности

не равно!' return True

#построение СПИСОКА РЕБЕР по матрице смежности

def get_list_edges_by_adjacency_matrix(adj_mat, peaks = [], view = True):

test = adjacency_matrix_check(adj_mat) if test != True: return test

#проверка матрицы смежности if not peaks:

peaks = [str(i) for i in range(len(adj_mat))]

#создание списка ребер графа

list_edges

= []

 

for row in

range(len(adj_mat)):

 

for col in range(len(adj_mat[row])):

 

if

adj_mat[row][col] != 0:

 

 

if view: list_edges.append((((row ,peaks[row]),

(col ,peaks[col])), adj_mat[row][col]))

 

 

else: list_edges.append(str(peaks[row]) + ' -> '

+ str(peaks[col]) + ': ' + str(adj_mat[row][col]))

# другое

передставление

ребер

 

return list_edges

 

# представление графа в виде МАССИВА ЗАПИСЕЙ

 

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])

32

, *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

# Рисует график по МАТРИЦЕ СМЕЖНОСТИ

def view_graph(adj_mat, peaks, curved_value = False):

g

= ig.Graph(directed=True)

# создание ориентированного

графа

 

 

g.add_vertices(len(peaks))

# добавление вершин графа

#добавление идентификаторов и меток к вершинам for i in range(len(g.vs)):

g.vs[i]["id"]= i g.vs[i]["label"]= peaks[i]

#получаем список ребер и их веса

list_edges

=

get_list_edges_by_adjacency_matrix(adj_mat,

peaks)

 

 

 

# задаем ребра

 

 

g.add_edges([(edge[0][0][0],

edge[0][1][0]) for edge in

list_edges])

 

 

 

# задаем веса ребер

 

weights = [edge[1] for edge in list_edges]

g.es['label'] = weights

 

g.es['edge_width'] = weights

 

g.es["curved"] = curved_value

 

ig.plot(g, bbox = (350,350)

# построение графика

,margin = 30

,vertex_label_size = 10

,vertex_size = 55

,vertex_color = 'white') return 1

#Запрос номера вопроса

def get_question_number(): while 1:

question = input('''\nНайти:

1 - всех соседей заданной вершины графа;

2 - ответ, образует ли заданная последовательность вершин

33

цепь; 3 - номера вершин, сумма весов инцидентных ребер которых больше

заданной величины; 4 - количество ребер в графе; Q - Выход.

Введите номер: ''')

if question.isdigit(): question = int(question)

if question in range(1,5): return question

else: print('\n!Указан не существующй номер вопроса! Повторите ввод.')

elif question.upper() == 'Q': 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- Q для выхода' + '\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 == 'Q': 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- Q для выхода' + '\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

34

elif chain_peaks[0].upper() == 'Q': 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 == 'Q': return -1

else: print('\n!Введено неверное значение! Повторите

ввод.')

#возвращает соседей указанной вершины по заданной МАТРИЦЕ СМЕЖНОСТИ

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])

#проверка вершин на цепь в передставлении графа МАТРИЦА СМЕЖНОСТИ 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)):

35

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

#номера вершин, сумма весов инцидентных ребер которых больше заданной величины в передставлении графа МАТРИЦА СМЕЖНОСТИ

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]

#определение кол-ва ребер в передставлении графа МАТРИЦА СМЕЖНОСТИ

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()

#поиск в МАТРИЦЕ СМЕЖНОСТИ

def search_in_views_by_adj_mat(adj_mat, peaks):

while 1:

question = get_question_number() match question:

36

case 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))

case 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Заданная последовательность вершин

не образует цепь.')

 

 

 

 

case 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))

 

 

case 4: # 4 - количество ребер в графе;

 

 

print('\nВ

 

 

графе',

get_edge_count_by_adj_mat(adj_mat), 'ребер.')

 

 

case -1: return -1

return -2

# поиск в СПИСОК РЕБЕР

def search_in_views_by_list_edges(l_edg, peaks): while 1:

question = get_question_number()

match question:

case 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))

case 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Заданная

37

последовательность вершин образует цепь.')

else: print('\nЗаданная последовательность вершин не образует цепь.')

case 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))

case 4: # 4 - количество ребер в графе;

print('\nВ графе', get_edge_count_by_l_edg(l_edg), 'ребер.')

case -1: return -1

return -2

# поиск в МАССИВ ЗАПИСЕЙ

def search_in_views_by_graph_mat(g_info, peaks): while 1:

question = get_question_number()

match question:

case 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))

case 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Заданная последовательность вершин не образует цепь.')

case 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))

38

case 4: # 4 - количество ребер в графе;

print('\nВ графе', get_edge_count_by_graph_info(g_info), 'ребер.')

case -1: return -1

return -2

# поиск в разных представлениях графа

def search_in_views(adj_mat, peaks, l_edg = [], g_info = []): while 1:

num = input('''\n

Выберете представление для поиска: 1 - матрица смежности; 2 - список ребер; 3 - массив записей;

Q - Выход. Введите номер: ''')

match num.upper(): case '1':

print('', pd.DataFrame(adj_mat, columns=peaks, index=peaks), sep='\n')

search_in_views_by_adj_mat(adj_mat, peaks)

case '2':

if l_edg == [] or isinstance(l_edg[0], str): l_edg = get_list_edges_by_adjacency_matrix(adj_mat, peaks)

print('', *l_edg, sep='\n') search_in_views_by_list_edges(l_edg, peaks)

case '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)

case 'Q': break

case _:

print('\n!Команда не найдена! Повторите ввод.')

return -2

# узнать размер представлений графа

def view_objects_size(adja_mat, l_edg, g_info):

info = '\nРазмер представлений:\n\t- матрица смежности: ' + str(sys.getsizeof(adja_mat)) +\

'байт;\n\t- список ребер: ' +

str(sys.getsizeof(l_edg)) +\

'байт;\n\t- массив записей: ' +

str(sys.getsizeof(g_info)) + ' байт.' print(info)

39

return info

# тест времени работы функций пункта 4

def func_time_test(adj_mat, l_edg, g_info, peaks): view = ('в представлении графа матрица смежности'

,'в представлении графа список ребер'

,'в представлении графа массив записей') fun_name = ('поиска соседей'

,'проверки последовательности вершин на образование

цепи'

, 'поиска вершин, сумма инцедентных ребер которых больше заданного числа'

, 'определения кол-ва ребер')

fun = (

(get_neighbours_by_adj_mat, (adj_mat, peaks, 6)), (get_neighbours_by_l_edg, (6, l_edg)), (get_neighbours_by_graph_info, (6, g_info, peaks)),

(get_chain_answer_by_adj_mat, (adj_mat, (5, 6, 7, 0, 1))), (get_chain_answer_by_l_edg, (l_edg, (5, 6, 7, 0, 1))), (get_chain_answer_by_graph_info, (g_info, (5, 6, 7, 0,

1))),

(get_peaks_weight_more_value_by_adj_mat, (adj_mat, 16)), (get_peaks_weight_more_value_by_l_edg, (peaks, l_edg,

16)),

(get_peaks_weight_more_value_by_graph_info, (peaks, g_info, 16)),

(get_edge_count_by_adj_mat, (adj_mat,)), (get_edge_count_by_l_edg, (l_edg,)), (get_edge_count_by_graph_info, (g_info,)),

)

 

 

 

 

 

 

for f in range(len(fun)):

 

 

 

 

 

print('\nФункция', fun[f][0].__name__, fun_name[f // 3],

view[f % 3])

 

 

 

 

 

 

start_time = time.time()

 

 

 

 

 

for iter in range(10**6): fun[f][0](*fun[f][1])

 

 

 

end_time = (time.time() - start_time)

 

 

 

 

print('\tВремя

выполнения

функции

10^6

раз:'

,

round(end_time, 3), 'секунд')

 

 

 

 

 

print('\tСреднее время одного выполнения функции:' ,

round(end_time / 10**6, 8), 'секунд')

 

 

 

 

# Меню вызова подпрограмм

 

 

 

 

 

def menu():

 

 

 

 

 

#

0

1

 

2

 

3

4

5

6

7

 

 

 

peaks = ['Pavel I', 'Aleksandr I', 'Nikolai I', 'Aleksandr II', 'Aleksandr III', 'Nikolai II', 'Petr III', 'Ekaterina II']

40

Соседние файлы в папке ЛР1