Last active
February 24, 2017 14:19
-
-
Save ctufts/abb05e2b804fc1dbdb16932663b30363 to your computer and use it in GitHub Desktop.
Traveling Politician (Metropolis Hastings) - the Clay Davis Edition
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from sys import exit | |
from scipy import stats | |
import math | |
import random | |
class Engine(object): | |
def direction(self): | |
if stats.bernoulli.rvs(0.5, size = 1)[0]: | |
direction = 'east' | |
else: | |
direction = 'west' | |
return direction | |
def next_hop(self, current_point, island_range, populations): | |
# continue using the island ranges to determine 'ends' | |
# of distributions | |
# just make sure to plug in the populations for the | |
# proposals... (still need to update east/west) | |
next_direction = self.direction() | |
# scenarios | |
# west & as far west as possible - stay | |
# east & as far east as possible - stay | |
# else | |
# if east: proposed is the pop east | |
# else west: proposed is the pop west | |
if next_direction == 'west' and (current_point == island_range[1]): | |
current_point = current_point | |
elif next_direction == 'east' and (current_point == island_range[0]): | |
current_point = current_point | |
else: | |
if next_direction == 'east': | |
p_proposed = populations[current_point - 1] | |
else: | |
p_proposed = populations[current_point + 1] | |
p_move = p_proposed/populations[current_point] | |
spinner = stats.uniform.rvs(size = 1) | |
if (spinner < p_move) and next_direction == 'east' : | |
current_point -= 1 | |
elif (spinner < p_move) and next_direction == 'west': | |
current_point += 1 | |
else: | |
current_point = current_point | |
return current_point | |
class Politician(object): | |
stay_quotes = [ | |
"Better lay low, Lt. Daniels is out there. We can wait it out here: ", | |
"""Because if some federal mothafucker comes walkin' through the door, | |
I say hey, it's all in the game! | |
But a city police, Baltimore City, Hell Naaaw, can't be happenin' | |
because I know I done raised too much goddamn money for the Mayor | |
and his ticket! Hell Naaaw, aint no soul in the world that fuckin' ungrateful! """, | |
"""I know you don't wanna know, but Im scratchin' and clawin' to get it | |
done for you Clarence, for you and me and the rest of the team and | |
who comes through my door but a Baltimore City police lookin' to get | |
up in my shit about everything!""", | |
"""You wanna run a campaign with my money pillowed under your ass, you | |
need yo people to back the fuck up Clarence!""", | |
"""Major crimes? Sheeeeeeeeeeyet. """ | |
] | |
move_quotes = [ | |
"Sheeeeeeeeeeeeeeit, warm up the car Day-Day. We need to collect our money from : ", | |
"""Mm-mmm. Twenty gets you the permits. | |
Five is for me for bribing these downtown motherfuckers. | |
I mean, I'm the one got to risk walking up to these thieving | |
bitches with cash in hand, right?""", | |
"""Money Launderin' they gonna come talk to me about Money Launderin' | |
in West Baltimore, SHIIIIT, Where do you think I'm gonna raise cash | |
for the whole damn ticket! From Laundromats and shit, from some tiny ass | |
korean groceries, you think I got time to ask a man why he given me | |
money or where he gets his money from, I'll take any mothafucker's money | |
if he given it away! """, | |
"""We spend this year dealing with the city, the next doing business with | |
the state. However, year three, then we go for the gold. Then we go | |
federal. Then we see the man with his hand on the faucet.""" | |
] | |
def __init__(self, starting_point, island_range): | |
self.previous_point = starting_point | |
self.current_point = starting_point | |
self.island_range = island_range | |
def speak(self): | |
if(self.previous_point != self.current_point): | |
return(Politician.move_quotes[ | |
random.randint(1,len(Politician.move_quotes)-1)] + | |
'\n\n' + Politician.move_quotes[0]) | |
else: | |
return(Politician.stay_quotes[ | |
random.randint(1,len(Politician.stay_quotes)-1)] + | |
'\n\n' + Politician.stay_quotes[0]) | |
class Map(object): | |
bmore_names = [ | |
"The Pit", | |
"The Tower", | |
"City Hall", | |
"Little Johnnies", | |
"Marlo's Court" | |
] | |
n_islands = len(bmore_names) | |
start_point = 3 | |
def __init__(self): | |
self.engine = Engine() | |
self.chain = {} | |
self.bmore_populations = Map.shuffle_baltimore(Map.bmore_names) | |
# self.island_chain = range(1,n_islands) | |
self.clay = Politician(Map.start_point, [0,Map.n_islands-1]) | |
for i in range(0,Map.n_islands): | |
self.chain[i] = 0 | |
if i == Map.start_point: | |
self.chain[i] += 1 | |
def shuffle_baltimore(locations): | |
# change bmore to a class instance variable so | |
# it can be altered/shuffled | |
return random.sample(range(1,len(locations)+1), len(locations)) | |
def print_histogram(self, iteration_number): | |
""" | |
prints a scaled histogram of the distributions generated | |
""" | |
print("Iteration %d complete. Here is the relative distribution of visits:" % iteration_number) | |
for key in self.chain: | |
print( "*" * math.floor(100*self.chain[key]/iteration_number),":", self.bmore_names[key]), | |
print('\n\n') | |
def print_relative_populations(self): | |
print("True Relative Money Counts:\n") | |
for p in range(0,len(self.bmore_populations)): | |
print("Money Count: %r ;location: %r" % | |
(self.bmore_populations[p], self.bmore_names[p])) | |
print('\n\n') | |
def opening_statement(self): | |
print(" Welcome to Baltimore. Senator Clay Davis\n", | |
"needs to pick up money from his 'constituents'. With\n", | |
"the help of his trusty driver, Damien 'Day-Day' Price,\n", | |
"he needs to go around and pick up his money, going\n", | |
"to the places with more money more frequently. To\n", | |
"accomplish this task he is going to use the Metropolis\n", | |
"Hastings algorithm.\nTime to get started....\n\n") | |
self.print_relative_populations() | |
("Current Location: " + self.bmore_names[self.clay.current_point] + "\n\n") | |
def simulate(self, sim_iterations=500,verbose = 'y'): | |
self.opening_statement() | |
prompt = '> ' | |
# make it verbose or not ... | |
for i in range(1, sim_iterations): | |
self.clay.previous_point = self.clay.current_point | |
self.clay.current_point = self.engine.next_hop(self.clay.current_point, | |
self.clay.island_range, | |
self.bmore_populations) | |
self.chain[self.clay.current_point] += 1 | |
if(verbose == 'y'): | |
print("Would you like to continue stepping through simulation?\n", | |
"(y - continue, any other key - show results of simulation after %d steps)" % | |
sim_iterations) | |
verbose = input(prompt) | |
if(verbose == 'y'): | |
print("Clay: " + self.clay.speak() + | |
self.bmore_names[self.clay.current_point] + '\n\n') | |
if i % 100 == 0: | |
self.print_histogram(i) | |
self.print_relative_populations() | |
m = Map() | |
m.simulate(sim_iterations=5000, verbose = 'y') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment