Perché un linguaggio imperativo sia completo, Turing deve avere:
- Ciclo condizionale
- Numero arbitrario di variabili
FRACTRAN è un linguaggio composto da una serie di frazioni che memorizza i suoi dati negli esponenti dei numeri primi.
Diciamo che vuoi aggiungere due numeri: 2 a 3 b diventa 5 ab
455 11 1 3 11 1
---, -, -, -, -, -
33 13 11 7 2 3
Questo è un programma FRACTRAN per fare questo cambiamento sopra.
Si inizia con un numero come 72 (2 3 3 2 ). Il programma va 'avanti' fino a quando non trova un numero che, quando moltiplicato per l'istruzione, è un altro numero intero (non sono consentiti resti).
72
andrà avanti fino a quando non arriva a 11/2
. Quindi dividerà il numero 2
e lo moltiplicherà per 11
(la potenza in 11 è una variabile). Questo dà 396
. 396
è divisibile per 33 (riducendo la potenza 3 e l'11) e moltiplicando per 455 (incrementando 5, 7 e 13 variabili). E così via. La descrizione completa di questo programma e la sua tabella di stato possono essere lette alla pagina di Wikipedia di FRACTRAN , incluso un gif animato davvero carino del programma sopra.
Altro materiale FRACTRAN su Stack Exchange che tocca la completezza di Turing può essere trovato su: Converti Fractran in Brainfuck (ok, è un uso molto produttivo del tuo tempo)
Il motivo per cui Fractran è Turing completo è perché simula una macchina di registro. La scomposizione in fattori primi del numero memorizza il contenuto dei registri, mentre la divisione e la moltiplicazione sono un modo per aggiungere e sottrarre condizionalmente dai registri.
Parte del trucco qui (e questo inizia ad andare in teoria) è che dietro le quinte, questa è una macchina del registro Minsky per la quale è stato dimostrato che alcuni nastri (programmi) sono macchine di Turing SE il nastro è rappresentato come un numero di Gödel che è esattamente qual è il numero FRACTRAN (dalla pagina di Wikipedia collegata):
Gödel utilizzava un sistema basato sulla fattorizzazione primaria. In primo luogo ha assegnato un numero naturale unico a ciascun simbolo di base nel linguaggio formale dell'aritmetica con cui aveva a che fare.
Quindi, abbiamo loop condizionali, variabili arbitrarie memorizzate come numeri di Gödel, abbiamo una macchina di Turing.
Qualche altra lettura divertente che tocca il Collatz come la natura di FRACTRAN può essere letta su Can't Decide? Undecide! che mettono in relazione la congettura di Collatz con FRACTRAN e il problema dell'arresto.
FRACTRAN è un po 'difficile da girare.
Considera il programma qualcosa come:
LABEL: start
block1
block2
block3
...
END
In questo, ogni blocco ha la forma:
IF(registers X >= a, Y >= b) # or any combination of registers
THEN
X -= a
Y -= b
I += n
J += m
goto start
La prima affermazione del programma di moltiplicazione sopra:
455
---
33
Sarebbe scritto in questa forma come:
IF(register `3` >= 1 && `11` >= 1)
THEN
`3` -= 1
`11` -= 1
`5` += 1
`7` += 1
`13` += 1
goto start
E così puoi vedere chiaramente l'archiviazione dei dati e i costrutti di loop necessari per la completezza di Turing. È molto rudimentale, ma esiste e funziona come una semplice macchina di registro, ma è tutto ciò che devi veramente essere in grado di fare.
Non sei ancora convinto?
Questo in gran parte prende in prestito da una lezione di Dimitri Hendricks su Modelli di calcolo
Questo richiede un programma molto semplice (2/3)
che è un sommatore (2 a 3 b -> 3 a + b ) Ma è distruttivo - il valore in 2 viene cancellato come parte del processo.
Scriviamo un FRACTRAN di livello superiore che rende facile non fare tale distruzione.
Il programma originale potrebbe essere pensato come:
2
α: - → α
3
In F 2 , si possono specificare 'funzioni' di un ordinamento.
10 1
α: - → α, - → β
3 1
3
β: - → β
5
Per convertire un programma F 2 (P) in un programma FRACTRAN standard, si fa:
- Cancella P di anelli di lunghezza 1
- Sostituisci le lettere greche (funzioni) con numeri primi nuovi
- Sostituisci le transizioni:
asso
p: - → q, - → r, - -> s, ...
BDF
diventa:
aq cr es
-, -, -, ...
bp dp fp
Ciò che ha fatto è stato usato i numeri primi p, q, r e s per memorizzare lo stato del programma.
E poi abbiamo la macchina dei registri ... ha un numero finito di registri che memorizzano numeri arbitrari di grandi dimensioni e due istruzioni:
- inc (x i , m) - incrementa il registro i e vai alla riga m
- jzdec (x i , m 1 , m 2 ) - se il registro i è 0 vai alla riga m, altrimenti decrementa i e vai alla riga m2.
Questa macchina del registro ha dimostrato di essere Turing completa.
Quindi mostra il processo su più diapositive della compilazione di un programma della macchina del registro in un programma FRACTRAN come parte di un processo meccanico.
Fondamentalmente:
pi)
inc (x (i), m) = ---- → m
1
1 1
jzdec (x (i), m1, m2) = ---- → m2, - → m1
p (i) 1
E quindi a causa dell'equivalenza tra questi due modelli di elaborazione, FRACTRAN è Turing completo.
A proposito, se vuoi davvero farti saltare la testa, leggi Code Golf: Fractran in cui alcune persone hanno scritto un programma FRACTRAN per eseguire un altro programma FRACTRAN.