CephBirk CephBirk - 2 months ago 13
R Question

Get out of infinite while loop

What is the best way to have a

while
loop recognize when it is stuck in an infinite loop in R?

Here's my situation:

diff_val = Inf
last_val = 0

while(diff_val > 0.1){

### calculate val from data subset that is greater than the previous iteration's val
val = foo(subset(data, col1 > last_val))

diff_val = abs(val - last_val) ### how much did this change val?
last_val = val ### set last_val for the next iteration
}


The goal is to have
val
get progressively closer and closer to a stable value, and when
val
is within 0.1 of the
val
from the last iteration, then it is deemed sufficiently stable and is released from the
while
loop. My problem is that with some data sets,
val
gets stuck alternating back and forth between two values. For example, iterating back and forth between 27.0 and 27.7. Thus, it never stabilizes. How can I break the
while
loop if this occurs?

I know of
break
but do not know how to tell the loop when to use it. I imagine holding onto the value from two iterations before would work, but I do not know of a way to keep values two iterations ago...

while(diff_val > 0.1){

val = foo(subset(data, col1 > last_val))

diff_val = abs(val - last_val)
last_val = val

if(val == val_2_iterations_ago) break
}


How can I create
val_2_iterations_ago
?

Apologies for the non-reproducible code. The real
foo()
and
data
that are needed to replicate the situation are not mine to share... they aren't key to figuring out this issue with control flow, though.

Answer

I don't know if just keeping track of the previous two iterations will actually suffice, but it isn't too much trouble to add logic for this.

The logic is that at each iteration, the second to last value becomes the last value, the last value becomes the current value, and the current value is derived from foo(). Consider this code:

while (diff_val > 0.1) {
    val <- foo(subset(data, col1 > last_val))

    if (val == val_2_iterations_ago) break

    diff_val = abs(val - last_val)
    val_2_iterations_ago <- last_val
    last_val <- val
}