Министерство образования и науки Российской Федерации ФЕДЕРАЛЬНОЕ ГОСУДАРСТВЕННОЕ БЮДЖЕТНОЕ ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ

advertisement
Министерство образования и науки Российской Федерации
ФЕДЕРАЛЬНОЕ ГОСУДАРСТВЕННОЕ БЮДЖЕТНОЕ ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ
ВЫСШЕГО ПРОФЕССИОНАЛЬНОГО ОБРАЗОВАНИЯ “САРАТОВСКИЙ
ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ ИМЕНИ Н.Г.ЧЕРНЫШЕВСКОГО” (СГУ)
УДК 004.4, 681.3.06, 681.322
УТВЕРЖДАЮ
Ректор Федерального государственного
бюджетного образовательного учреждения
высшего профессионального образования
“Саратовский государственный
университет имени Н.Г.Чернышевского”
_____________________ Л.Ю.Коссович
«_____» _________________2011г.
МП
ОТЧЕТ
О НАУЧНО-ИССЛЕДОВАТЕЛЬСКОЙ РАБОТЕ
по Государственному контракту от 7 сентября 2011 года № 07.Р20.11.0029
“Подготовка и переподготовка профильных специалистов на базе центров образования и
разработок в сфере информационных технологий в Южном и Северо-Кавказском федеральных
округах”
Тема НИР: “РАЗРАБОТКА АЛГОРИТМОВ ПОИСКА ГЛОБАЛЬНЫХ ЭКСТРЕМУМОВ ПРИ
НАЛИЧИИ ЯВНЫХ И НЕЯВНЫХ ОГРАНИЧЕНИЙ НА ПАРАЛЛЕЛЬНЫХ
ВЫЧИСЛИТЕЛЬНЫХ СИСТЕМАХ”
Научный руководитель
А.Н.Савин
Саратов 2011
Список исполнителей
Научный руководитель
НИР,
_________________
доцент кафедры ДМиИТ,
подпись, дата
к.ф.-м.н.
Исполнители темы
А.Н.Савин (реферат,
введение, раздел 1,
заключение)
Студент 5 курса
факультета КНиИТ СГУ
А.А. Ерофтиев (раздел 2,
_________________ раздел 4, приложение А,
подпись, дата
приложение В)
Студент 5 курса
факультета КНиИТ СГУ
И.В. Дружинин(раздел 3,
раздел 4, приложение Б,
приложение В)
______________
подпись, дата
2
Реферат
Отчет 88с.,20 рис., 4 табл., 10 источников,3 прил.
УСЛОВНАЯ ОПТИМИЗАЦИЯ КОМПЛЕКСНЫМ МЕТОДОМ БОКСА, ОПТИМИЗАЦИЯ
МЕТОДОМ
ИМИТАЦИИ
ОТЖИГА,
ОПТИМИЗАЦИИ,МНОГОЭКСТРЕМАЛЬНАЯ
ГЕНЕТИЧЕСКИЕ
ЦЕЛЕВАЯ
ФУНКЦИЯ,
АЛГОРИТМЫ
ПАРАЛЛЕЛЬНЫЕ
ВЫЧИСЛИТЕЛЬНЫЕ СИСТЕМЫ
Научно-исследовательская работа по теме «Разработка алгоритмов поиска
глобальных экстремумов при наличии явных и неявных ограничений на
параллельных вычислительных системах» выполняется в рамках федеральной
целевой программы развития образования на 2011-2015 годы по Государственному
контракту от 7 сентября 2011 года №07.Р20.11.0029.
Объектом
исследования
являются
различные
алгоритмы
нахождения
глобального экстремума многопараметрических целевых функций при наличии
явных и неявных ограничений.
Цель работы – исследование возможности распараллеливания известных
алгоритмов нахождения глобального минимума многоэкстремальной целевой
функции многих переменных с явными и неявными ограничениями, а также оценка
их эффективности при выполнения на параллельных вычислительных системах.
В процессе работы предложены варианты распараллеливания комплексного
метода оптимизации Бокса, алгоритма оптимизации, основанного на методе
имитации
отжига
и
генетического
алгоритма
оптимизации.
Проведены
экспериментальные исследования по оценке их эффективности и надёжности в
сравнении с исходными алгоритмами.
В
результате
исследования
для
комплексного
метода
оптимизации
Боксаопределено оптимальное число узлов вычислительной системы с точки зрения
требуемой точности вычислений и стабильности результатов. При этом время
выполнения программы оказалось в несколько раз меньше, чем на одной ЭВМ, а
надёжность нахождения глобального экстремума значительно выше за счёт
3
одновременного исследования целевой функции в нескольких областях факторного
пространства.
Для алгоритма оптимизации, основанного на методе имитации отжига
определены
зависимостинадёжности
количества
узлов
параллельной
нахождения
глобального
вычислительной
системы.
минимума
Показано,
от
что
распараллеленный вариант алгоритма имитации отжига, использующий схему
Больцмановского тушения, позволяет за небольшое время надёжно находить
область глобального минимума.
Для
параллельного
варианта
классического
генетического
алгоритма
оптимизации найдены зависимости надёжностии времени нахождения глобального
минимума от количества узлов параллельной вычислительной системы.Определены
оптимальные
параметры
алгоритма,
обеспечивающие
достаточно
быструю
сходимость.
Результаты работы могут использоваться при решении оптимизационных задач в
различных технических областях, в том числе при разработкеи исследованиях нанои метаматериалов.
Степень внедрения – научные публикации, программы для ЭВМ.
Настоящий отчет является заключительным. Работа в рамках проекта завершена
в соответствии с календарным планом Государственного контракта от 7 сентября
2011 года №07.Р20.11.0029.
4
Определения
В настоящем отчете используются следующие определения:
Условная оптимизация
Задача условной оптимизации заключается в поиске
минимального или максимального значения
скалярной функциимногих переменных (целевой)при
наличии различных ограничений на них
Многоэкстремальная
Целевая функция, имеющая как локальные, так и
целевая функция
глобальный экстремумы
Глобальный экстремум
Крайнее значение числовой функции на всем
множестве значений, принимаемых этой функцией, т.
е. ее глобальный максимум или глобальный минимум
Параллельные
Это физические компьютерные, а также программные
вычислительные системы
системы, реализующие тем или иным способом
параллельную обработку данных на многих
вычислительных узлах
5
Обозначения и сокращения
В настоящем отчете использованы следующие обозначения и сокращения:
ВС
вычислительная система
ЦФ
целевая функция
ГА
генетический алгоритм
6
Содержание
Список исполнителей
Реферат
Определения
Обозначения и сокращения
Содержание
Нормативные ссылки
Введение
1 Постановка задачи поиска глобального минимума
при наличии ограничений
2 Поиск глобального минимума модифицированным
комплексным методом Бокса
2.1 Адаптация алгоритма оптимизации
модифицированным комплексным методом Бокса
для использования на параллельной ВС
2.2 Оценка эффективности распараллеленного
алгоритма оптимизации модифицированным
комплексным методом Бокса
3 Поиск глобального минимума методом имитации
отжига
3.1 Адаптация алгоритма оптимизации методом
имитации отжига для использования на
параллельной ВС
3.2 Оценка эффективности распараллеленного
алгоритма оптимизации методом имитации отжига
4 Поиск глобального минимума с использованием
генетического алгоритма
4.1 Адаптация генетического алгоритма оптимизации
для использования на параллельной ВС
4.2 Оценка эффективности оптимизации с
использованием параллельных вариантов
генетического алгоритма
Заключение
Список использованных источников
Приложение А
Приложение Б
Приложение В
7
2
3
4
5
7
8
9
10
12
15
18
27
30
32
37
40
44
53
55
56
69
76
Нормативные ссылки
В настоящем отчете использованы ссылки на следующие стандарты.
ГОСТ 15.101–98
ГОСТ 19.001-77
Система разработки и постановки продукции на
производство. Порядок выполнения научноисследовательских работ
ЕСПД. Общие положения.
ГОСТ 19.401-78
ЕСПД. Текст программы. Требования к
содержанию и оформлению
ГОСТ 7.1-2003
Система стандартов по информации,
библиотечному и издательскому делу.
Библиографическая запись. Библиографическое
описание. Общие требования и правила
составления
ГОСТ 7.32-2001
Система стандартов по информации,
библиотечному и издательскому делу. Отчет о
научно-исследовательской работе. Структура и
правила оформления
8
Введение
Основанием
для
проведения
научно-исследовательской
работы
(НИР)
является Государственный контракт от 7 сентября 2009 года № 07.Р20.11.0029.
Начало работ: 10 октября 2011 г., окончание работ: 28 ноября 2011 г.
Многие сферы деятельности человека в настоящее время, такие как разработка
новых материалов и устройств, телекоммуникационные сети, требуют решения
оптимизационных задач. Как известно, подобные задачи сводятся к поиску
экстремумов ЦФ различными методами [1].
Задачи оптимизации,как правило, содержат явные ограничения на значения
параметров и различные дополнительные условия – неявные ограничения. При этом
ЦФ часто оказываются многоэкстремальными. Существующие для решения таких
задач методы условной оптимизации, как градиентные, так и случайного поиска, не
гарантируют
нахождение
глобального
экстремума
и
требуют
больших
вычислительных затрат [1].
Проблема
нехватки
вычислительных
ресурсов
может
быть
решена
применением современных параллельных и распределённых систем вычислений, в
сочетании с эффективно работающими на этих системах алгоритмами условной
оптимизации, учитывающими особенности конкретных задач [1].
Соответственно, разработка таких алгоритмов является актуальной задачей.
Целью данной работы является изучение возможностей распараллеливания
модифицированного комплексного метода оптимизации Бокса [2, 3], алгоритма
оптимизации, основанного на методе имитации отжига [4-7] и генетических
алгоритмов оптимизации [8, 9], применяемых при поиске глобальных экстремумов,
а также оценка эффективности и надёжности этих алгоритмов при выполнении на
параллельных ВС.
Данная работа тесно связана с плановыми научно-исследовательскими
работами, проводимыми на кафедре дискретной математики и информационных
технологий СГУ. Уровень разработки определяется имеющимися по теме
публикациями студентов, аспирантов и сотрудников кафедры, их выступлениями на
различных научных конференциях.
9
1 Постановка задачипоиска глобального минимума при наличии ограничений
Поиск глобального минимума функции f : R n при наличии ограничений
осуществляется на некотором собственном подмножестве

метрического
пространства R n [2]:
f ( x)  f ( x1 ,..., x n )  min, x  ,   R n ,
(1)
где подмножество  определяется явными ограничениями
l j  x j  u j , j  1,..., n ,
(2)
а также неявными ограничениями
hi x   bi , i  1,..., m .
Пусть имеется некоторое множество
(3)
X
состоящее из элементов
x,
принадлежащих подмножеству   R n , и на нём определена скалярная функция f x .
Говорят, что f x  имеет локальный минимум в точке x * , если существует некоторая
конечная  -окрестность этой точки, в которой выполняется условие:
 
f x *  f x , x  x *   .
У функции может быть много локальных минимумов. Если выполняется
неравенство f x *   f x  x  X , где x  x * – любая точка множества X , то говорят о
глобальном минимуме функции f x  [10].
Например, многоэкстремальная функцияможет иметь вид:
f x1 , x2   x12  x22  0.1cos18x1   0.1cos18x2  .
(4)
Эта функция имеет множество локальных минимумов и глобальный минимум,
равный -0.2 при x1  x2  0 . Вид функции приведён на рисунке1.
Как указывается в [10],в случае наличия явных (2) и неявных ограничений (3)
(вид которых в реальных задачах не слишком прост) поиск глобального
минимумамногоэкстремальных функций становится очень сложной задачей.
10
Рисунок 1– Вид многоэкстремальной функциидвух переменных
11
2Поиск глобального минимума модифицированным комплексным методом
Бокса
Поиск глобального минимума многоэкстремальной функции (1) при наличии
явных (2) и неявных (3) ограничений на варьируемые параметры может быть
осуществлён комплексным методом Бокса [2] с учётом его модификаций,
предложенных в [3].
Комплексный метод Бокса использует при поиске экстремума только значения
функции, а не её производные, то есть это метод прямого поиска. Он является
модификацией симплексного метода Нелдера-Мида [2], основанного на применении
процедуры симплекс-планирования при поиске экстремумов, однако позволяет
учитывать явные и неявные ограничения на изменения варьируемых параметров.
Если функция f (x) (1) выпукла и неявные ограничения hi x  (3) тоже
выпуклы, то сформулированная выше задача поиска минимума имеет единственное
решение, которое успешно находится комплексным методом Бокса. Однако при
наличии локальных невыпуклостей функции f (x) , т.е. при её многоэкстремальности
данный метод имеет возможность зацикливания [2].
В [3] предложена модификация комплексного метода Бокса, исключающая
возможность зацикливания. Она основана на дополнительном исследовании
функции
f (x )
в текущей области изменения варьируемых параметров для
выявления локальных невыпуклостей f (x) и на их обходе. Алгоритм оптимизации
модифицированным комплексным методом Бокса приведён ниже.
1. Поиск глобального минимума ЦФ f (x) (1) начинается с определения количества
параметров n , инициализации нижних и верхних границ явных ограничений (2)
l j , u j , j  1,..., n , ввода неявных ограничений(3) hi x   bi , i  1,..., m .
2. Строится комплекс из k  sn случайным образом распределённых точек в области,
заданной ограничениями (2) и (3) (Бокс использовал коэффициент умножения
комплекса s  2 ):
 выбирается начальная точка x[1] , удовлетворяющая ограничениям (2) и (3);
12
 координаты
остальных
точек,
удовлетворяющих
ограничениям
(2),
выбираются следующим образом:
x j [q]  l j  r (u j  l j ) ,
(5)
где j  1,..., n , q  2,..., k , r – псевдослучайная равномерно распределенная
переменная в интервале (0, 1) ;
 если выбранная в соответствии с (5) точка x[q ] не удовлетворяет неявным
ограничениям (3), то она смещается на половину расстояния до центра
тяжести
множества
уже
принятых
точек– x c :
q 1
x c   x[e] q  1 ,
т.е.
e 1
формируется точка x [q ] :


x[q]  x[q]  x c 2 ;
(6)
 точке x[q ] присваивается значение смещённой точки x [q ] : x[q]  x [q] ;
 если точка x[q ] всё еще не является допустимой, то описанная соотношением
(6) процедура повторяется до тех пор, пока точка x[q ] не станет допустимой, а
если функции hi x  выпуклы, то, в конце концов, ограничения выполняться;
 точки комплекса упорядочиваются в соответствии со значениями ЦФ:
f x[1]  ...  f x[k ] .
3. Определяется наименьшее значение ЦФ – f min : f min  f x[1] .
4. Определяются точка с наибольшим значением ЦФ– x[k ] и центр тяжести
k 1
остальных k  1 точек – x 0 : x 0   x[e] k  1 .
e 1
5. Вычисляется точка x r отражением худшей точки x[k ] относительно центра
тяжести x 0 , используя коэффициент отражения   1 : x r  x 0   x[k ]  x 0 .
6. Вычисляется значение ЦФ в центре тяжести k  1 точек f x 0  .
7. Осуществляется проверка ЦФ на выпуклость: если f x 0   f x[k  1] , то ЦФ
выпукла и переходим к шагу 8, иначе центр тяжести x 0 заменяется на лучшую
точку – x[1] : x 0  x[1] .
8. Выполняется проверка, является ли отражённая точка x r допустимой:
13
 если не выполняются ограничения для l j , j  1,..., n , то x rj  l j  10 6 ;
 если не выполняются ограничения для u j , j  1,..., n , то x rj  u j  10 6 ;
 если не выполняются неявные ограничения (3), то точка x r перемещается на
половину расстояния между x r и центром тяжести x 0 : x r  x r  x 0  2 , а
отражённой точке x r присваивается значение x  r : x r  x  r .
9. Производится повторная проверка отражённой точки x r на допустимость и шаг 8
повторяется до тех пор, пока не будет получена допустимая точка.
10.Осуществляется проверка на улучшение отражённой точки x r :
 вычисляется значение ЦФ f x r  и сравнивается с f x[k ] – наибольшим
значением ЦФ в комплексе;
 если f x r   f x[k ] , т.е. не лучше, чем наибольшее значение ЦФ, полученное
ранее, то отражённая точка x r перемещается на половину расстояния между


r
r
0
x r и центром тяжести x 0 : x  x  x 2 , отражённой точке x r присваивается
значение x  r : x r  x  r и процесс возвращается на шаг 8;
 если f x r   f x[k ] , то худшая точка x[k ] заменяется на точку x r : x[k ]  x r , то
есть
комплекс
обновляется,а
точки
комплекса
упорядочиваются
в
соответствии со значениями ЦФ: f x[1]  ...  f x[k ] .
11.Оценивается значение ЦФ в лучшей точке – f x[1]: если f x[1]  f min , то есть
наименьшее значение ЦФ – f min не уменьшено, то процесс возвращается на шаг 4.
Иначе выполняется проверка сходимости:
 вычисляется квадрат стандартного отклонения значений ЦФ для всех k точек
комплекса –  2 :  2    f x[e]  f  k , где f   f x[e] k ;
k
k
2
e 1
e 1
 вычисляется максимальное расстояние между точками комплекса – d max :
d max  max
 x [e]  x [q]
n
j 1
2
j
j
, e  1,..., k  1, q  e  1,..., k ;
14
 если  2   1 и d max   2 , где  1 ,  2 достаточно малые заданные величины, то
процедура поиска минимумацелевой функции f (x) (1) заканчивается. Иначе
осуществляется возврат на шаг 3 и продолжается поиск минимума.
Шаги 6 и 7, введённые в представленный в [2] исходный алгоритм
комплексного метода Бокса, обеспечивают выявление и обход локальных
невыпуклостей ЦФ. Соответственно, такие изменения, совместно со случайным
выбором начальных точек в факторном пространстве позволяют использовать
модифицированный комплексный метод Бокса для поиска глобального минимума
многоэкстремальных ЦФ при наличии явных и неявных ограничений.
При этом, как установлено в [2], для проверки того, что был найден
глобальный, а не локальный минимум требуется производить несколько запусков
при различных начальных точках. Это приводит к пропорциональному увеличению
вычислительных и, соответственно, временных затрат, что недопустимо для
сложных, многопараметрических ЦФ.
В этом случае проблема повышения эффективности работы рассматриваемого
алгоритма, с точки зрения минимизации времени вычислений, может быть решена
путём его распараллеливания.
2.1 Адаптация алгоритма оптимизации модифицированным комплексным
методом Бокса для использования на параллельной ВС
Анализ приведённого выше алгоритма оптимизации модифицированным
комплексным методом Бокса показывает:
 процедура инициализации комплекса (шаги 1, 2) подразумевает обновление
центра уже определенных точек и дальнейшее его использование на каждой
итерации,
следовательно,
распараллеливание
данного
участка
алгоритма
представляется невозможным.
 в основном процессорное время расходуется на многократное вычисление ЦФ в
итерационном процессе улучшения точек построенного комплекса (шаги 3 – 12).
Следовательно, наиболее ценным является распараллеливание этого участка
15
алгоритма.
Поэтому было предложено одновременно выполнять процедуру улучшения p
худших точек комплекса на параллельной ВС, состоящей из p  1 узлов. При этом
один выделенный узел должен осуществлять начальную инициализацию данных,
построение комплекса, выработку заданий по улучшению точек комплекса,
обновление комплекса, проверку сходимости. Вопрос выбора оптимального числа
вычислительных узлов будет рассматриваться далее при анализе результатов
тестирования.
На рисунке 2представлена блок-схема распараллеленного вышеуказанным
способом алгоритма оптимизации модифицированным комплексным методом
Бокса, выполняемого на параллельной ВС (пунктиром выделена параллельно
выполняемая часть алгоритма), а на рисунке 3 – блок-схема процедуры улучшения
одной из худших точек комплекса, выполняемой на отдельном узле ВС.
Реализованный таким образом для выполнения на параллельной ВС алгоритм
оптимизации
модифицированным
обеспечивать
надёжный
поиск
комплексным
глобального
методом
минимума
Бокса
ЦФ
за
должен
счёт
её
одновременного исследования в нескольких областях факторного пространства.
При этом,так как процесс поиска минимума осуществляется одновременно на
нескольких машинах, то затраченное на его выполнение время должно значительно
уменьшится.
Для
тестирования
алгоритмаоптимизации
предложенногопараллельного
модифицированным
комплексным
варианта
методом
Боксаразработана программа (см. приложение А) на языке программирования C++.
16
Начало оптимизации модифицированнымкомплекснымметодомБокса
Инициализация исходных данных: количество параметров – n;
явные ограничения ljxjuj, j=1,…,n; неявные ограничения hi(x)bi, i=1,…,m;
p+1 – число узлов параллельной вычислительной системы.
Построение комплекса из k=sn случайным образом распределенных в исследуемой
области факторного пространстваточек x[q], q=1,…,k, удовлетворяющих всем
ограничениям.
Упорядочивание точек комплекса x[q], q=1,…,k, в соответствии с возрастанием значений
целевой функции f(x) в них: f(x[1]) … f(x[k]).
Определение центра тяжести лучших k-p точек – x0и значения ЦФ в нём – f(x0).
Вычисление p отражённых точекxr[k-p+t], 1 t  p из соответствующих худших x[k-p+t]:
xr[k-p+t]=x0–a(x[k-p+t]–x0), коэффициент отражения a >1.
Проверка ЦФ на
выпуклость:
f(x0)<f(x[k-p]).
Нет
Замена центра тяжести x0 на лучшую точку
комплексаx[1]:x0=x[1].
Да
Для каждой из p худших точек комплекса x[k-p+t],1tp, на отдельном
вычислительном узле выполняется подпрограмма улучшения:
Процесс улучшенияx[k-p+1]
Процесс улучшенияx[k]

Замена худших p точек комплекса x[k-p+t], 1tp, насоответствующие улучшенные.
Упорядочивание точек комплекса x[q], q=1,…,k, в соответствии с возрастанием
значений целевой функции f(x) в них: f(x[1]) … f(x[k]).
Вычисление квадрата стандартного отклонения значений целевой функции 2
и максимального расстояния между точками комплекса dmax.
Нет
Проверка сходимости:
2<1иdmax<2.
Да
Завершение оптимизациимодифицированнымкомплекснымметодомБокса
Рисунок2 – Блок-схема алгоритма оптимизациимодифицированным комплексным
методом Бокса,выполняемого на параллельной ВС
17
Начало процедуры улучшения одной из худших точек комплекса
Получение от главного узла одной из p худших точек комплекса –
xисоответствующих ей значения ЦФ – f(x) и отражённой точки – xr, а также
центра тяжести лучших k-p точек – x0, заменённогов случае невыпуклости ЦФ на
лучшую точку комплексаx[1].
Нет
Проверка явных
ограничений для xr:
ljxrjuj.
Перемещение точки xr в
допустимые границы:
xrj=lj+10-6 или xrj=uj–10-6.
Да
Нет
Проверка неявных
ограничений для xr:
hi(xr)bi.
Перемещение точки xr:
xr=(xr+x0)/2.
Да
Нет
Проверка на
улучшение точки xr:
f(xr)<f(x).
Да
Замена полученнойот главного узла худшей точки x на отражённуюxr: x=xr.
Передача улучшенной точки xглавному узлу.
Завершение процедуры улучшения одной из худших точек комплекса
Рисунок3–Блок-схема процедурыулучшения одной из худших точек комплекса,
выполняемой на отдельных узлах параллельной ВС
2.2
Оценка
эффективности
распараллеленного
алгоритма
оптимизации
модифицированным комплексным методом Бокса
Оценка
надёжности
и
эффективности
распараллеленного
алгоритма
оптимизации модифицированным комплексным методом Бокса осуществлялась на
многоэкстремальных ЦФ, подобных функции (4), но при количестве параметров
оптимизации n равном 4, 6 и 8:
 число параметров оптимизации n  4 :


f x1 , x 2 , x3 , x 4    x 2j  0.1cos18x j  ,
4
j 1
где  0.5  x j  1 , j  1,...,4 ;
18
(7)
f min  0.4 при x j  0 , j  1,...,4 .
 число параметров оптимизации
n6:


f x1 , x2 , x3 , x4 , x5 , x6    x 2j  0.1cos18x j  ,
6
(8)
j 1
где  0.5  x j  1 , j  1,...,6 ;
f min  0.6 при x j  0 , j  1,...,6 .
 число параметров оптимизации n  8 :


f x1 , x2 , x3 , x4 , x5 , x6 , x7 , x8    x 2j  0.1cos18x j  ,
8
(9)
j 1
где  0.5  x j  1 , j  1,...,8 ;
f min  0.8 при x j  0 , j  1,...,8 .
Процесс поиска глобального минимума завершался при выполнении
следующих условий: квадрат стандартного отклонения значений ЦФ для всех k
точек комплекса–  2  0.0000001
и максимальное расстояние между точками
комплекса – d max  0.001 .
Для оценки времени работы разработанного приложения в указанные ЦФ
добавлялась инструкция задержки таким образом, чтобы время их выполнения
составляло 1 мс. Соответственно по времени поиска глобального экстремума можно
оценить количество вычислений ЦФ, так как основное время затрачивается на её
вычисление.
Статистическая
достоверность
полученных
данных
обеспечивалась
усреднением по результатам 100 запусков процесса поиска глобального минимума
при каждом сочетании параметров.
Тестирование распараллеленного алгоритма оптимизации модифицированным
комплексным методом Бокса для функций (7), (8) и (9)осуществлялось при
различном числе узлов параллельной ВС p .
Увеличение p должно приводить к уменьшению времени поиска глобального
минимума, так как будут одновременно улучшаться p точек комплекса, состоящего
в исходном алгоритме [2] из k  2n точек.Однакопри этом уменьшается оставшееся в
19
комплексе число точек (равное k  p ) по которым определяется направление
движения к глобальному минимуму. Соответственно, должна уменьшаться
вероятность его нахождения.
Увеличением
числа
точек
в
комплексе
можно
k
повысить
вероятностьнахождения глобального минимума, но это должно приводить к
увеличению времени его поиска.
Поэтому было решено исследовать также влияние количества точек комплекса
k  sn на время и надёжность поиска глобального минимума. При этом целый
коэффициент умножения комплекса s изменялся в пределах от 2 (как в исходном
алгоритме [2]) до n  1.
На
рисунках
4, 5
и
6,
соответственно
для
ЦФ
(7),
(8)
и
(9),
приведеныусредненные по итогам 100 запусков ВСвероятность нахождения
глобального минимума (а) и время его поиска (б) распараллеленным алгоритмом
оптимизации модифицированнымкомплексным методом Бокса в зависимости от
числа узлов ВС p и коэффициента умножения комплекса s .
Как видно из рисунков 4, 5 и 6, исходный алгоритм метода Бокса()
показывает низкую вероятность нахождения глобального минимума: 28%, 16% и
13%, соответственно для ЦФ (7), (8) и (9).
Увеличение числа узлов ВС p (), как и предполагалось выше, уменьшает
время поиска глобального минимума примерно в 4, 6.2 и 7.3 раза по сравнению с
исходным алгоритмом (), но вероятность нахождения глобального минимума при
этом понижается до 16%, 12% и 2%, соответственно для ЦФ (7), (8) и (9).
Повышение вероятности нахождения глобального минимума до 64%, 85% и
94% достигается увеличением числа точек в комплексе k (), но это приводит к
увеличению времени его поиска по сравнению с исходным алгоритмом () в 1.9, 2.3
и 3 раза, соответственно для ЦФ (7), (8) и (9).
20
а)
б)
– исходный алгоритм ( p  1, s  2 )
– оптимальное число узлов, коэфф-т умножения комплекса исходный ( p  n, s  2 )
– один узел и оптимальный коэфф-т умножения комплекса ( p  1, s  n )
– оптимальные число узлов и коэфф-т умножения комплекса ( p  n, s  n )
Рисунок 4 –Вероятность нахождения глобального минимума (а) и время его поиска
(б) методом Бокса на параллельной ВС при числе параметров оптимизации n  4
21
а)
б)
– исходный алгоритм ( p  1, s  2 )
– оптимальное число узлов, коэфф-т умножения комплекса исходный ( p  n, s  2 )
– один узел и оптимальный коэфф-т умножения комплекса ( p  1, s  n )
– оптимальные число узлов и коэфф-т умножения комплекса ( p  n, s  n )
Рисунок 5 –Вероятность нахождения глобального минимума (а) и время его поиска
(б) методом Бокса на параллельной ВС при числе параметров оптимизации n  6
22
а)
б)
– исходный алгоритм ( p  1, s  2 )
– оптимальное число узлов, коэфф-т умножения комплекса исходный ( p  n, s  2 )
– один узел и оптимальный коэфф-т умножения комплекса ( p  1, s  n )
– оптимальные число узлов и коэфф-т умножения комплекса ( p  n, s  n )
Рисунок 6 –Вероятность нахождения глобального минимума (а) и время его поиска
(б) методом Бокса на параллельной ВС при числе параметров оптимизации n  8
23
Как видно из рисунков 4, 5 и 6с точки зрения надёжности поиска глобального
минимума и времени его поискаоптимальными являются число узлов ВС p и,
соответственно, число одновременно улучшаемых точек p  n и число точек
комплекса k  sn при s  n ().
При таких значениях
p
и k обеспечивается наибольшая вероятность
нахождения глобального экстремума, составляющая 68%, 88% и 95%, а время его
поиска уменьшается примерно в 2.1, 2.3 и 2 разапо сравнению с исходным
алгоритмом (), соответственно для ЦФ (7), (8) и (9).
Увеличение числа узлов ВС p выше оптимального значения p  n снижает
вероятность нахождения глобального экстремума при незначительном уменьшении
времени его поиска. Увеличение числа точек в комплексе k выше оптимального
значения k  sn при s  n не повышает вероятность нахождения глобального
экстремума, но увеличивает время его поиска (см. рисунки 4, 5, 6).
В таблице 1 приведены результаты сравнения надёжностных и временных
характеристик исходного алгоритмаоптимизации модифицированным комплексным
методом Бокса( p  1, k  2n ) и распараллеленного с оптимальным количеством узлов
ВС p  n и количеством точек в комплексе k  sn при s  n .
Таблица
1–Сравнение
характеристик
исходного
алгоритма
оптимизации
модифицированным методом Бокса с оптимальным распараллеленным вариантом
Количество
Число узловВС p  1
Число узловВС p  n
Коэффициен
Коэффициен
параметров
Число точек комплекса
Число точек комплекса
т ускорения
т повышения
оптимизаци
k  2n
иn
k  sn при
sn
Время
Вероятност
Время
Вероятност
поискасе
ь
поискасе
ь
к
нахождения
к
нахождения
глобального
глобального
минимума
минимума
%
%
надёжности
4
0.625
28
0.299
68
2.09
2.43
6
1.215
16
0.526
88
2.31
5.5
24
8
1.858
13
0.915
95
2.03
7.31
Как видно из таблицы 1, коэффициент ускорения времени выполнения
распараллеленного алгоритма оптимизации модифицированным комплексным
методом Бокса на оптимальных числе узлов ВС и количестве точек комплекса по
сравнению с исходным алгоритмом составляет в среднем 2.14, а вероятность
нахождения глобального минимума повышается в среднем в 5.1 разаза счёт
одновременного исследования ЦФ в большем количестве точек факторного
пространства.
В таблице 2 приведены результаты сравнения надёжностных и временных
характеристик алгоритмаоптимизации модифицированным комплексным методом
Бокса, выполняемого на ВС с одним узлом ( p  1 ) с оптимальным количеством точек
в комплексе k  sn при s  n и выполняемого на ВС с оптимальным числом узлов ВС
p nи
с оптимальным количеством точек в комплексе k  sn при s  n .
Таблица 2–Сравнение характеристик алгоритма оптимизации методом Бокса с
оптимальным числом точек комплекса, выполняемом на одном и оптимальном
числе узлов ВС
Количество
Число узловВС p  1
Число узловВС p  n
Коэффициен
Коэффициен
параметров
Число точек комплекса
Число точек комплекса
т ускорения
т повышения
оптимизаци
иn
k  sn при
sn
k  sn при
sn
Время
Вероятност
Время
Вероятност
поискасе
ь
поискасе
ь
к
нахождения
к
нахождения
глобального
глобального
минимума
минимума
%
%
надёжности
4
1.163
64
0.299
68
3.89
1.06
6
2.854
85
0.526
88
5.43
1.04
8
5.657
94
0.915
95
6.18
1.01
Как видно из таблицы 2, вероятность нахождения глобального минимума при
его
поиске
распараллеленным
алгоритмомоптимизации
25
модифицированным
комплексным методом Бокса на оптимальных числе узлов ВС и количестве точек
комплекса по сравнению с алгоритмом, выполняемом на ВС с одним узлом и с
оптимальным количеством точек в комплексе, увеличивается незначительно,в
среднем в 1.04 раза, а коэффициент ускорения составляет в среднем в 5.17 разаза
счёт одновременного улучшения n точек комплекса на p  n узлах ВС.
Таким
образом,
распараллеленный
алгоритм
оптимизации
модифицированным комплексным методом Бокса может эффективно применяться
для решения различных технических задач, требующихпоиска глобального
экстремума при наличии явных и неявных ограничений.
26
3Поиск глобального минимума методом имитации отжига
Поиск глобального минимума функции (1) при наличии явных ограничений на
варьируемые параметры (2) может быть осуществлён методом имитации отжига,
предложенным С. Киркпатриком [4].
Этот метод представляет собой алгоритмический аналог физического
процесса управляемого охлаждения и использует упорядоченный случайный поиск
новых состояний системы с более низкой температурой [5, 6].
В процессе медленного управляемого охлаждения расплавленного материала,
называемого отжигом, кристаллизация расплава сопровождается глобальным
уменьшением его энергии E , однако допускаются ситуации, в которых она может на
какое-то
время
возрастать
(в
частности,
при
подогреве
расплава
для
предотвращения слишком быстрого его остывания). Благодаря допустимости
кратковременного повышения энергетического уровня, возможен выход из ловушек
локальных минимумов энергии, которые возникают при реализации процесса.
Только понижение температуры T до абсолютного нуля делает невозможным какоелибо самостоятельное повышение энергетического уровня расплава.
В этом случае элементы x подмножества  в (1) представляют собой
состояния воображаемой физической системы (энергетические уровни), а значение
функции f x  в этих точках используется как энергия системы E  f x .
В каждый момент времени предполагается заданной уменьшающаяся с
течением времени по определенному закону температура T системы, находящейся в
состоянии x .
Новое состояние системы x
выбирается в соответствии с заданным
порождающим семейством вероятностных распределений  x,T  , которое при
фиксированных x и T задаёт случайный элемент x  Gx,T  .
После генерации нового состояния x  Gx,T  , система с вероятностью pE,T 
переходит к следующему шагу в состоянии x , в противном случае повторяется
процесс генерации
x (в некоторых модификациях метода следующий шаг
27
начинается с состояния x , но с уменьшенным значением температуры T ). Здесь
E  f x  f x приращение энергии.
В качестве вероятности принятия нового состояния pE,T  выбирается либо
точное значение соответствующей физической величины
pE,T   1 1  expE T  ,
либо наиболее часто используемое приближенное значение
pE,T   exp  E T  .
Вторая формула используется наиболее часто. При этом pE,T   1 в случае
E  0 , и тогда вероятность принятия нового состояния pE,T  считается равной 1.
Соответственно, если новое состояние x дает лучшее значение оптимизируемой
функции, т.е. f x  f x , то переход в это состояние произойдет в любом случае.
Поиск минимума ЦФ заканчивается при уменьшении температуры T до
некоторого заданного уровня Tend .
Конкретная схема отжига задается следующими параметрами:
 законом изменения температуры T k  , где k – номер шага;
 порождающим семейством вероятностных распределений  x,T  ;
 функцией вероятности принятиянового состояния pE,T  .
Исторически первой схемой метода имитации отжига является схема
Больцмановского отжига. В ней изменение температуры задаётся в виде
T k   T0 ln 1  k  , k  0 .
Порождающее семейство вероятностных распределений  x,T  выбирается как
семейство нормальных распределений с математическим ожиданием
дисперсией T и, соответственно, задаётся плотностью

n 2
g x; x, T   2T   exp  x  x
2
x
и
2T ,
где n - размерность метрического пространства состояний.
Для данной схемы доказано, что при достаточно больших T0 и количестве
шагов гарантируется нахождение глобального минимума.
28
Недостатком схемыБольцмановского отжига является очень медленное
уменьшение температуры T . Решение этой проблемы возможно путём замены
закона изменения температуры, например, на следующий:
T k   r  T k 1 ,
(10)
где температурный коэффициент r выбирается, как правило, в пределах 0.7÷0.99.
Такая схема имитации отжига называется тушением. Она очень быстро
сходится,что позволяет экономить вычислительные ресурсы. При этом не
гарантируется нахождение глобального минимума, но, как правило, быстро
находится близкое решение, а на практике и сам минимум [7].
В данной работе требовалось разработать метод оптимизации, позволяющий
за небольшое время надёжно находить только область глобального минимума.
Соответственно, на основе анализа различных схем имитации отжига, проведённого
в [6], был выбран алгоритм поиска глобального минимума ЦФ (1) методом
имитации отжига по схеме Больцмановского тушения. Блок-схема процедуры,
реализующей данный алгоритм, приведена нарисунке 7.
В результате тестирования представленного на рисунке7 алгоритма, выявлено,
что решение (область минимума) находиться за действительно малое время, но
недостатком является возможность нахождения локальных минимумов, а не
глобального.
Данная проблема может решаться многократным повторным запуском
процедуры поиска при одинаковых начальных условиях, так как генерация новых
точек в факторном пространстве осуществляется случайным образом, а затем
выбором лучшего значения.Однако это приводит к пропорциональному увеличению
вычислительных и, соответственно, временных затрат, что недопустимо для
сложных, многопараметрических ЦФ.
В этом случае повышение эффективности работы алгоритма, с точки зрения
минимизации времени вычислений, возможно путём его распараллеливания.
29
Начало процедуры поиска минимума методом имитации отжига
Формирование исходных данных.
Выбор случайным образом начального состояния x=x0 ,x .
Вычисление текущего значения энергии: E=f(x0).
Установка начального номера шага: k=1.
Установка максимальной начальной температуры: T(k)=T0 , T0>Tend .
Генерация нового состояния: x’=G(x,T(k)).
Плотность порождающего семейства вероятностных распределений:
g(x’;x,T(k))=(2T)-n/2exp(-x’-x2/2T), гдеn – размерность факторного пространства.
Вычисление энергии в новом состоянии: E’=f(x’).
Вычисление приращения энергии: E=E'-E.
Да
E<0
Нет
Вычисление вероятности принятия нового состояния: p(E,T(k))=exp(-E/ T(k)).
Генерация случайного числа  из интервала [0,1].
Да
Нет
<p(E,T(k))
Переход к новому состоянию: x=x', E=E'.
Увеличение номера шага:k=k+1.
Уменьшение температуры: T(k)=rT(k-1), r=0.70.99 .
Да
Нет
T(k)<Tend
Завершение процедуры поиска минимумаметодом имитации отжига
Рисунок7 – Блок-схема процедуры поиска минимума ЦФ методом имитации отжига
по схеме Больцмановского тушения
3.1Адаптация
алгоритма
оптимизации
методом
имитации
отжига
для
использования на параллельной ВС
Неудобством
метода
имитации
отжига
(рисунок7)
с
точки
зрения
распараллеливания является то, что каждое новое системы x генерируется на
основе её предыдущего состояния
x
и, следовательно, нет возможности
распараллеливания какой-либо части алгоритма.
Поэтому было предложено осуществлять вычисление минимумов ЦФ (1)
одновременно на нескольких машинах (клиентская часть алгоритма) и выбирать
30
затем лучшее решение (глобальное) на выделенной машине (серверная часть
алгоритма).
В выполняемой на нескольких машинах клиентской части при одинаковых
начальных условиях осуществляется поиск минимума ЦФ (1) методом имитации
отжига по схеме Больцмановского тушения с помощью процедуры, представленной
на рисунке7.
Затем результаты, полученные в клиентских частях, передаются в серверную
часть (рисунок8), в которой осуществляется выбор решения с наименьшим
значением ЦФ, что должно обеспечивать глобальность найденного минимума.
Пунктиром на рисунке 8 выделена часть алгоритма, выполняемая на клиентских
машинах.
Начало оптимизации методом имитации отжига
На p узлах вычислительной системы выполняется
процедура поиска минимума методом имитации отжига.
Процесс поиска минимума 1

Процесс поиска минимума p
Выбор минимального значения ЦФ:f(xi) = min(f(x1),…, f(xp)).
Выбор оптимальных параметров: xopt = xi .
Завершение оптимизации методом имитации отжига
Рисунок8–Блок-схема алгоритма оптимизации методом имитации
отжига,выполняемого на параллельной ВС
Реализованный таким образом на параллельной ВС алгоритм оптимизации
методом имитации отжига должен обеспечивать надёжный поиск глобального
минимума ЦФ за счёт многократногоповторения поиска в заданной явными
ограничениями (2) области.
При этом, так как многократный процесс поиска минимума осуществляется
одновременно на соответствующем числе машин, то затраченное на выполнения
всего параллельного алгоритмавремя приблизительно должно равняться времени
выполнения одного процесса и практически не должно зависеть от числа процессов.
Соответственно,
при
использовании p клиентских
31
машин
можно
уменьшить
временные затраты при поиске глобального минимумапримерно в p раз.
Для
тестированияпредложенного
оптимизации
методом
имитации
параллельного
отжига
по
варианта
схеме
алгоритма
Больцмановского
тушенияразработана программа (см. приложение В) на языке программирования
C++.
3.2Оценка эффективности распараллеленного алгоритма оптимизации методом
имитации отжига
Оценка
надёжности
и
эффективности
распараллеленного
алгоритма
оптимизации методом имитации отжига по схеме Больцмановского тушения
осуществлялась на многоэкстремальных ЦФподобных функции (4), но при
количестве параметров оптимизации n равном 4, 6 и 8:
 число параметров оптимизации n  4 :
