Questo è un lungo testo. Per favore abbi pazienza. In poche parole, la domanda è: esiste un algoritmo di ordinamento radix sul posto praticabile ?
Preliminare
Ho un numero enorme di piccole stringhe a lunghezza fissa che usano solo le lettere “A”, “C”, “G” e “T” (sì, l'hai indovinato: DNA ) che voglio ordinare.
Al momento, io uso std::sort
che utilizza introsort in tutte le implementazioni comuni del STL . Funziona abbastanza bene. Tuttavia, sono convinto che l' ordinamento radix si adatta perfettamente al mio set di problemi e dovrebbe funzionare molto meglio nella pratica.
Dettagli
Ho testato questo presupposto con un'implementazione molto ingenua e per input relativamente piccoli (dell'ordine di 10.000) questo era vero (beh, almeno più del doppio della velocità). Tuttavia, il tempo di esecuzione si riduce in modo abissale quando la dimensione del problema aumenta ( N > 5.000.000).
Il motivo è ovvio: radix sort richiede la copia di tutti i dati (più di una volta nella mia ingenua implementazione, in realtà). Ciò significa che ho inserito ~ 4 GiB nella mia memoria principale, il che ovviamente uccide le prestazioni. Anche se non fosse così, non posso permettermi di usare così tanta memoria poiché le dimensioni del problema in realtà diventano ancora più grandi.
Casi d'uso
Idealmente, questo algoritmo dovrebbe funzionare con qualsiasi lunghezza di stringa compresa tra 2 e 100, sia per il DNA che per il DNA5 (che consente un carattere jolly aggiuntivo "N"), o persino il DNA con codici di ambiguità IUPAC (risultanti in 16 valori distinti). Tuttavia, mi rendo conto che tutti questi casi non possono essere coperti, quindi sono contento di qualsiasi miglioramento della velocità che ottengo. Il codice può decidere dinamicamente a quale algoritmo inviare.
Ricerca
Sfortunatamente, l' articolo di Wikipedia sull'ordinamento di Radix è inutile. La sezione relativa a una variante sul posto è spazzatura completa. La sezione NIST-DADS sull'ordinamento radix è accanto a inesistente. C'è un articolo dal suono promettente chiamato Efficient Adaptive In-Place Radix Sorting che descrive l'algoritmo "MSL". Sfortunatamente, anche questo documento è deludente.
In particolare, ci sono le seguenti cose.
Innanzitutto, l'algoritmo contiene diversi errori e lascia molto inspiegabile. In particolare, non dettaglia la chiamata di ricorsione (presumo semplicemente che aumenti o riduca alcuni puntatori per calcolare i valori di spostamento e maschera correnti). Inoltre, utilizza le funzioni dest_group
e dest_address
senza fornire definizioni. Non riesco a vedere come implementarli in modo efficiente (cioè in O (1); almeno dest_address
non è banale).
Ultimo ma non meno importante, l'algoritmo raggiunge la posizione sul posto scambiando gli indici di array con elementi all'interno dell'array di input. Questo ovviamente funziona solo su array numerici. Ho bisogno di usarlo sulle stringhe. Certo, potrei semplicemente rovinare la digitazione forte e andare avanti supponendo che la memoria tollererà la mia memorizzazione di un indice a cui non appartiene. Ma questo funziona solo finché riesco a comprimere le mie stringhe in 32 bit di memoria (assumendo numeri interi a 32 bit). Sono solo 16 caratteri (ignoriamo per il momento quel registro 16> (5.000.000)).
Un altro articolo di uno degli autori non fornisce alcuna descrizione accurata, ma fornisce l'autonomia di MSL come sub-lineare, il che è assolutamente sbagliato.
Ricapitolando : c'è qualche speranza di trovare un'implementazione di riferimento funzionante o almeno un buon pseudocodice / descrizione di un ordinamento radix sul posto funzionante che funzioni su stringhe di DNA?