class Gargor

Constants

VERSION

Public Class Methods

base() click to toggle source
# File lib/gargor.rb, line 50
def base
  @@base
end
crossover(a,b) click to toggle source
# File lib/gargor.rb, line 107
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) click to toggle source
# File lib/gargor.rb, line 18
def debug message
  log message,Logger::DEBUG
end
first_generation?() click to toggle source
# File lib/gargor.rb, line 71
def first_generation?
  @@generation == 1
end
float_rand(f,p = @@dsl.fitness_precision) click to toggle source

浮動小数点対応のrand

# File lib/gargor.rb, line 99
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() click to toggle source
# File lib/gargor.rb, line 26
def generation
  @@generation
end
individuals() click to toggle source
# File lib/gargor.rb, line 34
def individuals
  @@individuals
end
last_trials() click to toggle source
# File lib/gargor.rb, line 209
def last_trials
  last_trials_at_this_generation +
    (opt("max_generations")-@@generation)*(opt("population")-opt("elite"))
end
last_trials_at_this_generation() click to toggle source
# File lib/gargor.rb, line 205
def last_trials_at_this_generation
  @@individuals.select{ |i| i.fitness == nil }.count
end
load_dsl(params_file) click to toggle source
# File lib/gargor.rb, line 81
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) click to toggle source
# File lib/gargor.rb, line 13
def log message,level=Logger::INFO
  return if $TESTING
  message.to_s.split("\n").each { |line| @@logger.add(level) {line} }
end
logfile(file) click to toggle source
# File lib/gargor.rb, line 197
def logfile file
  File.expand_path(File.join(File.dirname(@@dsl_file),file))
end
logger() click to toggle source
# File lib/gargor.rb, line 38
def logger
  @@logger
end
logger=(logger) click to toggle source
# File lib/gargor.rb, line 42
def logger= logger
  @@logger = logger
end
mutate() click to toggle source
# File lib/gargor.rb, line 92
def mutate
  individual = @@dsl.create_individual
  log "mutate #{individual}"
  individual
end
mutation?(mutation= opt("mutation")) click to toggle source
# File lib/gargor.rb, line 144
def mutation? mutation= opt("mutation")
  rand <= mutation
end
next_generation() click to toggle source
# File lib/gargor.rb, line 187
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) click to toggle source
# File lib/gargor.rb, line 46
def opt name
  @@dsl.send(name)
end
options=(options) click to toggle source
# File lib/gargor.rb, line 88
def options= options
  @@dsl.options = options
end
params() click to toggle source
# File lib/gargor.rb, line 22
def params
  @@dsl.params
end
populate() click to toggle source
# File lib/gargor.rb, line 171
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() click to toggle source
# File lib/gargor.rb, line 126
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() click to toggle source
# File lib/gargor.rb, line 160
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() click to toggle source
# File lib/gargor.rb, line 152
def populate_one
  if mutation?
    mutate
  else
    crossover(*select_parents(@@prev_generation))
  end
end
prev_count(g = @@prev_generation) click to toggle source

前世代の数

# File lib/gargor.rb, line 76
def prev_count g = @@prev_generation
  # fitness > 0 適応している個体
  g.select { |i| i.fitness && i.fitness > 0 }.count
end
prev_generation() click to toggle source
# File lib/gargor.rb, line 30
def prev_generation
  @@prev_generation
end
select_elites(g,count) click to toggle source
# File lib/gargor.rb, line 139
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) click to toggle source
# File lib/gargor.rb, line 148
def select_parents g
  [selection(g),selection(g)]
end
selection(g) click to toggle source
# File lib/gargor.rb, line 116
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() click to toggle source
# File lib/gargor.rb, line 54
def start
  @@logger = Logger.new(STDOUT)
  @@base = nil
  @@individuals = []
  @@prev_generation = nil
  @@generation = 1
  @@dsl = Dsl.new
  @@dsl_file = nil
  true
end
total_trials() click to toggle source
# File lib/gargor.rb, line 201
def total_trials
  opt("population")+(opt("population")-opt("elite"))*(opt("max_generations")-1)
end
validate() click to toggle source
# File lib/gargor.rb, line 66
def validate
  raise ValidationError,"POPULATION isn't > 0" unless opt("population") > 0
  true
end