Class: Darwinning::Population

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

Constant Summary collapse

DEFAULT_EVOLUTION_TYPES =
[
  Darwinning::EvolutionTypes::Reproduction.new(crossover_method: :alternating_swap),
  Darwinning::EvolutionTypes::Mutation.new(mutation_rate: 0.10)
]

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Population

Returns a new instance of Population.



13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/darwinning/population.rb', line 13

def initialize(options = {})
  @organism = options.fetch(:organism)
  @population_size = options.fetch(:population_size)
  @fitness_goal = options.fetch(:fitness_goal)
  @fitness_objective = options.fetch(:fitness_objective, :nullify) # :nullify, :maximize, :minimize
  @generations_limit = options.fetch(:generations_limit, 0)
  @evolution_types = options.fetch(:evolution_types, DEFAULT_EVOLUTION_TYPES)
  @members = []
  @generation = 0 # initial population is generation 0
  @history = []

  build_population(@population_size)
end

Instance Attribute Details

#evolution_typesObject (readonly)

Returns the value of attribute evolution_types.



4
5
6
# File 'lib/darwinning/population.rb', line 4

def evolution_types
  @evolution_types
end

#fitness_goalObject (readonly)

Returns the value of attribute fitness_goal.



4
5
6
# File 'lib/darwinning/population.rb', line 4

def fitness_goal
  @fitness_goal
end

#fitness_objectiveObject (readonly)

Returns the value of attribute fitness_objective.



4
5
6
# File 'lib/darwinning/population.rb', line 4

def fitness_objective
  @fitness_objective
end

#generationObject (readonly)

Returns the value of attribute generation.



4
5
6
# File 'lib/darwinning/population.rb', line 4

def generation
  @generation
end

#generations_limitObject (readonly)

Returns the value of attribute generations_limit.



4
5
6
# File 'lib/darwinning/population.rb', line 4

def generations_limit
  @generations_limit
end

#historyObject (readonly)

Returns the value of attribute history.



4
5
6
# File 'lib/darwinning/population.rb', line 4

def history
  @history
end

#membersObject (readonly)

Returns the value of attribute members.



4
5
6
# File 'lib/darwinning/population.rb', line 4

def members
  @members
end

#organismObject (readonly)

Returns the value of attribute organism.



4
5
6
# File 'lib/darwinning/population.rb', line 4

def organism
  @organism
end

#population_sizeObject (readonly)

Returns the value of attribute population_size.



4
5
6
# File 'lib/darwinning/population.rb', line 4

def population_size
  @population_size
end

Instance Method Details

#best_each_generationObject



81
82
83
# File 'lib/darwinning/population.rb', line 81

def best_each_generation
  @history.map(&:first)
end

#best_memberObject



77
78
79
# File 'lib/darwinning/population.rb', line 77

def best_member
  @members.first
end

#build_population(population_size) ⇒ Object



27
28
29
30
31
# File 'lib/darwinning/population.rb', line 27

def build_population(population_size)
  population_size.times do |i|
    @members << build_member
  end
end

#evolution_over?Boolean

Returns:

  • (Boolean)


68
69
70
71
72
73
74
75
# File 'lib/darwinning/population.rb', line 68

def evolution_over?
  # check if the fitness goal or generation limit has been met
  if generations_limit > 0
    generation == generations_limit || goal_attained?
  else
    goal_attained?
  end
end

#evolve!Object



33
34
35
36
37
# File 'lib/darwinning/population.rb', line 33

def evolve!
  until evolution_over?
    make_next_generation!
  end
end

#make_next_generation!Object



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/darwinning/population.rb', line 45

def make_next_generation!
  verify_population_size_is_positive!
  sort_members
  @history << @members

  new_members = []

  until new_members.length >= members.length
    m1 = weighted_select
    m2 = weighted_select

    new_members += apply_pairwise_evolutions(m1, m2)
  end

  # In the case of an odd population size, we likely added one too many members.
  new_members.pop if new_members.length > members.length

  @members = apply_non_pairwise_evolutions(new_members)
  sort_members
  @history << @members
  @generation += 1
end

#organism_klassObject



89
90
91
92
93
94
95
96
# File 'lib/darwinning/population.rb', line 89

def organism_klass
  real_organism = @organism
  fitness_function = @fitness_function
  klass = Class.new(Darwinning::Organism) do
    @name = real_organism.name
    @genes = real_organism.genes
  end
end

#set_members_fitness!(fitness_values) ⇒ Object



39
40
41
42
43
# File 'lib/darwinning/population.rb', line 39

def set_members_fitness!(fitness_values)
  throw "Invaid number of fitness values for population size" if fitness_values.size != members.size
  members.to_enum.each_with_index { |m, i| m.fitness = fitness_values[i] }
  sort_members
end

#sizeObject



85
86
87
# File 'lib/darwinning/population.rb', line 85

def size
  @members.length
end