Stuck in infinite loop, where is the problem I am seeing? - r

My code is stuck in an infinite loop, with the stop sign occurring. I have read through it multiple times, can anyone help?
I am trying to run trials using samples of possession probabilities and the subsequent make probabilities for a basketball team. I am following along with a video and made sure each step was completed properly.
How can I tell where I am stuck in an infinite loop and how do I fix it?
mc_hoops_ex <- function(trials) {
prob_pos <- c(0.148, 0.544, 0.308, 0.256)
prob_2pm <- 0.524
prob_3pm <- 0.378
prob_ftm <- 0.761
prob_orb <- 0.319
a <- 1
pts_ct <- 0
while (a <= trials) {
pos_outcome <- sample(c(1:4), 1, prob = prob_pos)
if(pos_outcome == 2) {
pos_end <- 0
while (pos_end < 1) {
shot_prob <- runif(1)
if(shot_prob <= prob_2pm) {
pts_ct <- pts_ct + 2
pos_end <- 1
}
else {
orb_prob <- runif(1)
if(orb_prob >= prob_orb)
pos_end <- 1
}
}
}
}
if(pos_outcome == 3) {
pos_end <- 0
while (pos_end < 1) {
shot_prob <- runif(1)
if(shot_prob <= prob_3pm) {
pts_ct <- pts_ct + 3
pos_end <- 1
}
else {
orb_prob <- runif(1)
if(orb_prob >= prob_orb)
pos_end <- 1
}
}
}
if(pos_outcome == 4) {
pos_end <- 0
while (pos_end < 1) {
shot_prob <- runif(1)
if(shot_prob <= prob_ftm) {
pts_ct <- pts_ct + 1
pos_end <- 1
}
else {
orb_prob <- runif(1)
if(orb_prob >= prob_orb)
pos_end <- 1
}
}
}
a <- a + 1
print(pts_ct / trials)
print((pts_ct / trials) * 66.3)
}

This looks like R code, based on the syntax, <- assignment, and functions like c() and runif().
You have the following loop: while (a <= trials). This loop will continue running until the condition no longer holds. Since you initialize a <- 1, this loop will not stop unless (1) trials < 1, in which case the loop will not run a single time, or (2) a is incremented until a > trials.
We can see that the only time a is changed is near the bottom of the function: a <- a + 1. However, look closely at the braces. This increment is outside the while-loop, so it never occurs and the loop runs forever.
I'm not sure if this will produce the expected results, but a corrected version that does not have an infinite loop is given below.
mc_hoops_ex <- function(trials) {
prob_pos <- c(0.148, 0.544, 0.308, 0.256)
prob_2pm <- 0.524
prob_3pm <- 0.378
prob_ftm <- 0.761
prob_orb <- 0.319
a <- 1
pts_ct <- 0
while (a <= trials) {
pos_outcome <- sample(c(1:4), 1, prob = prob_pos)
if(pos_outcome == 2) {
pos_end <- 0
while (pos_end < 1) {
shot_prob <- runif(1)
if(shot_prob <= prob_2pm) {
pts_ct <- pts_ct + 2
pos_end <- 1
}
else {
orb_prob <- runif(1)
if(orb_prob >= prob_orb)
pos_end <- 1
}
}
}
# Removed the closing brace here
if(pos_outcome == 3) {
pos_end <- 0
while (pos_end < 1) {
shot_prob <- runif(1)
if(shot_prob <= prob_3pm) {
pts_ct <- pts_ct + 3
pos_end <- 1
}
else {
orb_prob <- runif(1)
if(orb_prob >= prob_orb)
pos_end <- 1
}
}
}
if(pos_outcome == 4) {
pos_end <- 0
while (pos_end < 1) {
shot_prob <- runif(1)
if(shot_prob <= prob_ftm) {
pts_ct <- pts_ct + 1
pos_end <- 1
}
else {
orb_prob <- runif(1)
if(orb_prob >= prob_orb)
pos_end <- 1
}
}
}
a <- a + 1
} # Added a closing brace here instead
print(pts_ct / trials)
print((pts_ct / trials) * 66.3)
}

Related

R next prime number Inclusive of start

