]> gitweb.michael.orlitzky.com - dead/census-tools.git/blob - src/probability/Distribution.py
Added the probability package containing the Distribution module.
[dead/census-tools.git] / src / probability / Distribution.py
1 import random
2
3 class Distribution(object):
4 """
5 A general class representing a probability distribution.
6 """
7
8 def __init__(self):
9 """
10 components is a list of probability distributions contained
11 within this one. Right now, it's only used for sums of other
12 distributions. This might change once I have a clearer idea of
13 how it should work.
14 """
15 self.components = []
16
17
18 def __add__(self, dist2):
19 """
20 Add another distribution to this one. Since we don't know what
21 kind of distributions we'll be adding here, we return a new
22 copy of the most general kind.
23 """
24 d = Distribution()
25 d.components = self.components + dist2.components
26 return d
27
28
29 def sample(self):
30 """
31 Sample one value from the distribution.
32 """
33 if len(self.components) == 0:
34 return None
35 else:
36 return sum([component.sample() for component in self.components])
37
38
39 def cdf(self, x):
40 """
41 Evaluate the cumulative distribution function at x. Since we don't
42 know our components, there is no good way to do this. Instead, we
43 take a large number of samples, and see how many were less than or
44 equal to x.
45 """
46 trials = 1000
47 lte_count = 0
48
49 for i in range(0, trials):
50 if self.sample() <= x:
51 lte_count += 1
52
53 return (float(lte_count) / float(trials))
54
55
56
57 class Uniform(Distribution):
58 """
59 Represents a uniform probability distribution.
60 """
61
62 def __init__(self, a, b):
63 """
64 In subclasses, we know that there are no other components. For
65 example, a uniform distribution is just made up of a uniform
66 distribution and not, say, the sum of two uniforms (because
67 that would no longer be uniform).
68 """
69 self.components = [self]
70 self.min = float(min(a,b))
71 self.max = float(max(a,b))
72
73
74 def sample(self):
75 return random.uniform(self.min, self.max)
76
77
78 def cdf(self, x):
79 """
80 We can evaluate the CDF in special cases like this.
81 """
82 x = float(x)
83
84 if x <= self.min:
85 return 0.0
86 elif x >= self.max:
87 return 1.0
88 else:
89 # x is somewhere between self.min and self.max and is equally
90 # likely to be at all points in between; so, we just compute
91 # "how far" through the interval (self.min, self.max) is as a
92 # fraction of the whole, and return that.
93 return ((x - self.min) / (self.max - self.min))