shortest-path 0.0.2 → 0.0.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: 55f2e617f1bb69175440dd880744b84a5b0ed480
4
- data.tar.gz: 575c55362f1987c38b1984457eab7c5314785f25
3
+ metadata.gz: 24e31f9a3e57ae30f4267b0ab9788a1966affe27
4
+ data.tar.gz: b360fe07466f51912ca373e945c846b0fa45ca23
5
5
  SHA512:
6
- metadata.gz: 2a6870f838329f9890c6094e1bf26457bb42312f01a093b02c5ab450c64093dd7f5b20ee6c5824085ab30005624a053a6d143dd0a3257356e9dc41e97b8f8b41
7
- data.tar.gz: e7933a68e0c285de39138690130658171fb9bf230a4261bbaa4f6e87c5836132fe18eb92b92756af07f2ce21b6d5e8d176e3392b44b5033608709a9a0f5e825c
6
+ metadata.gz: c325a13510629f21a1b448d49d5dec56eed2572c27551f6e9b9dd2781afd95b6310cf159d11d316d1ef25c99770854a15d878743858b7d4d6b723128ecd197eb
7
+ data.tar.gz: 657a108c7b5a1a34c497056fab0e53c44cefa34db8f7954b0f4806f4c33d5d800be95911529279fe3adae406fcf43a43aac3a85a5f24a156505b21231f87d663
@@ -1,4 +1,3 @@
1
1
  require "shortest/path/version"
2
2
  require "shortest/path/general"
3
- require "shortest/path/priority_queue"
4
3
  require "shortest/path/astar"
@@ -1,48 +1,48 @@
1
1
  module Shortest
2
2
  module Path
3
+
4
+ # @see http://branch14.org/snippets/a_star_in_ruby.html
5
+
6
+ class PriorityQueue
7
+ def initialize; @list = [] end
8
+
9
+ def add(priority, item)
10
+ @list << [priority, @list.length, item]
11
+ @list.sort!
12
+ self
13
+ end
14
+
15
+ def <<(pritem); add(*pritem) end
16
+ def next; @list.shift[2] end
17
+ def empty?; @list.empty? end
18
+ end
19
+
3
20
  class AStar
4
- def initialize(dist,heur,graph,start,goal)
5
- @dist=dist ; @heur=heur ; @graph=graph
6
- @start=start ; @goal=goal
21
+ def initialize(dist, cost, graph, start, goal)
22
+ @graph = graph
23
+ @dist = dist ; @cost = cost
24
+ @start = start ; @goal=goal
7
25
  end
8
26
 
9
27
  def search
10
- closedset=[] ; openset=Shortest::Path::PriorityQueue.new ; came_from={}
11
- start_g_score=0 ; start_f_score=start_g_score+@heur.call(@start,@goal)
12
- g_score={@start => start_g_score} ; f_score={@start => start_f_score}
13
- openset.add_with_priority(@start, start_f_score)
14
- until openset.empty?
15
- current=openset.pop
16
- return reconstruct_path(came_from,@goal) if current==@goal
17
- closedset<<current
18
- @graph.neighbors(current).each do |neighbor|
19
- next if closedset.include?(neighbor)
20
- tentative_g_score=g_score[current]+@dist.call(current,neighbor)
21
- if (not openset.include?(neighbor)) or (tentative_g_score < (g_score[neighbor]||Float::INFINITY))
22
- came_from[neighbor]=current
23
- g_score[neighbor]=tentative_g_score
24
- f_score[neighbor]=tentative_g_score+@heur.call(neighbor,@goal)
25
- if not openset.include?(neighbor)
26
- openset.add_with_priority(neighbor, f_score[neighbor])
27
- else
28
- openset.change_priority(neighbor, f_score[neighbor])
29
- end
30
- end
28
+ been_there = {}
29
+ pqueue = Shortest::Path::PriorityQueue.new
30
+ pqueue << [1, [@start, [], 0]]
31
+ while !pqueue.empty?
32
+ spot, path_so_far, cost_so_far = pqueue.next
33
+ next if been_there[spot]
34
+ newpath = path_so_far + [spot]
35
+ return newpath if (spot == @goal)
36
+ been_there[spot] = 1
37
+ @graph.neighbors(spot).each do |newspot|
38
+ next if been_there[newspot]
39
+ tcost = @cost.call(spot, newspot)
40
+ next unless tcost
41
+ newcost = cost_so_far + tcost
42
+ pqueue << [newcost + @dist.call(@goal, newspot), [newspot, newpath, newcost]]
31
43
  end
32
44
  end
33
- return [] # failure!
34
- end
35
-
36
- private
37
-
38
- def reconstruct_path(came_from, current_node)
39
- if came_from.include?(current_node)
40
- p = reconstruct_path(came_from, came_from[current_node])
41
- p << current_node
42
- p
43
- else
44
- [current_node]
45
- end
45
+ return []
46
46
  end
