class Evopop::Population

Represents the population that is being trained. Has various methods relevant to training.

Examples

population = Evopop::Population.new
... initialize population with parameters ...
population.train
population.crossover
population.mutate

Attributes

average_fitness[RW]
candidates[RW]
crossover_function[RW]
crossover_params[RW]
dna_len[RW]
fitness_function[RW]
initial_range_max[RW]
initial_range_min[RW]
max_generations[RW]
mutation_num[RW]
mutation_range_max[RW]
mutation_range_min[RW]
population_size[RW]

Public Class Methods

new() click to toggle source

Initializes the attributes with default values. This is not guaranteed to reach maxima.

# File lib/evopop/population.rb, line 22
def initialize
  Evopop.config.instance_variables.each do |iv|
    instance_variable_set(
      iv,
      Evopop.config.instance_variable_get(iv)
    )
  end
  create
  self
end

Public Instance Methods

create() click to toggle source

Creates a new set of population. Should be called after all the parameters have been set to the attributes.

# File lib/evopop/population.rb, line 35
def create
  @candidates = Array.new(@population_size) do
    dna = Evopop::Dna.new(
      @initial_range_min,
      @initial_range_max,
      @mutation_range_min,
      @mutation_range_max,
      @dna_len
    )
    candidate = Evopop::Candidate.new(dna)
    candidate
  end
end
crossover() click to toggle source

Performs simple mechanism of crossover - in this case picks two random candidates in from a top percentile of the population and performs one point crossover, producing new offspring equal to the population size attribute.

# File lib/evopop/population.rb, line 70
def crossover
  new_generation = []

  # For all the top candidates, take the top 2 and crossover
  (0...@population_size).each do
    children = @crossover_function.call(top_candidates.sample(2), @crossover_params)
    new_generation += children

    if new_generation.length >= population_size
      new_generation = new_generation.take(population_size)
      break
    end
  end

  @candidates = new_generation
end
mutate() click to toggle source

Performs simple mutation over the next generation. In this case, it either adds or substracts an amount to each dimension given the mutation range attributes.

# File lib/evopop/population.rb, line 90
def mutate
  mutated_candidates.each do |c|
    c.dna.dna_len_range.each do |i|
      c.dna.mutate(i)
    end
  end
end
train() click to toggle source

Determines the fitness of the population and thereafter sorts it based on fitness descdending (high fitness first, low fitness last).

# File lib/evopop/population.rb, line 51
def train
  average_fitness = 0
  @candidates.each do |c|
    c.fitness = fitness_function.call(c.dna)
    average_fitness += + c.fitness
  end

  average_fitness /= @population_size

  @average_fitness << average_fitness

  @candidates = @candidates.sort_by(&:fitness)
  @candidates = @candidates.reverse
end

Private Instance Methods

mutated_candidates() click to toggle source
# File lib/evopop/population.rb, line 104
def mutated_candidates
  @candidates.sample(@mutation_num)
end
top_candidates() click to toggle source
# File lib/evopop/population.rb, line 100
def top_candidates
  @candidates.take((@population_size * 0.75).to_i)
end