networkx 0.1.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +5 -5
  2. data/{CODE_OF_CONDUCT.md → .github/CODE_OF_CONDUCT.md} +0 -0
  3. data/{CONTRIBUTING.md → .github/CONTRIBUTING.md} +20 -10
  4. data/{ISSUE_TEMPLATE.md → .github/ISSUE_TEMPLATE.md} +1 -1
  5. data/{PULL_REQUEST_TEMPLATE.md → .github/PULL_REQUEST_TEMPLATE.md} +2 -4
  6. data/.github/workflows/ci.yml +17 -0
  7. data/.github/workflows/doc.yml +23 -0
  8. data/.rspec +0 -1
  9. data/.rubocop.yml +57 -71
  10. data/.yardopts +0 -1
  11. data/README.md +32 -34
  12. data/Rakefile +2 -3
  13. data/lib/networkx/auxillary_functions/cliques.rb +9 -12
  14. data/lib/networkx/auxillary_functions/cycles.rb +17 -7
  15. data/lib/networkx/auxillary_functions/dag.rb +10 -5
  16. data/lib/networkx/auxillary_functions/eccentricity.rb +2 -1
  17. data/lib/networkx/auxillary_functions/mis.rb +2 -2
  18. data/lib/networkx/auxillary_functions/mst.rb +1 -3
  19. data/lib/networkx/auxillary_functions/union_find.rb +92 -12
  20. data/lib/networkx/auxillary_functions/wiener.rb +1 -1
  21. data/lib/networkx/converters/to_csv.rb +1 -3
  22. data/lib/networkx/converters/to_json.rb +0 -2
  23. data/lib/networkx/digraph.rb +55 -49
  24. data/lib/networkx/flow/capacityscaling.rb +29 -35
  25. data/lib/networkx/flow/edmondskarp.rb +17 -15
  26. data/lib/networkx/flow/preflowpush.rb +29 -32
  27. data/lib/networkx/flow/shortestaugmentingpath.rb +17 -20
  28. data/lib/networkx/flow/utils.rb +6 -27
  29. data/lib/networkx/graph.rb +179 -72
  30. data/lib/networkx/link_analysis/hits.rb +9 -9
  31. data/lib/networkx/link_analysis/pagerank.rb +29 -31
  32. data/lib/networkx/multidigraph.rb +90 -81
  33. data/lib/networkx/multigraph.rb +91 -63
  34. data/lib/networkx/operators/all.rb +8 -4
  35. data/lib/networkx/operators/binary.rb +106 -128
  36. data/lib/networkx/operators/product.rb +61 -64
  37. data/lib/networkx/operators/unary.rb +1 -1
  38. data/lib/networkx/others/bridges.rb +30 -0
  39. data/lib/networkx/others/generators.rb +237 -0
  40. data/lib/networkx/others/grid_2d_graph.rb +38 -0
  41. data/lib/networkx/others/info.rb +11 -0
  42. data/lib/networkx/others/number_connected_components.rb +17 -0
  43. data/lib/networkx/others/reads.rb +52 -0
  44. data/lib/networkx/shortest_path/astar.rb +10 -8
  45. data/lib/networkx/shortest_path/dense.rb +1 -3
  46. data/lib/networkx/shortest_path/unweighted.rb +13 -16
  47. data/lib/networkx/shortest_path/weighted.rb +51 -42
  48. data/lib/networkx/to_matrix.rb +2 -3
  49. data/lib/networkx/traversals/bfs.rb +54 -2
  50. data/lib/networkx/traversals/dfs.rb +62 -6
  51. data/lib/networkx/traversals/edge_dfs.rb +36 -12
  52. data/lib/networkx/version.rb +1 -1
  53. data/lib/networkx.rb +7 -1
  54. data/networkx.gemspec +17 -14
  55. metadata +74 -84
  56. data/.rspec_formatter.rb +0 -24
  57. data/.travis.yml +0 -18
  58. data/Guardfile +0 -7
  59. data/RELEASE_POLICY.md +0 -20
@@ -10,12 +10,13 @@ module NetworkX
10
10
  class MultiDiGraph < DiGraph
11
11
  # Returns a new key
12
12
  #