47
47
  end
48
48
 
@@ -51,9 +51,7 @@ module Shortest
51
51
  # `graph` graph structure
52
52
  # `start` start node
53
53
  # `goal` goal node
54
- def astar(dist,heur,graph,start,goal)
55
- Shortest::Path::AStar.new(dist,heur,graph,start,goal).search
56
- end
54
+ def astar(dist, heur, graph, start, goal); Shortest::Path::AStar.new(dist, heur, graph, start, goal).search end
57
55
 
58
56
  module_function :astar
59
57
  end
@@ -28,6 +28,13 @@ module Shortest
28
28
  self.connect(vertex2, vertex1, length)
29
29
  end
30
30
 
31
+ def remove_edge(vertex1, vertex2)
32
+ for_remove = @edges.select{ |e| (e.src == vertex1 && e.dst == vertex2) || (e.src == vertex2 && e.dst == vertex1) }
33
+ for_remove.each do |edge|
34
+ @edges.delete_at(@edges.index(edge))
35
+ end
36
+ end
37
+
31
38
  def neighbors(vertex)
32
39
  neighbors = []
33
40
  @edges.each{|edge| neighbors.push edge.dst if edge.src==vertex }
@@ -1,5 +1,5 @@
1
1
  module Shortest
2
2
  module Path
3
- VERSION = "0.0.2"
3
+ VERSION = "0.0.3"
4
4
  end
5
5
  end
@@ -19,6 +19,7 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ["lib"]
20
20
 
21
21
  spec.add_development_dependency "bundler", "~> 1.6"
22
- spec.add_development_dependency "rspec", "~> 3.0"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
23
24
  spec.add_development_dependency "debugger"
24
25
  end
@@ -3,9 +3,9 @@ require 'spec_helper'
3
3
  class Point
4
4
  attr_reader :x, :y
5
5
 
6
- def initialize(x,y)
7
- @x=x ; @y=y
8
- end
6
+ def initialize(x,y); @x=x ; @y=y end
7
+
8
+ def <=> (obj); 0 end
9
9
  end
10
10
 
11
11
  def build_graph(n)
@@ -22,10 +22,22 @@ def build_graph(n)
22
22
  graph
23
23
  end
24
24
 
25
+ describe 'AStar priority queue' do
26
+ before(:all) do
27
+ @queue = Shortest::Path::PriorityQueue.new
28
+ @queue << [1, "A"]
29
+ @queue << [3, "C"]
30
+ @queue << [2, "B"]
31
+ end
32
+ specify{ expect(@queue.next).to eq("A") }
33
+ specify{ expect(@queue.next).to eq("B") }
34
+ specify{ expect(@queue.next).to eq("C") }
35
+ end
36
+
25
37
  describe 'AStar' do
26
38
  before(:all) do
27
39
  @graph=build_graph(3)
28
- @p1=@graph[0] ; @p2=@graph[8]
40
+ @p1=@graph.first ; @p2=@graph.last
29
41
  dist = heur = ->(p1,p2){ dx=p1.x-p2.x ; dy=p1.y-p2.y ; Math.sqrt(dx*dx + dy*dy) }
30
42
  @shortest=Shortest::Path.astar(dist, heur, @graph, @p1, @p2)
31
43
  end
@@ -34,8 +46,30 @@ describe 'AStar' do
34
46
  specify{ expect(@graph.edges.size).to eq(24) }
35
47
  specify{ expect(@shortest.size).to eq(5) }
36
48
  specify{ expect(@shortest[0]).to eq(@graph[0]) }
37
- specify{ expect(@shortest[1]).to eq(@graph[1]) }
38
- specify{ expect(@shortest[2]).to eq(@graph[4]) }
39
- specify{ expect(@shortest[3]).to eq(@graph[5]) }
49
+ specify{ expect(@shortest[1]).to eq(@graph[3]) }
50
+ specify{ expect(@shortest[2]).to eq(@graph[6]) }
51
+ specify{ expect(@shortest[3]).to eq(@graph[7]) }
40
52
  specify{ expect(@shortest[4]).to eq(@graph[8]) }
41
53
  end
54
+
55
+ def astar_performance(n)
56
+ graph = build_graph(n)
57
+ p1 = graph.first ; p2 = graph.last
58
+ dist = heur = ->(p1,p2){ dx=p1.x-p2.x ; dy=p1.y-p2.y ; Math.sqrt(dx*dx + dy*dy) }
59
+ t1 = Time.now
60
+ shortest=Shortest::Path.astar(dist, heur, graph, p1, p2)
61
+ Time.now - t1
62
+ end
63
+
64
+ describe 'AStar performance' do
65
+ before(:all) do
66
+ puts ""
67
+ k = 10
68
+ (1..3).each do |n|
69
+ t = astar_performance(k)
70
+ puts "#{k}: #{t} sec"
71
+ k = k * 2
72
+ end
73
+ end
74
+ specify{ expect(true).to eq(true) }
75
+ end
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe 'Graph' do
3
+ describe 'Normal path for graph creation' do
4
4
  before(:all) do
