Algorithmically 0.1.5 → 0.1.6

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: 90dbca96e9a153e6acfbdd2eac99f9e06054aa73
4
- data.tar.gz: a1a059aab483649dae1d890df74549a20cda0b42
3
+ metadata.gz: c6b37344d80011486740e722946df13475c44ba5
4
+ data.tar.gz: 46afbc8274889d7660acf6fd42f5e3e78260851e
5
5
  SHA512:
6
- metadata.gz: 9afc0731375aa0fae820aa4605b87ce7992f484430faaf0c1eabba5fa91eaf785c36457e4613c2c622e51078667a3ecec57f519243114cd3a0e7765e0c3f4029
7
- data.tar.gz: 7d30e282bc64b82fe5683b33308e218cea14ed76100841f314fc3a02ab14c4399a8faa62ed9e4c5aee866ac4acee44fb37cb1124ca513d1846225cf32fb2a541
6
+ metadata.gz: 1831736b94dc14f2234ebfe1c2ca1c3c33f9d1ff301dd81f070c97bce781e517e38929ba6579467f60fda7093f3d267aa71fc28736850f97ae42c9775c4c75e0
7
+ data.tar.gz: a68582cd9aebbb76d27b047643d5160ba6ce1e352e45299512088dfcfbc326d5a8a2f22b58d21006098b1af2b9cdc7701210c7eb481294af92b99504e71e7066
data/README.md CHANGED
@@ -22,20 +22,20 @@ Or install it yourself as:
22
22
 
23
23
  ### Evolutionary Algorithms
24
24
 
25
- Algorithmically::Genetic.new(100, 64, 100, 0.98)
25
+ Algorithmically::Evolutionary::Genetic.new(100, 64, 100, 0.98)
26
26
 
27
27
  ### Neural Algorithms
28
28
 
29
- Algorithmically::Perceptron.new([[0,0,0], [0,1,1], [1,0,1], [1,1,1]], 2, 20, 0.1)
29
+ Algorithmically::Neural::Perceptron.new([[0,0,0], [0,1,1], [1,0,1], [1,1,1]], 2, 20, 0.1)
30
30
 
31
31
  ### Stochastic Algorithms
32
32
 
33
- Algorithmically::RandomSearch.new(2, 50)
33
+ Algorithmically::Neural::RandomSearch.new(2, 50)
34
34
 
35
- Algorithmically::AdaptiveRandomSearch.new(1000, 2, 0.05, 1.3, 3.0, 10, 30)
35
+ Algorithmically::Neural::AdaptiveRandomSearch.new(1000, 2, 0.05, 1.3, 3.0, 10, 30)
36
36
 
37
- Algorithmically::HillClimbing.new(2, 1000)
37
+ Algorithmically::Neural::HillClimbing.new(2, 1000)
38
38
 
39
- Algorithmically::GuidedLocalSearch.new(150, [[565,575],[25,185],[345,750],[945,685]], 20, 0.3)
39
+ Algorithmically::Neural::GuidedLocalSearch.new(150, [[565,575],[25,185],[345,750],[945,685]], 20, 0.3)
40
40
 
41
41
 
@@ -1,77 +1,79 @@
1
- module Evolutionary
1
+ module Algorithmically
2
+ module Evolutionary
2
3
 
3
- class Genetic
4
+ class Genetic
4
5
 
5
- def initialize(max_gens, num_bits, pop_size, p_crossover)
6
- p_mutation = 1.0/num_bits
7
- best = search(max_gens, num_bits, pop_size, p_crossover, p_mutation)
8
- puts "done! Solution: f=#{best[:fitness]}, s=#{best[:bitstring]}"
9
- end
10
-
11
- def onemax(bitstring)
12
- sum = 0
13
- bitstring.size.times { |i| sum+=1 if bitstring[i].chr=='1' }
14
- sum
15
- end
6
+ def initialize(max_gens, num_bits, pop_size, p_crossover)
7
+ p_mutation = 1.0/num_bits
8
+ best = search(max_gens, num_bits, pop_size, p_crossover, p_mutation)
9
+ puts "done! Solution: f=#{best[:fitness]}, s=#{best[:bitstring]}"
10
+ end
16
11
 
17
- def random_bitstring(num_bits)
18
- (0...num_bits).inject("") { |s, i| s<<((rand<0.5) ? "1" : "0") }
19
- end
12
+ def onemax(bitstring)
13
+ sum = 0
14
+ bitstring.size.times { |i| sum+=1 if bitstring[i].chr=='1' }
15
+ sum
16
+ end
20
17
 
