Skip to content

Commit

Permalink
adding folder structure and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
tfburns committed Jul 25, 2019
1 parent 9b19fcf commit 27d65ff
Show file tree
Hide file tree
Showing 13 changed files with 561 additions and 35 deletions.
52 changes: 52 additions & 0 deletions Manifest.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# This file is machine-generated - editing it directly is not advised

[[Base64]]
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"

[[DataStructures]]
deps = ["InteractiveUtils", "OrderedCollections"]
git-tree-sha1 = "0809951a1774dc724da22d26e4289bbaab77809a"
uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
version = "0.17.0"

[[DelimitedFiles]]
deps = ["Mmap"]
uuid = "8bb1440f-4735-579b-a4ab-409b98df4dab"

[[Distributed]]
deps = ["Random", "Serialization", "Sockets"]
uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b"

[[InteractiveUtils]]
deps = ["Markdown"]
uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240"

[[Logging]]
uuid = "56ddb016-857b-54e1-b83d-db4d58db5568"

[[Markdown]]
deps = ["Base64"]
uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"

[[Mmap]]
uuid = "a63ad114-7e13-5084-954f-fe012c677804"

[[OrderedCollections]]
deps = ["Random", "Serialization", "Test"]
git-tree-sha1 = "c4c13474d23c60d20a67b217f1d7f22a40edf8f1"
uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
version = "1.1.0"

[[Random]]
deps = ["Serialization"]
uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"

[[Serialization]]
uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b"

[[Sockets]]
uuid = "6462fe0b-24de-5631-8697-dd941f90decc"

[[Test]]
deps = ["Distributed", "InteractiveUtils", "Logging", "Random"]
uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
9 changes: 9 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
name = "TuringMachine"
uuid = "d406e672-ae96-11e9-2f05-a59ccbfcb275"
authors = ["tfburns <[email protected]>"]
version = "0.1.0"

[deps]
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
1 change: 0 additions & 1 deletion example_input_1.txt

This file was deleted.

29 changes: 0 additions & 29 deletions example_program_1.txt

This file was deleted.

9 changes: 4 additions & 5 deletions example.jl → examples/example.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
include("simulator.jl")
using TuringMachine

input_file = "example_input_1.txt"
program_file = "example_program_1.txt"
Expand All @@ -8,15 +8,14 @@ program, init_state, halt_state = load_program(program_file)

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

# run simulation step-by-step until we reach the halting state
# run simulation step-by-step until we reach a halting state of 'accept' or 'reject'
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
catch err
println(err) && break
end
end
1 change: 1 addition & 0 deletions examples/example_input_1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
111000011
34 changes: 34 additions & 0 deletions examples/example_program_1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Binary numbers divisible by 3

// Input: a binary number n
// Output: accepts if n mod 3 == 0
// rejects if n mod 3 != 0

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

init: q0
halt: qAccept

q0,0,q0,0,>

q0,1,q1,1,>

q1,0,q2,0,>

q1,1,q0,1,>

q2,0,q1,0,>

q2,1,q2,1,>

q0,_,qAccept,_,-

q1,_,qReject,_,-

q2,_,qReject,_,-
188 changes: 188 additions & 0 deletions src/TuringMachine.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
module TuringMachine
export load_input, load_program, set_up, simulate

using DataStructures, DelimitedFiles

"""
load_input(file_name)
Takes a text file containing a continuous string of `n` integers (no spaces) and returns an `n`-element
array, where each element is an integer. The array is ordered as the input string.
Input
- `file_name`::string : path of text file containing an input string of `n` integers (no spaces)
Output
- ::`n`-element Array{Char, 1} : output array of integers, ordered as the input string
"""
function load_input(file_name)
file = readdlm(file_name, String)
return collect(file[])
end

"""
load_program(file_name)
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_raw = readdlm(file_name)
rows, cols = size(program_raw)
program = Dict{Any,Any}()
init_state = []
halt_state = []
for i = 1:rows
if program_raw[i,1] == "//"
continue
else
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_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
end
end
end
return program, init_state[], halt_state[]
end

"""
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
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(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


end # module
5 changes: 5 additions & 0 deletions simulator.jl → src/TuringSimulator-old.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
module TuringSimulator
export load_input, load_program, set_up, simulate

using DataStructures
using DelimitedFiles

Expand Down Expand Up @@ -181,3 +184,5 @@ function simulate(state, program, tape_left, tape_right)
tape_left, tape_right = write_move!(movement, write_cell, tape_left, tape_right)
return state, tape_left, tape_right
end

end
Loading

0 comments on commit 27d65ff

Please sign in to comment.