Este é um texto longo. Por favor, tenha paciência comigo. Resumindo, a questão é: existe um algoritmo de classificação de raiz no local viável ?
Preliminares
Eu tenho um grande número de pequenas cadeias de comprimento fixo que usam apenas as letras "A", "C", "G" e "T" (sim, você adivinhou: DNA ) que quero classificar.
No momento, eu uso o std::sort
que usa introsort em todas as implementações comuns do STL . Isso funciona muito bem. No entanto, estou convencido de que a classificação por radix se encaixa perfeitamente no meu conjunto de problemas e deve funcionar muito melhor na prática.
Detalhes
Testei essa suposição com uma implementação muito ingênua e, para entradas relativamente pequenas (da ordem de 10.000), isso era verdade (bem, pelo menos mais do que o dobro da velocidade). No entanto, o tempo de execução diminui enormemente quando o tamanho do problema se torna maior ( N > 5.000.000).
O motivo é óbvio: a classificação radix requer a cópia de todos os dados (mais de uma vez na minha implementação ingênua, na verdade). Isso significa que coloquei ~ 4 GiB na memória principal, o que obviamente mata o desempenho. Mesmo se não, não posso me dar ao luxo de usar tanta memória, pois os tamanhos dos problemas realmente se tornam ainda maiores.
Casos de Uso
Idealmente, esse algoritmo deve funcionar com qualquer comprimento de cadeia entre 2 e 100, tanto para o DNA quanto para o DNA5 (que permite um caractere curinga adicional "N"), ou mesmo DNA com códigos de ambiguidade IUPAC (resultando em 16 valores distintos). No entanto, percebo que todos esses casos não podem ser cobertos, por isso estou feliz com qualquer melhoria de velocidade que recebo. O código pode decidir dinamicamente para qual algoritmo enviar.
Pesquisa
Infelizmente, o artigo da Wikipedia sobre classificação radix é inútil. A seção sobre uma variante no local é um lixo completo. A seção NIST-DADS na classificação de raiz é quase inexistente. Existe um artigo que parece promissor, chamado Efficient Adaptive Radix Sorting, que descreve o algoritmo "MSL". Infelizmente, este artigo também é decepcionante.
Em particular, existem as seguintes coisas.
Primeiro, o algoritmo contém vários erros e deixa muita coisa inexplicável. Em particular, ele não detalha a chamada de recursão (simplesmente presumo que ela aumente ou reduz algum ponteiro para calcular os valores atuais de mudança e máscara). Além disso, ele usa as funções dest_group
e dest_address
sem fornecer definições. Não consigo entender como implementá-las com eficiência (ou seja, em O (1); pelo menos dest_address
não é trivial).
Por último, mas não menos importante, o algoritmo alcança o local, trocando os índices da matriz por elementos dentro da matriz de entrada. Obviamente, isso funciona apenas em matrizes numéricas. Eu preciso usá-lo em cordas. Claro, eu poderia simplesmente estragar a digitação forte e seguir em frente, assumindo que a memória toleraria que eu armazenasse um índice onde não pertence. Mas isso só funciona desde que eu possa espremer minhas strings em 32 bits de memória (assumindo números inteiros de 32 bits). São apenas 16 caracteres (vamos ignorar no momento que 16> log (5.000.000)).
Outro artigo de um dos autores não fornece uma descrição precisa, mas fornece o tempo de execução do MSL como sub-linear, o que é totalmente errado.
Recapitulando : Existe alguma esperança de encontrar uma implementação de referência de trabalho ou pelo menos um bom pseudocódigo / descrição de uma classificação de raiz no local que funcione que funcione em seqüências de DNA?