@@ -461,10 +461,17 @@ def full_gradient_selection(self, population_state: np.ndarray, beta: float) ->
461461 probability_selecting_strategy_first = population_state / self .pop_size
462462 probability_selecting_strategy_second = population_state / self .pop_size
463463 probabilities = np .outer (probability_selecting_strategy_first , probability_selecting_strategy_second )
464- fitness = np .asarray ([[self .full_fitness (i , j , population_state ) for i in
465- range (len (population_state ))] for j in range (len (population_state ))])
466- fitness [np .isnan (fitness )] = 0
467- return (probabilities * np .tanh ((beta / 2 ) * fitness )).sum (axis = 0 ) * (1 - self .mu ) + self .mu
464+ fitness = np .zeros (shape = (self .nb_strategies , self .nb_strategies ))
465+ for j in range (self .nb_strategies ):
466+ if population_state [j ] == 0 :
467+ continue
468+ for i in range (self .nb_strategies ):
469+ if population_state [i ] == 0 :
470+ continue
471+ fitness [j , i ] = self .full_fitness (i , j , population_state )
472+
473+ return (probabilities * np .tanh ((beta / 2 ) * fitness )).sum (axis = 0 ) * (1 - self .mu ) + (
474+ self .mu / (self .nb_strategies - 1 )) * probability_selecting_strategy_second
468475
469476 def full_gradient_selection_without_mutation (self , population_state : np .ndarray , beta : float ) -> np .ndarray :
470477 """
@@ -488,9 +495,14 @@ def full_gradient_selection_without_mutation(self, population_state: np.ndarray,
488495 probability_selecting_strategy_first = population_state / self .pop_size
489496 probability_selecting_strategy_second = population_state / self .pop_size
490497 probabilities = np .outer (probability_selecting_strategy_first , probability_selecting_strategy_second )
491- fitness = np .asarray ([[self .full_fitness (i , j , population_state ) for i in
492- range (len (population_state ))] for j in range (len (population_state ))])
493- fitness [np .isnan (fitness )] = 0
498+ fitness = np .zeros (shape = (self .nb_strategies , self .nb_strategies ))
499+ for j in range (self .nb_strategies ):
500+ if population_state [j ] == 0 :
501+ continue
502+ for i in range (self .nb_strategies ):
503+ if population_state [i ] == 0 :
504+ continue
505+ fitness [j , i ] = self .full_fitness (i , j , population_state )
494506
495507 return (probabilities * np .tanh ((beta / 2 ) * fitness )).sum (axis = 0 )
496508
@@ -588,17 +600,21 @@ def calculate_full_transition_matrix(self, beta: float, *args: Optional[list]) -
588600 increase = np .where (np .array (permutation ) == 1 )[0 ][0 ]
589601 decrease = np .where (np .array (permutation ) == - 1 )[0 ][0 ]
590602
591- # now we calculate the transition probability
592- fitness_diff = self .full_fitness (decrease , increase , current_state )
593- # Probability that the individual that will die is selected and that the individual that
594- # will be imitated is selected times the probability of imitation
595- prob = not_mu * (current_state [increase ] / (self .pop_size - 1 ))
596- prob *= StochDynamics .fermi (beta , fitness_diff )
597- # The probability that there will not be a mutation event times the probability of the transition
598- # plus the probability that if there is a mutation event, the dying strategy is selected
599- # times the probability that it mutates into the increasing strategy
600- prob = (current_state [decrease ] / self .pop_size ) * (prob + mutation_probability )
601- total_prob += prob
603+ if current_state [increase ] == 0 :
604+ prob = (current_state [decrease ] / self .pop_size ) * mutation_probability
605+ else :
606+ # now we calculate the transition probability
607+ fitness_diff = self .full_fitness (decrease , increase , current_state )
608+ # Probability that the individual that will die is selected and that the individual that
609+ # will be imitated is selected times the probability of imitation
610+ prob = not_mu * (current_state [increase ] / (self .pop_size - 1 ))
611+ prob *= StochDynamics .fermi (beta , fitness_diff )
612+ # The probability that there will not be a mutation event times the probability
613+ # of the transition
614+ # plus the probability that if there is a mutation event, the dying strategy is selected
615+ # times the probability that it mutates into the increasing strategy
616+ prob = (current_state [decrease ] / self .pop_size ) * (prob + mutation_probability )
617+ total_prob += prob
602618
603619 transitions [i , new_state_index ] = prob
604620
0 commit comments