metaheuristic_algorithms 0.1.3 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3dd2ffc0aa34514ddb6b911b08301698c1651fff
4
- data.tar.gz: 7cb81d28bee88c63d10ed5835b3f762b0a89728b
3
+ metadata.gz: 27858264b3ec8d6e8f908c77b72aaf02bb4fe520
4
+ data.tar.gz: 7f4fd083bb8a261f2ac48f8e50d7df18a714b28b
5
5
  SHA512:
6
- metadata.gz: b2c0db5f019af8720c407ff8ab1d8859041baa8bd9293a822734edc8892d56423dd6204798f565b7031d76fdf5ce882088f92fc7188444742afb1039ae907001
7
- data.tar.gz: 15f10112749131b6e775385228c8985207017ebe13550380c67b06b194940e746566c68fbb14e0a803767ed04c896b39f01e67152008403f19fe62da3d80673e
6
+ metadata.gz: 943a04193e2133c5cdc2aac48d5f1d6dddf5184363f6f38cd62e4d5d88abbf5f042a1935f4c92b4cf02e69823206e3492ed9d4acb31fd67d58bc07658096235b
7
+ data.tar.gz: 3a7ded6b05592213c574a06ed2019c7a5524f39e99723f0f12f27859b4b132088e3455740dbc861f84276e73a93a56fed338f1bcb30efaef4c73ae9a8da8e65f
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.2.2
1
+ 2.2.3
data/Gemfile CHANGED
@@ -2,3 +2,5 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in metaheuristic_algorithms.gemspec
4
4
  gemspec
5
+
6
+ gem "pry-byebug", group: [:development, :test], platforms: :ruby # In order to exclude jruby
data/README.md CHANGED
@@ -18,6 +18,32 @@ Or install it yourself as:
18
18
 
19
19
  $ gem install metaheuristic_algorithms
20
20
 
21
+ ## Supported Platforms
22
+
23
+ * MRI Ruby 2.2 or above.
24
+
25
+ * JRuby 9.0.0.0 or above. (In an attempt to have better speed, if not fast.)
26
+
27
+ ## Available Algorithms
28
+
29
+ In alphabetical order:
30
+
31
+ * Firefly Algorithm
32
+ MetaheuristicAlgorithms::FireflyAlgorithm
33
+ * Genetic Algorithm
34
+ MetaheuristicAlgorithms::GeneticAlgorithm
35
+ * Harmony Search
36
+ MetaheuristicAlgorithms::HarmonySearch
37
+ * Simplified Particle Swarm Optimization
38
+ MetaheuristicAlgorithms::SimplifiedParticleSwarmOptimization
39
+ * Simulated Annealing
40
+ MetaheuristicAlgorithms::SimulatedAnnealing
41
+
42
+ Algorithms under construction:
43
+
44
+ * Ant Colony Optimization
45
+ * Virtual Bee Algorithm
46
+
21
47
  ## Usage
22
48
 
23
49
  Step 1. Create a Function Wrapper for your objective function by extending MetaheuristicAlgorithms::FunctionWrappers::AbstractWrapper
@@ -26,25 +52,24 @@ Step 1. Create a Function Wrapper for your objective function by extending Metah
26
52
 
27
53
  ```ruby
28
54
  require 'metaheuristic_algorithms'
29
- require 'bigdecimal'
30
55
 
31
56
  class RosenbrookFunctionWrapper < MetaheuristicAlgorithms::FunctionWrappers::AbstractWrapper
32
57
 
33
58
  def maximum_decision_variable_values
34
- [BigDecimal('5'), BigDecimal('5')]
59
+ [5, 5]
35
60
  end
36
61
 
37
62
  def miminum_decision_variable_values
38
- [BigDecimal('-5'), BigDecimal('-5')]
63
+ [-5, -5]
39
64
  end
40
65
 
41
66
  def objective_function_value(decision_variable_values)
42
- (BigDecimal('1') - decision_variable_values[0]).power(2) + BigDecimal('100') * (decision_variable_values[1] - decision_variable_values[0].power(2)).power(2)
67
+ (1 - decision_variable_values[0])**2 + 100 * (decision_variable_values[1] - decision_variable_values[0]**2)**2
43
68
  end
44
69
 
45
70
  # For the algorithm that requires initial estimate that is depending on the particular objective function:
46
71
  def initial_decision_variable_value_estimates
47
- [BigDecimal('2'), BigDecimal('2')]
72
+ [2, 2]
48
73
  end
49
74
 
50
75
  end
@@ -58,25 +83,24 @@ Step 2. Instantiate the created Function Wrapper and pass it as the first argume
58
83
 
59
84
  ```ruby
60
85
  require 'metaheuristic_algorithms'
61
- require 'bigdecimal'
62
86
 
63
87
  rosenbrook_function_wrapper = RosenbrookFunctionWrapper.new
64
88
 
65
89
  harmony_search = MetaheuristicAlgorithms::HarmonySearch.new(rosenbrook_function_wrapper, number_of_variables: 2, objective: :minimization)
66
90
 
67
91
  maximum_attempt = 25000
68
- pitch_adjusting_range = BigDecimal('100')
92
+ pitch_adjusting_range = 100
69
93
  harmony_search_size = 20
70
- harmony_memory_acceping_rate = BigDecimal('0.95')
71
- pitch_adjusting_rate = BigDecimal('0.7')
94
+ harmony_memory_acceping_rate = 0.95
95
+ pitch_adjusting_rate = 0.7
72
96
 
73
97
  result = harmony_search.search(maximum_attempt: maximum_attempt, pitch_adjusting_range: pitch_adjusting_range,
74
98
  harmony_search_size: harmony_search_size, harmony_memory_acceping_rate: harmony_memory_acceping_rate,
75
99
  pitch_adjusting_rate: pitch_adjusting_rate)
76
100
 
