(defn random-stream [P]
(let [pseq (vec (mapcat (fn[[k v]](repeat v k )) P))]
(for [i (range)] (rand-nth pseq))))
(defn cost [encoder decoder message]
(let [coded (encoder message)]
(if (= (decoder coded) message) (count coded) :fail)))
(defn decoder
([code-tree stream] (decoder code-tree code-tree stream))
([current-code-tree code-tree stream]
(lazy-seq
(if (keyword? current-code-tree)
(cons current-code-tree (decoder code-tree code-tree stream))
(if-let [stream (seq stream)]
(if (= (first stream) 1)
(decoder (first current-code-tree) code-tree (rest stream))
(decoder (second current-code-tree) code-tree (rest stream))))))))
(defn encoder [code stream] (mapcat code stream))
(defn make-encoder [code] (fn [s] (encoder code s)))
(defn make-decoder [code-tree] (fn[s] (decoder code-tree s)))
(defn combine-keywords [& a] (keyword (apply str (mapcat #(drop 1 (str %)) a))))
(defn split-keyword [a] (map #(keyword (str %)) (drop 1 (str a))))
(defn make-combination-encoder [code n]
(fn [s] (encoder code (map #(apply combine-keywords %) (partition n s)))))
(defn make-combination-decoder [code-tree]
(fn [s] (mapcat split-keyword (decoder code-tree s))))
(def fair-coin {:H 1 :T 1})
(def unfair-coin {:H 3 :T 1})
(def unfair-pairs {:HH 9, :HT 3, :TH 3, :TT 1})
(def fair-code-tree [:H :T])
(def fair-code {:H '(1) :T '(0)})
(def unfair-code-tree [ :HH [ :HT [ :TH :TT]]])
(def unfair-code {:HH '(1) :HT '(0 1) :TH '(0 0 1) :TT '(0 0 0)})
(def fair-pairs {:HH 1 :HT 1 :TH 1 :TT 1})
(defn estimate-cost [P encoder decoder]
(let [n 100000
c (cost encoder decoder (take n (random-stream P)))]
(if (number? c) (float (/ c n)) c)))
(estimate-cost fair-coin (make-encoder fair-code) (make-decoder fair-code-tree)) (estimate-cost unfair-coin (make-encoder fair-code) (make-decoder fair-code-tree))
(estimate-cost unfair-pairs (make-encoder unfair-code) (make-decoder unfair-code-tree)) (estimate-cost fair-pairs (make-encoder unfair-code) (make-decoder unfair-code-tree))
(estimate-cost unfair-coin (make-combination-encoder unfair-code 2) (make-combination-decoder unfair-code-tree)) (estimate-cost fair-coin (make-combination-encoder unfair-code 2) (make-combination-decoder unfair-code-tree))
(defn combine-distributions
([P] P)
([P1 P2]
(into {}
(for [[s1 p1] P1
[s2 p2] P2]
[(combine-keywords s1 s2) (* p1 p2)])))
([P1 P2 & Plist] (reduce combine-distributions (cons P1 (cons P2 Plist)))))
(def unfair-triples (combine-distributions unfair-coin unfair-coin unfair-coin))
{:HHH 27, :HHT 9, :HTH 9, :HTT 3, :THH 9, :THT 3, :TTH 3, :TTT 1}
{:HHH 27, :HHT 9, :HTH 9, :HTT 3, :THH 9, :THT 3, {:TTH 3, :TTT 1} 4}
{:HHH 27, :HHT 9, :HTH 9, :HTT 3, :THH 9, :THT 3, {:TTH 3, :TTT 1} 4}
{:HHH 27, :HHT 9, :HTH 9, :HTT 3, :THH 9, {:THT 3, {:TTH 3, :TTT 1} 4} 7}
(defn huffman-combine [P]
(let [plist (sort-by second P)
newelement (into {} (take 2 plist))]
(into {} (cons [newelement (reduce + (vals newelement))] (drop 2 plist)))))
(nth (iterate huffman-combine unfair-triples) (dec (dec (count unfair-triples))))
(require 'clojure.walk)
(defn make-code-tree [P]
(clojure.walk/postwalk #(if (map? %) (into[] (map first %)) %)
(nth (iterate huffman-combine P) (dec (dec (count P))))))
(def triple-code-tree (make-code-tree unfair-triples))
(defn symbols [prefix code-tree]
(if (keyword? code-tree) (list prefix code-tree)
(concat (symbols (cons 1 prefix) (first code-tree))
(symbols (cons 0 prefix) (second code-tree)))))
(defn make-code [code-tree]
(into {} (map (fn[[c s]][s (reverse c)]) (partition 2 (symbols '() code-tree)))))
(def triple-code (make-code triple-code-tree))
(estimate-cost unfair-triples (make-encoder triple-code) (make-decoder triple-code-tree))
(defn bit-rate [P n]
(let [Pn (apply combine-distributions (repeat n P))
tree (make-code-tree Pn)]
(/ (estimate-cost Pn (make-encoder (make-code tree)) (make-decoder tree)) n)))
(bit-rate unfair-coin 1) (bit-rate unfair-coin 2) (bit-rate unfair-coin 3) (bit-rate unfair-coin 4) (bit-rate unfair-coin 5) (bit-rate unfair-coin 6) (bit-rate unfair-coin 7) (bit-rate unfair-coin 8) (bit-rate unfair-coin 9) (bit-rate unfair-coin 10) (bit-rate unfair-coin 11)
No comments:
Post a Comment