shortest-path 0.0.1 → 0.0.2

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: 4176937cca1a506176ab30d3b0657ae6634d0852
4
- data.tar.gz: 086449d097a560ec5f436fdf295105c68827029c
3
+ metadata.gz: 55f2e617f1bb69175440dd880744b84a5b0ed480
4
+ data.tar.gz: 575c55362f1987c38b1984457eab7c5314785f25
5
5
  SHA512:
6
- metadata.gz: 1e354fcf51cb029e4803ac1815aefd7eb0cdfb0a45f32fbb6dd47e39a4b95843500522de771568aa20c4b3bf8853bce59fccc5f2ed2ee158e73028dff66c94f2
7
- data.tar.gz: 04db5931140667647adffe7ddf2ab49419657b468379ea4830f0b76234996e3f13f153efac6c3381fb66ec207163085f8b8e160b547f9732509c74f9b9a8e8e7
6
+ metadata.gz: 2a6870f838329f9890c6094e1bf26457bb42312f01a093b02c5ab450c64093dd7f5b20ee6c5824085ab30005624a053a6d143dd0a3257356e9dc41e97b8f8b41
7
+ data.tar.gz: e7933a68e0c285de39138690130658171fb9bf230a4261bbaa4f6e87c5836132fe18eb92b92756af07f2ce21b6d5e8d176e3392b44b5033608709a9a0f5e825c
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour
data/lib/shortest/path.rb CHANGED
@@ -1,7 +1,4 @@
1
1
  require "shortest/path/version"
2
-
3
- module Shortest
4
- module Path
5
- # Your code goes here...
6
- end
7
- end
2
+ require "shortest/path/general"
3
+ require "shortest/path/priority_queue"
4
+ require "shortest/path/astar"
@@ -0,0 +1,60 @@
1
+ module Shortest
2
+ module Path
3
+ class AStar
4
+ def initialize(dist,heur,graph,start,goal)
5
+ @dist=dist ; @heur=heur ; @graph=graph
6
+ @start=start ; @goal=goal
7
+ end
8
+
9
+ 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
31
+ end
32
+ 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
46
+ end
47
+ end
48
+
49
+ # `dist` function which calculates distance between two points
50
+ # `heur` heuristic function
51
+ # `graph` graph structure
52
+ # `start` start node
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
57
+
58
+ module_function :astar
59
+ end
60
+ end
@@ -0,0 +1,38 @@
1
+ module Shortest
2
+ module Path
3
+ class Edge
4
+ attr_accessor :src, :dst, :length
5
+
6
+ def initialize(src, dst, length)
7
+ @src=src
8
+ @dst=dst
9
+ @length=length
10
+ end
11
+ end
12
+
13
+ class Graph < Array
14
+ attr_reader :edges
15
+
16
+ def initialize
17
+ @edges=[]
18
+ end
19
+
20
+ def connect(src, dst, length)
21
+ raise "No such vertex: #{src}" unless self.include?(src)
22
+ raise "No such vertex: #{dst}" unless self.include?(dst)
23
+ @edges.push Edge.new(src, dst, length)
24
+ end
25
+
26
+ def connect_mutually(vertex1, vertex2, length)
27
+ self.connect(vertex1, vertex2, length)
28
+ self.connect(vertex2, vertex1, length)
29
+ end
30
+
31
+ def neighbors(vertex)
32
+ neighbors = []
33
+ @edges.each{|edge| neighbors.push edge.dst if edge.src==vertex }
34
+ neighbors.uniq
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,33 @@
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,5 +1,5 @@
1
1
  module Shortest
2
2
  module Path
3
- VERSION = "0.0.1"
3
+ VERSION = "0.0.2"
4
4
  end
5
5
  end
@@ -19,5 +19,6 @@ 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 "rake"
22
+ spec.add_development_dependency "rspec", "~> 3.0"
23
+ spec.add_development_dependency "debugger"
23
24
  end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ class Point
