Docente: Giuseppe Scollo
Università di Catania, sede di Comiso (RG)
Facoltà di Scienze Matematiche, Fisiche e Naturali
Corso di Studi in Informatica applicata, AA 2007-8
origini incerte (v. (Lagarias, 1985) per saperne di più):
riscopertoa più riprese, motivo per cui è noto con più nomi: Collatz, Syracuse, Kakutani, Hasse, Ulam, 3x+1, ...
formulazione ufficiale
del Problema: sia
f : N+
→ N+
definita dalle regole seguenti:
è vero che l'applicazione iterata di f converge sempre a 1 ?
o, in altri termini, che f* ha il ciclo 1 → 4 → 2 → 1 quale (unico) attrattore?
Mathematics is not yet ready for such problems
(Erdös)
non ci poniamo l'obiettivo di risolvere il Problema (congettura: risposta positiva)
ci interessa il comportamento dinamico di f*
concetti di base della dinamica di f* :
l'accertamento che un x sia un CR richiede la certezza che nessun y < x abbia lo stesso ritardo: → calcolo del ritardo D(y) per tutti gli y < x ?
non necessariamente, poiché varie leggi pongono in relazione i ritardi di traiettorie confluenti in uno stesso punto
tali leggi possono rendere più spedita la ricerca dei CR, che tuttavia richiede una esplorazione esaustiva dello spazio di ricerca
questa può essere facilmente parallelizzata partizionando lo spazio di ricerca in intervalli disgiunti, esplorati da istanze indipendenti di un programma di ricerca, opportunamente parametrizzato, ciascuna delle quali produca un insieme di candidati CR
ipotesi: siano noti tutti i CR minori di un dato M
obiettivo: trovare tutti i nuovi CR minori di N > M
al cuore della ricerca dei CR è la funzione di calcolo del ritardo
l'esecuzione più rapida è quella ... di cui si può fare a meno :)
la confluenza di traiettorie in uno stesso punto comporta che la presenza di CR si possa escludere da certe classi di congruenza
per n > 0, le traiettorie di 8n+5 e 8n+4 confluiscono a 6n+4 dopo lo stesso numero di passi (3), dunque D(8n+5) = D(8n+4) → 8n+5 non può essere un CR
ciò si generalizza alle classi di congruenza (2k-2 + (k mod 2)2k-1 - 1) (mod 2k), k > 2
un'approssimazione limitata (e.g. k=17), è efficientemente realizzabile con un setaccio
costanti e strutture dati:
const unsigned short xsl = 15; const unsigned int xs = USHRT_MAX + 1; // cioè 2^16 = 65536 const unsigned int xr[xsl] = { 5, 3, 23, 15, 95, 63, 383, 255, 1535, 1023, 6143, 4095, 24575, 16383, 98303}; bool sieve[xs];
calcolo del setaccio:
for (int i = 0; i < xs; i++) sieve[i] = 1; for (int j = 0, m = 4; j < xsl; m *= 2, j++) for (int i = xr[j]/2; i < xs; i += m) sieve[i] = 0;
applicazione del setaccio:
unsigned short i = ( x / 2 ) % xs; if (sieve[i]) { ... }
tutte le traiettorie convergenti a 1 prima o poi cadono sotto 2t, per qualsiasi t > 0
il calcolo del ritardo può dunque essere reso più celere mediante il precalcolo e la memorizzazione di D(n) per ogni n < 2t,
si aggiunge quindi D(n) al ritardo parzialmente calcolato di x non appena la traiettoria di x raggiunge un qualsiasi n < 2t
in base a criteri, dipendenti dall'architettura hardware, simili a quelli di scelta ottimale della dimensione del setaccio:
risulta migliore una soglia bassa (t fra 8 e 16), dipendente dalla dimensione della cache
l'utilità del taglio in coda deriva da altre tecniche di ottimizzazione, come vedremo appresso
due DR sono consecutivi se non c'è alcun DR di valore intermedio fra loro
≤
D(x1)
si può sfruttare questo fatto per abbandonare anzitempo il calcolo del
ritardo di traiettorie senza speranza
:
≥
M
può essere un CR solo se ha un ritardo di almeno
u
≤
d + D(x1)
pregio di questa tecnica:
auto-ottimizzante
!
il progresso della ricerca dei CR
prima o poi permette di
le soglie di taglio in testa e di taglio in coda si combinano come qui si illustra:
l'efficacia del taglio in testa varia al variare dell'intervallo di ricerca
attualmente è in uso una sequenza di 7 soglie di taglio (per valori decrescenti), ottimizzata su base empirica, per l'esplorazione oltre 257
in forma semplificata, le principali costanti attualmente in uso per il taglio in testa sono così definite (per macchina a 64 bit):
#define CutOffWindowSize 7 const short int coth 2054 // cut-off threshold for v. 11.06.07 const unsigned long dr2th [CutOffWindowSize] = { 12769884180266527ul, 7579309213675935ul, 3586720916237671ul, 100759293214567ul, 3743559068799ul, 202485402111ul, 4578853915ul }; const short int dr1d[CutOffWindowSize] = { 1958, 1919, 1874, 1662, 1443, 1255, 1050 };
una piccola accelerazione del calcolo del ritardo si ottiene rimpiazzando la funzione f con T, definita come f sui numeri pari, mentre per x dispari si ha:
⌈
x/2⌉
chiaramente, se la T-traiettoria da x a 1 ha A applicazioni di questa regola e E applicazioni del dimezzamento dei pari, allora D(x) = 2A + E
l'interesse a T deriva dall'esistenza di una permutazione dei residui (mod 2k), definita dal k-prefisso del cosiddetto vettore di parità delle T-traiettorie, cioè la sequenza binaria, dipendente da x, definita da vi(x) = (T ix) mod 2
si possono dunque definire 2k composizioni distinte di k passi di applicazione di T, e decidere quale di esse si debba applicare a x solo in base al valore del residuo x (mod 2k) : ne risulta una notevole accelerazione del calcolo, mediante tecniche di pre-processing
anche la scelta ottimale del fattore di accelerazione k dipende dalla dimensione della cache, ma:
soluzione: controllo dell'accelerazione, vale a dire, accelerazione più moderata
sebbene si adoperino macchine a 64 bit, una parola di memoria non basta alla rappresentazione di molti dei valori attraversati da traiettorie con origine nell'attuale intervallo di ricerca
l'aritmetica delle traiettorie 3x+1 è relativamente semplice da realizzare per numeri rappresentati da 2 parole, quando si calcola il ritardo procedendo un passo alla volta nella traiettoria
buona parte dell'aumento di complessità può però essere affrontato in sede di pre-elaborazione delle costanti in gioco, dunque senza compromettere le prestazioni del programma di ricerca dei CR
la formulazione impiegata nel software attualmente in uso soddisfa questo requisito, e fornisce una definizione induttiva (in k), dei coefficienti che intervengono nell'espressione, che ne permette l'impiego in sede di pre-elaborazione; v. (Scollo, 2008) per dettagli