Skip to content

Instantly share code, notes, and snippets.

@el-hult
Created September 23, 2019 10:27
Show Gist options
  • Save el-hult/7b7332ee5abe56cf3d98960989661ea9 to your computer and use it in GitHub Desktop.
Save el-hult/7b7332ee5abe56cf3d98960989661ea9 to your computer and use it in GitHub Desktop.
A monkay-patching way to create random variables with overloaded plus operator. Not a pythonic way to do it, since monkey patching is generally frowned upon.
# standards
from itertools import islice
import types
# 3rd party
import numpy as np
class RandomVariable():
def __iter__(self):
return self
def __next__(self):
return self.draw_sample()
def draw_sample(self):
"""all instances MUST provide a 'draw_sample' method"""
raise NotImplementedError
def __add__(self, other):
def get_sum(self2):
a = self.__next__()
b = other.__next__()
return a + b
rv = RandomVariable()
rv.draw_sample = types.MethodType(get_sum, RandomVariable) # Check https://www.ianlewis.org/en/dynamically-adding-method-classes-or-class-instanc
return rv
def sample_descriptive_stats(self, n=100):
acc_sum = 0
acc_square = 0
for k in range(n):
sample = self.__next__()
acc_sum += sample
acc_square += sample**2
mean = acc_sum / n
variace = acc_square /n - mean**2
std_dev = np.sqrt(variace)
return {'mean':mean,'std_dev':std_dev,'n':n}
class Uniform(RandomVariable):
def __init__(self, a, b):
"""A random variable that is uniform on the interval [a,b)"""
super().__init__()
self.a = a
self.b = b
def __iter__(self):
return self
def draw_sample(self):
return np.random.random() * (self.b - self.a) + self.a
if __name__ == "__main__":
rv1 = Uniform(2, 3)
print(list(islice(rv1, 3)))
rv2 = Uniform(1, 2)
print(list(islice(rv2, 3)))
rv3 = rv1 + rv2
print(list(islice(rv3, 3)))
print(rv3.sample_descriptive_stats(1000000))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment