@@ -358,6 +358,33 @@ def _build_normalised_state_distribution(self):
358358 norm .append (counters )
359359 return norm
360360
361+ @update_progress_bar
362+ def _build_normalised_state_to_action_distribution (self ):
363+ """
364+ Returns
365+ ----------
366+
367+ Normalised state distribution. A list of lists of counter objects:
368+
369+ Dictionary where the keys are the states and the values are a
370+ normalized counts of the number of times that state goes to a given
371+ action.
372+ """
373+ norm = []
374+ for player in self .state_to_action_distribution :
375+ counters = []
376+ for counter in player :
377+ norm_counter = Counter ()
378+ for state in [(C , C ), (C , D ), (D , C ), (D , D )]:
379+ total = counter [(state , C )] + counter [(state , D )]
380+ if total > 0 :
381+ for action in [C , D ]:
382+ if counter [(state , action )] > 0 :
383+ norm_counter [(state , action )] = counter [(state , action )] / total
384+ counters .append (norm_counter )
385+ norm .append (counters )
386+ return norm
387+
361388 def _build_empty_metrics (self , keep_interactions = False ):
362389 """
363390 Creates the various empty metrics ready to be updated as the data is
@@ -385,6 +412,8 @@ def _build_empty_metrics(self, keep_interactions=False):
385412 self .initial_cooperation_count = [0 for player in plist ]
386413 self .state_distribution = [[Counter () for opponent in plist ]
387414 for player in plist ]
415+ self .state_to_action_distribution = [[Counter () for opponent in plist ]
416+ for player in plist ]
388417 self .good_partner_matrix = [[0 for opponent in plist ]
389418 for player in plist ]
390419
@@ -567,6 +596,26 @@ def _update_state_distribution(self, p1, p2, counter):
567596 counter [(C , D )], counter [(D , C )] = counter [(D , C )], counter [(C , D )]
568597 self .state_distribution [p2 ][p1 ] += counter
569598
599+ def _update_state_to_action_distribution (self , p1 , p2 , counter_list ):
600+ """
601+ During a read of the data, update the state_distribution attribute
602+
603+ Parameters
604+ ----------
605+
606+ p1, p2 : int
607+ The indices of the first and second player
608+ counter_list : list of collections.Counter
609+ A list of counter objects for the states to action of a match
610+ """
611+ counter = counter_list [0 ]
612+ self .state_to_action_distribution [p1 ][p2 ] += counter
613+
614+ counter = counter_list [1 ]
615+ for act in [C , D ]:
616+ counter [((C , D ), act )], counter [((D , C ), act )] = counter [((D , C ), act )], counter [((C , D ), act )]
617+ self .state_to_action_distribution [p2 ][p1 ] += counter
618+
570619 def _update_good_partner_matrix (self , p1 , p2 , cooperations ):
571620 """
572621 During a read of the data, update the good partner matrix attribute
@@ -671,6 +720,7 @@ def _build_score_related_metrics(self, progress_bar=False,
671720 self ._update_normalised_cooperation (p1 , p2 , interaction )
672721
673722 if p1 != p2 : # Anything that ignores self interactions
723+ state_to_actions = iu .compute_state_to_action_distribution (interaction )
674724
675725 for player in [p1 , p2 ]:
676726 self .total_interactions [player ] += 1
@@ -685,16 +735,19 @@ def _build_score_related_metrics(self, progress_bar=False,
685735 self ._update_initial_cooperation_count (p1 , p2 ,
686736 initial_coops )
687737 self ._update_state_distribution (p1 , p2 , state_counter )
738+ self ._update_state_to_action_distribution (p1 , p2 ,
739+ state_to_actions )
688740 self ._update_good_partner_matrix (p1 , p2 , cooperations )
689741
690742 if progress_bar :
691- self .progress_bar = tqdm .tqdm (total = 12 + 2 * self .nplayers ,
743+ self .progress_bar = tqdm .tqdm (total = 13 + 2 * self .nplayers ,
692744 desc = "Finishing" )
693745 self ._summarise_normalised_scores ()
694746 self ._summarise_normalised_cooperation ()
695747
696748 self .ranking = self ._build_ranking ()
697749 self .normalised_state_distribution = self ._build_normalised_state_distribution ()
750+ self .normalised_state_to_action_distribution = self ._build_normalised_state_to_action_distribution ()
698751 self .ranked_names = self ._build_ranked_names ()
699752 self .payoff_matrix = self ._build_payoff_matrix ()
700753 self .payoff_stddevs = self ._build_payoff_stddevs ()
@@ -772,7 +825,9 @@ def summarise(self):
772825 self .player = namedtuple ("Player" , ["Rank" , "Name" , "Median_score" ,
773826 "Cooperation_rating" , "Wins" ,
774827 "Initial_C_rate" , "CC_rate" ,
775- "CD_rate" , "DC_rate" , "DD_rate" ])
828+ "CD_rate" , "DC_rate" , "DD_rate" ,
829+ "CC_to_C_rate" , "CD_to_C_rate" ,
830+ "DC_to_C_rate" , "DD_to_C_rate" ])
776831
777832 states = [(C , C ), (C , D ), (D , C ), (D , D )]
778833 state_prob = []
@@ -787,13 +842,28 @@ def summarise(self):
787842 counts = [0 for c in counts ]
788843 state_prob .append (counts )
789844
845+ state_to_C_prob = []
846+ for player in self .normalised_state_to_action_distribution :
847+ rates = []
848+ for state in states :
849+ counts = [counter [(state , 'C' )] for counter in player
850+ if counter [(state , 'C' )] > 0 ]
851+
852+ if len (counts ) > 0 :
853+ rate = mean (counts )
854+ else :
855+ rate = 0
856+
857+ rates .append (rate )
858+ state_to_C_prob .append (rates )
859+
790860 summary_measures = list (zip (self .players , median_scores ,
791861 self .cooperating_rating , median_wins ,
792862 self .initial_cooperation_rate ))
793863
794864 summary_data = []
795865 for rank , i in enumerate (self .ranking ):
796- data = list (summary_measures [i ]) + state_prob [i ]
866+ data = list (summary_measures [i ]) + state_prob [i ] + state_to_C_prob [ i ]
797867 summary_data .append (self .player (rank , * data ))
798868
799869 return summary_data
@@ -802,7 +872,8 @@ def write_summary(self, filename):
802872 """
803873 Write a csv file containing summary data of the results of the form:
804874
805- "Rank", "Name", "Median-score-per-turn", "Cooperation-rating", "Initial_C_Rate", "Wins", "CC-Rate", "CD-Rate", "DC-Rate", "DD-rate"
875+ "Rank", "Name", "Median-score-per-turn", "Cooperation-rating", "Initial_C_Rate", "Wins", "CC-Rate", "CD-Rate", "DC-Rate", "DD-rate","CC-to-C-Rate", "CD-to-C-Rate", "DC-to-C-Rate", "DD-to-C-rate"
876+
806877
807878 Parameters
808879 ----------
0 commit comments