Вы находитесь на странице: 1из 12

МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РОССИЙСКОЙ ФЕДЕРАЦИИ

Федеральное государственное автономное образовательное учреждение


высшего образования
«Национальный исследовательский
Нижегородский государственный университет им. Н.И. Лобачевского»
(ННГУ)

Институт информационных технологий, математики и механики

Кафедра алгебры, геометрии и дискретной математики


Направление подготовки: «Фундаментальная информатика и
информационные технологии»

ОТЧЕТ
по учебной практике

на тему:
«Число Хадвигера»

Выполнила:
студентка группы 381706-3
Кашина Анастасия Александровна
_______________________Подпись

Научный руководитель:
Доцент кафедры АГДМ
Сорочан Сергей Владимирович
_______________________Подпись

Нижний Новгород
2019
Содержание

1. СОДЕРЖАНИЕ............................................................................................................................................2
2. ПОСТАНОВКА ЗАДАЧИ..............................................................................................................................3
3. МЕТОД РЕШЕНИЯ.....................................................................................................................................5
4. СХЕМА РАСПАРАЛЛЕЛИВАНИЯ................................................................................................................6
5. ОПИСАНИЕ ПРОГРАММНОЙ РЕАЛИЗАЦИИ............................................................................................7
1.1. РУКОВОДСТВО ПОЛЬЗОВАТЕЛЯ.......................................................................................................7
1.2. РУКОВОДСТВО ПРОГРАММИСТА.....................................................................................................8
6. ПОДТВЕРЖДЕНИЕ КОРРЕКТНОСТИ..........................................................................................................9
7. РЕЗУЛЬТАТЫ ЭКСПЕРИМЕНТОВ.............................................................................................................10
8. ЗАКЛЮЧЕНИЕ..........................................................................................................................................12
9. ПРИЛОЖЕНИЕ.........................................................................................................................................13

Шшш

2
Постановка задачи

Данная работа основана на операции слияния вершин. Пусть u и v — две


вершины графаG, H=G−u−v. К графу H присоединим новую вершину v ', соединив
её ребром с каждой из вершин, входящих в объединение окружений вершин u и v в
графе G. Говорят, что построенный граф получается из графа G
отождествлением(слиянием) вершин u и v.

Стягивание ребра uv означает отождествление смежных вершин u и v. Граф G


называется стягиваемым к графу H, если H получается из G в результате некоторой
последовательности стягивания ребер. Очевидно, что любой непустой связный граф,
отличный от K 1, стягиваем к K 2. Но уже не любой связный граф стягивается к графу
K 3. Естественно возникает параметр η(G) — максимум порядков полных графов, к
которым стягивается граф G. Параметр η(G) называется числом Хадвигера графа G .
Эквивалентно, число Хадвигера h(G) — это наибольшее число k, для которого
полный граф K k  является минором графа G, меньший граф, полученный из G 
стягиванием рёбер и удалением вершин и рёбер.

Задача данной работы – реализовать алгоритм, вычисляющий число Хадвигера


за приемлемое время для графов разных размеров.

3
Метод решения

Пусть граф G задан матрицей смежности. Матрица смежности задается


случайным образом. Также есть возможность задать матрицу смежности с любой
вероятностью появления ребра, а также, с любым количеством ребер.

Шаг алгоритма. В цикле по всем столбцам (строкам) матрицы смежности


выполняется попарная операция слияния вершин. Если в строке (столбце) оба
элемента на соответствующих позициях равны нулю, то на этой позиции в
результирующем столбце (строке) тоже будет 0, иначе — единица. Результат слияния
записывается в столбец (строку) с наименьшим индексом, после чего все столбцы
(строки), следующие после столбца (строки) с наибольшим индексом из двух,
сдвигаются на одну позицию влево (вверх).

После каждого слияния выполняется проверка на полноту: если все элементы


матрица смежности, за исключением диагонали, равны единице, то граф является
полным. Граф называется полным, если любые две его вершины смежны. Если
полученный граф — полный, то число Хадвигера найдено и равно количеству
вершин, оставшихся в графе. Если не полный — шаг алгоритма повторяется.

