Uploaded by Яблочный Сок

Разработка программного обеспечения на платформе .NET Framework КП

advertisement
Замечания руководителя
Содержание
Введение ............................................................................................................................ 4
1.Требования к программному обеспечению ................................................................ 5
1.1 Выбор языка высокого уровня .................................................................................. 5
1.1.1 Сведения о языках высокого уровня ..................................................................... 5
1.1.2 Описание языка C# .................................................................................................. 6
1.2 Сравнение .Net Framework и .Net Core ................................................................... 10
1.3 Преимущества и недостатки .NET Framework ...................................................... 12
2. Разработка математического обеспечения ............................................................... 14
2.1 Поиск наибольшего независимого множества ...................................................... 14
2.2 Алгоритм Брона — Кербоша ................................................................................... 16
2.3 Алгоритм математического функционирования ................................................... 18
3. Разработка архитектуры ПО ...................................................................................... 22
3.1 Диаграмма классов ................................................................................................... 22
3.2 Разработка алгоритмов и методов ........................................................................... 24
3.3 Описание диалога с пользователем ........................................................................ 25
3.4 Минимальные системные требования .................................................................... 28
3.5 Контрольный пример................................................................................................ 29
Заключение ...................................................................................................................... 31
Список литературы ......................................................................................................... 32
Введение
В данном курсовом проекте будет реализовано программное обеспечение
для конструирования некоторых алгоритмов на основе понятия максимального
независимого множества. Данное приложение будет разрабатываться в среде
разработки Microsoft Visual Studio 2019, на языке C# на платформе .NET Framework.
Максимальное независимое множество - независимое множество, не
являющееся подмножеством другого независимого множества. То есть это такое
множество вершин S, что любое ребро графа имеет хотя бы одну конечную
вершину, не принадлежащую S, и любая вершина не из S имеет хотя бы одну
соседнюю
в
S.
Максимальное
независимое
множество
является
также
доминирующим в графе, а любое доминирующее множество, являющееся
независимым, должно быть максимальным независимым, поэтому максимальные
независимые множества также называют независимыми доминирующими
множествами. Граф может иметь много максимальных независимых множеств в
широком диапазоне размеров.
4
1.Требования к программному обеспечению
1.1 Выбор языка высокого уровня
1.1.1 Сведения о языках высокого уровня
Язык программирования (ЯП) высокого уровня - формализованная
семантическая система, максимально приближенная к обычному человеческому
языку или иным привычным знаковым системам (например, математическим
формулам). Язык высокого уровня в минимальной степени привязан к процессору
или операционной системе и направлен на то, чтобы программист сосредоточился
на решении поставленной задачи, не отвлекаясь на особенности устройства
компьютера.
Язык Си, появившийся на рубеже 1960-1970-х гг. и ставший одним из
наиболее востребованных за всю историю развития компьютерных технологий,
дал толчок формированию большого количества языков, развивающих
заложенные в нем идеи:
 C++ - универсальный объектно-ориентированный язык, реализации
которого существуют практически для всех популярных операционных систем
(Unix, Windows, MacOS); программы, написанные на C++ отличаются высокой
производительностью, надежностью и масштабируемостью; язык обладает
развитой системой библиотек для решения практически любых задач;
 Objective C - версия Си для разработки программ, запускаемых на
платформах Apple (MacOS, iOS);
 C# - язык, применяемый преимущественно для разработки программ для
работы в операционной системе Windows;
 Java - универсальный язык, заявленный с самого момента своего появления
на рынке как кроссплатформенный, т.е. написанный на Java код можно без
внесения изменений использовать на любой операционной системе, в том числе
на мобильных устройствах (хотя, все-таки, с некоторыми оговорками);
 JavaScript - интерпретируемый язык для написания веб-приложений;
пригоден для решения широкого круга задач благодаря активно развивающемуся
в последние годы фреймворку Node.js..
5
Развитие языков программирования активно продолжается в связи с бурным
ростом вычислительных возможностей современной техники. В последние годы
появилось несколько языков, уверенно отвоевывающих популярность у
традиционных средств разработки. Основные из них:
 Язык Go, разрабатываемый и поддерживаемый компанией Google, стал
одним из первых, учитывающих преимущества многоядерных процессоров: он
отлично поддерживает многозадачность, что обеспечивает высокую
производительность написанных на нем приложений.
 Развиваемый организацией Mozilla Foundation язык Rust позиционируется
как низкоуровневый, однако код, написанный на нем считается безопасным, т.е.
можно сказать, что Rust преодолевает один из главных недостатков
низкоуровневых языков. Приоритетными в развитии Rust считаются эргономика,
скорость и безопасность.
 Swift - новый язык от компании Apple, призванный заменить устаревший
Objective-C. Этот ЯП предназначен для разработки нативных приложений как для
iOS (мобильные устройства), так и для MacOS (десктопные системы).
Приложения, написанные на Swift, демонстрируют высокую производительность.
Кроме того, он хорошо подходит для создания 2D-игр. На развитие Swift большое
влияние оказали ЯП Ruby и Python.
 Kotlin – язык, созданный на платформе Java. Он всё чаще используется для
