Este es un texto largo. Por favor, tenga paciencia conmigo. En resumen, la pregunta es: ¿existe un algoritmo de clasificación de radix in situ viable ?
Preliminar
Tengo una gran cantidad de pequeñas cadenas de longitud fija que solo usan las letras "A", "C", "G" y "T" (sí, lo has adivinado: ADN ) que quiero clasificar.
Por el momento, uso el std::sort
que usa introsort en todas las implementaciones comunes de STL . Esto funciona bastante bien. Sin embargo, estoy convencido de que la clasificación de radix se adapta perfectamente a mi conjunto de problemas y debería funcionar mucho mejor en la práctica.
Detalles
He probado esta suposición con una implementación muy ingenua y para entradas relativamente pequeñas (del orden de 10,000) esto era cierto (bueno, al menos más del doble de rápido). Sin embargo, el tiempo de ejecución se degrada abismalmente cuando el tamaño del problema aumenta ( N > 5,000,000).
La razón es obvia: la ordenación de radix requiere copiar todos los datos (más de una vez en mi ingenua implementación, en realidad). Esto significa que he puesto ~ 4 GiB en mi memoria principal, lo que obviamente mata el rendimiento. Incluso si no fuera así, no puedo permitirme usar tanta memoria ya que los tamaños del problema en realidad se vuelven aún mayores.
Casos de uso
Idealmente, este algoritmo debería funcionar con cualquier longitud de cadena entre 2 y 100, tanto para el ADN como para el ADN5 (que permite un carácter comodín adicional "N"), o incluso ADN con códigos de ambigüedad IUPAC (que dan como resultado 16 valores distintos). Sin embargo, me doy cuenta de que todos estos casos no pueden ser cubiertos, así que estoy contento con cualquier mejora de velocidad que obtengo. El código puede decidir dinámicamente a qué algoritmo enviar.
Investigación
Desafortunadamente, el artículo de Wikipedia sobre la clasificación de radix es inútil. La sección sobre una variante en el lugar es basura completa. La sección NIST-DADS en clasificación de radios está al lado de inexistente. Hay un documento prometedor llamado Efficient Adaptive In-Place Radix Sorting que describe el algoritmo "MSL". Desafortunadamente, este documento también es decepcionante.
En particular, hay las siguientes cosas.
Primero, el algoritmo contiene varios errores y deja mucho sin explicar. En particular, no detalla la llamada de recursión (simplemente supongo que incrementa o reduce algún puntero para calcular los valores actuales de desplazamiento y máscara). Además, utiliza las funciones dest_group
y dest_address
sin dar definiciones. No veo cómo implementarlos de manera eficiente (es decir, en O (1); al menos dest_address
no es trivial).
Por último, pero no menos importante, el algoritmo logra el lugar intercambiando índices de matriz con elementos dentro de la matriz de entrada. Obviamente, esto solo funciona en matrices numéricas. Necesito usarlo en cadenas. Por supuesto, podría simplemente teclear con fuerza y seguir adelante asumiendo que la memoria tolerará que almacene un índice donde no pertenece. Pero esto solo funciona mientras pueda exprimir mis cadenas en 32 bits de memoria (suponiendo enteros de 32 bits). Eso es solo 16 caracteres (ignoremos por el momento que 16> log (5,000,000)).
Otro artículo de uno de los autores no ofrece una descripción precisa, pero da el tiempo de ejecución de MSL como sub-lineal, lo cual es completamente incorrecto.
Para recapitular : ¿Hay alguna esperanza de encontrar una implementación de referencia que funcione o al menos un buen pseudocódigo / descripción de un tipo de radix en el lugar que funcione que funcione en cadenas de ADN?