Структура и объем работы - LMS

advertisement
Правительство Российской Федерации
Федеральное государственное автономное образовательное учреждение
высшего профессионального образования
Национальный исследовательский университет
«Высшая школа экономики»
Факультет информатики, математики и компьютерных наук
Вороная Ксения Эдуардовна
ЭФФЕКТИВНЫЕ АЛГОРИТМЫ РЕШЕНИЯ КВАДРАТИЧНОЙ ЗАДАЧИ О
НАЗНАЧЕНИЯХ (КЗН) ДЛЯ НЕКОТОРЫХ ТИПОВ ГРАФОВ
Выпускная квалификационная работа по направлению
01.03.02 «Прикладная математика и информатика»
студента группы № 11ПМИ
Рецензент
Научный руководитель
преподаватель кафедры ПМИ
доцент кафедры ПМИ
Грибанов Д. В.
Малышев Д. С.
Нижний Новгород, 2015
Содержание
Введение…………………………………………………………………………………3
1 Математическая постановка задачи и обзор существующих подходов к ее
решению…………………………………………………………………………………7
1.1 Изначальная матричная постановка КЗН………………………………………….7
1.2 Постановка КЗН в терминах теории графов……………..………………………...8
1.3 Обзор существующих подходов к решению КЗН…………………………………9
2 Описание алгоритмов, их теоретическое обоснование и оценки сложности……12
2.1 Описание первого алгоритма, теоретическое обоснование……………………..12
2.2 Описание второго алгоритма, теоретическое обоснование……………………..18
2.3 Описание третьего алгоритма, теоретическое обоснование……….....................21
2.4 Оценки сложности…………………………………………………………………23
3 Вычислительные эксперименты…………………………………………………...25
3.1 Результаты экспериментов для первого алгоритма……………………………...25
3.2 Результаты экспериментов для второго алгоритма………………………………27
3.3 Результаты экспериментов для третьего алгоритма……………………………..29
Заключение …………………………………………………………………………….31
Список литературы…………………………………………………………………….32
Приложение №1………………………………………………………………………..34
Приложение №2………………………………………………………………………..36
Приложение №3………………………………………………………………………..37
2
Введение
Квадратичная задача о назначениях (КЗН) является классической задачей
оптимального размещения взаимосвязанных объектов в дискретной постановке.
Эта проблема хорошо известна в области комбинаторной оптимизации и теории
графов. Впервые определение КЗН было введено T. Ч. Купмансом и М. А.
Бекманном в 1957 году [11]. На практике данная задача формулируется следующим
образом: необходимо разместить N объектов (предприятий) в N позиций таким
образом, чтобы суммарная стоимость связей, которая пропорциональна удельным
стоимостям связей между объектами, умноженным на расстояния между
позициями, была минимальной. При этом в каждую позицию может быть размещен
только один объект.
В дополнение к практической формулировке, наглядным примером является
размещение технологического оборудования нефтегазовых предприятий. Есть
схема производства, заданы единицы технологического оборудования, структура
связей и их удельная стоимость (стоимость трубопроводов). Известны возможные
позиции установки для оборудования. Также известны каналы между позициями
для прокладки коммуникаций. Целью является размещение оборудования на
позиции таким образом, чтобы связи были проложены по обозначенным каналам, и
суммарная стоимость связей была минимальной.
В КЗН связи между объектами и расстояния между позициями, в которые объекты
размещаются, представляются в виде матриц и графов. Стоит отметить, что в общем
случае, т.е. для произвольных графов и матриц, данная задача является NP-трудной.
В связи с этим поиск полиномиально разрешимых случаев КЗН является
актуальным направлением для различного рода исследований.
Полиномиально разрешимые случаи КЗН являются предметом моего исследования.
Данная задача рассматривается в терминах теории графов, когда структура связей
3
между размещаемыми объектами представлена в виде реберно-взвешенного графа
без петель и кратных ребер. Вершины графа представляют собой размещаемые
объекты, а ребра – связи. Вес ребра отражает удельную стоимость связи. Позиции
для размещения объектов представляются узлами сети. Целью является
нахождение взаимно однозначного соответствия между вершинами графа и узлами
сети таким образом, что суммарная стоимость связей минимальна.
Актуальность выбранной темы подтверждается тем фактом, что задачи
оптимального размещения имеют широкое практическое применение. Их
необходимо решать во время проектирования планов цехов предприятий, при
расстановке оборудования и при размещении элементов на интегральных схемах. В
частности, КЗН была применена при проектировании клавиатур пишущих
машинок. Стоит отметить, что КЗН является обобщением многих известных задач
оптимизации.
Например,
максимальной
клики.
задачи
Именно
коммивояжёра
поэтому
или
исследование
задачи
данной
нахождения
проблемы
представляет интерес с математической точки зрения.
Изучением прикладных и теоретических аспектов КЗН занимались многие
исследователи на протяжении более пяти десятилетий. Однако до сих пор не
существует точного алгоритма, решающего задачу в общем случае и за
полиномиальное время. Для нахождения приближенного решения КЗН широко
применяются эвристические алгоритмы: муравьиный алгоритм (ant colony
optimization) [10], генетический алгоритм (genetic algorithm) [12], алгоритм поиска
с запретами (tabu search algorithm) [14], алгоритм имитации отжига (simulated
annealing technique) [13] и ряд других подходов. Метод ветвей и границ (branch and
bound method) [13], относящийся к точным методам решения КЗН, используется
крайне редко. Применение метода ветвей и границ к задачам с числом объектов
более двадцати не дает получение точного решения за приемлемое время.
Существует немало точных подходов, решающих КЗН не в общем случае, а для
4
сетей со специальной структурой. Например, полиномиальные алгоритмы,
предложенные Г. Г. Забудским и А. Ю. Лагздиным для решения КЗН [3]. Интерес
представляет разработка полиномиальных алгоритмов решения КЗН в новых
частных случаях.
Цель выпускной квалификационной работы – изучение некоторых полиномиально
разрешимых случаев КЗН и реализация соответствующих алгоритмов.
Программный язык разработки – Python.
В целом исследование сфокусировано на следующих случаях:
 размещение невзвешенной цепи на взвешенном дереве произвольной
структуры
 размещение взвешенного графа произвольной структуры на взвешенной
звезде
 размещение взвешенной
звезды на взвешенной
сети
произвольной
структуры.
Для достижения поставленной цели необходимо решить следующие задачи:
 изучить общую математическую формулировку КЗН
 проанализировать существующие подходы к решению данной проблемы
 изучить полиномиальные алгоритмы для трех подзадач общей КЗН из
работы [3]
 реализовать полиномиальные алгоритмы их решения
 провести