13
- # @param node_1 [Object] the first node of a given edge
14
- # @param node_2 [Object] the second node of a given edge
15
- def new_edge_key(node_1, node_2)
16
- return 0 if @adj[node_1][node_2].nil?
17
- key = @adj[node_1][node_2].length
18
- key += 1 while @adj[node_1][node_2].key?(key)
13
+ # @param node1 [Object] the first node of a given edge
14
+ # @param node2 [Object] the second node of a given edge
15
+ def new_edge_key(node1, node2)
16
+ return 0 if @adj[node1][node2].nil?
17
+
18
+ key = @adj[node1][node2].length
19
+ key += 1 while @adj[node1][node2].has_key?(key)
19
20
  key
20
21
  end
21
22
 
@@ -27,52 +28,60 @@ module NetworkX
27
28
  # @example Add an edge with no attribute
28
29
  # graph.add_edge("Bangalore", "Chennai")
29
30
  #
30
- # @param node_1 [Object] the first node of the edge
31
- # @param node_2 [Object] the second node of the edge
31
+ # @param node1 [Object] the first node of the edge
32
+ # @param node2 [Object] the second node of the edge
32
33
  # @param edge_attrs [Hash{ Object => Object }] the hash of the edge attributes
33
- def add_edge(node_1, node_2, **edge_attrs)
34
- add_node(node_1)
35
- add_node(node_2)
36
- key = new_edge_key(node_1, node_2)
37
- all_edge_attrs = @adj[node_1][node_2] || {}
34
+ def add_edge(node1, node2, **edge_attrs)
35
+ add_node(node1)
36
+ add_node(node2)
37
+ key = new_edge_key(node1, node2)
38
+ all_edge_attrs = @adj[node1][node2] || {}
38
39
  all_edge_attrs[key] = edge_attrs
39
- @adj[node_1][node_2] = all_edge_attrs
40
- @pred[node_2][node_1] = all_edge_attrs
40
+ @adj[node1][node2] = all_edge_attrs
41
+ @pred[node2][node1] = all_edge_attrs
41
42
  end
42
43
 
43
- # TODO: Reduce method complexity
44
-
45
44
  # Removes edge from the graph
46
45
  #
47
46
  # @example
48
47
  # graph.remove_edge('Noida', 'Bangalore')
49
48
  #
50
- # @param node_1 [Object] the first node of the edge
51
- # @param node_2 [Object] the second node of the edge
52
- def remove_edge(node_1, node_2, key=nil)
53
- if key.nil?
54
- super(node_1, node_2)
55
- return
49
+ # @param node1 [Object] the first node of the edge
50
+ # @param node2 [Object] the second node of the edge
51
+ def remove_edge(node1, node2, key = nil)
52
+ return super(node1, node2) if key.nil?
53
+
54
+ raise KeyError, "#{node1} is not a valid node." unless @nodes.has_key?(node1)
55
+ raise KeyError, "#{node2} is not a valid node" unless @nodes.has_key?(node2)
56
+ raise KeyError, 'The given edge is not a valid one.' unless @adj[node1].has_key?(node2)
57
+ if @adj[node1][node2].none? { |_index, data| data[:key] == key }
58
+ raise KeyError, 'The given edge is not a valid one'
56
59
  end
57
- raise KeyError, "#{node_1} is not a valid node." unless @nodes.key?(node_1)
58
- raise KeyError, "#{node_2} is not a valid node" unless @nodes.key?(node_2)
59
- raise KeyError, 'The given edge is not a valid one.' unless @adj[node_1].key?(node_2)
60
- raise KeyError, 'The given edge is not a valid one.' unless @adj[node_1][node_2].key?(key)
61
- @adj[node_1][node_2].delete(key)
62
- @pred[node_2][node_1].delete(key)
60
+
61
+ @adj[node1][node2].delete_if { |_indx, data| data[:key] == key }
62
+ @pred[node2][node1].delete_if { |_indx, data| data[:key] == key }
63
63
  end
64
64
 
65
65
  # Checks if the the edge consisting of two nodes is present in the graph
66
66
  #
67
67
  # @example
68
- # graph.edge?(node_1, node_2)
68
+ # graph.edge?(node1, node2)
69
69
  #
