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

advertisement
МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РОССИЙСКОЙ ФЕДЕРАЦИИ
Федеральное государственное образовательное бюджетное учреждение высшего
профессионального образования
“КУБАНСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ”
(ФГБОУ ВПО “КубГУ”)
Кафедра вычислительных технологий
“СОЗДАНИЕ БАЗЫ ДАННЫХ МИНИ-КОДОВ ГРАФОВ”
Едигарев А.В.
Краснодар 2014
1
СОДЕРЖАНИЕ
ВВЕДЕНИЕ.................................................................................................................3
1. Проблема изоморфизма графов в теории алгоритмов........................................4
1.1. История и классификация проблемы...........................................................................4
1.2.
Некоторые
инварианты
графов
и
их
свойства.............................................................5
1.3. Понятие мини-кода графа, его плюсы и минусы........................................................6
2.
Разработка
ПО
для
структуризации
графов
при
помощи
мини-
кода................8
2.1. Анализ задачи.................................................................................................................8
2.2. Перечень использованных инструментов и причины их выбора..............................8
2.3.
Модель.............................................................................................................................9
2.4. Анализ алгоритма и полученных данных..................................................................15
ЗАКЛЮЧЕНИЕ........................................................................................................21
СПИСОК
ИСПОЛЬЗОВАННЫХ
ИСТОЧНИКОВ................................................22
ПРИЛОЖЕНИЕ А....................................................................................................23
ПРИЛОЖЕНИЕ Б.....................................................................................................28
ПРИЛОЖЕНИЕ В....................................................................................................31
ПРИЛОЖЕНИЕ Г.....................................................................................................33
2
ВВЕДЕНИЕ
В настоящее время, пожалуй, не существует такой области человеческой
жизнедеятельности, которая не была бы связана с графами. Они находят себе
применение как в химии (выступая в качестве представления структуры
химических соединений), так и при проектировании сетей, в теории автоматов
и т. д.
3
К сожалению, в теории графов имеется еще большое количество
нерешенных вопросов. Один из них — проблема выяснения изоморфизма
графов за полиномиальное время. Для многих классов графов (деревьев,
планарных графов, графов с ограниченным количеством степеней вершин и
т. д.) существуют алгоритмы, решающие эту задачу (один из
них,
предполагающий похожие ограничения на граф, рассматривается в [2]). Для
общего же случая такой алгоритм еще не найден, но не доказано, что он не
существует (см., например, [1], где приводятся аргументы против NP-полноты
данной задачи).
Другой подход к решению данной задачи — поиск инвариантов.
Инвариант графа - некоторое обычно числовое значение или упорядоченный
набор значений (хэш-функция), характеризующее структуру графа G = <E, V>.
Полные инварианты графа не зависят от способа обозначения вершин или
графического изображения графа. В настоящей работе рассмотрено получение
одного из них — т. н. мини-кода — и создание на его основе базы данных
неизоморфных графов.
1.
Проблема изоморфизма графов в теории алгоритмов
1.1.История и классификация проблемы
4
Задача изоморфизма графов служила предметом для исследования с
1970-х гг. Несмотря на огромное количество работ на эту тему, за все это
время не удалось установить, является ли эта задача NP-полной или нет.
Заслуживает внимания и тот факт, что алгоритм полиномиальной сложности
для ее решения в общем случае не найден до сих пор, хотя путем перебора
ответ находится поразительно просто (подробный обзор этой проблемы можно
найти в [3]). В некоторых случаях время работы этого алгоритма может быть
сокращено (например, [2] ссылается на результат 𝑂(𝑛𝑙𝑜𝑔𝑛 ) ), но остается
экспоненциальным.
С другой стороны, за годы существования этого вопроса было
разработано большое количество специализированных алгоритмов для
использования в практических целях. Один из ярких примеров — алгоритм
проверки изоморфизма графов с ограниченным (порядка 5-10) максимальным
количеством степеней вершин[4]. Кроме того, изоморфизм планарных графов
можно проверить за логарифмическое время[5]. На его основе появилось
множество достаточно эффективных программ, решающих вышеупомянутую
задачу для «почти всех» алгоритмов, тем самым делая ее полиномиальной «в
среднем случае». Кроме приведенных выше эти программы используют и
недетерминированные — эвристические — процессы для сужения области
перебора (как, например, [1]). Наиболее известная из таких программ — nauty.
С другой стороны, для них также можно найти классы «трудных» графов,
время работы с которыми не сводится к полиномиальному, хотя они и в этом
случае обычно работают достаточно быстро[3].
1.2. Некоторые инварианты и их свойства
5
Другой подход к решению проблемы изоморфизма (как в теории, так и
на практике) — поиск инвариантов графа, которые не меняют свое значение
при замене вершин местами. Примеры таких инвариантов:

