require 'set'
require 'lib/mapper_base'
module Operator
class CrossoverLHS
def initialize
@random = Kernel
end
attr_accessor :random
def crossover( parent1, parent2, track1, track2 )
raise "CrossoverLHS: no track_support. Check Mapper#track_support_on" unless track1.kind_of?( Enumerable ) and track2.kind_of?( Enumerable )
offspring1 = parent1.clone
offspring2 = parent2.clone
offspring1.concat parent1 while offspring1.size < track1.last.to+1
offspring2.concat parent2 while offspring2.size < track2.last.to+1
hash1 = {}
track1.each do |node|
choices = hash1.fetch( node.symbol, [] )
choices.push node
hash1[node.symbol] = choices
end
hash2 = {}
track2.each do |node|
choices = hash2.fetch( node.symbol, [] )
choices.push node
hash2[node.symbol] = choices
end
symbols = Set.new( hash1.keys ).intersection( hash2.keys ) return offspring1, offspring2 if symbols.empty? sym = symbols.to_a.sort[ @random.rand( symbols.size ) ]
choices = hash1[ sym ]
choice1 = choices[ @random.rand( choices.size ) ]
choices = hash2[ sym ]
choice2 = choices[ @random.rand( choices.size ) ]
part1 = offspring1[ choice1.from .. choice1.to ]
part2 = offspring2[ choice2.from .. choice2.to ]
offspring1[ choice1.from .. choice1.to ] = part2
offspring2[ choice2.from .. choice2.to ] = part1
return offspring1, offspring2
end
end
end