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.
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm ruby-1.9.3-head
File without changes
data/README.md CHANGED
@@ -1,18 +1,37 @@
1
1
  # Shortest Path [![Build Status](https://travis-ci.org/dryade/shortest_path.png)](http://travis-ci.org/dryade/shortest_path?branch=master) [![Dependency Status](https://gemnasium.com/dryade/shortest_path.png)](https://gemnasium.com/dryade/shortest_path) [![Code Climate](https://codeclimate.com/github/dryade/shortest_path.png)](https://codeclimate.com/github/dryade/shortest_path)
2
2
 
3
- A* ruby implementation to find shortest path and map in a graph.
3
+ A* ruby implementation to find shortest path and map in a graph with :
4
+ - a timeout to stop research when duration > timeout
5
+ - a context in a hash for each point in the graph
6
+ - the possibility to override default methods
7
+
4
8
 
5
9
  Requirements
6
10
  ------------
7
11
 
8
- This code has been run and tested on Ruby 1.8 and 1.9
12
+ This code has been run and tested on Ruby 1.9
13
+
14
+ External Deps
15
+ -------------
16
+ On Debian/Ubuntu/Kubuntu OS :
17
+ ```sh
18
+ sudo apt-get install git
19
+ ```
9
20
 
10
21
  Installation
11
22
  ------------
12
23
 
13
24
  This package is available in RubyGems and can be installed with:
14
-
15
- gem install shortest_path
25
+ ```sh
26
+ gem install shortest_path
27
+ ```
28
+
29
+ Test
30
+ ----
31
+
32
+ ```sh
33
+ bundle exec rake spec
34
+ ```
16
35
 
17
36
  More Information
18
37
  ----------------