написания мобильных приложений, работающих в среде ОС Android. Kotlin
обладает более низким порогом вхождения по сравнению с Java, при этом он
полностью поддерживается в привычной для разработчиков мобильных программ
IDE Android Studio. Вполне вероятно, что Kotlin может со временем стать
основным языком разработки для этого класса мобильных устройств.[1]
1.1.2 Описание языка C#
Язык C#, разработанный компанией Майкрософт, один из самых
популярных современных языков программирования. Он востребован на рынке
разработки в различных странах, C# применяют при работе с программами для
6
ПК, создании сложных веб-сервисов или мобильных приложений. Появившийся
как язык для собственных нужд платформы Microsoft .NET, постепенно этот язык
стал очень популярным. А потому мы решили сделать небольшой обзор для тех,
кто выбирает, какие инструменты разработки стоит освоить в ближайшее время.
Итак, разработка языка началась в 1998 году, а первая версия увидела свет в
2001. Группой разработчиков руководил известный в профессиональных кругах
специалист Андерс Хейлсберг. Новые версии C# выходят сравнительно часто, а
текущие доработки, исправление багов и расширение библиотек ведется
практически на постоянной основе.
В результате язык получился крайне гибкий, мощный и универсальный. На
нем пишут практически все, что угодно, от небольших веб-приложений до
мощных программных систем, объединяющих в себе веб-структуры, приложения
для десктопов и мобильных устройств. Все это стало возможным благодаря
удобному Си-подобному синтаксису, строгому структурированию, огромному
количеству фреймворков и библиотек (их число достигает нескольких сотен).
Долгое время платформа .NET поставлялась с закрытым ядром, что
создавало определенные сложности в разработке и снижало популярность C# в
профессиональной среде. Но в ноябре 2014 Майкрософт радикально изменила
подход и стала выдавать бесплатные лицензии для Visual Studio уже с открытым
исходным кодом для всех наборов инструментов
Плюсы языка C#:
1.
Поддержка
Компания Microsoft уделяет значительное внимание поддержке языка
разработки, а потому регулярно появляются обновления и дополнения,
исправляются выявленные баги в компиляторе, расширяются библиотеки.
Разработчики заинтересованы в популяризации инструмента и прилагают к этому
массу усилий.
2.
Документация и доступность
Разработчики предоставляют подробную и развернутую документацию на
своих официальных ресурсах. Кроме того, ответы практически на любые вопросы,
связанные с работой в C#, можно найти в сети. Популярность языка привела к
7
появлению множества профессиональных сообществ, посвященных Си шарпу.
Существует множество учебников, курсов для новичков и миддлов, видео
подборок и других обучающих материалов.
3.
Гибкость
Инструментарий C# позволяет решать широкий круг задач, язык
действительно очень мощный и универсальный. На нем разрабатывают:

Приложения для WEB.

Различные игровые программы.

Приложения платформ Андроид или iOS.

Программы для Windows.
Перечень возможностей разработки практически не имеет ограничений
благодаря широчайшему набору инструментов и средств. Конечно, все это можно
реализовать
при
помощи
других
языков,
но
некоторых
из
них
узкоспециализированные, в других придется использовать дополнительные
инструменты сторонних разработчиков. В C# решение широкого круга задач
возможна быстрее, проще и с меньшими затратами времени и ресурсов.
4.
Сборка мусора
Позволяет в автоматическом режиме очистить память от объектов, которые
не используются, или уничтоженных приложений.
5.
Обработка исключений
С помощью этого инструмента можно легко выявлять и обрабатывать
ошибки в коде. Способ является структурированным с широким набором
функций. При этом важно не злоупотреблять возможностями работы с
исключениями, так как при неправильном использовании появляется риск
появления «багов».
6.
Единая система типов
В языке принята общая система работы с типами, начиная от примитивов и
заканчивая сложными, в том числе, пользовательскими наборами. Применяется
единый набор операций для обработки и хранения значений типизации. Также
можно использовать ссылочные типы пользователя, что позволит динамически
выделить память под объект или хранить упрощенную структуру в сети.
8
Язык программирования запрещает обращение к переменным, которые не
были
инициализированы,
что
исключает
возможность
выполнения
бесконтрольного приведения типов или выхода за пределы определенного
массива данных.
7.
Управление версиями
Очень интересная особенность ЯП. Суть в том, что многие языки не
уделяют должного внимания этому вопросу, и программы нередко перестают
корректно работать при переходе на новую версию продукта. В C# это было
исправлено. [2]
9
1.2 Сравнение .Net Framework и .Net Core
NET Framework
NET Framework - это служба Windows следующего поколения от Microsoft,
существующая с 2000 года. Среда выполнения этой платформы помогает
разработчикам создавать приложения, веб-службы и настольные приложения для
Windows для Windows.
Два наиболее важных компонента .NET Framework:
 Общеязыковая среда выполнения (CLR)
 Обширная библиотека классов
