Class: Ai::Neat::Neat

Inherits:
Object
  • Object
show all
Defined in:
lib/ai/neat.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config) ⇒ Neat

Returns a new instance of Neat.



11
12
13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/ai/neat.rb', line 11

def initialize(config)
  @creatures = []
  @old_creatures = []
  @models = config[:models]
  @population_size = config[:population_size] || 500
  @mutation_rate = config[:mutation_rate] || 0.05
  @crossover_method = config[:crossover_method] || :random
  @mutation_method = config[:mutation_method] || :random
  @generation = 0

  (1..@population_size).each do |_i|
    @creatures.push(Creature.new(@models))
  end
end

Instance Attribute Details

#creaturesObject

Returns the value of attribute creatures.



8
9
10
# File 'lib/ai/neat.rb', line 8

def creatures
  @creatures
end

#crossover_methodObject

Returns the value of attribute crossover_method.



8
9
10
# File 'lib/ai/neat.rb', line 8

def crossover_method
  @crossover_method
end

#generationObject

Returns the value of attribute generation.



8
9
10
# File 'lib/ai/neat.rb', line 8

def generation
  @generation
end

#modelsObject

Returns the value of attribute models.



8
9
10
# File 'lib/ai/neat.rb', line 8

def models
  @models
end

#mutation_methodObject

Returns the value of attribute mutation_method.



8
9
10
# File 'lib/ai/neat.rb', line 8

def mutation_method
  @mutation_method
end

#mutation_rateObject

Returns the value of attribute mutation_rate.



8
9
10
# File 'lib/ai/neat.rb', line 8

def mutation_rate
  @mutation_rate
end

#old_creaturesObject

Returns the value of attribute old_creatures.



8
9
10
# File 'lib/ai/neat.rb', line 8

def old_creatures
  @old_creatures
end

#population_sizeObject

Returns the value of attribute population_size.



8
9
10
# File 'lib/ai/neat.rb', line 8

def population_size
  @population_size
end

Instance Method Details

#best_creatureObject



26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/ai/neat.rb', line 26

def best_creature
  index = 0
  max = -Float::INFINITY

  (0..(@old_creatures.count - 1)).each do |i|
    if @old_creatures[i].fitness > max
      max = @old_creatures[i].fitness
      index = i
    end
  end

  index
end

#crossoverObject



40
41
42
43
44
45
46
47
48
49
# File 'lib/ai/neat.rb', line 40

def crossover
  (0..@population_size - 1).each do |i|
    @old_creatures = @creatures.clone
    parent_x = pick_creature
    parent_y = pick_creature

    genes = Ai::Neat.crossover(@crossover_method, parent_x.flatten_genes, parent_y.flatten_genes)
    @creatures[i].flatten_genes = genes
  end
end

#decisionsObject



51
52
53
54
55
56
57
58
59
# File 'lib/ai/neat.rb', line 51

def decisions
  result = []

  @creatures.each do |creature|
    result.push(creature.decision)
  end

  result
end

#do_genObject



61
62
63
64
65
# File 'lib/ai/neat.rb', line 61

def do_gen
  crossover
  mutate
  @generation += 1
end

#exportObject



67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/ai/neat.rb', line 67

def export
  data = {
    models: @models,
    creatures: []
  }

  @creatures.each do |creature|
    data[:creatures].push(creature.flatten_genes)
  end

  data
end

#feed_forwardObject



80
81
82
# File 'lib/ai/neat.rb', line 80

def feed_forward
  @creatures.each(&:feed_forward)
end

#import(data) ⇒ Object



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/ai/neat.rb', line 84

def import(data)
  @models = data[:models]

  @creatures = []
  @population_size = 0

  data[:creatures].each do |genes|
    creature = Creature.new(@models)
    creature.flatten_genes = genes

    @creatures.push(creature)

    @population_size += 1
  end
end

#mutateObject



100
101
102
103
104
105
106
# File 'lib/ai/neat.rb', line 100

def mutate
  (0..@population_size - 1).each do |i|
    genes = @creatures[i].flatten_genes
    genes = Ai::Neat.mutate(@mutation_method, genes, @mutation_rate)
    @creatures[i].flatten_genes = genes
  end
end

#pick_creatureObject



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/ai/neat.rb', line 108

def pick_creature
  sum = 0.0

  @old_creatures.each do |creature|
    sum += creature.score ** 2
  end

  @old_creatures.each do |creature|
    creature.fitness = (creature.score ** 2) / sum
  end

  index = 0
  r = rand

  while r.positive?
    r -= @old_creatures[index].fitness
    index += 1
  end

  index -= 1

  @old_creatures[index]
end

#set_fitness(fitness, index) ⇒ Object



132
133
134
# File 'lib/ai/neat.rb', line 132

def set_fitness(fitness, index)
  @creatures[index].score = fitness
end

#set_inputs(inputs, index) ⇒ Object



136
137
138
# File 'lib/ai/neat.rb', line 136

def set_inputs(inputs, index)
  @creatures[index].inputs = inputs
end