shortest-path 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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