В целом .NET - это объектно-ориентированная среда, которая проста в
использовании и поддерживает несколько языков. Единственное ограничение это закрытый исходный код, для преодоления которого Microsoft использует .NET
Core в качестве платформы с открытым исходным кодом.
.NET Core
.NETCore - это инфраструктура, которая помогает создавать приложения
для всех операционных систем - Linux, Mac и Windows. Он поддерживает языки
программирования, такие как C #, F #, Visual Basic для разработки приложений и
библиотек.
Такие замечательные функции, как микросервисы, высокопроизводительная
сеть, множество API и компонентов и многое другое, делают эту платформу
привлекательной для разработчиков программного обеспечения. Веб-сайты,
мобильные, облачные, игровые, настольные, веб-приложения и приложения для
искусственного интеллекта можно создавать с помощью .NET Core.[3]
Основные отличия Net Framework от .Net Core:
1)
.NET
Core
предлагает
значительные
преимущества
для
новых
приложений и шаблонов приложений. Однако .NET Framework продолжает
оставаться естественным выбором для многих существующих сценариев, и
10
поэтому .NET Framework не заменяется .NET Core для всех серверных
приложений.
2) .NET Core является последней версией CLR и предпочтительным на
данный момент параметром. .NET Framework является самой старой реализацией
Common Language Runtime.
3) Многие инфраструктуры предлагают наибольшую поддержку для
приложений .NET Core. Поскольку они имеют меньший вес, чем приложения
.NET Framework, .NET Core работает быстрее и более масштабируемо.
4) .NET Core - это новая кроссплатформенная платформа с открытым
исходным
кодом, предназначенная
для
создания
приложений
для
всех
операционных систем, включая Windows, Mac и Linux, в то время как .NET
Framework поддерживает приложения Windows и веб-приложения.
Выбирать .NET Framework следует:

Когда вашему приложению нужны сторонние библиотеки или пакеты NuGet

Когда технологии .NET недоступны для .NET Core

Когда ваша платформа не поддерживает .NET Core
Переходить на .NET Core когда вы собираетесь:

Создавать кроссплатформенные приложения

Разрабатывать масштабируемое и высокопроизводительное приложение

Использовать различные версии .NET в вашем приложении