70
- # @param node_1 [Object] the first node of the edge to be checked
71
- # @param node_2 [Object] the second node of the edge to be checked
70
+ # @param node1 [Object] the first node of the edge to be checked
71
+ # @param node2 [Object] the second node of the edge to be checked
72
72
  # @param key [Integer] the key of the given edge
73
- def edge?(node_1, node_2, key=nil)
74
- super(node_1, node_2) if key.nil?
75
- node?(node_1) && @adj[node_1].key?(node_2) && @adj[node_1][node_2].key?(key)
73
+ def edge?(node1, node2, key = nil)
74
+ return super(node1, node2) if key.nil?
75
+
76
+ node?(node1) && @adj[node1].has_key?(node2) && @adj[node1][node2].has_key?(key)
77
+ end
78
+
79
+ def has_edge?(node1, node2, key = nil)
80
+ return super(node1, node2) if key.nil?
81
+
82
+ return false unless node?(node1) && @adj[node1].has_key?(node2)
83
+
84
+ @adj[node1][node2].any? { |_index, data| data[:key] == key }
76
85
  end
77
86
 
78
87
  # Returns the undirected version of the graph
@@ -80,13 +89,13 @@ module NetworkX
80
89
  # @example
81
90
  # graph.to_undirected
82
91
  def to_undirected
83
- graph = NetworkX::Graph.new(@graph)
84
- @nodes.each { |node, node_attr| graph.add_node(node, node_attr) }
85
- @adj.each do |node_1, node_1_edges|
86
- node_1_edges.each do |node_2, node_1_node_2|
92
+ graph = NetworkX::Graph.new(**@graph)
93
+ @nodes.each { |node, node_attr| graph.add_node(node, **node_attr) }
94
+ @adj.each do |node1, node1_edges|
95
+ node1_edges.each do |node2, node1_node2|
87
96
  edge_attrs = {}
88
- node_1_node_2.each { |_key, attrs| edge_attrs.merge!(attrs) }
89
- graph.add_edge(node_1, node_2, edge_attrs)
97
+ node1_node2.each { |_key, attrs| edge_attrs.merge!(attrs) }
98
+ graph.add_edge(node1, node2, **edge_attrs)
90
99
  end
91
100
  end
92
101
  graph
@@ -97,13 +106,13 @@ module NetworkX
97
106
  # @example
98
107
  # graph.to_directed
99
108
  def to_directed
100
- graph = NetworkX::DiGraph.new(@graph)
101
- @nodes.each { |node, node_attr| graph.add_node(node, node_attr) }
102
- @adj.each do |node_1, node_1_edges|
103
- node_1_edges.each do |node_2, node_1_node_2|
109
+ graph = NetworkX::DiGraph.new(**@graph)
110
+ @nodes.each { |node, node_attr| graph.add_node(node, **node_attr) }
111
+ @adj.each do |node1, node1_edges|
112
+ node1_edges.each do |node2, node1_node2|
104
113
  edge_attrs = {}
105
- node_1_node_2.each { |_key, attrs| edge_attrs.merge!(attrs) }
106
- graph.add_edge(node_1, node_2, edge_attrs)
114
+ node1_node2.each { |_key, attrs| edge_attrs.merge!(attrs) }
115
+ graph.add_edge(node1, node2, **edge_attrs)
107
116
  end
108
117
  end
109
118
  graph
@@ -114,13 +123,11 @@ module NetworkX
114
123
  # @example
115
124
  # graph.to_multigraph
116
125
  def to_multigraph
117
- graph = NetworkX::MultiGraph.new(@graph)
118
- @nodes.each { |node, node_attr| graph.add_node(node, node_attr) }
119
- @adj.each do |node_1, node_1_edges|
120
- node_1_edges.each_key do |node_2, node_1_node_2|
121
- edge_attrs = {}
122
- node_1_node_2.each { |_key, attrs| graph.add_edge(node_1, node_2, attrs) }
123
- graph.add_edge(node_1, node_2, edge_attrs)
126
+ graph = NetworkX::MultiGraph.new(**@graph)
127
+ @nodes.each { |node, node_attr| graph.add_node(node, **node_attr) }
128
+ @adj.each do |node1, node2_edges|
129
+ node2_edges.each do |node2, edges|
130
+ edges.each { |_key, attrs| graph.add_edge(node1, node2, **attrs) }
124
131
  end
