Skip to content

Commit

Permalink
Working example of program to compute if binary numbers divisible by 3
Browse files Browse the repository at this point in the history
  • Loading branch information
tfburns committed Jul 24, 2019
1 parent 369f189 commit 9b19fcf
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 24 deletions.
15 changes: 14 additions & 1 deletion example.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,17 @@ program_file = "example_program_1.txt"
input = load_input(input_file)
program, init_state, halt_state = load_program(program_file)

tape_left, tape_right = set_up(input)
state, tape_left, tape_right = set_up(init_state, input)

# run simulation step-by-step until we reach the halting state
while true
try
global state, tape_left, tape_right = simulate(state, program, tape_left, tape_right)
println(state)
state ==("qAccept") && break
catch err
global state = "qReject"
println(state)
state ==("qReject") && break
end
end
2 changes: 1 addition & 1 deletion example_input_1.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
01100101
1101101
12 changes: 6 additions & 6 deletions example_program_1.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
// Example: accepts 110 (=6)

// ------- States -----------|
// q0 - mod3 == 0 |
// q1 - mod3 == 1 |
// q2 - mod3 == 2 |
// qHalt - halting state |
// q0 : mod3 == 0 |
// q1 : mod3 == 1 |
// q2 : mod3 == 2 |
// qAccept : halting state |
// --------------------------|

init: q0
halt: qHalt
halt: qAccept

q0,0,q0,0,>

Expand All @@ -26,4 +26,4 @@ q2,0,q1,0,>

q2,1,q2,1,>

q0,_,qHalt,_,-
q0,_,qAccept,_,-
135 changes: 119 additions & 16 deletions simulator.jl
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
using DataStructures
using DelimitedFiles

# Read Input / Change value of current input (or do nothing), Move L or R or do nothing
# e.g. 1/0, L = if current cell value is 1, change it to 0, then move left
# e.g. 0/1, . = if current cell value is 0, change it to 1, then don't move

"""
load_input(file_name)
Expand All @@ -28,23 +24,27 @@ end
Takes a text file containing a Turing program. Please see docs for how to write such a program.
Input
- `file_name`::string : path of text file containing the Turing program to simulate
Output
- `program`::Dict{Any,Any} with `m` entries: dictionary with keys of [states,read_cells] and values of [next_state,write_cell,movement]
"""
function load_program(file_name)
program_file = readdlm("example_program_1.txt")
rows, cols = size(program_file)
program_raw = readdlm(file_name)
rows, cols = size(program_raw)
program = Dict{Any,Any}()
init_state = []
halt_state = []
for i = 1:rows
if program_file[i,1] == "//"
if program_raw[i,1] == "//"
continue
else
if program_file[i,1] == "init:"
push!(init_state, program_file[i,2])
elseif program_file[i,1] == "halt:"
push!(halt_state, program_file[i,2])
if program_raw[i,1] == "init:"
push!(init_state, program_raw[i,2])
elseif program_raw[i,1] == "halt:"
push!(halt_state, program_raw[i,2])
else
card = split(program_file[i,1], r",")
card = split(program_raw[i,1], r",")
state_read = (String(card[1]),String(card[2]))
instruction = (String(card[3]),String(card[4]),String(card[5]))
program[state_read] = instruction
Expand All @@ -55,26 +55,129 @@ function load_program(file_name)
end

"""
set_up(input)
set_up(init_state, input)
Performs initial set-up for the simulation of single tape. The `length(input)` must be equal of greater
than 1. The input will be placed on tape to the right of the head.
Input
- `input`::`n`-element Array{Char, 1} : initial data to insert to the right of the head
- `init_state`::String : string label for initial/starting state of the Turing machine
Output
Outputs
- `tape_left`::Deque{Int} : initial values for the stack to the left of the head
- `tape_right`::Deque{Int} : initial values for the stack to the right of the head
"""
function set_up(input)
function set_up(init_state, input)
# set up two stacks to simulate a single tape
tape_left = Deque{Int}() # simulates tape lying to the left of the head
tape_right = Deque{Int}() # simulates tape lying to the right of the head

for i = 1:length(input)
push!(tape_right, parse(Int, input[i]))
end
state = init_state
return state, tape_left, tape_right
end

"""
read_tape(tape_right)
Reads a tape and returns the current value.
Input
- `tape_right`::Deque{Int}() : values for the stack to the right of the head
Output
- `read_cell`::String : value for the current cell being read by the head
"""
function read_tape(tape_right)
read_cell = front(tape_right)
return read_cell
end

"""
get_instruction(state, read_cell, program)
Inputs
- `state`::String : curent state of the Turing machine
- `read_cell`::String : value for the current cell being read by the head
- `program`::Dict{Any,Any} with `m` entries: dictionary with keys of [states,read_cells] and values of [next_state,write_cell,movement]
Outputs
- `next_state`::String : next state for the Turing machine to move to
- `write_cell`::String : value for the head to write on the current cell
- `movement`::String : movement instruction for the head (left="<", right=">", any other symbol doesn't move)
"""
function get_instruction(state, read_cell, program)
instruction = program[(string(state), string(read_cell))]
next_state = instruction[1]
write_cell = instruction[2]
movement = instruction[3]
return next_state, write_cell, movement
end

"""
write_move!(movement, write_cell, tape_left, tape_right)
Performs the operations of writing at the current position then moving the head left or right.
Inputs
- `movement`::String : movement instruction for the head (left="<", right=">", any other symbol doesn't move)
- `write_cell`::String : value for the head to write on the current cell
- `tape_left`::Deque{Int} : values for the stack to the left of the head
- `tape_right`::Deque{Int} : values for the stack to the right of the head
Outputs
- `tape_left`::Deque{Int} : updated values for the stack to the left of the head (after writing/movement)
- `tape_right`::Deque{Int} : updated values for the stack to the right of the head (after writing/movement)
"""
function write_move!(movement, write_cell, tape_left, tape_right)
if isempty(tape_right)
return tape_left, tape_right
end
popfirst!(tape_right)
pushfirst!(tape_right, parse(Int, write_cell))
if movement == "<"
if isempty(tape_left)
pushfirst!(tape_right, "_")
else
carry = pop!(tape_left)
pushfirst!(tape_right, carry)
end
elseif movement == ">"
if isempty(tape_right)
push!(tape_left, "_")
else
carry = popfirst!(tape_right)
push!(tape_left, carry)
end
end
return tape_left, tape_right
end

"""
simulate(state, program, tape_left, tape_right)
Simulates one step of the Turing machine: reading, writing, and moving the head.
Inputs
- `state`::String : curent state of the Turing machine
- `program`::Dict{Any,Any} with `m` entries: dictionary with keys of [states,read_cells] and values of [next_state,write_cell,movement]
- `tape_left`::Deque{Int} : values for the stack to the left of the head
- `tape_right`::Deque{Int} : values for the stack to the right of the head
Outputs
- `state`::String : updated state of the Turing machine after one simulation step
- `tape_left`::Deque{Int} : updated values for the stack to the left of the head after one simulation step
- `tape_right`::Deque{Int} : updated values for the stack to the right of the head after one simulation step
"""
function simulate(state, program, tape_left, tape_right)
if isempty(tape_right)
read_cell = "_"
else
read_cell = read_tape(tape_right)
end
state, write_cell, movement = get_instruction(state, read_cell, program)
tape_left, tape_right = write_move!(movement, write_cell, tape_left, tape_right)
return state, tape_left, tape_right
end

0 comments on commit 9b19fcf

Please sign in to comment.