gimuby 0.7.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. data/Gemfile +1 -0
  2. data/LICENSE.md +25 -0
  3. data/README.md +0 -0
  4. data/lib/gimuby.rb +10 -0
  5. data/lib/gimuby/config.rb +39 -0
  6. data/lib/gimuby/dependencies.rb +37 -0
  7. data/lib/gimuby/event/event.rb +29 -0
  8. data/lib/gimuby/event/event_manager.rb +34 -0
  9. data/lib/gimuby/factory.rb +275 -0
  10. data/lib/gimuby/genetic/archipelago/archipelago.rb +305 -0
  11. data/lib/gimuby/genetic/archipelago/connect_strategy/barabasi_albert_connect_strategy.rb +77 -0
  12. data/lib/gimuby/genetic/archipelago/connect_strategy/circle_connect_strategy.rb +11 -0
  13. data/lib/gimuby/genetic/archipelago/connect_strategy/connect_strategy.rb +34 -0
  14. data/lib/gimuby/genetic/archipelago/connect_strategy/constant_degree_connect_strategy.rb +22 -0
  15. data/lib/gimuby/genetic/archipelago/connect_strategy/fully_connected_connect_strategy.rb +11 -0
  16. data/lib/gimuby/genetic/archipelago/connect_strategy/random_connect_strategy.rb +29 -0
  17. data/lib/gimuby/genetic/archipelago/connect_strategy/watts_strogatz_connect_strategy.rb +63 -0
  18. data/lib/gimuby/genetic/archipelago/measure/clustering_coefficient_measure.rb +92 -0
  19. data/lib/gimuby/genetic/archipelago/measure/connected_measure.rb +64 -0
  20. data/lib/gimuby/genetic/archipelago/measure/diameter_measure.rb +38 -0
  21. data/lib/gimuby/genetic/archipelago/measure/measure.rb +7 -0
  22. data/lib/gimuby/genetic/archipelago/measure/shortest_paths_measure.rb +46 -0
  23. data/lib/gimuby/genetic/population/pick_strategy/bests_pick_strategy.rb +17 -0
  24. data/lib/gimuby/genetic/population/pick_strategy/pick_strategy.rb +21 -0
  25. data/lib/gimuby/genetic/population/pick_strategy/random_wheel_pick_strategy.rb +40 -0
  26. data/lib/gimuby/genetic/population/pick_strategy/tournament_pick_strategy.rb +26 -0
  27. data/lib/gimuby/genetic/population/population.rb +97 -0
  28. data/lib/gimuby/genetic/population/replace_strategy/replace_strategy.rb +9 -0
  29. data/lib/gimuby/genetic/population/replace_strategy/replace_worst_replace_strategy.rb +52 -0
  30. data/lib/gimuby/genetic/population/replace_strategy/uniform_replace_strategy.rb +48 -0
  31. data/lib/gimuby/genetic/solution/check_strategy/check_strategy.rb +8 -0
  32. data/lib/gimuby/genetic/solution/check_strategy/permutation_check_strategy.rb +37 -0
  33. data/lib/gimuby/genetic/solution/check_strategy/solution_space_check_strategy.rb +74 -0
  34. data/lib/gimuby/genetic/solution/function_based_solution.rb +64 -0
  35. data/lib/gimuby/genetic/solution/mutation_strategy/mutation_strategy.rb +22 -0
  36. data/lib/gimuby/genetic/solution/mutation_strategy/permutation_mutation_strategy.rb +17 -0
  37. data/lib/gimuby/genetic/solution/mutation_strategy/solution_space_mutation_strategy.rb +69 -0
  38. data/lib/gimuby/genetic/solution/new_generation_strategy/average_new_generation_strategy.rb +41 -0
  39. data/lib/gimuby/genetic/solution/new_generation_strategy/combined_new_generation_strategy.rb +27 -0
  40. data/lib/gimuby/genetic/solution/new_generation_strategy/cross_over_new_generation_strategy.rb +40 -0
  41. data/lib/gimuby/genetic/solution/new_generation_strategy/new_generation_strategy.rb +9 -0
  42. data/lib/gimuby/genetic/solution/new_generation_strategy/parent_range_new_generation_strategy.rb +42 -0
  43. data/lib/gimuby/genetic/solution/solution.rb +86 -0
  44. data/lib/gimuby/problem/foxholes/foxholes.rb +76 -0
  45. data/lib/gimuby/problem/foxholes/foxholes_solution.rb +29 -0
  46. data/lib/gimuby/problem/lennard_jones/lennard_jones.rb +38 -0
  47. data/lib/gimuby/problem/lennard_jones/lennard_jones_solution.rb +62 -0
  48. data/lib/gimuby/problem/rastrigin/rastrigin.rb +26 -0
  49. data/lib/gimuby/problem/rastrigin/rastrigin_solution.rb +35 -0
  50. data/lib/gimuby/problem/rosenbrock/rosenbrock.rb +14 -0
  51. data/lib/gimuby/problem/rosenbrock/rosenbrock_solution.rb +39 -0
  52. data/lib/gimuby/problem/schaffer/schaffer.rb +18 -0
  53. data/lib/gimuby/problem/schaffer/schaffer_solution.rb +29 -0
  54. data/lib/gimuby/problem/sphere/sphere.rb +9 -0
  55. data/lib/gimuby/problem/sphere/sphere_solution.rb +27 -0
  56. data/lib/gimuby/problem/step/step.rb +9 -0
  57. data/lib/gimuby/problem/step/step_solution.rb +29 -0
  58. data/lib/gimuby/problem/tsp/tsp.rb +76 -0
  59. data/lib/gimuby/problem/tsp/tsp_solution.rb +46 -0
  60. metadata +128 -0