125
132
  end
126
133
  graph
@@ -131,10 +138,10 @@ module NetworkX
131
138
  # @example
132
139
  # graph.reverse
133
140
  def reverse
134
- new_graph = NetworkX::MultiDiGraph.new(@graph)
135
- @nodes.each { |node, attrs| new_graph.add_node(node, attrs) }
141
+ new_graph = NetworkX::MultiDiGraph.new(**@graph)
142
+ @nodes.each { |node, attrs| new_graph.add_node(node, **attrs) }
136
143
  @adj.each do |u, u_edges|
137
- u_edges.each { |v, uv_attrs| uv_attrs.each { |_k, edge_attrs| new_graph.add_edge(v, u, edge_attrs) } }
144
+ u_edges.each { |v, uv_attrs| uv_attrs.each { |_k, edge_attrs| new_graph.add_edge(v, u, **edge_attrs) } }
138
145
  end
139
146
  new_graph
140
147
  end
@@ -146,7 +153,7 @@ module NetworkX
146
153
  #
147
154
  # @param node [Object] the node whose in degree is to be calculated
148
155
  def in_degree(node)
149
- @pred[node].values.map(:length).inject(:+)
156
+ @pred[node].values.map(&:length).sum
150
157
  end
151
158
 
152
159
  # Returns out-degree of a given node
@@ -156,7 +163,7 @@ module NetworkX
156
163
  #
157
164
  # @param node [Object] the node whose out degree is to be calculated
158
165
  def out_degree(node)
159
- @adj[node].values.map(:length).inject(:+)
166
+ @adj[node].values.map(&:length).sum
160
167
  end
161
168
 
162
169
  # Returns number of edges
@@ -164,7 +171,7 @@ module NetworkX
164
171
  # @example
165
172
  # graph.number_of_edges
166
173
  def number_of_edges
167
- @adj.values.flat_map(&:values).map(&:length).inject(:+)
174
+ @adj.values.flat_map(&:values).map(&:length).sum
168
175
  end
169
176
 
170
177
  # Returns the size of the graph
@@ -174,19 +181,17 @@ module NetworkX
174
181
  #
175
182
  # @param is_weighted [Bool] if true, method returns sum of weights of all edges
176
183
  # else returns number of edges
177
- def size(is_weighted=false)
184
+ def size(is_weighted = false)
178
185
  if is_weighted
179
186
  graph_size = 0
180
187
  @adj.each do |_, hash_val|
181
- hash_val.each { |_, v| v.each { |_, attrs| graph_size += attrs[:weight] if attrs.key?(:weight) } }
188
+ hash_val.each { |_, v| v.each { |_, attrs| graph_size += attrs[:weight] if attrs.has_key?(:weight) } }
182
189
  end
183
190
  return graph_size
184
191
  end
185
192
  number_of_edges
186
193
  end
187
194
 
188
- # TODO: Reduce method length and method complexity
189
-
190
195
  # Returns subgraph consisting of given array of nodes
191
196
  #
192
197
  # @example
@@ -196,23 +201,22 @@ module NetworkX
196
201
  def subgraph(nodes)
197
202
  case nodes
198
203
  when Array, Set
199
- sub_graph = NetworkX::MultiDiGraph.new(@graph)
204
+ sub_graph = NetworkX::MultiDiGraph.new(**@graph)
200
205
  nodes.each do |u, _|
201
- raise KeyError, "#{u} does not exist in the current graph!" unless @nodes.key?(u)
202
- sub_graph.add_node(u, @nodes[u])
206
+ raise KeyError, "#{u} does not exist in the current graph!" unless @nodes.has_key?(u)
207
+
208
+ sub_graph.add_node(u, **@nodes[u])
203
209
  @adj[u].each do |v, edge_val|
204
- edge_val.each { |_, keyval| sub_graph.add_edge(u, v, keyval) if @adj[u].key?(v) && nodes.include?(v) }
210
+ edge_val.each { |_, keyval| sub_graph.add_edge(u, v, **keyval) if @adj[u].has_key?(v) && nodes.include?(v) }
205
211
  end
206
- return sub_graph
207
212
  end
213
+ sub_graph
208
214
  else
