mutate.rb

Path: lib/charlie/mutate.rb
Last Update: Sat Jan 26 00:46:58 +0100 2008

Contains some basic mutators and functions on mutators

Methods

PMutate   PMutateN  

Public Instance methods

Takes mutator m1 with probability p, and mutator m2 with probability 1-p

[Source]

    # File lib/charlie/mutate.rb, line 10
10: def PMutate(p,m1,m2=NullMutator)
11:   raise ArgumentError, "first argument to PMutate should be numeric (probability)." unless p.is_a?(Numeric)
12:   return m1 if m1==m2
13:   m1_name, m2_name = [m1,m2].map{|c| '_mutate_' + c.to_s.gsub(/[^A-Za-z0-9]/,'') + '!' }
14:   Module.new{
15:     include m1.dup # dup to avoid bugs on use PMutate(..,m1) .. use m1
16:     alias_method m1_name, :mutate!
17:     include m2.dup
18:     alias_method m2_name, :mutate!
19: 
20:     define_method(:mutate!) {
21:       rand < p ? send(m1_name) : send(m2_name)
22:     }
23:     self.name= "PMutate(#{p},#{m1},#{m2})"
24:   }
25: end

Variant of PMutate for more than 2 mutators

[Source]

    # File lib/charlie/mutate.rb, line 31
31: def PMutateN(hash)
32:   tot_p = hash.inject(0){|s,(m,p)| s+p }
33:   if (tot_p - 1.0).abs > 0.01 # close to 1?
34:     raise ArgumentError, "PMutateN: sum of probabilities > 1.0" if tot_p > 1.0
35:     hash[NullMutator] = (hash[NullMutator] || 0.0) + (1.0 - tot_p)
36:   end
37:   partial_sums = hash.sort_by{|m,p| -p } # max probability first
38:   s = 0.0
39:   partial_sums.map!{|m,p| ['_mutate_' + m.to_s.gsub(/[^A-Za-z0-9]/,'') + '!' , s+=p, m] }
40: 
41:   Module.new{
42:     partial_sums.each{|name,p,mod|
43:       include mod.dup
44:       alias_method name, :mutate!
45:     }
46:     define_method(:mutate!) {
47:       r = rand
48:       send partial_sums.find{|name,p,mod| p >= r }.first
49:     }
50:     self.name= "PMutateN(#{hash.inspect})"
51:   }
52: end

[Validate]