4
+ attr_reader :x, :y
5
+
6
+ def initialize(x,y)
7
+ @x=x ; @y=y
8
+ end
9
+ end
10
+
11
+ def build_graph(n)
12
+ graph=Shortest::Path::Graph.new
13
+ (0..n-1).each do |x|
14
+ (0..n-1).each do |y|
15
+ graph.push Point.new(x,y)
16
+ end
17
+ end
18
+ (0..n*n-1).each do |i|
19
+ graph.connect_mutually(graph[i], graph[i+1], 1) unless (i+1)%n == 0
20
+ graph.connect_mutually(graph[i], graph[i+n], 1) unless i+1 > n*(n-1)
21
+ end
22
+ graph
23
+ end
24
+
25
+ describe 'AStar' do
26
+ before(:all) do
27
+ @graph=build_graph(3)
28
+ @p1=@graph[0] ; @p2=@graph[8]
29
+ dist = heur = ->(p1,p2){ dx=p1.x-p2.x ; dy=p1.y-p2.y ; Math.sqrt(dx*dx + dy*dy) }
30
+ @shortest=Shortest::Path.astar(dist, heur, @graph, @p1, @p2)
31
+ end
32
+
33
+ specify{ expect(@graph.size).to eq(9) }
34
+ specify{ expect(@graph.edges.size).to eq(24) }
35
+ specify{ expect(@shortest.size).to eq(5) }
36
+ 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]) }
40
+ specify{ expect(@shortest[4]).to eq(@graph[8]) }
41
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Graph' do
4
+ before(:all) do
5
+ @graph=Shortest::Path::Graph.new
6
+ (1..4).each{|x| @graph.push x}
7
+ expect(@graph.size).to eq(4)
8
+ @graph.connect_mutually 1, 2, 10
9
+ @graph.connect_mutually 1, 3, 10
10
+ @graph.connect_mutually 1, 4, 10
11
+ @graph.connect_mutually 2, 4, 10
12
+
13
+ @first_edge=@graph.edges.first
14
+ end
15
+
16
+ specify{ expect(@graph.neighbors(1).size).to eq(3) }
17
+ specify{ expect(@graph.neighbors(2).size).to eq(2) }
18
+ specify{ expect(@graph.neighbors(3).size).to eq(1) }
19
+ specify{ expect(@graph.neighbors(4).size).to eq(2) }
20
+
21
+ specify{ expect(@first_edge.src).to eq(1) }
22
+ specify{ expect(@first_edge.dst).to eq(2) }
23
+ end
@@ -0,0 +1,20 @@
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
@@ -0,0 +1,3 @@
1
+ require 'rspec'
2
+ require 'debugger'
3
+ require 'shortest/path'
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.1
4
+ version: 0.0.2
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-06-19 00:00:00.000000000 Z
11
+ date: 2014-07-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -25,7 +25,21 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.6'
27
27
  - !ruby/object:Gem::Dependency
28
- name: rake
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '3.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '3.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: debugger
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
45
  - - '>='
@@ -46,13 +60,21 @@ extensions: []
46
60
  extra_rdoc_files: []
47
61
  files:
48
62
  - .gitignore
63
+ - .rspec
49
64
  - Gemfile
50
65
  - LICENSE.txt
51
66
  - README.md
52
67
  - Rakefile
53
68
  - lib/shortest/path.rb
69
+ - lib/shortest/path/astar.rb
70
+ - lib/shortest/path/general.rb
71
+ - lib/shortest/path/priority_queue.rb
54
72
  - lib/shortest/path/version.rb
55
73
  - shortest-path.gemspec
74
+ - spec/astar_spec.rb
75
+ - spec/general_spec.rb
76
+ - spec/priority_queue_spec.rb
77
+ - spec/spec_helper.rb
56
78
  homepage: http://github.com/georgian-se/shortest-path
57
79
  licenses:
58
80
  - MIT
@@ -77,4 +99,8 @@ rubygems_version: 2.3.0
77
99
  signing_key:
78
100
  specification_version: 4
79
101
  summary: finding shortest path
80
- test_files: []
102
+ test_files:
103
+ - spec/astar_spec.rb
104
+ - spec/general_spec.rb
105
+ - spec/priority_queue_spec.rb
106
+ - spec/spec_helper.rb