21
- def binary_tournament(pop)
22
- i, j = rand(pop.size), rand(pop.size)
23
- j = rand(pop.size) if j==i
24
- (pop[i][:fitness] > pop[j][:fitness]) ? pop[i] : pop[j]
25
- end
18
+ def random_bitstring(num_bits)
19
+ (0...num_bits).inject("") { |s, i| s<<((rand<0.5) ? "1" : "0") }
20
+ end
26
21
 
27
- def point_mutation(bitstring, rate=1.0/bitstring.size)
28
- child = ""
29
- bitstring.size.times do |i|
30
- bit = bitstring[i].chr
31
- child << ((rand()<rate) ? ((bit=='1') ? "0" : "1") : bit)
22
+ def binary_tournament(pop)
23
+ i, j = rand(pop.size), rand(pop.size)
24
+ j = rand(pop.size) if j==i
25
+ (pop[i][:fitness] > pop[j][:fitness]) ? pop[i] : pop[j]
32
26
  end
33
- child
34
- end
35
27
 
36
- def crossover(parent1, parent2, rate)
37
- ""+parent1 if rand()>=rate
38
- point = 1 + rand(parent1.size-2)
39
- parent1[0...point]+parent2[point...(parent1.size)]
40
- end
28
+ def point_mutation(bitstring, rate=1.0/bitstring.size)
29
+ child = ""
30
+ bitstring.size.times do |i|
31
+ bit = bitstring[i].chr
32
+ child << ((rand()<rate) ? ((bit=='1') ? "0" : "1") : bit)
33
+ end
34
+ child
35
+ end
41
36
 
42
- def reproduce(selected, pop_size, p_cross, p_mutation)
43
- children = []
44
- selected.each_with_index do |p1, i|
45
- p2 = (i.modulo(2)==0) ? selected[i+1] : selected[i-1]
46
- p2 = selected[0] if i == selected.size-1
47
- child = {}
48
- child[:bitstring] = crossover(p1[:bitstring], p2[:bitstring], p_cross)
49
- child[:bitstring] = point_mutation(child[:bitstring], p_mutation)
50
- children << child
51
- children.size >= pop_size
37
+ def crossover(parent1, parent2, rate)
38
+ ""+parent1 if rand()>=rate
39
+ point = 1 + rand(parent1.size-2)
40
+ parent1[0...point]+parent2[point...(parent1.size)]
52
41
  end
53
- children
54
- end
55
42
 
56
- def search(max_gens, num_bits, pop_size, p_crossover, p_mutation)
57
- population = Array.new(pop_size) do |i|
58
- {:bitstring => random_bitstring(num_bits)}
43
+ def reproduce(selected, pop_size, p_cross, p_mutation)
44
+ children = []
45
+ selected.each_with_index do |p1, i|
46
+ p2 = (i.modulo(2)==0) ? selected[i+1] : selected[i-1]
47
+ p2 = selected[0] if i == selected.size-1
48
+ child = {}
49
+ child[:bitstring] = crossover(p1[:bitstring], p2[:bitstring], p_cross)
50
+ child[:bitstring] = point_mutation(child[:bitstring], p_mutation)
51
+ children << child
52
+ children.size >= pop_size
53
+ end
54
+ children
59
55
  end
60
- population.each { |c| c[:fitness] = onemax(c[:bitstring]) }
61
- best = population.sort { |x, y| y[:fitness] <=> x[:fitness] }.first
62
- max_gens.times do |gen|
63
- selected = Array.new(pop_size) { |i| binary_tournament(population) }
64
- children = reproduce(selected, pop_size, p_crossover, p_mutation)
65
- children.each { |c| c[:fitness] = onemax(c[:bitstring]) }
66
- children.sort! { |x, y| y[:fitness] <=> x[:fitness] }
67
- best = children.first if children.first[:fitness] >= best[:fitness]
68
- population = children
69
- puts " > gen #{gen}, best: #{best[:fitness]}, #{best[:bitstring]}"
70
- break best[:fitness] == num_bits
56
+
57
+ def search(max_gens, num_bits, pop_size, p_crossover, p_mutation)
58
+ population = Array.new(pop_size) do |i|
59
+ {:bitstring => random_bitstring(num_bits)}
60
+ end
61
+ population.each { |c| c[:fitness] = onemax(c[:bitstring]) }
62
+ best = population.sort { |x, y| y[:fitness] <=> x[:fitness] }.first
63
+ max_gens.times do |gen|
64
+ selected = Array.new(pop_size) { |i| binary_tournament(population) }
65
+ children = reproduce(selected, pop_size, p_crossover, p_mutation)
66
+ children.each { |c| c[:fitness] = onemax(c[:bitstring]) }
67
+ children.sort! { |x, y| y[:fitness] <=> x[:fitness] }
68
+ best = children.first if children.first[:fitness] >= best[:fitness]
69
+ population = children
70
+ puts " > gen #{gen}, best: #{best[:fitness]}, #{best[:bitstring]}"
71
+ break best[:fitness] == num_bits
72
+ end
73
+ best
71
74
  end