I have the below existing code in R. The code prints the next immediate prime number. I want to consider inclusive of starting number
np <- function(x){
if (x==1L | x==2L) {return(2L)}
else {
temp <- x+1
test <- 2:x
while( any( (temp %% test) == 0 ) ){
temp <- temp+1
}
temp
} }
Eg.. np(7) returns 11. But expected output is 7.
Try the code below (following a similar idea in the answer here)
np <- function(x) {
p <- x
repeat {
if (p %in% c(2, 3) | all(p %% ceiling(sqrt(2:p)) != 0)) {
return(p)
}
p <- p + 1
}
}
and you will see
> np(2)
[1] 2
> np(3)
[1] 3
> np(4)
[1] 5
> np(5)
[1] 5
> np(7)
[1] 7
Maybe it's stupid but does this do the trip?
np <- function(x){
if (x==1L | x==2L) {return(2L)}
else {
x= x-1
temp <- x+1
test <- 2:x
while( any( (temp %% test) == 0 ) ){
temp <- temp+1
}
temp
} }
You are testing numbers above x only by calling temp <- x+1. Here is a version that should work with minimal changes to your code:
np <- function(x){
if (x==1L | x==2L) {return(2L)}
else {
temp <- x
test <- 2:(x - 1)
while( any( (temp %% test) == 0 ) ){
temp <- temp+1
}
temp
} }

R - Vectorize nested for loops to assign new values to a matrix

I'm currently trying to vectorize this nested for loop to save time during execution but it doesnt seem to work. What I want is to go through every cell of my matrix and check if the value is 0 or 1 then change the value based on a condition. This is the algorithm for the Forest-fire model
for (i in 1:nrow(X)) {
for (j in 1:ncol(X)) {
if (X[i, j] == 2) {
if (runif(1) > (1 - a)^neighbours(X, i, j)) {
B[i, j] <- 1
}
}
else if (X[i, j] == 1) {
burning <- TRUE
if (runif(1) < b) {
B[i, j] <- 0
}
}
}
}
Here is the neighbours function :
neighbours <- function(A, i, j) {
# calculate number of neighbours of A[i,j] that are infected
# we have to check for the edge of the grid
nbrs <- 0
# sum across row i - 1
if (i > 1) {
if (j > 1) nbrs <- nbrs + (A[i-1, j-1] == 1)
nbrs <- nbrs + (A[i-1, j] == 1)
if (j < ncol(A)) nbrs <- nbrs + (A[i-1, j+1] == 1)
}
# sum across row i
if (j > 1) nbrs <- nbrs + (A[i, j-1] == 1)
nbrs <- nbrs + (A[i, j] == 1)
if (j < ncol(A)) nbrs <- nbrs + (A[i, j+1] == 1)
# sum across row i + 1
if (i < nrow(A)) {
if (j > 1) nbrs <- nbrs + (A[i+1, j-1] == 1)
nbrs <- nbrs + (A[i+1, j] == 1)
if (j < ncol(A)) nbrs <- nbrs + (A[i+1, j+1] == 1)
}
return(nbrs)
}
And some code to make it work :
set.seed(3)
X <- matrix(2, 21, 21)
X[11, 11:13] <- 1
burning <- FALSE
a= 0.2
b = 0.4
B <- X
I've started by trying with sapply but couldn't get results back into the matrix and for the past hour I've been trying to use nested foreach loops
library(foreach)
B <-
foreach(i=1:nrow(X), .combine='cbind') %:%
foreach(j=1:ncol(X), .combine='c') %do% {
if (X[i, j] == 2) {
if (runif(1) > (1 - a)^neighbours(X, i, j)) {
1
}
}
else if (X[i, j] == 1) {
burning <- TRUE
if (runif(1) < b) {
0
print(i)
print(j)
}
}
}
But I'm only getting back the lines I need to change
I'm not familiar with vectorization so perhaps I'm missing some basic steps !
As you seem very comfortable in loops, you may want to recode in rcpp. Your code will translate very quickly.
Here's a draft that goes towards more efficient in R and is about 2.5 times more efficient on this small dataset.
## get constants out of the away above the loop
A = X == 1L
nr = nrow(X)
nc = ncol(X)
for (i in 1:nr) {
i_start = i - (i > 1L)
i_stop = i + (i < nr)
for (j in 1:nc) {
j_start = j - (j > 1L)
j_stop = j + (j < nc)
switch(X[i, j],
##refactoring of neighbours function which is a partial rolling sum of sub-matrixes equal to 1.
2, if (runif(1) > (1 - a)^sum(A[i_start:i_stop, j_start:j_stop])) B[i, j] <- 1,
1, {burning = TRUE
if (runif(1) < b) B[i, j] = 0}
)
}
}
It's likely possible that the outer loop can be removed but additional thought would be needed for the neighbors algorithm to allow more than one i at a time.

