networkx 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) 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/.github/workflows/gem-push.yml +45 -0
  9. data/.rspec +0 -1
  10. data/.rubocop.yml +57 -71
  11. data/.yardopts +0 -1
  12. data/README.md +27 -27
  13. data/Rakefile +2 -3
  14. data/lib/networkx/auxillary_functions/cliques.rb +9 -12
  15. data/lib/networkx/auxillary_functions/cycles.rb +17 -7
  16. data/lib/networkx/auxillary_functions/dag.rb +10 -5
  17. data/lib/networkx/auxillary_functions/eccentricity.rb +2 -1
  18. data/lib/networkx/auxillary_functions/mis.rb +2 -2
  19. data/lib/networkx/auxillary_functions/mst.rb +1 -3
  20. data/lib/networkx/auxillary_functions/union_find.rb +92 -12
  21. data/lib/networkx/auxillary_functions/wiener.rb +1 -1
  22. data/lib/networkx/converters/to_csv.rb +1 -3
  23. data/lib/networkx/converters/to_json.rb +0 -2
  24. data/lib/networkx/digraph.rb +55 -49
  25. data/lib/networkx/flow/capacityscaling.rb +29 -35
  26. data/lib/networkx/flow/edmondskarp.rb +17 -15
  27. data/lib/networkx/flow/preflowpush.rb +29 -32
  28. data/lib/networkx/flow/shortestaugmentingpath.rb +17 -20
  29. data/lib/networkx/flow/utils.rb +6 -27
  30. data/lib/networkx/graph.rb +179 -72
  31. data/lib/networkx/link_analysis/hits.rb +9 -9
  32. data/lib/networkx/link_analysis/pagerank.rb +48 -6
  33. data/lib/networkx/multidigraph.rb +90 -81
  34. data/lib/networkx/multigraph.rb +91 -63
  35. data/lib/networkx/operators/all.rb +8 -4
  36. data/lib/networkx/operators/binary.rb +106 -128
  37. data/lib/networkx/operators/product.rb +61 -64
  38. data/lib/networkx/operators/unary.rb +1 -1
  39. data/lib/networkx/others/bridges.rb +30 -0
  40. data/lib/networkx/others/generators.rb +237 -0
  41. data/lib/networkx/others/grid_2d_graph.rb +38 -0
  42. data/lib/networkx/others/info.rb +11 -0
  43. data/lib/networkx/others/number_connected_components.rb +17 -0
  44. data/lib/networkx/others/reads.rb +52 -0
  45. data/lib/networkx/shortest_path/astar.rb +10 -8
  46. data/lib/networkx/shortest_path/dense.rb +1 -3
  47. data/lib/networkx/shortest_path/unweighted.rb +13 -16
  48. data/lib/networkx/shortest_path/weighted.rb +51 -42
  49. data/lib/networkx/to_matrix.rb +2 -3
  50. data/lib/networkx/traversals/bfs.rb +54 -2
  51. data/lib/networkx/traversals/dfs.rb +62 -6
  52. data/lib/networkx/traversals/edge_dfs.rb +36 -12
  53. data/lib/networkx/version.rb +1 -1
  54. data/lib/networkx.rb +7 -1
  55. data/networkx.gemspec +12 -13
  56. metadata +71 -81
  57. data/.rspec_formatter.rb +0 -24
  58. data/.travis.yml +0 -18
  59. data/Guardfile +0 -7
  60. data/RELEASE_POLICY.md +0 -20
@@ -1,21 +1,24 @@
1
- # TODO: Reduce module length
2
-
3
1
  module NetworkX
4
2
  # Helper function to return an arbitrary element from an iterable object
5
3
  def self.arbitrary_element(iterable)
6
- iterable.each { |u| return u }
4
+ if iterable.is_a?(Hash)
5
+ iterable.first[0]
6
+ elsif iterable.respond_to?(:first)
7
+ iterable.first
8
+ elsif iterable.respond_to?(:[])
9
+ iterable[0]
10
+ end
7
11
  end
8
12
 
9
- # TODO: Reduce method complexity and method length
10
-
11
13
  # Helper function to apply the preflow push algorithm
12
14
  def self.preflowpush_impl(graph, source, target, residual, globalrelabel_freq, value_only)
