Class: TabooSearch::TabooSearch
- Inherits:
-
Object
- Object
- TabooSearch::TabooSearch
- Defined in:
- lib/taboo_search.rb
Instance Method Summary collapse
-
#candidate(best, taboo_list, cities) ⇒ Object
candidate.
-
#cost(shake, cities) ⇒ Object
gets distance between two cities.
-
#euc_2d(c1, c2) ⇒ Object
gets distance between cities.
-
#is_taboo?(shake, taboo_list) ⇒ Boolean
is taboo.
-
#search(cities, taboo_list_size, candidate_list_size, max_iter) ⇒ Object
search.
-
#shake(cities) ⇒ Object
shake.
-
#two_opt(shake) ⇒ Object
gets reverse in range.
Instance Method Details
#candidate(best, taboo_list, cities) ⇒ Object
candidate
57 58 59 60 61 62 63 64 65 |
# File 'lib/taboo_search.rb', line 57 def candidate(best, taboo_list, cities) shake, edges = nil, nil begin shake, edges = two_opt(best[:vector]) end while is_taboo?(shake, taboo_list) candidate = {:vector => shake} candidate[:cost] = cost(candidate[:vector], cities) return candidate, edges end |
#cost(shake, cities) ⇒ Object
gets distance between two cities
11 12 13 14 15 16 17 18 19 |
# File 'lib/taboo_search.rb', line 11 def cost(shake, cities) distance = 0 shake.each_with_index do |c1, i| c2 = (i == (shake.size - 1)) ? shake[0] : shake[i + 1] # +++ get distance between two cities distance += euc_2d cities[c1], cities[c2] end distance end |
#euc_2d(c1, c2) ⇒ Object
gets distance between cities
6 7 8 |
# File 'lib/taboo_search.rb', line 6 def euc_2d(c1, c2) Math.sqrt((c2[0] - c1[0]) ** 2.0 + (c2[1] - c1[1]) ** 2.0).round end |
#is_taboo?(shake, taboo_list) ⇒ Boolean
is taboo
46 47 48 49 50 51 52 53 54 |
# File 'lib/taboo_search.rb', line 46 def is_taboo?(shake, taboo_list) shake.each_with_index do |c1, i| c2 = (i == (shake.size - 1)) ? shake[0] : shake[i + 1] taboo_list.each do |forbidden_edge| return true if forbidden_edge == [c1, c2] end end false end |
#search(cities, taboo_list_size, candidate_list_size, max_iter) ⇒ Object
search
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/taboo_search.rb', line 68 def search(cities, taboo_list_size, candidate_list_size, max_iter) current = {:vector => shake(cities)} current[:cost] = cost(current[:vector], cities) best = current taboo_list = Array.new(taboo_list_size) max_iter.times do |iter| candidates = Array.new(candidate_list_size) do |i| candidate(current, taboo_list, cities) end candidates.sort!{|x, y| x.first[:cost] <=> y.first[:cost]} best_candidate = candidates.first[0] best_candidate_edges = candidates.first[1] if best_candidate[:cost] < current[:cost] current = best_candidate best = best_candidate if best_candidate[:cost] < best[:cost] best_candidate_edges.each{|edge| taboo_list.push(edge)} taboo_list.pop while taboo_list.size > taboo_list_size end puts " > iteration #{(iter + 1)}, best #{best[:cost]}" end best end |
#shake(cities) ⇒ Object
shake
22 23 24 25 26 27 28 29 |
# File 'lib/taboo_search.rb', line 22 def shake(cities) shake = Array.new(cities.size){|i| i} shake.each_index do |i| r = rand(shake.size - 1) + 1 shake[i], shake[r] = shake[r], shake[i] end shake end |
#two_opt(shake) ⇒ Object
gets reverse in range
32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/taboo_search.rb', line 32 def two_opt(shake) perm = Array.new(shake) c1, c2 = rand(perm.size), rand(perm.size) collection = [c1] collection << ((c1 == 0 ? perm.size - 1 : c1 - 1)) collection << ((c1 == perm.size - 1) ? 0 : c1 + 1) c2 = rand(perm.size) while collection.include? (c2) c1, c2 = c2, c1 if c2 < c1 # +++ reverses in range perm[c1...c2] = perm[c1...c2].reverse return perm, [[shake[c1 - 1], shake[c1]], [shake[c2 - 1], shake[c2]]] end |