72
- best
75
+
73
76
  end
74
77
 
75
78
  end
76
-
77
79
  end
@@ -1,78 +1,80 @@
1
- module Neural
1
+ module Algorithmically
2
+ module Neural
2
3
 
3
- class Perceptron
4
+ class Perceptron
4
5
 
5
- def initialize(or_problem, inputs, iterations, learning_rate)
6
- execute(or_problem, inputs, iterations, learning_rate)
7
- end
6
+ def initialize(or_problem, inputs, iterations, learning_rate)
7
+ execute(or_problem, inputs, iterations, learning_rate)
8
+ end
8
9
 
9
- def random_vector(minmax)
10
- Array.new(minmax.size) do |i|
11
- minmax[i][0] + ((minmax[i][1] - minmax[i][0]) * rand())
10
+ def random_vector(minmax)
11
+ Array.new(minmax.size) do |i|
12
+ minmax[i][0] + ((minmax[i][1] - minmax[i][0]) * rand())
13
+ end
12
14
  end
13
- end
14
15
 
15
- def initialize_weights(problem_size)
16
- minmax = Array.new(problem_size + 1) { [-1.0, 1.0] }
17
- random_vector(minmax)
18
- end
16
+ def initialize_weights(problem_size)
17
+ minmax = Array.new(problem_size + 1) { [-1.0, 1.0] }
18
+ random_vector(minmax)
19
+ end
19
20
 
20
- def update_weights(num_inputs, weights, input, out_exp, out_act, l_rate)
21
- num_inputs.times do |i|
22
- weights[i] += l_rate * (out_exp - out_act) * input[i]
21
+ def update_weights(num_inputs, weights, input, out_exp, out_act, l_rate)
22
+ num_inputs.times do |i|
23
+ weights[i] += l_rate * (out_exp - out_act) * input[i]
24
+ end
25
+ weights[num_inputs] += l_rate * (out_exp - out_act) * 1.0
23
26
  end
24
- weights[num_inputs] += l_rate * (out_exp - out_act) * 1.0
25
- end
26
27
 
27
- def activate(weights, vector)
28
- sum = weights[weights.size-1] * 1.0
29
- vector.each_with_index do |input, i|
30
- sum += weights[i] * input
28
+ def activate(weights, vector)
29
+ sum = weights[weights.size-1] * 1.0
30
+ vector.each_with_index do |input, i|
31
+ sum += weights[i] * input
32
+ end
33
+ sum
31
34
  end
32
- sum
33
- end
34
35
 
35
- def transfer(activation)
36
- (activation >= 0) ? 1.0 : 0.0
37
- end
36
+ def transfer(activation)
37
+ (activation >= 0) ? 1.0 : 0.0
38
+ end
38
39
 
39
- def get_output(weights, vector)
40
- activation = activate(weights, vector)
41
- transfer(activation)
42
- end
40
+ def get_output(weights, vector)
41
+ activation = activate(weights, vector)
42
+ transfer(activation)
43
+ end
44
+
45
+ def train_weights(weights, domain, num_inputs, iterations, lrate)
46
+ iterations.times do |epoch|
47
+ error = 0.0
48
+ domain.each do |pattern|
49
+ input = Array.new(num_inputs) { |k| pattern[k].to_f }
50
+ output = get_output(weights, input)
51
+ expected = pattern.last.to_f
52
+ error += (output - expected).abs
53
+ update_weights(num_inputs, weights, input, expected, output, lrate)
54
+ end
55
+ puts "> epoch=#{epoch}, error=#{error}"
56
+ end
57
+ end
43
58
 
44
- def train_weights(weights, domain, num_inputs, iterations, lrate)
45
- iterations.times do |epoch|
46
- error = 0.0
59
+ def test_weights(weights, domain, num_inputs)
60
+ correct = 0
47
61
  domain.each do |pattern|
48
- input = Array.new(num_inputs) { |k| pattern[k].to_f }
49
- output = get_output(weights, input)
50
- expected = pattern.last.to_f
51
- error += (output - expected).abs
52
- update_weights(num_inputs, weights, input, expected, output, lrate)
62
+ input_vector = Array.new(num_inputs) { |k| pattern[k].to_f }
63
+ output = get_output(weights, input_vector)
64
+ correct += 1 if output.round == pattern.last
53
65
  end
54
- puts "> epoch=#{epoch}, error=#{error}"
66
+ puts "Finished test with a score of #{correct}/#{domain.size}"
67
+ correct
55
68
  end
56
- end
57
69
 
