MACCHINE di TURING

    Il concetto di algoritmo (ossia "procedimento meccanico di calcolo") è usato intuitivamente sin dalla antichità, ma solo all'inizio del XX secolo viene messa a fuoco l'esigenza di formalizzarlo, in relazione a vari aspetti:
–  nello sviluppo dei primi sistemi formali si richiede che le regole di derivazione siano "meccaniche", ... in modo, ad es., da poter controllare in modo oggettivo se una dimostrazione è corretta o no;
–  nei primi tentativi di definire il concetto di casualità si incappa nel problema di precisare (per contrasto) quali siano i procedimenti "meccanici";
–  il fattore scatenante è, però, più specificamente, la necessità di dare alcune risposte ad alcuni problemi di risolviblità algortimica (esiste un algortimo per calcolare la soluzione di un certo problema?), sorti sia nell'ambito della teoria dei numeri che in quello della nascente logica matematica (decidere se una formula è un teorema o no, ...):  per stabilire delle risposte negative (non esiste alcun algortimo che ...) occorre aver definito che cosa è un algortimo.

    L'idea avuta da Turing (vedi), e più o meno contemporaneamente da Post, fu quella di cercare di formalizzare matematicamente il concetto di calcolatore. A noi può sembrare un'idea non particolarmente originale, ma occorre tener conto che si era intorno al 1930, 15 anni prima che nascessero i primi computer.

    Turing analizzò il concetto di algortimo, interpretandolo come un procedimento computazionale svolto dall'uomo, e ne individuò gli aspetti essenziali (non è necessaria la bidimensionalità del foglio, basta leggere/scrivere un simbolo per volta, ...).  Alla fine (siamo nel 1936) lo precisò descrivendolo mediante un opportuno modello:  un nastro suddiviso in celle potenzialmente illimitato, una quantità finita di simboli, un simbolo per cella, una "testina" di lettura/scrittura che può osservare (ossia, operare una scansione di) una cella per volta, può scrivervi un simbolo e spostarsi a sinistra o a destra di una cella per volta.

    Vediamo l'idea di macchina porgrammabile messa a punto da Turing in una versione intermedia tra la versione originale e quella messa a punto da Post, a noi più facile da comprendere  (questa versione fu presentata da Martin Davis in "What is a computation?", nel famoso libro "Mathematics Today" curato - nel 1978 - da Lynn Arthur Steen; chi è interessato ad approfondimenti può vedere qui).

Simboli sul nastro: solo 0 e 1
Programma: lista di istruzioni dei tipi seguenti (la semantica è descritta tra parentesi):
  print 0  (scrivi 0 nella cella su cui sei posizionato e passa alla istruzione successiva)
  print 1  (scrivi 1 nella cella su cui sei posizionato e passa alla istruzione successiva)
  go left  (spostati nella prima cella a sinistra e passa alla istruzione successiva)
  go right  (spostati nella prima cella a destra e passa alla istruzione successiva)
  go to step N if 1 is scanned  (se sei su un 1 vai alla istruzione n-esima)
  go to step N if 0 is scanned  (se sei su uno 0 vai alla istruzione n-esima)
  stop  (fermati)
Convenzione su input e output:
• la testina di lettura è inizialmente posizionata all'inizio della stringa di input (massima porzione del nastro nella sua configurazione iniziale che ha "1" come primo e ultimo carattere);
• il programma termina quando arriva alla istruzione stop o quando ha eseguito l'ultima istruzione o dovrebbe passare a un'istruzione che non è nell'elenco.

Esempio. Il programma a lato se la stringa di input è "11" (o una qualunque altra stringa costituita non da un solo "1") si ferma, mentre se la stringa di input è "1" continua ad spostare la testina di lettura a destra, girando senza fine sulle prime due istruzioni. Volendo, potrei non mettere stop.
Se indico con n la stringa costituita da n+1 "1" posso dire che il programma calcola la funzione a 1 input e 1 output che a n positivo associa n stesso e che non è definita in 0.
   go right 
   go to step 1 if 0 is scanned 
   stop 
Il programma a lato, invece, calcola la funzione predecessore, definita solo per input positivi. Infatti si sposta a destra e se incontra ancora un "1" torna indietro sull"1" inziale e lo sostituisce con uno "0", e si arresta. Se invece incontra "0" continua senza fine a spostarsi a destra.    go right 
   go to step 1 if 0 is scanned 
   go left 
   print 0 

Analogamente posso rappresentare la coppia 3,2 e la terna 3,0,2 con le stringhe 11110111 e 1111010111:  ogni numero naturale n con n+1 "1" e il separatore con uno "0".

Altri esempi di programmi di Turing-Post, in cui aggiungo i numeri delle istruzioni (che non fanno parte del programma) per facilitare la lettura.

Addizionatore. Idea: tolgo due "1" e trasformo in "1" lo "0" di separazione; se c'è un solo "1" prima di "0" mi limito a togliere questo "1": "111011", cioè (2,1), viene trasformato in "1111", cioè 3.   1  print 0 
  2  go right 
  3  go to step 8 if 0 is scanned 
  4  print 0 
  5  go right 
  6  go to step 5 if 1 is scanned 
  7  print 1 
  8  stop 
Esempio: 2+5
input:  1110111111
      0000000000000000011101111110000000000000000
p 0   0000000000000000001101111110000000000000000
go R  0000000000000000001101111110000000000000000
p 0   0000000000000000000101111110000000000000000
go R  0000000000000000000101111110000000000000000
go R  0000000000000000000101111110000000000000000
p 1   0000000000000000000111111110000000000000000
stop  0000000000000000000111111110000000000000000
output:  11111111

print 0 
go left 
go to step 2 if 1 is scanned  
print 1 
go right 
go to step 5 if 1 is scanned 
print 1 
go right 
go to step 1 if 1 is scanned 
10 stop 
Duplicatore (duplica stringhe di 1, ovvero a N associa 2N+1). Idea: man mano cancello un "1", ne aggiungo "1" a sinistra e lo riscrivo, poi mi sposto a destra e faccio lo stesso con un nuovo "1".

Tutte le altre formalizzazioni del concetto di algoritmo messe a punto più o meno negli stessi anni sono risultate essere equivalenti a questa. E tutti gli algortimi messi a punto nell'ambito della matematica sono risultati rappresentabili mediante programmi di Turing-Post. Possiamo, quindi, assumere questa come definizione di algortimo (l'assunzione di questa descrizione del concetto di algoritmo come sua definizione è nota come tesi di Church).

Per approfondimenti, vedi qui, qui e qui