misc: add simple turing machine from DAS.
This commit is contained in:
parent
b6e24b44ad
commit
af2db4ac8c
|
@ -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)
|
|
@ -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)
|
Loading…
Reference in New Issue