209
- raise ArgumentError, 'Expected Argument to be Array or Set of nodes, '\
215
+ raise ArgumentError, 'Expected Argument to be Array or Set of nodes, ' \
210
216
  "received #{nodes.class.name} instead."
211
217
  end
212
218
  end
213
219
 
214
- # TODO: Reduce method length and method complexity
215
-
216
220
  # Returns subgraph conisting of given edges
217
221
  #
218
222
  # @example
@@ -222,19 +226,24 @@ module NetworkX
222
226
  def edge_subgraph(edges)
223
227
  case edges
224
228
  when Array, Set
225
- sub_graph = NetworkX::MultiDiGraph.new(@graph)
229
+ sub_graph = NetworkX::MultiDiGraph.new(**@graph)
226
230
  edges.each do |u, v|
227
- raise KeyError, "Edge between #{u} and #{v} does not exist in the graph!" unless @nodes.key?(u)\
228
- && @adj[u].key?(v)
229
- sub_graph.add_node(u, @nodes[u])
230
- sub_graph.add_node(v, @nodes[v])
231
- @adj[u][v].each { |_, keyval| sub_graph.add_edge(u, v, keyval) }
231
+ raise KeyError, "Edge between #{u} and #{v} does not exist in the graph!" unless @nodes.has_key?(u) \
232
+ && @adj[u].has_key?(v)
233
+
234
+ sub_graph.add_node(u, **@nodes[u])
235
+ sub_graph.add_node(v, **@nodes[v])
236
+ @adj[u][v].each { |_, keyval| sub_graph.add_edge(u, v, **keyval) }
232
237
  end
233
- return sub_graph
238
+ sub_graph
234
239
  else
235
- raise ArgumentError, 'Expected Argument to be Array or Set of edges, '\
236
- "received #{edges.class.name} instead."
240
+ raise ArgumentError, 'Expected Argument to be Array or Set of edges, ' \
241
+ "received #{edges.class.name} instead."
237
242
  end
238
243
  end
244
+
245
+ def multigraph?
246
+ true
247
+ end
239
248
  end
240
249
  end
@@ -8,12 +8,13 @@ module NetworkX
8
8
  class MultiGraph < Graph
9
9
  # Returns a new key
10
10
  #
11
- # @param node_1 [Object] the first node of a given edge
12
- # @param node_2 [Object] the second node of a given edge
13
- def new_edge_key(node_1, node_2)
14
- return 0 if @adj[node_1][node_2].nil?
15
- key = @adj[node_1][node_2].length
16
- key += 1 while @adj[node_1][node_2].key?(key)
11
+ # @param node1 [Object] the first node of a given edge
12
+ # @param node2 [Object] the second node of a given edge
13
+ def new_edge_key(node1, node2)
14
+ return 0 if @adj[node1][node2].nil?
15
+
16
+ key = @adj[node1][node2].length
17
+ key += 1 while @adj[node1][node2].has_key?(key)
17
18
  key
18
19
  end
19
20
 
@@ -25,39 +26,39 @@ module NetworkX
25
26
  # @example Add an edge with no attribute
26
27
  # graph.add_edge("Bangalore", "Chennai")
27
28
  #
28
- # @param node_1 [Object] the first node of the edge
29
- # @param node_2 [Object] the second node of the edge
29
+ # @param node1 [Object] the first node of the edge
30
+ # @param node2 [Object] the second node of the edge
30
31
  # @param edge_attrs [Hash{ Object => Object }] the hash of the edge attributes
31
- def add_edge(node_1, node_2, **edge_attrs)
32
- add_node(node_1)
33
- add_node(node_2)
34
- key = new_edge_key(node_1, node_2)
35
- all_edge_attrs = @adj[node_1][node_2] || {}
32
+ def add_edge(node1, node2, **edge_attrs)
33
+ add_node(node1)
34
+ add_node(node2)
35
+ key = new_edge_key(node1, node2)
36
+ all_edge_attrs = @adj[node1][node2] || {}
36
37
  all_edge_attrs[key] = edge_attrs
37
- @adj[node_1][node_2] = all_edge_attrs
38
- @adj[node_2][node_1] = all_edge_attrs
38
+ @adj[node1][node2] = all_edge_attrs
39
+ @adj[node2][node1] = all_edge_attrs
39
40
  end
