Elvis
Elvis

Reputation: 425

How to stop the counting process for the if loop in my code?

I want to stop the counting process for y after it first time meet the condition of y < 0 for each i in the for loop. Which means, the counting process for x will still continue as long as x > 0 (condition stated in the while loop).

I had tried to do something which is if (y < 0 & (y - 120*(16/81)*time + (z-2)) > 0 & z > 2), it make sense for me but the result doesn't make sense because after I run the code, count_x is around 100 (make sense) but count_y is more than 1000 which doesn't make sense since the for loop is only from 1:1000.

count_x <- 0
count_y <- 0

for (i in 1:1000){
  x <- 25
  y <- 25
  t <- 0
  while ((x > 0 | y > 0) & t < 100){
    time <- rexp(1,100)
    u <- runif(1,0,1)
    z <- 4/((1-u)^0.2) - 4
    if (z < 2){
      x <- x + 110*(65/81)*time - z
    } else {
      y <- y + 120*(16/81)*time - (z-2)
      x <- x + 110*(65/81)*time - 2
    }
    t <- t + time
    if (x < 0){
      count_x <- count_x + 1
    }
    if (y < 0 & (y - 120*(16/81)*time + (z-2)) > 0 & z > 2){
      count_y <- count_y + 1
    }    
  }
}

For example, during the 1st iteration i=1, the while loop will start and run the code inside the loop. So what I want to do is:

When y first time reach negative value in the first iteration, it will update the count_y by one, then the whole if loop for the counting process of y will stop doing any thing even though the while loop is still continue to run since the if loop for counting process of x might not reach it first negative value yet (the condition for the while loop still satisfied if t is still smaller than 100), so the while loop need to be continue without touching last inner if loop until either t>100 first or x first time reach its negative value. Once, the conditions for while loop do not satisfied, then only go for the 2nd iteration i=2.

Same thing goes to x, the counting process for x will stop doing anything once x first time become a negative value but the while loop will continue working as long as the condition for the while loop still satisfied.

So, there will only be one time update for either x or y for each iteration (so maximum for y should be 1000 since we have 1000 iteration, although unlikely to reach 1000) since the counting process for both x and y will stop once it reaches the first negative value.

I'm thinking to add break function into it but not sure where should I add.

Upvotes: 3

Views: 874

Answers (2)

Mr.Rlover
Mr.Rlover

Reputation: 2623

We will create variables for both x and y that will store and track when both cross zero on each i iteration. First we will check if x or y is zero and if neg is of class NULL. If so, then this is the first negative. We store x_0 or y_0 as 1. Then when counting, we check if x_0 or y_0 is equal to one and if neg is NULL. Then we will add to the counter and record the first negative. Thereafter, the condition evaluates to FALSE.

count_x <- 0
count_y <- 0
while_x <- 0
while_y <- 0

for (i in 1:1000){
  x <- 25
  y <- 25
  t <- 0
  x_0 <- 0
  y_0 <- 0
  neg <- NULL
  neg_x <- NULL
  while ((x > 0 | y > 0) & t < 100){
    time <- rexp(1,100)
    u <- runif(1,0,1)
    z <- 4/((1-u)^0.2) - 4
    if (z < 2){
      x <- x + 110*(65/81)*time - z
      if (x < 0 & is.null(neg_x)){
        x_0 <- 1
      }
    } else {
      y <- y + 120*(16/81)*time - (z-2)
      x <- x + 110*(65/81)*time - 2
      if (x < 0 & is.null(neg_x)){
        x_0 <- 1
      }
      if (y < 0 & is.null(neg)) {
        y_0 <- 1
      }
    }
    t <- t + time

    if (x_0 == 1 & is.null(neg_x)){
      count_x <- count_x + 1
      neg_x <- "First Negative"
      x_0 <- x_0 + 1
    }
    if (y_0 == 1 & is.null(neg)){
      count_y <- count_y + 1
      neg <- "first negative"
      y_0 <- y_0 + 1
    }
  }
}

You can also place a counter outside the while loop. If x or y is less than 0, add to the counter. This is probably a better solution. The condition will evaluate regardless of when x or y cross below zero, as long as it went below zero, it will evaluate to TRUE

count_x <- 0
count_y <- 0

for (i in 1:1000){
  x <- 25
  y <- 25
  t <- 0
  while ((x > 0 | y > 0) & t < 100){
    time <- rexp(1,100)
    u <- runif(1,0,1)
    z <- 4/((1-u)^0.2) - 4
    if (z < 2){
      x <- x + 110*(65/81)*time - z
    } else {
      y <- y + 120*(16/81)*time - (z-2)
      x <- x + 110*(65/81)*time - 2
    }
    t <- t + time
  }
  if(x < 0) {
    count_x <- count_x + 1
  }
  if(y < 0){
    count_y <- count_y + 1
  }
}

For me, count_y comes out at a 1000 in both cases. This confirms what I said previously, y goes below zero at each while iteration.

Upvotes: 0

Mr.Rlover
Mr.Rlover

Reputation: 2623

I don't think there's anything wrong with the code. The y counter, to me at least, seems like it is correct. The reason why y is larger is two-fold. Firstly, even though the outer for loop is only 1000, the inner while loop could potentially run for more than a 100 at each i iteration. Secondly, it appears that y goes below 0 before x does, hence why the x counter is smaller.

I've modified your code to include a counter that counts how many while iterations occur, and two variables that store the values of x and y respectively, the first time that y goes below zero.

count_x <- 0
count_y <- 0
while_count <- 0
store_x <- 0
store_y <- 0

a <- 1
b <- 1

for (i in 1:1000){
  x <- 25
  y <- 25
  t <- 0
  count_while <- 0
  while ((x > 0 | y > 0) & t < 100){
    time <- rexp(1,100)
    u <- runif(1,0,1)
    z <- 4/((1-u)^0.2) - 4
    if (z < 2){
      x <- x + 110*(65/81)*time - z
    } else {
      y <- y + 120*(16/81)*time - (z-2)
      x <- x + 110*(65/81)*time - 2
    }
    t <- t + time
    if (x < 0){
      count_x <- count_x + 1
    }
    if (y < 0 & (y - 120*(16/81)*time + (z-2)) > 0 & z > 2){
      count_y <- count_y + 1
      store_y[a] <- y
      store_x[a] <- x
      a <- a + 1
    }
    if (y > 0){
      count_while <- count_while + 1
    }
  }
  while_count[b] <- count_while
  b <- b + 1
}

Checking the averages shows that x is almost exclusively greater than zero the first time y goes below zero. The while loop averages 163 iterations.

mean(store_x)
[1] 38.90333
mean(store_y)
[1] -2.035492
mean(while_count)
[1] 163.052
which(store_x < 0)
[1] 656

So, your counter seems correct to me, x is low simply because it rarely goes below zero. In fact, run the loop for just one iteration by setting for (i in 1:1) and run it several time, you'll find that your count_x rarely goes above zero, despite the while loop iterating over a 100 times. On the other hand, y goes below zero at least once on each i iteration.

I hope this helps!

Upvotes: 1

Related Questions