@@ -1092,8 +1092,6 @@ def __init__(self):
1092
1092
self .prob = 0.25 # After turn 37, probability that we'll defect
1093
1093
1094
1094
self .move_history = np .zeros ([4 , 2 ])
1095
- # Will cache value only for testing purposes, not used otherwise
1096
- self .chi_squared = None
1097
1095
1098
1096
self .more_coop = 0 # This schedules cooperation for future turns
1099
1097
# Initial last_generous_n_turns_ago to 3 because this counts up and
@@ -1127,35 +1125,21 @@ def try_return(self, to_return, lower_flags=True, inc_parity=False):
1127
1125
1128
1126
return to_return
1129
1127
1130
- def detect_random (self , turn ):
1128
+ def calculate_chi_squared (self , turn ):
1131
1129
"""
1132
- Calculates a modified Pearson's Chi Squared statistic on self.history,
1133
- and returns True (is random) if and only if the statistic is less than
1134
- or equal to 3.
1135
-
1136
1130
Pearson's Chi Squared statistic = sum[ (E_i-O_i)^2 / E_i ], where O_i
1137
1131
are the observed matrix values, and E_i is calculated as number (of
1138
1132
defects) in the row times the number in the column over (total number
1139
- in the matrix minus 1).
1140
-
1141
- We say this is modified because it differs from a usual Chi-Squared
1142
- test in that:
1143
-
1144
- - Terms where expected counts are less than 1 get excluded.
1145
- - There's a check at the beginning on the first cell of the matrix.
1146
- - There's a check at the beginning for the recorded number of defects.
1133
+ in the matrix minus 1). Equivalently, we expect we expect (for an
1134
+ independent distribution) the total number of recorded turns times the
1135
+ portion in that row times the portion in that column.
1147
1136
1137
+ In this function, the statistic is non-standard in that it excludes
1138
+ summands where E_i <= 1.
1148
1139
"""
1140
+
1149
1141
denom = turn - 2
1150
1142
1151
- if self .move_history [0 , 0 ] / denom >= 0.8 :
1152
- return False
1153
- if self .recorded_defects / denom < 0.25 or self .recorded_defects / denom > 0.75 :
1154
- return False
1155
-
1156
- # In each cell, we expect (for an independent distribution) the total
1157
- # number of recorded turns times the portion in that row times the
1158
- # portion in that column
1159
1143
expected_matrix = np .outer (self .move_history .sum (axis = 1 ),
1160
1144
self .move_history .sum (axis = 0 )) / denom
1161
1145
@@ -1166,10 +1150,30 @@ def detect_random(self, turn):
1166
1150
if expect > 1.0 :
1167
1151
chi_squared += (expect - self .move_history [i , j ]) ** 2 / expect
1168
1152
1169
- # Caching value only for testing purposes, not used otherwise
1170
- self .chi_squared = round (chi_squared , 3 )
1153
+ return chi_squared
1154
+
1155
+ def detect_random (self , turn ):
1156
+ """
1157
+ We check if the top-left cell of the matrix (corresponding to all
1158
+ Cooperations) has over 80% of the turns. In which case, we label
1159
+ non-random.
1160
+
1161
+ Then we check if over 75% or under 25% of the opponent's turns are
1162
+ Defections. If so, then we label as non-random.
1163
+
1164
+ Otherwise we calculates a modified Pearson's Chi Squared statistic on
1165
+ self.history, and returns True (is random) if and only if the statistic
1166
+ is less than or equal to 3.
1167
+ """
1168
+
1169
+ denom = turn - 2
1170
+
1171
+ if self .move_history [0 , 0 ] / denom >= 0.8 :
1172
+ return False
1173
+ if self .recorded_defects / denom < 0.25 or self .recorded_defects / denom > 0.75 :
1174
+ return False
1171
1175
1172
- if chi_squared > 3 :
1176
+ if self . calculate_chi_squared ( turn ) > 3 :
1173
1177
return False
1174
1178
return True
1175
1179
0 commit comments