40
41
 
41
- # TODO: Reduce method complexity
42
-
43
42
  # Removes edge from the graph
44
43
  #
45
44
  # @example
46
45
  # graph.remove_edge('Noida', 'Bangalore')
47
46
  #
48
- # @param node_1 [Object] the first node of the edge
49
- # @param node_2 [Object] the second node of the edge
50
- def remove_edge(node_1, node_2, key=nil)
51
- if key.nil?
52
- super(node_1, node_2)
53
- return
47
+ # @param node1 [Object] the first node of the edge
48
+ # @param node2 [Object] the second node of the edge
49
+ def remove_edge(node1, node2, key = nil)
50
+ return super(node1, node2) if key.nil?
51
+
52
+ raise KeyError, "#{node1} is not a valid node." unless @nodes.has_key?(node1)
53
+ raise KeyError, "#{node2} is not a valid node" unless @nodes.has_key?(node2)
54
+ raise KeyError, 'The given edge is not a valid one.' unless @adj[node1].has_key?(node2)
55
+
56
+ if @adj[node1][node2].none? { |_index, data| data[:key] == key }
57
+ raise KeyError, 'The given edge is not a valid one'
54
58
  end
55
- raise KeyError, "#{node_1} is not a valid node." unless @nodes.key?(node_1)
56
- raise KeyError, "#{node_2} is not a valid node" unless @nodes.key?(node_2)
57
- raise KeyError, 'The given edge is not a valid one.' unless @adj[node_1].key?(node_2)
58
- raise KeyError, 'The given edge is not a valid one.' unless @adj[node_1][node_2].key?(key)
59
- @adj[node_1][node_2].delete(key)
60
- @adj[node_2][node_1].delete(key)
59
+
60
+ @adj[node1][node2].delete_if { |_indx, data| data[:key] == key }
61
+ @adj[node2][node1].delete_if { |_indx, data| data[:key] == key }
61
62
  end
62
63
 
63
64
  # Returns the size of the graph
@@ -67,11 +68,11 @@ module NetworkX
67
68
  #
68
69
  # @param is_weighted [Bool] if true, method returns sum of weights of all edges
69
70
  # else returns number of edges
70
- def size(is_weighted=false)
71
+ def size(is_weighted = false)
71
72
  if is_weighted
72
73
  graph_size = 0
73
74
  @adj.each do |_, hash_val|
74
- hash_val.each { |_, v| v.each { |_, attrs| graph_size += attrs[:weight] if attrs.key?(:weight) } }
75
+ hash_val.each { |_, v| v.each { |_, attrs| graph_size += attrs[:weight] if attrs.has_key?(:weight) } }
75
76
  end
76
77
  return graph_size / 2
77
78
  end
@@ -83,20 +84,43 @@ module NetworkX
83
84
  # @example
84
85
  # graph.number_of_edges
85
86
  def number_of_edges
86
- @adj.values.flat_map(&:values).map(&:length).inject(:+) / 2
87
+ @adj.values.flat_map(&:values).map(&:length).sum / 2
87
88
  end
88
89
 
89
90
  # Checks if the the edge consisting of two nodes is present in the graph
90
91
  #
91
92
  # @example
92
- # graph.edge?(node_1, node_2)
93
+ # graph.edge?(node1, node2)
93
94
  #
94
- # @param node_1 [Object] the first node of the edge to be checked
95
- # @param node_2 [Object] the second node of the edge to be checked
95
+ # @param node1 [Object] the first node of the edge to be checked
96
+ # @param node2 [Object] the second node of the edge to be checked
96
97
  # @param key [Integer] the key of the given edge
