Ну, этот код действительно предназначен для меня и больше ни для кого. Я бросил это вместе через двадцать минут на днях для курса по марковским процессам. Я конечно нашел это полезным. Я использовал это, чтобы убедить профессора в том, что мой теоретический анализ проблемы был правильным. Честно говоря, классная штука (я думаю!) На самом деле - только первая функция, sample
. Я использую подобную функцию во многих своих проектах, и каким-то образом, спеша взломать ее, я наткнулся на свое лучшее решение.
(defn sample
"Samples once a discrete random distribution defined by
a vector. E.g., (sample [0.25 0.2 0.1 0.45]) should output
'0' 25% of the time, '1' 20% of the time, etc."
[p]
(let [r (rand)]
(count (take-while #(< % r) (reductions + p)))))
(defn transition
"Given a transition matrix and a history vector, returns
the history with an additional time step added."
[m h]
(conj h (sample (nth m (last h)))))
(defn process-gen
"Takes a transition probability matrix, initial state
probabilities, and a function.
The initial state probs should take the form [p .. q].
The function should accept the full process history
and return true if the process should stop.
Returns a function of no arguments that returns a full
simulated history of the process."
[m i f]
(fn [] (loop [h [(sample i)]] (if (f h) h (recur (transition m h))))))
(defn transition2
"Given a transition matrix and the current state, returns
a sampled state for the next time step."
[m s]
(sample (nth m s)))
(defn lazy-process
"Takes a transition probability matrix, initial state
probabilities, and a function.
The initial state probs should take the form [p .. q].
Returns a function which, when run, produces an infinite
lazy list sampling the process."
[m i]
(fn [] f
([] (f (sample initial)))
([s] (let [i (transition2 m s)]
(cons i (lazy-seq (f i)))))))
Удаление комментариев:
(defn sample [p]
(let [r (rand)]
(count (take-while #(< % r) (reductions + p)))))
(defn transition [m h]
(conj h (sample (nth m (last h)))))
(defn process-gen [m i f]
(fn [] (loop [h [(sample i)]] (if (f h) h (recur (transition m h))))))
(defn transition2 [m s]
(sample (nth m s)))
(defn lazy-process-gen [m i]
(fn [] f
([] (f (sample initial)))
([s] (let [i (transition2 m s)]
(cons i (lazy-seq (f i)))))))
Пример использования:
user=>(def squirrel-matrix [[0.8797 0.0212 0.0981 0.0010]
[0.0382 0.8002 0.0273 0.1343]
[0.0527 0.0041 0.8802 0.0630]
[0.0008 0.0143 0.0527 0.9322]])
user=>(def my-process (process-gen squirrel-matrix [1 0 0 0] #(and (> (count %) 1) (= 0 (last %)))))
user=> (/ (reduce + (map (comp dec count) (repeatedly 1000000 my-process))) 1000000.)
5.820319
user=> (let [hs (reduce + (filter #(> % 1) (map (comp dec count) (repeatedly 1000000 my-process))))] (/ (reduce + hs)) (count hs)))
5002699/120880 ; ~41.386
Эти два числа отвечают, через чрезмерное моделирование, двум различным интерпретациям вопроса здесь .
Я должен признаться, что немного почистил свой код для всех вас. В тот день, когда я написал это, я обнаружил, что Clojure разрешил Unicode в именах символов. Возможно, я изменил язык из-за немного . ;-) Итак ... эти первые три функции на самом деле выглядят так в моем файле!
(Λ σ [p] (let [r (rand)] (|| (take-while #(< % r) (∮ + p)))))
(Λ Δ [Ξ ξ] (⊞ ξ (σ (§ Ξ (last ξ)))))
(Λ Π [Ξ i ω] (λ [] (⟳ [ξ [(σ i)]] (⇒ (ω ξ) ξ (⟲ (Δ Ξ ξ))))))