13
- raise ArgumentError, 'Source not in graph!' unless graph.nodes.key?(source)
14
- raise ArgumentError, 'Target not in graph!' unless graph.nodes.key?(target)
15
+ raise ArgumentError, 'Source not in graph!' unless graph.nodes.has_key?(source)
16
+ raise ArgumentError, 'Target not in graph!' unless graph.nodes.has_key?(target)
15
17
  raise ArgumentError, 'Source and Target are same!' if source == target
16
18
 
17
19
  globalrelabel_freq = 0 if globalrelabel_freq.nil?
18
- raise ArgumentError, 'Global Relabel Freq must be nonnegative!' if globalrelabel_freq < 0
20
+ raise ArgumentError, 'Global Relabel Freq must be nonnegative!' if globalrelabel_freq.negative?
21
+
19
22
  r_network = residual.nil? ? build_residual_network(graph) : residual
20
23
  detect_unboundedness(r_network, source, target)
21
24
 
@@ -30,7 +33,7 @@ module NetworkX
30
33
 
31
34
  heights = reverse_bfs(target, residual_pred)
32
35
 
33
- unless heights.key?(source)
36
+ unless heights.has_key?(source)
34
37
  r_network.graph[:flow_value] = 0
35
38
  return r_network
36
39
  end
@@ -42,25 +45,25 @@ module NetworkX
42
45
  grt = GlobalRelabelThreshold.new(n, r_network.size, globalrelabel_freq)
43
46
 
44
47
  residual_nodes.each do |u, u_attrs|
45
- u_attrs[:height] = heights.key?(u) ? heights[u] : (n + 1)
48
+ u_attrs[:height] = heights.has_key?(u) ? heights[u] : (n + 1)
46
49
  u_attrs[:curr_edge] = CurrentEdge.new(residual_adj[u])
47
50
  end
48
51
 
49
52
  residual_adj[source].each do |u, attr|
50
53
  flow = attr[:capacity]
51
- push(source, u, flow, residual_nodes, residual_adj) if flow > 0
54
+ push(source, u, flow, residual_nodes, residual_adj) if flow.positive?
52
55
  end
53
56
 
54
- levels = (0..(2 * n - 1)).map { |_| Level.new }
57
+ levels = (0..((2 * n) - 1)).map { |_| Level.new }
55
58
  residual_nodes.each do |u, attr|
56
59
  if u != source && u != target
57
60
  level = levels[attr[:height]]
58
- residual_nodes[u][:excess] > 0 ? level.active.add(u) : level.inactive.add(u)
61
+ (residual_nodes[u][:excess]).positive? ? level.active.add(u) : level.inactive.add(u)
59
62
  end
60
63
  end
61
64
 
62
65
  height = max_height
63
- while height > 0
66
+ while height.positive?
64
67
  loop do
65
68
  level = levels[height]
66
69
  if level.active.empty?
@@ -116,6 +119,7 @@ module NetworkX
116
119
  def self.activate(node, source, target, levels, residual_nodes)
117
120
  return if node == source || node == target
118
121
  return unless level.inactive.include?(node)
122
+
119
123
  level = levels[residual_nodes[node][:height]]
120
124
  level.inactive.delete(node)
121
125
  level.active.add(node)
@@ -127,10 +131,8 @@ module NetworkX
127
131
  r_adj[u_node].map { |v, attr| attr[:flow] < (attr[:capacity] + 1) ? _nodes[v][:height] : Float::INFINITY }.min
128
132
  end
129
133
 
130
- # TODO: Reduce method complexity and method length
131
-
132
134
  # Helper function for discharging a node
133
- def self.discharge(u_node, is_phase_1, residual_nodes, residual_adj, height, levels, grt, source, target)
135
+ def self.discharge(u_node, is_phase1, residual_nodes, residual_adj, height, levels, grt, source, target)
134
136
  height_val = residual_nodes[u_node][:height]
135
137
  curr_edge = residual_nodes[u_node][:curr_edge]
136
138
  next_height = height_val
@@ -151,7 +153,7 @@ module NetworkX
151
153
  curr_edge.move_to_next
152
154
  rescue StopIteration
