def monomorphous_transition_matrix(intensity_of_selection, payoff_function=None, mutation_kernel=None, mutation_probability=None, population_size=None, game_matrix=None, number_of_strategies=None, mapping='EXP', **kwargs): """ Computes the associated markov chain (transition matrix), when mutations are assumed to be small. The approximation is accurate when there are no stable mixtures between any pair of strategies. Parameters ---------- game_matrix: numpy matrix population_size: int intensity_of_selection: float kernel: ndarray, optional stochastic matrix mutation_probability: float, optional uniform kernel Returns ------- ans: ndarray, stochastic matrix See also --------- old signature: (game_matrix, population_size, intensity_of_selection, kernel=None, mutation_probability=None) """ if mutation_kernel is None and mutation_probability is None: raise ValueError( 'Either a mutation kernel, or a mutation probability has to be specified' ) if game_matrix is not None: size = len(game_matrix) elif payoff_function is not None and number_of_strategies is not None: size = number_of_strategies else: raise ValueError( "if specifying a payoff function the number_of_strategies has to be provided" ) if mutation_kernel is None and mutation_probability is not None: mutation_kernel = utils.uniform_mutation_kernel( mutation_probability, size) ans = np.zeros((size, size)) for i in range(0, size): for j in range(0, size): if i != j: # chance that j appears in an i population # the mutation probability already comes from the kernel # divided by the number of strategies ans[i, j] = transition_probability( i, j, intensity_of_selection, payoff_function, mutation_kernel[i, j], population_size, game_matrix, number_of_strategies, mapping, **kwargs) for i in range(0, size): ans[i, i] = 1.0 - math.fsum(ans[i, :]) return ans
def __init__(self, population_size, intensity_of_selection, game_matrix=None, payoff_function=None, number_of_strategies=None, fitness_mapping='exp', mutation_probability=None, mutation_kernel=None): ''' Moran Process Parameters ---------- population_size: int (>0) intensity_of_selection: double game_matrix: np.darray, shape (n,n) (Optional) fitness_mapping (Optional): function, from ndarray (abundance of each strategy) into ndarray (payoff of each strategy) number_of_strategies (Optional): if a game_matrix is not provided you must provide the number of strategies mutation_probability:double between 0 and 1 (Optional) mutation_kernel: ndarray (Optional) ''' # CHECK THAT EVERYTHING IS IN ORDER self.__check_init_values(game_matrix, payoff_function, number_of_strategies, fitness_mapping, mutation_probability, mutation_kernel) # ASSIGN INIT VARIABLES # NUMBER OF STRATEGIES try: self.number_of_strategies = len(game_matrix) except TypeError: self.number_of_strategies = number_of_strategies # MUTATION KERNEL if (mutation_kernel is None and mutation_probability is not None): self.mutation_kernel = utils.uniform_mutation_kernel( mutation_probability, self.number_of_strategies) # PAYOFF FUNCTION self.game_matrix = game_matrix if self.game_matrix is not None: self.payoff_function = self.__default_payoff_function self.__diagonal = np.diagonal(self.game_matrix) else: self.payoff_function = payoff_function # test that the payoff function is well specified if len(self.payoff_function(np.ones( self.number_of_strategies))) != self.number_of_strategies: raise ValueError('The payoff function is mispecified') # INTENSITY OF SELECTION self.intensity_of_selection = intensity_of_selection # POP SIZE self.population_size = population_size # FITNESS MAPPING self.fitness_mapping = fitness_mapping
def test_uniform_mutation_kernel(self): #check for 10 random kernels that all rows sump up to 1 for _ in xrange(0,10): mutation_kernel = utils.uniform_mutation_kernel(np.random.rand(), np.random.randint(2, 10)) rows = mutation_kernel.shape[0] columns = mutation_kernel.shape[1] self.assertEqual(rows, columns, "Rows and columns must have same size") sum_rows = np.array([np.sum(mutation_kernel[i,:]) for i in xrange(0,rows)]) np.testing.assert_allclose(sum_rows, np.ones(columns), rtol=0.001, err_msg="Rows do not sum up to 1. in " + str(mutation_kernel))
def monomorphous_transition_matrix(intensity_of_selection, payoff_function=None, mutation_kernel=None, mutation_probability=None, population_size=None, game_matrix=None, number_of_strategies=None, mapping='EXP', **kwargs): """ Computes the associated markov chain (transition matrix), when mutations are assumed to be small. The approximation is accurate when there are no stable mixtures between any pair of strategies. Parameters ---------- game_matrix: numpy matrix population_size: int intensity_of_selection: float kernel: ndarray, optional stochastic matrix mutation_probability: float, optional uniform kernel Returns ------- ans: ndarray, stochastic matrix See also --------- old signature: (game_matrix, population_size, intensity_of_selection, kernel=None, mutation_probability=None) """ if mutation_kernel is None and mutation_probability is None: raise ValueError( 'Either a mutation kernel, or a mutation probability has to be specified') if game_matrix is not None: size = len(game_matrix) elif payoff_function is not None and number_of_strategies is not None: size = number_of_strategies else: raise ValueError( "if specifying a payoff function the number_of_strategies has to be provided") if mutation_kernel is None and mutation_probability is not None: mutation_kernel = utils.uniform_mutation_kernel( mutation_probability, size) ans = np.zeros((size, size)) for i in range(0, size): for j in range(0, size): if i != j: # chance that j appears in an i population # the mutation probability already comes from the kernel # divided by the number of strategies ans[i, j] = transition_probability(i, j, intensity_of_selection, payoff_function, mutation_kernel[ i, j], population_size, game_matrix, number_of_strategies, mapping, **kwargs) for i in range(0, size): ans[i, i] = 1.0 - math.fsum(ans[i, :]) return ans
def __init__(self, population_size, intensity_of_selection, game_matrix=None, payoff_function=None, number_of_strategies=None, fitness_mapping='exp', mutation_probability=None, mutation_kernel=None): ''' Moran Process Parameters ---------- population_size: int (>0) intensity_of_selection: double game_matrix: np.darray, shape (n,n) (Optional) fitness_mapping (Optional): function, from ndarray (abundance of each strategy) into ndarray (payoff of each strategy) number_of_strategies (Optional): if a game_matrix is not provided you must provide the number of strategies mutation_probability:double between 0 and 1 (Optional) mutation_kernel: ndarray (Optional) ''' # CHECK THAT EVERYTHING IS IN ORDER self.__check_init_values(game_matrix, payoff_function, number_of_strategies, fitness_mapping, mutation_probability, mutation_kernel) # ASSIGN INIT VARIABLES # NUMBER OF STRATEGIES try: self.number_of_strategies = len(game_matrix) except TypeError: self.number_of_strategies = number_of_strategies # MUTATION KERNEL if (mutation_kernel is None and mutation_probability is not None): self.mutation_kernel = utils.uniform_mutation_kernel(mutation_probability, self.number_of_strategies) # PAYOFF FUNCTION self.game_matrix = game_matrix if self.game_matrix is not None: self.payoff_function = self.__default_payoff_function self.__diagonal = np.diagonal(self.game_matrix) else: self.payoff_function = payoff_function # test that the payoff function is well specified if len(self.payoff_function(np.ones(self.number_of_strategies))) != self.number_of_strategies: raise ValueError('The payoff function is mispecified') # INTENSITY OF SELECTION self.intensity_of_selection = intensity_of_selection # POP SIZE self.population_size = population_size # FITNESS MAPPING self.fitness_mapping = fitness_mapping
def test_uniform_mutation_kernel(self): # check for 10 random kernels that all rows sump up to 1 for _ in range(0, 10): mutation_kernel = utils.uniform_mutation_kernel( np.random.rand(), np.random.randint(2, 10)) rows = mutation_kernel.shape[0] columns = mutation_kernel.shape[1] self.assertEqual(rows, columns, "Rows and columns must have same size") sum_rows = np.array( [np.sum(mutation_kernel[i, :]) for i in range(0, rows)]) np.testing.assert_allclose(sum_rows, np.ones(columns), rtol=0.001, err_msg="Rows do not sum up to 1. in " + str(mutation_kernel))