Changeset 1283 for framspy/evolalg


Ignore:
Timestamp:
09/11/23 23:54:06 (15 months ago)
Author:
Maciej Komosinski
Message:

Stochastic rounding to deliver on average the expected number of mutants and crossovers per generation

File:
1 edited

Legend:

Unmodified
Added
Removed
  • framspy/evolalg/base/experiment_abc.py

    r1194 r1283  
    44import pickle
    55import time
     6import math
     7import random
    68from abc import ABC, abstractmethod
    79
     
    4345            ind_list.append(new_individual)
    4446
     47    @staticmethod
     48    def stochastic_round(value): # https://en.wikipedia.org/wiki/Rounding#Stochastic_rounding
     49        # For example, value==2.1 should turn in most cases to int 2, rarely to int 3
     50        lower = math.floor(value) # returns int
     51        return lower + (random.random() < (value - lower))
     52
    4553    def make_new_population(self, individuals, prob_mut, prob_xov, tournament_size):
    4654        """'individuals' is the input population (a list of individuals).
     
    4856        Returns: a new population of size 'self.popsize' with prob_mut mutants, prob_xov offspring, and the remainder of clones."""
    4957
     58        # if (self.popsize * probability) below is not integer (e.g. popsize=50, prob_xov=0.333, expected number of crossovers = 50*0.333=16.65), stochastic_round() will ensure that you will get on average the expected number of crossovers per generation (e.g. 16.65: less often 16, more often 17).
     59        expected_mut = self.stochastic_round(self.popsize * prob_mut) # or int(...) if you accept less mutants in some cases, see the comment above
     60        expected_xov = self.stochastic_round(self.popsize * prob_xov) # or int(...) if you accept less crossovers in some cases, see the comment above
     61        assert expected_mut + expected_xov <= self.popsize, "If probabilities of mutation (%g) and crossover (%g) added together exceed 1.0, then the population would grow every generation..." % (prob_mut, prob_xov) # can be triggered due to stochastic_round() if prob_mut+prob_xov is close to 1 and the expected number of mutants or crossovers is not integer; if this happens, adjust popsize, prob_mut and prob_xov accordingly.
     62
    5063        newpop = []
    51         expected_mut = int(self.popsize * prob_mut)
    52         expected_xov = int(self.popsize * prob_xov)
    53         assert expected_mut + expected_xov <= self.popsize, "If probabilities of mutation (%g) and crossover (%g) added together exceed 1.0, then the population would grow every generation..." % (prob_mut, prob_xov)
    5464        ris = RandomIndexSequence(len(individuals))
    5565
Note: See TracChangeset for help on using the changeset viewer.