58
- def test_weights(weights, domain, num_inputs)
59
- correct = 0
60
- domain.each do |pattern|
61
- input_vector = Array.new(num_inputs) { |k| pattern[k].to_f }
62
- output = get_output(weights, input_vector)
63
- correct += 1 if output.round == pattern.last
70
+ def execute(domain, num_inputs, iterations, learning_rate)
71
+ weights = initialize_weights(num_inputs)
72
+ train_weights(weights, domain, num_inputs, iterations, learning_rate)
73
+ test_weights(weights, domain, num_inputs)
74
+ weights
64
75
  end
65
- puts "Finished test with a score of #{correct}/#{domain.size}"
66
- correct
67
- end
68
76
 
69
- def execute(domain, num_inputs, iterations, learning_rate)
70
- weights = initialize_weights(num_inputs)
71
- train_weights(weights, domain, num_inputs, iterations, learning_rate)
72
- test_weights(weights, domain, num_inputs)
73
- weights
74
77
  end
75
78
 
76
79
  end
77
-
78
80
  end
@@ -1,82 +1,84 @@
1
- module Stochastic
1
+ module Algorithmically
2
+ module Stochastic
2
3
 
3
- class AdaptiveRandomSearch
4
+ class AdaptiveRandomSearch
4
5
 
5
- def initialize(max_iter, bounds, init_factor, s_factor, l_factor, iter_mult, max_no_impr)
6
- problem_size = bounds
7
- @bounds1 = Array.new(problem_size) {|i| [-5, +5]}
8
- @max_iter = max_iter
9
- @init_factor = init_factor
10
- @s_factor = s_factor
11
- @l_factor = l_factor
12
- @iter_mult = iter_mult
13
- @max_no_impr = max_no_impr
14
- @best = search(@max_iter, @bounds1, @init_factor, @s_factor, @l_factor, @iter_mult, @max_no_impr)
15
- puts "Done. Best Solution: c=#{@best[:cost]}, v=#{@best[:vector].inspect}"
16
- end
6
+ def initialize(max_iter, bounds, init_factor, s_factor, l_factor, iter_mult, max_no_impr)
7
+ problem_size = bounds
8
+ @bounds1 = Array.new(problem_size) { |i| [-5, +5] }
9
+ @max_iter = max_iter
10
+ @init_factor = init_factor
11
+ @s_factor = s_factor
12
+ @l_factor = l_factor
13
+ @iter_mult = iter_mult
14
+ @max_no_impr = max_no_impr
15
+ @best = search(@max_iter, @bounds1, @init_factor, @s_factor, @l_factor, @iter_mult, @max_no_impr)
16
+ puts "Done. Best Solution: c=#{@best[:cost]}, v=#{@best[:vector].inspect}"
17
+ end
17
18
 
18
- def objective_function(vector)
19
- vector.inject(0) { |sum, x| sum + (x ** 2.0) }
20
- end
19
+ def objective_function(vector)
20
+ vector.inject(0) { |sum, x| sum + (x ** 2.0) }
21
+ end
21
22
 
22
- def rand_in_bounds(min, max)
23
- min + ((max-min) * rand())
24
- end
23
+ def rand_in_bounds(min, max)
24
+ min + ((max-min) * rand())
25
+ end
25
26
 
26
- def random_vector(minmax)
27
- Array.new(minmax.size) do |i|
28
- rand_in_bounds(minmax[i][0], minmax[i][1])
27
+ def random_vector(minmax)
28
+ Array.new(minmax.size) do |i|
29
+ rand_in_bounds(minmax[i][0], minmax[i][1])
30
+ end
29
31
  end
30
- end
31
32
 
32
- def take_step(minmax, current, step_size)
33
- position = Array.new(current.size)
34
- position.size.times do |i|
35
- min = [minmax[i][0], current[i]-step_size].max
36
- max = [minmax[i][1], current[i]+step_size].min
37
- position[i] = rand_in_bounds(min, max)
33
+ def take_step(minmax, current, step_size)
34
+ position = Array.new(current.size)
35
+ position.size.times do |i|
36
+ min = [minmax[i][0], current[i]-step_size].max
37
+ max = [minmax[i][1], current[i]+step_size].min
38
+ position[i] = rand_in_bounds(min, max)
39
+ end
40
+ position
38
41
  end
39
- position
40
- end
41
42
 
42
- def large_step_size(iter, step_size, s_factor, l_factor, iter_mult)
43
- step_size * l_factor if iter > 0 and iter.modulo(iter_mult) == 0
44
- step_size * s_factor
45
- end
43
+ def large_step_size(iter, step_size, s_factor, l_factor, iter_mult)
44
+ step_size * l_factor if iter > 0 and iter.modulo(iter_mult) == 0
45
+ step_size * s_factor
46
+ end
46
47
 