@@ -0,0 +1,97 @@
1
+ require 'gimuby/dependencies'
2
+ require 'gimuby/genetic/population/pick_strategy/random_wheel_pick_strategy'
3
+ require 'gimuby/genetic/population/replace_strategy/replace_worst_replace_strategy'
4
+
5
+ class Population
6
+
7
+ def initialize(solutions = nil)
8
+ if solutions.nil?
9
+ @solutions = []
10
+ else
11
+ @solutions = solutions
12
+ end
13
+ @pick_strategy ||= RandomWheelPickStrategy.new
14
+ @replace_strategy ||= ReplaceWorstReplaceStrategy.new
15
+
16
+ trigger(:on_population_init)
17
+ end
18
+
19
+ attr_reader :solutions
20
+ attr_accessor :pick_strategy
21
+ attr_accessor :selection_rate
22
+ attr_accessor :replace_strategy
23
+
24
+ # Run a step of genetic algorithm: reproduction + mutation
25
+ def generation_step
26
+ reproduce
27
+ @solutions.each do |solution|
28
+ solution.mutate
29
+ end
30
+ trigger(:on_population_generation_step)
31
+ end
32
+
33
+ # Replace part of the population (used by {Archipelago})
34
+ # @internal
35
+ def replace(solutions)
36
+ @solutions = @replace_strategy.replace(self, solutions)
37
+ end
38
+
39
+ # Simply pick some solutions and make them reproduce
40
+ # @internal
41
+ def reproduce
42
+ @solutions = @replace_strategy.replace(self)
43
+ end
44
+
45
+ # Pick some solutions
46
+ # @internal
47
+ def pick
48
+ @pick_strategy.pick(self)
49
+ end
50
+
51
+ # Add a solution
52
+ # @param solution [Solution]
53
+ def add_solution(solution)
54
+ @solutions.push solution
55
+ end
56
+
57
+ def get_population_size
58
+ @solutions.size
59
+ end
60
+
61
+ # Can be overridden
62
+ def get_fitness(solution)
63
+ solution.get_fitness
64
+ end
65
+
66
+ def get_average_fitness
67
+ sum = 0
68
+ @solutions.each do |solution|
69
+ sum += solution.get_fitness
70
+ end
71
+ # Beware of that division by 0
72
+ sum / @solutions.length
73
+ end
74
+
75
+ def get_best_fitness
76
+ best_solution = get_best_solution
77
+ best_solution.get_fitness
78
+ end
79
+
80
+ def get_best_solution
81
+ best_solution = @solutions.min_by do |solution|
82
+ solution.get_fitness
83
+ end
84
+ best_solution
85
+ end
86
+
87
+ protected
88
+
89
+ def trigger(event_type)
90
+ event_data = {:population => self}
91
+ get_event_manager.trigger_event(event_type, event_data)
92
+ end
93
+
94
+ def get_event_manager
95
+ $dependencies.event_manager
96
+ end
97
+ end
@@ -0,0 +1,9 @@
1
+ class ReplaceStrategy
2
+
3
+ # Replace solution within the population
4
+ # This function should call population.pick if selected is nil
5
+ def replace(population, selected = nil)
6
+ raise NotImplementedError
7
+ end
8
+
9
+ end
@@ -0,0 +1,52 @@
1
+ require 'gimuby/genetic/population/replace_strategy/replace_strategy'
2
+
3
+ class ReplaceWorstReplaceStrategy < ReplaceStrategy
4
+
5
+ def initialize
6
+ @replace_proportion = 50.to_f / 100.to_f
7
+ end
8
+
9
+ attr_accessor :replace_proportion
10
+
11
+ def replace(population, selected = nil)
12
+ solutions = population.solutions.clone
13
+
14
+ wished_length = solutions.length
15
+ solutions.sort! do |x, y|
16
+ x_fitness = population.get_fitness(x)
17
+ y_fitness = population.get_fitness(y)
18
+ x_fitness <=> y_fitness
19
+ end
20
+ if selected.nil?
21
+ selected = population.pick
22
+ end
23
+ number_to_remove = (wished_length * @replace_proportion).floor
24
+ if number_to_remove == wished_length
25
+ number_to_remove -= 1
26
+ end
27
+ solutions.slice!(-number_to_remove, number_to_remove)
28
+
29
+ while solutions.length < wished_length
30
+ begin
31
+ random_index1 = rand(selected.length)
32
+ random_index2 = rand(selected.length)
33
+ end while ((random_index1 == random_index2) && (selected.length != 1))
34
+ new_solutions = reproduce(selected[random_index1],
35
+ selected[random_index2])
36
+ new_solutions.each do |new_solution|
37
+ solutions.push(new_solution)
38
+ end
39
+ end
40
+
41
+ solutions.slice!(wished_length) # we could have one that should be dropped
42
+ solutions
43
+ end
44
+
45
+ protected
46
+
47
+ def reproduce(solution1, solution2)
48
+ solution1.reproduce(solution1, solution2)
49
+ end
50
+
51
+
52
+ end
@@ -0,0 +1,48 @@
1
+ require 'gimuby/genetic/population/replace_strategy/replace_strategy'
2
+
3
+ class UniformReplaceStrategy < ReplaceStrategy
4
+
5
+ def initialize
6
+ @replace_proportion = 50.to_f / 100.to_f
7
+ end
8
+
9
+ attr_accessor :replace_proportion
10
+
11
+ def replace(population, selected = nil)
12
+ solutions = population.solutions.clone
13
+
14
+ wished_length = solutions.length
15
+ solutions.shuffle!
16
+ if selected.nil?
17
+ selected = population.pick
18
+ end
19
+ number_to_remove = (wished_length * @replace_proportion).floor
20
+ if number_to_remove == wished_length
21
+ number_to_remove -= 1
22
+ end
23
+ solutions.slice!(-number_to_remove, number_to_remove)
24
+
25
+ while solutions.length < wished_length
26
+ begin
27
+ random_index1 = rand(selected.length)
28
+ random_index2 = rand(selected.length)
29
+ end while ((random_index1 == random_index2) && (selected.length != 1))
30
+ new_solutions = reproduce(selected[random_index1],
31
+ selected[random_index2])
32
+ new_solutions.each do |new_solution|
33
+ solutions.push(new_solution)
34
+ end
35
+ end
36
+
37
+ solutions.slice!(wished_length) # we could have one that should be dropped
38
+ solutions
39
+ end
40
+
41
+ protected
42
+
43
+ def reproduce(solution1, solution2)
44
+ solution1.reproduce(solution1, solution2)
45
+ end
46
+
47
+
48
+ end
@@ -0,0 +1,8 @@
1
+
2
+ class CheckStrategy
3
+
4
+ def check(solution_representation)
5
+ raise NotImplementedError
6
+ end
7
+
8
+ end
@@ -0,0 +1,37 @@
1
+ require 'gimuby/genetic/solution/check_strategy/check_strategy'
2
+
3
+ #
4
+ # Permutation goes represented as permutation from [0, ... l] indexes
5
+ class PermutationCheckStrategy < CheckStrategy
6
+
7
+ def check(solution_representation)
8
+ permutation = solution_representation
9
+ expected_elements = *(0..permutation.length - 1)
10
+ duplicate = []
11
+ missing = []
12
+ expected_elements.each do |element|
13
+ match = permutation.select do |concreteElement|
14
+ concreteElement == element
15
+ end
16
+ case match.length <=> 1
17
+ when -1 then
18
+ missing.push(element)
19
+ when 1 then
20
+ duplicate.push(element)
21
+ else
22
+ # do nothing
23
+ end
24
+ end
25
+ missing.shuffle!
26
+ duplicate.each do |to_remove|
27
+ to_insert = missing.pop()
28
+ ind = permutation.index(to_remove)
29
+ permutation[ind] = to_insert
30
+ end
31
+ unless missing.empty?
32
+ solution_representation = check(solution_representation)
33
+ end
34
+ solution_representation
35
+ end
36
+
37
+ end
@@ -0,0 +1,74 @@
1
+ require 'gimuby/genetic/solution/check_strategy/check_strategy'
2
+
3
+ # Permutation goes represented as permutation from [0, ... l] indexes
4
+ class SolutionSpaceCheckStrategy < CheckStrategy
5
+
6
+ def initialize
7
+ @default_min = nil
8
+ @default_max = nil
9
+ @mins = {}
10
+ @maxs = {}
11
+ end
12
+
13
+ def check(solution_representation)
14
+ solution_representation.each_index do |index|
15
+ value = solution_representation[index]
16
+
17
+ if value.class == Array
18
+ value = check(value)
19
+ else
20
+ min = get_min(index)
21
+ unless min.nil?
22
+ if value < min
23
+ value = min
24
+ end
25
+ end
26
+
27
+ max = get_max(index)
28
+ unless max.nil?
29
+ if value > max
30
+ value = max
31
+ end
32
+ end
33
+ end
34
+
35
+ solution_representation[index] = value
36
+ end
37
+
38
+ solution_representation
39
+ end
40
+
41
+ def set_min(min, index = nil)
42
+ if index.nil?
43
+ @default_min = min
44
+ else
45
+ @mins[index] = min
46
+ end
47
+ end
48
+
49
+ def set_max(max, index = nil)
50
+ if index.nil?
51
+ @default_max = max
52
+ else
53
+ @maxs[index] = max
54
+ end
55
+ end
56
+
57
+ protected
58
+
59
+ def get_min(index)
60
+ min = @default_min
61
+ if @mins.has_key?(index)
62
+ min = @mins[index]
63
+ end
64
+ min
65
+ end
66
+
67
+ def get_max(index)
68
+ max = @default_max
69
+ if @maxs.has_key?(index)
70
+ max = @maxs[index]
71
+ end
72
+ max
73
+ end
74
+ end
@@ -0,0 +1,64 @@
1
+ require 'gimuby/genetic/solution/solution'
2
+ require 'gimuby/genetic/solution/check_strategy/solution_space_check_strategy'
3
+ require 'gimuby/genetic/solution/new_generation_strategy/combined_new_generation_strategy'
4
+ require 'gimuby/genetic/solution/new_generation_strategy/parent_range_new_generation_strategy'
5
+ require 'gimuby/genetic/solution/new_generation_strategy/cross_over_new_generation_strategy'
6
+ require 'gimuby/genetic/solution/new_generation_strategy/average_new_generation_strategy'
7
+ require 'gimuby/genetic/solution/mutation_strategy/solution_space_mutation_strategy'
8
+
9
+ class FunctionBasedSolution < Solution
10
+
11
+ def initialize(x_values = nil)
12
+ super(x_values)
13
+
14
+ @check_strategy = SolutionSpaceCheckStrategy.new
15
+ @check_strategy.set_min(get_x_value_min)
16
+ @check_strategy.set_max(get_x_value_max)
17
+
18
+ @new_generation_strategy = CombinedNewGenerationStrategy.new
19
+ @new_generation_strategy.add_strategy(ParentRangeNewGenerationStrategy.new)
20
+ @new_generation_strategy.add_strategy(CrossOverNewGenerationStrategy.new)
21
+ @new_generation_strategy.add_strategy(AverageNewGenerationStrategy.new)
22
+
23
+ @mutation_strategy = SolutionSpaceMutationStrategy.new
24
+ @mutation_strategy.set_min(get_x_value_min)
25
+ @mutation_strategy.set_max(get_x_value_max)
26
+ end
27
+
28
+ def evaluate
29
+ raise NotImplementedError
30
+ end
31
+
32
+ def get_solution_representation
33
+ @x_values.clone
34
+ end
35
+
36
+ def set_solution_representation(x_values)
37
+ @x_values = x_values.clone
38
+ end
39
+
40
+ protected
41
+
42
+ def init_representation
43
+ @x_values = []
44
+ dimension = get_dimension_number
45
+ dimension.times do |_|
46
+ range = get_x_value_max - get_x_value_min
47
+ x_value = (rand() * range) + get_x_value_min
48
+ @x_values.push(x_value)
49
+ end
50
+ end
51
+
52
+ def get_x_value_min
53
+ raise NotImplementedError
54
+ end
55
+
56
+ def get_x_value_max
57
+ raise NotImplementedError
58
+ end
59
+
60
+ def get_dimension_number
61
+ raise NotImplementedError
62
+ end
63
+
64
+ end
@@ -0,0 +1,22 @@
1
+
2
+
3
+ class MutationStrategy
4
+
5
+ def initialize(mutation_rate = 0.01)
6
+ @mutation_rate = mutation_rate
7
+ end
8
+
9
+ attr_accessor :mutation_rate
10
+
11
+ def mutate(solution)
12
+ if rand < @mutation_rate
13
+ perform_mutation(solution)
14
+ solution.reset_fitness_state
15
+ end
16
+ end
17
+
18
+ def perform_mutation(solution)
19
+ raise NotImplementedError
20
+ end
21
+
22
+ end
@@ -0,0 +1,17 @@
1
+ require 'gimuby/genetic/solution/mutation_strategy/mutation_strategy'
2
+
3
+ class PermutationMutationStrategy < MutationStrategy
4
+
5
+ def perform_mutation(solution)
6
+ permutation = solution.get_solution_representation
7
+ begin
8
+ index1 = rand(permutation.length)
9
+ index2 = rand(permutation.length)
10
+ end while index1 == index2
11
+ tmp = permutation[index1]
12
+ permutation[index1] = permutation[index2]
13
+ permutation[index2] = tmp
14
+ solution.set_solution_representation(permutation)
15
+ end
16
+
17
+ end
@@ -0,0 +1,69 @@
1
+ require 'gimuby/genetic/solution/mutation_strategy/mutation_strategy'
2
+
3
+ class SolutionSpaceMutationStrategy < MutationStrategy
4
+
5
+ def initialize(mutation_rate = 0.01)
6
+ super(mutation_rate)
7
+ @default_min = nil
8
+ @default_max = nil
9
+ @mins = {}
10
+ @maxs = {}
11
+ end
12
+
13
+ def perform_mutation(solution)
14
+ x_values = solution.get_solution_representation
15
+ x_values = perform_mutation_from_representation(x_values)
16
+ solution.set_solution_representation(x_values)
17
+ end
18
+
19
+ def set_min(min, index = nil)
20
+ if index.nil?
21
+ @default_min = min
22
+ else
23
+ @mins[index] = min
24
+ end
25
+ end
26
+
27
+ def set_max(max, index = nil)
28
+ if index.nil?
29
+ @default_max = max
30
+ else
31
+ @maxs[index] = max
32
+ end
33
+ end
34
+
35
+ protected
36
+
37
+ def perform_mutation_from_representation(x_values)
38
+ index = rand(x_values.length)
39
+
40
+ x_value = x_values[index]
41
+ if x_value.class == Array
42
+ x_value = perform_mutation_from_representation(x_value)
43
+ else
44
+ min = get_min(index)
45
+ max = get_max(index)
46
+ range = max - min
47
+ x_value = rand() * range + min
48
+ end
49
+ x_values[index] = x_value
50
+ x_values
51
+ end
52
+
53
+ def get_min(index)
54
+ min = @default_min
55
+ if @mins.has_key?(index)
56
+ min = @mins[index]
57
+ end
58
+ min
59
+ end
60
+
61
+ def get_max(index)
62
+ max = @default_max
63
+ if @maxs.has_key?(index)
64
+ max = @maxs[index]
65
+ end
66
+ max
67
+ end
68
+
69
+ end