97
- def edge?(node_1, node_2, key=nil)
98
- super(node_1, node_2) if key.nil?
99
- node?(node_1) && @adj[node_1].key?(node_2) && @adj[node_1][node_2].key?(key)
98
+ def edge?(node1, node2, key = nil)
99
+ return super(node1, node2) if key.nil?
100
+
101
+ node?(node1) && @adj[node1].has_key?(node2) && @adj[node1][node2].has_key?(key)
102
+ end
103
+
104
+ def has_edge?(node1, node2, key = nil)
105
+ return super(node1, node2) if key.nil?
106
+
107
+ return false unless node?(node1) && @adj[node1].has_key?(node2)
108
+
109
+ @adj[node1][node2].any? { |_index, data| data[:key] == key }
110
+ end
111
+
112
+ def each_edge(data: false)
113
+ return enum_for(:each_edge, data: data) unless block_given?
114
+
115
+ @adj.each do |v, ws|
116
+ ws.each do |w, key_and_info|
117
+ next if v > w
118
+
119
+ key_and_info.each do |key, info|
120
+ data ? yield(v, w, key, info) : yield(v, w, key)
121
+ end
122
+ end
123
+ end
100
124
  end
101
125
 
102
126
  # Returns the undirected version of the graph
@@ -104,20 +128,18 @@ module NetworkX
104
128
  # @example
105
129
  # graph.to_undirected
106
130
  def to_undirected
107
- graph = NetworkX::Graph.new(@graph)
108
- @nodes.each { |node, node_attr| graph.add_node(node, node_attr) }
109
- @adj.each do |node_1, node_1_edges|
110
- node_1_edges.each do |node_2, node_1_node_2|
131
+ graph = NetworkX::Graph.new(**@graph)
132
+ @nodes.each { |node, node_attr| graph.add_node(node, **node_attr) }
133
+ @adj.each do |node1, node1_edges|
134
+ node1_edges.each do |node2, node1_node2|
111
135
  edge_attrs = {}
112
- node_1_node_2.each { |_key, attrs| edge_attrs.merge!(attrs) }
113
- graph.add_edge(node_1, node_2, edge_attrs)
136
+ node1_node2.each { |_key, attrs| edge_attrs.merge!(attrs) }
137
+ graph.add_edge(node1, node2, **edge_attrs)
114
138
  end
115
139
  end
116
140
  graph
117
141
  end
118
142
 
119
- # TODO: Reduce method complexity and method length
120
-
121
143
  # Returns subgraph consisting of given array of nodes
122
144
  #
123
145
  # @example
@@ -127,23 +149,24 @@ module NetworkX
127
149
  def subgraph(nodes)
128
150
  case nodes
129
151
  when Array, Set
130
- sub_graph = NetworkX::MultiGraph.new(@graph)
152
+ sub_graph = NetworkX::MultiGraph.new(**@graph)
131
153
  nodes.each do |u, _|
132
- raise KeyError, "#{u} does not exist in the current graph!" unless @nodes.key?(u)
133
- sub_graph.add_node(u, @nodes[u])
154
+ raise KeyError, "#{u} does not exist in the current graph!" unless @nodes.has_key?(u)
155
+
156
+ sub_graph.add_node(u, **@nodes[u])
134
157
  @adj[u].each do |v, edge_val|
135
- edge_val.each { |_, keyval| sub_graph.add_edge(u, v, keyval) if @adj[u].key?(v) && nodes.include?(v) }
158
+ next if u > v
159
+
160
+ edge_val.each { |_, keyval| sub_graph.add_edge(u, v, **keyval) if @adj[u].has_key?(v) && nodes.include?(v) }
136
161
  end
137
- return sub_graph
138
162
  end
163
+ sub_graph
139
164
  else
140
- raise ArgumentError, 'Expected Argument to be Array or Set of nodes, '\
165
+ raise ArgumentError, 'Expected Argument to be Array or Set of nodes, ' \
141
166
  "received #{nodes.class.name} instead."
142
167
  end
143
168
  end
144
169
 
145
- # TODO: Reduce method complexity and method length
146
-
147
170
  # Returns subgraph conisting of given edges
148
171
  #
149
172
  # @example
@@ -153,19 +176,24 @@ module NetworkX
153
176
  def edge_subgraph(edges)
154
177
  case edges
155
178
  when Array, Set
156
- sub_graph = NetworkX::MultiGraph.new(@graph)
179
+ sub_graph = NetworkX::MultiGraph.new(**@graph)
157
180
  edges.each do |u, v|
