Randomness with Clojure

Psyleron sells a hardware random number generator and associated software package for experimentation on the interaction of consciousness and randomness. No, don’t laugh. Princeton Engineering Anomalies Research conducted decades of methodologically rigorous research into the nature of randomness. They concluded that deliberate conscious intention can produce a small but statistically significant and reproducible effect on the outcome of stochastic processes. Psyleron is a commercial offshoot of PEAR.

The Psyleron system, unfortunately, costs hundreds of dollars and only runs on Windows, so I wrote some quick Clojure to do experimentation with randomness, using /dev/random as the source. (It appears that /dev/random on Mac OS X does not provide the same quality guarantees as it does on Linux, but it’s fine for a prototype and the implementation allows easy substitution of another randomness source later.)

Clojure random walk generator

(ns randomwalker.core
  (:use [incanter core charts]))

(defn random-walk
  "Returns a random walk of length steps. random-fn should return a random integer."
  [steps list random-fn]
  (if (= 1 steps)
    list
    (recur (dec steps) 
           (conj list
                   (+
                    (if (odd? (random-fn)) 1 -1)
                    (or (last list) 0)))
           random-fn)))


(defn dev-random-walk
  "Returns a random walk of length steps based on random numbers read from /dev/random."
  [steps]
  (with-open [random (java.io.FileInputStream. "/dev/random")]
    (random-walk steps [0] (fn [] (.read random)))))

(defn view-walk
  "Visualize a random walk."
  [steps]
  (view (incanter.charts/xy-plot (range 0 (dec steps)) (dev-random-walk steps))))

(defn walk-ratio
  "Generates the given number of random walks and returns the ratio of (walks ending > 0) / (walks ending < 0)."
  [runs steps-per-run greater less]
  (if (zero? runs)
    (double (/ greater less))
    (let [final (last (dev-random-walk steps-per-run))
          ;foo (println final)
          new-greater (if (> final 0) (inc greater) greater)
          new-less (if (< final 0) (inc less) less)]
      (recur (dec runs) steps-per-run new-greater new-less))))

This code generates a simple random walk. The user can easily visualize the random walk with Incanter, and it looks suspiciously like a stock chart.

Clojure Random Walker screenshotScreenshot of the Clojure Random Walker in action

Psyleron type functionality first vaguely appears in walk-ratio. This generates the requested number of random walks and returns the ratio of those that ended above zero to those that ended below. I imagine this will become the basis for some Psyleron Reflector style games and experiments.

This is probably not the most efficient way to implement this; any suggestions are welcome. Any ideas for a better source of randomness? Any insight into how the Psyleron games work? Their descriptions are a bit short on the details.

One Response to Randomness with Clojure