@@ -22,80 +22,51 @@ def median(lst):
2222class ResultSet (object ):
2323 """A class to hold the results of a tournament."""
2424
25- unfinalised_error_msg = 'payoffs_list has not been set.'
26-
27- def __init__ (self , players , turns , repetitions ):
25+ def __init__ (self , players , turns , repetitions , outcome ):
2826 self .players = players
2927 self .nplayers = len (players )
3028 self .turns = turns
3129 self .repetitions = repetitions
32- self ._init_results ()
33- self ._finalised = False
34-
35- # payoffs_list is the only property with a setter method.
36- #
37- # Setting payoffs_list calls methods to set all the other
38- # properties on the instance (result, scores, ranking, ranked_names,
39- # payoff_matrix, payoff_stddevs).
40- #
41- # The getter methods on those other properties will return an error
42- # if payoffs_list has not been set.
43-
44- @property
45- def payoffs_list (self ):
46- return self ._payoffs_list
47-
48- @payoffs_list .setter
49- def payoffs_list (self , payoffs_list ):
50- self ._payoffs_list = payoffs_list
51- self ._update_results ()
52- self ._finalised = True
53- self ._scores = self ._generate_scores ()
54- self ._normalised_scores = self ._generate_normalised_scores ()
55- self ._ranking = self ._generate_ranking (self .scores )
56- self ._ranked_names = self ._generate_ranked_names (self .ranking )
57- self ._payoff_matrix , self ._payoff_stddevs = self ._generate_payoff_matrix ()
58-
59- @payoffs_list .deleter
60- def payoffs_list (self ):
61- del (self ._payoffs_list )
62- self ._init_results ()
63- self ._finalised = False
64-
65- @property
66- def results (self ):
67- if self ._finalised :
68- return self ._results
69- else :
70- raise AttributeError (self .unfinalised_error_msg )
71-
72- def _init_results (self ):
30+ self .outcome = outcome
31+ self .results = self ._results (outcome )
32+ if 'payoff' in self .results :
33+ self .scores = self ._scores (self .results ['payoff' ])
34+ self .normalised_scores = self ._normalised_scores (self .scores )
35+ self .ranking = self ._ranking (self .scores )
36+ self .ranked_names = self ._ranked_names (self .ranking )
37+ self .payoff_matrix , self .payoff_stddevs = (
38+ self ._payoff_matrix (self .results ['payoff' ]))
39+ if 'cooperation' in self .results :
40+ self .cooperation = self ._cooperation (self .results ['cooperation' ])
41+ self .normalised_cooperation = (
42+ self ._normalised_cooperation (self .cooperation ))
43+
44+ def _null_matrix (self ):
7345 plist = list (range (self .nplayers ))
7446 replist = list (range (self .repetitions ))
75- self ._results = [[[0 for r in replist ] for j in plist ] for i in plist ]
76-
77- def _update_results (self ):
78- for index , payoffs in enumerate (self .payoffs_list ):
79- for i in range (len (self .players )):
80- for j in range (len (self .players )):
81- self ._results [i ][j ][index ] = payoffs [i ][j ]
82-
83- @property
84- def scores (self ):
85- if self ._finalised :
86- return self ._scores
87- else :
88- raise AttributeError (self .unfinalised_error_msg )
89-
90- def _generate_scores (self ):
91- """Return normalized scores based on the results.
92-
93- Originally there were no self-interactions, so the code here was rewritten
94- to exclude those from the generated score. To include self-interactions,
95- remove the condition on ip and ires and fix the normalization factor.
47+ return [[[0 for r in replist ] for j in plist ] for i in plist ]
48+
49+ def _results (self , outcome ):
50+ results = {}
51+ for result_type , result_list in outcome .items ():
52+ matrix = self ._null_matrix ()
53+ for index , result_matrix in enumerate (result_list ):
54+ for i in range (len (self .players )):
55+ for j in range (len (self .players )):
56+ matrix [i ][j ][index ] = result_matrix [i ][j ]
57+ results [result_type ] = matrix
58+ return results
59+
60+ def _scores (self , payoff ):
61+ """Return scores based on the results.
62+
63+ Originally there were no self-interactions, so the code here was
64+ rewritten to exclude those from the generated score. To include
65+ self-interactions, remove the condition on ip and ires and fix the
66+ normalization factor.
9667 """
9768 scores = []
98- for ires , res in enumerate (self . results ):
69+ for ires , res in enumerate (payoff ):
9970 scores .append ([])
10071 for irep in range (self .repetitions ):
10172 scores [- 1 ].append (0 )
@@ -104,26 +75,12 @@ def _generate_scores(self):
10475 scores [- 1 ][- 1 ] += res [ip ][irep ]
10576 return scores
10677
107- @property
108- def normalised_scores (self ):
109- if self ._finalised :
110- return self ._normalised_scores
111- else :
112- raise AttributeError (self .unfinalised_error_msg )
113-
114- def _generate_normalised_scores (self ):
78+ def _normalised_scores (self , scores ):
11579 normalisation = self .turns * (self .nplayers - 1 )
11680 return [
117- [1.0 * s / normalisation for s in r ] for r in self . scores ]
81+ [1.0 * s / normalisation for s in r ] for r in scores ]
11882
119- @property
120- def ranking (self ):
121- if self ._finalised :
122- return self ._ranking
123- else :
124- raise AttributeError (self .unfinalised_error_msg )
125-
126- def _generate_ranking (self , scores ):
83+ def _ranking (self , scores ):
12784 """
12885 Returns a list of players (their index within the
12986 players list rather than a player instance)
@@ -134,37 +91,16 @@ def _generate_ranking(self, scores):
13491 key = lambda i : - median (scores [i ]))
13592 return ranking
13693
137- @property
138- def ranked_names (self ):
139- if self ._finalised :
140- return self ._ranked_names
141- else :
142- raise AttributeError (self .unfinalised_error_msg )
143-
144- def _generate_ranked_names (self , ranking ):
94+ def _ranked_names (self , ranking ):
14595 """Returns a list of players names sorted by their ranked order."""
14696 ranked_names = [str (self .players [i ]) for i in ranking ]
14797 return ranked_names
14898
149- @property
150- def payoff_matrix (self ):
151- if self ._finalised :
152- return self ._payoff_matrix
153- else :
154- raise AttributeError (self .unfinalised_error_msg )
155-
156- @property
157- def payoff_stddevs (self ):
158- if self ._finalised :
159- return self ._payoff_stddevs
160- else :
161- raise AttributeError (self .unfinalised_error_msg )
162-
163- def _generate_payoff_matrix (self ):
99+ def _payoff_matrix (self , payoff ):
164100 """Returns a per-turn averaged payoff matrix and its stddevs."""
165101 averages = []
166102 stddevs = []
167- for res in self . results :
103+ for res in payoff :
168104 averages .append ([])
169105 stddevs .append ([])
170106 for s in res :
@@ -176,15 +112,22 @@ def _generate_payoff_matrix(self):
176112 stddevs [- 1 ].append (dev )
177113 return averages , stddevs
178114
115+ def _cooperation (self , results ):
116+ return [[sum (element ) for element in row ] for row in results ]
117+
118+ def _normalised_cooperation (self , cooperation ):
119+ normalisation = self .turns * self .repetitions
120+ return [
121+ [1.0 * element / normalisation for element in row ]
122+ for row in cooperation ]
123+
179124 def csv (self ):
180- if self ._finalised :
181- csv_string = StringIO ()
182- header = "," .join (self .ranked_names ) + "\n "
183- csv_string .write (header )
184- writer = csv .writer (csv_string , lineterminator = "\n " )
185- for irep in range (self .repetitions ):
186- data = [self .normalised_scores [rank ][irep ] for rank in self .ranking ]
187- writer .writerow (list (map (str , data )))
188- return csv_string .getvalue ()
189- else :
190- raise AttributeError (self .unfinalised_error_msg )
125+ csv_string = StringIO ()
126+ header = "," .join (self .ranked_names ) + "\n "
127+ csv_string .write (header )
128+ writer = csv .writer (csv_string , lineterminator = "\n " )
129+ for irep in range (self .repetitions ):
130+ data = [self .normalised_scores [rank ][irep ]
131+ for rank in self .ranking ]
132+ writer .writerow (list (map (str , data )))
133+ return csv_string .getvalue ()
0 commit comments