Module: EdgeRecombinationCrossover

Defined in:
lib/charlie/permutation/permutation.rb

Overview

Edge recombination operator (en.wikipedia.org/wiki/Edge_recombination_operator)

  • Useful in permutations representing a path, e.g. travelling salesperson.

  • Returns a single child.

  • Permutations of 0…n only, i.e. default second parameter to PermutationGenotype

  • Rather slow.

Instance Method Summary collapse

Instance Method Details

#cross(parent1, parent2) ⇒ Object



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/charlie/permutation/permutation.rb', line 98

def cross(parent1,parent2)
  p1, p2 = parent1.genes, parent2.genes
 
  nb = Array.new(parent1.size){[]}
  (p1 + p1[0..1]).each_cons(3){|l,m,r| nb[m] += [l,r] } # build neighbour lists
  (p2 + p2[0..1]).each_cons(3){|l,m,r| nb[m] += [l,r] } # build neighbour lists
  nb.map(&:uniq!)

  n = (rand < 0.5 ? p1.first : p2.first)
  child = [n]
  (nb.size-1).times{
    nb.each{|l| l.delete n unless l==:done }  # remove n from the lists

    if nb[n].empty?  # nb[n] empty, pick random next
      nb[n] = :done
      n = (0...nb.size).find_all{|x| nb[x] != :done }.at_rand # no neighbors left, pick random
    else # pick neighbour with minimal degree, random tie-breaking
      min_deg = nb[n].map{|x| nb[x].size }.min
      next_n = nb[n].find_all{|x| nb[x].size == min_deg }.at_rand # pick random neighbor with min. degree
      nb[n] = :done
      n = next_n
    end 
    child << n  # add new n to path
  }
  
  return from_genes(child)
end