gimuby 0.7.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -0
- data/LICENSE.md +25 -0
- data/README.md +0 -0
- data/lib/gimuby.rb +10 -0
- data/lib/gimuby/config.rb +39 -0
- data/lib/gimuby/dependencies.rb +37 -0
- data/lib/gimuby/event/event.rb +29 -0
- data/lib/gimuby/event/event_manager.rb +34 -0
- data/lib/gimuby/factory.rb +275 -0
- data/lib/gimuby/genetic/archipelago/archipelago.rb +305 -0
- data/lib/gimuby/genetic/archipelago/connect_strategy/barabasi_albert_connect_strategy.rb +77 -0
- data/lib/gimuby/genetic/archipelago/connect_strategy/circle_connect_strategy.rb +11 -0
- data/lib/gimuby/genetic/archipelago/connect_strategy/connect_strategy.rb +34 -0
- data/lib/gimuby/genetic/archipelago/connect_strategy/constant_degree_connect_strategy.rb +22 -0
- data/lib/gimuby/genetic/archipelago/connect_strategy/fully_connected_connect_strategy.rb +11 -0
- data/lib/gimuby/genetic/archipelago/connect_strategy/random_connect_strategy.rb +29 -0
- data/lib/gimuby/genetic/archipelago/connect_strategy/watts_strogatz_connect_strategy.rb +63 -0
- data/lib/gimuby/genetic/archipelago/measure/clustering_coefficient_measure.rb +92 -0
- data/lib/gimuby/genetic/archipelago/measure/connected_measure.rb +64 -0
- data/lib/gimuby/genetic/archipelago/measure/diameter_measure.rb +38 -0
- data/lib/gimuby/genetic/archipelago/measure/measure.rb +7 -0
- data/lib/gimuby/genetic/archipelago/measure/shortest_paths_measure.rb +46 -0
- data/lib/gimuby/genetic/population/pick_strategy/bests_pick_strategy.rb +17 -0
- data/lib/gimuby/genetic/population/pick_strategy/pick_strategy.rb +21 -0
- data/lib/gimuby/genetic/population/pick_strategy/random_wheel_pick_strategy.rb +40 -0
- data/lib/gimuby/genetic/population/pick_strategy/tournament_pick_strategy.rb +26 -0
- data/lib/gimuby/genetic/population/population.rb +97 -0
- data/lib/gimuby/genetic/population/replace_strategy/replace_strategy.rb +9 -0
- data/lib/gimuby/genetic/population/replace_strategy/replace_worst_replace_strategy.rb +52 -0
- data/lib/gimuby/genetic/population/replace_strategy/uniform_replace_strategy.rb +48 -0
- data/lib/gimuby/genetic/solution/check_strategy/check_strategy.rb +8 -0
- data/lib/gimuby/genetic/solution/check_strategy/permutation_check_strategy.rb +37 -0
- data/lib/gimuby/genetic/solution/check_strategy/solution_space_check_strategy.rb +74 -0
- data/lib/gimuby/genetic/solution/function_based_solution.rb +64 -0
- data/lib/gimuby/genetic/solution/mutation_strategy/mutation_strategy.rb +22 -0
- data/lib/gimuby/genetic/solution/mutation_strategy/permutation_mutation_strategy.rb +17 -0
- data/lib/gimuby/genetic/solution/mutation_strategy/solution_space_mutation_strategy.rb +69 -0
- data/lib/gimuby/genetic/solution/new_generation_strategy/average_new_generation_strategy.rb +41 -0
- data/lib/gimuby/genetic/solution/new_generation_strategy/combined_new_generation_strategy.rb +27 -0
- data/lib/gimuby/genetic/solution/new_generation_strategy/cross_over_new_generation_strategy.rb +40 -0
- data/lib/gimuby/genetic/solution/new_generation_strategy/new_generation_strategy.rb +9 -0
- data/lib/gimuby/genetic/solution/new_generation_strategy/parent_range_new_generation_strategy.rb +42 -0
- data/lib/gimuby/genetic/solution/solution.rb +86 -0
- data/lib/gimuby/problem/foxholes/foxholes.rb +76 -0
- data/lib/gimuby/problem/foxholes/foxholes_solution.rb +29 -0
- data/lib/gimuby/problem/lennard_jones/lennard_jones.rb +38 -0
- data/lib/gimuby/problem/lennard_jones/lennard_jones_solution.rb +62 -0
- data/lib/gimuby/problem/rastrigin/rastrigin.rb +26 -0
- data/lib/gimuby/problem/rastrigin/rastrigin_solution.rb +35 -0
- data/lib/gimuby/problem/rosenbrock/rosenbrock.rb +14 -0
- data/lib/gimuby/problem/rosenbrock/rosenbrock_solution.rb +39 -0
- data/lib/gimuby/problem/schaffer/schaffer.rb +18 -0
- data/lib/gimuby/problem/schaffer/schaffer_solution.rb +29 -0
- data/lib/gimuby/problem/sphere/sphere.rb +9 -0
- data/lib/gimuby/problem/sphere/sphere_solution.rb +27 -0
- data/lib/gimuby/problem/step/step.rb +9 -0
- data/lib/gimuby/problem/step/step_solution.rb +29 -0
- data/lib/gimuby/problem/tsp/tsp.rb +76 -0
- data/lib/gimuby/problem/tsp/tsp_solution.rb +46 -0
- 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
|
data/lib/gimuby/genetic/solution/new_generation_strategy/cross_over_new_generation_strategy.rb
ADDED
@@ -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
|
data/lib/gimuby/genetic/solution/new_generation_strategy/parent_range_new_generation_strategy.rb
ADDED
@@ -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
|