47
- def take_steps(bounds, current, step_size, big_stepsize)
48
- step, big_step = {}, {}
49
- step[:vector] = take_step(bounds, current[:vector], step_size)
50
- step[:cost] = objective_function(step[:vector])
51
- big_step[:vector] = take_step(bounds, current[:vector], big_stepsize)
52
- big_step[:cost] = objective_function(big_step[:vector])
53
- return step, big_step
54
- end
48
+ def take_steps(bounds, current, step_size, big_stepsize)
49
+ step, big_step = {}, {}
50
+ step[:vector] = take_step(bounds, current[:vector], step_size)
51
+ step[:cost] = objective_function(step[:vector])
52
+ big_step[:vector] = take_step(bounds, current[:vector], big_stepsize)
53
+ big_step[:cost] = objective_function(big_step[:vector])
54
+ return step, big_step
55
+ end
55
56
 
56
- def search(max_iter, bounds, init_factor, s_factor, l_factor, iter_mult, max_no_impr)
57
- step_size = (bounds[0][1]-bounds[0][0]) * init_factor
58
- current, count = {}, 0
59
- current[:vector] = random_vector(bounds)
60
- current[:cost] = objective_function(current[:vector])
61
- max_iter.times do |iter|
62
- big_stepsize = large_step_size(iter, step_size, s_factor, l_factor, iter_mult)
63
- step, big_step = take_steps(bounds, current, step_size, big_stepsize)
64
- if step[:cost] <= current[:cost] or big_step[:cost] <= current[:cost]
65
- if big_step[:cost] <= step[:cost]
66
- step_size, current = big_stepsize, big_step
57
+ def search(max_iter, bounds, init_factor, s_factor, l_factor, iter_mult, max_no_impr)
58
+ step_size = (bounds[0][1]-bounds[0][0]) * init_factor
59
+ current, count = {}, 0
60
+ current[:vector] = random_vector(bounds)
61
+ current[:cost] = objective_function(current[:vector])
62
+ max_iter.times do |iter|
63
+ big_stepsize = large_step_size(iter, step_size, s_factor, l_factor, iter_mult)
64
+ step, big_step = take_steps(bounds, current, step_size, big_stepsize)
65
+ if step[:cost] <= current[:cost] or big_step[:cost] <= current[:cost]
66
+ if big_step[:cost] <= step[:cost]
67
+ step_size, current = big_stepsize, big_step
68
+ else
69
+ current = step
70
+ end
71
+ count = 0
67
72
  else
68
- current = step
73
+ count += 1
74
+ count, step_size = 0, (step_size/s_factor) if count >= max_no_impr
69
75
  end
70
- count = 0
71
- else
72
- count += 1
73
- count, step_size = 0, (step_size/s_factor) if count >= max_no_impr
76
+ puts " > iteration #{(iter+1)}, best=#{current[:cost]}"
74
77
  end
75
- puts " > iteration #{(iter+1)}, best=#{current[:cost]}"
78
+ current
76
79
  end
77
- current
80
+
78
81
  end
79
82
 
80
83
  end
81
-
82
84
  end
@@ -1,107 +1,109 @@
1
- module Stochastic
1
+ module Algorithmically
2
+ module Stochastic
2
3
 
3
- class GuidedLocalSearch
4
+ class GuidedLocalSearch
4
5
 
5
- def initialize(max_iterations, berlin52, max_no_improv, lambda)
6
- @berlin52 = berlin52
7
- @max_iterations = max_iterations
8
- @max_no_improv = max_no_improv
9
- alpha = 0.3
10
- local_search_optima = 12000.0
11
- lambda = alpha * (local_search_optima/berlin52.size.to_f)
12
- @lambda = lambda
13
- best = search(@max_iterations, @berlin52, @max_no_improv, lambda)
14
- puts "Done. Best Solution: c=#{best[:cost]}, v=#{best[:vector].inspect}"
15
- end
16
-
17
- def euc_2d(c1, c2)
18
- Math.sqrt((c1[0] - c2[0])**2.0 + (c1[1] - c2[1])**2.0).round
19
- end
6
+ def initialize(max_iterations, berlin52, max_no_improv, lambda)
7
+ @berlin52 = berlin52
8
+ @max_iterations = max_iterations
9
+ @max_no_improv = max_no_improv
10
+ alpha = 0.3
11
+ local_search_optima = 12000.0
12
+ lambda = alpha * (local_search_optima/berlin52.size.to_f)
13
+ @lambda = lambda
14
+ best = search(@max_iterations, @berlin52, @max_no_improv, lambda)
15
+ puts "Done. Best Solution: c=#{best[:cost]}, v=#{best[:vector].inspect}"
16
+ end
20
17
 
