mvgraph 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
File without changes
@@ -0,0 +1,10 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ ruby-graphviz (0.9.21)
5
+
6
+ PLATFORMS
7
+ ruby
8
+
9
+ DEPENDENCIES
10
+ ruby-graphviz
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2011 Daniel Vingo, Jonathan McKenzie
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,2 @@
1
+ mvGraph is an implementation of the graph data structure in Ruby. It was created to solve
2
+ some classic AI search problems; as such, it currently supports BFS, DFS, any user-defined heuristic search, as well as A*.
@@ -0,0 +1,26 @@
1
+ require 'rake/gempackagetask'
2
+
3
+ spec = Gem::Specification.new do |s|
4
+ s.name = "mvgraph"
5
+ s.summary = "A generic graph implementation, useful for solving problems where some sort of search is needed."
6
+ s.description = File.read(File.join(File.dirname(__FILE__), 'README'))
7
+ s.requirements = [ 'None' ]
8
+ s.version = "0.0.1"
9
+ s.author = "Jon Mckenzie, Dan Vingo"
10
+ s.email = "danvingo@gmail.com"
11
+ s.homepage = ""
12
+ s.platform = Gem::Platform::RUBY
13
+ s.required_ruby_version = '>=1.9.2p180'
14
+ s.files = Dir['**/**']
15
+ s.executables = []
16
+ s.test_files = Dir["test/test*.rb"]
17
+ s.has_rdoc = false
18
+ end
19
+ Rake::GemPackageTask.new(spec).define
20
+
21
+ task :default => [:test]
22
+
23
+ task :test do
24
+ ruby "test/test_mvQueue.rb"
25
+ ruby "test/test_mvGraph.rb"
26
+ end
@@ -0,0 +1,42 @@
1
+ The graph is currently implemented in an undirected manner, such that
2
+ adding an edge will add edges in both directions, this can easily be changed
3
+ for example to implement a directed graph, or if you desire the behavior to
4
+ explicitly set edges in both directions for two vertices.
5
+ ==============
6
+ New Features
7
+ ==============
8
+ -Graph Visualization
9
+ -Output
10
+ -ASCII
11
+ -JSON
12
+ -OpenGL/WebGL
13
+ -Static image (png, jpeg, etc.)
14
+ -Graph Methods
15
+ -Search
16
+ *-Breadth-first
17
+ *-Shortest-path
18
+ *-Depth-first
19
+ -Iterative Depth-first
20
+ *-Best-first
21
+ -Greedy
22
+ -A*
23
+ -Database
24
+ -Back-end representation
25
+ -Give the option to use adjacency list or adjacency matrix to use more memory but make the search faster
26
+ -Sub/Supertypes
27
+ -Simple
28
+ -Directed
29
+ -Weighted-edges
30
+ -Hypergraph
31
+ -Toy implementations
32
+ -Slide puzzle
33
+ -Chess/checkers
34
+ -Perfomance enhancements
35
+ -Hash function to compare states instead of nxn linear search of the grid size when testing equality.
36
+
37
+ ======
38
+ TODO
39
+ ======
40
+ - Add a README
41
+ - Setup Rake tasks for testing with nPuzzle and mvGraph together.
42
+
@@ -0,0 +1,202 @@
1
+ require_relative 'mvQueue.rb'
2
+ class Graph
3
+ include Enumerable
4
+ def each
5
+ @adj_matrix.keys.each do |vertex|
6
+ yield vertex
7
+ end
8
+ end
9
+
10
+ def neighbors_of(vertex)
11
+ @adj_matrix[vertex].select { |v| has_edge?(vertex, v) }.keys
12
+ end
13
+
14
+ def initialize
15
+ @adj_matrix = Hash.new
16
+ end
17
+
18
+ def add_vertex(v)
19
+ @adj_matrix[v] = Hash.new
20
+ end
21
+
22
+ def vertex(v)
23
+ @adj_matrix.find { |vertex| vertex[0] == v }[0]
24
+ end
25
+
26
+ def add_edge(v1, v2)
27
+ if @adj_matrix[v1].nil?
28
+ @adj_matrix[v1] = Hash.new
29
+ end
30
+ if @adj_matrix[v2].nil?
31
+ @adj_matrix[v2] = Hash.new
32
+ end
33
+ @adj_matrix[v2][v1] = 1
34
+ @adj_matrix[v1][v2] = 1
35
+ end
36
+
37
+ def update_vertex(v)
38
+ @adj_matrix[v] = @adj_matrix[vertex(v)]
39
+ end
40
+
41
+ def has_edge?(v1, v2)
42
+ unless @adj_matrix[v1].nil? or @adj_matrix[v1][v2].nil?
43
+ @adj_matrix[v1][v2] == 1
44
+ end
45
+ end
46
+
47
+ #
48
+ # queue_type is one of fifo or lifo
49
+ #
50
+ # Look into passing a hash of arguments
51
+ def search(start_vertex, queue_type, neighbor_function=nil, goal_state=nil, search_depth=nil)
52
+ set_vertex_color(start_vertex, "gray")
53
+ set_vertex_distance(start_vertex, 0)
54
+ queue = Queue.new(queue_type)
55
+ queue.enqueue(get_graph_vertex(start_vertex))
56
+ goal_not_reached = true
57
+ count = 0
58
+ return_goal_state = nil
59
+ while queue.length != 0 and goal_not_reached
60
+ current_vertex = queue.dequeue
61
+ count += 1
62
+ # Full BFS or DFS with no goal state
63
+ if neighbor_function.nil? and search_depth.nil? and goal_state.nil?
64
+ neighbors_of(current_vertex).each do |neighbor|
65
+ if neighbor.color == "white"
66
+ set_vertex_color(get_graph_vertex(neighbor), "gray")
67
+ set_vertex_distance(get_graph_vertex(neighbor), get_vertex_distance(get_graph_vertex(current_vertex)) + 1)
68
+ set_vertex_predecessor(get_graph_vertex(neighbor), get_graph_vertex(current_vertex))
69
+ queue.enqueue(get_graph_vertex(neighbor))
70
+ end
71
+ end
72
+ set_vertex_color(get_graph_vertex(current_vertex), "black")
73
+ # Search for goal_state with no distance limit
74
+ elsif !neighbor_function.nil? and !goal_state.nil? and search_depth.nil?
75
+ neighbors = get_graph_vertex(current_vertex).send(neighbor_function, goal_state)
76
+ neighbors.each do |neighbor|
77
+ unless self.include? neighbor
78
+ self.add_vertex(neighbor)
79
+ self.add_edge(current_vertex, neighbor)
80
+ if neighbor == goal_state
81
+ set_vertex_color(get_graph_vertex(neighbor), "gray")
82
+ set_vertex_distance(get_graph_vertex(neighbor), get_vertex_distance(get_graph_vertex(current_vertex)) + 1)
83
+ set_vertex_predecessor(get_graph_vertex(neighbor), get_graph_vertex(current_vertex))
84
+ puts " a;dslfkj #{return_goal_state} "
85
+ return_goal_state = neighbor
86
+ goal_not_reached = false
87
+ break
88
+ end
89
+ if get_vertex_color(get_graph_vertex(neighbor)) == "white"
90
+ set_vertex_color(get_graph_vertex(neighbor), "gray")
91
+ set_vertex_distance(get_graph_vertex(neighbor), get_vertex_distance(get_graph_vertex(current_vertex)) + 1)
92
+ set_vertex_predecessor(get_graph_vertex(neighbor), get_graph_vertex(current_vertex))
93
+ queue.enqueue(get_graph_vertex(neighbor))
94
+ end
95
+ set_vertex_color(get_graph_vertex(current_vertex), "black")
96
+ end
97
+ end
98
+ # Random walk to a given distance and no goal state
99
+ elsif !neighbor_function.nil? and goal_state.nil? and !search_depth.nil?
100
+ neighbors = get_graph_vertex(current_vertex).send(neighbor_function)
101
+ neighbors.each do |neighbor|
102
+ unless self.include? neighbor
103
+ self.add_vertex(neighbor)
104
+ self.add_edge(current_vertex, neighbor)
105
+ if count == search_depth
106
+ return_goal_state = neighbor
107
+ goal_not_reached = false
108
+ break
109
+ end
110
+ if get_vertex_color(get_graph_vertex(neighbor)) == "white"
111
+ set_vertex_color(get_graph_vertex(neighbor), "gray")
112
+ set_vertex_distance(get_graph_vertex(neighbor), get_vertex_distance(get_graph_vertex(current_vertex)) + 1)
113
+ set_vertex_predecessor(get_graph_vertex(neighbor), get_graph_vertex(current_vertex))
114
+ queue.enqueue(get_graph_vertex(neighbor))
115
+ end
116
+ set_vertex_color(get_graph_vertex(current_vertex), "black")
117
+ end
118
+ end
119
+ else
120
+ # Other possible prototypes
121
+ end
122
+ end
123
+ puts "return_goal_state: #{return_goal_state}"
124
+ return return_goal_state, count
125
+ end
126
+
127
+ # Performs depth-first search to the given depth, starting at the vertex start_state.
128
+ def walk_n_steps(start_state, neighbor_function, depth)
129
+ search(start_state, "lifo", neighbor_function, nil, depth)
130
+ end
131
+
132
+ #
133
+ # Precondition: BFS has been run on the graph
134
+ #
135
+ def shortest_path(start_vertex, end_vertex)
136
+ @ret_array ||= []
137
+ predecessor = get_vertex_predecessor(get_graph_vertex(end_vertex))
138
+ if start_vertex == end_vertex
139
+ @ret_array << get_graph_vertex(start_vertex)
140
+ elsif predecessor.nil?
141
+ "No path."
142
+ else
143
+ shortest_path(get_graph_vertex(start_vertex), predecessor)
144
+ @ret_array << get_graph_vertex(end_vertex)
145
+ end
146
+ end
147
+
148
+ def set_vertex_color(v, color)
149
+ get_graph_vertex(v).color = color
150
+ end
151
+
152
+ def get_vertex_color(v)
153
+ get_graph_vertex(v).color
154
+ end
155
+
156
+ def set_vertex_distance(v, distance)
157
+ get_graph_vertex(v).distance = distance
158
+ end
159
+
160
+ def get_vertex_distance(v)
161
+ get_graph_vertex(v).distance
162
+ end
163
+
164
+ def set_vertex_predecessor(v, predecessor)
165
+ get_graph_vertex(v).predecessor = get_graph_vertex(predecessor) unless predecessor.nil?
166
+ end
167
+
168
+ def get_vertex_predecessor(v)
169
+ get_graph_vertex(v).predecessor
170
+ end
171
+
172
+ private
173
+ def get_graph_vertex(v)
174
+ @adj_matrix.find { |vertex| vertex[0] == v }[0]
175
+ end
176
+ end
177
+
178
+ class Vertex
179
+ attr_accessor :id, :color, :distance, :predecessor
180
+ def initialize(id)
181
+ @id = id
182
+ @color = "white"
183
+ @distance = 2**32
184
+ @predecessor = nil
185
+ end
186
+
187
+ def ==(other_vertex)
188
+ @id == other_vertex.id
189
+ end
190
+
191
+ def eql?(other_vertex)
192
+ @id == other_vertex.id
193
+ end
194
+
195
+ def hash
196
+ @id.hash
197
+ end
198
+
199
+ def to_s
200
+ "id: #{@id}, color: #{@color}, distance: #{@distance}, predecessor: \n\t\t #{@predecessor}"
201
+ end
202
+ end
@@ -0,0 +1,29 @@
1
+ class Queue < Array
2
+ def initialize(type)
3
+ super()
4
+ @type = type
5
+ @func_map = {"fi" => Proc.new{ |item| self.insert(0, item) }, "li" => Proc.new{ |item| self << item }, "fo" => Proc.new{ self.pop }, "lo" => Proc.new{ delete_at(0) },
6
+ "be" => Proc.new do |item|
7
+ self.insert(0, item)
8
+ self.sort_by! { |state| state.score }
9
+ end
10
+ }
11
+ end
12
+
13
+ def enqueue(item)
14
+ @func_map[@type[0..1]].call(item)
15
+ end
16
+
17
+ def dequeue
18
+ @func_map[@type[2..3]].call()
19
+ end
20
+
21
+ def to_s
22
+ the_string = ""
23
+ self.each do |item|
24
+ the_string += item.to_s
25
+ the_string += ","
26
+ end
27
+ the_string[0..the_string.size()-2]
28
+ end
29
+ end
@@ -0,0 +1,183 @@
1
+ require 'minitest/autorun'
2
+ require_relative '../lib/mvGraph.rb'
3
+
4
+ class TestGraph < MiniTest::Unit::TestCase
5
+ def setup
6
+ @graph = Graph.new
7
+ @vertex = Vertex.new(1)
8
+ end
9
+
10
+ def test_create_graph
11
+ assert @graph
12
+ end
13
+
14
+ def test_create_vertex
15
+ assert @vertex
16
+ end
17
+
18
+ def test_vertex_id
19
+ @vertex.id = 1
20
+ assert @vertex.id == 1
21
+ end
22
+
23
+ def test_add_vertex
24
+ @graph.add_vertex(Vertex.new(1))
25
+ assert @graph.vertex(Vertex.new(1))
26
+ end
27
+
28
+ def test_add_edge
29
+ vertex1 = Vertex.new(1)
30
+ @graph.add_vertex(vertex1)
31
+ @graph.add_vertex(Vertex.new(2))
32
+ @graph.add_edge(vertex1, Vertex.new(2))
33
+ assert @graph.has_edge?(Vertex.new(1), Vertex.new(2))
34
+ assert @graph.has_edge?(Vertex.new(2), Vertex.new(1))
35
+ end
36
+
37
+ def test_no_edge
38
+ refute @graph.has_edge?(Vertex.new(3),Vertex.new(4))
39
+ end
40
+
41
+ def test_add_multiple_vertices_and_edges
42
+ @graph.add_vertex(Vertex.new(1))
43
+ @graph.add_vertex(Vertex.new(2))
44
+ @graph.add_edge(Vertex.new(2),Vertex.new(1))
45
+ @graph.add_vertex(Vertex.new(3))
46
+ @graph.add_vertex(Vertex.new(4))
47
+ @graph.add_edge(Vertex.new(3),Vertex.new(4))
48
+ @graph.add_edge(Vertex.new(1),Vertex.new(4))
49
+ @graph.add_edge(Vertex.new(3),Vertex.new(2))
50
+ assert @graph.has_edge?(Vertex.new(1),Vertex.new(2))
51
+ assert @graph.has_edge?(Vertex.new(3),Vertex.new(4))
52
+ assert @graph.has_edge?(Vertex.new(4),Vertex.new(1))
53
+ assert @graph.has_edge?(Vertex.new(3),Vertex.new(2))
54
+ end
55
+
56
+ def test_loop
57
+ @graph.add_vertex(Vertex.new(1))
58
+ @graph.add_edge(Vertex.new(1),Vertex.new(1))
59
+ assert @graph.has_edge?(Vertex.new(1),Vertex.new(1)), "@graph should have the edge just added."
60
+ end
61
+
62
+ def test_vertex_equal
63
+ assert Vertex.new(1).eql? Vertex.new(1)
64
+ assert Vertex.new("12345").eql? Vertex.new("12345")
65
+ end
66
+
67
+ def bfs_setup_hard
68
+ @bfs_graph = Graph.new
69
+ @bfs_graph.add_vertex(Vertex.new(1))
70
+ @bfs_graph.add_vertex(Vertex.new(2))
71
+ @bfs_graph.add_vertex(Vertex.new(3))
72
+ @bfs_graph.add_vertex(Vertex.new(4))
73
+ @bfs_graph.add_vertex(Vertex.new(5))
74
+ @bfs_graph.add_vertex(Vertex.new(6))
75
+ @bfs_graph.add_vertex(Vertex.new(7))
76
+ @bfs_graph.add_vertex(Vertex.new(8))
77
+ @bfs_graph.add_vertex(Vertex.new(9))
78
+ @bfs_graph.add_vertex(Vertex.new(10))
79
+ @bfs_graph.add_vertex(Vertex.new(11))
80
+
81
+ @bfs_graph.add_edge(Vertex.new(1),Vertex.new(2))
82
+ @bfs_graph.add_edge(Vertex.new(1),Vertex.new(3))
83
+ @bfs_graph.add_edge(Vertex.new(1),Vertex.new(4))
84
+ @bfs_graph.add_edge(Vertex.new(2),Vertex.new(5))
85
+ @bfs_graph.add_edge(Vertex.new(5),Vertex.new(6))
86
+ @bfs_graph.add_edge(Vertex.new(6),Vertex.new(7))
87
+ @bfs_graph.add_edge(Vertex.new(7),Vertex.new(8))
88
+ @bfs_graph.add_edge(Vertex.new(11),Vertex.new(8))
89
+ @bfs_graph.add_edge(Vertex.new(10),Vertex.new(5))
90
+ @bfs_graph.add_edge(Vertex.new(10),Vertex.new(9))
91
+ @bfs_graph.add_edge(Vertex.new(11),Vertex.new(9))
92
+ end
93
+
94
+ def bfs_setup_easy
95
+ @bfs_graph = Graph.new
96
+ @bfs_graph.add_vertex(Vertex.new(1))
97
+ @bfs_graph.add_vertex(Vertex.new(2))
98
+ @bfs_graph.add_vertex(Vertex.new(3))
99
+ @bfs_graph.add_vertex(Vertex.new(4))
100
+ @bfs_graph.add_edge(Vertex.new(1), Vertex.new(2))
101
+ @bfs_graph.add_edge(Vertex.new(1), Vertex.new(3))
102
+ @bfs_graph.add_edge(Vertex.new(1), Vertex.new(4))
103
+ end
104
+
105
+ #def test_bfs
106
+ # bfs_setup_hard
107
+ # assert @bfs_graph
108
+ # @bfs_graph.search(Vertex.new(1), "fifo")
109
+ # assert_equal "black", @bfs_graph.vertex(Vertex.new(1)).color
110
+ # assert_equal 0, @bfs_graph.get_vertex_distance(Vertex.new(1))
111
+ # assert_equal nil, @bfs_graph.get_vertex_predecessor(Vertex.new(1))
112
+ # assert_equal @bfs_graph.get_vertex_color(Vertex.new(11)), "black"
113
+ # assert @bfs_graph.get_vertex_distance(Vertex.new(11)) == 5
114
+ # assert @bfs_graph.get_vertex_predecessor(Vertex.new(11)) == Vertex.new(9)
115
+ #end
116
+
117
+ #def test_shortest_path
118
+ # bfs_setup_hard
119
+ # assert @bfs_graph
120
+ # @bfs_graph.search(Vertex.new(1), "fifo")
121
+ # path = @bfs_graph.shortest_path(Vertex.new(1), Vertex.new(11))
122
+ # assert path[0] == Vertex.new(1)
123
+ # assert path[1] == Vertex.new(2)
124
+ # assert path[2] == Vertex.new(5)
125
+ # assert path[3] == Vertex.new(10)
126
+ # assert path[4] == Vertex.new(9)
127
+ # assert path[5] == Vertex.new(11)
128
+ #end
129
+
130
+ #def test_no_shortest_path
131
+ # bfs_setup_hard
132
+ # assert @bfs_graph
133
+ #@bfs_graph.add_vertex(Vertex.new(20))
134
+ #@bfs_graph.search(Vertex.new(1), "fifo")
135
+ #path = @bfs_graph.shortest_path(Vertex.new(1), Vertex.new(20))
136
+ #assert path == "No path."
137
+ #end
138
+
139
+ def test_get_all_vertices
140
+ bfs_setup_easy
141
+ @bfs_graph.each { |vertex| assert vertex }
142
+ end
143
+
144
+ def test_neighbors_of
145
+ bfs_setup_easy
146
+ neighbors = @bfs_graph.neighbors_of(Vertex.new(1))
147
+ assert_equal 2, neighbors[0].id, "First neighbor should be 2."
148
+ assert_equal 3, neighbors[1].id, "Second neighbor should be 3."
149
+ assert_equal 4, neighbors[2].id, "Third neighbor should be 4."
150
+ end
151
+
152
+ def test_vertex_color
153
+ v = Vertex.new(1)
154
+ v.color = "gray"
155
+ @graph.add_vertex(v)
156
+ assert_equal "gray", @graph.vertex(Vertex.new(1)).color
157
+ end
158
+
159
+ def test_vertex_distance
160
+ v = Vertex.new(1)
161
+ v.distance = 100
162
+ @graph.add_vertex(v)
163
+ assert_equal 100, @graph.vertex(Vertex.new(1)).distance
164
+ end
165
+
166
+ def test_vertex_predecessor
167
+ @graph.add_vertex(Vertex.new(1))
168
+ @graph.vertex(Vertex.new(1)).predecessor = "5"
169
+ assert_equal "5", @graph.vertex(Vertex.new(1)).predecessor
170
+ end
171
+
172
+ #def test_dfs
173
+ # bfs_setup_hard
174
+ # assert @bfs_graph
175
+ # @bfs_graph.search(Vertex.new(1), "lifo")
176
+ # assert_equal "black", @bfs_graph.vertex(Vertex.new(1)).color
177
+ # assert_equal 0, @bfs_graph.vertex(Vertex.new(1)).distance
178
+ # assert_equal nil, @bfs_graph.vertex(Vertex.new(1)).predecessor
179
+ # assert_equal @bfs_graph.vertex(Vertex.new(11)).color, "black"
180
+ # assert @bfs_graph.vertex(Vertex.new(11)).distance == 5
181
+ # assert @bfs_graph.vertex(Vertex.new(11)).predecessor == Vertex.new(9)
182
+ #end
183
+ end
@@ -0,0 +1,46 @@
1
+ require 'minitest/autorun'
2
+ require_relative '../lib/mvQueue.rb'
3
+
4
+ class TestQueue < MiniTest::Unit::TestCase
5
+ def setup
6
+ @queue = Queue.new("fifo")
7
+ end
8
+
9
+ def iterate_setup(type)
10
+ @queue = Queue.new(type)
11
+ @queue.enqueue(1)
12
+ @queue.enqueue(2)
13
+ @queue.enqueue(3)
14
+ @queue.enqueue(4)
15
+ @queue.enqueue(5)
16
+ end
17
+
18
+ def test_enqueue_dequeue
19
+ @queue.enqueue("x")
20
+ assert_equal @queue.dequeue, "x"
21
+ end
22
+
23
+ def test_queue_accessor_is_private
24
+ refute @queue.respond_to? :queue
25
+ end
26
+
27
+ def test_iterate_queue
28
+ iterate_setup("fifo")
29
+ assert_equal 1, @queue.dequeue
30
+ assert_equal 2, @queue.dequeue
31
+ assert_equal 3, @queue.dequeue
32
+ assert_equal 4, @queue.dequeue
33
+ assert_equal 5, @queue.dequeue
34
+ assert @queue.empty?
35
+ end
36
+
37
+ def test_to_string
38
+ iterate_setup("fifo")
39
+ assert_equal "5,4,3,2,1", @queue.to_s
40
+ end
41
+
42
+ def test_to_string_stack
43
+ iterate_setup("lifo")
44
+ assert_equal "1,2,3,4,5", @queue.to_s
45
+ end
46
+ end
metadata ADDED
@@ -0,0 +1,62 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mvgraph
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jon Mckenzie, Dan Vingo
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-05-17 00:00:00.000000000 -04:00
13
+ default_executable:
14
+ dependencies: []
15
+ description: ! "mvGraph is an implementation of the graph data structure in Ruby.
16
+ \ It was created to solve \nsome classic AI search problems; as such, it currently
17
+ supports BFS, DFS, any user-defined heuristic search, as well as A*.\n"
18
+ email: danvingo@gmail.com
19
+ executables: []
20
+ extensions: []
21
+ extra_rdoc_files: []
22
+ files:
23
+ - MIT-LICENSE.txt
24
+ - test/test_mvGraph.rb
25
+ - test/test_mvQueue.rb
26
+ - Gemfile.lock
27
+ - Gemfile
28
+ - README
29
+ - doc/design.txt
30
+ - lib/mvQueue.rb
31
+ - lib/mvGraph.rb
32
+ - Rakefile
33
+ has_rdoc: true
34
+ homepage: ''
35
+ licenses: []
36
+ post_install_message:
37
+ rdoc_options: []
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 1.9.2p180
46
+ required_rubygems_version: !ruby/object:Gem::Requirement
47
+ none: false
48
+ requirements:
49
+ - - ! '>='
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ requirements:
53
+ - None
54
+ rubyforge_project:
55
+ rubygems_version: 1.6.2
56
+ signing_key:
57
+ specification_version: 3
58
+ summary: A generic graph implementation, useful for solving problems where some sort
59
+ of search is needed.
60
+ test_files:
61
+ - test/test_mvGraph.rb
62
+ - test/test_mvQueue.rb