1
+ ; Copyright (c) Rich Hickey. All rights reserved.
2
+ ; The use and distribution terms for this software are covered by the
3
+ ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
4
+ ; which can be found in the file epl-v10.html at the root of this distribution.
5
+ ; By using this software in any fashion, you are agreeing to be bound by
6
+ ; the terms of this license.
7
+ ; ; You must not remove this notice, or any other, from this software.
8
+
9
+ (ns twitterbuzz.anneal )
10
+
11
+ (defn exp [x]
12
+ (js* " Math.exp(~{x})" ))
13
+
14
+ (defn abs [x]
15
+ (js* " Math.abs(~{x})" ))
16
+
17
+ (defn random []
18
+ (js* " Math.random()" ))
19
+
20
+ (defn standard-prob [e e1 temp]
21
+ (if (< e1 e)
22
+ 1
23
+ (exp (/ (- e e1) temp))))
24
+
25
+ (defn linear-cooling [steps]
26
+ (let [min (- 1 (/ steps (dec steps)))]
27
+ (fn [t]
28
+ (max min (- 1 (/ t steps))))))
29
+
30
+ (defn anneal
31
+ " Given an energy scoring function, a temperature function
32
+ (calculates temp given iteration t), a permutation function (creates
33
+ a candidate next state given a current state and iteration t), and
34
+ an acceptance probability function (of last next energy and temp),
35
+ yields a lazy seq of (accepted?) states of the form
36
+ {:state s :score :best best :best-score :t t}"
37
+
38
+ [energy ; ;(energy state) -> score
39
+ temp ; ;(temp t) -> 0-1.0
40
+ permute ; ;(permute state t) -> new-state
41
+ prob ; ;(prob e e1 temp) -> 0-1.0
42
+ state]
43
+
44
+ (let [init state
45
+ init-score (energy state)
46
+ step (fn step [{:keys [state score best best-score t]:as ret}]
47
+ (loop [next (permute state) t (inc t)]
48
+ (let [next-score (energy next)]
49
+ (if (> (prob score next-score (temp t)) (random ))
50
+ (let [ret {:state next :score next-score :t t
51
+ :best (if (< next-score best-score) next best)
52
+ :best-score (min next-score best-score)}]
53
+ (lazy-seq (cons ret (step ret))))
54
+ (recur (permute state) (inc t))))))]
55
+ (step {:state init :score init-score :best init :best-score init-score :t 0 })))
56
+
57
+
58
+ (comment
59
+
60
+ (take 10 (take-nth 100
61
+ (anneal #(abs (- % 42 ))
62
+ (linear-cooling 1000 )
63
+ (fn [s _] (+ s (- (random ) 0.5 )))
64
+ standard-prob
65
+ 55 )))
66
+ )
0 commit comments