aboutsummaryrefslogtreecommitdiffstats
path: root/gen/rv.py
blob: e6f4d0fa5c34c8f7954c42ce074838b8143dee01 (plain) (blame)
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
from __future__ import division
import random

def uniform_int(minval, maxval):
    "Create a function that draws ints uniformly from {minval, ..., maxval}"
    def _draw():
        return random.randint(minval, maxval)
    return _draw

def uniform(minval, maxval):
    "Create a function that draws floats uniformly from [minval, maxval]"
    def _draw():
        return random.uniform(minval, maxval)
    return _draw

def bernoulli(p):
    "Create a function that flips a weight coin with probability p"
    def _draw():
        return random.random() < p
    return _draw

def uniform_choice(choices):
    "Create a function that draws uniformly elements from choices"
    selector = uniform_int(0, len(choices) - 1)
    def _draw():
        return choices[selector()]
    return _draw

def truncate(minval, maxval):
    def _limit(fun):
        def _f(*args, **kargs):
            val = fun(*args, **kargs)
            return min(maxval, max(minval, val))
        return _f
    return _limit

def redraw(minval, maxval):
    def _redraw(dist):
        def _f(*args, **kargs):
            in_range = False
            while not in_range:
                val = dist(*args, **kargs)
                in_range = minval <= val <= maxval
            return val
        return _f
    return _redraw

def exponential(minval, maxval, mean, limiter=redraw):
    """Create a function that draws floats from an exponential
    distribution with expected value 'mean'. If a drawn value is less
    than minval or greater than maxval, then either another value is
    drawn (if limiter=redraw) or the drawn value is set to minval or
    maxval (if limiter=truncate)."""
    def _draw():
        return random.expovariate(1.0 / mean)
    return limiter(minval, maxval)(_draw)

def multimodal(weighted_distributions):
    """Create a function that draws values from several distributions
    with probability according to the given weights in a list of
    (distribution, weight) pairs."""
    total_weight = sum([w for (d, w) in weighted_distributions])
    selector = uniform(0, total_weight)
    def _draw():
        x = selector()
        wsum = 0
        for (d, w) in weighted_distributions:
            wsum += w
            if wsum >= x:
                return d()
        assert False # should never drop off
    return _draw

def uniform_slack(min_slack_ratio, max_slack_ratio):
    """Choose deadlines uniformly such that the slack
       is within [cost + min_slack_ratio * (period - cost),
                  cost + max_slack_ratio * (period - cost)].
                  
        Setting max_slack_ratio = 1 implies constrained deadlines.
    """
    def choose_deadline(cost, period):
        slack = period - cost
        earliest = slack * min_slack_ratio
        latest   = slack * max_slack_ratio
        return cost + random.uniform(earliest, latest)
    return choose_deadline