21
- def random_permutation(cities)
22
- perm = Array.new(cities.size) { |i| i }
23
- perm.each_index do |i|
24
- r = rand(perm.size-i) + i
25
- perm[r], perm[i] = perm[i], perm[r]
18
+ def euc_2d(c1, c2)
19
+ Math.sqrt((c1[0] - c2[0])**2.0 + (c1[1] - c2[1])**2.0).round
26
20
  end
27
- perm
28
- end
29
21
 
30
- def stochastic_two_opt(permutation)
31
- perm = Array.new(permutation)
32
- c1, c2 = rand(perm.size), rand(perm.size)
33
- exclude = [c1]
34
- exclude << ((c1==0) ? perm.size-1 : c1-1)
35
- exclude << ((c1==perm.size-1) ? 0 : c1+1)
36
- c2 = rand(perm.size) while exclude.include?(c2)
37
- c1, c2 = c2, c1 if c2 < c1
38
- perm[c1...c2] = perm[c1...c2].reverse
39
- perm
40
- end
22
+ def random_permutation(cities)
23
+ perm = Array.new(cities.size) { |i| i }
24
+ perm.each_index do |i|
25
+ r = rand(perm.size-i) + i
26
+ perm[r], perm[i] = perm[i], perm[r]
27
+ end
28
+ perm
29
+ end
41
30
 
42
- def augmented_cost(permutation, penalties, cities, lambda)
43
- distance, augmented = 0, 0
44
- permutation.each_with_index do |c1, i|
45
- c2 = (i==permutation.size-1) ? permutation[0] : permutation[i+1]
31
+ def stochastic_two_opt(permutation)
32
+ perm = Array.new(permutation)
33
+ c1, c2 = rand(perm.size), rand(perm.size)
34
+ exclude = [c1]
35
+ exclude << ((c1==0) ? perm.size-1 : c1-1)
36
+ exclude << ((c1==perm.size-1) ? 0 : c1+1)
37
+ c2 = rand(perm.size) while exclude.include?(c2)
46
38
  c1, c2 = c2, c1 if c2 < c1
47
- d = euc_2d(cities[c1], cities[c2])
48
- distance += d
49
- augmented += d + (lambda * (penalties[c1][c2]))
39
+ perm[c1...c2] = perm[c1...c2].reverse
40
+ perm
50
41
  end
51
- [distance, augmented]
52
- end
53
42
 
54
- def cost(cand, penalties, cities, lambda)
55
- cost, acost = augmented_cost(cand[:vector], penalties, cities, lambda)
56
- cand[:cost], cand[:aug_cost] = cost, acost
57
- end
43
+ def augmented_cost(permutation, penalties, cities, lambda)
44
+ distance, augmented = 0, 0
45
+ permutation.each_with_index do |c1, i|
46
+ c2 = (i==permutation.size-1) ? permutation[0] : permutation[i+1]
47
+ c1, c2 = c2, c1 if c2 < c1
48
+ d = euc_2d(cities[c1], cities[c2])
49
+ distance += d
50
+ augmented += d + (lambda * (penalties[c1][c2]))
51
+ end
52
+ [distance, augmented]
53
+ end
58
54
 
59
- def local_search(current, cities, penalties, max_no_improv, lambda)
60
- cost(current, penalties, cities, lambda)
61
- count = 0
62
- begin
63
- candidate = {:vector => stochastic_two_opt(current[:vector])}
64
- cost(candidate, penalties, cities, lambda)
65
- count = (candidate[:aug_cost] < current[:aug_cost]) ? 0 : count+1
66
- current = candidate if candidate[:aug_cost] < current[:aug_cost]
67
- end until count >= max_no_improv
68
- current
69
- end
55
+ def cost(cand, penalties, cities, lambda)
56
+ cost, acost = augmented_cost(cand[:vector], penalties, cities, lambda)
57
+ cand[:cost], cand[:aug_cost] = cost, acost
58
+ end
70
59
 
71
- def calculate_feature_utilities(penal, cities, permutation)
72
- utilities = Array.new(permutation.size, 0)
73
- permutation.each_with_index do |c1, i|
74
- c2 = (i==permutation.size-1) ? permutation[0] : permutation[i+1]
75
- c1, c2 = c2, c1 if c2 < c1
76
- utilities[i] = euc_2d(cities[c1], cities[c2]) / (1.0 + penal[c1][c2])
60
+ def local_search(current, cities, penalties, max_no_improv, lambda)
61
+ cost(current, penalties, cities, lambda)
62
+ count = 0
63
+ begin
64
+ candidate = {:vector => stochastic_two_opt(current[:vector])}
65
+ cost(candidate, penalties, cities, lambda)
66
+ count = (candidate[:aug_cost] < current[:aug_cost]) ? 0 : count+1
67
+ current = candidate if candidate[:aug_cost] < current[:aug_cost]
68
+ end until count >= max_no_improv
69
+ current
77
70
  end
