Class: Biopsy::Generation

Inherits:
Object
  • Object
show all
Defined in:
lib/biopsy/optimisers/spea2.rb,
lib/biopsy/optimisers/genetic_algorithm.rb

Overview

Algorithm

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(population_size, parameter_ranges) ⇒ Generation



85
86
87
88
89
90
91
# File 'lib/biopsy/optimisers/spea2.rb', line 85

def initialize(population_size, archive_size)
  @archive_generation = ArchiveGeneration.new
  @population_size = population_size
  @archive_size = archive_size
  @population_array = []
  @archive_array = []
end

Instance Attribute Details

#archive_arrayObject

Returns the value of attribute archive_array.



84
85
86
# File 'lib/biopsy/optimisers/spea2.rb', line 84

def archive_array
  @archive_array
end

#bestObject (readonly)

Returns the value of attribute best.



9
10
11
# File 'lib/biopsy/optimisers/genetic_algorithm.rb', line 9

def best
  @best
end

#population_arrayObject

Returns the value of attribute population_array.



84
85
86
# File 'lib/biopsy/optimisers/spea2.rb', line 84

def population_array
  @population_array
end

#population_homogenosityObject (readonly)

Returns the value of attribute population_homogenosity.



9
10
11
# File 'lib/biopsy/optimisers/genetic_algorithm.rb', line 9

def population_homogenosity
  @population_homogenosity
end

Instance Method Details

#add_new_individual(individual) ⇒ Object



92
93
94
95
96
97
98
99
100
101
# File 'lib/biopsy/optimisers/spea2.rb', line 92

def add_new_individual individual
  @population_array << Individual.new(individual)
  # run generation
  if @population_array.length == @population_size
    self.run_generation
    true
  else
    false
  end
end

#crossoverObject



89
90
91
92
93
94
95
96
97
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
125
126
# File 'lib/biopsy/optimisers/genetic_algorithm.rb', line 89

def crossover
  def mating_process(mother, father)
    children = [{:parameters=>{}}, {:parameters=>{}}]
    mother[:parameters].each do |mother_key, mother_value|
      if rand <= 0.5
        children[0][:parameters][mother_key.to_sym] = mother_value
        children[1][:parameters][mother_key.to_sym] = father[:parameters][mother_key.to_sym]
      else
        children[0][:parameters][mother_key.to_sym] = father[:parameters][mother_key.to_sym]
        children[1][:parameters][mother_key.to_sym] = mother_value
      end
    end
    return children
  end
  # mate the best quarter with the best half
  best_quarter_num = (@current_generation.length.to_f/4.0).round
  best_half_num = best_quarter_num

  best_quarter = @current_generation[-best_quarter_num..-1]
  best_half = @current_generation[-(best_quarter_num+best_half_num)..-(best_quarter_num+1)]
  children = []
  best_quarter.each do |father|
    twins = mating_process(best_half.shuffle!.pop, father)
    children += twins.map{|value| value}
  end
  (0..(children.length-1)).each do |num|
    @current_generation.delete_at(0)
  end
  children.each do |child|
    if @MUTATION_RATE > rand
      children.delete_at(children.index(child))
      children += [generateMutation(child)]
    end
  end

  @current_generation += children
  return true
end

#generateMutation(chromosome) ⇒ Object



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/biopsy/optimisers/genetic_algorithm.rb', line 128

def generateMutation chromosome
  if !@mutation_wheel
    @mutation_wheel = [{}, 0]
    total_param_ranges = 0
    @ranges.each do |key, value|
      next if value.length <= 1
      total_param_ranges += value.length
      @mutation_wheel[0][key.to_sym] = total_param_ranges
    end
    @mutation_wheel[1] = total_param_ranges
  end
  mutation_location = rand(1..@mutation_wheel[1])
  temp_options_params = Marshal.load(Marshal.dump(@ranges))
  @mutation_wheel[0].each do |key, value|
    next if value < mutation_location
    temp_options_params[key.to_sym].delete(chromosome[:parameters][key.to_sym])
    chromosome[:parameters][key.to_sym] = temp_options_params[key.to_sym].sample(1)[0]
    break
  end
  return chromosome
end

#get_populationObject



165
166
167
168
169
170
171
# File 'lib/biopsy/optimisers/genetic_algorithm.rb', line 165

def get_population
  if self.last?
    return @current_generation
  else
    return false
  end
