class MHL::RealVectorGenotypeSpace
This class implements a genotype with real space representation
Public Class Methods
new(opts, logger)
click to toggle source
# File lib/mhl/real_vector_genotype_space.rb, line 5 def initialize(opts, logger) @random_func = opts[:random_func] @dimensions = opts[:dimensions].to_i unless @dimensions and @dimensions > 0 raise ArgumentError, 'The number of dimensions must be a positive integer!' end # TODO: enable to choose which recombination function to use case opts[:recombination_type].to_s when /intermediate/i @recombination_func = :extended_intermediate_recombination when /line/i @recombination_func = :extended_line_recombination else raise ArgumentError, 'Recombination function must be either line or intermediate!' end @constraints = opts[:constraints] if !@constraints or @constraints.size != @dimensions raise ArgumentError, 'Real-valued GA variants require constraints!' end @logger = logger end
Public Instance Methods
get_random()
click to toggle source
# File lib/mhl/real_vector_genotype_space.rb, line 31 def get_random if @random_func @random_func.call else if @constraints @constraints.map{|x| x[:from] + SecureRandom.random_number(x[:to] - x[:from]) } else raise 'Automated random genotype generation when no constraints are provided is not implemented yet!' end end end
reproduce_from(p1, p2, mutation_rv, recombination_rv)
click to toggle source
reproduction with power mutation and line or intermediate recombination
# File lib/mhl/real_vector_genotype_space.rb, line 44 def reproduce_from(p1, p2, mutation_rv, recombination_rv) # make copies of p1 and p2 # (we're only interested in the :genotype key) c1 = { genotype: p1[:genotype].dup } c2 = { genotype: p2[:genotype].dup } # mutation comes first power_mutation(c1[:genotype], mutation_rv) power_mutation(c2[:genotype], mutation_rv) # and then recombination send(@recombination_func, c1[:genotype], c2[:genotype], recombination_rv) if @constraints repair_chromosome(c1[:genotype]) repair_chromosome(c2[:genotype]) end return c1, c2 end
Private Instance Methods
extended_intermediate_recombination(g1, g2, recombination_rv)
click to toggle source
extended intermediate recombination [MUHLENBEIN93] (see [LUKE15] page 42)
# File lib/mhl/real_vector_genotype_space.rb, line 90 def extended_intermediate_recombination(g1, g2, recombination_rv) # TODO: disable this check in non-debugging mode raise ArgumentError, 'g1 and g2 must have the same dimension' unless g1.size == g2.size # recombination g1.each_index do |i| begin alpha = recombination_rv.next beta = recombination_rv.next t = alpha * g1[i] + (1.0 - alpha) * g2[i] s = beta * g2[i] + (1.0 - beta) * g1[i] end g1[i] = t g2[i] = s end end
extended_line_recombination(g1, g2, recombination_rv)
click to toggle source
extended line recombination [MUHLENBEIN93] (see [LUKE15] page 42)
# File lib/mhl/real_vector_genotype_space.rb, line 108 def extended_line_recombination(g1, g2, recombination_rv) # TODO: disable this check in non-debugging mode raise ArgumentError, 'g1 and g2 must have the same dimension' unless g1.size == g2.size alpha = recombination_rv.next beta = recombination_rv.next # recombination g1.each_index do |i| t = alpha * g1[i] + (1.0 - alpha) * g2[i] s = beta * g2[i] + (1.0 - beta) * g1[i] g1[i] = t g2[i] = s end end
power_mutation(parent, mutation_rv)
click to toggle source
power mutation [DEEP07] NOTE: this mutation operator won't work unless constraints are given
# File lib/mhl/real_vector_genotype_space.rb, line 70 def power_mutation(parent, mutation_rv) s = mutation_rv.next ** 10.0 min = @constraints.map{|x| x[:from] } max = @constraints.map{|x| x[:to] } parent.each_index do |i| t_i = (parent[i] - min[i]) / (max[i]-min[i]) if rand() >= t_i # sometimes the variation will be positive ... parent[i] += s * (max[i] - parent[i]) else # ... and sometimes it will be negative parent[i] -= s * (parent[i] - min[i]) end end end
repair_chromosome(g)
click to toggle source
# File lib/mhl/real_vector_genotype_space.rb, line 124 def repair_chromosome(g) g.each_index do |i| if g[i] < @constraints[i][:from] range = "[#{@constraints[i][:from]},#{@constraints[i][:to]}]" @logger.debug "repairing g[#{i}] #{g[i]} to fit within #{range}" if @logger g[i] = @constraints[i][:from] @logger.debug "g[#{i}] repaired as: #{g[i]}" if @logger elsif g[i] > @constraints[i][:to] range = "[#{@constraints[i][:from]},#{@constraints[i][:to]}]" @logger.debug "repairing g[#{i}] #{g[i]} to fit within #{range}" if @logger g[i] = @constraints[i][:to] @logger.debug "g[#{i}] repaired as: #{g[i]}" if @logger end end end