shortest-path 0.0.1 → 0.0.2

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: 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