78
- utilities
79
- end
80
71
 
81
- def update_penalties!(penalties, cities, permutation, utilities)
82
- max = utilities.max()
83
- permutation.each_with_index do |c1, i|
84
- c2 = (i==permutation.size-1) ? permutation[0] : permutation[i+1]
85
- c1, c2 = c2, c1 if c2 < c1
86
- penalties[c1][c2] += 1 if utilities[i] == max
72
+ def calculate_feature_utilities(penal, cities, permutation)
73
+ utilities = Array.new(permutation.size, 0)
74
+ permutation.each_with_index do |c1, i|
75
+ c2 = (i==permutation.size-1) ? permutation[0] : permutation[i+1]
76
+ c1, c2 = c2, c1 if c2 < c1
77
+ utilities[i] = euc_2d(cities[c1], cities[c2]) / (1.0 + penal[c1][c2])
78
+ end
79
+ utilities
80
+ end
81
+
82
+ def update_penalties!(penalties, cities, permutation, utilities)
83
+ max = utilities.max()
84
+ permutation.each_with_index do |c1, i|
85
+ c2 = (i==permutation.size-1) ? permutation[0] : permutation[i+1]
86
+ c1, c2 = c2, c1 if c2 < c1
87
+ penalties[c1][c2] += 1 if utilities[i] == max
88
+ end
89
+ penalties
87
90
  end
88
- penalties
89
- end
90
91
 
91
- def search(max_iterations, cities, max_no_improv, lambda)
92
- current = {:vector => random_permutation(cities)}
93
- best = nil
94
- penalties = Array.new(cities.size) { Array.new(cities.size, 0) }
95
- max_iterations.times do |iter|
96
- current=local_search(current, cities, penalties, max_no_improv, lambda)
97
- utilities=calculate_feature_utilities(penalties, cities, current[:vector])
98
- update_penalties!(penalties, cities, current[:vector], utilities)
99
- best = current if best.nil? or current[:cost] < best[:cost]
100
- puts " > iter=#{(iter+1)}, best=#{best[:cost]}, aug=#{best[:aug_cost]}"
92
+ def search(max_iterations, cities, max_no_improv, lambda)
93
+ current = {:vector => random_permutation(cities)}
94
+ best = nil
95
+ penalties = Array.new(cities.size) { Array.new(cities.size, 0) }
96
+ max_iterations.times do |iter|
97
+ current=local_search(current, cities, penalties, max_no_improv, lambda)
98
+ utilities=calculate_feature_utilities(penalties, cities, current[:vector])
99
+ update_penalties!(penalties, cities, current[:vector], utilities)
100
+ best = current if best.nil? or current[:cost] < best[:cost]
101
+ puts " > iter=#{(iter+1)}, best=#{best[:cost]}, aug=#{best[:aug_cost]}"
102
+ end
103
+ best
101
104
  end
102
- best
105
+
103
106
  end
104
107
 
105
108
  end
106
-
107
109
  end
@@ -1,42 +1,44 @@
1
- module Stochastic
1
+ module Algorithmically
2
+ module Stochastic
2
3
 
3
- class HillClimbing
4
+ class HillClimbing
4
5
 
5
- def initialize(max_iterations, num_bits)
6
- best = search(max_iterations, num_bits)
7
- puts "Done. Best Solution: c=#{best[:cost]}, v=#{best[:vector].join}"
8
- end
6
+ def initialize(max_iterations, num_bits)
7
+ best = search(max_iterations, num_bits)
8
+ puts "Done. Best Solution: c=#{best[:cost]}, v=#{best[:vector].join}"
9
+ end
9
10
 
10
- def onemax(vector)
11
- vector.inject(0.0) { |sum, v| sum + ((v=="1") ? 1 : 0) }
12
- end
11
+ def onemax(vector)
12
+ vector.inject(0.0) { |sum, v| sum + ((v=="1") ? 1 : 0) }
13
+ end
13
14
 
14
- def random_bitstring(num_bits)
15
- Array.new(num_bits) { |i| (rand<0.5) ? "1" : "0" }
16
- end
15
+ def random_bitstring(num_bits)
16
+ Array.new(num_bits) { |i| (rand<0.5) ? "1" : "0" }
17
+ end
17
18
 
18
- def random_neighbor(bitstring)
19
- mutant = Array.new(bitstring)
20
- pos = rand(bitstring.size)
21
- mutant[pos] = (mutant[pos]=='1') ? '0' : '1'
22
- mutant
23
- end
19
+ def random_neighbor(bitstring)
20
+ mutant = Array.new(bitstring)
21
+ pos = rand(bitstring.size)
22
+ mutant[pos] = (mutant[pos]=='1') ? '0' : '1'
23
+ mutant
24
+ end
24
25
 
