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
--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to