Skip to content

Instantly share code, notes, and snippets.

@ctufts
Last active February 24, 2017 14:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ctufts/abb05e2b804fc1dbdb16932663b30363 to your computer and use it in GitHub Desktop.
Save ctufts/abb05e2b804fc1dbdb16932663b30363 to your computer and use it in GitHub Desktop.
Traveling Politician (Metropolis Hastings) - the Clay Davis Edition
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