Это длинный текст. Пожалуйста, потерпите меня. Вопрос сводится к следующему: существует ли работоспособный алгоритм сортировки по основанию ?
предварительный
У меня есть огромное количество маленьких строк фиксированной длины, которые используют только буквы «A», «C», «G» и «T» (да, вы уже догадались: ДНК ), которые я хочу отсортировать.
На данный момент я использую, std::sort
который использует интросорт во всех распространенных реализациях STL . Это работает довольно хорошо. Тем не менее, я убежден, что радикальная сортировка идеально подходит для моей задачи и должна работать намного лучше на практике.
подробности
Я проверил это предположение с очень наивной реализацией и для относительно небольших входных данных (порядка 10000) это было правдой (ну, по крайней мере, более чем в два раза быстрее). Тем не менее, время выполнения ужасно ухудшается, когда размер проблемы становится больше ( N > 5 000 000).
Причина очевидна: радикальная сортировка требует копирования всех данных (на самом деле, не раз в моей наивной реализации). Это означает, что я поместил ~ 4 ГиБ в мою основную память, что, очевидно, снижает производительность. Даже если это не так, я не могу позволить себе использовать столько памяти, поскольку размеры проблем на самом деле становятся еще больше.
Случаи использования
В идеале этот алгоритм должен работать с любой длиной строки от 2 до 100, для ДНК, а также для ДНК5 (которая допускает дополнительный подстановочный знак «N»), или даже для ДНК с кодами неоднозначности IUPAC (в результате получается 16 различных значений). Тем не менее, я понимаю, что все эти случаи не могут быть покрыты, поэтому я доволен любым улучшением скорости, которое я получаю. Код может динамически решать, какой алгоритм отправить.
Исследовательская работа
К сожалению, статья в Википедии о радикальной сортировке бесполезна. Раздел о варианте на месте - полная чушь. Раздел NIST-DADS для сортировки по основанию почти отсутствует. Есть многообещающая статья под названием « Эффективная адаптивная сортировка по месту нахождения радиксов», в которой описывается алгоритм «MSL». К сожалению, эта статья тоже разочаровывает.
В частности, есть следующие вещи.
Во-первых, алгоритм содержит несколько ошибок и оставляет много необъяснимых. В частности, он не детализирует рекурсивный вызов (я просто предполагаю, что он увеличивает или уменьшает некоторый указатель для вычисления текущих значений сдвига и маски). Также он использует функции dest_group
и dest_address
не дает определения. Я не вижу, как реализовать это эффективно (то есть в O (1); по крайней мере dest_address
, не тривиально).
Наконец, что не менее важно, алгоритм достигает на месте путем замены индексов массива элементами внутри входного массива. Это очевидно работает только на числовых массивах. Мне нужно использовать его на строки. Конечно, я мог бы просто прокрутить строгую типизацию и продолжить, предполагая, что память будет терпеть мое хранение индекса там, где он не принадлежит. Но это работает только до тех пор, пока я могу втиснуть свои строки в 32-битную память (при условии, что 32-битные целые числа). Это всего 16 символов (на данный момент давайте игнорируем 16> log (5 000 000)).
Другая статья одного из авторов не дает точного описания вообще, но она дает время выполнения MSL как сублинейное, что совершенно неверно.
Напомним : есть ли надежда найти работающую эталонную реализацию или, по крайней мере, хороший псевдокод / описание работающей радикальной сортировки на месте, которая работает со строками ДНК?