-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmemory_inference.py
122 lines (100 loc) · 3.87 KB
/
memory_inference.py
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
"""
Inferring memory depth of Iterated Prisoner's Dilemma strategies
using scipy and the Axelrod library.
"""
from itertools import islice
import numpy
from scipy import stats
import axelrod
C, D = axelrod.Actions.C, axelrod.Actions.D # The plays
def fet_tests(data_dict):
"""Performs four Fisher exact tests on each possible context."""
# What has the opponent been doing?
C_count = sum(v[0] for (k, v) in data_dict.items())
D_count = sum(v[1] for (k, v) in data_dict.items())
test_results = dict()
# Pull out the C and D counts for each context
for context in data_dict.keys():
C_count_context = data_dict[context][0]
D_count_context = data_dict[context][1]
# Build the conditional table
table = numpy.array([[C_count, D_count], [C_count_context, D_count_context]])
# Run the Fisher test
test_stat, pvalue = stats.fisher_exact(table)
test_results[context] = (test_stat, pvalue)
return test_results
def memory_one_estimate(data_dict):
"""Estimates the memory one strategy probabilities from the observed
data."""
estimates = dict()
for context in data_dict.keys():
C_count = data_dict[context][0]
D_count = data_dict[context][1]
try:
estimates[context] = float(C_count) / (C_count + D_count)
except ZeroDivisionError:
estimates[context] = None
return estimates
def print_dict(d):
for key, value in sorted(d.items()):
print key, value
def collect_data(opponent):
"""Generator to collect data from opponent."""
player = axelrod.Random(0.5) # The probe strategy
while True:
player.play(opponent)
yield (player.history[-1], opponent.history[-1])
def infer_depth(opponent, test_rounds=200):
"""Collect data and report statistical tests."""
data_dict = {(C, C): [0, 0],
(C, D): [0, 0],
(D, C): [0, 0],
(D, D): [0, 0]}
# Save the history locally as we go
history = []
for turn in islice(collect_data(opponent), test_rounds + 1):
history.append(turn)
if len(history) < 2:
continue
# Record opponents play and context
context = history[-2]
# Context is reversed for opponent
context = (context[1], context[0])
# Count the opponent's Cs and Ds
if turn[1] == C:
data_dict[context][0] += 1
else:
data_dict[context][1] += 1
# Perform the Fisher tests
test_results = fet_tests(data_dict)
# Estimate the four conditional probabilities
estimate = memory_one_estimate(data_dict)
return data_dict, test_results, estimate
def main():
strategies = [axelrod.Cooperator(), axelrod.Defector(),
axelrod.Random(0.4), axelrod.Random(0.5), axelrod.Random(0.9),
axelrod.Alternator(),
axelrod.TitForTat(), axelrod.GTFT(),
axelrod.WinStayLoseShift(), axelrod.ZDGTFT2(),
axelrod.ZDExtort2(),
axelrod.TitFor2Tats(), axelrod.TwoTitsForTat(),
axelrod.CyclerCCD(), axelrod.CyclerCCCD(),
axelrod.CyclerCCCCCD(), axelrod.HardTitForTat(),
axelrod.AntiCycler(),
axelrod.Grudger()]
for opponent in strategies:
data_dict, test_results, estimate = infer_depth(opponent)
print opponent
print "-"*len(str(opponent))
print "Collected Data"
print_dict(data_dict)
C_count = sum(v[0] for (k, v) in data_dict.items())
D_count = sum(v[1] for (k, v) in data_dict.items())
print "C count, D count: %s, %s" % (C_count, D_count)
print "\nFisher Exact Tests"
print_dict(test_results)
print "\nEstimated Memory One Probabilities"
print_dict(estimate)
print
if __name__ == "__main__":
main()