4
f x1 , x2 , x3 , x4    x 2j  0.1cos3x1   0.2 cos2 x2   0.5 cos5x3   0.6 cosx4 ,
(11)
j 1
где  0.5  x j  1 , j  1,..., 4 ;
 число параметров оптимизации n  6 :
6
f x1 , x2 , x3 , x4 , x5 , x6    x 2j  0.1cos3x1   0.2 cos2 x2   0.3 cos5 x3   0.5 cosx4  
j 1
 0.1cos2 x5   0.2 cosx6 ,
(12)
где  0.5  x j  1 , j  1,...,6 ;
 число параметров оптимизации n  8 :
8
f x1 , x2 , x3 , x4 , x5 , x6 , x7 , x8    x 2j  0.1cos3x1   0.2 cos2 x2   0.2 cos5 x3   0.4 cosx4  
j 1
 0.1cos2 x5   0.2 cosx6   0.1cos4 x7   0.1cosx8 ,
(13)
где  0.5  x j  1 , j  1,...,8 .
Глобального минимума f min  1.4 все эти функций достигают при x j  0 ,
j  1,..., n .
Тестирование проводилось при следующих условиях: начальная температура
32
T0  0.5 , конечная Tend  0.005 , коэффициент изменения температуры r  0.97 . При
таких
значениях
параметров
нахождение
области
глобального
минимума
обеспечивалось за небольшое количество итераций.
Как указывалось выше, рассматриваемый алгоритм поиска глобального
минимума должен иметь хорошую сходимость, но большую погрешность.
Соответственно, одной из задач тестирования было выявление зависимости
точности нахождения глобального минимума от количества одновременно
работающих процессов p и количества оптимизируемых параметров ЦФ n .
Результаты поиска минимума ЦФ (11), (12)и (13) методом имитации отжига в
зависимости от числа одновременно работающих процессов p , усредненные по
итогам 100 запусков вычислительной системы, приведены на рисунке9.
-1.29
-1.3
Минимальное значение ЦФ
-1.31
-1.32
-1.33
-1.34
-1.35
-1.36
-1.37
-1.38
-1.39
-1.4
1
3
5
7
9
11
13
15
Количество процессов p
 – n  4 ,  – n  6 ,  – n  8
Рисунок9 – Зависимость найденного минимального значения ЦФ с указанием 95%
доверительного интервала от количества параметров оптимизации n и числа
одновременно работающих процессов поиска минимума p методом имитации
отжига по схеме Больцмановского тушения
Как видно из рисунка 9, для всех значений числа оптимизируемых параметров
ЦФ n при малом количестве работающих процессов
33
p
результат выдается с
большим разбросом, но при увеличении
p
результаты стабилизируются и
приближаются к глобальному минимуму, так как поиск в этом случае ведётся в
большей части заданной явными ограничениями области факторного пространства.
При этом увеличение числа параллельно работающих процессов p с 1 до 16
приводит к уменьшению размеров области глобального минимума, оцениваемой по
среднеквадратическому отклонению минимального значения ЦФ, на 60%, 55% и
50% для n  4 , n  6 и n  8 соответственно (см. рисунок10).
Относительный размер области минимума (%)
100
90
80
70
60
50
40
30
1
3
5
7
9
11
13
15
Количество процессов p
 – n  4 ,  – n  6 ,  – n  8
Рисунок10– Зависимость размеров области глобального минимума от количества
параметров оптимизации n и числа одновременно работающих процессов поиска
минимума p методом имитации отжига по схеме Больцмановского тушения
Следовательно, увеличение числа процессов p при параллельном поиске
области глобального минимума многопараметрической ЦФметодом имитации
отжига повышает надёжность и точность вычислений.
При решении реальных оптимизационных задач большое время занимает
вычисление ЦФ. Соответственно эффективность метода оптимизации можно
оценивать по требуемому для поиска глобального минимумаколичеству вычислений
ЦФ. На рисунке11 приведено количество вычислений ЦФ тестируемым методом в
34
зависимости от количества одновременно работающих процессов p и количества
оптимизируемых параметров n .
212
Число вычислений ЦФ
208
204
200
196
192
188
1
3
5
7
9
11
13
15
Количество процессов p
 – n  4 ,  – n  6 ,  – n  8
Рисунок11–Зависимость числа вычислений ЦФ от количества параметров
оптимизации n и одновременно работающих процессов p в параллельном
алгоритме имитации отжига по схеме Больцмановского тушения
Из
рисунка
11
видно,
что
время
выполнения
параллельного
алгоритма,пропорциональноечислу вычислений ЦФ, практически не зависит от
числа процессов p и примерно равно времени выполнения одного процесса при
одинаковых n .
Увеличение числа параметров оптимизации n приводит к незначительному
уменьшению числа вычислений ЦФ, но увеличиваетразмеры найденной области
глобального минимума.
Значительное влияние на количество вычислений ЦФ и, соответственно, на
эффективность
тестируемого
метода
оптимизации
оказывает
значение
температурного коэффициента r в законе изменения температуры (10). Данная
зависимость приведена на рисунке 12.
Из рисунка 12 видно, что увеличение r с 0.95 до 0.99 приводит к увеличению
числа вычислений ЦФ практически в 6 раз. Однако при этом размеры найденной
35
области глобального минимума уменьшаются, то есть точность повышается.
650
600
Число вычислений ЦФ
550
500
450
400
350
300
250
200
150
100
0.95
0.96
0.97
0.98
0.99
Температурный коэффициент r
 – n  4 ,  – n  6 ,  – n  8
Рисунок12–Зависимость числа вычислений ЦФот температурного коэффициента r в
законе изменения температуры и от количества параметров оптимизации n в
параллельном алгоритме имитации отжига по схеме Больцмановского тушения
Следовательно, при решении конкретных задач есть возможность выбирать
параметры закона изменения температуры (10) для обеспечения баланса между
временными затратами и точностью.
Таким образом, из результатов тестирования видно, что предложенный
параллельный вариант алгоритма оптимизации методом имитации отжига по схеме
Больцмановского тушения может эффективно применяться для решения задач
поиска области глобального минимума многоэкстремальной ЦФ при наличии явных
ограничений на варьируемые параметры. Точное значение глобального минимума
может быть найдено далее с помощью хорошо разработанныхметодов поиска
локальных экстремумов, например методом Хука-Дживса [2].
36
4 Поиск глобального минимума с использованием генетического
алгоритма
Поиск глобального минимума функции (1) при наличии явных (2) и неявных
(3) ограничений на варьируемые параметры может быть осуществлён с помощью
генетических алгоритмов [8].
ГА представляют собой модель процесса эволюции в природе. В них
используются аналоги механизмов генетического наследования и естественного
отбора.
Эволюционная
теория
утверждает,
что
каждый
биологический
вид
целенаправленно развивается и изменяется для того, чтобы наилучшим образом
приспособиться к окружающей среде. Основной механизм эволюции – это
естественный отбор. Его суть состоит в том, что более приспособленные особи
имеют больше возможностей для выживания и размножения и, следовательно,
приносят больше потомства, чем плохо приспособленные особи. При этом
благодаря передаче генетической информации (генетическому наследованию)
потомки наследуют от родителей основные их качества. Таким образом, потомки
сильных индивидуумов также будут относительно хорошо приспособленными, а их
доля в общей массе особей будет возрастать. После смены нескольких десятков или
сотен поколений средняя приспособленность особей данного вида заметно
возрастает.
В теории ГА используется биологическая терминология в упрощенном виде:
 хромосома – вектор чисел;
 ген – бит хромосомы;
 особь – набор хромосом;
 популяция – совокупность особей.
В
качестве
критерия
жизнеспособности
особи
выступает
функция
приспособленности F – отображение совокупности хромосом особи на множество
вещественных
чисел.
Точное
выражение
для
составляется индивидуально для каждой задачи.
37
функции
приспособленности
В этом случае элементы x подмножества  в (1) можно рассматривать какособи
некоторой популяции точек n -мерного пространства, а значения функции f x  с
измененным знаком в этих точках в отсутствии неявных ограничений (3) можно
рассматриватькак значение функции приспособленности F   f x.
Основные шаги работы классическогоГА можно записать в следующем виде
(рисунок 13):
1. Генерация начальной популяции из k особей.
2. Вычисление функции приспособленности каждой особи и отброс наименее
приспособленных особей.
3. Выбор среди оставшихся особей двух родителей.
4. Применение
к
родительским
хромосомам
оператора
скрещивания
с
вероятностью pc ; при отсутствии скрещивания дочерние хромосомы равны
родительским.
5. Применение к полученным дочерним хромосомам оператора мутации с
вероятностью pm ; в отсутствии мутации хромосомы не изменяются.
6. Повторение шагов 3–5, пока популяция вновь не будет содержать k особей.
7. Повторение шагов 1–6 до тех пор, пока не будет достигнут критерий окончания
процесса.
Скрещивание (кроссовер) – это операция, при которой две хромосомы
обмениваются своими частями. В модели, описываемой ГА, кроссовер выполняет
оператор
скрещивания
C.
Существует
несколько
алгоритмов
оператора
скрещивания[8], самые простые из них – одно- и многоточечный.
В одноточечном варианте происходит разрыв двух родительских хромосом в
случайной позиции, после чего они обмениваются полученными участками. При
многоточечном кроссовере хромосомы обмениваются участками, полученными в
результате нескольких разрывов.
Мутацией называется случайное изменение одного или нескольких генов
хромосомы.
38
Начало
Формирование исходных данных.
Количество параметров: n
Объем (численность) популяции: k
Начальная случайная популяция: X1 = {x11, …, xk1}
Вероятность мутации: pm
Вероятность скрещивания: pc
Число новых особей популяции на каждом этапе: m
Максимальное число шагов алгоритма: N
Точность определения схождения популяции: ε
i=1
Вычисление наборов значений функции приспособленности Fi = {f1i, …, fni}
Нет
i<N
Да
Для любых l, t |fli – fti| < ε
Да
Нет
Отброс m особей с наименьшими значениями fji
Для j = 1, …, [m/2]:
 выбрать с помощью оператора выбора родителей пару особей популяции;
 с вероятностью pc применить оператор скрещивания C. Если оператор не
применяется, дочерние хромосомы равны родительским;
 с вероятностью pm применить к каждой хромосоме оператор мутации M.
Добавить m полученных таким образом хромосом в популяцию. Если m
нечетное, то удалить случайным образом 1 новую хромосому.
i=i+1
f = min{fji} – искомое значение
Завершение поиска
Рисунок 13 – Блок-схема классического ГА, используемого для поиска глобального
экстремума ЦФ
В качестве критерия окончания алгоритма могут выступать 2 условия:
 достижение заданного максимального количества итераций (поколений);
 схождение популяции.
Схождением популяции называется такое её состояние, когда все особи
популяции практически одинаковы и находятся в области некоторого экстремума.
ГА контролируется следующими параметрами:
39
 объемом популяции k ;
 вероятностью мутации pm ;
 вероятностью скрещивания pc ;
 числом новых особей на каждом этапе развития популяции m ;
 максимальным числом итераций алгоритма N ;
 при использовании критерия сходимости популяции – точностью схождения  .
В данной работе требовалось исследовать применение ГА на параллельных
ВС к нахождению глобальных экстремумов многоэкстремальных функций
нескольких переменных в условиях наличия явных и неявных ограничений.
4.1 Адаптация генетического алгоритма оптимизации для использования
на параллельной ВС
Существует несколько вариантов использования ГА на параллельных ВС. В
работе [9], выполняемой врамках данной НИР, было предложено два варианта:
1. На i -мэтапе получения потомков с помощью разделенияна m 2 процессов
основного потока выполнения каждый процесс проводит скрещивание двух
особей, затем при вычислении функции приспособленности каждый узел ВС
отыскивает значения Fi (функция приспособленности на i -м этапе) для
порождённых на нём особей.
2. Параллельное развитие нескольких популяций на узлах ВС с последующим
выбором наилучшего результата.
Второй вариант является приемлемым в случае легко вычислимых ЦФ, когда
потери на пересылках данных в коммуникационной среде параллельной ВС могут
быть сравнимы со временем вычисления функции приспособленности F . Также
одновременная
эволюция
нескольких
популяций
может
скомпенсировать
возможное схождение популяции к локальному экстремуму.
В первом случае было предложено осуществлять скрещивание и вычисление
значений функции приспособленности, а, следовательно, и ЦФ (1), одновременно на
40
нескольких машинах (клиентская часть алгоритма), а проверять условие сходимости
на выделенной машине (серверная часть алгоритма).
Блок-схема первого параллельного варианта ГА представлена на рисунке 14.
Пунктиром выделеначасть алгоритма, выполняемая на клиентских машинах.
По достижении условия сходимости или заданного количества итераций, в
серверной части осуществляется выбор решения с наибольшим значением функции
приспособленности, что соответствует наименьшему значению ЦФ, что должно
обеспечивать глобальность найденного минимума.
Так как вычисление значений функции приспособленности F , а значит, и ЦФ
производится одновременно на m 2 вычислительных узлах, то при использовании
клиентских машин можно уменьшить временные затраты при поиске
m2
глобального минимума примерно в m 2 раз. Более точное значение коэффициента
ускорения S можно получить из закона Амдала:
S
1
1

p
где  – доля вычислений, выполняемая в последовательной части,
p
– количество рабочих узлов в параллельной системе.
В
начале
работы
приспособленности F ,
алгоритма
составляющие
производится
k
вычислений
последовательную
часть
функции
вычислений.
Учитывая, что на каждой итерации алгоритма на каждом из m 2 вычислительных
узлов выполняется два вычисления функции приспособленности, при общем числе
m
2
итераций I получим 2 I  mI вычислений в параллельной части.
Таким образом, коэффициент ускорения вычислений S без учета затрат на
пересылку данных между вычислительными узлами равен
S
mI  k
2I  k
41
(14)
Начало
Формирование исходных данных.
Количество параметров: n
Объем (численность) популяции: k
Начальная случайная популяция: X1 = {x11, …, xk1}
Вероятность мутации: pm
Вероятность скрещивания: pc
Число новых особей популяции на каждом этапе: m
Максимальное число шагов алгоритма: N
Точность определения схождения популяции: ε
i=1
На p узлах вычислительной системы выполняется вычисление наборов
i
i
i
значений функции приспособленности F = {f1 , …, fn }
i
i
i
F 1 = {f1 , …,fn }
…
i
i
i
F p= {f1 , …,fn }
Нет
i<N
Да
Для любых l, t |fli – fti| < ε
Да
Нет
Отброс m особей с наименьшими значениями fji
Для j = 1, …, [m/2]:
 выбрать с помощью оператора выбора родителей пару особей популяции;
 с вероятностью pc применить оператор скрещивания C. Если оператор не