5
5
  @graph=Shortest::Path::Graph.new
6
6
  (1..4).each{|x| @graph.push x}
@@ -21,3 +21,21 @@ describe 'Graph' do
21
21
  specify{ expect(@first_edge.src).to eq(1) }
22
22
  specify{ expect(@first_edge.dst).to eq(2) }
23
23
  end
24
+
25
+ describe 'Remove graph edge' do
26
+ before(:all) do
27
+ @graph=Shortest::Path::Graph.new
28
+ (1..4).each{|x| @graph.push x}
29
+ @graph.connect_mutually 1, 2, 10
30
+ @graph.connect_mutually 1, 3, 10
31
+ @graph.connect_mutually 1, 4, 10
32
+ @graph.connect_mutually 2, 4, 10
33
+ @graph.connect_mutually 2, 3, 10
34
+ @graph.connect_mutually 3, 4, 10
35
+
36
+ @graph.remove_edge(1, 2)
37
+ @graph.remove_edge(1, 3)
38
+ end
39
+
40
+ specify{ expect(@graph.edges.size).to eq(4 * 2) }
41
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shortest-path
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dimitri Kurashvili
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-07-07 00:00:00.000000000 Z
11
+ date: 2014-07-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -24,20 +24,34 @@ dependencies:
24
24
  - - ~>
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rspec
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
- - - ~>
45
+ - - '>='
32
46
  - !ruby/object:Gem::Version
33
- version: '3.0'
47
+ version: '0'
34
48
  type: :development
35
49
  prerelease: false
36
50
  version_requirements: !ruby/object:Gem::Requirement
37
51
  requirements:
38
- - - ~>
52
+ - - '>='
39
53
  - !ruby/object:Gem::Version
40
- version: '3.0'
54
+ version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: debugger
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -68,12 +82,10 @@ files:
68
82
  - lib/shortest/path.rb
69
83
  - lib/shortest/path/astar.rb
70
84
  - lib/shortest/path/general.rb
71
- - lib/shortest/path/priority_queue.rb
72
85
  - lib/shortest/path/version.rb
73
86
  - shortest-path.gemspec
74
87
  - spec/astar_spec.rb
75
88
  - spec/general_spec.rb
76
- - spec/priority_queue_spec.rb
77
89
  - spec/spec_helper.rb
78
90
  homepage: http://github.com/georgian-se/shortest-path
79
91
  licenses:
@@ -102,5 +114,4 @@ summary: finding shortest path
102
114
  test_files:
103
115
  - spec/astar_spec.rb
104
116
  - spec/general_spec.rb
105
- - spec/priority_queue_spec.rb
106
117
  - spec/spec_helper.rb
@@ -1,33 +0,0 @@
1
- module Shortest
2
- module Path
3
- class PriorityQueueItem
4
- attr_reader :item, :priority
5
-
6
- def initialize(item,priority)
7
- @item = item ; @priority = priority
8
- end
9
- end
10
-
11
- class PriorityQueue
12
- def initialize; @heap = [] end
13
-
14
- def add_with_priority(object, priority)
15
- item = PriorityQueueItem.new(object,priority)
16
- @heap << item
17
- sort_by_priority
18
- end
19
-
20
- def change_priority(object, priority)
21
- @heap.select{|x| x.item==object}.first.priority=priority
22
- sort_by_priority
23
- end
24
-
25
- def pop; @heap.delete_at(0).item end
26
- def empty?; @heap.empty? end
27
- def include?(object); @heap.select{|x| x.item==object}.any? end
28
-
29
- private
30
- def sort_by_priority; @heap.sort!{ |x,y| x.priority <=> y.priority } end
31
- end
32
- end
33
- end
@@ -1,20 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe 'PriorityQueue' do
4
- before(:all) do
5
- @queue=Shortest::Path::PriorityQueue.new
6
- @queue.add_with_priority("A",1)
7
- @queue.add_with_priority("D",4)
8
- @queue.add_with_priority("C",3)
9
- @queue.add_with_priority("B",2)
10
- end
11
-
12
- specify{ expect(@queue).not_to be_empty }
13
- specify{ expect(@queue.include?("A")).to eq(true) }
14
- specify{ expect(@queue.pop).to eq("A") }
15
- specify{ expect(@queue.pop).to eq("B") }
16
- specify{ expect(@queue.pop).to eq("C") }
17
- specify{ expect(@queue.pop).to eq("D") }
18
- specify{ expect(@queue).to be_empty }
19
- specify{ expect(@queue.include?("A")).to eq(false) }
20
- end