Class: Gargor
- Inherits:
-
Object
show all
- Defined in:
- lib/gargor.rb,
lib/gargor/cli.rb,
lib/gargor/dsl.rb,
lib/gargor/version.rb,
lib/gargor/reporter.rb,
lib/gargor/parameter.rb,
lib/gargor/exceptions.rb,
lib/gargor/individual.rb,
lib/gargor/individuals.rb
Defined Under Namespace
Classes: ArgumentError, CLI, DeployError, Double, Dsl, ExterminationError, GargorError, Individual, Individuals, OptimizeReporter, Parameter, ParameterError, Reporter, ValidationError
Constant Summary
collapse
- VERSION =
File.read(File.expand_path(File.join(File.dirname(__FILE__),"..","..","VERSION")))
Class Method Summary
collapse
Class Method Details
.base ⇒ Object
51
52
53
|
# File 'lib/gargor.rb', line 51
def base
@@base
end
|
.crossover(a, b) ⇒ Object
108
109
110
111
112
113
114
115
|
# File 'lib/gargor.rb', line 108
def crossover a,b
return a.clone if a.params == b.params
log "crossover: #{a} #{b}"
total = a.fitness + b.fitness
c = Individual.new
c.params = a.params.clone
c.overwrite_by(b,b.fitness,total)
end
|
.debug(message) ⇒ Object
19
20
21
|
# File 'lib/gargor.rb', line 19
def debug message
log message,Logger::DEBUG
end
|
.first_generation? ⇒ Boolean
72
73
74
|
# File 'lib/gargor.rb', line 72
def first_generation?
@@generation == 1
end
|
.float_rand(f, p = @@dsl.fitness_precision) ⇒ Object
100
101
102
103
104
105
106
|
# File 'lib/gargor.rb', line 100
def float_rand(f,p = @@dsl.fitness_precision)
raise ArgumentError,"max must be > 0" unless f > 0
f *= p
i = f.to_i
f = rand(i)
f / p.to_f
end
|
.generation ⇒ Object
27
28
29
|
# File 'lib/gargor.rb', line 27
def generation
@@generation
end
|
.individuals ⇒ Object
35
36
37
|
# File 'lib/gargor.rb', line 35
def individuals
@@individuals
end
|
.last_trials ⇒ Object
210
211
212
213
|
# File 'lib/gargor.rb', line 210
def last_trials
last_trials_at_this_generation +
(opt("max_generations")-@@generation)*(opt("population")-opt("elite"))
end
|
.last_trials_at_this_generation ⇒ Object
206
207
208
|
# File 'lib/gargor.rb', line 206
def last_trials_at_this_generation
@@individuals.select{ |i| i.fitness == nil }.count
end
|
.load_dsl(params_file) ⇒ Object
82
83
84
85
86
87
|
# File 'lib/gargor.rb', line 82
def load_dsl(params_file)
@@dsl_file = params_file
contents = File.read(params_file)
@@dsl.instance_eval(contents)
validate
end
|
.log(message, level = Logger::INFO) ⇒ Object
14
15
16
17
|
# File 'lib/gargor.rb', line 14
def log message,level=Logger::INFO
return if $TESTING
message.to_s.split("\n").each { |line| @@logger.add(level) {line} }
end
|
.logfile(file) ⇒ Object
198
199
200
|
# File 'lib/gargor.rb', line 198
def logfile file
File.expand_path(File.join(File.dirname(@@dsl_file),file))
end
|
.logger ⇒ Object
39
40
41
|
# File 'lib/gargor.rb', line 39
def logger
@@logger
end
|
.logger=(logger) ⇒ Object
43
44
45
|
# File 'lib/gargor.rb', line 43
def logger= logger
@@logger = logger
end
|
.mutate ⇒ Object
93
94
95
96
97
|
# File 'lib/gargor.rb', line 93
def mutate
individual = @@dsl.create_individual
log "mutate #{individual}"
individual
end
|
.mutation?(mutation = opt("mutation")) ⇒ Boolean
145
146
147
|
# File 'lib/gargor.rb', line 145
def mutation? mutation= opt("mutation")
rand <= mutation
end
|
.next_generation ⇒ Object
188
189
190
191
192
193
194
195
196
|
# File 'lib/gargor.rb', line 188
def next_generation
log "<== end generation #{@@generation}"
@@generation += 1
return false if @@generation > opt("max_generations")
log "==> next generation #{@@generation}"
@@prev_generation = @@individuals
true
end
|
.opt(name) ⇒ Object
47
48
49
|
# File 'lib/gargor.rb', line 47
def opt name
@@dsl.send(name)
end
|
.options=(options) ⇒ Object
89
90
91
|
# File 'lib/gargor.rb', line 89
def options= options
@@dsl.options = options
end
|
.params ⇒ Object
23
24
25
|
# File 'lib/gargor.rb', line 23
def params
@@dsl.params
end
|
.populate ⇒ Object
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
|
# File 'lib/gargor.rb', line 172
def populate
@@individuals = if first_generation?
populate_first_generation
else
raise ExterminationError unless prev_count >= 2
populate_next_generation
end
@@dsl.save_state(@@individuals) if @@dsl.has_state?
log "populate:"
@@individuals.each { |i| log i }
end
|
.populate_first_generation ⇒ Object
127
128
129
130
131
132
133
134
135
136
137
138
|
# File 'lib/gargor.rb', line 127
def populate_first_generation
@@base = @@dsl.create_individual.load_now
individuals = @@dsl.load_state if @@dsl.has_state?
unless individuals
individuals = Gargor::Individuals.new
individuals << base
until individuals.length >= opt("population")
individuals << mutate
end
end
Gargor::Individuals.new(individuals.shuffle)
end
|
.populate_next_generation ⇒ Object
161
162
163
164
165
166
167
168
169
170
|
# File 'lib/gargor.rb', line 161
def populate_next_generation
log "population: #{@@prev_generation.length}"
individuals = Gargor::Individuals.new(select_elites @@prev_generation,opt("elite"))
until individuals.length >= opt("population") do
i = populate_one
individuals << i unless individuals.has?(i)
end
Gargor::Individuals.new(individuals.shuffle)
end
|
.populate_one ⇒ Object
153
154
155
156
157
158
159
|
# File 'lib/gargor.rb', line 153
def populate_one
if mutation?
mutate
else
crossover(*select_parents(@@prev_generation))
end
end
|
.prev_count(g = @@prev_generation) ⇒ Object
77
78
79
80
|
# File 'lib/gargor.rb', line 77
def prev_count g = @@prev_generation
g.select { |i| i.fitness && i.fitness > 0 }.count
end
|
.prev_generation ⇒ Object
31
32
33
|
# File 'lib/gargor.rb', line 31
def prev_generation
@@prev_generation
end
|
.select_elites(g, count) ⇒ Object
140
141
142
143
|
# File 'lib/gargor.rb', line 140
def select_elites g,count
return [] unless count > 0
Gargor::Individuals.new(g.sort{ |a,b| a.fitness<=>b.fitness }.last(count))
end
|
.select_parents(g) ⇒ Object
149
150
151
|
# File 'lib/gargor.rb', line 149
def select_parents g
[selection(g),selection(g)]
end
|
.selection(g) ⇒ Object
117
118
119
120
121
122
123
124
125
|
# File 'lib/gargor.rb', line 117
def selection g
total = g.inject(0) { |sum,i| sum += i.fitness }
cur = float_rand(total)
g.each { |i|
return i if i.fitness > cur
cur -= i.fitness
}
raise GargorError,"error selection"
end
|
.start ⇒ Object
55
56
57
58
59
60
61
62
63
64
|
# File 'lib/gargor.rb', line 55
def start
@@logger = Logger.new(STDOUT)
@@base = nil
@@individuals = []
@@prev_generation = nil
@@generation = 1
@@dsl = Dsl.new
@@dsl_file = nil
true
end
|
.total_trials ⇒ Object
202
203
204
|
# File 'lib/gargor.rb', line 202
def total_trials
opt("population")+(opt("population")-opt("elite"))*(opt("max_generations")-1)
end
|
.validate ⇒ Object
67
68
69
70
|
# File 'lib/gargor.rb', line 67
def validate
raise ValidationError,"POPULATION isn't > 0" unless opt("population") > 0
true
end
|