153
155
  height_val = relabel(u_node, grt, residual_adj, residual_nodes, source, target, levels)
154
- if is_phase_1 && height_val >= n - 1
156
+ if is_phase1 && height_val >= n - 1
155
157
  levels[height].active.add(u_node)
156
158
  break
157
159
  end
@@ -162,8 +164,6 @@ module NetworkX
162
164
  next_height
163
165
  end
164
166
 
165
- # TODO: Reduce method complexity
166
-
167
167
  # Helper function for applying gap heuristic
168
168
  def self.gap_heuristic(height, levels, residual_nodes)
169
169
  ((height + 1)..(max_height)).each do |idx|
@@ -177,8 +177,6 @@ module NetworkX
177
177
  end
178
178
  end
179
179
 
180
- # TODO: Reduce method complexity and method length
181
-
182
180
  # Helper function for global relabel heuristic
183
181
  def self.global_relabel(from_sink, source, target, residual_nodes, num, levels, residual_pred)
184
182
  src = from_sink ? target : source
@@ -186,7 +184,7 @@ module NetworkX
186
184
  heights.delete(target) unless from_sink
187
185
  max_height = heights.values.max
188
186
  if from_sink
189
- residual_nodes.each { |u, attr| heights[u] = num + 1 if !heights.key?(u) && attr[:height] < num }
187
+ residual_nodes.each { |u, attr| heights[u] = num + 1 if !heights.has_key?(u) && attr[:height] < num }
190
188
  else
191
189
  heights.each_key { |u| heights[u] += num }
192
190
  max_height += num
@@ -195,6 +193,7 @@ module NetworkX
195
193
  heights.each do |u, new_height|
196
194
  old_height = residual_nodes[u][:height]
197
195
  next unless new_height != old_height
196
+
198
197
  if levels[old_height].active.include?(u)
199
198
  levels[old_height].active.delete(u)
200
199
  levels[new_height].active.add(u)
@@ -208,15 +207,13 @@ module NetworkX
208
207
  end
209
208
 
210
209
  # Helper function for augmenting flow
211
- def self.push(node_1, node_2, flow, residual_nodes, residual_adj)
212
- residual_adj[node_1][node_2][:flow] += flow
213
- residual_adj[node_2][node_1][:flow] -= flow
214
- residual_nodes[node_1][:excess] -= flow
215
- residual_nodes[node_2][:excess] += flow
210
+ def self.push(node1, node2, flow, residual_nodes, residual_adj)
211
+ residual_adj[node1][node2][:flow] += flow
212
+ residual_adj[node2][node1][:flow] -= flow
213
+ residual_nodes[node1][:excess] -= flow
214
+ residual_nodes[node2][:excess] += flow
216
215
  end
217
216
 
218
- # TODO: Reduce method length
219
-
220
217
  # Helper function for reverse bfs
221
218
  def self.reverse_bfs(src, residual_pred)
222
219
  heights = {src => 0}
@@ -226,7 +223,7 @@ module NetworkX
226
223
  u, height = q.shift
227
224
  height += 1
228
225
  residual_pred[u].each do |v, attr|
229
- if !heights.key?(v) && attr[:flow] < attr[:capacity]
226
+ if !heights.has_key?(v) && attr[:flow] < attr[:capacity]
230
227
  heights[v] = height
231
228
  q << [v, height]
232
229
  end
@@ -246,7 +243,7 @@ module NetworkX
246
243
  # maximum preflow
247
244
  #
248
245
  # @return [DiGraph] a residual graph containing the flow values
249
- def self.preflowpush(graph, source, target, residual=nil, globalrelabel_freq=1, value_only=false)
246
+ def self.preflowpush(graph, source, target, residual = nil, globalrelabel_freq = 1, value_only = false)
250
247
  preflowpush_impl(graph, source, target, residual, globalrelabel_freq, value_only)
251
248
  end
252
249
  end
@@ -1,12 +1,8 @@
1
- # TODO: Reduce module length
2
-
3
1
  module NetworkX
4
- # TODO: Reduce method complexity and method length
5
-
6
2
  # Helper function for running the shortest augmenting path algorithm
7
3
  def self.shortest_augmenting_path_impl(graph, source, target, residual, two_phase, cutoff)