@@ -23,8 +42,40 @@ There is extensive usage documentation available [on the wiki](https://github.co
23
42
  Example Usage
24
43
  -------------
25
44
 
45
+ Create a basic shortest path finder :
46
+ ```ruby
47
+ # Create a graph
48
+ graph = { :a => { :e => 3, :b => 1, :c => 3},
49
+ :b => {:e => 1, :a => 1, :c => 3, :d => 5},
50
+ :c => {:a => 3, :b => 3, :d => 1, :s => 3},
51
+ :d => {:b => 5, :c => 1, :s => 1},
52
+ :e => {:a => 3, :b => 1},
53
+ :s => {:c => 3, :d => 1} }
54
+ }
55
+
56
+ # Create a finder
57
+ finder = ShortestPath::Finder.new(:a, :e).tap do |shortest_path|
58
+ shortest_path.ways_finder = Proc.new { |node| graph[node] }
59
+ end
60
+
61
+ # Change the timeout in seconds
62
+ finder.timeout = 2
63
+
64
+ # Call graph result
65
+ finder.path
66
+
67
+ ```
68
+
69
+ Overwrite shortest path finder :
70
+ ```ruby
71
+
72
+ # TODO : Class that overwrites shortest path finder
26
73
  ...
27
74
 
75
+
76
+ ```
77
+
78
+
28
79
  License
29
80
  -------
30
81
 
@@ -14,7 +14,11 @@ module ShortestPath
14
14
  # Example : { :a => 2, :b => 3 }
15
15
  attr_accessor :ways_finder
16
16
 
17
- def ways(node)
17
+ def refresh_context( node, context)
18
+ {}
19
+ end
20
+
21
+ def ways(node, context={})
18
22
  ways_finder.call node
19
23
  end
20
24
 
@@ -26,17 +30,26 @@ module ShortestPath
26
30
  @previous ||= {}
27
31
  end
28
32
 
33
+ # @context is a hash
34
+ # each node is related to an hash defining the context
35
+ # context is specific to the path solution between departure dans target node
36
+ #
37
+ def context
38
+ @context ||= {}
39
+ end
40
+
29
41
  def search_heuristic(node)
30
42
  shortest_distances[node]
31
43
  end
32
44
 
33
- def follow_way?(node, destination, weight)
45
+ def follow_way?(node, destination, weight, context={})
34
46
  true
35
47
  end
36
48
 
49
+ # timeout is in seconds
37
50
  attr_accessor :timeout
38
51
  attr_reader :begin_at, :end_at
39
-
52
+
40
53
  def timeout?
41
54
  timeout and (duration > timeout)
42
55
  end
@@ -47,7 +60,7 @@ module ShortestPath
47
60
  end
48
61
 
49
62
  def visited?(node)
50
- @visited[node]
63
+ @visited[node]
51
64
  end
52
65
 
53
66
  def visit(node)
@@ -60,15 +73,16 @@ module ShortestPath
60
73
 
61
74
  def path_without_cache
62
75
  @begin_at = Time.now
63
-
76
+
64
77
  visited = {}
65
- pq = PQueue.new do |x,y|
78
+ pq = PQueue.new do |x,y|
66
79
  search_heuristic(x) < search_heuristic(y)
67
80
  end
68
81
 
69
- pq.push(source)
82
+ pq.push( source)
70
83
  visit source
71
84
  shortest_distances[source] = 0
85
+ context[source] = {}
72
86
 
73
87
  not_found = !found?(source)
74
88
 
@@ -79,16 +93,17 @@ module ShortestPath
79
93
  not_found = !found?(v)
80
94
  visit v
81
95
 
82
- weights = ways(v)
96
+ weights = ways(v, context[v])
83
97
  if weights
84
98
  weights.keys.each do |w|
85
99
  if !visited?(w) and
86
100
  weights[w] and
87
- ( shortest_distances[w].nil? || shortest_distances[w] > shortest_distances[v] + weights[w]) and
88
- follow_way?(v, w, weights[w])
101
+ ( shortest_distances[w].nil? || shortest_distances[w] > shortest_distances[v] + weights[w]) and
102
+ follow_way?(v, w, weights[w], context[v])
89
103
  shortest_distances[w] = shortest_distances[v] + weights[w]
90
104
  previous[w] = v
91
- pq.push(w)
105
+ context[w] = refresh_context( w, context[v])
106
+ pq.push( w)
92
107
  end
93
108
  end
94
109
  end
@@ -1,3 +1,3 @@
1
1
  module ShortestPath
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -1,5 +1,17 @@
1
1
  require 'spec_helper'
2
2
 
3
+ class TestContextualFinder < ShortestPath::Finder
4
+ def refresh_context( node, context)
5
+ count = context[:edges_count] ? context[:edges_count] : 0
6
+ return { :edges_count => (count + 1)}
7
+ end
8
+
9
+ def follow_way?(node, destination, weight, context={})
10
+ return context[:edges_count].nil? || context[:edges_count] < 3
11
+ end
12
+
13
+ end
14
+
3
15
  describe ShortestPath::Finder do
4
16
  let(:graph) {
5
17
  { :a => { :e => 3, :b => 1, :c => 3},
@@ -10,6 +22,18 @@ describe ShortestPath::Finder do
10
22
  :s => {:c => 3, :d => 1} }
11
23
  }
12
24
 
25
+ def contextual_shortest_path(source, destination, given_graph = graph)
26
+ TestContextualFinder.new(source, destination).tap do |shortest_path|
27
+ shortest_path.ways_finder = Proc.new { |node| given_graph[node] }
28
+ end.path
29
+ end
30
+
31
+ context "when using an edge_count filter in context " do
32
+ it "should find shortest path in an exemple" do
33
+ contextual_shortest_path(:e, :s).should == [:e, :b, :c, :s]
34
+ end
35
+ end
36
+
13
37
  def shortest_path(source, destination, given_graph = graph)
14
38
  ShortestPath::Finder.new(source, destination).tap do |shortest_path|
15
39
  shortest_path.ways_finder = Proc.new { |node| given_graph[node] }
@@ -38,16 +62,16 @@ describe ShortestPath::Finder do
38
62
  shortest_path(:e, :s, not_connex).should be_empty
39
63
  end
40
64
 
41
- subject {
65
+ subject {
42
66
  ShortestPath::Finder.new(:e, :s).tap do |shortest_path|
43
67
  shortest_path.ways_finder = Proc.new { |node| graph[node] }
44
68
  end
45
69
  }
46
70
 
47
71
  describe "begin_at" do
48
-
72
+
49
73
  let(:expected_time) { Time.now }
50
-
74
+
51
75
  it "should be defined when path starts" do
52
76
  Time.stub :now => expected_time
53
77
  subject.path
@@ -57,9 +81,9 @@ describe ShortestPath::Finder do
57
81
  end
58
82
 
59
83
  describe "end_at" do
60
-
84
+
61
85
  let(:expected_time) { Time.now }
62
-
86
+
63
87
  it "should be defined when path ends" do
64
88
  Time.stub :now => expected_time
65
89
  subject.path
@@ -69,7 +93,7 @@ describe ShortestPath::Finder do
69
93
  end
70
94
 
71
95
  describe "duration" do
72
-
96
+
73
97
  it "should be nil before path is search" do
74
98
  subject.duration.should be_nil
75
99
  end
@@ -99,12 +123,12 @@ describe ShortestPath::Finder do
99
123
  subject.timeout = nil
100
124
  subject.should_not be_timeout
101
125
  end
102
-
126
+
103
127
  it "should be false when duration is lower than timeout" do
104
128
  subject.stub :duration => (subject.timeout - 1)
105
129
  subject.should_not be_timeout
106
130
  end
107
-
131
+
108
132
  it "should be true when duration is greater than timeout" do
109
133
  subject.stub :duration => (subject.timeout + 1)
110
134
  subject.should be_timeout
@@ -113,7 +137,7 @@ describe ShortestPath::Finder do
113
137
  end
114
138
 
115
139
  describe "path" do
116
-
140
+
117
141
  it "should raise a Timeout::Error when timeout?" do
118
142
  subject.stub :timeout? => true
119
143
  lambda { subject.path }.should raise_error(ShortestPath::TimeoutError)
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shortest_path
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 25
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 2
10
- version: 0.0.2
9
+ - 3
10
+ version: 0.0.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - Alban Peignier
@@ -17,7 +17,7 @@ autorequire:
17
17
  bindir: bin
18
18
  cert_chain: []
19
19
 
20
- date: 2013-05-07 00:00:00 Z
20
+ date: 2013-08-12 00:00:00 Z
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency
23
23
  type: :development
@@ -116,10 +116,11 @@ extra_rdoc_files: []
116
116
 
117
117
  files:
118
118
  - .gitignore
119
+ - .rvmrc
119
120
  - .travis.yml
120
121
  - Gemfile
121
122
  - Guardfile
122
- - LICENSE.txt
123
+ - MIT-LICENSE
123
124
  - README.md
124
125
  - Rakefile
125
126
  - lib/shortest_path.rb