применяется, дочерние хромосомы равны родительским;
 с вероятностью pm применить к каждой хромосоме оператор мутации M.
Добавить m полученных таким образом хромосом в популяцию. Если m
нечетное, то удалить случайным образом 1 новую хромосому.
i=i+1
f = min{fji} – искомое значение
Завершение поиска
Рисунок 14 –Блок-схема первого варианта параллельного ГА, используемого для
поиска глобального экстремума ЦФ
Второй вариант параллельной реализации ГА предполагает одновременный
запуск алгоритма на p вычислительных узлах. По окончании работы алгоритма на
всех рабочих узлах параллельной ВС производится сбор данных о полученных
значениях экстремума и выбор наибольшего значения функции приспособленности
F
, соответствующего глобальному минимуму ЦФ.
42
Блок-схема второго варианта распараллеливания ГА приведена на рисунке15.
Пунктиром выделена часть алгоритма, выполняемая на клиентских машинах.
Начало оптимизации с помощью ГА
На p узлах вычислительной системы выполняется
процедура поиска минимума с помощью ГА.
Процесс поиска минимума 1

Процесс поиска минимума p
Выбор минимального значения ЦФ:f(xi) = min(f(x1),…, f(xp)).
Выбор оптимальных параметров: xopt = xi .
Завершение оптимизациис помощью ГА
Рисунок 15 –Блок-схема второго варианта параллельного ГА, используемого для
поиска глобального экстремума ЦФ
Каждый процесс поиска минимума, запускаемый на рабочем узле ВС,
представляет собой классическую реализацию ГА (см. рисунок 13). Параметры
алгоритма при этом задаются одинаковыми для всех процессов.
Такой способ поиска с помощью ГА должен обеспечивать надёжное
нахождение глобального минимума ЦФ за счёт многократного повторения поиска в
заданной ограничениями области.
При этом, так как многократный процесс поиска минимума осуществляется
одновременно на соответствующем числе узлов, то затраченное на выполнения
всего параллельного алгоритмавремя приблизительно должно равняться времени
выполнения одного процесса и практически не должно зависеть от числа процессов.
Соответственно, при использовании p рабочих узлов можно уменьшить временные
затраты при поиске глобального минимумапримерно в p раз.
Для
тестированияпредложенныхпараллельныхвариантовклассического
генетического алгоритма оптимизации разработана программа (см. приложение В)
на языке программирования C++.
43
4.2 Оценка эффективности оптимизации с использованием параллельных
вариантов генетического алгоритма
Оценка надёжности и эффективности описанных выше параллельных
вариантов ГА осуществлялась на многоэкстремальных ЦФ (7), (8) и (9) при
количестве параметров оптимизации n , равном соответственно 4, 6 и 8.
Процесс поиска глобального минимума завершался при выполнении
следующих условий: при схождении популяции, которое оценивалось по
максимальному расстоянию между значениями функции приспособленности –
max ( F )  0.00001 ,
k
или по достижении максимального количества итераций
алгоритма– N  10000 .
Для оценки производительности разработанного приложения использовалось
количество вычислений ЦФ, так как основное время при поиске глобального
минимума с помощью ГА затрачивается на получение её значений.
Статистическая
достоверность
полученных
данных
обеспечивалась
усреднением по результатам 100 запусков процесса поиска глобального минимума
при каждом сочетании параметров.
Тестирование первого варианта параллельного ГА для функций (7), (8) и (9)
осуществлялось при различном числе узлов параллельной ВС
p.
Также
исследовалось влияние объема популяции k , числа новых особей на каждом этапе
развития популяции m , вероятности скрещивания pc и вероятности мутации pm на
процесс поиска глобального минимума. Пределы изменения этих параметров
представлены в таблице 3.
Таблица 3 – Диапазоны изменения параметров ГА в численном эксперименте
k
m
pc
pm
min
10
2
0.1
0.05
max
100
16
1.0
0.1
На рисунках 16 – 19 приведены усредненные по итогам 100 запусков ВС
результаты тестирования первого варианта параллельного ГА.
44
а)
б)
в)
г)
 – n  4 ,  – n  6 ,  – n  8
Параметры алгоритма: m  16, pc  0.75, pm  0.1
Рисунок 16–Зависимость найденного минимального значения ЦФ с указанием 95%
доверительного интервала (а), (б), (в) и числа вычислений ЦФ (г) от количества
параметров оптимизации n и размера популяции k
45
а)
б)
в)
г)
 – n  4 ,  – n  6 ,  – n  4
Параметры алгоритма: k  50, pc  0.75, pm  0.1
Рисунок 17–Зависимость найденного минимального значения ЦФ с указанием 95%
доверительного интервала (а), (б), (в) и числа вычислений ЦФ (г) от количества
параметров оптимизации n и числа детей в каждом поколении m
46
а)
б)
в)
г)
 – n  4 ,  – n  6 ,  – n  4
Параметры алгоритма: k  50, m  10, pm  0.05
Рисунок 18–Зависимость найденного минимального значения ЦФ с указанием 95%
доверительного интервала (а), (б), (в) и числа вычислений ЦФ (г) от количества
параметров оптимизации n и вероятности применения кроссовера p c
47
а)
б)
в)
г)
 – n  4 ,  – n  6 ,  – n  4
Параметры алгоритма: k  50, m  10, pc  0.75
Рисунок 19–Зависимость найденного минимального значения ЦФ с указанием 95%
доверительного интервала (а), (б), (в) и числа вычислений ЦФ (г) от количества
параметров оптимизации n и вероятности применения мутации p m
48
На рисунке 16 приведены зависимости найденных минимальных значений ЦФ
с указанием 95% доверительного интервала (а), (б, (в) и числа вычислений ЦФ (7),
(8), (9) (г) от размера популяции k .При этом остальные исследуемые параметры
алгоритма фиксировались ( m  16, pc  0.75, pm  0.1 ).
Как видно, увеличение размера популяции k с 10 до 100 приводит к
значительному повышению точности нахождения глобального минимума, но при
этом быстро растет количество вычислений ЦФ. Оптимальным, с точки зрения
точности
и
времени
вычислений,
является
диапазон
значений
k  [50,60] .
Коэффициент ускорения, рассчитанный по (14) для середины оптимального
диапазона k , составил 7.41, 7.7 и 7.83 для ЦФ (7), (8) и (9) соответственно.
На рисунке 17 приведены зависимости найденных минимальных значений ЦФ
с указанием 95% доверительного интервала (а), (б), (в) и числа вычислений ЦФ (7),
(8), (9) (г) от числа детей в каждом поколении m . При этом остальные исследуемые
параметры алгоритма имели следующие значения: k  50, pc  0.75, pm  0.1 .
Из рисунка 17 следует, что увеличение числа детей в каждом поколении m с 2
до 16 приводит к значительному повышению точности нахождения глобального
минимума. При этом количество вычислений ЦФ имеет минимум в диапазоне
значений m  [6,8] при удовлетворительной точности для всех исследованных ЦФ.
Коэффициент ускорения, рассчитанный по (14) для середины оптимального
диапазона m , составил 3.28, 3.39 и 3.45 для ЦФ (7), (8) и (9) соответственно.
На рисунке 18 приведены зависимости найденных минимальных значений ЦФ
с указанием 95% доверительного интервала (а), (б), (в) и числа вычислений ЦФ (7),
(8), (9) (г) отвероятности применения кроссовера p c . При этом остальные
исследуемые параметры алгоритма фиксировались ( k  50, m  10, pm  0.05 ).
Из рисунка 18 видно, что точность нахождения глобального минимума
максимальна в диапазоне значений pc  [0.3,0.7] . Число вычислений ЦФ также
минимально при этих значениях p c для всех рассмотренных ЦФ. Коэффициент
ускорения, рассчитанный по (14) для середины оптимального диапазона pc ,
49
составил 4.35, 4.6 и 4.74 для ЦФ (7), (8) и (9) соответственно.
На рисунке 19 приведены зависимости найденных минимальных значений ЦФ
с указанием 95% доверительного интервала (а), (б), (в) и числа вычислений ЦФ (7),
(8), (9) (г) от вероятности мутации pm . При этом остальные исследуемые параметры
алгоритма имели значения: k  50, m  10, pc  0.75 .
Как видно, увеличение вероятности применения оператора мутации pm с 0.05
до 0.1 приводит к значительному повышению точности нахождения глобального
минимума, но при этом быстро растет количество вычислений. Оптимальным, с
точки зрения точности и времени вычислений, является диапазон значений
pm  [0.06,0.07] .Коэффициент
ускорения, рассчитанный по (14) для середины
оптимального диапазона pm , составил 4.46, 4.72 и 4.86 для ЦФ (7), (8), (9)
соответственно.
Таким образом, в результате численного эксперимента были определены
оптимальные диапазоны параметров первого варианта распараллеливания ГА,
обеспечивающие высокуюточность при приемлемом времени поиска глобального
минимума ЦФ (7), (8), (9) (см. таблицу 4).
Таблица 4 – Оптимальные диапазоны изменения параметров параллельного ГА
k
m
pc
pm
min
50
6
0.3
0.06
max
60
8
0.7
0.07
Оценка эффективности второго варианта параллельного ГА для функций (7),
(8) и (9) осуществлялась путем проведения серии экспериментов при различном
числе узлов параллельной ВС
p
и фиксированных значениях остальных
параметров: k  50, m  10, pc  0.75, pm  0.05 .
Как видно из результатов тестирования (см. рисунок 20), с ростом числа узлов
ВС p с 1 до 30 наблюдается уменьшение доверительного интервала в 7.89, 5.64 и
7.87 раз соответственно для ЦФ (7), (8) и (9), что говорит о значительном
повышении надежности нахождения глобального минимума. При этом число
вычислений ЦФ, а значит, и время работы параллельной ВС, практически не
50
изменяется и составляет в среднем 257, 450, 740для ЦФ (7), (8), (9) соответственно.
а)
б)
в)
г)
 – n  4 ,  – n  6 ,  – n  8
Параметры алгоритма: k  50, m  10, pc  0.75, pm  0.05
Рисунок 20–Зависимость найденного минимального значения ЦФ с указанием 95%
доверительного интервала (а), (б),(в) и числа вычислений ЦФ (г) от количества
параметров оптимизации n и количества параллельных запусков
51
Следовательно, вариант распараллеливания ГА путём множественного
запуска на параллельной ВС обеспечивает значительное увеличение вероятности
нахождения глобального экстремума за счёт более полного исследования области
факторного пространства ЦФ. При этом время выполнения параллельного
алгоритма,пропорциональноечислу вычислений ЦФ, практически не зависит от
числа узлов ВС p и примерно равно времени выполнения алгоритма на одномузле
ВС при одинаковых n .
Таким образом, из результатов тестирования видно, что предложенные
вариантыраспараллеливания
генетического
алгоритма
оптимизации
могут
эффективно применяться для решения задач поиска как глобального минимума
многоэкстремальной ЦФ при наличии явных ограничений на варьируемые
параметры (первый вариант), так и его области (второй вариант).
52
Заключение
В результате научно-исследовательской работы по теме «Разработка
алгоритмов поиска глобальных экстремумов при наличии явных и неявных
ограничений на параллельных вычислительных системах» проведены исследования
возможности
распараллеливания
комплексного
метода
оптимизации
Бокса,
алгоритма оптимизации, основанного на методе имитации отжига и классического
генетического алгоритма оптимизации. При этом были получены следующие
результаты:
 Осуществлена адаптация модифицированного метода условной оптимизации
Бокса
для
выполнения
на
распределённых
и
параллельных
ВС.Экспериментально определены оптимальные с точки зрения надёжности
нахождения глобального экстремума и времени его поиска параметры комплекса
и число узлов ВС.При этом время поиска глобального экстремума оказалось в
несколько раз меньше, чем на одной ЭВМ, а вероятностьего нахождения
значительно выше за счёт одновременного исследования ЦФ в нескольких
областях факторного пространства.
 Предложен вариант распараллеливания алгоритма оптимизации методом
имитации отжига, основанный на многократном повторном запуске процедуры
поиска при одинаковых начальных условиях на параллельных ВС.Определены
зависимости надёжности нахождения глобального минимума от количества
узлов параллельной ВС. Показано, что распараллеленный вариант алгоритма
имитации отжига, использующий схему Больцмановского тушения, позволяет за
небольшое время надёжно находить область глобального минимумаза счёт
одновременного
пространства,
а
исследования
также
то,что
ЦФ
в
различных
выбором
областях
параметров
закона
факторного
изменения
температуры есть возможность обеспечивать баланс между временными
затратами и точностьюпри решении конкретных задач.
 Предложены
два
варианта
распараллеливания
генетических
алгоритмов
оптимизации для случаев сложных и простых ЦФ. В результате численного
эксперимента были определены оптимальные диапазоны параметров первого
53
варианта
распараллеливания
ГА,
обеспечивающие
небольшое
время
поискаглобального минимума ЦФ ивысокую надёжность его нахождения при
выполнении
на
параллельной
ВС.
Тестирование
второго
варианта
распараллеливания ГА, основанного на множественном запуске на параллельной
ВС,показало значительное увеличение вероятности нахождения глобального
экстремума
за
счёт
более
полного
исследования
области
факторного
пространства ЦФ. Время выполнения параллельного алгоритмапри этом
практически не зависело от числа узлов ВС и примерно равнялось времени
выполнения алгоритма на одномузле ВС.
 Разработаны
