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 +4 -4
- data/lib/shortest/path.rb +0 -1
- data/lib/shortest/path/astar.rb +38 -40
- data/lib/shortest/path/general.rb +7 -0
- data/lib/shortest/path/version.rb +1 -1
- data/shortest-path.gemspec +2 -1
- data/spec/astar_spec.rb +41 -7
- data/spec/general_spec.rb +19 -1
- metadata +20 -9
- data/lib/shortest/path/priority_queue.rb +0 -33
- data/spec/priority_queue_spec.rb +0 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 24e31f9a3e57ae30f4267b0ab9788a1966affe27
|
4
|
+
data.tar.gz: b360fe07466f51912ca373e945c846b0fa45ca23
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c325a13510629f21a1b448d49d5dec56eed2572c27551f6e9b9dd2781afd95b6310cf159d11d316d1ef25c99770854a15d878743858b7d4d6b723128ecd197eb
|
7
|
+
data.tar.gz: 657a108c7b5a1a34c497056fab0e53c44cefa34db8f7954b0f4806f4c33d5d800be95911529279fe3adae406fcf43a43aac3a85a5f24a156505b21231f87d663
|
data/lib/shortest/path.rb
CHANGED
data/lib/shortest/path/astar.rb
CHANGED
@@ -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,
|
5
|
-
@
|
6
|
-
@
|
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
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
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 []
|
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 }
|
data/shortest-path.gemspec
CHANGED
@@ -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 "
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec"
|
23
24
|
spec.add_development_dependency "debugger"
|
24
25
|
end
|
data/spec/astar_spec.rb
CHANGED
@@ -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
|
-
|
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
|
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[
|
38
|
-
specify{ expect(@shortest[2]).to eq(@graph[
|
39
|
-
specify{ expect(@shortest[3]).to eq(@graph[
|
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
|
data/spec/general_spec.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe '
|
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.
|
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-
|
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: '
|
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: '
|
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
|
data/spec/priority_queue_spec.rb
DELETED
@@ -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
|