Numerabilità e numerabilità
Prima di procedere coi razionali, un distillato della puntata precedente (lussu, ci sei ancora? dove ti abbiamo perso?).
Ho provato a distinguere tra numerabilità di un insieme ed enumerabilità, un concetto che ho solo implicitamente definito, e per fortuna essendo io un fisico e questo un blog non ho nè la volontà nè l’urgenza di definire in maniera più rigorosa. In pratica per enumerare intendo costruire un algoritmo che mette in fila gli elementi dell’insieme, e la discussione dell’altro giorno dovrebbe avervi convinto che dato un qualsiasi linguaggio di programmazione, posso costruire un insieme numerabile che non è enumerabile da nessun programma scritto in quel linguaggio di programmazione. D’altra parte io stesso ho enumerato i numeri busy beaver
BB(1), BB(2), BB(3) …
per cui è chiaro che esiste un altro linguaggio di programmazione, più potente, in grado di svolgere questo compito, ma allora esisterà un insieme non enumerabile da qualsiasi programma in quest’altro linguaggio di programmazione etc. etc. Insomma il solito tram-tram quotidiano quando si tratta di delicate questioni di incompletezza: dato un sistema di assiomi di finita informazione, esistono proposizioni vere non dimostrabili in tale sistema perché la forza espressiva di tale linguaggio è limitata. Concetto concisamente espresso da un vero matematico nei commenti allo scorso post:
I possibili output di macchine di Turing sono numerabili; infatti esistono una quantità numerabile di macchine di Turing. Invece, l’insieme potenza dei numeri naturali è più che numerabile. È quindi ovvio che esistono insiemi di naturali che non sono computabili.
Il cortocircuito si crea perché, cosa piuttosto notevole, con la nostra intelligenza, che ci permette di fare salti tra diversi piani logici, possiamo costruire in quel linguaggio di programmazione fatti metalogici. Per esempio siccome sia le istruzioni che l’input/output di una macchina di Turing sono stringhe di bits, possiamo dare in pasto una macchina di Turing ad una macchina di Turing, o analogalmente possiamo assegnare un numero ad una proposizione che parla di una teoria dei numeri.
In soldoni, numerabilità non equivale ad enumerabilità. Il primo concetto dice che esiste una biiezione, il secondo che tale biiezione è esprimibile in un certo linguaggio. Il Princeton Companion to Mathematics dice che
An infinite set is called countable if it has the same size as the natural numbers […] This is exactly the same as saying that we can list the elements of the set.
E’ giusta, ma avrei da obiettare su quell’exactly.
E’ finita l’informazione
Sui razionali possiamo procedere allegramente, servono solo per parlare di informazione. Tutti sanno (??) che i razionali, numeri esprimibili come frazioni di numeri interi, sono quanti i numeri interi e quindi quanti i naturali. Non è difficile metterli in fila tutti, trovando una strategia per muoversi nel piano numeratore-denominatore. Per esempio la strategia di Cantor, visualizzabile qui. Parentesi: sebbene gli interi sembrino il doppio dei naturali, e i razionali sembrino quanto gli interi al quadrato (tutte le scelte possibili di denominatore per tutte le scelte possibili di numeratore), eppure l’infinito è sempre lo stesso (detto aleph_0):
Questo fatto si riassume molto ecologicamente considerando questo argomento. Sia i numeri naturali, che interi, che razionali sono esprimibili con una quantità finita di informazione, con un numero finito di cifre. Per esempio, un razionale può essere espresso con le cifre di denominatore/numeratore, oppure con il suo sviluppo decimale, che come ben sappiamo è periodico: basta specificare quali e quante sono le cifre del periodo e lo abbiamo determinato univocamente. Se ci mettiamo in base due, tutti questi numeri si possono esprimere come stringhe finite di bits:
11010010 . 1100101001 0110 0110 0110 0110 …
ove abbiamo diviso la parte intera (a sinistra della virgola), un primo pezzo di sviluppo decimale dopo la virgola e la parte periodica. I razionali sono quindi stringhe di un numero finito di bits, scelti in maniera aleatoria: ognuno dei bits può assumere il valore che vuole*.
Oltre i razionali
L’informazione di un messaggio dipende da come decido di decodificarla, per cui in ogni messaggio esiste infinita e nulla informazione. Il fatto che io abbia deciso che stringhe finite di bits siano numeri razionali dipende dal fatto che, dato un linguaggio meta-logico, interpreto quella sequenza in un certo modo (sviluppi decimali, frazioni). Avrei potuto sceglierne un altro ed ottenere altri numeri. Per esempio, la sezione aurea, un numero magico che gode della proprietà
Se sostituite al denominatore della frazione nuovamente la definizione, potete scrivere la sezione aurea come frazione continua:
Una frazione continua è un qualsiasi numero esprimibile come
ove abbiamo anche indicato una delle tante possibili notazioni per frazione continua, che mette in luce il fatto che questi numeri si possono scrivere tutti come stringhe. In particolare, la sezione aurea è data dalla stringa periodica [1;1,1,1,1…]. La sezione aurea non è un numero razionale; lo si può infatti esprimere in termini della radice di 5
e si può mostrare che la radice di 5 non è un numero razionale. Più precisamente, la sezione aurea è un numero irrazionale quadratico, soluzione di un’equazione quadratica
con a,b,c coefficienti razionali (o interi). Si può mostrare (Eulero-Lagrange) che ogni frazione continua periodica è un numero irrazionale quadratico, e viceversa. Ma una frazione continua periodica è rappresentabile come una stringa con una parte decimale aperiodica ed un periodo, e pertanto la stessa stringa può rappresentare un numero razionale o un numero irrazionale quadratico, a seconda della decodificazione della stringa, ossia del linguaggio che stiamo usando.
Siamo quindi ai numeri algebrici generici, radici (soluzioni) di equazioni algebriche del tipo:
ossia tutti i numeri che si possono scrivere in termini di radici di numeri razionali. Anche questi si possono scrivere con finita informazione, per esempio specificando tutti i coefficienti a_0 … a_n, ognuno dei quali è razionale e quindi di finita informazione.
La carreggiata
Tutto questo discorso per dire una cosa. Una stringa finita di bits (con punteggiatura, vedi sotto) ha un certo significato a seconda del linguaggio che la decodifica, il quale a sua volta è anche scritto in una stringa finita di bits (per esempio i 10 000 caratteri del post di oggi). Con finita informazione ed un opportuno linguaggio che la interpreta, logico o meta-logico, posso andare molto lontano. Le domande che ora mi pongo, e a cui non darò risposta, sono:
- gli assiomi dei numeri reali, che contengono finita informazione, comprendono tutti i reali comunemente intesi come stringhe infinite di bit aleatori?
- se no, posso costruire un modello dei reali con soli numeri computabili (piano logico) o definibili in qualche linguaggio (piano meta-logico?)? Quanto sarebbe grande, un simile modello?
* Qui mi sarebbe piaciuto parlare di enumerazione dei razionali, ma mi sono inceppato perché l’argomento è molto più complesso di quello che pensavo a prima vista. Ed in ogni caso è del tutto inessenziale. Il sunto è questo. Posso costruire una macchina di Turing che enumera i naturali, ovverosia una macchina di Turing che dato un naturale permette di determinare univocamente il suo rappresentativo rispetto ad una biiezionee, e questo mi pare abbastanza banale. E’ semplicemente la macchina che restituisce l’input. Possiamo costruire una macchina di Turing che permette di determinare un rappresentativo intero di ogni razionale? La cosa è delicata. Sul piano di Cantor, non c’è problema. Ma il linguaggio che stiamo usando richiede l’utilizzo di simboli non conosciuti da una macchina di Turing, per esempio la linea rapporto
o, se scriviamo un razionale in cifre decimali, la barra periodica
Stiamo comunque sempre usando un linguaggio non decodificabile da una macchina di Turing. Questo è il nostro imprinting meta-logico: NOI sappiamo farlo. Ma possiamo farne a meno?
Mettiamoci quindi in testa che vogliamo trovare un algoritmo per enumerare i razionali. Consideriamo di lavorare solo sulla notazione decimale. Per comodità supponiamo di muoverci solo verso destra (anche se una macchina di Turing potrebbe continuare a muoversi da destra a sinistra, ma a lungo andare si romperebbe…). Potremmo alternare nello sviluppo decimale una cifra dello sviluppo ed una della parte intera, per esempio. Concentriamoci quindi sui razionali che cominciano per "0.".
Per enumerare tutti i razionali senza sviluppo periodico o con sviluppo periodico che comincia immediatamente dopo la virgola, possiamo usare la notazione
0 . [0] 11001001 = def = 0 . 11001001
0 . [1[ 0110 = def = 0. 0110 0110 0110…
La prima cifra decimale in verità è un’istruzione per decidere se lo sviluppo successivo è finito (nel caso 0) o periodico (nel caso 1). OK, adesso vogliamo fare un programma per enumerare anche quelli con sviluppo periodico che inizia dopo un certo numero di cifre significative aperiodiche dopo la virgola. Come faccio?
0 . [101] (11) 11001 110
= 11001 110 110 110 …
Da qualche parte nella stringa devo infilare un’istruzione che mi dica quante cifre aperiodiche (tra parentesi quadre) e quante cifre periodiche (tra parentesi tonde) devo mettere dopo la virgola. Il problema è che non posso sapere quante cifre avranno questi due numeri di controllo, per cui dovrei inserire altri numeri di controllo che mi dicano quante cifre avranno i numeri di controllo successivi
0 . 11101011111001110
-> 0 . [[11]] ((10)) [101] (11) 11001 110
= 0. 11001 110 110 110 …
Il numero di cifre di un numero avrà sempre un numero di cifre inferiore a quello del numero stesso, e scendendo scendendo si arriva fino alla stringa minima, che è quella di lunghezza 2 (lunghezza 1 non va bene, è l’unica stabile).
Sembra piuttosto complicato… proviamo con una strategia diversa. Alterniamo una cifra dello sviluppo decimale aperiodico ad una cifra del periodo
0 . 10 01 10 01 01 00 10 10 10 00 10
= ? = 0 . 1010011101 01011000000 01011000000 …
= ? = 0 . 1010011101 01011 01011 01011 …
Anche in questo caso c’è una certa ambiguità, dovuta al fatto che dobbiamo decodificare con lo stesso linguaggio, fatto di 0 ed 1, simboli metalogici.
Come vedete ideare un algoritmo completo è così facile. In primo luogo, bisogna che le stringhe siano ben formate, cioè che il numero totale di caratteri sia consistente con l’informazione contenuta nei caratteri di controllo. Poi c’è il rischio che la stringa non abbia interpretazione univoca, oppure che non sia esaustiva. Francamente non so dire se esista un metodo corretto, o se sia possibile dimostrare con un paradosso di tipo Russel i numeri razionali sono numerabili ma non enumerabili nello stesso linguaggio in cui sono espressi. Ho smesso di pensarci sennò mi viene il malditesta. Megio lasciar stare per ora. Stay tuned.