Death and birth process and proportion

I have this code which describes a death and birht procceses with four states, 0,1,2,3.
bd_process <- function(lambda, mu, initial_state = 0, steps = 100) {
time_now <- 0
state_now <- initial_state
time <- 0
state <- initial_state
for (i in 1:steps) {
if (state_now == 3) {
lambda_now <- 0
} else {
lambda_now <- lambda
}
if (state_now == 0) {
mu_now <- 0
} else {
mu_now <- mu
}
time_to_transition <- rexp(1, mu_now + lambda_now)
if (runif(1) < mu_now/(lambda_now + mu_now)) {
state_now <- state_now - 1
} else {
state_now <- state_now + 1
}
time_now <- time_now + time_to_transition
time <- c(time, time_now)
state <- c(state, state_now)
}
return(list(time = time, state= state))
}
From this code I want to create a function which count the proportion of time in each time. The function is aimed to take two parameters, and Im a bit lost. Any suggestions?
This is an example function that identifies the times for each state and sums them. It uses sapply to iterate over the possible states.
x=bd_process(2,3)
#' #param x a list returned by bd_process function
#' #return a vector of times spent in state 0,1,2,3
get_times=function(x) {
sapply(0:3, function(i) {
sum(x$time[which(x$state==i)])
})
}
get_times(x)
[1] 401.52405 607.44447 253.52741 38.58117

R - for loop error: "Unexpected '}' in '}'"

here is the code for a simulation I'm trying to run:
n_draws <- 1000
black <- rep(0, n_draws)
hispanic <- rep(0, n_draws)
asian <- rep(0, n_draws)
white <- rep(0, n_draws)
cutoff <- c(0.05,0.1,0.25,1)
draws <- runif(n_draws,0,1)
for (i in draws){
if (draws[i] < cutoff[1]){
black[i] <- 1
} else if ((draws[i] >= cutoff[1]) & (draws[i] < cutoff[2])){
hispanic[i] <- 1
} else if ((draws[i] >= cutoff[2]) & (draws[i] < cutoff[3]){
asian[i] <- 1
} else {
white[i] <- 1
}
}
Basically, I want to add a 1 to the corresponding list, conditional on where that number falls in the range (0,1). I'm not sure why this is giving an error. Suggestions?
You're just missing a closing bracket just after cutoff[3], also used seq_along in my example as it's a bit nicer
for (i in seq_along(draws)){
if (draws[i] < cutoff[1]){
black[i] <- 1
} else if ((draws[i] >= cutoff[1]) & (draws[i] < cutoff[2])){
hispanic[i] <- 1
} else if ((draws[i] >= cutoff[2]) & (draws[i] < cutoff[3])){
asian[i] <- 1
} else {
white[i] <- 1
}
}

How to repeat same codes in 10 times and get those results in R?

Here is my code:
f.x <- function(x) {
60*x^3*(1-x)^2
}
x <- seq(0, 1, length=100)
n.samps <- 1000
n <- 0 # counter for accepted
i <- 0 # iterations
samps <- numeric(n.samps)
while (n < n.samps) {
y <- runif(1)
i <- i + 1
u <- runif(1)
if (u < f.x(y) / 2.0736) {
n <- n + 1
samps[n] <- y
}
}
I want to repeat the code above for 10 times, each time an "i" will be produced. I want to take the average of these ten "i". Instead of run the code each time, is there any way I can run one time but get 10 trials?
You can try placing your entire script into a function, and then just call it 10 times from a loop:
getValue <- function() {
x <- seq(0, 1, length=100)
n.samps <- 1000
n <- 0 # counter for accepted
i <- 0 # iterations
samps <- numeric(n.samps)
while (n < n.samps) {
y <- runif(1)
i <- i + 1
u <- runif(1)
if (u < f.x(y) / 2.0736) {
n <- n + 1
samps[n] <- y
}
}
return(i)
}
Usage:
result <- replicate(10, getValue())

Resources