158
- raise KeyError, "Edge between #{u} and #{v} does not exist in the graph!" unless @nodes.key?(u)\
159
- && @adj[u].key?(v)
160
- sub_graph.add_node(u, @nodes[u])
161
- sub_graph.add_node(v, @nodes[v])
162
- @adj[u][v].each { |_, keyval| sub_graph.add_edge(u, v, keyval) }
181
+ raise KeyError, "Edge between #{u} and #{v} does not exist in the graph!" unless @nodes.has_key?(u) \
182
+ && @adj[u].has_key?(v)
183
+
184
+ sub_graph.add_node(u, **@nodes[u])
185
+ sub_graph.add_node(v, **@nodes[v])
186
+ @adj[u][v].each { |_, keyval| sub_graph.add_edge(u, v, **keyval) }
163
187
  end
164
- return sub_graph
188
+ sub_graph
165
189
  else
166
- raise ArgumentError, 'Expected Argument to be Array or Set of edges, '\
167
- "received #{edges.class.name} instead."
190
+ raise ArgumentError, 'Expected Argument to be Array or Set of edges, ' \
191
+ "received #{edges.class.name} instead."
168
192
  end
169
193
  end
194
+
195
+ def multigraph?
196
+ true
197
+ end
170
198
  end
171
199
  end
@@ -1,11 +1,12 @@
1
1
  module NetworkX
2
2
  # Performs the union of many graphs
3
3
  #
4
- # @param [Array<Graph>, Array<DiGraph>, Array<MultiGraph>, Array<MultiDiGraph>] Array of graphs
4
+ # @param graphs [Array<Graph>, Array<DiGraph>, Array<MultiGraph>, Array<MultiDiGraph>] Array of graphs
5
5
  #
6
6
  # @return [Graph, DiGraph, MultiGraph, MultiDiGraph] union of all the graphs
7
7
  def self.union_all(graphs)
8
8
  raise ArgumentError, 'Argument array is empty' if graphs.empty?
9
+
9
10
  result = graphs.shift
10
11
 
11
12
  graphs.each do |graph|
@@ -16,11 +17,12 @@ module NetworkX
16
17
 
17
18
  # Performs the disjoint union of many graphs
18
19
  #
19
- # @param [Array<Graph>, Array<DiGraph>, Array<MultiGraph>, Array<MultiDiGraph>] Array of graphs
20
+ # @param graphs [Array<Graph>, Array<DiGraph>, Array<MultiGraph>, Array<MultiDiGraph>] Array of graphs
20
21
  #
21
22
  # @return [Graph, DiGraph, MultiGraph, MultiDiGraph] disjoint union of all the graphs
22
23
  def self.disjoint_union_all(graphs)
23
24
  raise ArgumentError, 'Argument array is empty' if graphs.empty?
25
+
24
26
  result = graphs.shift
25
27
 
26
28
  graphs.each do |graph|
@@ -31,11 +33,12 @@ module NetworkX
31
33
 
32
34
  # Performs the intersection of many graphs
33
35
  #
34
- # @param [Array<Graph>, Array<DiGraph>, Array<MultiGraph>, Array<MultiDiGraph>] Array of graphs
36
+ # @param graphs [Array<Graph>, Array<DiGraph>, Array<MultiGraph>, Array<MultiDiGraph>] Array of graphs
35
37
  #
36
38
  # @return [Graph, DiGraph, MultiGraph, MultiDiGraph] intersection of all the graphs
37
39
  def self.intersection_all(graphs)
38
40
  raise ArgumentError, 'Argument array is empty' if graphs.empty?
41
+
39
42
  result = graphs.shift
40
43
 
41
44
  graphs.each do |graph|
@@ -46,11 +49,12 @@ module NetworkX
46
49
 
47
50
  # Performs the composition of many graphs
48
51
  #
49
- # @param [Array<Graph>, Array<DiGraph>, Array<MultiGraph>, Array<MultiDiGraph>] Array of graphs
52
+ # @param graphs [Array<Graph>, Array<DiGraph>, Array<MultiGraph>, Array<MultiDiGraph>] Array of graphs
50
53
  #
51
54
  # @return [Graph, DiGraph, MultiGraph, MultiDiGraph] composition of all the graphs
52
55
  def self.compose_all(graphs)
53
56
  raise ArgumentError, 'Argument array is empty' if graphs.empty?
57
+
54
58
  result = graphs.shift
55
59
 
56
60
  graphs.each do |graph|