# max / min / smallest float value on Python 2.5

duncan smith buzzard at urubu.freeserve.co.uk
Sun Feb 7 21:45:59 CET 2010

```Steven D'Aprano wrote:
> On Sun, 07 Feb 2010 03:02:05 +0000, duncan smith wrote:
>
>> The precise issue is that I'm supplying a default value of
>> 2.2250738585072014e-308 for a parameter (finishing temperature for a
>> simulated annealing algorithm) in an application.  I develop on
>> Ubuntu64, but (I am told) it's too small a value when run on a Win32
>> server.  I assume it's being interpreted as zero and raising an
>> exception.  Thanks.
>
> I'm trying to think of what sort of experiment would be able to measure
> temperatures accurate to less than 3e-308 Kelvin, and my brain boiled.
>
> Surely 1e-100 would be close enough to zero as to make no practical
> difference? Or even 1e-30? Whatever you're simulating surely isn't going
> to require 300+ decimal points of accuracy.
>
> I must admit I'm not really familiar with simulated annealing, so I could
> be completely out of line, but my copy of "Numerical Recipes ..." by
> Press et al has an example, and they take the temperature down to about
> 1e-6 before halting. Even a trillion times lower that that is 1e-15.
>
>

It depends on the optimisation problem, but I suppose the fitness
functions could be tweaked.  I could paste the actual code if anyone's
interested, but the following pseudo-python gives the idea.  For an
exponential cooling schedule the temperatures are generated as below.
The lower the final temperature the greater the number of iterations,
and the longer the algorithm spends searching locally for an optimal
solution (having already searched more widely for areas of high fitness
at higher temperatures).  The probability of moving to a less fit
solution is given by exp(dF/temp) where dF is a (negative) change in
fitness and temp is the current temperature.  So I could scale the
fitness function to cope with higher finishing temperatures.

I'm going to have to think about the point raised by Steve (Holden).

I also think I can probably improve on raising StopIteration if
exp(dF/temp) overflows by yielding False instead (although if it does
overflow it probably indicates a poor choice of cooling schedule for the
given problem).  Stuff to think about.  Cheers.

Duncan

import random
import math

def temps(start, final, mult):
t = start
while t > final:
yield t
t *= mult

def sim_anneal(permuter, start, final, mult):
rand = random.random
exp = math.exp
for temp in temps(start, final, mult):
dF = permuter.next()
if dF >= 0:
yield True
else:
try:
yield rand() < exp(dF / temp)
except OverflowError:
raise StopIteration

class Permuter(object):
def __init__(self, obj):
self.obj = obj
self.proposed = None

def run(self, start, final, mult):
for decision in sim_anneal(self, start, final, mult):
if decision:
# commit proposed change to self.obj

def next():
# propose a change to self.obj
# calculate and return the change in fitness
self.proposed = proposed
return dF

```