Class: Evopop::Population

Inherits:
Object
  • Object
show all
Defined in:
lib/evopop/population.rb

Overview

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

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializePopulation

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



22
23
24
25
26
27
28
29
30
31
# 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

Instance Attribute Details

#average_fitnessObject

Returns the value of attribute average_fitness.



15
16
17
# File 'lib/evopop/population.rb', line 15

def average_fitness
  @average_fitness
end

#candidatesObject

Returns the value of attribute candidates.



15
16
17
# File 'lib/evopop/population.rb', line 15

def candidates
  @candidates
end

#crossover_functionObject

Returns the value of attribute crossover_function.



15
16
17
# File 'lib/evopop/population.rb', line 15

def crossover_function
  @crossover_function
end

#crossover_paramsObject

Returns the value of attribute crossover_params.



15
16
17
# File 'lib/evopop/population.rb', line 15

def crossover_params
  @crossover_params
end

#dna_lenObject

Returns the value of attribute dna_len.



15
16
17
# File 'lib/evopop/population.rb', line 15

def dna_len
  @dna_len
end

#fitness_functionObject

Returns the value of attribute fitness_function.



15
16
17
# File 'lib/evopop/population.rb', line 15

def fitness_function
  @fitness_function
end

#initial_range_maxObject

Returns the value of attribute initial_range_max.



15
16
17
# File 'lib/evopop/population.rb', line 15

def initial_range_max
  @initial_range_max
end

#initial_range_minObject

Returns the value of attribute initial_range_min.



15
16
17
# File 'lib/evopop/population.rb', line 15

def initial_range_min
  @initial_range_min
end

#max_generationsObject

Returns the value of attribute max_generations.



15
16
17
# File 'lib/evopop/population.rb', line 15

def max_generations
  @max_generations
end

#mutation_numObject

Returns the value of attribute mutation_num.



15
16
17
# File 'lib/evopop/population.rb', line 15

def mutation_num
  @mutation_num
end

#mutation_range_maxObject

Returns the value of attribute mutation_range_max.



15
16
17
# File 'lib/evopop/population.rb', line 15

def mutation_range_max
  @mutation_range_max
end

#mutation_range_minObject

Returns the value of attribute mutation_range_min.



15
16
17
# File 'lib/evopop/population.rb', line 15

def mutation_range_min
  @mutation_range_min
end

#population_sizeObject

Returns the value of attribute population_size.



15
16
17
# File 'lib/evopop/population.rb', line 15

def population_size
  @population_size
end

Instance Method Details

#createObject

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



35
36
37
38
39
40
41
42
43
44
45
46
47
# 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

#crossoverObject

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.



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# 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

#mutateObject

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.



90
91
92
93
94
95
96
# 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

#trainObject

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



51
52
53
54
55
56
57
58
59
60
61
62
63
64
# 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