Project

General

Profile

root / branches / 1.1 / src / haizea / common / stats.py @ 798

1
# -------------------------------------------------------------------------- #
2
# Copyright 2006-2009, University of Chicago                                 #
3
# Copyright 2008-2009, Distributed Systems Architecture Group, Universidad   #
4
# Complutense de Madrid (dsa-research.org)                                   #
5
#                                                                            #
6
# Licensed under the Apache License, Version 2.0 (the "License"); you may    #
7
# not use this file except in compliance with the License. You may obtain    #
8
# a copy of the License at                                                   #
9
#                                                                            #
10
# http://www.apache.org/licenses/LICENSE-2.0                                 #
11
#                                                                            #
12
# Unless required by applicable law or agreed to in writing, software        #
13
# distributed under the License is distributed on an "AS IS" BASIS,          #
14
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
15
# See the License for the specific language governing permissions and        #
16
# limitations under the License.                                             #
17
# -------------------------------------------------------------------------- #
18

    
19
import random
20
import math
21
from haizea.common.utils import abstract
22

    
23

    
24
class Distribution(object):
25
    def __init__(self):
26
        self.random = random.Random()
27
    
28
    def seed(self, x):
29
        self.random.seed(x)
30

    
31
class ContinuousDistribution(Distribution):
32
    def __init__(self):
33
        Distribution.__init__(self)
34
        
35
    def get(self): 
36
        abstract()
37
            
38
    def get_list(self, n):
39
        l = []
40
        for i in xrange(1, n):
41
            l.append(self.get())
42
        return l
43

    
44
        
45
class BoundedContinuousDistribution(ContinuousDistribution):
46
    def __init__(self, min, max):
47
        ContinuousDistribution.__init__(self)
48
        self.min = float(min)
49
        self.max = float(max)
50
        
51

    
52
class UniformDistribution(BoundedContinuousDistribution):
53
    def __init__(self, min, max):
54
        BoundedContinuousDistribution.__init__(self, min, max)
55
        
56
    def get(self):
57
        return self.random.uniform(self.min, self.max)
58
                    
59
class NormalDistribution(ContinuousDistribution):
60
    def __init__(self, mu, sigma):
61
        ContinuousDistribution.__init__(self)
62
        self.mu = mu
63
        self.sigma = sigma
64
        
65
    def get(self):
66
        return self.random.normalvariate(self.mu, self.sigma)
67
    
68
class BoundedNormalDistribution(BoundedContinuousDistribution):
69
    def __init__(self, min, max, mu, sigma):
70
        BoundedContinuousDistribution.__init__(self, min, max)
71
        self.mu = float(mu)
72
        self.sigma = float(sigma)
73
        
74
    def get(self):
75
        n = self.random.normalvariate(self.mu, self.sigma) 
76
        if n < self.min:
77
            n = self.min
78
        elif n > self.max:
79
            n = self.max
80
        return n
81
        
82
    
83
class BoundedParetoDistribution(BoundedContinuousDistribution):
84
    def __init__(self, min, max, alpha, invert = False):
85
        BoundedContinuousDistribution.__init__(self, min, max)
86
        self.alpha = float(alpha)
87
        self.invert = invert
88
        
89
    def get(self):
90
        u = self.random.random()
91
        l = self.min
92
        h = self.max
93
        a = self.alpha
94
        p = (-((u*h**a - u*l**a - h**a)/((h**a)*(l**a))))**(-1/a)
95
        if self.invert:
96
            p = h - p
97
        return p
98
           
99
class TruncatedParetoDistribution(BoundedContinuousDistribution):
100
    def __init__(self, min, max, scale, alpha, invert = False):
101
        BoundedContinuousDistribution.__init__(self, min, max)
102
        self.alpha = float(alpha)
103
        self.scale = float(scale)
104
        self.invert = invert
105
        
106
    def get(self):
107
        # Temporary kludge. This just happens to be a range
108
        # that, with shape and scale both 1.0, yields a roughly
109
        # 80-20 distribution
110
        min2 = 0.0
111
        max2 = 10.0
112
        v = max2 + 1
113
        while v > max2: 
114
            u = self.random.random()
115
            pareto = self.scale/u**(1/self.alpha)
116
            v = pareto - (self.scale - min2)
117
            
118
        v = self.min + (v/10.0)*(self.max - self.min)
119
        
120
        if self.invert:
121
            v = self.max - (v - self.min)
122
        return v
123
                                    
124
            
125
class DiscreteDistribution(object):
126
    def __init__(self, values):
127
        self.values = values
128
        self.num_values = len(self.values)
129

    
130
    # Expects value in [0,1)
131
    def _get_from_prob(self, prob):
132
        pos = int(math.floor(prob * self.num_values))
133
        return self.values[pos]
134
    
135
class DiscreteUniformDistribution(DiscreteDistribution):
136
    def __init__(self, values):
137
        DiscreteDistribution.__init__(self, values)
138
        self.__distribution = UniformDistribution(0,1)
139
        
140
    def seed(self, x):
141
        self.__distribution.seed(x)
142
        
143
    def get(self):
144
        return self._get_from_prob(self.__distribution.get())      
145
    
146
def percentile(values, percent):
147
    pos = int(len(values) * percent)
148
    return values[pos]
149