simple_graph 0.1.0 → 0.2.0

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/lib/simple_graph.rb CHANGED
@@ -1,7 +1,11 @@
1
1
  require "simple_graph/version"
2
+ require "JSON"
2
3
 
4
+ # Top level namespace for classes provided by this gem
3
5
  module SimpleGraph
6
+ # A class representing a unweighted, undirected graph
4
7
  class Graph
8
+ # A internal class representing a single vertex/node inside a graph
5
9
  class Node
6
10
  def initialize(id:, data:)
7
11
  @data = data
@@ -9,6 +13,7 @@ module SimpleGraph
9
13
  @id = id
10
14
  end
11
15
 
16
+ # Adds a neighbor to the given node
12
17
  def add_neighbor(node)
13
18
  @neighbors << node
14
19
  end
@@ -18,7 +23,6 @@ module SimpleGraph
18
23
  attr_reader :id
19
24
  end
20
25
 
21
- # Constructor
22
26
  def initialize
23
27
  # Our array of internal nodes
24
28
  @nodes = []
@@ -28,6 +32,11 @@ module SimpleGraph
28
32
  @last_id = 0
29
33
  end
30
34
 
35
+ # Remove all nodes from the graph
36
+ def clear
37
+ initialize
38
+ end
39
+
31
40
  # Add a new node to the graph
32
41
  def add_node(id: nil, data: {})
33
42
  id ||= next_id
@@ -58,42 +67,80 @@ module SimpleGraph
58
67
  @nodes_by_id.keys.to_a
59
68
  end
60
69
 
70
+ # Returns a hash of nodes in the graph mapped to node_id => node_data pairs
71
+ def nodes
72
+ @nodes.map { |node| { node.id => node.data } }
73
+ end
74
+
61
75
  # Method to connect 2 nodes
62
76
  def connect_nodes(first, second)
63
77
  @nodes_by_id[first].add_neighbor(@nodes_by_id[second])
64
78
  @nodes_by_id[second].add_neighbor(@nodes_by_id[first])
65
79
  end
66
80
 
81
+ # Checks whether the graph contains a node with the given ID
82
+ def include?(node_id)
83
+ @nodes_by_id.key?(node_id)
84
+ end
85
+
86
+ # Check if two nodes are connected by an edge
87
+ def are_connected?(first, second)
88
+ @nodes_by_id[first].neighbors.include?(@nodes_by_id[second])
89
+ end
90
+
67
91
  # Retrieve the current graph in the DOT format to be used with Graphviz
68
92
  def to_dot_string
69
93
  str = "strict graph {\n"
70
94
 
71
95
  @nodes.each do |node|
72
96
  node.neighbors.each do |neighbor|
73
- str << " \"#{node.data[:name]}\" -- \"#{neighbor.data[:name]}\";\n"
97
+ str << " \"#{node.id}\" -- \"#{neighbor.id}\";\n"
74
98
  end
75
99
  end
76
100
 
77
101
  str << "}"
78
102
  end
79
103
 
80
- def load_from_string(str)
81
- lines = str.lines.map(&:chomp)
104
+ # Dumps the graph to a JSON string
105
+ def to_json
106
+ temp_hash = {
107
+ nodes: {},
108
+ edges: []
109
+ }
110
+
111
+ @nodes.each do |node|
112
+ temp_hash[:nodes][node.id] = node.data
113
+ end
82
114
 
83
- separator_position = lines.index("#")
115
+ @nodes.each do |node|
116
+ node.neighbors.each do |neighbor|
117
+ temp_hash[:edges] << [node.id, neighbor.id]
118
+ end
119
+ end
120
+
121
+ JSON.dump(temp_hash)
122
+ end
84
123
 
85
- nodes = lines[0..separator_position - 1]
86
- edges = lines[separator_position + 1..-1].map(&:split)
124
+ # Loads the graph from a JSON string
125
+ # Returns the number of Nodes imported
126
+ def load_from_json(str)
127
+ temp_hash = JSON.parse(str)
128
+ nodes = temp_hash["nodes"]
129
+ edges = temp_hash["edges"]
87
130
 
88
- nodes.each do |node|
89
- add_node(id: node)
131
+ nodes.each do |node_id, data|
132
+ add_node(id: node_id, data: data)
90
133
  end
91
134
 
92
- edges.each do |edge|
93
- connect_nodes(edge.first, edge.last)
135
+ edges.each do |node_pair|
136
+ # Ignore duplicate edges for now
137
+ connect_nodes(node_pair.first, node_pair.last) unless are_connected?(node_pair.first, node_pair.last)
94
138
  end
139
+
140
+ nodes.length
95
141
  end
96
142
 
143
+ # Returns all the paths between two nodes as found by breadth-first-search
97
144
  def find_paths(source_id, terminal_id)
98
145
  found_paths = []
99
146
 
@@ -121,11 +168,12 @@ module SimpleGraph
121
168
  end
122
169
  end
123
170
 
124
- found_paths.map { |found_path| found_path.map(&:id) }
171
+ found_paths.map { |found_path| found_path.map { |item| { item.id => item.data } } }
125
172
  end
126
173
 
127
174
  private
128
175
 
176
+ # Helper method to autoincrement generated node IDs
129
177
  def next_id
130
178
  @last_id += 1 while @nodes_by_id.keys.include?(@last_id + 1)
131
179
  @last_id += 1
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple_graph
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin Nowald
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-11-23 00:00:00.000000000 Z
11
+ date: 2017-12-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -123,7 +123,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
123
123
  version: '0'
124
124
  requirements: []
125
125
  rubyforge_project:
126
- rubygems_version: 2.6.7
126
+ rubygems_version: 2.5.2
127
127
  signing_key:
128
128
  specification_version: 4
129
129
  summary: A simple graph library for Ruby supporting undirected, unweighted graphs.