| 1 | ;; Shuffling and sampling |
|---|
| 2 | ;; Liam Healy, Sat Dec 2 2006 - 18:40 |
|---|
| 3 | ;; Time-stamp: <2008-02-17 16:31:02EST shuffling-sampling.lisp> |
|---|
| 4 | ;; $Id$ |
|---|
| 5 | |
|---|
| 6 | (in-package :gsl) |
|---|
| 7 | |
|---|
| 8 | ;;; These are currently defined only for vectors. |
|---|
| 9 | |
|---|
| 10 | (defmfun shuffle (generator base) |
|---|
| 11 | "gsl_ran_shuffle" |
|---|
| 12 | (((generator generator) :pointer) |
|---|
| 13 | ((gsl-array base) :pointer) ((dim0 base) size) ((element-size base) size)) |
|---|
| 14 | :c-return :void |
|---|
| 15 | :documentation ; FDL |
|---|
| 16 | "Randomly shuffle the order of n objects, each of |
|---|
| 17 | size size, stored in the array base[0...n-1]. The |
|---|
| 18 | output of the random number generator r is used to produce the |
|---|
| 19 | permutation. The algorithm generates all possible n! |
|---|
| 20 | permutations with equal probability, assuming a perfect source of random |
|---|
| 21 | numbers.") |
|---|
| 22 | |
|---|
| 23 | (defmfun choose-random (generator dest src) |
|---|
| 24 | "gsl_ran_choose" |
|---|
| 25 | (((generator generator) :pointer) |
|---|
| 26 | ((gsl-array dest) :pointer) ((dim0 dest) size) |
|---|
| 27 | ((gsl-array src) :pointer) ((dim0 src) size) ((element-size src) size)) |
|---|
| 28 | ;; This is described in the GSL docs as returning int, but it does |
|---|
| 29 | ;; not say what the return value means. Therefore, we ignore it. |
|---|
| 30 | :c-return :void |
|---|
| 31 | :documentation ; FDL |
|---|
| 32 | "Fill the array dest[k] with k objects taken |
|---|
| 33 | randomly from the n elements of the array |
|---|
| 34 | src[0...n-1]. The objects are each of size size. The |
|---|
| 35 | output of the random number generator r is used to make the |
|---|
| 36 | selection. The algorithm ensures all possible samples are equally |
|---|
| 37 | likely, assuming a perfect source of randomness. |
|---|
| 38 | |
|---|
| 39 | The objects are sampled without replacement, thus each object can |
|---|
| 40 | only appear once in dest[k]. It is required that k be less |
|---|
| 41 | than or equal to n. The objects in dest will be in the |
|---|
| 42 | same relative order as those in src. You will need to call |
|---|
| 43 | #'shuffle if you want to randomize the order.") |
|---|
| 44 | |
|---|
| 45 | (defmfun sample (generator dest src) |
|---|
| 46 | "gsl_ran_sample" |
|---|
| 47 | (((generator generator) :pointer) |
|---|
| 48 | ((gsl-array dest) :pointer) ((dim0 dest) size) |
|---|
| 49 | ((gsl-array src) :pointer) ((dim0 src) size) ((element-size src) size)) |
|---|
| 50 | :c-return :void |
|---|
| 51 | :documentation |
|---|
| 52 | "Like #'choose-random, but samples k items |
|---|
| 53 | from the original array of n items src with replacement, so |
|---|
| 54 | the same object can appear more than once in the output sequence |
|---|
| 55 | dest. There is no requirement that k be less than n |
|---|
| 56 | in this case.") |
|---|
| 57 | |
|---|
| 58 | ;;; Examples and unit test |
|---|
| 59 | #| |
|---|
| 60 | (make-tests shuffling-sampling |
|---|
| 61 | (letm ((rng (random-number-generator *mt19937* 0)) |
|---|
| 62 | (v1 (vector-fixnum #(1 2 3 4 5 6 7 8)))) |
|---|
| 63 | (shuffle rng v1) |
|---|
| 64 | (data v1)) |
|---|
| 65 | (letm ((rng (random-number-generator *mt19937* 0)) |
|---|
| 66 | (v1 (vector-fixnum #(1 2 3 4 5 6 7 8))) |
|---|
| 67 | (v2 (vector-fixnum 4))) |
|---|
| 68 | (choose-random rng v2 v1) |
|---|
| 69 | (data v2)) |
|---|
| 70 | (letm ((rng (random-number-generator *mt19937* 0)) |
|---|
| 71 | (v1 (vector-fixnum #(1 2 3 4 5 6 7 8))) |
|---|
| 72 | (v2 (vector-fixnum 10))) |
|---|
| 73 | (sample rng v2 v1) |
|---|
| 74 | (data v2))) |
|---|
| 75 | |# |
|---|
| 76 | |
|---|
| 77 | (LISP-UNIT:DEFINE-TEST SHUFFLING-SAMPLING |
|---|
| 78 | (LISP-UNIT::ASSERT-NUMERICAL-EQUAL |
|---|
| 79 | (LIST #(4 3 6 1 5 7 2 8)) |
|---|
| 80 | (MULTIPLE-VALUE-LIST |
|---|
| 81 | (LETM |
|---|
| 82 | ((RNG (RANDOM-NUMBER-GENERATOR *MT19937* 0)) |
|---|
| 83 | (V1 (VECTOR-FIXNUM #(1 2 3 4 5 6 7 8)))) |
|---|
| 84 | (SHUFFLE RNG V1) (DATA V1)))) |
|---|
| 85 | (LISP-UNIT::ASSERT-NUMERICAL-EQUAL |
|---|
| 86 | (LIST #(2 3 5 8)) |
|---|
| 87 | (MULTIPLE-VALUE-LIST |
|---|
| 88 | (LETM |
|---|
| 89 | ((RNG (RANDOM-NUMBER-GENERATOR *MT19937* 0)) |
|---|
| 90 | (V1 (VECTOR-FIXNUM #(1 2 3 4 5 6 7 8))) |
|---|
| 91 | (V2 (VECTOR-FIXNUM 4))) |
|---|
| 92 | (CHOOSE-RANDOM RNG V2 V1) |
|---|
| 93 | (DATA V2)))) |
|---|
| 94 | (LISP-UNIT::ASSERT-NUMERICAL-EQUAL |
|---|
| 95 | (LIST #(8 2 3 8 2 4 8 6 5 6)) |
|---|
| 96 | (MULTIPLE-VALUE-LIST |
|---|
| 97 | (LETM |
|---|
| 98 | ((RNG (RANDOM-NUMBER-GENERATOR *MT19937* 0)) |
|---|
| 99 | (V1 (VECTOR-FIXNUM #(1 2 3 4 5 6 7 8))) |
|---|
| 100 | (V2 (VECTOR-FIXNUM 10))) |
|---|
| 101 | (SAMPLE RNG V2 V1) (DATA V2))))) |
|---|