8
- raise ArgumentError, 'Source is not in the graph!' unless graph.nodes.key?(source)
9
- raise ArgumentError, 'Target is not in the graph!' unless graph.nodes.key?(target)
4
+ raise ArgumentError, 'Source is not in the graph!' unless graph.nodes.has_key?(source)
5
+ raise ArgumentError, 'Target is not in the graph!' unless graph.nodes.has_key?(target)
10
6
  raise ArgumentError, 'Source and Target are the same!' if source == target
11
7
 
12
8
  residual = residual.nil? ? build_residual_network(graph) : residual
@@ -27,14 +23,14 @@ module NetworkX
27
23
  u, height = q.shift
28
24
  height += 1
29
25
  r_pred[u].each do |v, attrs|
30
- if !heights.key?(v) && attrs[:flow] < attrs[:capacity]
26
+ if !heights.has_key?(v) && attrs[:flow] < attrs[:capacity]
31
27
  heights[v] = height
32
28
  q << [v, height]
33
29
  end
34
30
  end
35
31
  end
36
32
 
37
- unless heights.key?(source)
33
+ unless heights.has_key?(source)
38
34
  residual.graph[:flow_value] = 0
39
35
  return residual
40
36
  end
@@ -43,12 +39,11 @@ module NetworkX
43
39
  m = residual.size / 2
44
40
 
45
41
  r_nodes.each do |node, attrs|
46
- attrs[:height] = heights.key?(node) ? heights[node] : n
42
+ attrs[:height] = heights.has_key?(node) ? heights[node] : n
47
43
  attrs[:curr_edge] = CurrentEdge.new(r_adj[node])
48
44
  end
49
45
 
50
- counts = Array.new(2 * n - 1, 0)
51
- counts.fill(0)
46
+ counts = [0] * (2 * n - 1)
52
47
  r_nodes.each_value { |attrs| counts[attrs[:height]] += 1 }
53
48
  inf = graph.graph[:inf]
54
49
 
@@ -56,7 +51,7 @@ module NetworkX
56
51
  flow_value = 0
57
52
  path = [source]
58
53
  u = source
59
- d = two_phase ? n : [m ** 0.5, 2 * n ** (2. / 3)].min.floor
54
+ d = two_phase ? n : [m**0.5, 2 * (n**(2./ 3))].min.floor
60
55
  done = r_nodes[source][:height] >= d
61
56
 
62
57
  until done
@@ -79,12 +74,12 @@ module NetworkX
79
74
  end
80
75
  height = relabel(u, n, r_adj, r_nodes)
81
76
  if u == source && height >= d
82
- if !two_phase
83
- residual.graph[:flow_value] = flow_value
84
- return residual
85
- else
77
+ if two_phase
86
78
  done = true
87
79
  break
80
+ else
81
+ residual.graph[:flow_value] = flow_value
82
+ return residual
88
83
  end
89
84
  end
90
85
  counts[height] += 1
@@ -97,6 +92,7 @@ module NetworkX
97
92
  end
98
93
  end
99
94
  next unless u == target
95
+
100
96
  flow_value += augment(path, inf, r_adj)
101
97
  if flow_value >= cutoff
102
98
  residual.graph[:flow_value] = flow_value
@@ -108,8 +104,6 @@ module NetworkX
108
104
  residual
109
105
  end
110
106
 
111
- # TODO: Reduce method complexity and method length
112
-
113
107
  # Helper function for augmenting flow
114
108
  def augment(path, inf, r_adj)
115
109
  flow = inf
@@ -121,6 +115,7 @@ module NetworkX
121
115
  u = v
122
116
  end
123
117
  raise ArgumentError, 'Infinite capacity path!' if flow * 2 > inf
118
+
124
119
  temp_path = path.clone
125
120
  u = temp_path.shift
126
121
  temp_path.each do |v|
@@ -146,12 +141,14 @@ module NetworkX
146
141
  # @param source [Object] source node
147
142
  # @param target [Object] target node
148
143
  # @param residual [DiGraph, nil] residual graph
149
- # @param value_only [Boolean] if true, compute only the maximum flow value
144
+ # @param _value_only [Boolean] if true, compute only the maximum flow value
150
145
  # @param two_phase [Boolean] if true, two phase variant is used