Полином Татта[6]. Он может быть вычислен рекурсивно по следующим
формулам:
1)
Если в графе G нет ребер, то T(G, x, y) = 1.
2)
𝑇(𝐺, 𝑥, 𝑦) = 𝑇(𝐺1𝑒 , 𝑥, 𝑦) + 𝑇(𝐺2𝑒 , 𝑥, 𝑦),
где
𝐺1𝑒
обозначает
граф,
полученный после удаления ребра e из G, а 𝐺2𝑒 обозначает граф,
полученный после удаления ребра e из G и соединения в одну ранее
связанных им вершин.
3)
Если e — мост, то 𝑇(𝐺, 𝑥, 𝑦) = 𝑥𝑇(𝐺1𝑒 , 𝑥, 𝑦).
4)
Если e — петля, то 𝑇(𝐺, 𝑥, 𝑦) = 𝑦𝑇(𝐺2𝑒 , 𝑥, 𝑦).
В [6] показано, что время вычисления этого многочлена не является
полиномиальным.

Спектр графа (набор собственных чисел его матрицы смежности);

Набор степеней вершин графа, упорядоченный по неубыванию.

Инвариант Колен де Вердьера[7] μ(G) для неориентированных графов,
основанный на свойствах матриц, связанных с графом. Интерес в нем
обусловливается не только свойством его инвариантности, но и
наличием у него других свойств, интересных для теории графов,
например:
1) μ(G) = 0, если G не имеет ребер;
6
2) μ(G) = 3, если G — планарный граф и т. д.

Хроматическое
число
χ(G).
Определяет
количество
«цветов»,
необходимых для того, чтобы «покрасить» граф так, чтобы вершины с
разными
«цветами»
не
соединялись
ребром.
Хорошо
известен
результат[8] о том, что максимальное хроматическое число планарного
графа — 4.
1.3. Понятие мини-кода графа, его плюсы и минусы.
Один из самых простых инвариантов с точки зрения представления —
мини-код графа 𝜇𝑚𝑖𝑛 . Он представляет собой минимальную из поразрядных
записей матриц смежности графов, изоморфных данному, записанную в
десятичной
системе
счисления.
В
случае,
если
граф
не
является
ориентированным, логично будет хранить не всю матрицу смежности, а только
половину (исключая, к тому же, главную диагональ). Таким образом, для
представления графа из N вершин в этом случае требуется
(𝑁−1)∗(𝑁−2)
2
двоичных
разрядов. Несмотря на эту квадратичную зависимость размеров памяти от
количества вершин, для малых графов такой способ вполне приемлем. В
ситуации, когда необходим перебор всех возможных графов с определенным
количеством вершин, мини-код может быть использован в качестве простого
счетчика цикла. К тому же очевидно, что преобразование (мини-)кода графа в
матрицу смежности и обратно можно выполнить за квадратичное время одним
проходом. Учитывая все эти факторы, данное представление является
идеальным для баз данных при условии, что граф содержит небольшое
количество вершин.
К сожалению, у этого способа представления имеются свои недостатки.
Как известно, матрица смежности теряет свою эффективность в случае т. н.
7
разреженных графов, когда число вершин намного превышает количество
ребер. Мини-код графа всего лишь нивелирует эту потерю, но не устраняет ее
полностью, представляя ребра в графе аналогичным способом. Другим
аспектом является то, что в таком виде на каждое ребро отводится 1 бит, в
котором можно хранить только 2 состояния: «вершины смежны» и «вершины
не
смежны»,
что
исключает
возможность
хранения
дополнительной
информации, касающейся ребер. Преобразование к более удобной записи —
матрице смежности — требует расходов как по времени, так и по памяти, а
работа непосредственно с целым числом, каким является мини-код, на уровне
побитовых операций нетривиальна и чревата ошибками. Добавим сюда тот
факт, что сколько-нибудь большие графы (содержащие 12 вершин и больше)
требуют реализации длинной арифметики, т. к. их мини-код не помещается в
64 бита. И, наконец, то полезное свойство, что мини-код является полным
инвариантом, нейтрализуется тем фактом, что его поиск сводится к перебору n!
перестановок, сохраняющих изоморфизм графа. Учитывая, что с увеличением
числа вершин это количество растет быстрее, чем полиномиально (известная
𝑛 𝑛
формула Стирлинга приближает его как 𝑛! ≈ 2𝜋𝑛 ∗ (𝑒 ) ), нетрудно видеть, что
при обработке графов с количеством вершин уже больше 10 расход памяти
становится угрожающе высоким.
В целом, можно охарактеризовать мини-код как упакованную запись
матрицы смежности, которая превосходно подходит для матриц размера не
выше 12 и является хорошим кандидатом на их представление в базе данных,
но является совершенно не оптимальной для графов с большим количеством
вершин.
8
Разработка ПО для структуризации графов при помощи мини-кода
2.
2.1. Анализ задачи
Необходимо разработать программный продукт, позволяющий:

