simanneal icon indicating copy to clipboard operation
simanneal copied to clipboard

ZeroDivisionError in anneal.py

Open terrycojones opened this issue 4 years ago • 4 comments

I'm not sure how this can happen, but I'm looking at it in my terminal output, so I can at least say that it did happen!

  File "/home/terry/s/net/simanneal/simanneal/anneal.py", line 211, in anneal
    if dE > 0.0 and math.exp(-dE / T) < random.random():
ZeroDivisionError: float division by zero

So it seems T=0, which, from code about 10 lines above, would mean that self.Tmax would need to be zero. I'm running using the auto method and set_schedule. So maybe when auto sets Tmax to be the result of running round_figures the value is zero?

terrycojones avatar Nov 07 '20 11:11 terrycojones

@terrycojones Can you share a small python script to recreate it?

perrygeo avatar Nov 19 '20 14:11 perrygeo

Hi @perrygeo Unfortunately it's not so easy to get you a failing example. My code loads a ton of sensitive data and it's not simple to make a failing case. I get this error regularly, so this is definitely not a one-off issue. I just had one tonight and I've had dozens of them in a recent set of runs. At the moment I'm so busy that instead of digging in further I just restart the runs. Anyway, I would like to help figure this out & realize I'm not really helping that the moment! I am out here, though :-)

terrycojones avatar Dec 04 '20 20:12 terrycojones

I just spent a bit more time looking and playing around with bits of code. I don't think round_figures can be the culprit. But there is this in the anneal function:

T = self.Tmax * math.exp(Tfactor * step / self.steps)

If Tfactor is large and negative, math.exp will return zero:

In [74]: exp(-1000) == 0.0
Out[74]: True

That results in T being set to zero, which causes if dE > 0.0 and math.exp(-dE / T) < random.random(): to get the ZeroDivisionError.

We're clearly dealing with some corner case here. I'm trying some fractions to get myself a large Tfactor:

In [90]: log(1e205 / 1e-100)
Out[90]: 702.288453363184

I can't get it higher than that just in mucking around. But an infinite value gets us the problem:

In [92]: log(1e205 / 1e-105)
Out[92]: inf

In [98]: exp(-log(1e205 / 1e-105)) == 0.0
Out[98]: True

So exp can give you back zero, in which case T (very top of this comment) is set to zero, giving the error.

So Tmax / Tmin would need to be extremely small to result in such a large value coming out of -math.log(self.Tmax / self.Tmin). I can't get such a high value in playing around, but getting close:

In [104]: -log(1e-300)
Out[104]: 690.7755278982137

All this would imply that Tmax can be less than Tmin at the end of auto.

OK, leaving this here for now..... Thanks!

terrycojones avatar Dec 04 '20 21:12 terrycojones

I printed out the schedule I get back from some failing runs:

{'tmax': 33.0, 'tmin': 5e-324, 'steps': 22000, 'updates': 100}
{'tmax': 36.0, 'tmin': 5e-324, 'steps': 22000, 'updates': 100}
{'tmax': 45.0, 'tmin': 5e-324, 'steps': 21000, 'updates': 100}
{'tmax': 32.0, 'tmin': 5e-324, 'steps': 22000, 'updates': 100}
{'tmax': 32.0, 'tmin': 5e-324, 'steps': 22000, 'updates': 100}
{'tmax': 30.0, 'tmin': 5e-324, 'steps': 22000, 'updates': 100}
{'tmax': 32.0, 'tmin': 5e-324, 'steps': 22000, 'updates': 100}
{'tmax': 36.0, 'tmin': 3.3e-315, 'steps': 22000, 'updates': 100}
{'tmax': 33.0, 'tmin': 5e-324, 'steps': 22000, 'updates': 100}
{'tmax': 22.0, 'tmin': 5e-324, 'steps': 22000, 'updates': 100}
{'tmax': 33.0, 'tmin': 5e-324, 'steps': 14000, 'updates': 100}
{'tmax': 22.0, 'tmin': 5e-324, 'steps': 19000, 'updates': 100}
{'tmax': 27.0, 'tmin': 5e-324, 'steps': 18000, 'updates': 100}
{'tmax': 21.0, 'tmin': 5e-324, 'steps': 19000, 'updates': 100}
{'tmax': 48.0, 'tmin': 5e-324, 'steps': 35000, 'updates': 100}
{'tmax': 24.0, 'tmin': 3.9e-317, 'steps': 38000, 'updates': 100}

terrycojones avatar Dec 05 '20 15:12 terrycojones