Skip to content

Commit 76c9805

Browse files
committed
new patch correcting an error in the calculation of full_gradients and full_transition_matrix
1 parent 5f8ca6c commit 76c9805

4 files changed

Lines changed: 45 additions & 20 deletions

File tree

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres
66
to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
77

8+
## [0.1.11.patch2] - 16-11-2022
9+
10+
### Fixed
11+
12+
- Fixed error in `calculate_full_transition_matrix`. The previous implementation tried to calculate the fitness for
13+
strategies with 0 counts in the population. This would lead to an error when calculating the probability of group
14+
forming. Now, we calculate directly the probability of a strategy with 0 counts increasing by 1 individual in the
15+
population, i.e., prob = (n_decreasing_strategy / population_size) * (mu / (1 - nb_strategies)).
16+
817
## [0.1.11.patch1] - 10-11-2022
918

1019
### Fixed

cpp/src/version.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@
1818
#ifndef EGTTOOLS_VERSION_H
1919
#define EGTTOOLS_VERSION_H
2020

21-
#define EGTTOOLS_VERSION 0.1.11.1
21+
#define EGTTOOLS_VERSION 0.1.11.2
2222

2323
#endif//EGTTOOLS_VERSION_H

pybind11

Submodule pybind11 updated 126 files

src/egttools/analytical/sed_analytical.py

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)