4
Примеры

Реализуем несколько способов выбора двух вершин для слияния.

1. Вершины выбираются по порядку: первая вершина всегда с индексом 1, вторая


— следующая за ней вершина. Так как матрица смежности задается случайным
образом, то и последовательность слияния вершин оказывается случайной.

2. Вершины с наибольшей и наименьшей степенью. Степени вершин обновляются


после каждого шага алгоритма.

3. Обе вершины — вершины с минимальными степенями. Степени вершин


обновляются после каждого шага алгоритма.

5
Результаты экспериментов

Персональный компьютер:

CPU: AMD Ryzen 7 2700X 4.3GHz;

RAM: 16 Gb;

OS: Windows 10 x64.

1. Рассмотрим время работы алгоритма в зависимости от числа вершин.

1600

1400

1200

1000

800
Время

600

400

200

0
15 30 45 60 75 90 120 140 160 175 190 300 450 600 750 900 100 400 700 000 300 600 500
1 1 1 2 2 2 3

Количество вершин

2. Рассмотрим значение числа Хадвигера в зависимости от числа вершин.

6
30

25

Число Хадвигера 20

15

10

0
15 30 45 60 75 90 110 135 155 170 185 250 400 550 700 850 000 300 600 900 200 500 000 500
1 1 1 1 2 2 3 4

Количество вершин

7
Заключение

В результате работы была написана программа, позволяющая находить число


Хадвигера для графа с любым числом вершин. После серии экспериментов было
установлено, что время работы алгоритма в зависимости от числа вершин возрастает
по экспоненте. Число Хадвигера не зависит от числа вершин в графе. Таким образом,
можно сделать вывод, что при больших входных данных программа вычисляет
результат за неприемлемо большое время.

8
Литература

1. Лекции по теории графов / В. А. Емеличев [и др.]. — М.: Наука. Гл. ред. Физ.-
мат. Лит., 1990 — 384 с.

2. Число Хадвигера. – Режим доступа: https://ru.wikipedia.org/wiki/


%D0%A7%D0%B8%D1%81%D0%BB%D0%BE_
%D0%A5%D0%B0%D0%B4%D0%B2%D0%B8%D0%B3%D0%B5%D1%80%D0
%B0. – Загл. с экрана.

9
Приложение

1. void first_to_all(vector<vector<int>>vec)
{ unsigned int start_time = clock();
unsigned int counting = 0;
bool find = false;
int n = vec.size();
unsigned int versh1 = 0, versh2 = 1;
while (!find) {
for (int i = 1, size = n; i < size; ++i)//i с 1 т.к. не считаем диагональ
{ if (i != versh1)//чтобы вершина не складывалась с собой
if (vec[i][versh1] + vec[i][versh2] > 0)
vec[i][versh1] = 1;
} for (int i = 1, size = n; i < size; ++i)
vec[versh1][i] = vec[i][versh1];
for (int i = versh2, size = n - 1; i < size; ++i)//удаляю следующую строку
for (int j = 0; j < n; ++j)
vec[i][j] = vec[i + 1][j];//присваивает следующую
for (int j = versh2; j < n - 1; ++j)//удаляю следующий столбец
for (int i = 0, size = n; i < size; ++i)
vec[i][j] = vec[i][j + 1];
--n;//уменьшаем размерность
find = checking(vec, n);
counting++;
}
}