Заняться построением микросервисов
11
1.3 Преимущества и недостатки .NET Framework
.NET. Платформа Microsoft .NET Framework состоит из большого
количества инструментов для разработки и технологий, используя которые
разработчик может создавать различные типы приложений, от обычных
настольных приложений и сайтов, заканчивая решениями для мобильных
платформ и компьютерными играми. В основе платформы Microsoft .NET
Framework лежит язык программирования C#.
Основной идеей при разработке .NET Framework являлось обеспечение
свободы разработчика за счёт предоставления ему возможности создавать
приложения различных типов, способные выполняться на различных типах
устройств и в различных средах.
Вторым принципом стала ориентация на системы, работающие под
управлением семейства операционных систем Microsoft Windows.
Достоинства платформы .NET:
1.
Цельная
объектно-ориентированная
модель
программирования,
упрощающая разработку программ
2.
Многоплатформенность приложений
3.
Автоматическое управление ресурсами
4.
Улучшение возможностей для повторного использования исходного
кода Упрощение развертывания приложений
5.
Современная модель безопасности развертывания и сопровождения
6.
Полный отказ от реестра
7.
Безопасные типы и общее повышение безопасности приложений
8.
Единая модель обработки ошибок
9.
Межъязыковое взаимодействие (language interoperability)
10.
Единая среда разработки, позволяющая проводить межъязыковую
кода
отладку
11.
Расширенные возможности повторного использования кода. [4]
12
Недостатки платформы .NET:
1.
Замедление при выполнении программ
2.
Привязанность некоторых архитектурных решений .NET к С++-
подобным языкам
3.
Необходимость
изменения
стандартов
для
многих
языков
программирования.
Проанализировав все достоинства и недостатки вышеописанных платформ,
я пришел к выводу, что нужно использовать именно .NET Framework, так как
именно эта языковая платформа обладает нужной инструментальной базой для
работы над задачей курсового проекта.
13
2. Разработка математического обеспечения
2.1 Поиск наибольшего независимого множества
В теории графов максимальным независимым множеством, максимальным
устойчивым множеством, или максимальным стабильным множеством называется
независимое множество, не являющееся подмножеством другого независимого
множества. То есть это такое множество вершин S, что любое ребро графа имеет
хотя бы одну конечную вершину, не принадлежащую S, и любая вершина не из S
имеет хотя бы одну соседнюю в S. Максимальное независимое множество
является также доминирующим в графе, а любое доминирующее множество,
являющееся независимым, должно быть максимальным независимым, поэтому
максимальные
независимые
множества
также
называют
независимыми
доминирующими множествами. Граф может иметь много максимальных
независимых множеств в широком диапазоне размеров. [5]
Задача нахождения наибольшего независимого множества и задача о
наибольшей клике полиномиально эквивалентны — можно найти наибольшее
независимое множество путём поиска максимальной клики в дополнении графа,
так что многие авторы особенно не заботятся о разделении этих двух задач. Обе
задачи NP-полны, так что вряд ли их можно решить за полиномиальное время.
Тем не менее, задача о наибольшем независимом множестве может быть решена
эффективнее, чем за время O (n2 2n), которое даёт полный перебор, проверяющий
все подмножества вершин, являются ли они независимыми множествами.
Алгоритм Брона-Кербоша [6] решает задачу за время O(3^n/3).
Вопреки близкой связи между наибольшей кликой и наибольшим
независимым
множеством
в
произвольном
графе,
задачи
нахождения
независимого множества и клики могут существенно отличаться, когда решаются
на специальном классе графов. Например, для разреженных графов (графы, в
которых в любом подграфе число рёбер не больше числа вершин, умноженного на
некоторую константу) наибольшая клика имеет ограниченный размер и может
быть найдена точно за линейное время [7]. Тем не менее, для тех же классов
графов, или даже для случая более жёстких ограничений у класса графов с
14
ограниченной степенью, поиск наибольшего независимого множества является
MAXSNP-полной, что означает, что для некоторой константы c (зависящей от
степени) NP-трудно найти приближённое решение, отличающееся на множитель c
от оптимального [8]. Однако эффективные приближённые алгоритмы известны,
но для них гарантированная эффективность хуже, чем этот порог. Например,
жадный алгоритм создаёт максимальное по включению независимое множество,
на каждом шаге выбирая вершину с минимальной степенью и удаляя её соседей.
Этот алгоритм достигает гарантированной эффективности (Δ+2)/3 на графах с
максимальной степенью Δ. [9]
В некоторых классах графов (включая графы без клешней [10] и
совершенные графы [11]; к последнему классу принадлежат и деревья)
наибольшее независимое множество может быть найдено за полиномиальное
время. Для планарных графов задача о наибольшем независимом множестве
остаётся NP-полной для точного решения, но может быть аппроксимирована с
любой гарантированной эффективностью "c" < 1 за полиномиальное время.
Похожие приближённые схемы полиномиального времени существуют в любом
семействе минорно замкнутых графов. [12]
В двудольных графах все вершины, не входящие в наименьшее вершинное
покрытие, могут быть включены в наибольшее независимое множество (смотри
теорему Кёнига). Поэтому наибольшее независимое множество может быть
найдено с помощью алгоритма нахождения наибольшего паросочетаний в
двудольных графах.
15
2.2 Алгоритм Брона — Кербоша
Алгоритм Брона — Кербоша — метод ветвей и границ для поиска всех клик
(а также максимальных по включению независимых множеств вершин)
неориентированного графа. Разработан голландскими математиками Броном и
Кербошем в 1973 году и до сих пор является одним из самых эффективных
алгоритмов поиска клик.
Алгоритм использует тот факт, что всякая клика в графе является его
максимальным по включению полным подграфом. Начиная с одиночной вершины
(образующей полный подграф), алгоритм на каждом шаге пытается увеличить уже
построенный полный подграф, добавляя в него вершины из множества
кандидатов. Высокая скорость обеспечивается отсечением при переборе
вариантов, которые заведомо не приведут к построению клики, для чего
используется дополнительное множество, в которое помещаются вершины,
которые уже были использованы для увеличения полного подграфа.
Основной
формой
алгоритма
Брона-Кербоша
является
рекурсивно-
возвращающийся алгоритм, который ищет все максимальные клики в данной
графе G . В целом, учитывая три непересекающихся множества вершин R , P и X ,
он находит максимальные клики , которые включают в себя все вершины в R ,
некоторые из вершин в Р , и ни одну из вершин X. В каждом вызове алгоритма, Р
и Х - непересекающиеся множества, объединение которых состоит из тех вершин,
которые образуют клики при добавлении к R. Другими словами, Р ∪ X это
множество вершин, которые соединены с каждым элементом R. Когда P и X оба
пусты, больше нет элементов, которые можно добавить к R, поэтому R является
максимальной кликой, и алгоритм выводит R. Рекурсия инициируется установкой
R и X как пустые множества, а P как набор вершин графа. В каждом рекурсивном
вызове алгоритм по очереди рассматривает вершины в P; если таких вершин нет,
он либо выводит R как максимальную клику (если X пусто), либо выполняет
возврат. Для каждой вершины V, выбранной из Р, происходит рекурсивный вызов,
в котором V добавляется к R, и в котором Р и Х имеют ограниченный к набору
соседей N (V) из V, находящему и сообщающему все расширения клики R ,
16
которые содержат V. Затем он перемещает V из P в X , чтобы исключить его из
рассмотрения в будущих кликах и продолжает со следующей вершиной в P .
Алгоритм Брона-Кербоша не является алгоритмом, чувствительным к
выходным данным: в отличие от некоторых других алгоритмов для задачи о
клике, он не выполняется за полиномиальное время на сгенерированную
максимальную клику. Однако он эффективен в худшем случае: по результатам
Moon & Moser (1965) любой n-вершинный граф имеет не более 3n / 3
максимальных клик, а время работы алгоритма Брон-Кербоша в худшем случае
составляет O (3n / 3), что соответствует этой границе.
Для разреженных графов возможны более жесткие границы. В частности,
версию алгоритма Брона-Кербоша с упорядочением вершин можно заставить
работать за время O (dn3^(d/3)), где d - вырожденность графа, мера его
разреженности. Существуют d-вырожденные графы, для которых общее
количество максимальных клик равно (n - d) 3^(d / 3), поэтому эта оценка близка к
точной. [13]
17
2.3 Алгоритм математического функционирования
Рисунок 1 – Блок-схема алгоритма Брона-Кербоша
Алгоритм оперирует тремя множествами вершин графа:
1.
Множество compsub — множество, содержащее на каждом шаге
рекурсии полный подграф для данного шага. Строится рекурсивно.
2.
Множество
candidates
—
множество
вершин,
которые могут
увеличить compsub
3.
Множество not — множество вершин, которые уже использовались
для расширения compsub на предыдущих шагах алгоритма.
18
Алгоритм является рекурсивной процедурой, применяемой к этим трем
множествам.
Описание работы алгоритма:
1.
Положить множества not и compsub пустыми, множество candidates –
множество всех вершин графа.
2.
Пусть во множестве compsub k вершин. Взять вершину
xi
k 1
из
множества candidates, и поместить её во множество compsub.
3.
Если в not есть вершина, связанная со всеми из candidates, то перейти
к шагу 5, иначе к шагу 4.
4.
Если candidates и new_candidates пусты, что напечатать клику compsub
и перейти к шагу 5. Если пусто только candidates, то перейти к шагу 5. Иначе
перейти к шагу 2.
5.
Удалить из compsub вершину xi
k 1
. Удалить эту же вершину из
candidates и добавить её в not. Если candidates и compsub пусты, алгоритм
останавливается. Иначе перейти к шагу 3.
Псевдокод алгоритма:
1.
ПРОЦЕДУРА extend (candidates, not):
2.
ПОКА candidates НЕ пусто И not НЕ содержит вершины,
СОЕДИНЕННОЙ СО ВСЕМИ вершинами из candidates,
3.
ВЫПОЛНЯТЬ:
4.
Выбираем вершину v из candidates и добавляем её в compsub
5.
Формируем new_candidates и new_not, удаляя из candidates и not
вершины, не СОЕДИНЕННЫЕ с v
6.
ЕСЛИ new_candidates и new_not пусты
7.
ТО compsub – клика
8.
ИНАЧЕ рекурсивно вызываем extend (new_candidates, new_not)
9.
Удаляем v из compsub и candidates, и помещаем в not
Нетрудно видеть, что задача о клике и задача о независимом множестве по
сути эквивалентны: каждая из них получается из другой, путём построения
дополнения графа — такого графа, в котором есть все вершины исходного графа,
19
причем в дополнении графа вершины соединены ребром тогда и только тогда,
если они не были соединены в исходном графе.
Поэтому алгоритм Брона — Кербоша можно использовать для нахождения
максимальных по включению независимых множеств вершин, если построить
дополнение к исходному графу, либо изменив условие в основном цикле (условие
остановки) и формирование новых множеств new_candidates и new_not:
Условие в основном цикле: not не должно содержать ни одной вершины, не
соединенной ни с одной из вершин во множестве candidates
Для формирования new_candidates и new_not, необходимо удалять из
candidates и not вершины, соединенные с выбранной вершиной. [14]
20
Рисунок 2 – Блок-схема модифицированного алгоритма Брона-Кербоша
Для того, чтобы алгоритм искал максимальное по размеру независимое
множество, необходимо:
1.
завести еще одно множество max_compsub (начальное значение —
пустое множество)
2.
на шаге 4, когда найдена очередная клика, сравнить размер
(количество вершин) в compsub и в max_compsub и поместить в max_compsub
множество с большим числом вершин. [15]
21
3. Разработка архитектуры ПО
3.1 Диаграмма классов
Рисунок 3 – Диаграмма классов
Описание классов:
Vertex – «вершина», хранит координаты по оси «x» и оси «y»
местонахождения вершины в окне рисования графа и список рёбер, с которыми он
связан, содержит метод для проверки двух вершин на смежность(наличие ребра
между ними) и конструктор для выделения памяти под список связанных рёбер.
Edge – «ребро», хранит информацию о двух вершинах, которые соединяет,
имеет конструктор, заполняющий поля под эти вершины.
Graph – «граф», хранит информацию о вершинах, рёбрах и максимальных
независимых множествах в виде списков соответствующих типов, имеет
конструктор для выделения памяти под них, а так же методы для прорисовки
составляющих элементов и самого графа полностью, метод для поиска
максимальных по включению независимых множеств – BronKerbosch(), который
выполнен в виде процедуры, реализующей алгоритм Брона-Кербоша и метод для
поиска максимальных по длине независимых множеств – GetMaxLengthSets()
22
MaxSet – «максимальное независимое множество, наследуется от класса
Graph, и в основном использует методы и поля базового класса, так как имеет
только один собственный метод – DrawMaxSet, который прорисовывает все
составные элементы класса.
23
3.2 Разработка алгоритмов и методов
Описание ключевых методов программы:
Класс Graph:
Метод поиска максимального по включению независимого множества:
метод использует алгоритм Брона-Кербоша, чтобы найти все максимальные
независимые множества графа. Однако стоит отметить, что оригинальный
алгоритм, ищет не независимые множества, а клики, поэтому для того, чтобы
найти именно множества, нам нужно выполнить данный алгоритм на обратной
матрице смежности, в которой нули заменены единицами и наоборот, которую
можно получить при помощи специального метода. Алгоритм функционирует
следующим образом: циклом перебираются все вершины, затем рассматриваются
её соседи, если один из них имеет рёбра со всеми теми, что уже добавлены в
набор вершин клики, то тоже добавляется в этот набор. Затем, когда у очередной
вершины таких соседей нет, клика сохраняется и цикл продолжается с
предыдущей по добавлению вершины, а текущая отмечается как «отработанная».
После того как все вершины отработаны их список очищается и цикл
продолжается со следующей вершины. Так продолжается пока не будут
перебраны все вершины.
Метод поиска максимальных по длине независимых множеств: реализован с
помощью двух циклов: первый находит максимальную длину найденных
максимальных независимых множеств графа, второй сравнивает эту длину с
длиной каждого такого множества и добавляет в соответствующий список при
совпадении.
Метод получения обратной матрицы смежности– получает матрицу
смежности обратного графа заданному, представляет из себя матрицу смежности
рассматриваемого графа, в которой нули заменены на единицы и наоборот.
Класс Vertex:
Метод проверки связанности двух вершин: проверяет, является ли текущая
вершина и переданная в качестве параметра связаны ребром, перебирая список
имеющихся рёбер и сравнивая вершины каждого ребра с переданной.
24
3.3 Описание диалога с пользователем
При запуске программы пользователь видит главное меню программы.
Там ему доступны 5 основных кнопок:
Добавить вершину. Добавляет вершину на граф (рисунок 4).
Рисунок 4 – Добавление вершины
Добавить ребро. Кнопка нужна для создания ребер между вершинами
(рисунок 5).
25
Рисунок 5 – Добавление ребра
Удалить элемент. Кнопка позволяет удалять вершины и ребра графа
(рисунок 6).
Рисунок 6 – Удаление элемента
Удалить граф. Кнопка позволяет пользователю удалить весь граф.
Брон-Кербош. Кнопка запускает работу алгоритма Брона-Кербоша. Правое
окно становится активным и пользователь может выбрать для отображения
максимальные
независимые
множества,
26
которые
найдет
алгоритм.
Они
отобразятся на графе (рисунки 7-8). Пользователь может выбрать как он хочет
отобразить нужный ему ответ на графе. Для этого над полем с вершинами есть
вкладки «МНМ по включению» и «МНМ по длине»
Рисунок 7 – Результат работы программы
Рисунок 8 – Результат работы программы
Также в приложении есть кнопка «Скрыть множество», позволяющая
пользователю скрыть отображаемый ответ на графе.
27
3.4 Минимальные системные требования
Разработанная
программа
обладает
следующими
минимальными
требованиями:
· Операционная система Windows 10;
· Процессор с тактовой частотой не ниже 1,3 ГГц и количеством ядер не
менее 2;
· 1 Мб свободного места на жестком диске;
· .NET Framework не ниже 4.8
28
3.5 Контрольный пример
На рисунке 9 представлен граф.
Рисунок 9 – Граф
В ходе решения находим максимальные независимые множества (рисунок
10). Ответами будут: {1,2},{2,3},{4}
Рисунок 10 – Решение по алгоритму
29
Воссоздаем граф в программе и нажимаем кнопку «Брон-Кербош».
Программа находит те же самые максимальные независимые множества, что и
было рассчитано до этого (рисунок 11).
Рисунок 11 – Результат работы программы
30
Заключение
В ходе выполнения данного курсового проекта была написана программа на
объектно-ориентированном языке C#, способная по нарисованному графу найти
все максимальные независимые множества с помощью алгоритма Брона-Кербоша.
В ходе работы были развиты навыки программирования, дискретной
математики, были изучены методы по работе с графами, получены практические
навыки проектирования архитектуры ПО.
31
Список литературы
1.
Языки программирования высокого уровня [Электронный ресурс] //
Справочник
//
URL:
https://spravochnick.ru/programmirovanie/yazyki_programmirovaniya_vysokogo_urov
uro (Дата обращения:10.10.2020)
2.
Язык программирования C#: краткий обзор [Электронный ресурс] //
Techrocks // URL: https://techrocks.ru/2019/02/16/c-sharp-programming-languageoverview/ (Дата обращения:10.10.2020)
3.
Microsoft .NET Framework [Электронный ресурс] // Flexberry // URL:
https://flexberry.github.io/ru/gbt_dotnet.html (Дата обращения:11.10.2020)
4.
Платформа .NET. Основные возможности и достоинства. CLR. MSIL.
Особенности .NET Framework 2.0. Microsoft Visual Studio 2005. [Электронный
ресурс] // Конспектов нет // URL: http://www.konspektov.net/question/4056 (Дата
обращения: 05.11.2020)
5.
On cliques in graphs / P. Erdős – Israel J. Math.. 1966. Т. 4, вып. 4. — С.
233—234.
6.
Graphs & paths: Bron-Kerbosch [Электронный ресурс] // LaptrinhX //
URL: maximal cliques https://laptrinhx.com/graphs-paths-bron-kerbosch-maximalcliques-1126883855/ (Дата обращения: 05.11.2020)
7.
Nishizeki Arboricity and subgraph listing algorithms / N. Chiba T. –
SIAM Journal on Computing. 1985.
8.
On approximation properties of the independent set problem for degree 3
graphs / Piotr Berman, Toshihiro Fujito – Lecture Notes in Computer Science 1995. —
Т. 955. — С. 449–460.
9.
Greed is good: Approximating independent sets in sparse and bounded-
degree graphs / M. M. Halldórsson, J. Radhakrishnan – Algorithmica. 1997.
10.
Algorithme de recherche d'un stable de cardinalité maximum dans un
graphe sans étoile (фр.) / Najiba Sbihi – Discrete Mathematics. 1980
11.
Geometric Algorithms and Combinatorial Optimization. / M. Grötschel, L.
Lovász, A. Schrijver – Springer–Verlag, 1988. Т. 2. С. 296–298
32
12.
Approximation algorithms for NP-complete problems on planar graphs /
Brenda S. Baker – Journal of the ACM. 1994
13.
Listing all maximal cliques in large sparse real-world graphs / Eppstein,
David; Strash, Darren – 10th International Symposium on Experimental Algorithms
2011
14.
Algorithm 457 Finding all cliques of an undirected graph / Bron C.,
Kerbosh J. – Comm. of ACM 1973, p. 575—577.
15.
The worst-case time complexity for generating all maximal cliques and
computational experiments / Etsuji Tomita, Akira Tanaka, Haruhisa Takahash
Theoretical Computer Science, 2006, p. 28-42.
33
–
Листинг кода
Edge.cs
using
using
using
using
using
System;
System.Collections.Generic;
System.Linq;
System.Text;
System.Threading.Tasks;
namespace Variant1
{
public class Edge
{
public Vertex vertexOne;
public Vertex vertexTwo;
public Edge(Vertex start, Vertex end, int id)
{
vertexOne = start;
vertexTwo = end;
}
}
}
Graph.cs
using
using
using
using
using
using
System;
System.Collections.Generic;
System.Drawing;
System.Linq;
System.Text;
System.Threading.Tasks;
namespace Variant1
{
public class Graph
{
private const int vDiameter = 30;
private const int nRadius = 7;
private Font font;
public
public
public
public
List<Vertex> vertices;
List<Edge> edges;
List<MaxSet> maxSets;
List<MaxSet> maxLengthSets;
public Graph()
{
vertices = new List<Vertex>();
edges = new List<Edge>();
font = new Font("Lucida Console", 12);
}
private int[,] GetReverseMatrix()
{
int[,] matrix = new int[vertices.Count, vertices.Count];
for(int i = 0; i < vertices.Count; i++)
{
for(int j = 0; j < vertices.Count; j++)
{
if (vertices[i].hasEdgeWith(vertices[j])) matrix[i, j] = 0;
else matrix[i, j] = 1;
}
}
return matrix;
34
}
public void BronKerbosch()
{
maxSets = new List<MaxSet>();
int[,] gmatrix = GetReverseMatrix();
int n = vertices.Count;
List<List<int>> output = new List<List<int>>();
List<int> M = new List<int>();
List<int> K = new List<int>();
List<int> P = new List<int>();
int v;
Stack<int> stackV = new
Stack<List<int>> stackM
Stack<List<int>> stackK
Stack<List<int>> stackP
Stack<int>();
= new Stack<List<int>>();
= new Stack<List<int>>();
= new Stack<List<int>>();
List<int> GS = new List<int>();
for (int i = 0; i < n; i++)
K.Add(i);
while (K.Count != 0 || M.Count != 0)
{
if (K.Count != 0)
{
v = K[0];
stackM.Push(M.GetRange(0, M.Count));
stackK.Push(K.GetRange(0, K.Count));
stackP.Push(P.GetRange(0, P.Count));
stackV.Push(v);
M.Add(v);
GS = G(v);
SubtractSet2(K, GS);
SubtractSet1(K, v);
SubtractSet2(P, GS);
}
else
{
if (P.Count == 0)
output.Add(M.GetRange(0, M.Count));
M = stackM.Pop();
K = stackK.Pop();
P = stackP.Pop();
v = stackV.Pop();
SubtractSet1(K, v);
P.Add(v);
}
}
foreach (List<int> maxSetPath in output)
{
MaxSet maxSet = new MaxSet();
foreach (int vertex in maxSetPath)
{
maxSet.vertices.Add(GetVertexById(vertex + 1));
}
maxSets.Add(maxSet);
}
void SubtractSet1(List<int> set, int vert)
{
35
for (int i = 0; i < set.Count; i++)
{
if (set[i] == vert)
set.RemoveAt(i);
}
}
void SubtractSet2(List<int> set1, List<int> set2)
{
for (int i = 0; i < set1.Count; i++)
for (int j = 0; j < set2.Count; j++)
if (set1.Count != 0 && i < set1.Count)
if (set1[i] == set2[j])
set1.RemoveAt(i);
}
List<int> G(int vert)
{
List<int> ret = new List<int>();
for (int i = 0; i < n; i++)
if (gmatrix[i, vert] == 0)
ret.Add(i);
return ret;
}
}
public void GetMaxLengthSets()
{
maxLengthSets = new List<MaxSet>();
int maxLength = 0;
foreach(MaxSet maxSet in maxSets)
{
if (maxSet.vertices.Count > maxLength) maxLength = maxSet.vertices.Count;
}
foreach (MaxSet maxSet in maxSets)
{
if (maxSet.vertices.Count == maxLength) maxLengthSets.Add(maxSet);
}
}
public Vertex GetVertexById(int id)
{
return vertices.Find(v => v.id == id);
}
public void DrawVertex(ref Graphics graphics, Vertex vertex, Pen pen, Brush brush)
{
graphics.DrawEllipse(pen, vertex.x - vDiameter / 2, vertex.y - vDiameter / 2,
vDiameter, vDiameter);
int bias = 0;
if (vertex.id > 9) bias = 5;
if (vertex.id > 99) bias = 10;
Point point = new Point(vertex.x - nRadius - bias, vertex.y - nRadius);
graphics.DrawString(vertex.id.ToString(), font, brush, point);
}
public void DrawEdge(ref Graphics graphics, Vertex start, Vertex end, Pen pen)
{
double angle = Math.Atan2(end.x - start.x, end.y - start.y);
36
graphics.DrawLine(pen,
Convert.ToInt32(end.x Convert.ToInt32(end.y Convert.ToInt32(start.x
Convert.ToInt32(start.y
vDiameter /
vDiameter /
- vDiameter
- vDiameter
2
2
/
/
*
*
2
2
Math.Sin(angle)),
Math.Cos(angle)),
* Math.Sin(angle + Math.PI)),
* Math.Cos(angle + Math.PI)));
}
public void DrawGraph(ref Graphics graphics)
{
foreach(Vertex vertex in vertices)
{
DrawVertex(ref graphics, vertex, new Pen(Color.Blue), Brushes.Blue);
}
foreach(Edge edge in edges){
DrawEdge(ref graphics, edge.vertexOne, edge.vertexTwo, new Pen(Color.Black));
}
}
}
}
MaxSet.cs
using
using
using
using
using
using
System;
System.Collections.Generic;
System.Drawing;
System.Linq;
System.Text;
System.Threading.Tasks;
namespace Variant1
{
public class MaxSet : Graph
{
public void DrawMaxSet(ref Graphics graphics)
{
foreach (Vertex vertex in vertices)
{
DrawVertex(ref graphics, vertex, new Pen(Color.Gold, 4), Brushes.Gold);
}
}
public void DrawMaxLengthSet(ref Graphics graphics)
{
foreach (Vertex vertex in vertices)
{
DrawVertex(ref graphics, vertex, new Pen(Color.Red, 4), Brushes.Red);
}
}
}
}
Vertex.cs
using
using
using
using
using
System;
System.Collections.Generic;
System.Linq;
System.Text;
System.Threading.Tasks;
namespace Variant1
{
public class Vertex
{
public List<Edge> connectedEdges;
public int id;
public int x;
public int y;
public Vertex()
{
37
connectedEdges = new List<Edge>();
}
public bool hasEdgeWith(Vertex vertex)
{
foreach(Edge edge in connectedEdges)
{
if (id != vertex.id && (edge.vertexOne == vertex || edge.vertexTwo == vertex))
return true;
}
return false;
}
}
}
Program.cs
using
using
using
using
using
System;
System.Collections.Generic;
System.Linq;
System.Threading.Tasks;
System.Windows.Forms;
namespace Variant1
{
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
}
}
38
Download