Algorithmically 0.1.2 → 0.1.3

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: 7a20a235b28515eea9f3bc92defec55d22d6729d
4
- data.tar.gz: 5d21f847f53c63d35c3418e2b0f66c84486494b1
3
+ metadata.gz: 923dab150a1c719d4578803afb1f2f00f0cefa9d
4
+ data.tar.gz: df4628866699eab63f79a99aa315dba1cc58d466
5
5
  SHA512:
6
- metadata.gz: 875e6766cd3c27056098131cd6ddd7bf997a36df96ef8cbb6c5ce7bcb1f4327cfe3c91441d0e0f9cdfda4b6a4b88c17c9b1a45e063eeefc5589018ae446b93f1
7
- data.tar.gz: 93adaaae0738b14f82936259b788c3b89d95875bd6745704f35ca640957f95da2919991c7e3c9bdb2e4356d9f123a70426b12b16da25f52264c1c0e24055a7f9
6
+ metadata.gz: 5cac3441e02e4de16906501f54904bee60c51259ba2dcff2c9dbbe14e48f52e2160a42b043b96aff8a9db53820fa4e71937db65a9fd8d043eb434c8ff9895a8e
7
+ data.tar.gz: 931ca10d22d3a4a4bbb6896a93337b0b9ac96d33ee4e3e38fbd825c360711733aebb82f2d52ac24aeb1cfec24b728ee2f0b3bb0df835852776ec5dd3ade3ddad
data/README.md CHANGED
@@ -25,5 +25,9 @@ Or install it yourself as:
25
25
  Algorithmically::RandomSearch.new(2, 50)
26
26
 
27
27
  Algorithmically::AdaptiveRandomSearch.new(1000, 2, 0.05, 1.3, 3.0, 10, 30)
28
+
29
+ Algorithmically::HillClimbing.new(2, 1000)
30
+
31
+ Algorithmically::GuidedLocalSearch.new(150, [[565,575],[25,185],[345,750],[945,685]], 20, 0.3)
28
32
 
29
33
 
@@ -1,6 +1,7 @@
1
1
  require 'Algorithmically/version'
2
2
  require 'Algorithmically/Stochastic/random_search'
3
3
  require 'Algorithmically/Stochastic/hill_climbing'
4
+ require 'Algorithmically/Stochastic/guided_local_search'
4
5
 
5
6
 
6
7
  module Algorithmically
@@ -0,0 +1,107 @@
1
+ module Stochastic
2
+
3
+ class GuidedLocalSearch
4
+
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
20
+
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]
26
+ end
27
+ perm
28
+ end
29
+
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
41
+
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]
46
+ 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]))
50
+ end
51
+ [distance, augmented]
52
+ end
53
+
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
58
+
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
70
+
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])
77
+ end
78
+ utilities
79
+ end
80
+
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
87
+ end
88
+ penalties
89
+ end
90
+
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]}"
101
+ end
102
+ best
103
+ end
104
+
105
+ end
106
+
107
+ end
@@ -1,3 +1,3 @@
1
1
  module Algorithmically
2
- VERSION = '0.1.2'
2
+ VERSION = '0.1.3'
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.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - popac
@@ -77,6 +77,7 @@ files:
77
77
  - bin/setup
78
78
  - lib/Algorithmically.rb
79
79
  - lib/Algorithmically/Stochastic/adaptive_random_search.rb
80
+ - lib/Algorithmically/Stochastic/guided_local_search.rb
80
81
  - lib/Algorithmically/Stochastic/hill_climbing.rb
81
82
  - lib/Algorithmically/Stochastic/random_search.rb
82
83
  - lib/Algorithmically/version.rb