2. void min_max_degree(vector<vector<int>>vec)
{ unsigned int counting = 0;
vector<unsigned int> array;//будем хранить вектор степеней
array.resize(vec.size());//задает размер, равный количеству вершин
counting_degree(vec, array);
bool find = false;
int n = vec.size();
unsigned int versh1, versh2;
while (!find)
{ int min_index = 0, max_index = 1;
int min = array[0], max = array[1];
if (max < min)
{ min = max;
max = array[0];
min_index = 1, max_index = 0;
}
else if (min > max)
{ max = min;
min = array[1];
min_index = 1, max_index = 0;
}
for (int i = 2; i < n; i++)//т.к. в строке выше присвоили 0 и 1
if (array[i] <= min)
{ min = array[i];
min_index = i;
}else if (array[i] >= max)
{ max = array[i];
max_index = i;
} versh1 = min_index; versh2 = max_index;
for (int i = 1, size = n; i < size; ++i)//i с 1 т.к. не считаем диагональ
{ if (i != versh1)//чтобы вершина не складывалась с собой
if (vec[i][versh1] + vec[i][versh2] > 0)
vec[i][versh1] = 1;
}
10
for (int i = 1, size = n; i < size; ++i)
vec[versh1][i] = vec[i][versh1];

for (int i = versh2, size = n - 1; i < size; ++i)//удаляю строку


for (int j = 0; j < n; ++j)
vec[i][j] = vec[i + 1][j];//присваивает следующую

for (int j = versh2; j < n - 1; ++j)//удаляю столбец


for (int i = 0, size = n; i < size; ++i)
vec[i][j] = vec[i][j + 1];
--n;//уменьшаем размерность
find = checking(vec, n);
int tmp = 0;
for (int j = 0; j < n; ++j)
if (vec[versh1][j] == 1)
tmp++;//количество единиц в вершине
array[versh1] = tmp;
for (int i = versh2; i < n - 1; i++)
array[i] = array[i + 1];
counting++;
}
}

3. void min_degree(vector<vector<int>> vec)


{ unsigned int counting = 0;
vector<unsigned int> array;//будем хранить вектор степеней
array.resize(vec.size());//задает размер, равный количеству вершин
counting_degree(vec, array);
bool find = false;
int n = vec.size();
unsigned int versh1, versh2;
while (!find)
{ int min1 = array[0], min2 = array[1];
int min_index1 = 0, min_index2 = 1;
for (int i = 2; i < n; i++)//т.к. в строке выше присвоили 0 и 1
if (array[i] <= min1)
{ if (min1 <= min2)
{ min2 = array[i];
min_index2 = i;
}
else
{ min1 = array[i];
min_index1 = i;
}
} else if (array[i] <= min2)
{ min2 = array[i];
min_index2 = i;
}
if (min_index1 < min_index2)
{versh1 = min_index1; versh2 = min_index2;}
else
{versh2 = min_index1; versh1 = min_index2;}
for (int i = 1, size = n; i < size; ++i)//i с 1 т.к. не считаем диагональ
{ if (i != versh1)//чтобы вершина не складывалась с собой
if (vec[i][versh1] + vec[i][versh2] > 0)
vec[i][versh1] = 1;
} for (int i = 1, size = n; i < size; ++i)
vec[versh1][i] = vec[i][versh1];
for (int i = versh2, size = n - 1; i < size; ++i)//удаляю строку
for (int j = 0; j < n; ++j)
vec[i][j] = vec[i + 1][j];//присваивает следующую
11
for (int j = versh2; j < n - 1; ++j)//удаляю столбец
for (int i = 0, size = n; i < size; ++i)
vec[i][j] = vec[i][j + 1];
--n;//уменьшаем размерность
find = checking(vec, n);
int tmp = 0;
for (int j = 0; j < n; ++j)
if (vec[versh1][j] == 1)
tmp++;//количество единиц в вершине
array[versh1] = tmp;
for (int i = versh2; i < n - 1; i++)
array[i] = array[i + 1];
counting++;
}

4. bool checking(vector<vector<int>>& vec, int& n)//проверяет на планарность


{ for (int i = 0, size = n; i < size; ++i)
{ for (int j = 0; j < n; ++j)
if (i != j)
if (vec[i][j] == 0)
return false;
}
return true;
}

5. void counting_degree(vector<vector<int>>& M, vector<unsigned int >& vec)//считаем


построчно //степень вершины
{ for (int i = 0; i < M.size(); i++)
for (int j = 0; j < M.size(); j++)
if (M[i][j] == 1)
vec[i]++;
}

12