необходимые
тестовые
эксперименты
для
демонстрации
производительности реализованных алгоритмов.
Методы исследования, обоснованность научных положений, результатов и
выводов, содержащихся в данной работе, основываются на фундаментальных
5
положениях теории графов, математического моделирования, целочисленного и
динамического программирования.
Основные результаты работы заключаются в следующем: изучена КЗН в теоретикографовой постановке, рассмотрены и проанализированы существующие подходы к
решению проблемы, исследованы три полиномиально-разрешимых случая КЗН,
разработаны и реализованы точные полиномиальные алгоритмы для них,
проведены
экспериментальные
исследования
точности
и
эффективности
разработанных алгоритмов.
Структура и объем работы:
Квалификационная работа состоит из введения, трех глав, заключения и списка
литературы. Объем работы – 40 страниц.
6
1
Математическая постановка задачи и обзор существующих подходов к ее
решению
1.1 Изначальная матричная постановка КЗН
В 1957 году Т. Ч. Купманс и М. А. Бекманн сформулировали КЗН в общем случае с
помощью трех матриц: матрицы стоимостей связей А, матрицы расстояний между
позициями B и матрицы стоимости размещений C.
𝐴 = (𝑎𝑖𝑘 ), где 𝑎𝑖𝑘 – стоимость связи между объектами i и k
𝐵 = (𝑏𝑗𝑙 ), где 𝑏𝑗𝑙 – расстояние между позициями j и l
𝐶 = (𝑐𝑖𝑗 ), где 𝑐𝑖𝑗 – стоимость размещения объекта i в позицию j
𝑖, 𝑗, 𝑘, 𝑙 = 1, … , 𝑛
𝜋 – это подстановка на множестве {1, … , 𝑛}
𝑃𝑛 – это множество всех подстановок на множестве {1, … , 𝑛}
Целевая функция F в КЗН имеет следующий вид:
𝑛
𝑛
𝑛
𝐹 = (∑ ∑ 𝑎𝑖𝑘 𝑏𝜋(𝑖)𝜋(𝑘) + ∑ 𝑐𝑖𝜋(𝑖) ) → 𝑚𝑖𝑛
𝑖=1 𝑘=1
𝑖=1
𝜋∈𝑃𝑛
Условие: в каждую позицию может быть размещен только один объект.
Часто в практических задачах элементы матрицы B удовлетворяют неравенству
треугольника 𝑏𝑗𝑙 + 𝑏𝑖𝑟 > 𝑏𝑗𝑟 , в таком случае задача является метрической
квадратичной задачей о назначениях.
Если стоит условие о минимизации максимальной стоимости связи между
объектами, то задача является КЗН с минимаксным критерием. Целевая функция в
таком случае, при отсутствии матрицы стоимости размещений C, имеет вид:
7
𝑚𝑎𝑥 𝑎𝑖𝑘 𝑏𝜋(𝑖)𝜋(𝑘) → 𝑚𝑖𝑛
𝑖,𝑘=1…𝑛
𝜋∈𝑃𝑛
Позднее было доказано что КЗН является NP-трудной для произвольных матриц. В
данной постановке задачи полиномиально-разрешимые случаи определяются
условиями на матрицы, при которых решением является заданная подстановка.
Такие случаи принято называть сильно разрешимыми. Например, для классов
аддитивно монотонных матриц и матриц анти-Монжа известны ограничения, при
которых гарантируется сильная разрешимость КЗН.
1.2 Постановка КЗН в терминах теории графов
Задан неориентированный взвешенный по ребрам граф G = (N, E), где N –
множество вершин, E – множество ребер. Граф G не имеет кратных ребер и петель.
Каждое ребро (𝑒𝑖 , 𝑒𝑗 ) ∈ 𝐸 имеет вес 𝑤(𝑒𝑖 , 𝑒𝑗 ) ≥ 0 . Вес ребра отражает удельную
стоимость связи.
Также задана взвешенная по ребрам сеть M = (V, U), где V – множество узлов, U –
множество дуг. У сети М отсутствуют кратные дуги и петли.
Любая дуга (𝑢𝑖 , 𝑢𝑗 ) ∈ 𝑈 имеет вес 𝑟(𝑢𝑖 , 𝑢𝑗 ) ≥ 0. Вес дуги является стоимостью
размещения объекта в позицию.
Считается, что количество вершин в графе G равно количеству узлов в сети M.
Размещением графа G на сети M называется взаимно однозначное отображение
𝜋: 𝑁 → 𝑉 . Отображение 𝜋 является подстановкой.
Целью является размещение вершин графа в узлы сети, по одной вершине в каждый
узел, таким образом, чтобы суммарная стоимость связей между вершинами графа
была минимальной.
Целевая функция F имеет следующий вид:
8
𝐹=
∑ (𝑤(𝑒𝑖 , 𝑒𝑗 ) × 𝑑(𝜋(𝑒𝑖 ), 𝜋(𝑒𝑗 ))) → 𝑚𝑖𝑛 (1.1)
𝜋
(𝑒𝑖 ,𝑒𝑗 )∈𝐸
Где 𝑑(𝜋(𝑒𝑖 ), 𝜋(𝑒𝑗 )) – это кратчайшее расстояние между узлами 𝜋(𝑒𝑖 ) и 𝜋(𝑒𝑗 ) в сети,
в которые размещены вершины 𝑛𝑖 и 𝑛𝑗 .
1.3 Обзор существующих подходов к решению КЗН
В этой части работы рассматриваются некоторые уже известные подходы к
решению КЗН в различных постановках. Анализ существующих методов полезен
при разработке новых алгоритмов.
Одним из точных подходов к решению КЗН является метод плетей и границ (plaits
and bounds method). Этот подход успешно применяется ко многим сложным задачам
комбинаторной оптимизации. Метод плетей и границ является обобщением хорошо
известного алгоритма ветвей и границ (branches and bounds algorithm),
предложенного Лендом и Дойгом в 1960 году. Основная используемая граница —
это граница Гилмора-Лоулера. В отличие от алгоритма ветвей и границ
параметрами в методе плетей и границ являются не только выбор способа
оценивания и тактики ветвления, но и способа формирования недревовидных
покрытий. Преимуществом метода плетей и границ является тот факт, что при
попадании ветвей, содержащих частные решения, в одну плеть, большой класс
неперспективных решений отсекается за одну итерацию (одно оценивание). Метод
плетей и границ широко представлен в работах А. В. Мартюшева. Однако данный
подход работает за приемлемое время только для задач с числом объектов не более
двадцати. В связи с этим метод плетей и границ почти не применим на практике.
Для эффективного и быстрого поиска приближенного решения часто используются
эвристические алгоритмы.
9
Одним из широко применимых эвристических алгоритмов является алгоритм
поиска с запретами (tabu search algorithm), предложенный Ф. Гловером в 1986 году,
как концептуально новая схема локального поиска. Ключевая особенность данного
подхода состоит в том, что алгоритм не завершает работу в точке локального
оптимума, как это делает стандартный алгоритм локального поиска, а продвигается
дальше в поисках глобального. Список запретов позволяет алгоритму выбраться из
одного локального оптимума и перейти к следующему. Стоит отметить, что
алгоритм поиска с запретами является достаточно быстрым и работает за
полиномиальное время. Применение данного подхода к решению КЗН по большей
части описывается в работах американской ученой Jadranka Skorin-Kapov [14].
На практике часто используется так называемый генетический алгоритм (genetic
algorithm). Джон Холланд в 1975 году стал первым, кто применил генетический
алгоритм для поиска решения КЗН. Стоит отметить, что данный подход основан на
эвристике. Суть работы генетического алгоритма заключается в случайном
подборе, комбинировании и вариации искомых параметров с использованием
механизмов, аналогичных механизмам живой природы, в частности процессу
естественного отбора. Например, множество строк матриц, которые кодируют
возможные решения, называется генотипом. Каждое полученное решение
называется существом. Алгоритм начинает работу с создания множества начальных
возможных решений, которые генерируются случайным образом или с помощью
некой эвристики. Генетический алгоритм относится к классу эволюционных
алгоритмов и работает за полиномиальное время. Однако он достаточно сложен в
реализации.
Значительное внимание уделяется изучению КЗН в терминах теории графов.
Разработано немало подходов и эффективных алгоритмов решения КЗН для
специальных структур связей между объектами и сетей.
10
Одним из подходов к решению КЗН в теоретико-графовой постановке является
замена исходной задачи на схожую задачу размещения двудольных графов. Задача
размещения двудольных графов является аналогом КЗН. Данный подход и
необходимые численные методы впервые были описаны Н. М. Метельским в 1984
году [4]. Суть подхода заключается в применении численных методов локальной
оптимизации к проблеме размещения двудольных графов, с целю нахождения
решения КЗН. Преимущество подхода заключается в том, что алгоритмы просты в
реализации и допускают распараллеливание вычислительного процесса. Однако,
численные методы локальной оптимизации дают лишь приближенное решение.
11
2
Описание алгоритмов, их теоретическое обоснование и оценки сложности
В данной главе предоставляется описание трех реализованных полиномиальных
алгоритмов:
1. Алгоритм
размещения
невзвешенной
цепи
на
взвешенном
дереве
произвольной структуры;
2. Алгоритм размещения взвешенного графа произвольной структуры на
взвешенной звезде;
3. Алгоритм размещения взвешенной звезды на взвешенной сети произвольной
структуры.
2.1 Описание первого алгоритма, теоретическое обоснование
Рассматривается задача размещения невзвешенной цепи C = (N, E) на заданной
взвешенной древовидной сети T = (V, U), где |N| = |V|. Суть алгоритма заключается
в построение маршрута, проходящего по всем узлам сети как минимум один раз,
причем суммарный вес входящих в этот маршрут дуг должен быть минимальным.
Программный код разработан на языке Python и представлен в Приложение №1.
Входные данные:
На вход алгоритму подается текстовый файл, с заданной сетью T. Сеть
представлена в виде списка ее дуг и соответствующих весов. Вершины цепи
последовательно пронумерованы числами, начиная с единицы. В качестве
древовидной сети было взято остовное дерево случайного графа, сгенерированного
по модели Эрдеша-Реньи.
Стоит отметить, что в модели Эрдеша-Реньи каждое ребро строящегося графа
проводится с определенной вероятностью р. Считается что потенциальных ребер у
графа с n вершинами не более чем 𝐶𝑛2 штук. Любые две вершины соединяются
12
ребром с некоторой вероятностью 𝑝 ∈ [0,1], независимо от всех остальных 𝐶𝑛2 − 1
пар. Таким образом ребра в графе появляются в соответствии со стандартной
схемой Бернулли, в которой 𝐶𝑛2 испытаний и вероятность успеха равна р.
Шаг I:
Находим степень каждого узла из сети, т.е. 𝑓𝑜𝑟 ∀ 𝑣𝑖 ∈ 𝑉 находим 𝑑(𝑣𝑖 ).
Затем в сети T = (V, U) выделяем цепь С∗ → (𝑣𝑖1 , 𝑣𝑖2 … 𝑣𝑖𝑘 ) максимальной длинный,
т.е. 𝑝(𝑣𝑖1 , 𝑣𝑖𝑘 ) = max 𝑝(𝑣𝑖 , 𝑣𝑗 ). Для этого рассматриваются все простые пути,
𝑣𝑖 ,𝑣𝑗 ∈𝑉
между каждой парой узлов, чья степень равняется единице. Из рассмотренных
путей выбирается путь максимальный по суммарному весу, входящих в него дуг и
длине.
Шаг II:
Каждому узлу 𝑣𝑖1 , 𝑣𝑖2 … 𝑣𝑖𝑘 из найденной цепи С∗ = (𝑉 ∗ , 𝑈 ∗ ) сопоставляем
поддерево 𝑇𝑖∗ = (𝑉𝑖∗ , 𝑈𝑖∗ ). Таким образом, что множество 𝑉𝑖∗ состоит из 𝑣𝑖1 , 𝑣𝑖2 … 𝑣𝑖𝑘
и всех тех узлов дерева T, которые соединены с 𝑣𝑖1 , 𝑣𝑖2 … 𝑣𝑖𝑘 цепями, не
содержащими дуг из 𝑈 ∗ . В то время как множество 𝑈𝑖∗ образовано дугами таких
цепей.
Шаг III:
На данном шаге алгоритм будет производить построение некоторого размещения
𝜋 ∗ . Стоит отметить, что для удобства реализации 𝜋 ∗ можно представить в виде
словаря, где ключами являются последовательные числа – номера вершин в
заданной цепи C = (N, E), а значениями ключей будут являться узлы сети T. Таким
образом будет построено размещение цепи C на древовидной сети T.
Начинаем последовательно рассматриваются узлы выделенной цепи С∗ :
13
𝑐𝑜𝑢𝑛𝑡 = вычисляется как первый встретившийся незаполненный ключ словаря
𝜋 ∗ минус единица; на первой итерации естественно получается равным нулю
𝑓𝑜𝑟 ∀ 𝑣𝑖𝑗 ∈ 𝑉 ∗
𝑖𝑓 𝑑 (𝑣𝑖𝑗 ) ≤ 2
𝑘𝑒𝑦 = 𝑐𝑜𝑢𝑛𝑡 + 1
𝜋 ∗ (𝑘𝑒𝑦) = 𝑣𝑖𝑗
𝑐𝑜𝑢𝑛𝑡 = 𝑘𝑒𝑦
𝑒𝑙𝑠𝑒
𝑘𝑒𝑦 = 𝑐𝑜𝑢𝑛𝑡 + |𝑉𝑖∗ |
на втором шаге алгоритма каждому узлу ставилось в соответствие поддерево
𝑇𝑖∗ = (𝑉𝑖∗ , 𝑈𝑖∗ ), отсюда и берется |𝑉𝑖∗ | как мощность множества узлов,
принадлежащее конкретному поддереву рассматриваемой сейчас вершины 𝑣𝑖𝑗
𝜋 ∗ (𝑘𝑒𝑦) = 𝑣𝑖𝑗
𝑐𝑜𝑢𝑛𝑡 = 𝑘𝑒𝑦
Для размещения еще нерассмотренных узлов сети T, которые не попали в
выделенную цепь С∗ , применяется редуцированный вариант данного алгоритма для
поддеревьев. В связи с тем, что эти нерассмотренные узлы содержатся в
выделенных на втором шаге поддеревьях.
Шаг IV:
Считаем целевую функцию F, обозначенную в постановке задачи. Для этого в
полученном размещение 𝜋 ∗ , а именно среди значений ключей, для каждой пары
узлов ищем суммарный вес кратчайшего пути между этими узлами. Разбиение
узлов
на
пары
организовано
следующим
образом:
(1,2); (2,3); … (𝑞 −
1, 𝑞); (𝑞, 𝑞 + 1), где q – индекс элемента в полученном размещение 𝜋 ∗ . Затем
14
суммируем веса найденный для каждой пары, таким образом считаем целевую
функцию.
Теоретическое обоснование оптимальности найденного решения:
Утверждение 2.1
Разработанный алгоритм находит оптимальное решение задачи размещения
невзвешенной цепи на взвешенном дереве произвольной структуры.
Доказательство:
Поскольку заданная цепь является невзвешенной, полагаем что вес каждого ребра
равен единице. Пускай 𝜋 является некоторым размещением цепи С на сети Т. Тогда
цепь С∗ (𝜋) = (𝑉 ∗ (𝜋), 𝑈 ∗ (𝜋)), выделенная в сети Т, называется главной если ее
концевые
узлы
суть
𝜋(1) и 𝜋(𝑛), где 𝑛 − это общее число узлов
сети
Т.
Аналогично по описанному выше способу сопоставим каждому узлу главной цепи
поддерево. Целевую функцию F можно представить в виде суммы весов дуг сети Т
с неотрицательными целыми коэффициентами:
𝐹(𝜋) = ∑(𝜋(𝑖),𝜋(𝑗))∈𝑈 𝛼𝑖𝑗 (𝜋)𝑟(𝜋(𝑖), 𝜋(𝑗)), где 𝛼𝑖𝑗 (𝜋) ∈ 𝑍 + .
Стоит отметить что согласно построению в размещение 𝜋 ∗ коэффициенты 𝛼𝑖𝑗 = 1
для всех дуг (𝜋 ∗ (𝑖), 𝜋 ∗ (𝑗)) ∈ 𝑈 ∗ (𝜋 ∗ ) и 𝛼𝑠𝑡 = 2 для всех дуг (𝜋 ∗ (𝑠), 𝜋 ∗ (𝑡)) ∈
𝑈 𝑙 (𝜋 ∗ ), где 𝑙 = 1,2, … , 𝑝.
Любая произвольная дуга (𝜋(𝑖), 𝜋(𝑗)) ∈ 𝑈 разбивает множество узлов V на два
подмножества:
𝐴𝑖𝑗 (𝜋) = {𝜋(𝑘) ∈ 𝑉|𝜋(𝑘) соед. с 𝜋(𝑖) цепью, не содержащей этой дуги} ∪ {𝜋(𝑖)},
𝐴∗𝑖𝑗 (𝜋) = {𝜋(𝑘) ∈ 𝑉|𝜋(𝑘) соед. с 𝜋(𝑗) цепью, не содержащей этой дуги} ∪ {𝜋(𝑗)}.
15
Также стоит заметить что для ∀ дуги (𝜋(𝑖), 𝜋(𝑗)) ∈ произвольному поддереву
𝑇 𝑙 (𝜋) выполняется неравенство 𝛼𝑖𝑗 (𝜋) ≥ 2.
Доказательство данного утверждения в основном базируется на двух леммах,
которые имеют место быть.
Лемма 2.1
Для нахождения оптимального размещения 𝜋 невзвешенной цепи на взвешенной
сети древовидной структуры имеют место следующие равенства 𝛼𝑖𝑗 (𝜋) = 1 для ∀
дуги (𝜋(𝑖), 𝜋(𝑗)) ∈ 𝑉 ∗ (𝜋) и 𝛼𝑠𝑡 (𝜋) = 2 для произвольной дуги (𝜋(𝑠), 𝜋(𝑡)) ∈
поддереву 𝑇 𝑙 (𝜋), где 𝑙 = 1,2, … , 𝑝.
Доказательство Леммы 2.1:
В случае если 𝛼𝑖𝑗 (𝜋) > 1 для некоторой дуги (𝜋(𝑖), 𝜋(𝑗)) ∈ 𝑉 ∗ (𝜋) тогда очевидно
что нумерация цепи 𝐶 ∗ (𝜋) не будет монотонной и соответственно найденное
размещение 𝜋 не будет оптимальным.
Известно, что 𝛼𝑝𝑞 (𝜋) ≥ 2 для всех дуг (𝜋(𝑝), 𝜋(𝑞)) принадлежащих поддеревьям.
Пусть 𝛼𝑠𝑡 (𝜋) > 2 в некотором поддереве 𝑇𝑙 (𝜋) для дуги (𝜋(𝑠), 𝜋(𝑡)) ∈ 𝑉𝑙 (𝜋).
Согласно алгоритму выбираем цепь 𝐶 ∗ (𝜋) и строим новое размещение 𝜋 ∗ . По
построению 𝐶 ∗ (𝜋) = 𝐶 ∗ (𝜋 ∗ ) и 𝛼𝑖𝑗 (𝜋 ∗ ) = 1 для всех дуг (𝜋 ∗ (𝑖), 𝜋 ∗ (𝑗)) ∈ 𝑉 ∗ (𝜋) и
𝛼𝑠𝑡 (𝜋 ∗ ) = 2 для всех дуг (𝜋 ∗ (𝑠), 𝜋 ∗ (𝑡)) ∈ 𝑉𝑙 (𝜋), 𝑙 = 1,2, … , 𝑝. Следовательно 𝐹(𝜋) >
𝐹(𝜋 ∗ ), а это противоречит оптимальности 𝜋. Лемма доказана.
Лемма 2.2
Среди всех размещений невзвешенной цепи на С на взвешенной сети Т
древовидной структуры, для которых 𝛼𝑖𝑗 (𝜋) = 1 для дуг (𝜋(𝑖), 𝜋(𝑗)) ∈ 𝑉 ∗ (𝜋) и
𝛼𝑠𝑡 (𝜋) = 2 для дуг
(𝜋(𝑠), 𝜋(𝑡)) ∈ 𝑉 𝑙 (𝜋), 𝑙 = 1,2, … , 𝑝 оптимальным является
размещение в котором суммарный вес дуг главной цепи является наибольшим.
16
Доказательство Леммы 2.2:
Будем рассматривать оптимальное размещение 𝜋 ∗ невзвешенной цепи С на сети
древовидной структуры Т. По лемме 2.1 для ∀ дуги (𝜋 ∗ (𝑖), 𝜋 ∗ (𝑗)) ∈ 𝑉 ∗ (𝜋 ∗ )
выполняется 𝛼𝑖𝑗 (𝜋 ∗ ) = 1, а для ∀ дуги (𝜋(𝑠), 𝜋(𝑡)) ∈ 𝑉𝑙 (𝜋 ∗ ) верно равенство
𝛼𝑠𝑡 (𝜋 ∗ ) = 2. Обозначим через {𝑢𝑖 } множество дуг главной цепи 𝐶 ∗ (𝜋 ∗ ), {𝑔𝑗 } –
множество дуг поддеревьев 𝑇ℎ (𝜋 ∗ ), ℎ = 1,2, … , 𝑝. Очевидно {𝑢𝑖 } ∪ {𝑔𝑗 } = 𝑈. Через r
обозначим вес дуги 𝑢 ∈ 𝑈. По лемме 2.1 имеем: 𝐹(𝜋 ∗ ) = ∑𝑖∈𝐼 𝑟(𝑢𝑖 ) + 2 ∑𝑗∈𝐽 𝑟(𝑔𝑗 ).
Пусть ∃ размещение 𝜋 ′ сети С на сети Т такое, что: 𝐹(𝜋 ′ ) = ∑𝑘∈𝐾 𝑟(𝑐𝑘 ) +
2 ∑𝑙∈𝐿 𝑟(𝑒𝑙 ), причем ∑𝑘∈𝐾 𝑟(𝑐𝑘 ) > ∑𝑖∈𝐼 𝑟(𝑢𝑖 ) и 𝐹(𝜋 ′ ) > 𝐹(𝜋 ∗ ), 𝑐𝑘 – множество дуг
главной
цепи
𝐶 ∗ (𝜋 ′ ),
а
𝑒𝑙
–
множество
дуг
поддеревьев
𝑇ℎ (𝜋 ′ ), ℎ =
1,2, … , 𝑝 и {𝑐𝑘 } ∪ {𝑒𝑙 } = 𝑈. Очевидно, что можно представить ∑𝑘∈𝐾 𝑟(𝑐𝑘 ) и
∑𝑙∈𝐿 𝑟(𝑒𝑙 )
в
виде
∑𝑘∈𝐾 𝑟(𝑐𝑘 ) = ∑𝑖1∈𝐼1 𝑟(𝑢𝑖1 ) + ∑𝑗1∈𝐽1 𝑟(𝑔𝑗1 ),
∑𝑙∈𝐿 𝑟(𝑒𝑙 ) =
∑𝑖2∈𝐼2 𝑟(𝑢𝑖2 ) + ∑𝑗2∈𝐽2 𝑟(𝑔𝑗2 ), где 𝐼1 , 𝐼2 ∈ 𝐼; 𝐽1 , 𝐽2 ∈ 𝐽; 𝐼1 ∪ 𝐼2 = 𝐼; 𝐽1 , 𝐽2 ∈ 𝐽. При
этом:
∑𝑖∈𝐼 𝑟(𝑢𝑖 ) =
∑𝑖1∈𝐼1 𝑟(𝑢𝑖1 ) + ∑𝑖2∈𝐼2 𝑟(𝑢𝑖2 ),
∑𝑗∈𝐽 𝑟(𝑔𝑗 ) = ∑𝑗1∈𝐽1 𝑟(𝑔𝑗1 ) +
∑𝑗2∈𝐽2 𝑟(𝑔𝑗2 ). Так как 𝐹(𝜋 ′ ) > 𝐹(𝜋 ∗ ), то
[ ∑ 𝑟(𝑢𝑖1 ) + ∑ 𝑟(𝑔𝑗1 )] + 2 [ ∑ 𝑟(𝑢𝑖2 ) + ∑ 𝑟(𝑔𝑗2 )] >
𝑖1 ∈𝐼1
𝑗1 ∈𝐽1
𝑖2 ∈𝐼2
𝑗2 ∈𝐽2
> [ ∑ 𝑟(𝑢𝑖1 ) + ∑ 𝑟(𝑢𝑖2 )] + 2 [ ∑ 𝑟(𝑔𝑗1 ) + ∑ 𝑟(𝑔𝑗2 )].
𝑖1 ∈𝐼1
𝑖2 ∈𝐼2
𝑗1 ∈𝐽1
𝑗2 ∈𝐽2
Из этого следует что ∑𝑖2∈𝐼2 𝑟(𝑢𝑖2 ) > ∑𝑗1∈𝐽1 𝑟(𝑔𝑗1 ).
По предположению что ∑𝑘∈𝐾 𝑟(𝑐𝑘 ) > ∑𝑖∈𝐼 𝑟(𝑢𝑖 ) получаем
∑𝑖1∈𝐼1 𝑟(𝑢𝑖1 ) + ∑𝑗1∈𝐽1 𝑟(𝑔𝑗1 ) > ∑𝑖1∈𝐼1 𝑟(𝑢𝑖1 ) + ∑𝑖2∈𝐼2 𝑟(𝑢𝑖2 ) и следовательно
17
∑𝑗1∈𝐽1 𝑟(𝑔𝑗1 ) > ∑𝑖2∈𝐼2 𝑟(𝑢𝑖2 ), что является противоречием. Таким образом для
размещения 𝜋 ∗ суммарный вес главной цепи максимален. Лемма доказана.
Так как на первом шаге алгоритм выбирает цепь максимальной длинны,
построенное размещение удовлетворяет условиям леммы 2.2 и, следовательно,
является оптимальным. Утверждение является доказанным.
2.2 Описание второго алгоритма, теоретическое обоснование
Второй алгоритм предназначен для размещения взвешенного графа L = (N, E)
произвольной структуры на взвешенной звезде S = (V, U), причем |N| = |V|.
Стоит напомнить, что звездой называется граф, у которого степень одной из вершин
на единицу меньше общего числа вершин в графе, а степени остальных равняются
единице.
Основная идея алгоритма заключается в нахождение медианы у графа L и
размещение ее в центр звезды S. Оставшиеся вершины размещаются произвольным
образом. Медианой графа называется вершина, сумма кратчайших расстояний от
которой до всех других минимальна.
Программный код разработан на языке Python и представлен в Приложение №2.
Входные данные:
На вход алгоритм принимает текстовый файл, в котором граф и звезда заданы
матрицами смежности. Однако, в матрицах на пересечении двух смежных вершин
указан вес ребра, соединяющего эти вершины. Указание веса необходимо т.к. граф
и звезда являются взвешенными. Стоит отметить, что граф L генерируется по
модели Эрдеша-Реньи и является случайным графом. Звезда S получается
следующим образом: генерируется полный граф без петель и кратных ребер, в нем
18
случайным образом выбирается любая вершина, все ребра который сохраняются, а
ребра остальных вершин подлежат удалению.
Шаг I:
Необходимо упорядочить вершины графа L по не возрастанию их суммарной
стоимости связей со смежными вершинами. Для этого получаем сумму каждой
строки в матрице, задающей граф. Затем, зная сумму и номер строки,
соответствующий номеру вершины, упорядочиваем сами вершины.
Z – вектор индексов-номеров вершин, получившийся в процессе упорядочивания.
𝑍 = (𝑛1 , 𝑛2 , … , 𝑛𝑁 ).
Х – упорядоченный вектор суммарных стоимостей связей каждой вершины графа
со смежными.
𝑋(𝑛𝑖 ) = ∑𝑖,𝑗=1…𝑁 𝑤(𝑛𝑖 , 𝑛𝑗 )
Нумерация вершин графа такова: 𝑋(𝑛1 ) ≥ 𝑋(𝑛2 ) ≥ ⋯ ≥ 𝑋(𝑛𝑁 ).
Шаг II:
На этом шаге алгоритма происходит упорядочивание узлов звезды S по не
убыванию расстояний от центра. Для этого в матрице, задающей звезду, находим
строку, в которой только один элемент равен нулю. Элементы строки
упорядочиваем в порядке не убывания, сохраняя индекс каждого элемента.
W – вектор индексов-номеров узлов, получившийся в процессе упорядочивания.
𝑊 = (𝑣1 , 𝑣2 , … , 𝑣𝑁 ).
Y – упорядоченный вектор расстояний между узлами звезды.
19
Шаг III:
Находим размещение 𝜋 взвешенного графа произвольной структуры на взвешенной
звезде. Полагаем 𝜋(𝑛1 ) = 𝑣1 , 𝜋(𝑛2 ) = 𝑣2 , … , 𝜋(𝑛𝑁 ) = 𝑣𝑁 для ∀𝑛𝑖 ∈ 𝑍, ∀𝑣𝑗 ∈ 𝑊.
При реализации алгоритма размещение 𝜋 удобнее всего представлять в виде
словаря, где ключами являются элементы вектора Z, а значениями ключей являются
элементы вектора W.
Шаг IV:
Находим целевую функцию F, обозначенную в постановке задачи.
Целевая функция равняется скалярному произведению двух векторов X и Y:
𝐹 = (𝑋, 𝑌).
Теоретическое обоснование оптимальности найденного решения:
Утверждение 2.2
Разработанный алгоритм находит оптимальное решение задачи размещения
взвешенного графа произвольной структуры на взвешенной звезде.
Доказательство:
Пусть 𝜋 – это некоторое размещение графа на звезде, Y – упорядоченный вектор
расстояний между узлами звезды, и Х – упорядоченный вектор суммарных
стоимостей связей каждой вершины графа со смежными. И пусть узел 𝑣1 – это
центр звезды.
Тогда справедливы следующие равенства:
𝐹(𝜋) = ∑𝑣𝑗 ∑𝑛𝑖 𝑤 (𝑛𝑖 , 𝜋 −1 (𝑣𝑗 )) 𝑑(𝑣𝑗 , 𝑣1 ) = ∑𝑣𝑗 𝑑(𝑣𝑗 , 𝑣1 ) ∑𝑛𝑖 𝑤 (𝑛𝑖 , 𝜋 −1 (𝑣𝑗 )) =
∑𝑣𝑗 𝑑(𝑣𝑗 , 𝑣1 )𝑋 (𝜋 −1 (𝑣𝑗 )) = (𝑋, 𝑌), где (𝑋, 𝑌) – скалярное произведение векторов.
20
В таком случае для минимизации функции 𝐹(𝜋) необходимо вектор Y упорядочить
в порядке не убывания, а вектор X в порядке не возрастания.
2.3 Описание третьего алгоритма, теоретическое обоснование
Третий алгоритм решает задачу размещения взвешенной звезды S = (N, E) на
взвешенной сети M = (V, U), имеющей произвольную структуру. Причем |N| = |V|.
Сущность алгоритма заключается в нахождение медианы сети М, и размещение
центра звезды S в найденную медиану. Остальные вершины размещаются
произвольным образом.
Программный код разработан на языке Python и представлен в Приложение №3.
Входные данные:
На вход подается текстовый файл, в котором сеть и звезда заданы матрицами
смежности. На пересечение смежных вершин указываем вес ребра. Сеть
генерируется по модели Эрдеша-Реньи. Звезда же генерируется аналогичным
образом, описанным во втором алгоритме.
Шаг I:
Находим
с
помощью
алгоритма Флойда-Уоршелла матрицу кратчайших
расстояний между всеми парами узлов сети М. Получившаяся матрица должна
иметь N строк и N-1 столбец, т.к. нулевые диагональные элементы не учитываются.
N – это число узлов в сети.
Шаг II:
Элементы каждой строки полученной матрицы упорядочиваются по не убыванию.
В итоге получается новая матрица 𝐾 = (𝑘𝑖𝑗 ), где 𝑖 = 1, … , 𝑁;
𝑗 = 1, … , 𝑁 − 1.
21
Шаг III:
Упорядочиваем вершины звезды S по не возрастанию расстояний от центра. Для
этого в матрице, задающей звезду, находим строку, в которой только один элемент
равен нулю. Элементы строки упорядочиваем в порядке не возрастания, сохраняя
индекс каждого элемента.
P – вектор индексов-номеров вершин, получившийся в процессе упорядочивания.
𝑃 = (𝑛1 , 𝑛2 , … , 𝑛𝑁 ).
Q – упорядоченный вектор расстояний между вершинами звезды.
Шаг IV:
Находим наименьшее покомпонентное произведение каждой из строк матрицы K
на упорядоченный вектор расстояний Q между вершинами звезды. Допустим
минимальное
покомпонентное
произведение
достигается
в
строке,
соответствующей узлу 𝑣1 , причем столбцы в этой строке соответствуют узлам
𝑣2 , … , 𝑣𝑁 .
Шаг V:
Находим размещение 𝜋 взвешенной звезды на взвешенной сети. Полагаем 𝜋(𝑛1 ) =
𝑣1 , 𝜋(𝑛2 ) = 𝑣2 , … , 𝜋(𝑛𝑁 ) = 𝑣𝑁 для ∀𝑛𝑖 ∈ 𝑃, ∀𝑣𝑗 ∈ 𝑉. Размещение 𝜋 удобнее всего
представлять в виде словаря, где ключами являются элементы вектора P, а
значениями ключей являются элементы из множества V. Если бы минимальное
покомпонентное произведение достигалось в строке, соответствующей например
узлу 𝑣3 , то при нахождение размещения полагалось бы 𝜋(𝑛1 ) = 𝑣3 , 𝜋(𝑛2 ) =
𝑣1 , 𝜋(𝑛3 ) = 𝑣2 , 𝜋(𝑛4 ) = 𝑣4 , … , 𝜋(𝑛𝑁 ) = 𝑣𝑁 .
22
Шаг VI:
Целевая функция F, обозначенная в постановке задачи, равняется уже найденному
наименьшему покомпонентному произведению.
Теоретическое обоснование оптимальности найденного решения:
Доказательство оптимальности найденного решения аналогично доказательству,
приведенному в описание второго алгоритма, и также основывается на свойстве
минимума скалярного произведения векторов.
2.4 Оценки сложности
Как уже было отмечено, что во всех трех рассмотренных случаях КЗН решается за
полиномиальное время с помощью разработанных алгоритмов.
Утверждение 2.3
КЗН в случае размещения невзвешенной цепи на заданной взвешенной
древовидной сети разрешима за 𝑂(𝑛3 ) операций, где n – это число узлов в сети,
эквивалентное числу вершин в цепи.
Доказательство:
На первом шаге за линейное время находятся степени всех узлов, затем выбирается
цепь максимальной длины, трудоемкость данной операции составляет 𝑂(𝑛3 ). Далее
на втором и третьем шагах происходит выделение поддеревьев и последовательное
размещение вершин цепи в узлы дерева, трудоемкость ля этих двух шагов
эквивалентна 𝑂(𝑛) операций. Таким образом, общая трудоемкость алгоритма не
превосходит 𝑂(𝑛3 ), т.к. 𝑂(𝑛3 + 𝑛) ~ 𝑂(𝑛3 ).
23
Утверждение 2.4
КЗН в случае размещения взвешенного графа произвольной структуры на
взвешенной звезде разрешима за 𝑂(𝑛2 ) операций, где n – это число узлов в звезде,
эквивалентное числу вершин в графе.
Доказательство:
Трудоемкость
разработанного
алгоритма
определяется
затратами
на
упорядочивание двух n-мерных массивов и затратами на вычисление суммарного
веса инцидентных дуг для каждого узла. Упорядочивание массива выполняется за
𝑂(𝑛) операций. Таким образом трудоемкость всего алгоритма не превосходит
𝑂(𝑛2 ), т.к. 𝑂(𝑛 × 𝑛) ~ 𝑂(𝑛2 ).
Утверждение 2.5
КЗН в случае размещения взвешенной звезды на взвешенной сети разрешима за
𝑂(𝑛3 ) операций, где n – это число вершин в звезде, эквивалентное числу узлов в
сети.
Доказательство:
Трудоемкость алгоритма определяется количеством операций, необходимых для
построения матрицы кратчайших расстояний и упорядочивания строк матрицы К.
Известно, что алгоритм Флойда-Уоршелла имеет кубическую сложность, т.е.
выполняется за 𝑂(𝑛3 ) операций. Упорядочивание строк матрицы К происходит за
𝑂(𝑛2 log 𝑛) операций. Поэтому общая трудоемкость алгоритма не превосходит
𝑂(𝑛3 ) операций, т.к. 𝑂(𝑛3 + 𝑛2 log 𝑛) ~ 𝑂(𝑛3 ).
24
3
Вычислительные эксперименты
Представляется
целесообразным
проведение
двух
типов
вычислительных
экспериментов для рассмотренных алгоритмов:
1. Tест на точность;
2. Тест на производительность.
Цели:
1. Убедиться, что на тестовых примерах все три алгоритма работают корректно
и действительно находят оптимальные решения задач;
2. Убедиться, что на тестовых примерах алгоритмы дают заявленное время
работы.
Описания экспериментов:
1. Данный тест проводится на сетях небольшого размера (8 или 10 узлов). Число
узлов остается строго зафиксированным.
2. В ходе эксперимента измеряется время работы алгоритмов (в секундах).
Число узлов в сети не фиксировано и увеличивается на 50 с каждым шагом.
Тестирование начинается с сетей по 10 узлов. Результатами экспериментов
являются графики зависимости времени работы алгоритмов от числа узлов в
сетях.
3.1 Результаты экспериментов для первого алгоритма
Первый алгоритм решает задачу размещения невзвешенной цепи на взвешенной
сети древовидной структуры. Заявленная оценка сложности 𝑂(𝑛3 ) операций, где n
– число узлов в сети, эквивалентное числу вершин в цепи.
Тест на точность:
25
Рис. 3.1 Визуализация невзвешенной цепи и взвешенной сети древовидной структуры
Оптимальное размещение и целевая функция, найденные алгоритмом:
Тест на производительность:
Таблица 1 Результаты теста на производительность для первого алгоритма
Число
10
50
100
150
200
250
300
350
400
450
0.001
0.018
0.159
0.555
1.4
3.647
5.691
11.681
18.902
30.325
500
550
600
650
700
750
800
850
900
950
1000
45.126
64.54
89.828
123.765
152.961
200.069
247.127
312.106
391.263
428.894
598
вершин
(узлов)
Время в
секундах
Число
вершин
(узлов)
Время в
секундах
26
Рис. 3.2 График зависимости времени работы первого алгоритма от числа узлов в сети
3.2 Результаты экспериментов для второго алгоритма
Второй алгоритм решает задачу размещения взвешенного графа произвольной
структуры на взвешенной звезде. Заявленная оценка сложности 𝑂(𝑛2 ) операций,
где n – это число узлов в звезде, эквивалентное числу вершин в графе.
Тест на точность:
Рис. 3.3 Визуализация взвешенного графа произвольной структуры и взвешенной звезды
Оптимальное размещение и целевая функция, найденные алгоритмом:
27
Тест на производительность:
Таблица 2 Результаты теста на производительность для второго алгоритма
Число
10
50
100
150
200
250
300
350
400
450
500
0
0.002
0.005
0.011
0.017
0.02
0.023
0.043
0.072
0.094
0.1
550
600
650
700
750
800
850
900
950
1000
1050
0.099
0.158
0.148
0.254
0.222
0.264
0.276
0.325
0.311
0.342
0.334
1100
1150
1200
1250
1300
1350
1400
1450
1500
1550
1600
0.354
0.385
0.423
0.476
0.526
0.701
0.767
0.8
0.899
0.873
0.9
1650
1700
1750
1800
1850
1900
1950
2000
1.04
1.326
1.3
1.321
1.393
1.5
1.642
1.7
вершин
(узлов)
Время в
секундах
Число
вершин
(узлов)
Время в
секундах
Число
вершин
(узлов)
Время в
секундах
Число
вершин
(узлов)
Время в
секундах
28
Рис. 3.4 График зависимости времени работы второго алгоритма от числа узлов в звезде
3.3 Результаты экспериментов для третьего алгоритма
Третий алгоритм решает задачу размещения взвешенной звезды на взвешенной
сети произвольной структуры. Заявленная оценка сложности 𝑂(𝑛3 ) операций, где
n – это число вершин в звезде, эквивалентное числу узлов в сети.
Тест на точность:
Рис. 3.5 Визуализация взвешенной звезды и взвешенной сети произвольной структуры
29
Оптимальное размещение и целевая функция, найденные алгоритмом:
Тест на производительность:
Таблица 3 Результаты теста на производительность для третьего алгоритма
Число
10
50
100
150
200
250
300
350
400
450
0.002
0.021
0.159
0.343
1.232
2.42
4.78
6.973
10.005
15.695
500
550
600
650
700
750
800
850
900
950
1000
22.095
25.765
35.12
52.473
63.56
83.423
103.78
145.675
167.87
199.33
217.576
вершин
(узлов)
Время в
секундах
Число
вершин
(узлов)
Время в
секундах
Рис. 3.6 График зависимости времени работы третьего алгоритма от числа узлов в сети
30
Заключение
В данной работе в графовой постановке была рассмотрена квадратичная задача о
назначениях (КЗН), принадлежащая к классу NP-трудных задач. Рассматривались
три эффективно разрешимых случая КЗН из работы Г. Г. Забудского и А. Ю.
Лагздина [3], а именно:
 размещение невзвешенной цепи на взвешенном дереве произвольной
