gimuby 0.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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