25
- def search(max_iterations, num_bits)
26
- candidate = {}
27
- candidate[:vector] = random_bitstring(num_bits)
28
- candidate[:cost] = onemax(candidate[:vector])
29
- max_iterations.times do |iter|
30
- neighbor = {}
31
- neighbor[:vector] = random_neighbor(candidate[:vector])
32
- neighbor[:cost] = onemax(neighbor[:vector])
33
- candidate = neighbor if neighbor[:cost] >= candidate[:cost]
34
- puts " > iteration #{(iter+1)}, best=#{candidate[:cost]}"
35
- break if candidate[:cost] == num_bits
26
+ def search(max_iterations, num_bits)
27
+ candidate = {}
28
+ candidate[:vector] = random_bitstring(num_bits)
29
+ candidate[:cost] = onemax(candidate[:vector])
30
+ max_iterations.times do |iter|
31
+ neighbor = {}
32
+ neighbor[:vector] = random_neighbor(candidate[:vector])
33
+ neighbor[:cost] = onemax(neighbor[:vector])
34
+ candidate = neighbor if neighbor[:cost] >= candidate[:cost]
35
+ puts " > iteration #{(iter+1)}, best=#{candidate[:cost]}"
36
+ break if candidate[:cost] == num_bits
37
+ end
38
+ candidate
36
39
  end
37
- candidate
40
+
38
41
  end
39
42
 
40
43
  end
41
-
42
44
  end
@@ -1,37 +1,39 @@
1
- module Stochastic
1
+ module Algorithmically
2
+ module Stochastic
2
3
 
3
- class RandomSearch
4
+ class RandomSearch
4
5
 
5
- def initialize(size, max_iter)
6
- problem_size = size
7
- search_space = Array.new(problem_size) { |i| [-5, +5] }
8
- maximum_iterations = max_iter
9
- best_solution = self.search(search_space, maximum_iterations)
10
- puts "Done. Best Solution: c = #{best_solution[:cost]}, v = #{best_solution[:vector].inspect}"
11
- end
6
+ def initialize(size, max_iter)
7
+ problem_size = size
8
+ search_space = Array.new(problem_size) { |i| [-5, +5] }
9
+ maximum_iterations = max_iter
10
+ best_solution = self.search(search_space, maximum_iterations)
11
+ puts "Done. Best Solution: c = #{best_solution[:cost]}, v = #{best_solution[:vector].inspect}"
12
+ end
12
13
 
13
- def objective_function(vector)
14
- vector.inject(0) { |sum, x| sum + (x ** 2.0) }
15
- end
14
+ def objective_function(vector)
15
+ vector.inject(0) { |sum, x| sum + (x ** 2.0) }
16
+ end
16
17
 
17
- def random_vector(minmax)
18
- Array.new(minmax.size) do |i|
19
- minmax[i][0] + ((minmax[i][1]) - minmax[i][0] * rand())
18
+ def random_vector(minmax)
19
+ Array.new(minmax.size) do |i|
20
+ minmax[i][0] + ((minmax[i][1]) - minmax[i][0] * rand())
21
+ end
20
22
  end
21
- end
22
23
 
23
- def search(search_space, maximum_iterations)
24
- best_solution = nil
25
- maximum_iterations.times do |iterate|
26
- search_candidate = {}
27
- search_candidate[:vector] = random_vector(search_space)
28
- search_candidate[:cost] = objective_function(search_candidate[:vector])
29
- best_solution = search_candidate if best_solution.nil? or search_candidate[:cost] < best_solution[:cost]
30
- puts " > iteration = #{(iterate + 1)}, best = #{best_solution[:cost]}"
24
+ def search(search_space, maximum_iterations)
25
+ best_solution = nil
26
+ maximum_iterations.times do |iterate|
27
+ search_candidate = {}
28
+ search_candidate[:vector] = random_vector(search_space)
29
+ search_candidate[:cost] = objective_function(search_candidate[:vector])
30
+ best_solution = search_candidate if best_solution.nil? or search_candidate[:cost] < best_solution[:cost]
31
+ puts " > iteration = #{(iterate + 1)}, best = #{best_solution[:cost]}"
32
+ end
33
+ best_solution
31
34
  end
32
- best_solution
35
+
33
36
  end
34
37
 
35
38
  end
36
-
37
39
  end
@@ -1,3 +1,3 @@
1
1
  module Algorithmically
2
- VERSION = '0.1.5'
2
+ VERSION = '0.1.6'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: Algorithmically
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - popac