We first load the needed packages:
library(tidyverse)
library(ggplot2)
library(gganimate)
We define a function that can create 1d inputs that can be read by our Turing machine:
<- function(n){
input_builder_1d_animated <- c(rep(1,n+1))
output
output }
We define a function that can create 2d inputs that can be read by our Turing machine:
<- function(n,m){
input_builder_2d_animated <- c(rep(1,n+1), NA, rep(1,m+1))
output
output }
We now define a function that will return a data set we can be use to make an animated plot of a turing program. As in our original implementation, it takes a program and an input (build by one of the input generators above) as arguments. If the browser arguments is TRUE
in a call to the function, we enter the function environment and can follow along every step of the way. Since R cannot use negative indices, and we want our infinite tape to be intuitive, the n_na argument allow us to add some NA to the left of the first 1 on the input tape, such that the machine can go to the left of the starting position.
<- function(program, input, browser = FALSE, numeric = FALSE, n_na=0){
turingmachine_animated_data #if(browser){browser()} we have to comment out the browser function for publishing. Uncomment if you want to use the browser argument.
<- n_na+1
position <- "1"
state <- c(rep(NA, n_na),input)
input <- c(n_na+1)
position_animate <- list(input)
input_animate <- c("1")
state_animate <- 1
s
while(state != "0"){
if(is.na(input[position])){
<- program[[state]]$if_read_na$return
input[position] <- append(input_animate, list(input))
input_animate <- s+1
s if(program[[state]]$if_read_na$direction == "R"){position <- position + 1
<- c(position_animate, position)
position_animate <- s+1
s else {
} <- position -1
position <- c(position_animate, position)
position_animate <- s+1
s
}<- program[[state]]$if_read_na$state
state <- c(state_animate,state)
state_animate
}else {
<- program[[state]]$if_read_one$return
input[position] <- append(input_animate, list(input))
input_animate <- s+1
s if(program[[state]]$if_read_one$direction == "R"){
<- position + 1
position <- c(position_animate, position)
position_animate <- s+1
s else {
} <- position -1
position <- c(position_animate, position)
position_animate <- s+1
s
}<- program[[state]]$if_read_one$state
state <- c(state_animate,state)
state_animate
}
}
# collect variables to make the data from
<-
animate_list list(position=position_animate,
input=input_animate,
state=state_animate,
steps=s)
<- c()
position_out <- c()
input_out <- c()
state_out <- c()
input_x <- c()
step_out
for(i in c(1:length(animate_list$state))){
<- length(animate_list$input[[i]])
l <- c(input_out,as.numeric(animate_list$input[[i]]))
input_out <- c(input_x, 1:l)
input_x <- c(state_out,rep(as.numeric(animate_list$state[i]),l))
state_out <- c(step_out, rep(i,l))
step_out <- c(position_out, rep(animate_list$position[i],l))
position_out
}#return the collected data
tibble(position_out,input_out,state_out,input_x,step_out)
}
We define a function for creating animated plots of turingmachines. The function call the turing_animated_data()
function we defined above with the program, input and n_na specified in the arguments. The title argument is the plot title. After having created the data, the function creates and return a ggplot object, ready to be rendered into a gif.
<- function(program, input, title, n_na =0){
animated_turingmachine_plot
# create the data
<- turingmachine_animated_data(program, input, n_na = n_na) %>%
data_anim mutate(label_text= paste("state: ", as.character(state_out)))
# create an object which can be rendered using animate()
ggplot(data=data_anim, aes(input_x, input_out))+
geom_point(size=3, colour = "magenta") +
geom_point(aes(x=position_out, y = 2),size = 5,shape = 25, fill = "orange", colour = "orange")+
theme_minimal()+
ylim(0,3.5)+
transition_states(step_out, transition_length = 1 , state_length = 1, wrap = FALSE)+
theme(axis.text.x=element_blank(),
axis.text.y=element_blank(),
axis.title.x=element_blank(),
axis.title.y=element_blank(),
legend.position="none",
text = element_text(family = "Times New Roman", size = 15))+
ggtitle(title) +
geom_text(aes(x=1.5,y=0.3,label=label_text),size = 6, check_overlap=TRUE,
family = "Times New Roman")
}