77
- puts result[:best_decision_variable_values][0] # x value: Example: BigDecimal('1.0112')
78
- puts result[:best_decision_variable_values][1] # y value: Example: BigDecimal('0.9988')
79
- puts result[:best_objective_function_value] # f(x,y) value: Example: BigDecimal('0.0563')
101
+ puts result[:best_decision_variable_values][0] # x value: Example: 1.0112
102
+ puts result[:best_decision_variable_values][1] # y value: Example: 0.9988
103
+ puts result[:best_objective_function_value] # f(x,y) value: Example: 0.0563
80
104
  ```
81
105
 
82
106
  ## Development
@@ -87,7 +111,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
87
111
 
88
112
  ## Contributing
89
113
 
90
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/metaheuristic_algorithms. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
114
+ Bug reports and pull requests are welcome on GitHub at https://github.com/tadatoshi/metaheuristic_algorithms. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
91
115
 
92
116
 
93
117
  ## License
@@ -3,10 +3,23 @@ module MetaheuristicAlgorithms
3
3
  module BaseAlgorithmModule
4
4
 
5
5
  def get_decision_variable_value_by_randomization(decision_variable_index)
6
+ # @function_wrapper.miminum_decision_variable_values[decision_variable_index]
7
+ # + (@function_wrapper.maximum_decision_variable_values[decision_variable_index] - @function_wrapper.miminum_decision_variable_values[decision_variable_index]) * bigdecimal_rand
6
8
  @function_wrapper.miminum_decision_variable_values[decision_variable_index]
7
- + (@function_wrapper.maximum_decision_variable_values[decision_variable_index] - @function_wrapper.miminum_decision_variable_values[decision_variable_index]) * bigdecimal_rand
9
+ + (@function_wrapper.maximum_decision_variable_values[decision_variable_index] - @function_wrapper.miminum_decision_variable_values[decision_variable_index]) * rand
8
10
  end
9
11
 
12
+ # Based on the code by antonakos on http://stackoverflow.com/questions/5825680/code-to-generate-gaussian-normally-distributed-random-numbers-in-ruby
13
+ # His code is under CC0 1.0 Universal (CC0 1.0)
14
+ def gaussian(mean, stddev)
15
+ theta = 2 * Math::PI * Kernel.rand
16
+ rho = Math.sqrt(-2 * Math.log(1 - Kernel.rand))
17
+ scale = stddev * rho
18
+ x = mean + scale * Math.cos(theta)
19
+ # y = mean + scale * Math.sin(theta)
20
+ return x
21
+ end
22
+
10
23
  end
11
24
 
12
25
  end
@@ -1,13 +1,17 @@
1
+ require 'bigdecimal'
2
+
1
3
  module MetaheuristicAlgorithms
2
4
 
3
5
  module CalculationHelper
4
6
 
5
7
  def degree_to_radian(degree)
6
- degree * BigDecimal(Math::PI.to_s) / BigDecimal('180')
8
+ # degree * BigDecimal(Math::PI.to_s) / BigDecimal('180')
9
+ degree * Math::PI / 180
7
10
  end
8
11
 
9
12
  def radian_to_degree(radian)
10
- radian * BigDecimal('180') / BigDecimal(Math::PI.to_s)
13
+ # radian * BigDecimal('180') / BigDecimal(Math::PI.to_s)
14
+ radian * 180 / Math::PI
11
15
  end
12
16
 
13
17
  def bigdecimal_exp(bigdecimal_value)
@@ -1,5 +1,5 @@
1
- require 'bigdecimal'
2
- require 'bigdecimal/math'
1
+ # require 'bigdecimal'
2
+ # require 'bigdecimal/math'
3
3
 
4
4
  module MetaheuristicAlgorithms
5
5
 
@@ -42,17 +42,19 @@ module MetaheuristicAlgorithms
42
42
  end
43
43
  end
44
44
 
45
- def search(number_of_fireflies: 10, maximun_generation: 10, randomization_parameter_alpha: BigDecimal('0.2'), absorption_coefficient_gamma: BigDecimal('1.0'))
45
+ # def search(number_of_fireflies: 10, maximun_generation: 10, randomization_parameter_alpha: BigDecimal('0.2'), absorption_coefficient_gamma: BigDecimal('1.0'))
46
+ def search(number_of_fireflies: 10, maximun_generation: 10, randomization_parameter_alpha: 0.2, absorption_coefficient_gamma: 1.0)
46
47
 
47
48
  number_of_fireflies = number_of_fireflies.to_i unless number_of_fireflies.kind_of?(Integer)
48
49
  maximun_generation = maximun_generation.to_i unless maximun_generation.kind_of?(Integer)
49
- randomization_parameter_alpha = BigDecimal(randomization_parameter_alpha.to_s) unless randomization_parameter_alpha.kind_of?(BigDecimal)
50
- absorption_coefficient_gamma = BigDecimal(absorption_coefficient_gamma.to_s) unless absorption_coefficient_gamma.kind_of?(BigDecimal)
50
+ # randomization_parameter_alpha = BigDecimal(randomization_parameter_alpha.to_s) unless randomization_parameter_alpha.kind_of?(BigDecimal)
51
+ # absorption_coefficient_gamma = BigDecimal(absorption_coefficient_gamma.to_s) unless absorption_coefficient_gamma.kind_of?(BigDecimal)
52
+ randomization_parameter_alpha = randomization_parameter_alpha.to_f unless randomization_parameter_alpha.kind_of?(Float)
53
+ absorption_coefficient_gamma = absorption_coefficient_gamma.to_f unless absorption_coefficient_gamma.kind_of?(Float)
51
54
 
52
55
  initialize_fireflies(number_of_fireflies)
53
56
 
54
- # 0 to maximun_generation-1
55
- (0...maximun_generation).each do |generation|
57
+ maximun_generation.times do |generation|
56
58
 
57
59
  @fireflies.each { |firefly| firefly.update_light_intensity }
58
60
 
@@ -76,7 +78,8 @@ module MetaheuristicAlgorithms
76
78
  get_decision_variable_value_by_randomization(variable_index)
77
79
  end
78
80
 
79
- firefly = Firefly.new(@function_wrapper, decision_variable_values, BigDecimal('0'))
81
+ # firefly = Firefly.new(@function_wrapper, decision_variable_values, BigDecimal('0'))
82
+ firefly = Firefly.new(@function_wrapper, decision_variable_values, 0)
80
83
  @fireflies << firefly
81
84
  end
82
85
 
@@ -84,7 +87,8 @@ module MetaheuristicAlgorithms
84
87
 
85
88
  def move_fireflies(randomization_parameter_alpha, absorption_coefficient_gamma)
86
89
 
87
- attractiveness_beta_at_distance_0 = BigDecimal('1')
90
+ # attractiveness_beta_at_distance_0 = BigDecimal('1')
91
+ attractiveness_beta_at_distance_0 = 1
88
92
 
89
93
  fireflies_copy = @fireflies.map(&:deep_clone)
90
94
 
@@ -98,12 +102,16 @@ module MetaheuristicAlgorithms
98
102
 
99
103
  distance_of_two_fireflies = distance_of_two_fireflies(firefly_i, firefly_j)
100
104
 
101
- attractiveness_beta = attractiveness_beta_at_distance_0 * BigMath.exp(-absorption_coefficient_gamma * distance_of_two_fireflies.power(2), 10)
105
+ # attractiveness_beta = attractiveness_beta_at_distance_0 * BigMath.exp(-absorption_coefficient_gamma * distance_of_two_fireflies.power(2), 10)
106
+ attractiveness_beta = attractiveness_beta_at_distance_0 * Math.exp(-absorption_coefficient_gamma * distance_of_two_fireflies**2)
102
107
 
103
- (0...@number_of_variables).each do |variable_index|
104
- new_location_coordinate = firefly_i.location_coordinates[variable_index] * (BigDecimal('1') - attractiveness_beta)
108
+ @number_of_variables.times do |variable_index|
109
+ # new_location_coordinate = firefly_i.location_coordinates[variable_index] * (BigDecimal('1') - attractiveness_beta)
110
+ # + firefly_j.location_coordinates[variable_index] * attractiveness_beta
111
+ # + randomization_parameter_alpha * (bigdecimal_rand - BigDecimal('0.5'))
112
+ new_location_coordinate = firefly_i.location_coordinates[variable_index] * (1 - attractiveness_beta)
105
113
  + firefly_j.location_coordinates[variable_index] * attractiveness_beta
106
- + randomization_parameter_alpha * (bigdecimal_rand - BigDecimal('0.5'))
114
+ + randomization_parameter_alpha * (rand - 0.5)
107
115
  new_location_coordinate = constrain_within_range(new_location_coordinate, variable_index)
108
116
 
109
117
  firefly_i.location_coordinates[variable_index] = new_location_coordinate
@@ -129,11 +137,12 @@ module MetaheuristicAlgorithms
129
137
 
130
138
  def distance_of_two_fireflies(firefly_1, firefly_2)
131
139
 
132
- sum_of_squares = (0...@number_of_variables).inject(BigDecimal('0')) do |sum, variable_index|
133
- sum + (firefly_1.location_coordinates[variable_index] - firefly_2.location_coordinates[variable_index]).power(2)
140
+ # sum_of_squares = (0...@number_of_variables).inject(BigDecimal('0')) do |sum, variable_index|
141
+ sum_of_squares = (0...@number_of_variables).inject(0) do |sum, variable_index|
142
+ sum + (firefly_1.location_coordinates[variable_index] - firefly_2.location_coordinates[variable_index])**2
134
143
  end
135
144
 
136
- sum_of_squares.sqrt(10)
145
+ Math.sqrt(sum_of_squares)
137
146
 
138
147
  end
139
148
 
@@ -1,4 +1,4 @@
1
- require 'bigdecimal/math'
1
+ # require 'bigdecimal/math'
2
2
 
3
3
  module MetaheuristicAlgorithms
4
4
 
@@ -8,15 +8,18 @@ module MetaheuristicAlgorithms
8
8
  include MetaheuristicAlgorithms::CalculationHelper
9
9
 
10
10
  def maximum_decision_variable_values
11
- [BigDecimal('10')]
11
+ # [BigDecimal('10')]
12
+ [10]
12
13
  end
13
14
 
14
15
  def miminum_decision_variable_values
15
- [BigDecimal('-10')]
16
+ # [BigDecimal('-10')]
17
+ [-10]
16
18
  end
17
19
 
18
20
  def objective_function_value(decision_variable_values)
19
- -bigdecimal_cos(decision_variable_values[0]) * BigMath.exp((-(decision_variable_values[0] - BigMath.PI(10)).power(2)), 10)
21
+ # -bigdecimal_cos(decision_variable_values[0]) * BigMath.exp((-(decision_variable_values[0] - BigMath.PI(10)).power(2)), 10)
22
+ -Math.cos(decision_variable_values[0]) * Math.exp(-(decision_variable_values[0] - Math::PI)**2)
20
23
  end
21
24
 
22
25
  def initial_decision_variable_value_estimates
@@ -1,4 +1,4 @@
1
- require 'bigdecimal/math'
1
+ # require 'bigdecimal/math'
2
2
 
3
3
  module MetaheuristicAlgorithms
4
4
 
@@ -8,16 +8,20 @@ module MetaheuristicAlgorithms
8
8
  include MetaheuristicAlgorithms::CalculationHelper
9
9
 
10
10
  def maximum_decision_variable_values
11
- [BigDecimal('4'), BigDecimal('4')]
11
+ # [BigDecimal('4'), BigDecimal('4')]
12
+ [4, 4]
12
13
  end
13
14
 
14
15
  def miminum_decision_variable_values
15
- [BigDecimal('0'), BigDecimal('0')]
16
+ # [BigDecimal('0'), BigDecimal('0')]
17
+ [0, 0]
16
18
  end
17
19
 
18
20
  def objective_function_value(decision_variable_values)
19
- -bigdecimal_sin(decision_variable_values[0]) * bigdecimal_sin(decision_variable_values[0].power(2) / BigMath.PI(10)).power(20) -
20
- bigdecimal_sin(decision_variable_values[1]) * bigdecimal_sin(decision_variable_values[1].power(2) / BigMath.PI(10)).power(20)
21
+ # -bigdecimal_sin(decision_variable_values[0]) * bigdecimal_sin(decision_variable_values[0].power(2) / BigMath.PI(10)).power(20) -
22
+ # bigdecimal_sin(decision_variable_values[1]) * bigdecimal_sin(decision_variable_values[1].power(2) / BigMath.PI(10)).power(20)
23
+ -Math.sin(decision_variable_values[0]) * (Math.sin(decision_variable_values[0]**2 / Math::PI))**20 -
24
+ Math.sin(decision_variable_values[1]) * (Math.sin(decision_variable_values[1]**2 / Math::PI))**20
21
25
  end
22
26
 
23
27
  def initial_decision_variable_value_estimates
@@ -1,4 +1,4 @@
1
- require 'bigdecimal/math'
1
+ # require 'bigdecimal/math'
2
2
 
3
3
  module MetaheuristicAlgorithms
4
4
 
@@ -7,15 +7,18 @@ module MetaheuristicAlgorithms
7
7
  class NonsmoothMultipeakFunctionWrapper < AbstractWrapper
8
8
 
9
9
  def maximum_decision_variable_values
10
- [BigDecimal('5'), BigDecimal('5')]
10
+ # [BigDecimal('5'), BigDecimal('5')]
11
+ [5, 5]
11
12
  end
12
13
 
13
14
  def miminum_decision_variable_values
14
- [BigDecimal('-5'), BigDecimal('-5')]
15
+ # [BigDecimal('-5'), BigDecimal('-5')]
16
+ [-5, -5]
15
17
  end
16
18
 
17
19
  def objective_function_value(decision_variable_values)
18
- (decision_variable_values[0].abs + decision_variable_values[1].abs) * BigMath.exp((BigDecimal('-0.0625') * (decision_variable_values[0].power(2) + decision_variable_values[1].power(2))), 10)
20
+ # (decision_variable_values[0].abs + decision_variable_values[1].abs) * BigMath.exp((BigDecimal('-0.0625') * (decision_variable_values[0].power(2) + decision_variable_values[1].power(2))), 10)
21
+ (decision_variable_values[0].abs + decision_variable_values[1].abs) * Math.exp(-0.0625 * (decision_variable_values[0]**2 + decision_variable_values[1]**2))
19
22
  end
20
23
 
21
24
  def initial_decision_variable_value_estimates
@@ -5,19 +5,23 @@ module MetaheuristicAlgorithms
5
5
  class RosenbrookFunctionWrapper < AbstractWrapper
6
6
 
7
7
  def maximum_decision_variable_values
8
- [BigDecimal('5'), BigDecimal('5')]
8
+ # [BigDecimal('5'), BigDecimal('5')]
9
+ [5, 5]
9
10
  end
10
11
 
11
12
  def miminum_decision_variable_values
12
- [BigDecimal('-5'), BigDecimal('-5')]
13
+ # [BigDecimal('-5'), BigDecimal('-5')]
14
+ [-5, -5]
13
15
  end
14
16
 
15
17
  def objective_function_value(decision_variable_values)
16
- (BigDecimal('1') - decision_variable_values[0]).power(2) + BigDecimal('100') * (decision_variable_values[1] - decision_variable_values[0].power(2)).power(2)
18
+ # (BigDecimal('1') - decision_variable_values[0]).power(2) + BigDecimal('100') * (decision_variable_values[1] - decision_variable_values[0].power(2)).power(2)
19
+ (1 - decision_variable_values[0])**2 + 100 * (decision_variable_values[1] - decision_variable_values[0]**2)**2
17
20
  end
18
21
 
19
22
  def initial_decision_variable_value_estimates
20
- [BigDecimal('2'), BigDecimal('2')]
23
+ # [BigDecimal('2'), BigDecimal('2')]
24
+ [2, 2]
21
25
  end
22
26
 
23
27
  end
@@ -19,23 +19,28 @@ module MetaheuristicAlgorithms
19
19
  # @string_length_in_bits = 16
20
20
  end
21
21
 
22
- def search(population_size: 20, maximum_number_of_generations: 100, number_of_mutation_sites: BigDecimal('2'), crossover_probability: BigDecimal('0.95'), mutation_probability: BigDecimal('0.05'))
22
+ # def search(population_size: 20, maximum_number_of_generations: 100, number_of_mutation_sites: BigDecimal('2'), crossover_probability: BigDecimal('0.95'), mutation_probability: BigDecimal('0.05'))
23
+ def search(population_size: 20, maximum_number_of_generations: 100, number_of_mutation_sites: 2, crossover_probability: 0.95, mutation_probability: 0.05)
23
24
 
24
25
  population_size = population_size.to_i unless population_size.kind_of?(Integer)
25
26
  maximum_number_of_generations = maximum_number_of_generations.to_i unless maximum_number_of_generations.kind_of?(Integer)
26
- number_of_mutation_sites = BigDecimal(number_of_mutation_sites.to_s) unless number_of_mutation_sites.kind_of?(BigDecimal)
27
- crossover_probability = BigDecimal(crossover_probability.to_s) unless crossover_probability.kind_of?(BigDecimal)
28
- mutation_probability = BigDecimal(mutation_probability.to_s) unless mutation_probability.kind_of?(BigDecimal)
27
+ # number_of_mutation_sites = BigDecimal(number_of_mutation_sites.to_s) unless number_of_mutation_sites.kind_of?(BigDecimal)
28
+ # crossover_probability = BigDecimal(crossover_probability.to_s) unless crossover_probability.kind_of?(BigDecimal)
29
+ # mutation_probability = BigDecimal(mutation_probability.to_s) unless mutation_probability.kind_of?(BigDecimal)
30
+ number_of_mutation_sites = number_of_mutation_sites.to_i unless number_of_mutation_sites.kind_of?(Integer)
31
+ crossover_probability = crossover_probability.to_f unless crossover_probability.kind_of?(Float)
32
+ mutation_probability = mutation_probability.to_f unless mutation_probability.kind_of?(Float)
29
33
 
30
34
  initialize_population(population_size)
31
35
 
32
- (0...maximum_number_of_generations).each do |generation_index|
36
+ maximum_number_of_generations.times do |generation_index|
33
37
 
34
38
  @population_copy = deep_clone_population
35
39
 
36
- (0...population_size).each do |individual_index|
40
+ population_size.times do |individual_index|
37
41
 
38
- if bigdecimal_rand < crossover_probability
42
+ # if bigdecimal_rand < crossover_probability
43
+ if rand < crossover_probability
39
44
 
40
45
  # Crossover pair:
41
46
  crossover_pair_1_index = generate_random_index(population_size)
@@ -45,7 +50,8 @@ module MetaheuristicAlgorithms
45
50
 
46
51
  end
47
52
 
48
- if bigdecimal_rand < mutation_probability
53
+ # if bigdecimal_rand < mutation_probability
54
+ if rand < mutation_probability
49
55
 
50
56
  mutation_individual_index = generate_random_index(population_size)
51
57
 
@@ -71,8 +77,7 @@ module MetaheuristicAlgorithms
71
77
  @population = []
72
78
  @population_fitness = []
73
79
 
74
- # 0 to population_size-1
75
- (0...population_size).each do |individual_index|
80
+ population_size.times do |individual_index|
76
81
  decision_variable_values = (0...@number_of_variables).map do |variable_index|
77
82
  get_decision_variable_value_by_randomization(variable_index)
78
83
  end
@@ -91,7 +96,7 @@ module MetaheuristicAlgorithms
91
96
  crossover_pair_1_decimal_values = []
92
97
  crossover_pair_2_decimal_values = []
93
98
 
94
- (0...@number_of_variables).each do |variable_index|
99
+ @number_of_variables.times do |variable_index|
95
100
 
96
101
  crossover_pair_1_decimal_value = @population_copy[crossover_pair_1_index][variable_index]
97
102
  crossover_pair_2_decimal_value = @population_copy[crossover_pair_2_index][variable_index]
@@ -143,7 +148,7 @@ module MetaheuristicAlgorithms
143
148
 
144
149
  def binary_32_string_to_decimal(binary_32_string)
145
150
  decimal_float_value = [binary_32_string].pack("B*").unpack('g')[0].round(4)
146
- BigDecimal(decimal_float_value.to_s)
151
+ # BigDecimal(decimal_float_value.to_s)
147
152
  end
148
153
 
149
154
  def mutate(individual_index, number_of_mutation_sites)
@@ -155,7 +160,7 @@ module MetaheuristicAlgorithms
155
160
 
156
161
  mutated_binary_32_string = binary_32_string.clone
157
162
 
158
- (0...number_of_mutation_sites).each do |i|
163
+ number_of_mutation_sites.to_i.times do |i|
159
164
  mutation_site_index = generate_mutation_site_index
160
165
  # Flips 1 to 0 or 0 to 1:
161
166
  mutated_binary_32_string[mutation_site_index] = ((binary_32_string[mutation_site_index].to_i + 1).modulo(2)).to_s
@@ -20,22 +20,23 @@ module MetaheuristicAlgorithms
20
20
  when :minimization
21
21
  :<
22
22
  end
23
-
24
- @decision_variable_range = [@function_wrapper.miminum_decision_variable_values, @function_wrapper.maximum_decision_variable_values]
25
23
  end
26
24
 
27
- def search(maximum_attempt: 2500, pitch_adjusting_range: BigDecimal('100'), harmony_search_size: 20, harmony_memory_acceping_rate: BigDecimal('0.95'), pitch_adjusting_rate: BigDecimal('0.7'))
25
+ # def search(maximum_attempt: 2500, pitch_adjusting_range: BigDecimal('100'), harmony_search_size: 20, harmony_memory_acceping_rate: BigDecimal('0.95'), pitch_adjusting_rate: BigDecimal('0.7'))
26
+ def search(maximum_attempt: 2500, pitch_adjusting_range: 100, harmony_search_size: 20, harmony_memory_acceping_rate: 0.95, pitch_adjusting_rate: 0.7)
28
27
 
29
28
  maximum_attempt = maximum_attempt.to_i unless maximum_attempt.kind_of?(Integer)
30
- pitch_adjusting_range = BigDecimal(pitch_adjusting_range.to_s) unless pitch_adjusting_range.kind_of?(BigDecimal)
29
+ # pitch_adjusting_range = BigDecimal(pitch_adjusting_range.to_s) unless pitch_adjusting_range.kind_of?(BigDecimal)
30
+ pitch_adjusting_range = pitch_adjusting_range.to_f unless pitch_adjusting_range.kind_of?(Float)
31
31
  harmony_search_size = harmony_search_size.to_i unless harmony_search_size.kind_of?(Integer)
32
- harmony_memory_acceping_rate = BigDecimal(harmony_memory_acceping_rate.to_s) unless harmony_memory_acceping_rate.kind_of?(BigDecimal)
33
- pitch_adjusting_rate = BigDecimal(pitch_adjusting_rate.to_s) unless pitch_adjusting_rate.kind_of?(BigDecimal)
32
+ # harmony_memory_acceping_rate = BigDecimal(harmony_memory_acceping_rate.to_s) unless harmony_memory_acceping_rate.kind_of?(BigDecimal)
33
+ # pitch_adjusting_rate = BigDecimal(pitch_adjusting_rate.to_s) unless pitch_adjusting_rate.kind_of?(BigDecimal)
34
+ harmony_memory_acceping_rate = harmony_memory_acceping_rate.to_f unless harmony_memory_acceping_rate.kind_of?(Float)
35
+ pitch_adjusting_rate = pitch_adjusting_rate.to_f unless pitch_adjusting_rate.kind_of?(Float)
34
36
 
35
37
  initialize_harmony_memory(harmony_search_size)
36
38
 
37
- # 0 to maximum_attempt-1
38
- (0...maximum_attempt).each do |count|
39
+ maximum_attempt.times do |count|
39
40
 
40
41
  decision_variable_values = (0...@number_of_variables).map do |variable_index|
41
42
 
@@ -43,12 +44,15 @@ module MetaheuristicAlgorithms
43
44
  decision_variable_value = get_decision_variable_value_by_randomization(variable_index)
44
45
  else
45
46
  # Since the array index starts with 0 unlike MatLab, 1 is not added as in the code example in MatLab:
46
- harmony_memory_random_index = (harmony_search_size * bigdecimal_rand).fix
47
+ # harmony_memory_random_index = (harmony_search_size * bigdecimal_rand).fix
48
+ harmony_memory_random_index = (harmony_search_size * rand).to_i
47
49
  decision_variable_value = @harmony_memory[harmony_memory_random_index][variable_index]
48
50
 
49
- if bigdecimal_rand < pitch_adjusting_rate
51
+ # if bigdecimal_rand < pitch_adjusting_rate
52
+ if rand < pitch_adjusting_rate
50
53
  pitch_adjusting = (@function_wrapper.maximum_decision_variable_values[variable_index] - @function_wrapper.miminum_decision_variable_values[variable_index]) / pitch_adjusting_range
51
- decision_variable_value = decision_variable_value + pitch_adjusting * (bigdecimal_rand - BigDecimal('0.5'))
54
+ # decision_variable_value = decision_variable_value + pitch_adjusting * (bigdecimal_rand - BigDecimal('0.5'))
55
+ decision_variable_value = decision_variable_value + pitch_adjusting * (rand -0.5)
52
56
  end
53
57
  end
54
58
 
@@ -15,20 +15,22 @@ module MetaheuristicAlgorithms
15
15
  end
16
16
  end
17
17
 
18
- def search(number_of_particiles: 20, number_of_iterations: 15, social_coefficient: BigDecimal('0.5'), random_variable_coefficient: BigDecimal('0.2'))
18
+ # def search(number_of_particiles: 20, number_of_iterations: 15, social_coefficient: BigDecimal('0.5'), random_variable_coefficient: BigDecimal('0.2'))
19
+ def search(number_of_particiles: 20, number_of_iterations: 15, social_coefficient: 0.5, random_variable_coefficient: 0.2)
19
20
 
20
21
  number_of_particiles = number_of_particiles.to_i unless number_of_particiles.kind_of?(Integer)
21
22
  number_of_iterations = number_of_iterations.to_i unless number_of_iterations.kind_of?(Integer)
22
- social_coefficient = BigDecimal(social_coefficient.to_s) unless social_coefficient.kind_of?(BigDecimal)
23
- random_variable_coefficient = BigDecimal(random_variable_coefficient.to_s) unless random_variable_coefficient.kind_of?(BigDecimal)
23
+ # social_coefficient = BigDecimal(social_coefficient.to_s) unless social_coefficient.kind_of?(BigDecimal)
24
+ # random_variable_coefficient = BigDecimal(random_variable_coefficient.to_s) unless random_variable_coefficient.kind_of?(BigDecimal)
25
+ social_coefficient = social_coefficient.to_f unless social_coefficient.kind_of?(Float)
26
+ random_variable_coefficient = random_variable_coefficient.to_f unless random_variable_coefficient.kind_of?(Float)
24
27
 
25
28
  initialize_particles(number_of_particiles)
26
29
 
27
30
  global_best_position = nil
28
31
  best_function_value = nil
29
32
 
30
- # 0 to number_of_iterations-1
31
- (0...number_of_iterations).each do |iteration|
33
+ number_of_iterations.times do |iteration|
32
34
 
33
35
  function_values = @particle_locations.map do |particle_location|
34
36
  @function_wrapper.objective_function_value(particle_location)
@@ -50,8 +52,7 @@ module MetaheuristicAlgorithms
50
52
 
51
53
  @particle_locations = []
52
54
 
53
- # 0 to number_of_particiles-1
54
- (0...number_of_particiles).each do |individual_index|
55
+ number_of_particiles.times do |individual_index|
55
56
  decision_variable_values = (0...@number_of_variables).map do |variable_index|
56
57
  get_decision_variable_value_by_randomization(variable_index)
57
58
  end
@@ -68,10 +69,12 @@ module MetaheuristicAlgorithms
68
69
  (0...@number_of_variables).map do |variable_index|
69
70
 
70
71
  # The value out-of-range in order to enter while loop
71
- new_particle_location_coordinate = @function_wrapper.miminum_decision_variable_values[variable_index] - BigDecimal('1')
72
+ # new_particle_location_coordinate = @function_wrapper.miminum_decision_variable_values[variable_index] - BigDecimal('1')
73
+ new_particle_location_coordinate = @function_wrapper.miminum_decision_variable_values[variable_index] - 1
72
74
 
73
75
  while new_particle_location_coordinate < @function_wrapper.miminum_decision_variable_values[variable_index] || new_particle_location_coordinate > @function_wrapper.maximum_decision_variable_values[variable_index]
74
- new_particle_location_coordinate = (BigDecimal('1') - social_coefficient) * particle_location[variable_index] + social_coefficient * global_best_position[variable_index] + random_variable_coefficient * (bigdecimal_rand - BigDecimal('0.5'))
76
+ # new_particle_location_coordinate = (BigDecimal('1') - social_coefficient) * particle_location[variable_index] + social_coefficient * global_best_position[variable_index] + random_variable_coefficient * (bigdecimal_rand - BigDecimal('0.5'))
77
+ new_particle_location_coordinate = (1 - social_coefficient) * particle_location[variable_index] + social_coefficient * global_best_position[variable_index] + random_variable_coefficient * (rand - 0.5)
75
78
  end
76
79
 
77
80
  new_particle_location_coordinate
@@ -1,10 +1,12 @@
1
- require 'bigdecimal/math'
2
- require 'distribution'
1
+ # require 'bigdecimal/math'
2
+ # In order to support JRuby, decided not to use distribution gem:
3
+ # require 'distribution'
3
4
 
4
5
  module MetaheuristicAlgorithms
5
6
 
6
7
  class SimulatedAnnealing
7
8
  include MetaheuristicAlgorithms::Helper
9
+ include MetaheuristicAlgorithms::BaseAlgorithmModule
8
10
 
9
11
  def initialize(function_wrapper, number_of_variables: 1, objective: :maximization)
10
12
  @function_wrapper = function_wrapper
@@ -17,21 +19,32 @@ module MetaheuristicAlgorithms
17
19
  end
18
20
  end
19
21
 
20
- def search(temperature: BigDecimal('100.0'), minimal_temperature: BigDecimal('1'), maximum_number_of_rejections: 2500,
22
+ # def search(temperature: BigDecimal('100.0'), minimal_temperature: BigDecimal('1'), maximum_number_of_rejections: 2500,
23
+ # maximum_number_of_runs: 500, maximum_number_of_acceptances: 15,
24
+ # bolzmann_constant: BigDecimal('1'), cooling_factor: BigDecimal('0.95'), energy_norm: BigDecimal('10'),
25
+ # standard_diviation_for_estimation: BigDecimal('6'), ratio_of_energy_delta_over_evaluation_delta: BigDecimal('10'))
26
+ def search(temperature: 100.0, minimal_temperature: 1, maximum_number_of_rejections: 2500,
21
27
  maximum_number_of_runs: 500, maximum_number_of_acceptances: 15,
22
- bolzmann_constant: BigDecimal('1'), cooling_factor: BigDecimal('0.95'), energy_norm: BigDecimal('10'),
23
- standard_diviation_for_estimation: BigDecimal('6'), ratio_of_energy_delta_over_evaluation_delta: BigDecimal('10'))
28
+ bolzmann_constant: 1, cooling_factor: 0.95, energy_norm: 10,
29
+ standard_diviation_for_estimation: 6, ratio_of_energy_delta_over_evaluation_delta: 10)
24
30
 
25
- temperature = BigDecimal(temperature.to_s) unless temperature.kind_of?(BigDecimal)
26
- minimal_temperature = BigDecimal(minimal_temperature.to_s) unless minimal_temperature.kind_of?(BigDecimal)
31
+ # temperature = BigDecimal(temperature.to_s) unless temperature.kind_of?(BigDecimal)
32
+ # minimal_temperature = BigDecimal(minimal_temperature.to_s) unless minimal_temperature.kind_of?(BigDecimal)
33
+ temperature = temperature.to_f unless temperature.kind_of?(Float)
34
+ minimal_temperature = minimal_temperature.to_f unless minimal_temperature.kind_of?(Float)
27
35
  maximum_number_of_rejections = maximum_number_of_rejections.to_i unless maximum_number_of_rejections.kind_of?(Integer)
28
36
  maximum_number_of_runs = maximum_number_of_runs.to_i unless maximum_number_of_runs.kind_of?(Integer)
29
37
  maximum_number_of_acceptances = maximum_number_of_acceptances.to_i unless maximum_number_of_acceptances.kind_of?(Integer)
30
- bolzmann_constant = BigDecimal(bolzmann_constant.to_s) unless bolzmann_constant.kind_of?(BigDecimal)
31
- cooling_factor = BigDecimal(cooling_factor.to_s) unless cooling_factor.kind_of?(BigDecimal)
32
- energy_norm = BigDecimal(energy_norm.to_s) unless energy_norm.kind_of?(BigDecimal)
33
- standard_diviation_for_estimation = BigDecimal(standard_diviation_for_estimation.to_s) unless standard_diviation_for_estimation.kind_of?(BigDecimal)
34
- ratio_of_energy_delta_over_evaluation_delta = BigDecimal(ratio_of_energy_delta_over_evaluation_delta.to_s) unless ratio_of_energy_delta_over_evaluation_delta.kind_of?(BigDecimal)
38
+ # bolzmann_constant = BigDecimal(bolzmann_constant.to_s) unless bolzmann_constant.kind_of?(BigDecimal)
39
+ # cooling_factor = BigDecimal(cooling_factor.to_s) unless cooling_factor.kind_of?(BigDecimal)
40
+ # energy_norm = BigDecimal(energy_norm.to_s) unless energy_norm.kind_of?(BigDecimal)
41
+ # standard_diviation_for_estimation = BigDecimal(standard_diviation_for_estimation.to_s) unless standard_diviation_for_estimation.kind_of?(BigDecimal)
42
+ # ratio_of_energy_delta_over_evaluation_delta = BigDecimal(ratio_of_energy_delta_over_evaluation_delta.to_s) unless ratio_of_energy_delta_over_evaluation_delta.kind_of?(BigDecimal)
43
+ bolzmann_constant = bolzmann_constant.to_f unless bolzmann_constant.kind_of?(Float)
44
+ cooling_factor = cooling_factor.to_f unless cooling_factor.kind_of?(Float)
45
+ energy_norm = energy_norm.to_f unless energy_norm.kind_of?(Float)
46
+ standard_diviation_for_estimation = standard_diviation_for_estimation.to_f unless standard_diviation_for_estimation.kind_of?(Float)
47
+ ratio_of_energy_delta_over_evaluation_delta = ratio_of_energy_delta_over_evaluation_delta.to_f unless ratio_of_energy_delta_over_evaluation_delta.kind_of?(Float)
35
48
 
36
49
  number_of_runs = 0
37
50
  number_of_rejections = 0
@@ -66,13 +79,15 @@ module MetaheuristicAlgorithms
66
79
  # Accept if improved:
67
80
  # When objective = :maximization, "if evaluation_delta > 0 && evaluation_delta > energy_norm"
68
81
  # When objective = :minimization, "if evaluation_delta < 0 && -evaluation_delta > energy_norm"
69
- if evaluation_delta.send(@objective_comparison_operator, BigDecimal('0')) && evaluation_delta.abs > energy_norm
82
+ # if evaluation_delta.send(@objective_comparison_operator, BigDecimal('0')) && evaluation_delta.abs > energy_norm
83
+ if evaluation_delta.send(@objective_comparison_operator, 0) && evaluation_delta.abs > energy_norm
70
84
  best_solution = new_estimates
71
85
  best_evaluation = new_evaluation
72
86
  number_of_acceptances = number_of_acceptances + 1
73
87
  number_of_rejections = 0
74
88
  # Accept with a small probability if not improved
75
- elsif acceptance_probability(evaluation_delta, temperature, bolzmann_constant) > bigdecimal_rand
89
+ # elsif acceptance_probability(evaluation_delta, temperature, bolzmann_constant) > bigdecimal_rand
90
+ elsif acceptance_probability(evaluation_delta, temperature, bolzmann_constant) > rand
76
91
  best_solution = new_estimates
77
92
  best_evaluation = new_evaluation
78
93
  number_of_acceptances = number_of_acceptances + 1
@@ -92,13 +107,17 @@ module MetaheuristicAlgorithms
92
107
  (0...@number_of_variables).map do |variable_index|
93
108
 
94
109
  # The value out-of-range in order to enter while loop
95
- new_estimate = @function_wrapper.miminum_decision_variable_values[variable_index] - BigDecimal('1')
110
+ # new_estimate = @function_wrapper.miminum_decision_variable_values[variable_index] - BigDecimal('1')
111
+ new_estimate = @function_wrapper.miminum_decision_variable_values[variable_index] - 1
96
112
 
97
113
  while new_estimate < @function_wrapper.miminum_decision_variable_values[variable_index] || new_estimate > @function_wrapper.maximum_decision_variable_values[variable_index]
98
114
 
99
115
  # MatLab example code uses newGuess = initialGuess + rand(1,2) * randn;
100
116
  # But in our case, the value range is different.
101
- new_estimate = BigDecimal(Distribution::Normal.rng(previous_estimates[variable_index], standard_diviation_for_estimation).call.to_s)
117
+ # In order to support JRuby, decided not to use Distribution::Normal.rng:
118
+ # new_estimate = BigDecimal(Distribution::Normal.rng(previous_estimates[variable_index], standard_diviation_for_estimation).call.to_s)
119
+ # new_estimate = BigDecimal(gaussian(previous_estimates[variable_index], standard_diviation_for_estimation).to_s)
120
+ new_estimate = gaussian(previous_estimates[variable_index], standard_diviation_for_estimation)
102
121
 
103
122
  end
104
123
 
@@ -1,3 +1,3 @@
1
1
  module MetaheuristicAlgorithms
2
- VERSION = "0.1.3"
3
- end
2
+ VERSION = "0.2.1"
3
+ end
@@ -1,4 +1,4 @@
1
- require 'bigdecimal'
1
+ # require 'bigdecimal'
2
2
 
3
3
  module MetaheuristicAlgorithms
4
4
 
@@ -1,9 +1,9 @@
1
1
  require 'metaheuristic_algorithms/version'
2
- require 'bigdecimal'
2
+ # require 'bigdecimal'
3
3
  require 'metaheuristic_algorithms/calculation_helper'
4
4
  require 'metaheuristic_algorithms/function_wrappers'
5
- require 'metaheuristic_algorithms/base_algorithm_module'
6
5
  require 'metaheuristic_algorithms/helper'
6
+ require 'metaheuristic_algorithms/base_algorithm_module'
7
7
  require 'metaheuristic_algorithms/harmony_search'
8
8
  require 'metaheuristic_algorithms/firefly_algorithm'
9
9
  require 'metaheuristic_algorithms/genetic_algorithm'
@@ -32,5 +32,6 @@ Gem::Specification.new do |spec|
32
32
  spec.add_development_dependency "bundler", "~> 1.10"
33
33
  spec.add_development_dependency "rake", "~> 10.0"
34
34
  spec.add_development_dependency "rspec"
35
- spec.add_development_dependency "pry-byebug"
35
+ # Requires native C extension. Doesn't work with JRuby. Hence moved to Gemfile:
36
+ #spec.add_development_dependency "pry-byebug"
36
37
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metaheuristic_algorithms
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tadatoshi Takahashi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-08-09 00:00:00.000000000 Z
11
+ date: 2015-10-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: distribution
@@ -66,20 +66,6 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: pry-byebug
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
69
  description: Various metaheuristic algorithms implemented in Ruby.
84
70
  email:
85
71
  - tadatoshi@gmail.com
@@ -139,7 +125,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
139
125
  version: '0'
140
126
  requirements: []
141
127
  rubyforge_project:
142
- rubygems_version: 2.4.7
128
+ rubygems_version: 2.4.5.1
143
129
  signing_key:
144
130
  specification_version: 4
145
131
  summary: Various metaheuristic algorithms implemented in Ruby.