структуры
 размещение взвешенного графа произвольной структуры на взвешенной
звезде
 размещение
взвешенной
звезды на взвешенной
сети
произвольной
структуры.
В рамках выполнения работы были подправлены алгоритмы из [3], приведено более
подробное их изложение. На языке Python впервые написаны реализации этих
алгоритмов. Были проведены вычислительные эксперименты, подтвердившие на
тестовых данных правильность работы алгоритмов и соответствие времени работы
заявленным верхним оценками сложности.
Перспектива развития данной темы состоит в изучение других полиномиально
разрешимых случаев КЗН в разных областях, а также в терминах теории графов.
31
Список литературы
1. Гэри М., Джонсон Д. Вычислительные машины и труднорешаемые задачи /
М. Гэри, Д. Джонсон. – М.: Мир, 1982. – 416 с.
2. Забудский Г. Г. О некоторых задачах размещения на графах / Г.Г. Забудский
// Тр. XI Байкальской междунар. школы семинара “Методы оптимизации и их
приложения”. Иркутск. – 1998. – С. 135–138.
3. Забудский Г. Г., Лагздин А. Ю. Полиномиальные алгоритмы решения
квадратичной задачи о назначениях на сетях / Г. Г. Забудский, А. Ю. Лагздин
// Ж. вычислительной математики и математической физики. – 2010. – №11.
– С. 252-259.
4. Метельский Н. Н. Методы локальной оптимизации для задачи размещения
двудольных графов / Н. Н. Метельский // Ж. вычислительной математики и
математической физики. – 1984. – №9. – С. 1428-1432.
5. Райгородский А. М. Модели случайных графов и их применение / А. М.
Райгородский // Ж. Труды МФТИ. – 2010. – №4. – С. 130-140.
6. Abeer M. M. A Comparative Study of Meta-heuristic Algorithms for Solving
Quadratic Assignment Problem / M. M. Abeer, A. A. Gamal, M. El-Sayed //
International Journal of Advanced Computer Science and Applications. – 2014. –
№1.
7. Anstreicher, K. M. Recent advances in the solution of quadratic assignment
problems / K. M. Anstreicher // Mathematical Programming Series. – 2003. – №97.
– P. 27-42.
8. Demidenko, V. M. Well solvable cases of the quadratic assignment problem with
monotone and bimonotone matrices / V. M. Demidenko, G. Finke, V. S. Gordon //
Modeling and Algorithms. – 2006. – №2. – P. 167-187.
9. Fleurent, C. Genetic hybrids for the quadratic assignment problem, in Quadratic
Assignment and Related Problems / C. Fleurent, J. Ferland // DIMACS Series in
32
Discrete Mathematics and Theoretical Computer Science. – 1994. – №16. – P. 173187.
10.Gambardella, L. M. Ant colonies for the quadratic assignment problem / L. M.
Gambardella, M. Dorigo // Journal of the operational research society. – 1999. –
№50. – P. 167-176.
11.Koopmans, T. C. Assignment problems and the location of economics activities /
T. C. Koopmans, M. Beckmann // Econometrics. – 1957. – №25. – P. 53-76.
12.Kratica, J. A new genetic representation for quadratic assignment problem / J.
Kratica // Yugoslav Journal of Operations Research. – 2011. – №2. – P. 225-238.
13.Pardalos P. M. The quadratic assignment problem / P. M. Pardalos, F. Rendl,
Wolkowicz // American Mathematical Society. – 1994. – №1. – P. 1-42.
14.Skorin-Kapov J. Tabu search applied to the quadratic assignment problem / J.
Skorin-Kapov // ORSA Journal on computing. – 1990. – №1. – P. 33-40.
33
Приложение №1
Исходный программный код для первого алгоритма
__author__ = 'Ksenia Voronaya'
# 1 algorithm
from collections import defaultdict
import itertools as it
try:
import networkx as nx
except ImportError:
raise ImportError("Please, install networkx package: pip install networkx")
INPUT_FILE = r"C:\Users\ksenia\alg_1\test_1.txt"
OUTPUT_FILE = r"C:\Users\ksenia\alg_1\ans_1.txt"
def parse_file(file_name):
for line in open(file_name):
u, v, w = [int(i) for i in line.strip().split()]
if not all((u, v, w)):
continue
yield u, v, w
def graph_processing(permutations, G):
degree = nx.degree(G)
c_0 = sorted([node for node, j in degree.iteritems() if j == 1])
weight, chain = (-1, list())
for u, v in it.combinations(c_0, 2):
weight_ = nx.dijkstra_path_length(G, source=u, target=v)
if weight_ < weight:
continue
chain_ = nx.dijkstra_path(G, source=u, target=v)
if (weight_ > weight) or len(chain_) > len(chain):
chain = chain_
weight = weight_
new_table = G.copy()
new_table.remove_nodes_from(n for n in G if n in chain)
weight = nx.get_edge_attributes(G, 'weight')
elist = {u: (u, v, weight.get((u, v), weight.get((v, u)))) for u, v in
nx.edge_boundary(G, chain)}
new_table.add_weighted_edges_from(elist.itervalues())
sub_trees = dict()
for tree_key in nx.connected_component_subgraphs(new_table):
for node in tree_key.nodes_iter():
if node in chain:
sub_trees[node] = tree_key
break
count = min([k for k, v in permutations.iteritems() if v is None]) - 1
visited_nodes = [v for k, v in permutations.iteritems() if v is not None]
34
for node in chain:
if node in visited_nodes:
continue
k = degree[node]
if k <= 2:
key = count + 1
permutations[key] = node
count = key
else:
key = count + sub_trees[node].number_of_nodes()
permutations[key] = node
count = key
return sub_trees
def main():
graph = defaultdict(dict)
for k, v, w in parse_file(INPUT_FILE):
graph[k].update({v: {'weight': w}})
G = nx.Graph(graph)
permutations = {node: None for node in nx.nodes_iter(G)}
trees = [G]
while trees:
tree = trees.pop()
new_trees = graph_processing(permutations, tree)
trees.extend([new_trees[i] for i in sorted(new_trees, reverse=True)])
weight = 0
for from_node, to_node in it.izip(permutations.itervalues(),
it.islice(permutations.itervalues(), 1, None)):
weight += nx.dijkstra_path_length(G, source=from_node, target=to_node)
with open(OUTPUT_FILE, 'w') as f:
f.writelines(["{0}: {1}\n".format(*i) for i in
permutations.iteritems()]+["\nResult: %s" % weight])
if __name__ == "__main__":
from sys import exit
from datetime import datetime
start = datetime.now()
r = main()
print "Done in %s seconds" % (datetime.now() - start).total_seconds()
exit(r)
35
Приложение №2
Исходный программный код для второго алгоритма
__author__ = 'Ksenia Voronaya'
# 2 algorithm
INPUT_FILE = r'C:\Users\ksenia\alg_2\test_2.txt'
OUTPUT_FILE = r'C:\Users\ksenia\alg_2\ans_2.txt'
def parse_file(file_name):
file_context = open(file_name)
for line in file_context:
total = [float(i) for i in line.rstrip().split()]
if not total:
for i in file_context:
line = map(lambda x: float(x), i.rstrip().split())
if line.count(0) == 1:
yield line
raise StopIteration
yield sum(total)
def main():
sum_stoim_link = {i: v for i, v in enumerate(parse_file(INPUT_FILE), start=1)}
dist_ = sum_stoim_link.pop(max(sum_stoim_link))
dist_from_cent = {i: v for i, v in enumerate(dist_, start=1)}
z = sorted(sum_stoim_link, key=lambda x: sum_stoim_link[x], reverse=True)
r = sorted(dist_from_cent, key=lambda x: dist_from_cent[x])
f = sum(map(lambda x, y: x*y, sorted(sum_stoim_link.values(), reverse=True),
sorted(dist_)))
print "LW: %s\nSW: %s\nF: %s" % (z, r, f)
with open(OUTPUT_FILE, 'w') as f_:
f_.writelines(["%s: %s\n" % (i, j) for i, j in zip(z, r)])
f_.writelines(["\nF = %s" % f])
if __name__ == '__main__':
from sys import exit
from datetime import datetime
start = datetime.now()
r = main()
print "\nDone in %s seconds" % (datetime.now() - start).total_seconds()
exit(r)
36
Приложение №3
Исходный программный код для третьего алгоритма
__author__ = 'Ksenia Voronaya'
# 3 algorithm
from itertools import izip
from collections import OrderedDict
INPUT_FILE = r'C:\Users\ksenia\alg_3\test_3.txt'
OUTPUT_FILE = r'C:\Users\ksenia\alg_3\ans_3.txt'
INF = 999999999
def Floyd_Warshall(graph):
for k in graph:
for i in graph:
for j in graph:
if graph[i][k] + graph[k][j] < graph[i][j]:
graph[i][j] = graph[i][k]+graph[k][j]
return graph
def parse_file(file_name):
convert = lambda x: float(INF) if x == '0' else float(x)
file_context = open(file_name)
for i, line in enumerate(file_context, start=1):
# replace each 0 to 999999999
lines = [convert(j) for j in line.rstrip().split()]
if not lines:
for i in file_context:
line = map(lambda x: float(x), i.rstrip().split())
if line.count(0) == 1:
yield 'w', line
raise StopIteration
lines[i-1] = 0.0
yield i, {k: v for k, v in enumerate(lines, start=1)}
def main():
graph = {i: j for i, j in parse_file(INPUT_FILE)}
w = graph.pop('w')
w_new_dict = {k: v for k, v in enumerate(w, start=1)}
w_new = sorted(w_new_dict, key=lambda x: w_new_dict[x], reverse=True)
mw_matr = Floyd_Warshall(graph)
mw_matr = OrderedDict(sorted(mw_matr.iteritems(), key=lambda x: x[0]))
k = list()
for i in mw_matr:
del(mw_matr[i][i])
k.append(sorted(mw_matr[i].itervalues()))
vector_stoim_link = [i for i in w if i != 0]
Arr = [sum(map(lambda x: x[0]*x[1], izip(i, vector_stoim_link))) for i in k]
index = Arr.index(min(Arr))+1
37
permutation = {k: v for k, v in izip(w_new, [index]+[i for i in range(1,
len(w_new)+1) if i != index])}
with open(OUTPUT_FILE, 'w') as f:
f.writelines(["Minimum of function is %s and position is %s\n" %
(Arr[index-1], index)] +
["%s: %s\n" % (i, j) for i, j in permutation.iteritems()])
if __name__ == '__main__':
from sys import exit
from datetime import datetime
start = datetime.now()
r = main()
print "\nDone in %s seconds" % (datetime.now() - start).total_seconds()
exit(r)
38
Приложение №4
Исходный программный код генератора случайных графов по модели
Эрдеша-Реньи
__author__ = 'Ksenia Voronaya'
# generator
from random import randint, random
import math
try:
import networkx as nx
except ImportError:
raise ImportError("Please, install networkx package: pip install networkx")
N = 20
OUTPUT_FILE = r'C:\Users\ksenia\generator\test_1.txt'
OUTPUT_FILE_2 = r'C:\Users\ksenia\generator\test_2.txt'
def star_graph(n):
G = nx.Graph()
G.name = "star graph(%s)" % n
centre = randint(0, n)
G.add_weighted_edges_from([(centre, i, randint(1, 40)) for i in xrange(n) if i
!= centre])
return G
def random_graph(n, p):
G = nx.empty_graph(n)
G.name = "random graph(%s)" % n
w, v = -1, 1
lp = math.log(1.0 - p)
while v < n:
lr = math.log(1.0 - random())
w = w + 1 + int(lr/lp)
while w >= v and v < n:
w = w - v
v = v + 1
if v < n:
G.add_edge(v, w, weight=randint(1, 40))
return G
def main():
sw = star_graph(N)
mw = random_graph(N, 0.5)
tree = nx.minimum_spanning_tree(mw)
# removing isolated nodes
tree.remove_nodes_from(nx.isolates(tree))
results = []
39
for graph in (mw, sw):
for i in xrange(N):
weights = [str(graph[i].get(j, {}).get('weight', 0)) for j in
xrange(N)]
results.append(" ".join(weights))
results.append("")
with open(OUTPUT_FILE, 'w') as f:
f.writelines([i+'\n' for i in results])
with open(OUTPUT_FILE_2, 'w') as f:
f.writelines(["{0} {1} {2}\n".format(i[0]+1, i[1]+1, randint(1, 30)) for i
in tree.edges_iter()])
if __name__ == "__main__":
from sys import exit
from datetime import datetime
start = datetime.now()
r = main()
print "Done in %s seconds" % (datetime.now() - start).total_seconds()
exit(r)
40
Download