diff options
author | Stuart Sierra <mail@stuartsierra.com> | 2010-01-20 15:39:56 -0500 |
---|---|---|
committer | Stuart Sierra <mail@stuartsierra.com> | 2010-01-20 15:39:56 -0500 |
commit | 2ede388a9267d175bfaa7781ee9d57532eb4f20f (patch) | |
tree | bb42002af196405d7e25cc4e30b4c1c9de5c06d5 /src/clojure/contrib/probabilities | |
parent | 1bc820d96048a6536706ff999e9892649b53c700 (diff) |
Move source files into Maven-style directory structure.
Diffstat (limited to 'src/clojure/contrib/probabilities')
5 files changed, 0 insertions, 788 deletions
diff --git a/src/clojure/contrib/probabilities/examples_finite_distributions.clj b/src/clojure/contrib/probabilities/examples_finite_distributions.clj deleted file mode 100644 index 56f25bad..00000000 --- a/src/clojure/contrib/probabilities/examples_finite_distributions.clj +++ /dev/null @@ -1,209 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; Probability distribution application examples -;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(ns - #^{:author "Konrad Hinsen" - :skip-wiki true - :doc "Examples for finite probability distribution"} - clojure.contrib.probabilities.examples-finite-distributions - (:use [clojure.contrib.probabilities.finite-distributions - :only (uniform prob cond-prob join-with dist-m choose - normalize certainly cond-dist-m normalize-cond)]) - (:use [clojure.contrib.monads - :only (domonad with-monad m-seq m-chain m-lift)]) - (:require clojure.contrib.accumulators)) - -;; Simple examples using dice - -; A single die is represented by a uniform distribution over the -; six possible outcomes. -(def die (uniform #{1 2 3 4 5 6})) - -; The probability that the result is odd... -(prob odd? die) -; ... or greater than four. -(prob #(> % 4) die) - -; The sum of two dice -(def two-dice (join-with + die die)) -(prob #(> % 6) two-dice) - -; The sum of two dice using a monad comprehension -(assert (= two-dice - (domonad dist-m - [d1 die - d2 die] - (+ d1 d2)))) - -; The two values separately, but as an ordered pair -(domonad dist-m - [d1 die - d2 die] - (if (< d1 d2) (list d1 d2) (list d2 d1))) - -; The conditional probability for two dice yielding X if X is odd: -(cond-prob odd? two-dice) - -; A two-step experiment: throw a die, and then add 1 with probability 1/2 -(domonad dist-m - [d die - x (choose (/ 1 2) d - :else (inc d))] - x) - -; The sum of n dice -(defn dice [n] - (domonad dist-m - [ds (m-seq (replicate n die))] - (apply + ds))) - -(assert (= two-dice (dice 2))) - -(dice 3) - - -;; Construct an empirical distribution from counters - -; Using an ordinary counter: -(def dist1 - (normalize - (clojure.contrib.accumulators/add-items - clojure.contrib.accumulators/empty-counter - (for [_ (range 1000)] (rand-int 5))))) - -; Or, more efficiently, using a counter that already keeps track of its total: -(def dist2 - (normalize - (clojure.contrib.accumulators/add-items - clojure.contrib.accumulators/empty-counter-with-total - (for [_ (range 1000)] (rand-int 5))))) - - -;; The Monty Hall game -;; (see http://en.wikipedia.org/wiki/Monty_Hall_problem for a description) - -; The set of doors. In the classical variant, there are three doors, -; but the code can also work with more than three doors. -(def doors #{:A :B :C}) - -; A simulation of the game, step by step: -(domonad dist-m - [; The prize is hidden behind one of the doors. - prize (uniform doors) - ; The player make his initial choice. - choice (uniform doors) - ; The host opens a door which is neither the prize door nor the - ; one chosen by the player. - opened (uniform (disj doors prize choice)) - ; If the player stays with his initial choice, the game ends and the - ; following line should be commented out. It describes the switch from - ; the initial choice to a door that is neither the opened one nor - ; his original choice. - choice (uniform (disj doors opened choice)) - ] - ; If the chosen door has the prize behind it, the player wins. - (if (= choice prize) :win :loose)) - - -;; Tree growth simulation -;; Adapted from the code in: -;; Martin Erwig and Steve Kollmansberger, -;; "Probabilistic Functional Programming in Haskell", -;; Journal of Functional Programming, Vol. 16, No. 1, 21-34, 2006 -;; http://web.engr.oregonstate.edu/~erwig/papers/abstracts.html#JFP06a - -; A tree is represented by two attributes: its state (alive, hit, fallen), -; and its height (an integer). A new tree starts out alive and with zero height. -(def new-tree {:state :alive, :height 0}) - -; An evolution step in the simulation modifies alive trees only. They can -; either grow by one (90% probability), be hit by lightning and then stop -; growing (4% probability), or fall down (6% probability). -(defn evolve-1 [tree] - (let [{s :state h :height} tree] - (if (= s :alive) - (choose 0.9 (assoc tree :height (inc (:height tree))) - 0.04 (assoc tree :state :hit) - :else {:state :fallen, :height 0}) - (certainly tree)))) - -; Multiple evolution steps can be chained together with m-chain, -; since each step's input is the output of the previous step. -(with-monad dist-m - (defn evolve [n tree] - ((m-chain (replicate n evolve-1)) tree))) - -; Try it for zero, one, or two steps. -(evolve 0 new-tree) -(evolve 1 new-tree) -(evolve 2 new-tree) - -; We can also get a distribution of the height only: -(with-monad dist-m - ((m-lift 1 :height) (evolve 2 new-tree))) - - - -;; Bayesian inference -;; -;; Suppose someone has three dice, one with six faces, one with eight, and -;; one with twelve. This person throws one die and gives us the number, -;; but doesn't tell us which die it was. What are the Bayesian probabilities -;; for each of the three dice, given the observation we have? - -; A function that returns the distribution of a dice with n faces. -(defn die-n [n] (uniform (range 1 (inc n)))) - -; The three dice in the game with their distributions. With this map, we -; can easily calculate the probability for an observation under the -; condition that a particular die was used. -(def dice {:six (die-n 6) - :eight (die-n 8) - :twelve (die-n 12)}) - -; The only prior knowledge is that one of the three dice is used, so we -; have no better than a uniform distribution to start with. -(def prior (uniform (keys dice))) - -; Add a single observation to the information contained in the -; distribution. Adding an observation consists of -; 1) Draw a die from the prior distribution. -; 2) Draw an observation from the distribution of that die. -; 3) Eliminate (replace by nil) the trials that do not match the observation. -; 4) Normalize the distribution for the non-nil values. -(defn add-observation [prior observation] - (normalize-cond - (domonad cond-dist-m - [die prior - number (get dice die) - :when (= number observation) ] - die))) - -; Add one observation. -(add-observation prior 1) - -; Add three consecutive observations. -(-> prior (add-observation 1) - (add-observation 3) - (add-observation 7)) - -; We can also add multiple observations in a single trial, but this -; is slower because more combinations have to be taken into account. -; With Bayesian inference, it is most efficient to eliminate choices -; as early as possible. -(defn add-observations [prior observations] - (with-monad cond-dist-m - (let [n-nums #(m-seq (replicate (count observations) (get dice %)))] - (normalize-cond - (domonad - [die prior - nums (n-nums die) - :when (= nums observations)] - die))))) - -(add-observations prior [1 3 7]) diff --git a/src/clojure/contrib/probabilities/examples_monte_carlo.clj b/src/clojure/contrib/probabilities/examples_monte_carlo.clj deleted file mode 100644 index 44c6a7e2..00000000 --- a/src/clojure/contrib/probabilities/examples_monte_carlo.clj +++ /dev/null @@ -1,73 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; Monte-Carlo application examples -;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(ns - #^{:author "Konrad Hinsen" - :skip-wiki true - :doc "Examples for monte carlo methods"} - clojure.contrib.probabilities.random.examples-monte-carlo - (:require [clojure.contrib.generic.collection :as gc]) - (:use [clojure.contrib.probabilities.random-numbers - :only (lcg rand-stream)]) - (:use [clojure.contrib.probabilities.finite-distributions - :only (uniform)]) - (:use [clojure.contrib.probabilities.monte-carlo - :only (random-stream discrete interval normal lognormal exponential - n-sphere - sample sample-sum sample-mean sample-mean-variance)] - :reload) - (:use [clojure.contrib.monads - :only (domonad state-m)])) - -; Create a linear congruential generator -(def urng (lcg 259200 7141 54773 1)) - -;; Use Clojure's built-in random number generator -;(def urng rand-stream) - -; Sample transformed distributions -(defn sample-distribution - [n rt] - (take n (gc/seq (random-stream rt urng)))) - -; Interval [-2, 2) -(sample-distribution 10 (interval -2 2)) -; Compare with a direct transformation -(= (sample-distribution 10 (interval -2 2)) - (map (fn [x] (- (* 4 x) 2)) (take 10 (gc/seq urng)))) - -; Normal distribution -(sample-distribution 10 (normal 0 1)) - -; Log-Normal distribution -(sample-distribution 10 (lognormal 0 1)) - -; Exponential distribution -(sample-distribution 10 (exponential 1)) - -; n-sphere distribution -(sample-distribution 10 (n-sphere 2 1)) - -; Discrete distribution -(sample-distribution 10 (discrete (uniform (range 1 7)))) - -; Compose distributions in the state monad -(def sum-two-dists - (domonad state-m - [r1 (interval -2 2) - r2 (normal 0 1)] - (+ r1 r2))) - -(sample-distribution 10 sum-two-dists) - -; Distribution transformations -(sample-distribution 5 (sample 2 (interval -2 2))) -(sample-distribution 10 (sample-sum 10 (interval -2 2))) -(sample-distribution 10 (sample-mean 10 (interval -2 2))) -(sample-distribution 10 (sample-mean-variance 10 (interval -2 2))) - diff --git a/src/clojure/contrib/probabilities/finite_distributions.clj b/src/clojure/contrib/probabilities/finite_distributions.clj deleted file mode 100644 index a93aa0d8..00000000 --- a/src/clojure/contrib/probabilities/finite_distributions.clj +++ /dev/null @@ -1,203 +0,0 @@ -;; Finite probability distributions - -;; by Konrad Hinsen -;; last updated January 8, 2010 - -;; Copyright (c) Konrad Hinsen, 2009-2010. All rights reserved. The use -;; and distribution terms for this software are covered by the Eclipse -;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) -;; which can be found in the file epl-v10.html at the root of this -;; distribution. By using this software in any fashion, you are -;; agreeing to be bound by the terms of this license. You must not -;; remove this notice, or any other, from this software. - -(ns - #^{:author "Konrad Hinsen" - :doc "Finite probability distributions - This library defines a monad for combining finite probability - distributions."} - clojure.contrib.probabilities.finite-distributions - (:use [clojure.contrib.monads - :only (defmonad domonad with-monad maybe-t m-lift m-chain)] - [clojure.contrib.def :only (defvar)])) - -; The probability distribution monad. It is limited to finite probability -; distributions (e.g. there is a finite number of possible value), which -; are represented as maps from values to probabilities. - -(defmonad dist-m - "Monad describing computations on fuzzy quantities, represented by a finite - probability distribution for the possible values. A distribution is - represented by a map from values to probabilities." - [m-result (fn m-result-dist [v] - {v 1}) - m-bind (fn m-bind-dist [mv f] - (reduce (partial merge-with +) - (for [[x p] mv [y q] (f x)] - {y (* q p)}))) - ]) - -; Applying the monad transformer maybe-t to the basic dist monad results -; in the cond-dist monad that can handle invalid values. The total probability -; for invalid values ends up as the probability of m-zero (which is nil). -; The function normalize takes this probability out of the distribution and -; re-distributes its weight over the valid values. - -(defvar cond-dist-m - (maybe-t dist-m) - "Variant of the dist monad that can handle undefined values.") - -; Normalization - -(defn- scale-by - "Multiply each entry in dist by the scale factor s and remove zero entries." - [dist s] - (into {} - (for [[val p] dist :when (> p 0)] - [val (* p s)]))) - -(defn normalize-cond [cdist] - "Normalize a probability distribution resulting from a computation in - the cond-dist monad by re-distributing the weight of the invalid values - over the valid ones." - (let [missing (get cdist nil 0) - dist (dissoc cdist nil)] - (cond (zero? missing) dist - (= 1 missing) {} - :else (let [scale (/ 1 (- 1 missing))] - (scale-by dist scale))))) - -(defn normalize - "Convert a weight map (e.g. a map of counter values) to a distribution - by multiplying with a normalization factor. If the map has a key - :total, its value is assumed to be the sum over all the other values and - it is used for normalization. Otherwise, the sum is calculated - explicitly. The :total key is removed from the resulting distribution." - [weights] - (let [total (:total weights) - w (dissoc weights :total) - s (/ 1 (if (nil? total) (reduce + (vals w)) total))] - (scale-by w s))) - -; Functions that construct distributions - -(defn uniform - "Return a distribution in which each of the elements of coll - has the same probability." - [coll] - (let [n (count coll) - p (/ 1 n)] - (into {} (for [x (seq coll)] [x p])))) - -(defn choose - "Construct a distribution from an explicit list of probabilities - and values. They are given in the form of a vector of probability-value - pairs. In the last pair, the probability can be given by the keyword - :else, which stands for 1 minus the total of the other probabilities." - [& choices] - (letfn [(add-choice [dist [p v]] - (cond (nil? p) dist - (= p :else) - (let [total-p (reduce + (vals dist))] - (assoc dist v (- 1 total-p))) - :else (assoc dist v p)))] - (reduce add-choice {} (partition 2 choices)))) - -(defn bernoulli - [p] - "Returns the Bernoulli distribution for probability p." - (choose p 1 :else 0)) - -(defn- bc - [n] - "Returns the binomial coefficients for a given n." - (let [r (inc n)] - (loop [c 1 - f (list 1)] - (if (> c n) - f - (recur (inc c) (cons (* (/ (- r c) c) (first f)) f)))))) - -(defn binomial - [n p] - "Returns the binomial distribution, which is the distribution of the - number of successes in a series of n experiments whose individual - success probability is p." - (let [q (- 1 p) - n1 (inc n) - k (range n1) - pk (take n1 (iterate #(* p %) 1)) - ql (reverse (take n1 (iterate #(* q %) 1))) - f (bc n)] - (into {} (map vector k (map * f pk ql))))) - -(defn make-distribution - "Returns the distribution in which each element x of the collection - has a probability proportional to (f x)" - [coll f] - (normalize (into {} (for [k coll] [k (f k)])))) - -(defn zipf - "Returns the Zipf distribution in which the numbers k=1..n have - probabilities proportional to 1/k^s." - [s n] - (make-distribution (range 1 (inc n)) #(/ (java.lang.Math/pow % s)))) - -(defn certainly - "Returns a distribution in which the single value v has probability 1." - [v] - {v 1}) - -(with-monad dist-m - - (defn join-with - "Returns the distribution of (f x y) with x from dist1 and y from dist2." - [f dist1 dist2] - ((m-lift 2 f) dist1 dist2)) - -) - -(with-monad cond-dist-m - (defn cond-prob - "Returns the conditional probability for the values in dist that satisfy - the predicate pred." - [pred dist] - (normalize-cond - (domonad - [v dist - :when (pred v)] - v)))) - -; Select (with equal probability) N items from a sequence - -(defn- nth-and-rest [n xs] - "Return a list containing the n-th value of xs and the sequence - obtained by removing the n-th value from xs." - (let [[h t] (split-at n xs)] - (list (first t) (concat h (rest t))))) - -(with-monad dist-m - - (defn- select-n [n xs] - (letfn [(select-1 [[s xs]] - (uniform (for [i (range (count xs))] - (let [[nth rest] (nth-and-rest i xs)] - (list (cons nth s) rest)))))] - ((m-chain (replicate n select-1)) (list '() xs)))) - - (defn select [n xs] - "Return the distribution for all possible ordered selections of n elements - out of xs." - ((m-lift 1 first) (select-n n xs))) - -) - -; Find the probability that a given predicate is satisfied - -(defn prob - "Return the probability that the predicate pred is satisfied in the - distribution dist, i.e. the sum of the probabilities of the values - that satisfy pred." - [pred dist] - (apply + (for [[x p] dist :when (pred x)] p))) - diff --git a/src/clojure/contrib/probabilities/monte_carlo.clj b/src/clojure/contrib/probabilities/monte_carlo.clj deleted file mode 100644 index e3bc0f7e..00000000 --- a/src/clojure/contrib/probabilities/monte_carlo.clj +++ /dev/null @@ -1,240 +0,0 @@ -;; Monte-Carlo algorithms - -;; by Konrad Hinsen -;; last updated May 3, 2009 - -;; Copyright (c) Konrad Hinsen, 2009. All rights reserved. The use -;; and distribution terms for this software are covered by the Eclipse -;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) -;; which can be found in the file epl-v10.html at the root of this -;; distribution. By using this software in any fashion, you are -;; agreeing to be bound by the terms of this license. You must not -;; remove this notice, or any other, from this software. - -(ns - #^{:author "Konrad Hinsen" - :doc "Monte-Carlo method support - - Monte-Carlo methods transform an input random number stream - (usually having a continuous uniform distribution in the - interval [0, 1)) into a random number stream whose distribution - satisfies certain conditions (usually the expectation value - is equal to some desired quantity). They are thus - transformations from one probability distribution to another one. - - This library represents a Monte-Carlo method by a function that - takes as input the state of a random number stream with - uniform distribution (see - clojure.contrib.probabilities.random-numbers) and returns a - vector containing one sample value of the desired output - distribution and the final state of the input random number - stream. Such functions are state monad values and can be - composed using operations defined in clojure.contrib.monads."} - clojure.contrib.probabilities.monte-carlo - (:refer-clojure :exclude (deftype)) - (:use [clojure.contrib.macros :only (const)]) - (:use [clojure.contrib.types :only (deftype)]) - (:use [clojure.contrib.stream-utils :only (defstream stream-next)]) - (:use [clojure.contrib.monads - :only (with-monad state-m m-lift m-seq m-fmap)]) - (:require [clojure.contrib.generic.arithmetic :as ga]) - (:require [clojure.contrib.accumulators :as acc])) - -;; Random number transformers and random streams -;; -;; A random number transformer is a function that takes a random stream -;; state as input and returns the next value from the transformed stream -;; plus the new state of the input stream. Random number transformers -;; are thus state monad values. -;; -;; Distributions are implemented as random number transformers that -;; transform a uniform distribution in the interval [0, 1) to the -;; desired distribution. Composition of such distributions allows -;; the realization of any kind of Monte-Carlo algorithm. The result -;; of such a composition is always again a distribution. -;; -;; Random streams are defined by a random number transformer and an -;; input random number stream. If the randon number transformer represents -;; a distribution, the input stream must have a uniform distribution -;; in the interval [0, 1). - -; Random stream definition -(deftype ::random-stream random-stream - "Define a random stream by a distribution and the state of a - random number stream with uniform distribution in [0, 1)." - {:arglists '([distribution random-stream-state])} - (fn [d rs] (list d rs))) - -(defstream ::random-stream - [[d rs]] - (let [[r nrs] (d rs)] - [r (random-stream d nrs)])) - -; Rejection of values is used in the construction of distributions -(defn reject - "Return the distribution that results from rejecting the values from - dist that do not satisfy predicate p." - [p dist] - (fn [rs] - (let [[r nrs] (dist rs)] - (if (p r) - (recur nrs) - [r nrs])))) - -; Draw a value from a discrete distribution given as a map from -; values to probabilities. -; (see clojure.contrib.probabilities.finite-distributions) -(with-monad state-m - (defn discrete - "A discrete distribution, defined by a map dist mapping values - to probabilities. The sum of probabilities must be one." - [dist] - (letfn [(pick-at-level [l dist-items] - (let [[[x p] & rest-dist] dist-items] - (if (> p l) - x - (recur (- l p) rest-dist))))] - (m-fmap #(pick-at-level % (seq dist)) stream-next)))) - -; Uniform distribution in an finite half-open interval -(with-monad state-m - (defn interval - [a b] - "Transform a sequence of uniform random numbers in the interval [0, 1) - into a sequence of uniform random numbers in the interval [a, b)." - (let [d (- b a) - f (if (zero? a) - (if (= d 1) - identity - (fn [r] (* d r))) - (if (= d 1) - (fn [r] (+ a r)) - (fn [r] (+ a (* d r)))))] - (m-fmap f stream-next)))) - -; Normal (Gaussian) distribution -(defn normal - "Transform a sequence urs of uniform random number in the interval [0, 1) - into a sequence of normal random numbers with mean mu and standard - deviation sigma." - [mu sigma] - ; This function implements the Kinderman-Monahan ratio method: - ; A.J. Kinderman & J.F. Monahan - ; Computer Generation of Random Variables Using the Ratio of Uniform Deviates - ; ACM Transactions on Mathematical Software 3(3) 257-260, 1977 - (fn [rs] - (let [[u1 rs] (stream-next rs) - [u2* rs] (stream-next rs) - u2 (- 1. u2*) - s (const (* 4 (/ (. Math exp (- 0.5)) (. Math sqrt 2.)))) - z (* s (/ (- u1 0.5) u2)) - zz (+ (* 0.25 z z) (. Math log u2))] - (if (> zz 0) - (recur rs) - [(+ mu (* sigma z)) rs])))) - -; Lognormal distribution -(with-monad state-m - (defn lognormal - "Transform a sequence of uniform random numbesr in the interval [0, 1) - into a sequence of lognormal random numbers with mean mu and standard - deviation sigma." - [mu sigma] - (m-fmap #(. Math exp %) (normal mu sigma)))) - -; Exponential distribution -(with-monad state-m - (defn exponential - "Transform a sequence of uniform random numbers in the interval [0, 1) - into a sequence of exponential random numbers with parameter lambda." - [lambda] - (when (<= lambda 0) - (throw (IllegalArgumentException. - "exponential distribution requires a positive argument"))) - (let [neg-inv-lambda (- (/ lambda)) - ; remove very small numbers to prevent log from returning -Infinity - not-too-small (reject #(< % 1e-323) stream-next)] - (m-fmap #(* (. Math log %) neg-inv-lambda) not-too-small)))) - -; Another implementation of the normal distribution. It uses the -; Box-Muller transform, but discards one of the two result values -; at each cycle because the random number transformer interface cannot -; handle two outputs at the same time. -(defn normal-box-muller - "Transform a sequence of uniform random numbers in the interval [0, 1) - into a sequence of normal random numbers with mean mu and standard - deviation sigma." - [mu sigma] - (fn [rs] - (let [[u1 rs] (stream-next rs) - [u2 rs] (stream-next rs) - v1 (- (* 2.0 u1) 1.0) - v2 (- (* 2.0 u2) 1.0) - s (+ (* v1 v1) (* v2 v2)) - ls (. Math sqrt (/ (* -2.0 (. Math log s)) s)) - x1 (* v1 ls) - x2 (* v2 ls)] - (if (or (>= s 1) (= s 0)) - (recur rs) - [x1 rs])))) - -; Finite samples from a distribution -(with-monad state-m - - (defn sample - "Return the distribution of samples of length n from the - distribution dist" - [n dist] - (m-seq (replicate n dist))) - - (defn sample-reduce - "Returns the distribution of the reduction of f over n samples from the - distribution dist." - ([f n dist] - (if (zero? n) - (m-result (f)) - (let [m-f (m-lift 2 f) - sample (replicate n dist)] - (reduce m-f sample)))) - ([f val n dist] - (let [m-f (m-lift 2 f) - m-val (m-result val) - sample (replicate n dist)] - (reduce m-f m-val sample)))) - - (defn sample-sum - "Return the distribution of the sum over n samples from the - distribution dist." - [n dist] - (sample-reduce ga/+ n dist)) - - (defn sample-mean - "Return the distribution of the mean over n samples from the - distribution dist" - [n dist] - (let [div-by-n (m-lift 1 #(ga/* % (/ n)))] - (div-by-n (sample-sum n dist)))) - - (defn sample-mean-variance - "Return the distribution of the mean-and-variance (a vector containing - the mean and the variance) over n samples from the distribution dist" - [n dist] - (let [extract (m-lift 1 (fn [mv] [(:mean mv) (:variance mv)]))] - (extract (sample-reduce acc/add acc/empty-mean-variance n dist)))) - -) - -; Uniform distribution inside an n-sphere -(with-monad state-m - (defn n-sphere - "Return a uniform distribution of n-dimensional vectors inside an - n-sphere of radius r." - [n r] - (let [box-dist (sample n (interval (- r) r)) - sq #(* % %) - r-sq (sq r) - vec-sq #(apply + (map sq %)) - sphere-dist (reject #(> (vec-sq %) r-sq) box-dist) - as-vectors (m-lift 1 vec)] - (as-vectors sphere-dist)))) - diff --git a/src/clojure/contrib/probabilities/random_numbers.clj b/src/clojure/contrib/probabilities/random_numbers.clj deleted file mode 100644 index bc21769b..00000000 --- a/src/clojure/contrib/probabilities/random_numbers.clj +++ /dev/null @@ -1,63 +0,0 @@ -;; Random number generators - -;; by Konrad Hinsen -;; last updated May 3, 2009 - -;; Copyright (c) Konrad Hinsen, 2009. All rights reserved. The use -;; and distribution terms for this software are covered by the Eclipse -;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) -;; which can be found in the file epl-v10.html at the root of this -;; distribution. By using this software in any fashion, you are -;; agreeing to be bound by the terms of this license. You must not -;; remove this notice, or any other, from this software. - -(ns - #^{:author "Konrad Hinsen" - :doc "Random number streams - - This library provides random number generators with a common - stream interface. They all produce pseudo-random numbers that are - uniformly distributed in the interval [0, 1), i.e. 0 is a - possible value but 1 isn't. For transformations to other - distributions, see clojure.contrib.probabilities.monte-carlo. - - At the moment, the only generator provided is a rather simple - linear congruential generator."} - clojure.contrib.probabilities.random-numbers - (:refer-clojure :exclude (deftype)) - (:use [clojure.contrib.types :only (deftype)]) - (:use [clojure.contrib.stream-utils :only (defstream)]) - (:use [clojure.contrib.def :only (defvar)])) - -;; Linear congruential generator -;; http://en.wikipedia.org/wiki/Linear_congruential_generator - -(deftype ::lcg lcg - "Create a linear congruential generator" - {:arglists '([modulus multiplier increment seed])} - (fn [modulus multiplier increment seed] - {:m modulus :a multiplier :c increment :seed seed}) - (fn [s] (map s (list :m :a :c :seed)))) - -(defstream ::lcg - [lcg-state] - (let [{m :m a :a c :c seed :seed} lcg-state - value (/ (float seed) (float m)) - new-seed (rem (+ c (* a seed)) m)] - [value (assoc lcg-state :seed new-seed)])) - -;; A generator based on Clojure's built-in rand function -;; (and thus random from java.lang.Math) -;; Note that this generator uses an internal mutable state. -;; -;; The state is *not* stored in the stream object and can thus -;; *not* be restored! - -(defvar rand-stream (with-meta 'rand {:type ::rand-stream}) - "A random number stream based on clojure.core/rand. Note that this - generator uses an internal mutable state. The state is thus not stored - in the stream object and cannot be restored.") - -(defstream ::rand-stream - [dummy-state] - [(rand) dummy-state]) |