В настоящее время я работаю над проблемой NP-полной и для этой цели реализовал персональный генетический алгоритм. Результаты больше, чем я мог ожидать. С хорошо спроектированной функцией фитнеса и тщательной настройкой популяции/мутации, я думаю, GA может быть отличным инструментом в некоторых случаях.
Во всяком случае, теперь я ищу метаэвристический (GA, имитированный отжиг...), способный производить оптимальный перетасовки.
Перемешиваясь, я имею в виду, в этом контексте, непредвзятую (à la Fisher-Yates) случайную перестановку конечного множества. Как колода карт. Огромная (~ 500! Перестановки).
Значения этого набора все разные. Никаких столкновений не ожидается.
Из-за этого противоречия у меня есть некоторые трудности для реализации решения GA. Действительно, перетасованные значения не могут использоваться в качестве генов. Легко понять, почему:
#include <iostream>
#include <vector>
#define SPLICING 50 // 50|50 one-point crossover
int crossover(int gene, int DNA_length, int A, int B)
{if (gene < (SPLICING*DNA_length)/100) return A; else return B;}
int main() {
std::vector<int> A, B, C;
A = { 3, 4, 8, 12, 2, 0, 9, 7, 10, 20 };
B = { 8, 10, 3, 4, 20, 0, 7, 9, 2, 12 };
int DNA_length = int(A.size());
for (int i=0; i<DNA_length; i++) {
C.push_back(crossover(i, DNA_length, A[i], B[i]));
if (i == DNA_length/2) std::cout << "| ";
std::cout << C[i] << " ";}
}
Выход: 3 4 8 12 2 | 0 7 9 2 12
Имеются два столкновения (2, 12).
Мой ожидаемый результат выглядит примерно так: 3 4 8 12 2 | 0 7 9 10 20 (без столкновения, идеальная перетасовка исходного набора).
Затем мне нужно закодировать порядок этих значений, чтобы избежать таких трудностей.
Наивный способ состоит в том, чтобы идентифицировать каждое значение с помощью уникального ключа. Но созданное тогда множество является порядковым, потому что оно относится к последовательности значений.
Похоже, что функция кроссовера имеет дело с обыденностью ДНК родителей. Но я не могу окунуться в вопрос о смешивании двух нелинейно упорядоченных порядковых подмножеств (фрагментов ДНК родителей) ординального набора (целая ДНК) без столкновения!
Возможно, я могу полагаться только на мутацию для конвергенции. Нет выбора, нет родителей/детей и только функция подкачки в одном наборе (отдельная ДНК). Короче: не очень убедительно.
На самом деле легко переставить порядковые числа в единственном конечном множестве (например, тривиально: первое становится седьмым, второе, десятое и т.д.). Но я не уверен, имеет ли смысл говорить, что первая из множества А становится седьмой, когда вторая из множества В становится десятой части нового набора.
Тогда, мой вопрос:
На ваш взгляд, может ли обыденность набора перетасоваться с использованием функции кроссовера в контексте генетического алгоритма? Если нет, можете ли вы предложить более эффективный метаэвристический подход для этой цели, чем метод грубой силы, восхождение или генетический алгоритм?
Спасибо.
То, что вы ищете, называется генетическими алгоритмами на основе порядка. У вас есть много основанных на заказе операторов кроссовера и мутаций, предназначенных для работы с такими проблемами. Самый простой оператор кроссовера работает следующим образом:
Вы можете увидеть пример из моей книги на рисунке ниже (извините, но описания на португальском языке - пожалуйста, сравните с приведенным выше списком):
Вы можете выполнять поиск в Интернете для операторов, основанных на заказе, или, если хотите, просмотрите цифры из моей книги в книге " My Geneetic Algorithm". Цифры, которые вас интересуют, относятся к главе 10 (вы можете использовать переводчик Google для понимания легенд).
Вам не нужно забывать, что книга использует последовательные номера - если у вас нет повторений, все объясненные понятия действительны для вашей проблемы.
Я надеюсь, что это помогает.
1 4 5 0 2 3 6 7
, это довольно хорошо. Что хорошего в этом? Например, это 1 рядом с 4, где бы они ни встречались в строке, или это 4 находится точно во второй позиции? Вы можете посмотреть на разные операторы, которые сохраняют разные свойства хороших родителей, и это может сильно повлиять на производительность.