Строить матрицы смежности неориентированных графов с
количеством вершин не больше 10 и находить их мини-коды.

Находить набор степеней вершин графа, а также обеспечить
возможность получения его графического представления.

Занести полученную информацию в базу данных.
Оценить время выполнения разработанного продукта и объем
перерабатываемой им информации.
2.2. Перечень использованных инструментов и причины их выбора
Для хранения данных использована БД MySQL версии 5.6. Причины ее
выбора:

MySQL – очень быстрая, надежная, стабильная и простая в
использовании БД. Она идеально подходит для небольших систем (таких,
9
как рассматриваемая мной далее база данных). Кроме того, во время
работы она не занимает много оперативной памяти или места на
жестком диске;

MySQL поставляется с удобным ПО, к тому же не тратящим много
времени на установку (например, утилита mysql.exe предоставляет
консольный интерфейс для выполнения как одиночных запросов, так и
целых сценариев на языке SQL);

Все программные компоненты MySQL распространяются по
лицензии GPL – это означает, что не только они, но и их исходный код
может быть найден в свободном доступе.
Для реализации кода использован язык С# (версии 4.0) по следующим
причинам:

С# является настолько же мощным и выразительным, как и любой
наследник языка С, но не является ни чрезмерно перегруженным, что
значительно понижает порог вхождения, ни искусственно ограниченным
в своих возможностях, что позволяет создавать изящные и компактные
решения.

