Skip to content

Commit d9b6147

Browse files
Merge pull request #717 from theref/issue-138
Issue 138 - Adds functions to calculate the state distribution of a Match
2 parents e7491d7 + 49f7fb7 commit d9b6147

File tree

3 files changed

+81
-0
lines changed

3 files changed

+81
-0
lines changed

axelrod/interaction_utils.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
interactions.
1010
"""
1111
import csv
12+
from collections import Counter
1213

1314
from .game import Game
1415
from axelrod import Actions
@@ -87,6 +88,57 @@ def compute_normalised_cooperation(interactions):
8788
return normalised_cooperation
8889

8990

91+
def compute_state_distribution(interactions):
92+
"""
93+
Returns the count of each state for a set of interactions.
94+
95+
Parameters
96+
----------
97+
interactions : list of tuples
98+
A list containing the interactions of the match as shown at the top of
99+
this file.
100+
101+
Returns
102+
----------
103+
Counter(interactions) : Counter Object
104+
Dictionary where the keys are the states and the values are the number
105+
of times that state occurs.
106+
"""
107+
if not interactions:
108+
return None
109+
return Counter(interactions)
110+
111+
112+
def compute_normalised_state_distribution(interactions):
113+
"""
114+
Returns the normalized count of each state for a set of interactions.
115+
116+
Parameters
117+
----------
118+
interactions : list of tuples
119+
A list containing the interactions of the match as shown at the top of
120+
this file.
121+
122+
Returns
123+
----------
124+
normalized_count : Counter Object
125+
Dictionary where the keys are the states and the values are a normalized
126+
count of the number of times that state occurs.
127+
"""
128+
if not interactions:
129+
return None
130+
131+
interactions_count = Counter(interactions)
132+
total = sum(interactions_count.values(), 0.0)
133+
# By starting the sum with 0.0 we make sure total is a floating point value,
134+
# avoiding the Python 2 floor division behaviour of / with integer operands
135+
# (Stack Overflow)
136+
137+
normalized_count = Counter({key: value / total for key, value in
138+
interactions_count.items()})
139+
return normalized_count
140+
141+
90142
def sparkline(actions, c_symbol=u'█', d_symbol=u' '):
91143
return u''.join([
92144
c_symbol if play == 'C' else d_symbol for play in actions])

axelrod/match.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,18 @@ def normalised_cooperation(self):
159159
"""Returns the count of cooperations by each player per turn"""
160160
return iu.compute_normalised_cooperation(self.result)
161161

162+
def state_distribution(self):
163+
"""
164+
Returns the count of each state for a set of interactions.
165+
"""
166+
return iu.compute_state_distribution(self.result)
167+
168+
def normalised_state_distribution(self):
169+
"""
170+
Returns the normalized count of each state for a set of interactions.
171+
"""
172+
return iu.compute_normalised_state_distribution(self.result)
173+
162174
def sparklines(self, c_symbol=u'█', d_symbol=u' '):
163175
return iu.compute_sparklines(self.result, c_symbol, d_symbol)
164176

axelrod/tests/unit/test_interaction_utils.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# -*- coding: utf-8 -*-
22
import unittest
33
import tempfile
4+
from collections import Counter
45
import axelrod
56
import axelrod.interaction_utils as iu
67

@@ -17,6 +18,14 @@ class TestMatch(unittest.TestCase):
1718
winners = [False, 0, 1, None]
1819
cooperations = [(1, 1), (0, 2), (2, 1), None]
1920
normalised_cooperations = [(.5, .5), (0, 1), (1, .5), None]
21+
state_distribution = [Counter({('C', 'D'): 1, ('D', 'C'): 1}),
22+
Counter({('D', 'C'): 2}),
23+
Counter({('C', 'C'): 1, ('C', 'D'): 1}),
24+
None]
25+
normalised_state_distribution = [Counter({('C', 'D'): 0.5, ('D', 'C'): 0.5}),
26+
Counter({('D', 'C'): 1.0}),
27+
Counter({('C', 'C'): 0.5, ('C', 'D'): 0.5}),
28+
None]
2029
sparklines = [ u'█ \n █', u' \n██', u'██\n█ ', None ]
2130

2231

@@ -46,6 +55,14 @@ def test_compute_normalised_cooperations(self):
4655
for inter, coop in zip(self.interactions, self.normalised_cooperations):
4756
self.assertEqual(coop, iu.compute_normalised_cooperation(inter))
4857

58+
def test_compute_state_distribution(self):
59+
for inter, dist in zip(self.interactions, self.state_distribution):
60+
self.assertEqual(dist, iu.compute_state_distribution(inter))
61+
62+
def test_compute_normalised_state_distribution(self):
63+
for inter, dist in zip(self.interactions, self.normalised_state_distribution):
64+
self.assertEqual(dist, iu.compute_normalised_state_distribution(inter))
65+
4966
def test_compute_sparklines(self):
5067
for inter, spark in zip(self.interactions, self.sparklines):
5168
self.assertEqual(spark, iu.compute_sparklines(inter))

0 commit comments

Comments
 (0)