From af2db4ac8c813a005f5f412b455ea3d9d51a8742 Mon Sep 17 00:00:00 2001 From: Kyle Isom Date: Sat, 7 Apr 2018 13:36:30 -0700 Subject: [PATCH] misc: add simple turing machine from DAS. --- misc/turing-machine/turing.poly.pm | 79 ++++++++++++++++++++++++++++++ misc/turing-machine/turing.py | 36 ++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 misc/turing-machine/turing.poly.pm create mode 100755 misc/turing-machine/turing.py diff --git a/misc/turing-machine/turing.poly.pm b/misc/turing-machine/turing.poly.pm new file mode 100644 index 0000000..8df99fd --- /dev/null +++ b/misc/turing-machine/turing.poly.pm @@ -0,0 +1,79 @@ +◊h1{Turing machines} + +◊h2{Introduction} +One of the motivators is exploring the limits of computation via the halting +problem: + + halt :: function → bool + +The question is: does `function` always return? This is an undecidable problem. + +The Chomsky hierarchy: + +1. Regular expressions +2. Simple programming languages +3. Complex programming languages +4. Turing equivalence + +◊h2{Computing by changing} + +Imperative model of computation: order of instructions matters, and generally +destructive operations. + +Turing machine: + +* infinite tape composed of cells, initialisation is the blank symbol ('B') +* head pointing to a cell on the tape +* instructions: head movement, read, write + +Example machine: X_B + +two-cell tape: + +``` +BB +^ +``` + +rewrite first cell with X->B repeatedly: when we see a B, write an X. When we see an X, write a B. +head has to move on every single instruction, only one step +we'll move to the right +cell 2: read B, see B, move left + +ex: + +BB +^ +XB + ^ +XB +^ +BB + ^ + +Turing machines aren't imperatively organised; it uses a state table. +state symbols: +s_1...s_4 + +(symbol, state) -> write, head move, next state +B, s1 -> X, R, s2 +B, s2 -> B, L, s3 +X, s3 -> B, R, s4 +B, s4 -> B, L, s1 + +a state table and four-line turing machine: + + X_B = { + ('B', 's1'): ('X', 'R', 's2'), + ('B', 's2'): ('B', 'L', 's3'), + ('X', 's3'): ('B', 'R', 's4'), + ('B', 's4'): ('B', 'L', 's1') + } + + def simulate(instructions): + tape, head, state = ['B', 'B'], 0, 's1' + for _ in range(8): + (tape[head], head_dir, state) = instructions[(tape[head], state)] + head += 1 if head_dir == 'R' else -1 + + simulate(X_B) diff --git a/misc/turing-machine/turing.py b/misc/turing-machine/turing.py new file mode 100755 index 0000000..692246f --- /dev/null +++ b/misc/turing-machine/turing.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 + +X_B = { + ('B', 's1'): ('X', 'R', 's2'), + ('B', 's2'): ('B', 'L', 's3'), + ('X', 's3'): ('B', 'R', 's4'), + ('B', 's4'): ('B', 'L', 's1') +} + +def simulate(instructions): + # set up initial state + + # note that tape is hard-coded for now, but should be a data structure that + # can grow in either direction and the state shouldn't be hard-coded. This + # works for the initial pass at this. + tape, head, state = ['B', 'B'], 0, 's1' + + # loop: this should be an infinite loop (with a possible halting state in the state table) + for _ in range(8): + print(state + ': ' + ''.join(tape)) + print(' ' + ' ' * head + '^') + + # look up instruction + (tape[head], head_dir, state) = instructions[(tape[head], state)] + + # apply instruction + head += 1 if head_dir == 'R' else -1 + + # sanity checks + assert(head_dir in ['R', 'L']) + assert(head >= 0) + assert(head < len(tape)) + +# four lines of actual code that can simulate any CPU + +simulate(X_B) \ No newline at end of file