C#
поддерживает
такую
неизмеримо
богатую
библиотеку,
как .NET Framework. В нее входят классы, необходимые «на все случаи
жизни», а их количество позволяет выбрать нужный программисту,
поддерживаемому обширной документацией. Не последнее место в этой
библиотеке занимают средства написания GUI, легкости и возможностям
которых позавидуют многие другие программисты.
И наконец, для связи двух вышеперечисленных программных продуктов
использована библиотека MySQL Connector for .NET (она входит в
стандартный комплект MySQL Community Server, распространяемый на сайте
10
http://dev.mysql.com/downloads/mysql/) Она предоставляет интерфейс для
работы
с
БД
MySQL
при
помощи
языков
программирования,
использующих .NET Framework.
2.3.
Модель
Получение мини-кода и его хранение в памяти
Мини-код графа определяется как минимальная двоичная запись матриц
смежности,
изоморфных
(неориентированного)
(𝑁−1)∗(𝑁−2)
2
графа
данному
из
N
графу.
вершин
Для
эта
представления
запись
требует
двоичных разрядов. Нетрудно видеть, что для графа из 10 вершин
необходимо
9∗8
2
= 36двоичных разрядов. Это определяет выбор типа данных —
целочисленный беззнаковый (очевидно, что для мини-кодов знак не имеет
смысла) 64-битный тип данных ulong.
Матрица смежности графа представлена как List<string> - список строк,
на каждой позиции которого стоит либо '1', либо '0'. Она не учитывает
ориентированность, т. е. каждая связь записывается дважды. Преобразование
матрицы смежности в мини-код (далее упаковка графа) происходит за время
𝑂(𝑛2 ) путем добавления каждого значения матрицы смежности сверху от
главной диагонали в код и сдвигом этого кода на 1 влево (см. функцию
make_code() в приложении А), а обратное преобразование (распаковка) —
путем последовательной записи всех битов мини-кода сверху и снизу от
главной диагонали (см. функцию natural_code() в приложении А).
Именно такое распакованное представление и используется для
перестановок вершин графа. Оно состоит в простой замене всех элементов
матрицы с индексами i и j на элементы с индексами 𝑝𝑒𝑟𝑚𝑖 и 𝑝𝑒𝑟𝑚𝑗 при условии,
что perm — последовательность, содержащая целые числа от 0 до количества
вершин графа без единицы в произвольном порядке. Легко видеть, что такая
11
замена не нарушает ни симметрии графа, ни изолированности главной
диагонали; кроме того, она из матрицы смежности графа получает матрицу
смежности изоморфного ему графа.
Для получения перестановок используется класс Permutator<T> - по сути,
обертка вокруг своего конструктора, возвращающего n! перестановок
вышеупомянутой последовательности в поле класса unique_codes. Он работает
посредством поочередного обмена первого элемента последовательности с
очередным
и
рекурсивного
рассмотрения
оставшейся
части
последовательности (приложение Б).
Нахождение кодов неизоморфных графов
Самая ресурсоемкая часть приложения — нахождение мини-кодов
неизоморфных графов для определенного количества вершин (приложение В).
Структура данных, используемая для работы, такова: Dictionary<ulong,
List<ulong>>, т. е. мини-коду соответствует список кодов неизоморфных
графов. Работа осуществляется следующим образом:
1)
Определяется количество кодов, которые необходимо перебрать (по
формуле 2𝑟 , 𝑟 =
2)
Код
(𝑁−1)(𝑁−2)
графа
2
), где N — количество вершин графа.
ищется
среди
уже
найденных
изоморфных
графов
посредством двоичного поиска. Если совпадение найдено, программа
увеличивает код на единицу и начинает заново искать его.
3)
Если же совпадения нет, для каждого кода генерируется N! перестановок
в виде целочисленных кодов, которые сортируются по возрастанию и
добавляются к уже имеющимся.
Для получения всех необходимых нам кодов вышеприведенный
алгоритм запускается с N от 2 до 10.
Визуальное представление графов. Программа dot
12
Для визуализации графа можно воспользоваться программой dot,
доступной
в
пакете
GraphViz
(последняя
версия
2.38)
на
сайте
http://graphviz.org. Для рисования неориентированных графов подойдет
описание, пример которого приведен ниже (для полного графа с 4 вершинами):
graph gr {
a -- b -- c -- d;
a -- c;
b -- d;
};
Здесь вместо gr, а также a, b, c и d можно задать любые последовательности
букв и цифр. Для того, чтобы создать представление, которое будет
действительно для команды dot, для каждой связи между вершинами i и j
создается запись типа i -- j; В качестве имени графа выступает его мини-код.
Пример представления полного графа с 5 вершинами представлен ниже
(рисунок 1).
13
Рисунок 1.
Организация БД
Используемая база данных graphs содержит следующие поля:

id — идентификатор записи, ее первичный ключ;

rank — количество вершин графа;

degrees — набор степеней вершин графа (он хранится в виде символьной
строки — последовательности цифр, но это временное решение и
подходит только для таких малых графов, как рассматриваемые нами);

code — мини-код графа (код создания графа приведен в приложении В):

