Module: OptimizerFactory

Includes:
LoggedClass
Defined in:
lib/optimizer_factory.rb

Overview

This module provides functions to generate Optimizers and termination criterions.

For an overview and description of the availiable algorithms see the algorithms documentation

Constant Summary

Constants included from LoggedClass

LoggedClass::LoggedClasses

Class Method Summary collapse

Methods included from LoggedClass

#debug, #error, #fatal, generate_outputter_config, included, #info, #warn

Class Method Details

.generate_genetic_optimizer(evaluator, population_size, selection_method, crossovers, crossover_probability, mutations, mutation_probability, termination_criterion, seed, flag_set) ⇒ GeneticOptimizer

Generates a new genetic optimizer. For the other parameters see the documentation of the GeneticOptimizer class.

Parameters:

  • evaluator (Evaluator)

    The evaluator to use.

  • selection_method (String)

    The selection method. This is either “truncate” for a truncating selection or “proportionate” for a proportionate selection.

  • termination_criterion (Proc)

    The termination criterion to use.

  • seed (Fixnum)

    The seed for the random generator.

  • flag_set (FlagSet)

    The flag set to optimize.

Returns:


131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/optimizer_factory.rb', line 131

def OptimizerFactory.generate_genetic_optimizer(evaluator, population_size,
                                                selection_method, crossovers,
                                                crossover_probability,
                                                mutations,
                                                mutation_probability,
                                                termination_criterion,
                                                seed, flag_set)
  select = case selection_method
  when "truncate"
    OptimizerUtils.get_truncation_select population_size
  when "proportionate"
    OptimizerUtils.get_proportionate_select population_size
  end

  GeneticOptimizer.new "Genetic Algorithm", seed, evaluator, population_size,
    select,
    crossovers, crossover_probability,
    mutations, mutation_probability,
    termination_criterion, flag_set
end

.generate_hillclimber(evaluator, parallel_evaluations, termination_criterion, seed, flag_set) ⇒ MutationSearch

Generates a new random walk optimizer

Parameters:

  • evaluator (Evaluator)

    The evaluator to use.

  • parallel_evaluations (Fixnum)

    The number of candidates around the best candidate of the last round to consider.

  • termination_criterion (Proc)

    The termination criterion to use.

  • seed (Fixnum)

    The seed for the random generator.

  • flag_set (FlagSet)

    The flag set to optimize.

Returns:

Raises:

  • (ArgumentError)

74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
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
# File 'lib/optimizer_factory.rb', line 74

def OptimizerFactory.generate_hillclimber(evaluator, parallel_evaluations,
                                          termination_criterion,
                                          seed, flag_set)
  raise ArgumentError if parallel_evaluations % 2 != 0

  init_mutate = lambda do |genotypes, results, random, mutation_state|
    genotypes.map! do |genotype|
      genotype.alter_each do |flag|
        flag[:flag].pick(random)
      end
    end
    genotypes = genotypes.each_with_index.map do |genotype, idx|
      idx.even? ? genotype :
        OptimizerUtils.flip_component(0, genotypes[idx - 1])
    end
    return genotypes, 1
  end

  mutate = lambda do |genotypes, results, random, mutation_state|
    mutation_state = 0 if mutation_state >= genotypes[0].size
    (0...(genotypes.size)).step(2) do |idx|
      this_idx, other_idx = idx, idx + 1

      last_elem_this = results.last[this_idx]
      last_elem_other = results.last[other_idx]

      last_elems = [last_elem_this, last_elem_other]
      last_elems = last_elems.map(&OptimizerUtils.method(:fitness)).
        zip(last_elems)

      best_last = last_elems.min_by(&:first).last.last
      genotypes[this_idx] = best_last.dup
      genotypes[other_idx] = OptimizerUtils.flip_component(mutation_state,
                                                           best_last).dup
      puts "Hillclimber #{last_elem_this.last.show_binstring} => " +
        "#{OptimizerUtils.fitness(last_elem_this)}\n" +
        "#{last_elem_other.last.show_binstring} => " +
        "#{OptimizerUtils.fitness(last_elem_other)}\n======="
    end
    return genotypes, mutation_state + 1
  end

  init = OptimizerUtils.get_init init_mutate, parallel_evaluations, flag_set

  MutationSearch.new "Hillclimber", seed, evaluator, init, mutate,
    termination_criterion
end

.generate_local_search(evaluator, parallel_evaluations, termination_criterion, seed, flag_set, distance) ⇒ MutationSearch

Generates a new random walk optimizer

Parameters:

  • evaluator (Evaluator)

    The evaluator to use.

  • parallel_evaluations (Fixnum)

    The number of candidates around the best candidate of the last round to consider.

  • termination_criterion (Proc)

    The termination criterion to use.

  • seed (Fixnum)

    The seed for the random generator.

  • flag_set (FlagSet)

    The flag set to optimize.

Returns:


37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/optimizer_factory.rb', line 37

def OptimizerFactory.generate_local_search(evaluator, parallel_evaluations,
                                           termination_criterion,
                                           seed, flag_set, distance)
  init = OptimizerUtils.get_init OptimizerUtils.get_init_mutate,
    parallel_evaluations, flag_set

  mutate = lambda do |genotypes, results, random, mutation_state|
    # Determine current element
    best = results.last.min_by(&OptimizerUtils.method(:fitness))


    puts "LocalSearch: best #{best.last.show_binstring} " +
      "#{OptimizerUtils.fitness(best)}"

    # Generate all other elements
    genotypes = parallel_evaluations.times.map do
      genotype = best.last.dup
      (0...flag_set.size).to_a.shuffle(random: random).take(distance).map do |idx|
        genotype = OptimizerUtils.flip_component idx, genotype
      end
      genotype
    end

    return genotypes, mutation_state
  end

  MutationSearch.new "Local Search", seed, evaluator, init, mutate,
    termination_criterion
end

.generate_no_stop_criterionProc

Create a termination criterion that will never terminate the optimizer.

Returns:

  • (Proc)

163
164
165
166
167
# File 'lib/optimizer_factory.rb', line 163

def OptimizerFactory.generate_no_stop_criterion()
  lambda do |steps, results|
    false
  end
end

.generate_random_search(evaluator, parallel_evaluations, termination_criterion, seed, flag_set) ⇒ MutationSearch

Generates a new random search optimizer

Parameters:

  • evaluator (Evaluator)

    The evaluator to use.

  • parallel_evaluations (Fixnum)

    The number of candidates to evaluate in parallel.

  • termination_criterion (Proc)

    The termination criterion to use.

  • seed (Fixnum)

    The seed for the random generator.

  • flag_set (FlagSet)

    The flag set to optimize.

Returns:


20
21
22
23
24
25
26
27
28
# File 'lib/optimizer_factory.rb', line 20

def OptimizerFactory.generate_random_search(evaluator, parallel_evaluations,
                                            termination_criterion,
                                            seed, flag_set)
  mutate = OptimizerUtils.get_init_mutate
  init = OptimizerUtils.get_init mutate, parallel_evaluations, flag_set

  MutationSearch.new "Random Search", seed, evaluator, init, mutate,
    termination_criterion
end

.generate_steps_criterion(max_steps) ⇒ Proc

Create a termination criterion that only considers a maximum number of steps.

Parameters:

  • max_steps (Fixnum)

    The maximum number of steps after which the algorithm has to terminate.

Returns:

  • (Proc)

155
156
157
158
159
# File 'lib/optimizer_factory.rb', line 155

def OptimizerFactory.generate_steps_criterion(max_steps)
  lambda do |steps, results|
    steps >= max_steps
  end
end