00001
00002
00003
00004 from __future__ import division
00005 from random import random
00006
00007 def integrate(f, lo, hi, steps=1000):
00008 dx = (hi - lo) / steps
00009 lo += dx / 2
00010 return sum(f(i*dx + lo) * dx for i in range(steps))
00011
00012 def make_cdf(f, lo, hi, steps=1000):
00013 total_area = integrate(f, lo, hi, steps)
00014 def cdf(x):
00015 assert lo <= x <= hi
00016 return integrate(f, lo, x, steps) / total_area
00017 return cdf
00018
00019 def bisect(target, f, lo, hi, n=20):
00020 'Find x between lo and hi where f(x)=target'
00021 for i in range(n):
00022 mid = (hi + lo) / 2.0
00023 if target < f(mid):
00024 hi = mid
00025 else:
00026 lo = mid
00027 return (hi + lo) / 2.0
00028
00029 def make_user_distribution(f, lo, hi, steps=1000, n=20):
00030 cdf = make_cdf(f, lo, hi, steps)
00031 return lambda: bisect(random(), cdf, lo, hi, n)
00032
00033 if __name__ == '__main__':
00034 def linear(x):
00035 return 3 * x - 6
00036 lo, hi = 2, 10
00037 r = make_user_distribution(linear, lo, hi)
00038 for i in range(20):
00039 print r()