приложения
на
языке
программирования
C++
для
тестированияпредложенныхпараллельных вариантовалгоритмов оптимизации
(см. приложения А, Б, В).
К опубликованию в журнале «Известия Саратовского университета. Серия
Математика.
Механика.
Информатика»,
входящем
в
перечень
российских
рецензируемых научных журналов, учитываемых ВАК,подготовлена статья,
содержащая полученные в ходе выполнения НИР результаты:
Дружинин И.В., Ерофтиев А.А., Савин А.Н. Применение генетических
алгоритмов для решения задач оптимизации на параллельных и распределённых
вычислительных системах.
Результаты
НИР
были
доложены
на
конференции
«Современные
информационные технологии и ИТ-образование» (Москва, МФТИ, 10 ноября 2011
г.).
Результаты НИР могут быть использованы как в теоретических, так и
прикладных работах при решении оптимизационных задач в различных технических
областях, в том числе при разработке и исследованиях нано- и метаматериалов.
Уровень выполнения НИР сопоставим с известными достижениями в данной
области.
Как видно из отчетных материалов, все исследовательские задачи по проекту
выполнены полностью с должным качеством.
54
Список использованных источников
1. Орлянская, И.В. Современные подходы к построению методов глобальной
оптимизации / Орлянская И.В.//Электронный журнал «Исследовано в России». –
С. 2097–2108. http://zhurnal.ape.relarn.ru/articles/2002/189.pdf (19.05.2009).
2. Банди, Б. Методы оптимизации – М.: Радио и связь, 1988. – С. 128.
3. Савин, А. Н. Модификация комплексного метода условной оптимизации Бокса
для
определения
размеров
замедляющих
систем
по
заданным
электродинамическим характеристикам / Савин А. Н., Шараевский Ю. П.,
Тимофеева
Н.
Е.//
СВЧ-техника
и
телекоммуникационные
технологии:
Материалы 15-ой Междун. Крымской конф. (КрыМиКо2005). –Украина.
Севастополь: Вебер, 2005. –С. 779–780.
4. Kirkpatrick, S. Optimization by simulated annealing. / Kirkpatrick S., Gelatt C.D.,
Vecchi M.P.// Science. v220. 1983. P. 671_680.
5. Ingber, L. Simulated Annealing: Practice versus theory / Ingber L.// Mathematical and
Computer Modelling. v18(11). 1993. P. 29_57.
6. Лопатин, А.С. Метод отжига / Лопатин А.С.// Межвуз. сб. «Стохастическая
оптимизация в информатике». Выпуск 1, 2005. – Санкт-Петербург: изд-во
СПбГУ. С. 133-149.
7. Wilson, J.D.
Designofhigh-efficiencywide-bandwidthcoupled-cavitytraveling-
wavetubephasevelocitytaperswithsimulatedannealingalgorithms
/
Wilson J.D.
//
IEEETrans. ElectronDevices. Vol. 48, pp. 95-100, Jan. 2001.
8. Панченко, Т. В. «Генетические алгоритмы: учебно-методическое пособие» под
ред. Ю. Ю. Тарасевича. – Астрахань: Издательский дом «Астраханский
университет», 2007. – 87с.
9. Eroftiev, A.A. Computing in Application to Global Optimization Problem Solving /
EroftievА.А., TimofeevaN.E, SavinA.N. // Grid and Visualization Systems: MIPRO,
2011 Proceedings of the 34th International Convention.− Zagreb, Croatia: DENONA,
2011. P. 185-190.
10. Калиткин, Н.Н. Численные методы. – М.: Наука, 1978. – С. 512.
55
Приложения
Приложение А. Листинг программы для ЭВМ «Приложение для тестирования
распараллеленного
алгоритма
оптимизации
модифицированным
комплексным методом Бокса»
// functions.hpp
#ifndef _MY_FUNCTIONS_
#define _MY_FUNCTIONS_
#include <vector>
using std::vector;
double target_kuraev(const vector<double>&);
double glimit_kuraev(const vector<double>&);
const vector<double>&ulimit_kuraev();
const vector<double>&llimit_kuraev();
#endif
// functions.cpp
#include "functions.hpp"
#include <cmath>
#include <vector>
using std::vector;
double target_kuraev(const vector<double>&arg) {
return arg[0] * arg[0] + arg[1] * arg[1] - 0.1 * cos(18 * arg[0]) - 0.1 * cos(18 *
arg[1]);
}
double glimit_kuraev(const vector<double>&arg) {
return true;
}
56
const vector<double>&ulimit_kuraev() {
static vector<double> limits(2, 1.0);
return limits;
}
const vector<double>&llimit_kuraev() {
static vector<double> limits(2, -0.5);
return limits;
}
// test_box.hpp
#ifndef _TEST_BOX_
#define _TEST_BOX_
#include <vector>
using namespace std;
class test_box {
public:
/**
* Конструктор
* @paramul массив нижних границ явных ограничений
* @paramuu массив верхних границ явных ограничений
* @paramprecision требуемая точность вычислений
* @paramglimit указатель на функцию неявных ограничений
* @paramtarget_func указатель на целевую функцию
*/
test_box(
const vector<double>&ul,
const vector<double>&uu,
const double precision,
double (*glimit)(const vector<double>&),
double (*target_func)(const vector<double>&));
/**
* @params коэффициент умножения комплекса
* @return количество вычислений целевой функции
*/
unsigned start(unsigned s);
57
/**
* @return найденный минимум
*/
doubleresult();
/**
* @return массив аргументов, соответствующих
*
найденному минимуму
*/
const vector<double>&result_args();
protected:
/**
* @paramfull_limit признак полной проверки ограничений:
*
true - полная (при оптимизации),
*
false - неполная (при построении комплекса)
*/
void limit(const bool full_limit);
/**
* @paramie счетчик количества вычислений целевой функции
* @return значение целевой функции, соответствующее текущему _x
*/
double target_func_box(unsigned &ie);
protected:
vector<double> _ul, _uu, _x;
double _precision;
double _target;
double (*_glimit)(const vector<double>&);
double (*_target_func)(const vector<double>&);
vector<int> _iec;
unsigned _nvar_box, _kvar_box;
bool _glimit_error, _ulimit_error;
};
#endif
58
// test_box.cpp
#include "test_box.hpp"
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <iostream>
using namespace std;
static double random(int range_min, int range_max) {
return (static_cast<double>(rand()) * (range_max - range_min)) / (RAND_MAX + 1);
}
static double random(int range_max) {
return random(0, range_max);
}
test_box::test_box(
const vector<double>&ul,
const vector<double>&uu,
const double precision,
double (*glimit)(const vector<double>&),
double (*target_func)(const vector<double>&)) {
_ul = ul;
_uu = uu;
_precision = precision;
_glimit = glimit;
_target_func = target_func;
_x.resize(_ul.size());
}
double test_box::target_func_box(unsigned &ie) {
ie++;
return _target_func(_x);
}
void test_box::limit(const bool full_limit) {
_glimit_error = !_glimit(_x);
if (full_limit) {
59
for (unsigned i=0; i<_kvar_box; i++) {
_iec[i] = 0;
}
_ulimit_error = false;
for (unsigned i=0; i<_nvar_box; i++) {
if (_x[i] < _ul[i]) {
_iec[i] = 1;
_ulimit_error = true;
}
if (_x[i] > _uu[i]) {
_iec[_nvar_box + i] = 1;
_ulimit_error = true;
}
}
}
}
unsigned test_box::start(unsigned s) {
unsigned ie = 0;
double _fxo, _fr, _sc, _sd, _dm, _d;
/*
Определяем размерность масива параметров (= количество параметров
оптимизации - 1, т.к. нумерация в динамических массивах начинается с 0)
Причём размерность массива параметров должна быть равна размерностям массивов
ограничений
*/
_nvar_box = _ul.size();
/*
Если оптимизация идет по одному параметру, то строим комплекс из 4 точек
*/
if (_nvar_box == 1) {
_kvar_box = 4 * _nvar_box;
}
else {
_kvar_box = s * _nvar_box;
}
/*
Инициализируем служебные открытые массивы (размерности ul, uu, x задаются
перед вызовом подпрограммы)
60
*/
vector<double>
_temp_e(_nvar_box),
_xo(_nvar_box),
_xr(_nvar_box),
_xh(_nvar_box),
_xc(_nvar_box);
vector<double> _f(_kvar_box);
vector< vector<double>> _c(_kvar_box);
for (size_t i=0; i<_c.size(); i++) {
_c[i].resize(_nvar_box);
}
_iec.resize(_kvar_box);
/*
Обнуляем счетчик количества вычислений целевой функции и признак печати
*/
bool _print_ok = false;
// Присвоим центру начальные значения
for (unsigned i=0; i<_nvar_box; i++) {
// вычисляем начальное приближение
_x[i] = (_uu[i] + _ul[i]) / 2.0;
_c[0][i] = _x[i];
_xc[i] = _x[i];
}
// Строим комплекс
// первое значение в комплексе
_f[0] = target_func_box(ie);
// остальные значения в комплексе от i=1 до KVarBox
// Инициализируем генератор случайных чисел по таймеру
srand((unsigned) time(NULL) * clock());
// Вычисляем и запоминаем случайное число в диапазоне [0,255]
unsigned _rand_seed_tmp = static_cast<unsigned>(random(255));
for (unsigned i=1; i<_kvar_box; i++) {
// инициализиреум нахождение равномерно распределённых чисел
srand(_rand_seed_tmp * i);
for (unsigned j=0; j<_nvar_box; j++) {
// Random(64000)/64001.0 - равномерно распределённые вещественные числа
// в диапазоне [0,1]
_c[i][j] = _ul[j] + (random(64000) / 64001.0) * (_uu[j] - _ul[j]);
61
_x[j] = _c[i][j];
}
lbl_640:
// неполная проверка
limit(false);
if (_glimit_error) goto lbl_720;
// Обновим значение центра тяжести
for (unsigned j=0; j<_nvar_box; j++) {
_xc[j] = (i * _xc[j] + _c[i][j]) / (i+1);
}
goto lbl_760;
lbl_720:
for (unsigned j=0; j<_nvar_box; j++) {
_c[i][j] = (_c[i][j] + _xc[j]) / 2.0;
_x[j] = _c[i][j];
}
goto lbl_640;
lbl_760:
_f[i] = target_func_box(ie);
}
/*
Комплекс построен. Упорядочим значения функции и точки,
в которых она вычислена
*/
for (unsignedj=0; j<_kvar_box-1; j++) {
for (unsigned i=j+1; i<_kvar_box; i++) {
if (_f[j] > _f[i]) {
double _f0 = _f[j];
_f[j] = _f[i];
_f[i] = _f0;
for (unsigned l=0; l<_nvar_box; l++) {
_temp_e[l] = _c[j][l];
_c[j][l] = _c[i][l];
_c[i][l] = _temp_e[l];
}
62
}
}
}
// Запомним наименьшее значение функции
double _fm = _f[0];
// Первая точка!
#ifdef _DEBUG
// Распечатаем минимальное значение f[0]
cout.precision(15);
cout << "First point: " << _f[0] << " Ie=" << ie << endl;
#endif
// Зададим коэффициент отражения
double _a = 1.3;
lbl_1190:
for (unsigned l=0; l<_nvar_box; l++) {
/*
Определим центр тяжести наилучших ((KVarBox+1)-1) точек
и запомним наихудшую точку
*/
_xh[l] = _c[_kvar_box-1][l];
_xo[l] = (_kvar_box * _xc[l] - _xh[l]) / (_kvar_box - 1);
// Найдем f[xo]=fxo
_x[l] = _xo[l];
}
_fxo = target_func_box(ie);
// Получим отраженную точку
for (unsignedl=0; l<_nvar_box; l++) {
_xr[l] = (1.0 + _a) * _xo[l] - _a * _xh[l];
_x[l] = _xr[l];
}
/*
Проверка на выпуклость:
Функция невыпукла если значение функции в центре ((KVarBox+1)-1) точек больше
значения функции в худшей из ((KVarBox+1)-1) точек
*/
63
if (_fxo >= _f[_kvar_box - 2]) {
#ifdef _DEBUG
cout << "Function is nonconvex: " << _f[0] << " Ie=" << ie << endl;
#endif
// Заменяем центр ((KVarBox+1)-1) точек на лучшую точку
for (unsigned l=0; l<_nvar_box; l++) {
_xo[l] = _c[0][l];
}
}
// Проверим, допустима ли новая точка
lbl_1490:
// полная проверка
limit(true);
if (!_ulimit_error && !_glimit_error) goto lbl_2000;
/*
Если точка является допустимой, то перейдем к оператору 2000
и вычислим значение функции
*/
if (_ulimit_error) {
// Если явные ограничения нарушены, то поместим точку внутрь границ
for (unsigned j=0; j<_nvar_box; j++) {
if (_iec[j] == 1) {
_xr[j] = _ul[j] + 0.00001;
_x[j] = _xr[j];
}
if (_iec[_nvar_box + j] == 1) {
_xr[j] = _uu[j] - 0.00001;
_x[j] = _xr[j];
}
}
}
lbl_1800:
if (!_glimit_error) goto lbl_2000;
/*
Если неявные ограничения нарушены, то переместимся
на половину расстояния к 'центру тяжести'
64
*/
for (unsigned l=0; l<_nvar_box; l++) {
_xr[l] = (_xr[l] + _xo[l]) / 2.0;
_x[l] = _xr[l];
}
goto lbl_1490;
lbl_2000:
_fr = target_func_box(ie);
/*
Если новое значениие - наихудшее, то переместимся на половину
расстояния к точке XO и вычислим новое значение функции
*/
if (_fr < _f[_kvar_box - 1]) goto lbl_2400;
for (unsigned l=0; l<_nvar_box; l++) {
_xr[l] = (_xr[l] + _xo[l]) / 2.0;
_x[l] = _xr[l];
}
gotolbl_1490;
// Обновим XC и заменим наихудшую точку новой точкой
lbl_2400:
_f[_kvar_box - 1] = _fr;
for (unsigned l=0; l<_nvar_box; l++) {
_xc[l] = (_kvar_box * _xc[l] - _c[_kvar_box - 1][l] + _xr[l]) / _kvar_box;
_c[_kvar_box - 1][l] = _xr[l];
}
// Упорядочим значения функции и точки, в которых она вычислена
for (unsigned j=0; j<_kvar_box-1; j++) {
for (unsigned i=j+1; i<_kvar_box; i++) {
if (_f[j] > _f[i]) {
double _f0 = _f[j];
_f[j] = _f[i];
_f[i] = _f0;
for (unsigned l=0; l<_nvar_box; l++) {
_temp_e[l] = _c[j][l];
_c[j][l] = _c[i][l];
_c[i][l] = _temp_e[l];
}
65
}
}
}
// Если наименьшее значение функции уменьшено, выставим признак печати
if (_f[0] < _fm) {
_print_ok = true;
}
/*
Если уменьшение функции не обнаружено, то проверку критерия
завершения поиска минимума не производим
*/
if (!_print_ok) goto lbl_1190;
// Найдем среднее значение функции в комплексе
_sc = 0.0;
for (unsigned i=0; i<_kvar_box; i++) {
_sc += _f[i];
}
_sc /= _kvar_box;
// Найдем среднеквадратичное отклонение функции в комплексе
_sd = 0.0;
for (unsigned i=0; i<_kvar_box; i++) {
_sd += (_f[i] - _sc) * (_f[i] - _sc);
}
_sd /= _kvar_box;
// Найдем максимальное расстояние между точками комплекса
_dm = 0.0;
for (unsigned i=0; i<_kvar_box-1; i++) {
for (unsigned j=i+1; j<_kvar_box; j++) {
_d = 0.0;
for (unsigned l=0; l<_nvar_box; l++) {
_d += (_c[i][l] - _c[j][l]) * (_c[i][l] - _c[j][l]);
}
_d = sqrt(_d);
if (_d > _dm) _dm = _d;
}
}
66
if (_print_ok) {
// Новая точка
#ifdef _DEBUG
// Распечатаем минимальное значение f[0]
cout<< "Newpoint: " << _f[0] << " Ie=" <<ie<<endl;
#endif
// Запомним минимальное значение и обнулим признак печати
_fm = _f[0];
_print_ok = false;
}
// Проверка сходимости
if (_sd > _precision * 0.0001 || _dm > _precision) goto lbl_1190;
/*
Минимум найден
*/
// Присвоим значение выходным параметрам x
for (unsigned l=0; l<_nvar_box; l++) {
_x[l] = _c[0][l];
}
// Присвоим значение выходному параметру Target (функция цели)
_target = target_func_box(ie);
#ifdef _DEBUG
// Распечатаем минимальное значение и кол-во вычислений ie целевой функции
cout << "Minimum: " << _target << " Ie=" << ie << endl;
#endif
return ie;
}
double test_box::result() {
return _target;
}
const vector<double>&test_box::result_args() {
return _x;
}
67
// main.cpp
#include "test_box.hpp"
#include "functions.hpp"
#include <iostream>
#include <sstream>
#include <vector>
using namespace std;
int main(int argc, char* argv[]) {
if (argc < 3) {
cout << "Usage:" << endl;
cout << "box <EPS><S>" << endl;
cout << "\tEPS - convergence precision" << endl;
cout << "\tS - complex multiplier" << endl;
return 1;
}
stringstream ss;
ss << argv[1] << " " << argv[2];
double eps;
unsigned s;
ss >> eps >> s;
test_box box(llimit_kuraev(), ulimit_kuraev(), eps, glimit_kuraev, target_kuraev);
unsigned count = box.start(s);
double result = box.result();
cout.precision(15);
cout << "Minimum: " << result << endl;
cout << "Iteration count: " << count << endl;
return 0;
}
68
Приложение Б. Листинг программы для ЭВМ «Приложение для тестирования
распараллеленного
алгоритма
оптимизации
методом
отжигапо
схеме
Больцмановского тушения»
//annealing_engine.hpp
#ifndef ANNEALING_ENGINE_HPP
#define ANNEALING_ENGINE_HPP
#include <vector>
#include <limits>
#include <utility>
#include <boost/random.hpp>
namespace annealing
{
using std::vector;
usingnamespaceboost;
/// базовй класс функтора на основе которого пользователь строит свой
template <size_t N, typename T = double>
class annealing_functor
{
public:
typedef T arg_type;
static const size_t arg_num = N;
/// явные ограничения снизу
static const vector<T>&lower_explicit_limits()
{
static vector<T> limits(N, -std::numeric_limits<T>::infinity());
return limits;
}
/// явные ограничения сверху
static const vector<T>&upper_explicit_limits()
{
static vector<T> limits(N, std::numeric_limits<T>::infinity());
return limits;
}
annealing_functor() :
x(arg_num, 0)
69
{ }
protected:
template <typename F> friend class annealing_engine;
vector<T>x;
};
/// основной класс реализации метода отжига
template <typename F>
class annealing_engine
{
public:
typedef typename F::arg_type arg_type;
/**
* @brief конструктор метода отжига
* @parammin_temp минмальная температура
* @paraminit_temp начальная температура
* @paramtemp_coeff температурный коэффициент
* @paramfunc пользовательский функтор с входной функцией
*/
annealing_engine(double min_temp, double init_temp, double temp_coeff,
F func = F()) throw (std::invalid_argument);
/**
* @brief запустить метод отжига
* @paramn максимальное количество итераций алгоритма
* @parameps точность сходимости
* @return возвращает количество итераций алгоритма
*/
unsigned start(unsigned n = 0, arg_type eps = arg_type());
/**
* @brief получить результат работы метода отжига
*/
arg_type result() const { return _energy; }
private:
/// получиь случайное значение аргумента n в его допустимой области
arg_type randx(size_t n);
/// постоянные параметры алогритма
const double _min_temp, _init_temp, _temp_coeff;
F _func;
mt19937 _rng;
/// энергия и состояние системы
70
arg_type _energy;
vector<arg_type> _state;
};
}
#endif /* ANNEALING_ENGINE_HPP */
// annealing_engine.cpp
#include <cmath>
#include <ctime>
#include <cstdlib>
#include <boost/random.hpp>
namespace annealing
{
template <typename F>
annealing_engine<F>::annealing_engine(double min_temp, double init_temp,
double temp_coeff, F func) throw (std::invalid_argument) :
_min_temp(min_temp), _init_temp(init_temp), _temp_coeff(temp_coeff),
_func(func), _state(F::arg_num)
{
if (min_temp <= 0)
throw std::invalid_argument("Minimal tempreture must be positive");
if (init_temp <= 0)
throw std::invalid_argument("Initial tempreture must be positive");
if (temp_coeff <= 0 || temp_coeff >= 1)
throw std::invalid_argument("Tempreture coefficient must be between
0 and 1");
_rng.seed(static_cast<unsigned>(std::time(0) + clock()));
}
template <typename F>
unsigned annealing_engine<F>::start(unsigned n, arg_type eps)
{
unsignediteration_count = 0;
//
устанавливаем
произвольные
начальное
энергию в ней
for (size_t i = 0; i < F::arg_num; i++)
_state[i] = _func.x[i] = randx(i);
_energy = _func();
71
состояние
системы
и
считаем
double current_temp = _init_temp;
// основной цикл алгоритма
while (current_temp > _min_temp) {
iteration_count++;
// генерируем новое состояние в соответствие с явными ограничениями
normal_distribution<arg_type> norm_dist(arg_type(), current_temp);
variate_generator<mt19937&,
normal_distribution<arg_type>>
normal_sampler(_rng, norm_dist);
bool next_iteration = false;
vector<arg_type> new_state(F::arg_num);
for (size_t i = 0; i < F::arg_num && !next_iteration; i++) {
new_state[i] = _func.x[i] = _state[i] + normal_sampler();
if (new_state[i] > F::upper_explicit_limits()[i] ||
new_state[i] < F::lower_explicit_limits()[i]
) {
current_temp *= _temp_coeff;
next_iteration = true;
}
}
// если новое состояние не удовлетворяет явным ограничениям, то
переходим на следующую итерацию
if (next_iteration) continue;
// если новая энергия системы меньше текущей,- переходим в новое
состояние
arg_type new_energy = _func();
if (new_energy < _energy) {
_state = new_state;
_energy = new_energy;
current_temp *= _temp_coeff;
continue;
}
// иначе переходим в новое состояние с некоторой вероятностью
uniform_real<double> uniform_dist;
variate_generator<mt19937&,
uniform_real<double>>
uniform_sampler(_rng, uniform_dist);
double probability = exp((_energy - new_energy) / current_temp);
if (probability > uniform_sampler()) {
_state = new_state;
_energy = new_energy;
current_temp *= _temp_coeff;
}
}
72
return iteration_count - 1;
}
template <typename F>
typename annealing_engine<F>::arg_type annealing_engine<F>::randx(size_t n)
{
uniform_real<arg_type>
uniform_dist(F::lower_explicit_limits()[n],
F::upper_explicit_limits()[n]);
variate_generator<mt19937&, uniform_real<arg_type>> uniform_sampler(_rng,
uniform_dist);
return uniform_sampler();
}
}
// main.cpp
#include <cmath>
#include <iostream>
#include <sstream>
#include "annealing_engine.hpp"
using namespace std;
using namespace annealing;
class my_functor4 : public annealing_functor<4, double>
{
public:
double operator()()
{
return x[0] * x[0] + x[1] * x[1] + x[2] * x[2] + x[3] * x[3] - 0.1 *
cos(3 * x[0]) 0.2 * cos(2 * x[1]) - 0.5 * cos(5 * x[2]) - 0.6 * cos(x[3]);
}
static const vector<double>&lower_explicit_limits()
{
static vector<double> limits(4, -0.5);
return limits;
}
static const vector<double>&upper_explicit_limits()
{
static vector<double> limits(4, 1);
return limits;
73
}
};
class my_functor6 : public annealing_functor<6, float>
{
public:
float operator()()
{
return x[0] * x[0] + x[1] * x[1] + x[2] * x[2] + x[3] * x[3] + x[4] *
x[4] + x[5] * x[5] 0.1 * cos(3 * x[0]) - 0.2 * cos(2 * x[1]) - 0.3 * cos(5 *
x[2]) - 0.5 * cos(x[3]) 0.1 * cos(2 * x[4]) - 0.2 * cos(x[5]);
}
static const vector<float>&lower_explicit_limits()
{
static vector<float> limits(6, -0.5);
return limits;
}
static const vector<float>&upper_explicit_limits()
{
static vector<float> limits(6, 1);
return limits;
}
};
class my_functor8 : public annealing_functor<8, double>
{
public:
double operator()()
{
return x[0] * x[0] + x[1] * x[1] + x[2] * x[2] + x[3] * x[3] + x[4] *
x[4] +
x[5] * x[5] + x[6] * x[6] + x[7] * x[7] - 0.1 * cos(3 * x[0])
- 0.2 * cos(2 * x[1]) 0.2 * cos(5 * x[2]) - 0.4 * cos(x[3]) -
0.1 * cos(2 * x[4])
- 0.2 * cos(x[5]) 0.1 * cos(4 * x[6]) - 0.1 * cos(2 * x[7]);
}
static const vector<double>&lower_explicit_limits()
{
static vector<double> limits(8, -0.5);
74
return limits;
}
static const vector<double>&upper_explicit_limits()
{
static vector<double> limits(8, 1);
return limits;
}
};
int main(int argc, char **argv)
{
if (argc < 4) {
cout << "Usage:" << endl;
cout << "annealing <MIN_TEMP><INIT_TEMP><TEMP_COEFF>" << endl;
cout << "\tMIN_TEMP - minimal tempreture" << endl;
cout << "\tINIT_TEMP - initial tempreture" << endl;
cout << "\tTEMP_COEFF - tempreture coefficient" << endl;
return 1;
}
stringstream ss;
ss << argv[1] << " " << argv[2] << " " << argv[3];
double min_temp, init_temp, temp_coeff;
ss >> min_temp >> init_temp >> temp_coeff;
try {
annealing_engine<my_functor4> annealing(min_temp, init_temp, temp_coeff);
unsigned iteration_count = annealing.start();
cout << "Iteration count " << iteration_count << endl;
cout.precision(15);
cout << "Minimum is " << annealing.result() << endl;
} catch (const exception &e) {
cerr << "Exception: " << e.what() << endl;
return 1;
}
return 0;
}
//реализация шаблонного класса
#include "annealing_engine.cpp"
75
Приложение В. Листинг программы для ЭВМ «Приложение для тестирования
распараллеленного алгоритма оптимизации генетическим алгоритмом»
// individual.hpp
#ifndef INDIVIDUAL_HPP
#define INDIVIDUAL_HPP
#include <vector>
#include <stdexcept>
namespace ga
{
/// класс хромосомы
template <typename G>
class chromosome
{
public:
/**
* @briefконструкторхромосомы
* @paramgenes_numколичествохромосомухромосомы
*/
explicit chromosome(size_t genes_num) :
_genes(genes_num)
{ }
/**
* @brief получить ссылку на ген
* @paramnum номер гена в хромосоме начиная с 0
* @return ссылка на ген
*/
G &get_gene(size_t num) throw(std::out_of_range)
{
return _genes.at(num);
}
/**
* @brief получить количество генов в хромосоме
* @return количество генов в хромосоме
*/
size_t genes_amount() const { return _genes.size(); }
private:
std::vector<G> _genes;
};
76
/// класс особи
template <typename T>
class individual
{
public:
/**
* @briefконструкторособи
* @paramchromosomes_num количество хромосом у особи
* @paramgenes_in_chromosome количество генов в хромосоме
*/
individual(size_t chromosomes_num, size_t genes_in_chromosome) :
_chromosomes(chromosomes_num, chromosome<T>(genes_in_chromosome))
{ }
/**
* @brief получить ссылку на n-ую хромосому
* @param номер хромосомы начиная с 0
* @return ссылка на хромосому
*/
chromosome<T>&get_chromosome(size_t num) throw(std::out_of_range)
{
return _chromosomes.at(num);
}
/**
* @brief получить количество хромосом у индивидума
*/
size_t chromosomes_amount() const { return _chromosomes.size();
/// оператор сравнения для сортировки
bool operator<(const individual &rhs) const { return false; }
private:
std::vector<chromosome<T>> _chromosomes;
};
}
#endif /* INDIVIDUAL_HPP */
// ga_engine.hpp
#ifndef GA_ENGINE_HPP
#define GA_ENGINE_HPP
#include <vector>
77
}
#include <limits>
#include <utility>
#include "individual.hpp"
namespace ga
{
usingstd::vector;
/// базовй класс функтора на основе которого пользователь строит свой
template <size_t N, typename T = double>
class ga_functor
{
public:
typedef T arg_type;
static const size_t arg_num = N;
/// явные ограничения снизу
static const vector<T>&lower_explicit_limits()
{
static vector<T> limits(N, -std::numeric_limits<T>::infinity());
return limits;
}
/// явные ограничения сверху
static const vector<T>&upper_explicit_limits()
{
static vector<T> limits(N, std::numeric_limits<T>::infinity());
return limits;
}
ga_functor() :
x(arg_num, 0)
{ }
protected:
template <typename F> friend class ga_engine;
vector<T>x;
};
/// основной класс реализации генетического алгоритма
template <typename F>
class ga_engine
{
public:
typedef typename F::arg_type arg_type;
78
// первый элемент пары - значение ЦФ для данной особи
typedef vector<std::pair<arg_type, individual<arg_type>>> population;
/**
* @brief конструктор генетического алгоритма
* @paramk размер популяции
* @paramm количество детей в каждом поколении
* @parampm вероятность применения мутации
* @parampc вероятность применения скрещивания
* @paramfunc пользовательский функтор с входной функцией
*/
ga_engine(unsigned k, unsigned m, double pc, double pm, F func = F())
throw (std::invalid_argument);
/**
* @brief запустить генетический алгоритм
* @paramn максимальное количество итераций алгоритма
* @parameps точность сходимости популяции
* @return возвращает количество итераций алгоритма
*/
unsigned start(unsigned n, arg_type eps);
/**
* @brief получить результат работы генетического алгоритма
*/
arg_type result() const { return _population[0].first; }
private:
/// получиь случайное значение аргумента n в его допустимой области
static arg_type randx(size_t n);
/// оператор скрещивания
void crossover(size_t first_parent, size_t second_parent,
size_t first_child, size_t second_child);
/// оператор мутации
void mutation(size_t child);
/// постоянные параметры алогритма
constunsigned _k, _m;
const double _pm, _pc;
F _func;
unsigned _iteration_count;
population _population;
};
}
#endif /* GA_ENGINE_HPP */
79
// ga_engine.cpp
#include <cmath>
#include <ctime>
#include <cstdlib>
#include <algorithm>
namespace ga
{
template <typename F>
ga_engine<F>::ga_engine(unsigned k, unsigned m, double pc, double pm, F func)
throw (std::invalid_argument) :
_k(k), _m(m), _pm(pm), _pc(pc),
_func(func),
_population(k, std::make_pair(0, individual<arg_type>(F::arg_num, 1)))
{
if (k <= m) throw std::invalid_argument("K <= M");
if (m % 2 != 0)
throw std::invalid_argument("M must be even");
if (pc < 0 || pc > 1)
throw std::invalid_argument("PC must be from 0 to 1");
if (pm < 0 || pm > 1)
throw std::invalid_argument("PM must be from 0 to 1");
std::srand(std::time(NULL) + clock());
}
// основной цикл алгоритма
template <typename F>
unsigned ga_engine<F>::start(unsigned n, arg_type eps)
{
_iteration_count = 0;
// устанавливаем произвольные начальные значения особей и подсчитываем
значения ЦФ в ней
for (unsigned i = 0; i < _k; i++) {
for (size_t j = 0; j < F::arg_num; j++)
_population[i].second.get_chromosome(j).get_gene(0)
_func.x[j] = randx(j);
_population[i].first = _func();
}
// основной цикл алгоритма
while (_iteration_count++ <n) {
// сортируем популяцию по значению ЦФ
sort(_population.begin(), _population.end());
// если популяция сошлась то получаем результат и выходим
80
=
if ((*(_population.end()-1)).first - (*_population.begin()).first <
eps)
return _iteration_count - 1;;
// заменяем m наименее приспособленных особей на порожденных детей
for (unsigned i = _k - _m; i < _k; i += 2) {
//выбираем 2-х родителей
size_t first_parent, second_parent;
do {
first_parent = rand() % (_k - _m);
second_parent = rand() % (_k - _m);
} while (first_parent == second_parent);
// применяем операции кроссовера и мутации
crossover(first_parent, second_parent, i, i + 1);
mutation(i);
mutation(i + 1);
// пересчитываем значение ЦФ у детей
for (size_t j = 0; j < F::arg_num; j++)
_func.x[j]
=
_population[i].second.get_chromosome(j).get_gene(0);
_population[i].first = _func();
for (size_t j = 0; j < F::arg_num; j++)
_func.x[j]
=
_population[i
+
1].second.get_chromosome(j).get_gene(0);
_population[i + 1].first = _func();
}
}
sort(_population.begin(), _population.end());
return _iteration_count - 1;
}
template <typename F>
typename ga_engine<F>::arg_type ga_engine<F>::randx(size_t n)
{
arg_type
dx
=
F::upper_explicit_limits()[n]
-
F::lower_explicit_limits()[n];
return rand() * dx / RAND_MAX + F::lower_explicit_limits()[n];
}
template <typename F>
void ga_engine<F>::crossover(size_t first_parent, size_t second_parent,
size_t
second_child)
81
first_child,
size_t
{
_population[first_child].second = _population[first_parent].second;
_population[second_child].second = _population[second_parent].second;
for
(size_t
i
=
0;
i
<
_population[first_child].second.chromosomes_amount() &&
i
<
_population[second_child].second.chromosomes_amount(); i++)
{
if (static_cast<double>(rand()) / RAND_MAX < _pc)
// обмениваемся генами по разрыву 0
for
(size_t
j
=
0;
j
<
_population[first_child].second.get_chromosome(i).genes_amount() &&
j
<
_population[second_child].second.get_chromosome(i).genes_amount(); j++)
swap(_population[first_child].second.get_chromosome(i).get_gene(j),
_population[second_child].second.get_chromosome(i).get_gene(j));
}
}
template <typename F>
void ga_engine<F>::mutation(size_t child)
{
for (size_t i = 0; i < _population[child].second.chromosomes_amount();
i++)
if (static_cast<double>(rand()) / RAND_MAX < _pm)
// мутируют все гены хромосомы
for
(size_t
j
=
0;
j
<
_population[child].second.get_chromosome(i).genes_amount(); j++) {
arg_type
&gene
_population[child].second.get_chromosome(i).get_gene(j);
gene = (gene + randx(i)) / 2;
}
}
}
// main.cpp
#include <cmath>
#include <iostream>
#include <sstream>
82
=
#include <vector>
#include "ga_engine.hpp"
using namespace std;
using namespace ga;
class my_functor4 : public ga_functor<4, double>
{
public:
double operator()()
{
return x[0] * x[0] + x[1] * x[1] + x[2] * x[2] + x[3] * x[3] - 0.1 *
cos(3 * x[0]) 0.2 * cos(2 * x[1]) - 0.5 * cos(5 * x[2]) - 0.6 * cos(x[3]);
}
static const vector<double>&lower_explicit_limits()
{
static vector<double> limits(4, -0.5);
return limits;
}
static const vector<double>&upper_explicit_limits()
{
static vector<double> limits(4, 1);
return limits;
}
};
class my_functor4_proper : public ga_functor<4, double>
{
public:
double operator()()
{
return x[0] * x[0] + x[1] * x[1] + x[2] * x[2] + x[3] * x[3] - 0.1 *
cos(18 * x[0]) 0.1 * cos(18 * x[1]) - 0.1 * cos(18 * x[2]) - 0.1 * cos(18 *
x[3]);
}
static const vector<double>&lower_explicit_limits()
{
static vector<double> limits(4, -0.5);
return limits;
}
83
static const vector<double>&upper_explicit_limits()
{
static vector<double> limits(4, 1);
return limits;
}
};
class my_functor6 : public ga_functor<6, double>
{
public:
double operator()()
{
return x[0] * x[0] + x[1] * x[1] + x[2] * x[2] + x[3] * x[3] + x[4] *
x[4] + x[5] * x[5] 0.1 * cos(3 * x[0]) - 0.2 * cos(2 * x[1]) - 0.3 * cos(5 *
x[2]) - 0.5 * cos(x[3]) 0.1 * cos(2 * x[4]) - 0.2 * cos(x[5]);
}
static const vector<double>&lower_explicit_limits()
{
static vector<double> limits(6, -0.5);
return limits;
}
static const vector<double>&upper_explicit_limits()
{
static vector<double> limits(6, 1);
return limits;
}
};
class my_functor6_proper : public ga_functor<6, double>
{
public:
double operator()()
{
return x[0] * x[0] + x[1] * x[1] + x[2] * x[2] + x[3] * x[3] + x[4] *
x[4] + x[5] * x[5] 0.1 * cos(18 * x[0]) - 0.1 * cos(18 * x[1]) - 0.1 * cos(18 * x[2])
- 0.1 * cos(18 * x[3]) 0.1 * cos(18 * x[4]) - 0.1 * cos(18 * x[5]);
}
static const vector<double>&lower_explicit_limits()
84
{
static vector<double> limits(6, -0.5);
return limits;
}
static const vector<double>&upper_explicit_limits()
{
static vector<double> limits(6, 1);
return limits;
}
};
class my_functor8 : public ga_functor<8, double>
{
public:
double operator()()
{
return x[0] * x[0] + x[1] * x[1] + x[2] * x[2] + x[3] * x[3] + x[4] *
x[4] +
x[5] * x[5] + x[6] * x[6] + x[7] * x[7] - 0.1 * cos(3 * x[0])
- 0.2 * cos(2 * x[1]) 0.2 * cos(5 * x[2]) - 0.4 * cos(x[3]) -
0.1 * cos(2 * x[4])
- 0.2 * cos(x[5]) 0.1 * cos(4 * x[6]) - 0.1 * cos(2 * x[7]);
}
static const vector<double>&lower_explicit_limits()
{
static vector<double> limits(8, -0.5);
return limits;
}
static const vector<double>&upper_explicit_limits()
{
static vector<double> limits(8, 1);
return limits;
}
};
class my_functor8_proper : public ga_functor<8, double>
{
public:
double operator()()
{
85
return x[0] * x[0] + x[1] * x[1] + x[2] * x[2] + x[3] * x[3] + x[4] *
x[4] +
x[5] * x[5] + x[6] * x[6] + x[7] * x[7] - 0.1 * cos(18 * x[0]) 0.1 * cos(18 * x[1]) 0.1 * cos(18 * x[2]) - 0.1 * cos(18 * x[3]) -
0.1 * cos(18 * x[4])
- 0.1 * cos(18 * x[5]) 0.1 * cos(18 * x[6]) - 0.1 * cos(18 * x[7]);
}
static const vector<double>&lower_explicit_limits()
{
static vector<double> limits(8, -0.5);
return limits;
}
static const vector<double>&upper_explicit_limits()
{
static vector<double> limits(8, 1);
return limits;
}
};
int main(int argc, char **argv)
{
#ifdef _TESTS
if (argc < 8) {
#else
if (argc < 7) {
#endif
std::cout << "Usage:" << std::endl;
std::cout << "ga <K><M><PC><PM><N><EPS>" << std::endl;
std::cout << "\tK - population size" << std::endl;
std::cout << "\tM - number of children in each generation" << std::endl;
std::cout << "\tPC - probability of crossover" << std::endl;
std::cout << "\tPM - probability of mutation" << std::endl;
std::cout << "\tN - max iteration count" << std::endl;
std::cout << "\tEPS - convergence precision" << std::endl;
return 1;
}
stringstream ss;
ss << argv[1] << " " << argv[2] << " " << argv[3] << " "
<< argv[4] << " " << argv[5] << " " << argv[6];
86
unsigned k, m, n;
double pc, pm, eps;
ss >> k >> m >> pc >> pm >> n >> eps;
try {
#ifdef _TESTS
ss.clear();
ss << argv[7];
unsigned tests;
ss >> tests;
vector<double> results;
vector<unsigned> par_summaries;
for (unsigned i=0; i<tests; ++i) {
#endif
ga_engine<my_functor8_proper> *ga = new ga_engine<my_functor8_proper>(k, m, pc,
pm);
unsigned iteration_count = ga->start(n, eps);
//std::cout << "Iteration count: " << iteration_count << std::endl;
unsigned ser_comp_count = k;
//cout << "Serial f computation count: " << ser_comp_count << endl;
unsigned par_comp_count = (2 * iteration_count);
//cout << "Parallel f computation count: " << par_comp_count << endl;
unsigned par_summary = (2 * iteration_count + k);
//cout << "Parallel summary: " << par_summary << endl;
double alpha = ((double) k) / (m * iteration_count + k);
cout.precision(6);
//cout << "Serial part: " << alpha << endl;
double max_acc_rate = 1.0 / (alpha + 2.0 * (1.0 - alpha) / m);
//cout << "Max acceleration rate: " << max_acc_rate << endl;
std::cout.precision(15);
//std::cout << "Minimum: " << ga->result() << std::endl;
#ifdef _TESTS
results.push_back(ga->result());
par_summaries.push_back(par_summary);
delete ga;
87
}
cout.precision(6);
double min_avg = 0.0;
for (unsigned i=0; i<tests; ++i) {
min_avg += results[i];
}
min_avg /= tests;
cout << "Average minimum: " << min_avg << endl;
double sigma = 0.0;
for (unsigned i=0; i<tests; ++i) {
sigma += (min_avg - results[i]) * (min_avg - results[i]);
}
sigma = sqrt(sigma / tests);
//cout << "Sigma: " << sigma << endl;
double upper_value = min_avg + 1.96 * sigma / sqrt(static_cast<double>(tests));
double lower_value = min_avg - 1.96 * sigma / sqrt(static_cast<double>(tests));
cout << "Upper value: " << upper_value << endl;
cout << "Lower value: " << lower_value << endl;
cout << "Upper-lower: " << (upper_value - lower_value) << endl;
double par_count_avg = 0.0;
for (unsigned i=0; i<tests; ++i) {
par_count_avg += par_summaries[i];
}
par_count_avg = par_count_avg / tests;
cout << "Summary count average: " << par_count_avg << endl;
#endif
} catch (const std::exception &e) {
std::cerr << "Exception: " << e.what() << std::endl;
return 1;
}
return 0;
}
//реализация шаблонного класса
#include "ga_engine.cpp"
88
Download