151
146
  # @param cutoff [Numeric] cutoff value for the algorithm
152
147
  #
153
148
  # @return [DiGraph] a residual graph containing the flow values
154
- def self.shortest_augmenting_path(graph, source, target, residual=nil, _value_only=false, two_phase=false, cutoff=nil)
149
+ def self.shortest_augmenting_path(graph, source, target, residual = nil, \
150
+ _value_only = false, two_phase = false, cutoff = nil)
151
+
155
152
  shortest_augmenting_path_impl(graph, source, target, residual, two_phase, cutoff)
156
153
  end
157
154
  end
@@ -34,9 +34,9 @@ module NetworkX
34
34
 
35
35
  # Helper class for preflow push algorithm
36
36
  class GlobalRelabelThreshold
37
- def initialize(num_1, num_2, freq)
37
+ def initialize(num1, num2, freq)
38
38
  freq = freq.nil? ? Float::INFINITY : freq
39
- @threshold = (num_1 + num_2) / freq
39
+ @threshold = (num1 + num2) / freq
40
40
  @work = 0
41
41
  end
42
42
 
@@ -53,8 +53,6 @@ module NetworkX
53
53
  end
54
54
  end
55
55
 
56
- # TODO: Reduce method complexity and method length
57
-
58
56
  # Builds a residual graph from a constituent graph
59
57
  #
60
58
  # @param graph [DiGraph] a graph
@@ -69,31 +67,13 @@ module NetworkX
69
67
  edge_list = []
70
68
 
71
69
  graph.adj.each do |u, u_edges|
72
- require 'spec_helper'
73
- RSpec.describe NetworkX::DiGraph do
74
- subject { graph }
75
-
76
- let(:graph) { described_class.new }
77
-
78
- before do
79
- graph.add_edge(1, 2)
80
- graph.add_edge(2, 4)
81
- end
82
-
83
- context 'when capacity_scaling is called' do
84
- subject { NetworkX.capacity_scaling(graph) }
85
-
86
- it { is_expected.to eq([0, {1=>{2=>0}, 2=>{4=>0}, 4=>{}}]) }
87
- end
88
- end
89
-
90
70
  u_edges.each do |v, uv_attrs|
91
- edge_list << [u, v, uv_attrs] if (uv_attrs[:capacity] || inf) > 0 && u != v
71
+ edge_list << [u, v, uv_attrs] if (uv_attrs[:capacity] || inf).positive? && u != v
92
72
  end
93
73
  end
94
74
 
95
75
  inf_chk = 3 * edge_list.inject(0) do |result, arr|
96
- arr[2].key?(:capacity) && arr[2][:capacity] != inf ? (result + arr[2][:capacity]) : result
76
+ arr[2].has_key?(:capacity) && arr[2][:capacity] != inf ? (result + arr[2][:capacity]) : result
97
77
  end
98
78
  inf = inf_chk.zero? ? 1 : inf_chk
99
79
 
@@ -118,8 +98,6 @@ module NetworkX
118
98
  r_network
119
99
  end
120
100
 
121
- # TODO: Reduce method complexity and method length
122
-
123
101
  # Detects unboundedness in a graph, raises exception when
124
102
  # infinite capacity flow is found
125
103
  #
@@ -135,6 +113,7 @@ module NetworkX
135
113
  r_network.adj[u].each do |v, uv_attrs|
136
114
  next unless uv_attrs[:capacity] == inf && !seen.include?(v)
137
115
  raise ArgumentError, 'Infinite capacity flow!' if v == target
116
+
138
117
  seen << v
139
118
  q << v
140
119
  end
@@ -153,7 +132,7 @@ module NetworkX
153
132
  graph.edges.each do |u, u_edges|
154
133
  flow_dict[u] = {}
155
134
  u_edges.each_key { |v| flow_dict[u][v] = 0 }
156
- u_edges.each_key { |v| flow_dict[u][v] = residual[u][v][:flow] if residual[u][v][:flow] > 0 }
135
+ u_edges.each_key { |v| flow_dict[u][v] = residual[u][v][:flow] if (residual[u][v][:flow]).positive? }
157
136
  end
158
137
  flow_dict
159
138
  end