aboutsummaryrefslogtreecommitdiff
path: root/src/clojure/contrib/probabilities
diff options
context:
space:
mode:
authorStuart Sierra <mail@stuartsierra.com>2010-01-20 15:39:56 -0500
committerStuart Sierra <mail@stuartsierra.com>2010-01-20 15:39:56 -0500
commit2ede388a9267d175bfaa7781ee9d57532eb4f20f (patch)
treebb42002af196405d7e25cc4e30b4c1c9de5c06d5 /src/clojure/contrib/probabilities
parent1bc820d96048a6536706ff999e9892649b53c700 (diff)
Move source files into Maven-style directory structure.
Diffstat (limited to 'src/clojure/contrib/probabilities')
-rw-r--r--src/clojure/contrib/probabilities/examples_finite_distributions.clj209
-rw-r--r--src/clojure/contrib/probabilities/examples_monte_carlo.clj73
-rw-r--r--src/clojure/contrib/probabilities/finite_distributions.clj203
-rw-r--r--src/clojure/contrib/probabilities/monte_carlo.clj240
-rw-r--r--src/clojure/contrib/probabilities/random_numbers.clj63
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])