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,41 @@
1
+ require 'gimuby/genetic/solution/new_generation_strategy/new_generation_strategy'
2
+
3
+ class AverageNewGenerationStrategy < NewGenerationStrategy
4
+
5
+ # @param best_weight {Float} The weight given to the best solution
6
+ def initialize(best_weight = 1.0)
7
+ @best_weight = best_weight
8
+ end
9
+
10
+ def reproduce(solution1, solution2)
11
+ weight1 = 1.0
12
+ weight2 = 1.0
13
+ if solution1.get_fitness < solution2.get_fitness
14
+ weight1 = @best_weight
15
+ else
16
+ weight2 = @best_weight
17
+ end
18
+ x_values1 = solution1.get_solution_representation
19
+ x_values2 = solution2.get_solution_representation
20
+ reproduce_from_representation(x_values1, x_values2, weight1, weight2)
21
+ end
22
+
23
+ protected
24
+
25
+ def reproduce_from_representation(x_values1, x_values2, weight1, weight2)
26
+ x_values = []
27
+ x_values1.each_index do |i|
28
+ x_value1 = x_values1[i]
29
+ x_value2 = x_values2[i]
30
+ if x_value1.class == Array
31
+ x_value = reproduce_from_representation(x_value1, x_value2, weight1, weight2).pop()
32
+ else
33
+ x_value = x_value1 * weight1 + x_value2 * weight2
34
+ x_value /= (weight1 + weight2)
35
+ end
36
+ x_values.push(x_value)
37
+ end
38
+ [x_values]
39
+ end
40
+
41
+ end
@@ -0,0 +1,27 @@
1
+ require 'gimuby/genetic/solution/new_generation_strategy/new_generation_strategy'
2
+
3
+ # This class pick randomly between strategies to implement more
4
+ # mitigated new generation strategy
5
+ class CombinedNewGenerationStrategy < NewGenerationStrategy
6
+
7
+ def initialize
8
+ @strategies = []
9
+ end
10
+
11
+ def reproduce(solution1, solution2)
12
+ strategy = get_concrete_strategy
13
+ strategy.reproduce(solution1, solution2)
14
+ end
15
+
16
+ # Add a strategy in the handled strategy of the system
17
+ # @param strategy {NewGenerationStrategy}
18
+ def add_strategy(strategy)
19
+ @strategies.push(strategy)
20
+ end
21
+
22
+ protected
23
+
24
+ def get_concrete_strategy
25
+ @strategies.choice
26
+ end
27
+ end
@@ -0,0 +1,40 @@
1
+ require 'gimuby/genetic/solution/new_generation_strategy/new_generation_strategy'
2
+
3
+ class CrossOverNewGenerationStrategy < NewGenerationStrategy
4
+
5
+ def initialize(cross_overs_number = 1)
6
+ @cross_overs_number = cross_overs_number
7
+ end
8
+
9
+ def reproduce(solution1, solution2)
10
+ permutation1 = solution1.get_solution_representation
11
+ permutation2 = solution2.get_solution_representation
12
+ cross_overs_number = @cross_overs_number
13
+ if cross_overs_number <= 0
14
+ cross_overs_number = permutation1.length - cross_overs_number
15
+ end
16
+ cross_overs_number.times do |_|
17
+ r = reproduce_step(permutation1, permutation2)
18
+ permutation1 = r.shift
19
+ permutation2 = r.shift
20
+ end
21
+ [permutation1, permutation2]
22
+ end
23
+
24
+ protected
25
+
26
+ def reproduce_step(permutation1, permutation2)
27
+ random_index = rand(permutation1.length)
28
+ if random_index == permutation1.length - 1
29
+ new_permutation1 = permutation1.clone()
30
+ new_permutation2 = permutation2.clone()
31
+ else
32
+ new_permutation1 = permutation1[0..random_index] +
33
+ permutation2[random_index + 1..-1]
34
+ new_permutation2 = permutation2[0..random_index] +
35
+ permutation1[random_index + 1..-1]
36
+ end
37
+ [new_permutation1, new_permutation2]
38
+ end
39
+
40
+ end
@@ -0,0 +1,9 @@
1
+
2
+ class NewGenerationStrategy
3
+
4
+ # Output an array of solution representations
5
+ def reproduce(solution1, solution2)
6
+ raise NotImplementedError
7
+ end
8
+
9
+ end
@@ -0,0 +1,42 @@
1
+ require 'gimuby/genetic/solution/new_generation_strategy/new_generation_strategy'
2
+
3
+
4
+ class ParentRangeNewGenerationStrategy < NewGenerationStrategy
5
+
6
+ def initialize(widen_range_ratio = 1.10)
7
+ @widen_range_ratio = widen_range_ratio
8
+ end
9
+
10
+ def reproduce(solution1, solution2)
11
+ x_values1 = solution1.get_solution_representation
12
+ x_values2 = solution2.get_solution_representation
13
+ reproduce_from_representation(x_values1, x_values2)
14
+ end
15
+
16
+ protected
17
+
18
+ def reproduce_from_representation(x_values1, x_values2)
19
+ new_values = []
20
+ x_values1.each_index do |i|
21
+ x_value1 = x_values1[i]
22
+ x_value2 = x_values2[i]
23
+ if x_value1.class == Array
24
+ new_x_value = reproduce_from_representation(x_value1, x_value2).pop
25
+ else
26
+ new_x_value = rand_in([x_value1, x_value2])
27
+ end
28
+ new_values.push(new_x_value)
29
+ end
30
+ [new_values]
31
+ end
32
+
33
+ def rand_in(values)
34
+ min = values.min
35
+ max = values.max
36
+ range = max - min
37
+ delta_range = range * @widen_range_ratio
38
+ range += delta_range
39
+ (rand() * range) + (min - delta_range / 2)
40
+ end
41
+
42
+ end
@@ -0,0 +1,86 @@
1
+ #!/usr/bin/env ruby
2
+ require 'gimuby/config'
3
+ require 'gimuby/dependencies'
4
+
5
+ # Base class for solutions, extended by each given problem
6
+ class Solution
7
+
8
+ def initialize(representation = nil)
9
+ @fitness = nil
10
+
11
+ @check_strategy ||= nil
12
+ @new_generation_strategy ||= nil
13
+ @mutation_strategy ||= nil
14
+
15
+ if representation.nil?
16
+ init_representation
17
+ else
18
+ set_solution_representation(representation)
19
+ end
20
+ end
21
+
22
+ attr_accessor :check_strategy
23
+ attr_accessor :new_generation_strategy
24
+ attr_accessor :mutation_strategy
25
+
26
+ # @return [Float]
27
+ def get_fitness
28
+ unless has_fitness?
29
+ @fitness = evaluate
30
+ event_data = {:solution => self}
31
+ get_event_manager.trigger_event(:on_solution_needs_evaluation, event_data)
32
+ end
33
+ @fitness
34
+ end
35
+
36
+ def reset_fitness_state
37
+ @fitness = nil
38
+ end
39
+
40
+ def mutate
41
+ @mutation_strategy.mutate(self)
42
+ end
43
+
44
+ def reproduce(sol1, sol2)
45
+ new_solutions_representations = @new_generation_strategy.reproduce(sol1, sol2)
46
+ new_solutions_representations.map do |representation|
47
+ solution = self.class.new(representation)
48
+ solution.check
49
+ solution.mutation_strategy = sol1.mutation_strategy
50
+ solution.check_strategy = sol1.check_strategy
51
+ solution.new_generation_strategy = sol1.new_generation_strategy
52
+ solution
53
+ end
54
+ end
55
+
56
+ def get_solution_representation
57
+ raise NotImplementedError
58
+ end
59
+
60
+ def set_solution_representation(representation)
61
+ raise NotImplementedError
62
+ end
63
+
64
+ protected
65
+
66
+ def init_representation
67
+ raise NotImplementedError
68
+ end
69
+
70
+ def has_fitness?
71
+ not @fitness.nil?
72
+ end
73
+
74
+ def evaluate
75
+ raise NotImplementedError
76
+ end
77
+
78
+ def check
79
+ checked_representation = @check_strategy.check(get_solution_representation)
80
+ set_solution_representation(checked_representation)
81
+ end
82
+
83
+ def get_event_manager
84
+ $dependencies.event_manager
85
+ end
86
+ end
@@ -0,0 +1,76 @@
1
+ require 'gimuby/config'
2
+
3
+ # Implementation according to
4
+ # http://www.sfu.ca/~ssurjano/shekel.html
5
+ # http://www.zsd.ict.pwr.wroc.pl/files/docs/functions.pdf
6
+ #
7
+ class Foxholes
8
+
9
+ @@x_value_min = -65536
10
+ @@x_value_max = 65536
11
+
12
+ def initialize
13
+ ensure_holes_coordinates
14
+ end
15
+
16
+ def evaluate(x_values)
17
+ sum = 0.0
18
+ get_number_holes.times do |j|
19
+ hole_coordinate = @holes_coordinates[j]
20
+ sub_sum = 0.10
21
+ hole_coordinate.each_index do |i|
22
+ sub_sum += (x_values[i].to_f - hole_coordinate[i]) ** 2
23
+ end
24
+ sum += 1.0 / sub_sum
25
+ end
26
+ sum
27
+ end
28
+
29
+ protected
30
+
31
+ def get_number_holes
32
+ 25
33
+ end
34
+
35
+ def get_holes_coordinates
36
+ @holes_coordinates
37
+ end
38
+
39
+ def ensure_holes_coordinates
40
+ path = $config.persistence_dir_path + '/foxholes_holes_coordinates_' +
41
+ get_number_holes.to_s + '.data'
42
+ load_holes_coordinates(path)
43
+ if @holes_coordinates.nil?
44
+ init_holes_coordinates
45
+ persist_holes_coordinates(path)
46
+ end
47
+ end
48
+
49
+ def load_holes_coordinates(path)
50
+ if File::exists? path
51
+ f = File.new(path, 'r')
52
+ @holes_coordinates = Marshal.load(f.read())
53
+ f.close()
54
+ end
55
+ end
56
+
57
+ def persist_holes_coordinates(path)
58
+ f = File.new(path, 'w')
59
+ f.write(Marshal.dump(@holes_coordinates))
60
+ f.close()
61
+ end
62
+
63
+ def init_holes_coordinates
64
+ @holes_coordinates = []
65
+ get_number_holes.times do |_|
66
+ @holes_coordinates.push(get_random_coordinates)
67
+ end
68
+ end
69
+
70
+ def get_random_coordinates
71
+ scale = @@x_value_max - @@x_value_min
72
+ x = rand() * scale + @@x_value_min
73
+ y = rand() * scale + @@x_value_min
74
+ [x, y]
75
+ end
76
+ end
@@ -0,0 +1,29 @@
1
+ require 'gimuby/dependencies'
2
+ require 'gimuby/config'
3
+ require 'gimuby/genetic/solution/function_based_solution'
4
+
5
+ class FoxholesSolution < FunctionBasedSolution
6
+
7
+ def evaluate
8
+ get_foxholes.evaluate(@x_values.clone)
9
+ end
10
+
11
+ protected
12
+
13
+ def get_x_value_min
14
+ -65536
15
+ end
16
+
17
+ def get_x_value_max
18
+ 65536
19
+ end
20
+
21
+ def get_dimension_number
22
+ 2
23
+ end
24
+
25
+ def get_foxholes
26
+ # load through dependency
27
+ $dependencies.foxholes
28
+ end
29
+ end
@@ -0,0 +1,38 @@
1
+
2
+
3
+ class LennardJones
4
+
5
+ def initialize
6
+ @sigma = 1
7
+ end
8
+
9
+ # @param atoms_positions {Array}
10
+ def evaluate(atoms_positions)
11
+ number = atoms_positions.length
12
+ potential = 0.0
13
+ (number - 1).times do |i|
14
+ atom_position_i = atoms_positions[i]
15
+ target_indices = *(i+1..number-1)
16
+ target_indices = [target_indices] unless target_indices.class == Array
17
+ target_indices.each do |j|
18
+ atom_position_j = atoms_positions[j]
19
+ distance = get_euclidian_distance(atom_position_i, atom_position_j)
20
+ if distance != 0
21
+ potential += (@sigma / distance) ** 12
22
+ potential -= (@sigma / distance) ** 6
23
+ end
24
+ end
25
+ end
26
+ potential * 4
27
+ end
28
+
29
+ protected
30
+
31
+ def get_euclidian_distance(atom_position1, atom_position2)
32
+ distance = 0.0
33
+ atom_position1.each_index do |k|
34
+ distance += (atom_position1[k] - atom_position2[k]) ** 2
35
+ end
36
+ Math.sqrt(distance)
37
+ end
38
+ end
@@ -0,0 +1,62 @@
1
+ require 'gimuby/config'
2
+ require 'gimuby/problem/lennard_jones/lennard_jones'
3
+ require 'gimuby/genetic/solution/solution'
4
+
5
+ class LennardJonesSolution < Solution
6
+
7
+ @@positions_dimensions = 3
8
+ @@position_dimension_min = -3.0
9
+ @@position_dimension_max = 3.0
10
+
11
+ def initialize(atoms_positions = nil)
12
+ super(atoms_positions)
13
+
14
+ @check_strategy = SolutionSpaceCheckStrategy.new
15
+ @check_strategy.set_min(@@position_dimension_min)
16
+ @check_strategy.set_max(@@position_dimension_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
+
22
+ @mutation_strategy = SolutionSpaceMutationStrategy.new
23
+ @mutation_strategy.set_min(@@position_dimension_min)
24
+ @mutation_strategy.set_max(@@position_dimension_max)
25
+ end
26
+
27
+ def evaluate
28
+ get_lennard_jones.evaluate(get_solution_representation)
29
+ end
30
+
31
+ def get_solution_representation
32
+ @atoms_positions.clone
33
+ end
34
+
35
+ def set_solution_representation(atoms_positions)
36
+ @atoms_positions = atoms_positions.clone
37
+ #@atoms_positions = @atoms_positions.sort_by do |atom_position|
38
+ # atom_position[0]
39
+ #end
40
+ end
41
+
42
+ protected
43
+
44
+ def init_representation
45
+ @atoms_positions = []
46
+ atoms_number = $config.lennard_jones_atoms
47
+ atoms_number.times do
48
+ atom_position = []
49
+ @@positions_dimensions.times do
50
+ position_dimension_range = (@@position_dimension_max - @@position_dimension_min)
51
+ position_dimension = (rand * position_dimension_range) + @@position_dimension_min
52
+ atom_position.push(position_dimension)
53
+ end
54
+ @atoms_positions.push(atom_position)
55
+ end
56
+ end
57
+
58
+ def get_lennard_jones
59
+ LennardJones.new
60
+ end
61
+
62
+ end