這部份我重新設計了一下。
program(pgm::Type{Val{:linear}}, t0::Float64, a::Float64=1.0) = k -> t0 / (1+a*k)
program(pgm::Type{Val{:quadratic}}, t0::Float64, a::Float64=1.0) = k -> t0 / (1+a*k^2)
program(pgm::Type{Val{:exp}}, t0::Float64, a::Float64=0.85) = k -> t0*a^k
program(pgm::Type{Val{:log}}, t0::Float64, a::Float64=1.1) = k -> t0 / (1+a*log(1+k))
program(pgm::Symbol, t0::Float64, a::Float64) = program(Val{pgm}, t0, a)
type CoolingScheduler
T::Float64
T_MAX::Float64
T_MIN::Float64
cycle::Int64
process::Function
cooling::Function
isfrozen::Function
function CoolingScheduler(pgm::Type{Val{Symbol}}, tmax=500::Float64, tmin=1::Float64, alpha=nothing)
this = new()
(this.T, this.T_MAX, this.T_MIN, this.cycle) = (tmax, tmax, tmin, 1)
this.process = program(pgm, this.T_MAX, this.alpha)
this.isfrozen = () -> this.T <= this.T_MIN
function cooling()
this.T = this.process(this.cycle)
cycle += 1
end
this.cooling = cooling
return this
end
end
CoolingScheduler(pgm::Symbol, tmax::Float64, tmin::Float64, alpha::Float64) = CoolingScheduler(Val{pgm}, tmax, tmin, alpha)
這邊我運用了Julia特有的,至少我沒有在其他語言看過,"Value" type來實作,因為一般來說,multiple dispatch只能對型別做分派,無法對值做分派。
當呼叫program
函式的時候
program(:linear, t0, a)
他會回傳一個線性的降溫程序,接著你只要給他k
他就可以幫你計算出目前的溫度了。
program(:quadratic, t0, a) # 回傳二次的降溫程序
program(:foo, t0, a) # 會出現Error
所以他可以針對不同的值分派不同的函式去執行。
type StabilityCounter
stable_halt::Int64
tolerance::Float64
counter::Int64
ishalt::Function
update::Function
function StabilityCounter(halt=150::Int64, tol=1e-12)
this = new()
this.stable_halt = halt
this.tolerance = tol
this.counter = 0
this.ishalt = () -> this.counter >= this.stable_halt
function update(ΔE::Float64)
if ΔE < this.tolerance
this.counter += 1
else
this.counter = 0
end
end
this.update = update
return this
end
end
這個是個穩定計數器,他會計算降溫的過程中是不是已經進入穩定。
穩定的定義在前面沒有講到,他會去計算能量差是否小於某個容忍值,如果比容忍值小就代表兩個幾乎是一樣的,就代表穩定了。
如果連續穩定達到某個水準,那我們就說他可以停機了,所以會去比較ΔE
跟this.tolerance
哪個小,然後決定要不要重新計數。