image — рассмотренное ранее текстовое представление графа для
последующей обработки с помощью dot
Работа в БД
Работа с базой данных graphs осуществляется достаточно просто с
использованием интерфейса MySQL Connector for .NET. Вначале создается
соединение при помощи класса MySqlConnection (инкапсулированного в класс
14
db_connection), используя данные о таблице и учетных данных пользователя.
Затем полученные выше коды графов считываются, для них определяется
набор вершин и текстовое представление, и эти коды заносятся в БД.
Занесение производится при помощи запроса INSERT (приложение Г). Сам же
запрос
выполняется
при
помощи
метода
ExecuteNonQuery()
класса
MySqlCommand. В конце (в деструкторе класса db_connection) соединение с
БД обязательно закрывается для предотвращения потери данных. После
окончания работы БД содержит столько же записей, сколько неизоморфных
графов в таблице.
Графический интерфейс пользователя
GUI приложения состоит из одной формы (рисунок 2).
Рисунок 2
По кнопке «Начать» происходит процесс поиска изоморфных графов и
заполнения данными о них БД. Кроме того, в текстовое поле внизу заносятся
15
данные о том, какое количество вершин было обработано (с точностью до
10000 вершин для того, чтобы обновление данных занимало меньше времени).
Вид формы после завершения обработки показан на рисунке 3.
Рисунок 3
Вид БД (точнее, его часть) после обработки значений показан на рисунке 4.
16
Рисунок 4
2.4.
Анализ алгоритма и полученных данных
Оценка сложности алгоритма
Процедура формирования n! перестановок займет G(n) времени, где G(k) = 2(k
- 1) * G(k - 1), учитывая 2 обмена и рекурсивную перестановку оставшихся
элементов. Несложно видеть, что эта величина пропорциональна n!. Если
учесть, что в матрице смежности переставляются (за квадратичное время)
элементы в соответствии с перестановкой (см. 2.3), а результирующий массив
сортируется, то общее время генерации массива кодов графов, изоморфных
данному, равняется 𝑂(𝑛! ⋅ (𝑛2 𝑙𝑜𝑔𝑛!)).
Обозначим как I(m, n) количество неизоморфных графов с количеством
вершин n, мини-код которых меньше m. Тогда процедура поиска кода среди
уже исследованных займет, очевидно, O(I(m, n) log(n!)) времени с учетом того,
17
что поиск в отсортированном массиве будет двоичным. Всего будет совершено
n таких поисков, а также I(n, n) генераций массива. Отсюда общая сложность
алгоритма равна
𝑂([∑𝑛𝑘=0(𝐼(𝑘, 𝑛) ⋅ 𝑙𝑜𝑔𝑛!)] + [𝐼(𝑛, 𝑛) ⋅ 𝑛! ⋅ (𝑛2 + 𝑙𝑜𝑔𝑛!)])
(1).
Известна достаточно сложная формула для I(n, n), иначе говоря, количества
неизоморфных графов с количеством вершин n [9]. Остается «всего лишь»
исследовать функцию I(m, n). Это можно сделать при помощи таблиц ее
значений.
Замечание. В силу технических ограничений и для удобства восприятия ниже
(рисунки 5-7 для n = 4-6 соответственно) приведены графики функции 𝐽(𝑘, 𝑛) =
(𝑚 ⋮ 𝐼(𝑚, 𝑛) = 𝑘)
Рисунок 5
18
Рисунок 6
Рисунок 7
Исходя из этих графиков, единственная оценка, которая представляется
очевидной, - √𝑚 < 𝐼(𝑚, 𝑛) < 𝑚0.6, причем точность верхней оценки быстро
падает с ростом m. Это показано на рисунке 8.
19
Рисунок 8.
Тем не менее, с ее использованием можно переписать формулу (1) в виде
𝑂([𝑙𝑜𝑔𝑛! ⋅ ∑𝑛𝑘=0 𝑘 0.6 ] + [𝑛0.6 ⋅ 𝑛! ⋅ (𝑛2 + 𝑙𝑜𝑔𝑛!)])
(2)
Кроме того, в ходе работы алгоритм потребляет вплоть до 𝑂(𝐼(𝑛, 𝑛) ⋅
𝑛!) памяти. Это происходит тогда, когда перед концом работы алгоритма
(размер самого мини-кода можно не учитывать, т. к. в условиях нашей задачи
он ограничен 8 байтами).
Экспериментальные данные о времени работы и потреблении памяти
алгоритмом
Учитывая непредсказуемый рост I(m, n) с ростом m, а также наличие в
формуле (2) факториалов, об оценке времени работы алгоритма можно
говорить только для 6 ≤ 𝑛 ≤ 9. Эти данные приведены в таблице 1.
Таблица 1
20
n
Время работы
Потребление памяти,
КБ
6
00.01 с
10
7
01.08 с
34
8
26.30 с
84
9
343,5 мин
340
Более наглядно потребление алгоритмом памяти представлено на
графике (рисунок 9). Как видно, потребление памяти растет, хотя и не так
быстро. Однако с дальнейшим ростом n это превращается в проблему, т. к. в
современных компьютерах количество (оперативной) памяти ограничено 4-8
Гб.
Рисунок 9
21
ЗАКЛЮЧЕНИЕ
Основные результаты и выводы работы:
Разработана программа, перебирающая все графы с количеством вершин
от 1 до 10 и заносящая в БД их мини-коды. В процессе разработки был найден
подход к получению графов, изоморфных данному. Также был рассмотрен
вопрос эффективного хранения графов с малым числом вершин как в БД, так и
в оперативной памяти. Проведена оценка сложности алгоритма по времени и
памяти, а также найдены верхняя и нижняя оценки для количества
неизоморфных графов, чей мини-код меньше данного.
Основной вывод состоит в том, что, будучи наиболее простым в
реализации
для
небольших
графов,
мини-код
служит
идеальным
представлением для их хранения. Тем не менее, для работы с графами этот
формат не очень удобен, налагая к тому же существенные ограничения на
структуру графов. Кроме того, он занимает экспоненциальное количество как
времени, так и памяти для получения.
22
СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ
1.
Gow-Hsing King, Wen-Guey Tzeng. A New Graph Invariant For Graph
Isomorphism: Probability Propagation Matrix. // Journal of Information Science and
Engineering 15, 337-352 (1999). p.1.
2.
Paolo Codenotti. Testing isomorphism of combinatorial and algebraic
structures. // University of Chicago, Illinois, August 2011.
3.
Scott Fortin: The Graph Isomorphism Problem. // The department of computer
science, University of Alberta, Edmorton, Alberta, Canada. Technical report TR 9620, July 1996.
4.
Eugene M. Luks. Isomorphism of Graphs of Bounded Valence Can Be Tested
in Polynomial Time. // Department of Mathematics, Bucknell University, Lewisburg,
Pennsylvania 17837. Received October 21, 1981.
5.
Samir Datta, Nutan Limaye, Prajakta Nimbhorkar, Thomas Thierauf, Fabian
Wagner. Planar Isomorphism is in Log-Space. // June 15, 2009.
6.
Dominic Welsh. The Tutte Polynomial. // Merton College, University of
Oxford, Oxford OX1 4JD, England. Accepted 19 March 1999.
7.
Hein van der Holst, László Lovatz, and Alexander Schrijver. The Colin de
Verdière graph parameter. // Preliminary version, March 1997.
8.
Georges Gonthier. A computer-checked proof of the Four Colour Theorem. //
Microsoft Research Cambridge.
23
ПРИЛОЖЕНИЕ А
Класс graph_t.
namespace term_paper {
public class graph_t {
public int rank;
private ulong code, min_code;
public ulong binary_code {
get {
return code;
}
}
private ulong factorial(int rank) {
ulong res = 1;
for (uint i = 1; i <= rank; i++)
res *= i;
return res;
}
private List<string> natural_code() {
ulong code_copy = this.code;
List<char[]> res = new List<char[]>();
for (int i = 0; i != rank; i++){
res.Add(new char[rank]);
res[i][i] = global_data.invalid_char;
24
}
for (int i = rank - 1; i >= 0; i--) {
for (int j = rank - 1; j > i; j--) {
res[i][j] = res[j][i] = (char)((code_copy & 1)
+ '0');
code_copy >>= 1;
}
}
List<string> res_1 = new List<string>();
foreach (var s in res) {
res_1.Add(new string(s));
}
return res_1;
}
private ulong make_code(List<string> lst) {
ulong _code = 0;
for (int i = 0; i != rank; i++) {
for (int j = i + 1; j != rank; j++) {
_code += ((ulong)lst[i][j] - '0');
_code <<= 1;
}
}
_code >>= 1; // roll back
return _code;
}
private ulong permuted_code (int[] perm) {
25
List<string> nat_code = this.natural_code();
List<string> perm_code = new List<string>();
for(int i = 0; i != rank; i++) {
perm_code.Add("");
}
for(int i = 0; i != rank; i++) {
for(int j = 0; j != rank; j++) {
perm_code[i] += nat_code[perm[i]][perm[j]];
}
}
return make_code(perm_code);
}
public bool is_isomorph(graph_t gr) {
if (this.rank != gr.rank) {
return false;
}
int[] arr = new int[rank];
for (int i = 0; i != rank; i++)
arr[i] = i;
var perms = new Permutator<int>(arr, null).result;
foreach (var perm in perms) {
if (gr.permuted_code(perm) == this.code) {
return true;
}
}
return false;
26
}
public List<ulong> isomorph_codes() {
List<ulong> res = new List<ulong>();
int[] arr = new int[rank];
for (int i = 0; i != rank; i++)
arr[i] = i;
var perms = new Permutator<int>(arr, null).result;
foreach (var perm in perms) {
res.Add(this.permuted_code(perm));
}
return res;
}
public List<byte> degrees() {
var lst = this.natural_code();
var res = new List<byte>();
byte val;
foreach (var s in lst) {
val = 0;
foreach (var c in s) {
val += (byte)(c - '0');
}
res.Add((byte)(val - (global_data.invalid_char '0')));
}
return res;
}
27
public static ulong total_vertices (int rank) {
ulong max_code = 1;
int max_power = (rank - 1) * rank / 2;
for (int i = 0; i != max_power; i++)
max_code <<= 1;
return max_code;
}
public string image_representation() {
string res = "graph " + this.code + " {";
var arr = this.natural_code();
for (int i = 0; i != arr.Count; i++) {
for (int j = i + 1; j != arr[i].Length; j++) {
if (arr[i][j] == '1') {
res += (char)(i + (int)'0');
res += " -- ";
res += (char)(j + (int)'0');
res += ";";
}
}
}
res += '}';
return res;
}
public graph_t (ulong code, int rank) {
this.min_code = code;
this.code = code;
28
this.rank = rank;
}
}}
ПРИЛОЖЕНИЕ Б.
Класс permutator<T>.
namespace term_paper {
class Permutator<T> {
private List<T[]> lst;
private T[] array;
private int rank;
private Func<T[], int, int, T[]> swap;
public List<T[]> result {
get {
return lst;
}
}
private Permutator() {;}
public Permutator(T[] array, int rank, Func<T[], int,
int, T[]> swap) {
this.array = new T[array.Length];
array.CopyTo(this.array, 0);
this.rank = rank;
this.swap = swap;
this.lst = new List<T[]>();
permutations(0);
}
29
public Permutator(T[] array, int? rank) {
this.swap = (arr, i, j) => {
T t = arr[i];
arr[i] = arr[j];
arr[j] = t;
return arr;
};
this.array = new T[array.Length];
array.CopyTo(this.array, 0);
this.rank = rank ?? array.Length;
this.lst = new List<T[]>();
permutations(0);
}
private void permutations(int pos) {
try {
if (pos == rank - 1) {
lst.Add(new T[array.Length]);
array.CopyTo(lst[lst.Count - 1], 0);
}
else {
for (int i = pos; i != rank; i++) {
array = swap(array, pos, i);
permutations(pos + 1);
array = swap(array, i, pos);
}
}
30
}
finally {
;
}
}
}
}
31
ПРИЛОЖЕНИЕ В.
Класс i_sequence_t.
class i_sequence_codes {
public List<ulong> unique_codes;
public i_sequence_codes(int rank) {
unique_codes = new List<ulong>();
Dictionary<ulong, List<ulong>> i_codes = new
Dictionary<ulong, List<ulong>>();
ulong max_code = graph_t.total_vertices(rank);
bool flag;
for (ulong min_code = 1; min_code != max_code;
min_code++) {
if (min_code % 10000 == 0) {
global_data.main_form.update_interface(min_code,
max_code);
}
flag = false;
foreach(var i_code in i_codes) {
if (i_code.Value.BinarySearch(min_code) >= 0)
{
flag = true;
goto exit;
32
}
}
exit:
if (!flag) {
unique_codes.Add(min_code);
var i_code = new graph_t(min_code,
rank).isomorph_codes();
i_code.Sort();
i_codes.Add(min_code, i_code);
}
}
}
}
33
ПРИЛОЖЕНИЕ Г
Класс db_connection
public class db_connection_t {
MySqlConnection connection;
string table;
public db_connection_t(string location, string
_database, string table, string user, string password) {
this.table = table;
string str_con = "Database=" + _database + ";Data
Source=" + location + ";Username=" + user + ";Password="
+ password + ";";
connection = new MySqlConnection(str_con);
connection.Open();
// global_data.text.AppendText("Connected with " +
str_con);
}
public void insert (graph_t gr) {
string res = "";
foreach (byte c in gr.degrees()) {
res += (char)(c + (int)'0');
}
string query = "INSERT INTO " + this.table + "
34
VALUES (NULL, "
+ gr.rank + ", "
+ gr.binary_code + ", "
+ res + ", "
+ "\"" + gr.image_representation() + "\""
+ ");";
(new MySqlCommand(query,
connection)).ExecuteNonQuery();
}
~db_connection_t() {
connection.Close();
}
}
35
Download