Skip to content

Instantly share code, notes, and snippets.

@drocamor
Created February 25, 2013 03:59
Show Gist options
  • Save drocamor/5027626 to your computer and use it in GitHub Desktop.
Save drocamor/5027626 to your computer and use it in GitHub Desktop.
Thinking about the prisoners dilemma with iPython. This is an iPython notebook. I made it python to share it with people.
# -*- coding: utf-8 -*-
# <nbformat>3.0</nbformat>
# <headingcell level=1>
# The Game World
# <codecell>
def pd(previous_games, p1_fun, p2_fun):
"""Run one iteration of the prisoners dilemna"""
p1_result = p1_fun(previous_games, player_identity='p1')
p2_result = p2_fun(previous_games, player_identity='p2')
previous_games.append({'p1': p1_result, 'p2': p2_result})
return previous_games
# <codecell>
def ipd(p1_fun, p2_fun, iterations = 100):
games = []
for i in range(iterations):
result = pd(games, p1_fun, p2_fun)
games = result
scores = score(games)
# Make the players names readable
scores['game'] = p1_fun.func_name + " vs " + p2_fun.func_name
return scores
# <codecell>
def score_a_game(game):
p1 = game['p1']
p2 = game['p2']
if p1 is True and p2 is True:
return {'p1': 3, 'p2': 3}
if p1 is True and p2 is False:
return {'p1': 0, 'p2': 5}
if p1 is False and p2 is False:
return {'p1': 1, 'p2': 1}
if p1 is False and p2 is True:
return {'p1': 5, 'p2': 0}
# <codecell>
def score(games):
# Convert game outcomes into scores
scores = [ score_a_game(x) for x in games ]
p1_score = 0
p2_score = 0
for score in scores:
p1_score += score['p1']
p2_score += score['p2']
return {'p1': p1_score,
'p2': p2_score}
# <headingcell level=1>
# Helper functions, imports, etc
# <codecell>
from random import choice
import itertools
import operator
def most_common(L):
# get an iterable of (item, iterable) pairs
SL = sorted((x, i) for i, x in enumerate(L))
# print 'SL:', SL
groups = itertools.groupby(SL, key=operator.itemgetter(0))
# auxiliary function to get "quality" for an item
def _auxfun(g):
item, iterable = g
count = 0
min_index = len(L)
for _, where in iterable:
count += 1
min_index = min(min_index, where)
# print 'item %r, count %r, minind %r' % (item, count, min_index)
return count, -min_index
# pick the highest-count/earliest item
return max(groups, key=_auxfun)[0]
# <headingcell level=1>
# The Players
# <codecell>
def tit_for_tat(previous_games, player_identity):
"""Just do whatever the opponent did to you last time. Cooperate the first time."""
opponent = 'p1' if player_identity == 'p2' else 'p2'
if len(previous_games) == 0:
return True
else:
return previous_games[-1][opponent]
# <codecell>
def tat_for_tit(previous_games, player_identity):
"""Do the opposite of whatever the opponent did last time. Cooperate the first time."""
opponent = 'p1' if player_identity == 'p2' else 'p2'
if len(previous_games) == 0:
return True
if previous_games[-1][opponent]:
return False
else:
return True
# <codecell>
def be_an_ass(previous_games, player_identity):
"""Dumb and mean."""
return False
# <codecell>
def be_naive(previous_games, player_identity):
"""Cooperative, and pretty stupid."""
return True
# <codecell>
def be_crazy(previous_games, player_identity):
"""I AM SO RANDOM"""
return choice([True, False])
# <codecell>
def have_a_long_memory(previous_games, player_identity):
"""Evaluate all of the games played, and do what the opponent usually does. Cooperate the first time."""
opponent = 'p1' if player_identity == 'p2' else 'p2'
if len(previous_games) == 0:
return True
else:
opponents_moves = [ x[opponent] for x in previous_games ]
return most_common(opponents_moves)
# <headingcell level=1>
# Let the games begin!
# <codecell>
# Get the players in a list
players = [tit_for_tat, tat_for_tit, be_an_ass, be_naive, be_crazy, have_a_long_memory]
matches = itertools.combinations_with_replacement(players, 2)
results = [ ipd(match[0], match[1]) for match in matches ]
# <codecell>
for result in results:
print "%s: %s to %s" % (result['game'], result['p1'], result['p2'])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment