之前有了大致的框架,不過對於控制溫度下降的速度也是重要的一環。
這決定了整體函數收斂的情況。
參考了A Comparison of Cooling Schedules for Simulated Annealing (Artificial Intelligence)
SCHEDULES = Dict{Symbol, Function}()
SCHEDULES[:linear] = (k, a, t0) -> t0 / (1+a*k)
SCHEDULES[:quadratic] = (k, a, t0) -> t0 / (1+a*k^2)
SCHEDULES[:exp] = (k, a, t0) -> t0*a^k
SCHEDULES[:log] = (k, a, t0) -> t0 / (1+a*log(1+k))
type CoolingScheduler
    T::Float64
    T_MAX::Float64
    T_MIN::Float64
    alpha::Float64
    cooling::Function
    isfrozen::Function
    function CoolingScheduler(sch, tmax=500, tmin=1, alpha=nothing)
        this = new()
        (this.T, this.T_MAX, this.T_MIN) = (tmax, tmax, tmin)
        if alpha == nothing
            if sch == :exp
                alpha = 0.85
            elseif sch == :log
                alpha = 1.1
            else
                alpha = 1.0
            end
        end
        this.alpha = alpha
        this.cooling = k -> this.T = SCHEDULES[sch](k, this.alpha, this.T_MAX)
        this.isfrozen = () -> this.T <= this.T_MIN
        return this
    end
end
前面宣告了不同種的scheduler,後面宣告了CoolingScheduler,他基本上掌管了溫度跟降溫的程序,所以每次呼叫cooling的時候就進行一次降溫,isfrozen去檢查是不到到達T_MIN的意思,如果到達,那就freeze起來!
這邊的cooling跟isfrozen用了傳統OOP的寫法,把行為寫在型別的定義當中,這麼做只是覺得在行為的解釋上比較直覺。