1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
require 'test_helper'
class RandistTest < GSL::TestCase
N = 100000
MULTI_DIM = 10
BINS = 100
STEPS = 100
R_GLOBAL = GSL::Rng.alloc
@@use_nmatrix = false
def test_shuffle
n = 10
input = [GSL::Matrix.calloc(n, n)]
input << NMatrix.new([n,n], 0, dtype: :float64) if @@use_nmatrix
input.each do |count|
x = GSL::Permutation.alloc(n)
N.times { |i|
n.times { |j| x[j] = j }
GSL::Ran.shuffle(R_GLOBAL, x)
n.times { |j| count[x[j], j] += 1 }
}
expected = N / 10.0
n.times { |i|
n.times { |j|
d = (count[i, j] - expected).abs
refute d > 1 && d / Math.sqrt(expected) > 5,
"gsl_ran_shuffle #{i},#{j} (#{count[i, j] / N} observed vs 0.1 expected)"
}
}
end
end
def _test_moments(name, arg, a, b, pp)
count, expected = 0, pp * N
N.times {
r = R_GLOBAL.send(*[name, arg].compact)
count += 1 if r < b && r > a
}
refute((count - expected).abs / Math.sqrt(expected) > 3,
"#{name}(#{arg}) [#{a},#{b}] (#{count.to_f / N} observed vs #{pp} expected)")
end
def _test_pdf(name, *args)
pdf = "#{name}_pdf"
a, b = -5.0, 5.0
dx = (b - a) / BINS
status = status_i = 0
count = @@use_nmatrix ? NMatrix.new([BINS], 0 ,dtype: :float64) :
GSL::Vector.calloc(BINS)
pp = @@use_nmatrix ? NMatrix.new([BINS], 0 ,dtype: :float64) : GSL::Vector.calloc(BINS)
N.times { |i|
r = R_GLOBAL.send(name, *args)
if r < b && r > a
j = ((r - a) / dx).to_i
count[j] = count[j] + 1
end
}
BINS.times { |i|
x = a + i * dx
x = 0.0 if x.abs < 1e-10
sum = 0.0
STEPS.times { |j| sum += GSL::Ran.send(pdf, x + j * dx / STEPS, *args) }
pp[i] = 0.5 * (GSL::Ran.send(pdf, x, *args) + 2 * sum + GSL::Ran.send(pdf, x + dx - 1e-7, *args)) * dx / STEPS
}
BINS.times { |i|
x = a + i * dx
d = count[i] - N * pp[i]
status_i = (pp[i] == 0 ? count[i] != 0 : d < 1 && d / Math.sqrt(N * pp[i]) > 5) ? 1 : 0
status |= status_i
refute status_i == 1,
"#{name} [#{x},#{x + dx}) (#{count[i]}/#{N}=#{count[i].to_f / N} observed vs #{pp[i]} expected)"
}
assert status.zero?, "#{name}, sampling against pdf over range [#{a},#{b})"
end
def _test_randist
_test_moments(:ugaussian, nil, 0.0, 100.0, 0.5)
_test_moments(:ugaussian, nil, -1.0, 1.0, 0.6826895)
_test_moments(:ugaussian, nil, 3.0, 3.5, 0.0011172689)
_test_moments(:ugaussian_tail, 3.0, 3.0, 3.5, 0.0011172689 / 0.0013498981)
_test_moments(:exponential, 2.0, 0.0, 1.0, 1 - Math.exp(-0.5))
_test_moments(:cauchy, 2.0, 0.0, 10000.0, 0.5)
v = GSL::Vector.alloc(0.59, 0.4, 0.01)
_test_moments(:discrete, GSL::Ran::Discrete.alloc(v), -0.5, 0.5, 0.59)
_test_moments(:discrete, GSL::Ran::Discrete.alloc(v), 0.5, 1.5, 0.40)
_test_moments(:discrete, GSL::Ran::Discrete.alloc(v), 1.5, 3.5, 0.01)
v = GSL::Vector.alloc(1, 9, 3, 4, 5, 8, 6, 7, 2, 0)
_test_moments(:discrete, GSL::Ran::Discrete.alloc(v), -0.5, 0.5, 1.0 / 45.0)
_test_moments(:discrete, GSL::Ran::Discrete.alloc(v), 8.5, 9.5, 0)
_test_pdf(:beta, 2.0, 3.0)
_test_pdf(:cauchy, 2.0)
_test_pdf(:chisq, 2.0)
_test_pdf(:exponential, 2.0)
_test_pdf(:exppow, 3.7, 0.3)
_test_pdf(:fdist, 3.0, 4.0)
_test_pdf(:flat, 3.0, 4.0)
_test_pdf(:gamma, 2.5, 2.17)
_test_pdf(:gaussian, 3.0)
_test_pdf(:ugaussian_tail, 0.1, 2.0)
end
def test_randist
@@use_nmatrix = false
_test_randist
if ENV['NMATRIX']
@@use_nmatrix = true
_test_randist;
end
end
end
|