end

#homogeneous_testObject



150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/biopsy/optimisers/genetic_algorithm.rb', line 150

def homogeneous_test
  homo_val = 0
  (0..(@current_generation.length-1)).each do |i|
     (i..(@current_generation.length-1)).each do |j|
        next if i == j
        @current_generation[i][:parameters].each do |key, val|
          homo_val += 1 if val == @current_generation[j][:parameters][key.to_sym]
        end
      end
  end
  n_value = @current_generation.length-1
  sum = (n_value/2)*(n_value+1)
  @population_homogenosity = (homo_val/(sum*@current_generation[0][:parameters].length).to_f)
end

#last?Boolean

is the generation now full?



33
34
35
# File 'lib/biopsy/optimisers/genetic_algorithm.rb', line 33

def last?
  return @current_generation.length == @population_size
end

#mating_process(mother, father) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/biopsy/optimisers/genetic_algorithm.rb', line 90

def mating_process(mother, father)
  children = [{:parameters=>{}}, {:parameters=>{}}]
  mother[:parameters].each do |mother_key, mother_value|
    if rand <= 0.5
      children[0][:parameters][mother_key.to_sym] = mother_value
      children[1][:parameters][mother_key.to_sym] = father[:parameters][mother_key.to_sym]
    else
      children[0][:parameters][mother_key.to_sym] = father[:parameters][mother_key.to_sym]
      children[1][:parameters][mother_key.to_sym] = mother_value
    end
  end
  return children
end

#next_chromosome(chromosome) ⇒ Object

insert the next chromosome into the generation



24
25
26
# File 'lib/biopsy/optimisers/genetic_algorithm.rb', line 24

def next_chromosome (chromosome)
  @current_generation += [chromosome]
end

#run_generationObject



102
103
104
105
106
# File 'lib/biopsy/optimisers/spea2.rb', line 102

def run_generation
  @pop_and_archive = @population_array + @archive_array
  FitnessAssignment.run(@pop_and_archive)
  @archive_array = @archive_generation.run(@pop_and_archive, 10)
end

#selection_processObject

—-remainder stochastic sampling (stochastic universal sampling method)—- apply obj function on parameter_sets, rank parameter_sets by obj func score scale obj func score to ranking where: highest rank=2, lowest rank=0 for each integer in rank reproduce += 1, for decimal allow random reproduction (based on size of decimal)



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/biopsy/optimisers/genetic_algorithm.rb', line 52

def selection_process
  current_generation_temp = []
  #apply obj func on all params, store score in @current_generation[X][:score]
  @current_generation.each do |chromosome|
    current_generation_temp << {:parameters => chromosome[:parameters], :score => chromosome[:score]}
  end
  # sort @current_generation by objective function score (ASC), replace @current_generation w/ temporary array
  @current_generation = current_generation_temp.sort {|a, b| a[:score] <=> b[:score]}
  # the highest rank is 2.0, generate step_size (difference in rank between each element)
  step_size = 2.0/(@current_generation.length-1)
  # counter to be used when assigning rank
  counter = 0
  # next_generation temporary array, @current_generation is replaced by next_generation after loop
  next_generation = []
  # switch scores with ranks
  @current_generation.each do |chromosome|
    # rank (asc) is the order in which the element appears (counter) times step_size so that the max is 2
    rank = counter * step_size
    next_generation << {:parameters => chromosome[:parameters], :score => rank} if rank >= 1.0
    next_generation << {:parameters => chromosome[:parameters], :score => rank} if rank >= 2.0
    next_generation << {:parameters => chromosome[:parameters], :score => rank} if rand <= rank.modulo(1)
    counter += 1
  end
  # if population is too small
  while next_generation.length < @population_size
    select_chromosome = next_generation.sample(1)[0]
    next_generation << select_chromosome
  end
  while next_generation.length > @population_size
    select_chromosome_index = next_generation.index(next_generation.sample(1)[0])
    next_generation.delete_at(select_chromosome_index)
  end
  # sort @current_generation by objective function score (ASC), replace @current_generation w/ temporary array
  @current_generation = next_generation.sort {|a, b| a[:score] <=> b[:score]}
  return
end

#update_best?(current) ⇒ Boolean



28
29
30
# File 'lib/biopsy/optimisers/genetic_algorithm.rb', line 28

def update_best? (current)
  @best = current if current[:score] > @best[:score]
end