Class: Gargor
- Inherits:
-
Object
show all
- Defined in:
- lib/gargor.rb,
lib/gargor/version.rb,
lib/gargor/parameter.rb,
lib/gargor/individual.rb
Defined Under Namespace
Classes: ArgumentError, ExterminationError, GargorError, Individual, Individuals, Parameter, ParameterError, ValidationError
Constant Summary
collapse
- GLOBAL_OPTS =
["population","max_generations","target_nodes",
"attack_cmd","elite","mutation","target_cooking_cmd",
"fitness_precision"]
- VERSION =
File.read(File.expand_path(File.join(File.dirname(__FILE__),"..","..","VERSION")))
Class Method Summary
collapse
Instance Method Summary
collapse
Class Method Details
.crossover(a, b) ⇒ Object
114
115
116
117
118
119
120
121
|
# File 'lib/gargor.rb', line 114
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
41
42
43
|
# File 'lib/gargor.rb', line 41
def debug message
log message,Logger::DEBUG
end
|
.first_generation? ⇒ Boolean
77
78
79
|
# File 'lib/gargor.rb', line 77
def first_generation?
@@generation == 1
end
|
.float_rand(f, p = @@fitness_precision) ⇒ Object
106
107
108
109
110
111
112
|
# File 'lib/gargor.rb', line 106
def float_rand(f,p = @@fitness_precision)
raise ArgumentError,"max must be > 0" unless f > 0
f *= @@fitness_precision
i = f.to_i
f = rand(i)
f / @@fitness_precision.to_f
end
|
.individuals ⇒ Object
201
202
203
|
# File 'lib/gargor.rb', line 201
def individuals
@@individuals
end
|
.last_trials ⇒ Object
221
222
223
224
|
# File 'lib/gargor.rb', line 221
def last_trials
last_trials_at_this_generation +
(@@max_generations-@@generation)*(@@population-@@elite)
end
|
.last_trials_at_this_generation ⇒ Object
217
218
219
|
# File 'lib/gargor.rb', line 217
def last_trials_at_this_generation
@@individuals.select{ |i| i.fitness == nil }.count
end
|
.load_dsl(params_file) ⇒ Object
87
88
89
90
91
92
|
# File 'lib/gargor.rb', line 87
def load_dsl(params_file)
@@dsl_file = params_file
contents = File.read(params_file)
new.instance_eval(contents)
validate
end
|
.log(message, level = Logger::INFO) ⇒ Object
36
37
38
39
|
# File 'lib/gargor.rb', line 36
def log message,level=Logger::INFO
return if $TESTING
message.to_s.split("\n").each { |line| @@logger.add(level) {line} }
end
|
.logfile(file) ⇒ Object
209
210
211
|
# File 'lib/gargor.rb', line 209
def logfile file
File.expand_path(File.join(File.dirname(@@dsl_file),file))
end
|
.mutate ⇒ Object
94
95
96
97
98
99
100
101
102
103
|
# File 'lib/gargor.rb', line 94
def mutate
individual = Individual.new
@@param_procs.each { |name,proc|
param = Parameter.new(name)
param.instance_eval(&proc)
individual.params[name] = param
}
log "mutate #{individual}"
individual
end
|
.mutation?(mutation = @@mutation) ⇒ Boolean
149
150
151
|
# File 'lib/gargor.rb', line 149
def mutation? mutation=@@mutation
rand <= mutation
end
|
.next_generation ⇒ Object
191
192
193
194
195
196
197
198
199
|
# File 'lib/gargor.rb', line 191
def next_generation
log "<== end generation #{@@generation}"
@@generation += 1
return false if @@generation > @@max_generations
log "==> next generation #{@@generation}"
@@prev_generation = @@individuals
true
end
|
.opt(name) ⇒ Object
205
206
207
|
# File 'lib/gargor.rb', line 205
def opt name
Gargor.class_variable_get("@@#{name}")
end
|
.params ⇒ Object
45
46
47
48
49
50
51
|
# File 'lib/gargor.rb', line 45
def params
result = {}
GLOBAL_OPTS.map { |name|
result[name] = Gargor.class_variable_get("@@#{name}")
}
result
end
|
.populate ⇒ Object
179
180
181
182
183
184
185
186
187
188
|
# File 'lib/gargor.rb', line 179
def populate
@@individuals = if first_generation?
populate_first_generation
else
raise ExterminationError unless prev_count >= 2
populate_next_generation
end
end
|
.populate_first_generation ⇒ Object
133
134
135
136
137
138
139
140
141
142
|
# File 'lib/gargor.rb', line 133
def populate_first_generation
individuals = Gargor::Individuals.new
individuals << mutate.load_now
loop{
break if individuals.length >= @@population
individuals << mutate
}
Gargor::Individuals.new(individuals.shuffle)
end
|
.populate_next_generation ⇒ Object
165
166
167
168
169
170
171
172
173
174
175
176
177
|
# File 'lib/gargor.rb', line 165
def populate_next_generation
log "population: #{@@prev_generation.length}"
individuals = Gargor::Individuals.new(select_elites @@prev_generation,@@elite)
loop{
break if individuals.length >= @@population
i = populate_one
individuals << i unless individuals.has?(i)
}
log "populate:"
individuals.each { |i| log i }
Gargor::Individuals.new(individuals.shuffle)
end
|
.populate_one ⇒ Object
157
158
159
160
161
162
163
|
# File 'lib/gargor.rb', line 157
def populate_one
if mutation?
mutate
else
crossover(*select_parents(@@prev_generation))
end
end
|
.prev_count(g = @@prev_generation) ⇒ Object
82
83
84
85
|
# File 'lib/gargor.rb', line 82
def prev_count g = @@prev_generation
g.select { |i| i.fitness && i.fitness > 0 }.count
end
|
.select_elites(g, count) ⇒ Object
144
145
146
147
|
# File 'lib/gargor.rb', line 144
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
153
154
155
|
# File 'lib/gargor.rb', line 153
def select_parents g
[selection(g),selection(g)]
end
|
.selection(g) ⇒ Object
123
124
125
126
127
128
129
130
131
|
# File 'lib/gargor.rb', line 123
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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
# File 'lib/gargor.rb', line 53
def start
@@logger = Logger.new(STDOUT)
@@fitness_precision = 100000000
@@prev_generation = nil
@@individuals = []
@@param_procs = {}
@@population = 0
@@max_generations = 1
@@generation = 1
@@elite = 0
@@attack_cmd = "false"
@@attack_proc = nil
@@evaluate_proc = Proc.new { 0 }
@@target_nodes = []
@@dsl_file = nil
true
end
|
.total_trials ⇒ Object
213
214
215
|
# File 'lib/gargor.rb', line 213
def total_trials
@@population+(@@population-@@elite)*(@@max_generations-1)
end
|
.validate ⇒ Object
72
73
74
75
|
# File 'lib/gargor.rb', line 72
def validate
raise ValidationError,"POPULATION isn't > 0" unless @@population > 0
true
end
|
Instance Method Details
#attack(cmd, &block) ⇒ Object
232
233
234
235
|
# File 'lib/gargor.rb', line 232
def attack cmd,&block
@@attack_cmd = cmd
@@attack_proc = block
end
|
#evaluate(&block) ⇒ Object
237
238
239
|
# File 'lib/gargor.rb', line 237
def evaluate &block
@@evaluate_proc = block
end
|
#log(message, level = Logger::INFO) ⇒ Object
32
33
34
|
# File 'lib/gargor.rb', line 32
def log message,level=Logger::INFO
Gargor.log(message,level)
end
|
#logger(*args, &block) ⇒ Object
241
242
243
244
245
|
# File 'lib/gargor.rb', line 241
def logger *args, &block
file = args.shift
@@logger = Logger.new(Gargor.logfile(file),*args)
block.call(@@logger) if block
end
|
#param(name, &block) ⇒ Object
228
229
230
|
# File 'lib/gargor.rb', line 228
def param name,&block
@@param_procs[name] = block
end
|