Class: NetworkX::Graph

Inherits:
Object
  • Object
show all
Defined in:
lib/networkx/graph.rb,
lib/networkx/others/reads.rb,
lib/networkx/traversals/bfs.rb,
lib/networkx/traversals/dfs.rb,
lib/networkx/others/generators.rb,
lib/networkx/traversals/edge_dfs.rb

Overview

Describes the class for making Undirected Graphs

Direct Known Subclasses

DiGraph, MultiGraph

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(**graph_attrs) ⇒ Graph

Constructor for initializing graph

Examples:

Initialize a graph with attributes 'type' and 'name'

graph = NetworkX::Graph.new(name: "Social Network", type: "undirected")

Parameters:

  • graph_attrs (Hash{ Object => Object })

    the graph attributes in a hash format



16
17
18
19
20
# File 'lib/networkx/graph.rb', line 16

def initialize(**graph_attrs)
  @nodes = {}
  @adj = {}
  @graph = graph_attrs
end

Instance Attribute Details

#adjHash{ Object => Hash{ Object => Hash{ Object => Object } } } (readonly)

Stores the edges and their attributes in an adjencency list form

Returns:

  • (Hash{ Object => Hash{ Object => Hash{ Object => Object } } })

    the current value of adj



7
8
9
# File 'lib/networkx/graph.rb', line 7

def adj
  @adj
end

#graphHash{ Object => Object } (readonly)

Stores the attributes of the graph

Returns:

  • (Hash{ Object => Object })

    the current value of graph



7
8
9
# File 'lib/networkx/graph.rb', line 7

def graph
  @graph
end

Class Method Details

.balanced_tree(r, h) ⇒ Object



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/networkx/others/generators.rb', line 18

def self.balanced_tree(r, h)
  edges = []
  q = [0]
  i = 0
  h.times do
    t = q.dup
    q.clear
    t.each do |v|
      r.times do
        i += 1
        edges << [v, i]
        q << i
      end
    end
  end
  graph = new(name: "balanced_tree(#{r}, #{h})")
  graph.add_edges(edges)
  graph
end

.barbell_graph(m1, m2) ⇒ Object



38
39
40
41
42
43
44
45
46
# File 'lib/networkx/others/generators.rb', line 38

def self.barbell_graph(m1, m2)
  edges = complete_edges(m1)
  edges.concat((m1..m2 + m1).map { |k| [k - 1, k] })
  edges.concat complete_edges(m1 + m2...m1 + m2 + m1)

  graph = new(name: "barbell_graph(#{m1}, #{m2})")
  graph.add_edges(edges)
  graph
end

.bull_graphObject



145
146
147
148
149
150
# File 'lib/networkx/others/generators.rb', line 145

def self.bull_graph
  edges = [[0, 1], [1, 2], [2, 0], [1, 3], [2, 4]]
  graph = new(name: 'bull_graph')
  graph.add_edges(edges)
  graph
end

.circular_ladder_graph(n) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
# File 'lib/networkx/others/generators.rb', line 63

def self.circular_ladder_graph(n)
  edges = (0...n - 1).map { |v| [v, v + 1] }
  edges << [n - 1, 0]
  edges.concat((n...2 * n - 1).map { |v| [v, v + 1] })
  edges << [2 * n - 1, n]
  edges.concat((0...n).map { |v| [v, v + n] })

  graph = new(name: "circular_ladder_graph(#{n})")
  graph.add_edges(edges)
  graph
end

.complete_edges(n) ⇒ Object

private class method



6
7
8
9
10
11
12
13
14
15
16
# File 'lib/networkx/others/generators.rb', line 6

def self.complete_edges(n)
  n = (0...n) if n.is_a?(Integer)

  edges = []
  n.each do |i|
    n.each do |j|
      edges << [i, j] if i < j
    end
  end
  edges
end

.complete_graph(n) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/networkx/others/generators.rb', line 48

def self.complete_graph(n)
  n = (0...n) if n.is_a?(Integer)

  edges = []
  n.each do |i|
    n.each do |j|
      edges << [i, j] if i < j
    end
  end

  graph = new(name: "complete_graph(#{n})")
  graph.add_edges(edges)
  graph
end

.cubical_graphObject



152
153
154
155
156
# File 'lib/networkx/others/generators.rb', line 152

def self.cubical_graph
  graph = circular_ladder_graph(4)
  graph.graph[:name] = 'cubical_graph'
  graph
end

.cycle_graph(n) ⇒ Object



75
76
77
78
79
80
81
82
# File 'lib/networkx/others/generators.rb', line 75

def self.cycle_graph(n)
  edges = (0...n - 1).map { |v| [v, v + 1] }
  edges << [n - 1, 0]

  graph = new(name: "cycle_graph(#{n})")
  graph.add_edges(edges)
  graph
end

.diamond_graphObject



158
159
160
161
162
163
# File 'lib/networkx/others/generators.rb', line 158

def self.diamond_graph
  edges = [[0, 1], [0, 2], [1, 2], [1, 3], [2, 3]]
  graph = new(name: 'diamond_graph')
  graph.add_edges(edges)
  graph
end

.dodecahedral_graphObject

12



166
167
168
169
170
171
172
# File 'lib/networkx/others/generators.rb', line 166

def self.dodecahedral_graph
  edges = (0...19).map { |k| [k, k + 1] }
  edges.concat [[0, 19], [0, 10], [1, 8], [2, 6], [3, 19], [4, 17], [5, 15], [7, 14], [9, 13], [11, 18], [12, 16]]
  graph = new(name: 'dodecahedral_graph')
  graph.add_edges(edges)
  graph
end

.empty_graph(number_of_nodes) ⇒ Object



84
85
86
87
88
# File 'lib/networkx/others/generators.rb', line 84

def self.empty_graph(number_of_nodes)
  empty_graph = new(name: "empty_graph#{number_of_nodes}")
  empty_graph.add_nodes_from(0...number_of_nodes)
  empty_graph
end

.heawood_graphObject



174
175
176
177
178
179
180
181
# File 'lib/networkx/others/generators.rb', line 174

def self.heawood_graph
  edges = (0...13).map { |k| [k, k + 1] }
  edges << [13, 0]
  edges.concat [[0, 5], [1, 10], [2, 7], [3, 12], [4, 9], [6, 11], [8, 13]]
  graph = new(name: 'heawood_graph')
  graph.add_edges(edges)
  graph
end

.house_graphObject



183
184
185
186
187
188
# File 'lib/networkx/others/generators.rb', line 183

def self.house_graph
  edges = [[0, 1], [0, 2], [1, 3], [2, 3], [2, 4], [3, 4]]
  graph = new(name: 'house_graph')
  graph.add_edges(edges)
  graph
end

.house_x_graphObject



190
191
192
193
194
195
196
# File 'lib/networkx/others/generators.rb', line 190

def self.house_x_graph
  edges = (0...4).map { |k| [k, k + 1] }
  edges.concat [[0, 2], [0, 3], [1, 3], [2, 4], [3, 4]]
  graph = new(name: 'house_x_graph')
  graph.add_edges(edges)
  graph
end

.ladder_graph(n) ⇒ Object



90
91
92
93
94
95
96
97
98
# File 'lib/networkx/others/generators.rb', line 90

def self.ladder_graph(n)
  edges = (0...n - 1).map { |k| [k, k + 1] }
  edges.concat((n...2 * n - 1).map { |k| [k, k + 1] })
  edges.concat((0...n).map { |k| [k, k + n] })

  graph = new(name: "ladder_graph(#{n})")
  graph.add_edges(edges)
  graph
end

.lollipop_graph(m, n) ⇒ Object



100
101
102
103
104
105
106
107
# File 'lib/networkx/others/generators.rb', line 100

def self.lollipop_graph(m, n)
  edges = complete_edges(m)
  edges.concat((m - 1...m - 1 + n).map { |v| [v, v + 1] })

  graph = new(name: "lollipop_graph(#{m}, #{n})")
  graph.add_edges(edges)
  graph
end

.moebius_kantor_graphObject



198
199
200
201
202
203
204
205
# File 'lib/networkx/others/generators.rb', line 198

def self.moebius_kantor_graph
  edges = (0...15).map { |k| [k, k + 1] }
  edges << [15, 0]
  edges.concat [[0, 5], [1, 12], [2, 7], [4, 9], [3, 14], [6, 11], [8, 13], [10, 15]]
  graph = new(name: 'moebius_kantor_graph')
  graph.add_edges(edges)
  graph
end

.null_graphObject



109
110
111
# File 'lib/networkx/others/generators.rb', line 109

def self.null_graph
  new(name: 'null_graph')
end

.octahedral_graphObject

8: 6 nodes, 12 edges



208
209
210
211
212
213
214
215
216
217
218
# File 'lib/networkx/others/generators.rb', line 208

def self.octahedral_graph
  edges = []
  6.times do |i|
    6.times do |j|
      edges << [i, j] if i != j && i + j != 5
    end
  end
  graph = new(name: 'octahedral_graph')
  graph.add_edges(edges)
  graph
end

.path_graph(n) ⇒ Object



113
114
115
116
117
118
119
# File 'lib/networkx/others/generators.rb', line 113

def self.path_graph(n)
  edges = (0...n - 1).map { |v| [v, v + 1] }

  graph = new(name: "path_graph(#{n})")
  graph.add_edges(edges)
  graph
end

.read_edgelist(path, comment: '#', delimiter: nil) ⇒ Object Also known as: read_edges



6
7
8
9
10
11
12
13
14
15
16
17
# File 'lib/networkx/others/reads.rb', line 6

def read_edgelist(path, comment: '#', delimiter: nil)
  edges = File.readlines(path).filter_map do |line|
    line.sub!(/#{comment}.+/, '')
    line.strip.split(delimiter) if line.strip.size > 0
  end

  edges.each{|edge| edge.map!{|node| NetworkX.to_number_if_possible(node) } }

  graph = new
  graph.add_edges(edges)
  graph
end

.read_weighted_edgelist(path, comment: '#', delimiter: nil) ⇒ Object Also known as: read_weighted_edges



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/networkx/others/reads.rb', line 20

def read_weighted_edgelist(path, comment: '#', delimiter: nil)
  edges = File.readlines(path).filter_map do |line|
    line.sub!(/#{comment}.+/, '')
    line.strip.split(delimiter) if line.strip.size > 0
  end

  edges.map! do |x, y, weight|
    [
      NetworkX.to_number_if_possible(x),
      NetworkX.to_number_if_possible(y),
      {weight: NetworkX.to_number_if_possible(weight)}
    ]
  end

  graph = new
  graph.add_edges(edges)
  graph
end

.star_graph(n) ⇒ Object



121
122
123
124
125
126
127
# File 'lib/networkx/others/generators.rb', line 121

def self.star_graph(n)
  edges = (1..n).map { |i| [0, i] }

  graph = new(name: "star_graph(#{n})")
  graph.add_edges(edges)
  graph
end

.tetrahedral_graphObject



220
221
222
223
224
# File 'lib/networkx/others/generators.rb', line 220

def self.tetrahedral_graph
  graph = complete_graph(4)
  graph.graph[:name] = 'tetrahedral_graph'
  graph
end

.trivial_graphObject



129
130
131
132
133
# File 'lib/networkx/others/generators.rb', line 129

def self.trivial_graph
  trivial_graph = new(name: 'trivial_grpph')
  trivial_graph.add_node(0)
  trivial_graph
end

.wheel_graph(n) ⇒ Object



135
136
137
138
139
140
141
142
143
# File 'lib/networkx/others/generators.rb', line 135

def self.wheel_graph(n)
  edges = (1..n - 1).map { |i| [0, i] }
  edges.concat((1...n - 1).map { |i| [i, i + 1] })
  edges << [1, n - 1]

  graph = new(name: "wheel_graph(#{n})")
  graph.add_edges(edges)
  graph
end

Instance Method Details

#add_edge(node1, node2, **edge_attrs) ⇒ Object

Adds the respective edges

Examples:

Add an edge with attribute name

graph.add_edge(node1, node2, name: "Edge1")

Add an edge with no attribute

graph.add_edge("Bangalore", "Chennai")

Parameters:

  • node1 (Object)

    the first node of the edge

  • node2 (Object)

    the second node of the edge

  • edge_attrs (Hash{ Object => Object })

    the hash of the edge attributes



33
34
35
36
37
38
39
40
# File 'lib/networkx/graph.rb', line 33

def add_edge(node1, node2, **edge_attrs)
  add_node(node1)
  add_node(node2)

  edge_attrs = (@adj[node1][node2] || {}).merge(edge_attrs)
  @adj[node1][node2] = edge_attrs
  @adj[node2][node1] = edge_attrs
end

#add_edges(edges) ⇒ Object

Adds multiple edges from an array

Examples:

Add multiple edges without any attributes

graph.add_edges([['Nagpur', 'Kgp'], ['Noida', 'Kgp']])

Parameters:

  • edges (Array<Object, Object>)


47
48
49
50
51
52
53
54
55
# File 'lib/networkx/graph.rb', line 47

def add_edges(edges)
  case edges
  when Array
    edges.each { |node1, node2, attrs| add_edge(node1, node2, **(attrs || {})) }
  else
    raise ArgumentError, 'Expected argument to be an Array of edges, ' \
                         "received #{edges.class.name} instead."
  end
end

#add_edges_from(rng) ⇒ Object



57
58
59
# File 'lib/networkx/graph.rb', line 57

def add_edges_from(rng)
  rng.each { |node| add_edge(*node) }
end

#add_node(node, **node_attrs) ⇒ Object

Adds a node and its attributes to the graph

Examples:

Add a node with attribute 'type'

graph.add_node("Noida", type: "city")

Parameters:

  • node (Object)

    the node object

  • node_attrs (Hash{ Object => Object })

    the hash of the attributes of the node



68
69
70
71
72
73
74
75
# File 'lib/networkx/graph.rb', line 68

def add_node(node, **node_attrs)
  if @nodes.has_key?(node)
    @nodes[node].merge!(node_attrs)
  else
    @adj[node] = {}
    @nodes[node] = node_attrs
  end
end

#add_nodes(nodes) ⇒ Object

Adds multiple nodes to the graph

Examples:

Adds multiple nodes with attribute 'type'

graph.add_nodes([["Noida", type: "city"], ["Kgp", type: "town"]])

Parameters:

  • nodes (Array<Object, Hash{ Object => Object }>)

    the Array of pair containing nodes and its attributes



83
84
85
86
87
88
89
90
91
92
93
# File 'lib/networkx/graph.rb', line 83

def add_nodes(nodes)
  case nodes
  when Set, Array
    nodes.each { |node, node_attrs| add_node(node, **(node_attrs || {})) }
  when Range
    nodes.each { |node| add_node(node) }
  else
    raise ArgumentError, 'Expected argument to be an Array/Set/Range of nodes, ' \
                         "received #{nodes.class.name} instead."
  end
end

#add_nodes_from(nodes_for_adding) ⇒ Object

[TODO][EXPERIMENTAL]

Parameters:

  • nodes_for_adding (Array | Range | String)

    nodes



98
99
100
101
102
103
104
105
# File 'lib/networkx/graph.rb', line 98

def add_nodes_from(nodes_for_adding)
  case nodes_for_adding
  when String
    nodes_for_adding.each_char { |node| add_node(node) }
  else
    nodes_for_adding.each { |node| add_node(node) }
  end
end

#add_path(paths) ⇒ Object



107
108
109
# File 'lib/networkx/graph.rb', line 107

def add_path(paths)
  paths.each_cons(2){|x, y| add_edge(x, y) }
end

#add_weighted_edge(node1, node2, weight) ⇒ Object

Adds weighted edge

Examples:

graph.add_weighted_edge('Noida', 'Bangalore', 1000)

Parameters:

  • node1 (Object)

    the first node of the edge

  • node2 (Object)

    the second node of the edge

  • weight (Integer)

    the weight value



183
184
185
# File 'lib/networkx/graph.rb', line 183

def add_weighted_edge(node1, node2, weight)
  add_edge(node1, node2, weight: weight)
end

#add_weighted_edges(edges, weights) ⇒ Object

Adds multiple weighted edges

Examples:

graph.add_weighted_edges([['Noida', 'Bangalore'],
                          ['Noida', 'Nagpur']], [1000, 2000])

Parameters:

  • edges (Array<Object, Object>)

    the array of edges

  • weights (Array<Integer>)

    the array of weights

Raises:

  • (ArgumentError)


195
196
197
198
199
200
201
202
203
204
# File 'lib/networkx/graph.rb', line 195

def add_weighted_edges(edges, weights)
  raise ArgumentError, 'edges and weights array must have equal number of elements.' \
                       unless edges.size == weights.size
  raise ArgumentError, 'edges and weight must be given in an Array.' \
                       unless edges.is_a?(Array) && weights.is_a?(Array)

  (edges.transpose << weights).transpose.each do |node1, node2, weight|
    add_weighted_edge(node1, node2, weight)
  end
end

#add_weighted_edges_from(edges, weight: :weight) ⇒ Object

[TODO][EXPERIMENTAL]

Parameters:

  • edges ([Object, Object, Integer|Float])

    the weight of edge

  • weight (Symbol) (defaults to: :weight)

    weight name key. default key is :weight`



210
211
212
213
214
# File 'lib/networkx/graph.rb', line 210

def add_weighted_edges_from(edges, weight: :weight)
  edges.each do |s, t, w|
    add_edge(s, t, **{weight => w})
  end
end

#bfs_edges(node) ⇒ Object

[EXPERIMENTAL]

Parameters:

  • node (Object)

    which is root, start ,source



84
85
86
# File 'lib/networkx/traversals/bfs.rb', line 84

def bfs_edges(node)
  each_bfs_edge(node).to_a
end

#bfs_nodes(root) ⇒ Object



60
61
62
# File 'lib/networkx/traversals/bfs.rb', line 60

def bfs_nodes(root)
  each_bfs_node(root).to_a
end

#clearObject

Clears the graph

Examples:

graph.clear


270
271
272
273
274
# File 'lib/networkx/graph.rb', line 270

def clear
  @adj.clear
  @nodes.clear
  @graph.clear
end

#degree(nodes = nil) ⇒ Object

[EXPERIMENTAL]



421
422
423
424
425
426
427
428
429
# File 'lib/networkx/graph.rb', line 421

def degree(nodes = nil)
  if nodes.nil?
    @adj.transform_values(&:size)
  else
    res = {}
    nodes.each { |node| res[node] = @adj[node].size }
    res
  end
end

#dfs_edges(node) ⇒ Object



89
90
91
# File 'lib/networkx/traversals/edge_dfs.rb', line 89

def dfs_edges(node)
  each_dfs_edge(node).to_a
end

#dfs_postorder_nodes(root, used = {root => true}) ⇒ Array[Object]

[EXPERIMENTAL]

Parameters:

  • root (Object)

    node which is root, start, source

Returns:

  • (Array[Object])

    array of dfs postorder nodes



115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/networkx/traversals/dfs.rb', line 115

def dfs_postorder_nodes(root, used = {root => true})
  res = []
  @adj[root].each do |v, _data|
    next if used[v]

    used[v] = true
    res.concat dfs_postorder_nodes(v, used)
  end

  res << root
  res
end

#dfs_preorder_nodes(root) ⇒ Array[Object]

[EXPERIMENTAL]

Parameters:

  • root (Object)

    node which is root, start, source

Returns:

  • (Array[Object])

    nodes



86
87
88
# File 'lib/networkx/traversals/dfs.rb', line 86

def dfs_preorder_nodes(root)
  each_dfs_preorder_node(root).to_a
end

#directed?Boolean

Returns:

  • (Boolean)


443
444
445
# File 'lib/networkx/graph.rb', line 443

def directed?
  ['NetworkX::DiGraph', 'NetworkX::MultiDiGraph'].include?(self.class.name)
end

#each_bfs_edge(node) ⇒ Object

[EXPERIMENTAL]

Parameters:

  • node (Object)

    which is root, start ,source



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/networkx/traversals/bfs.rb', line 91

def each_bfs_edge(node)
  return enum_for(:each_bfs_edge, node) unless block_given?

  que = [node]
  used = {node => true}
  while que[0]
    node = que.shift

    @adj[node].each do |v, _data|
      next if used[v]

      used[v] = true

      yield(node, v)
      que << v
    end
  end
end

#each_bfs_node(root) ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/networkx/traversals/bfs.rb', line 64

def each_bfs_node(root)
  return enum_for(:each_bfs_node, root) unless block_given?

  queue = [root]
  dist = {root => 0}
  while (v = queue.shift)
    yield v
    d = dist[v]
    @adj[v].each do |u, _data|
      next if dist[u]

      dist[u] = d + 1
      queue << u
    end
  end
end

#each_dfs_edge(node) ⇒ Object



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/networkx/traversals/edge_dfs.rb', line 93

def each_dfs_edge(node)
  return enum_for(:each_dfs_edge, node) unless block_given?

  st = [node]
  used = {}
  parents = {}
  while st[-1]
    node = st.pop

    yield(parents[node], node) if parents[node]

    used[node] = true
    @adj[node].reverse_each do |v, _data|
      next if used[v]

      parents[v] = node
      st << v unless used[v]
    end
  end
end

#each_dfs_postorder_node(root, &block) ⇒ Object

Parameters:

  • root (Object)

    node which is root, start, source



129
130
131
132
133
# File 'lib/networkx/traversals/dfs.rb', line 129

def each_dfs_postorder_node(root, &block)
  return enum_for(:each_dfs_postorder_node, root) unless block_given?

  dfs_postorder_nodes(root).each(&block)
end

#each_dfs_preorder_node(root) ⇒ Object

[EXPERIMENTAL]

Parameters:

  • root (Object)

    node which is root, start, source



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/networkx/traversals/dfs.rb', line 93

def each_dfs_preorder_node(root)
  return enum_for(:each_dfs_preorder_node, root) unless block_given?

  st = [root]
  used = {root => true}
  while st[-1]
    node = st.pop
    yield(node)
    @adj[node].reverse_each do |v, _data|
      next if used[v]

      used[v] = node
      st << v
    end
  end
end

#each_edge(data: false) ⇒ Object

[TODO][EXPERIMENTAL]

Parameters:

  • data (bool) (defaults to: false)

    true if you want data of each edge



248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/networkx/graph.rb', line 248

def each_edge(data: false)
  return enum_for(:each_edge, data: data) unless block_given?

  h = {}
  @adj.each do |v, ws|
    ws.each do |w, info|
      next if v > w

      h[[v, w, info]] = true
    end
  end
  if data
    h.each { |(v, w, info), _true| yield(v, w, info) }
  else
    h.each { |(v, w, _info), _true| yield(v, w) }
  end
end

#each_node(data: false, &block) ⇒ Object



230
231
232
233
234
# File 'lib/networkx/graph.rb', line 230

def each_node(data: false, &block)
  return enum_for(:each_node, data: data) unless block_given?

  data ? @nodes.each(&block) : @nodes.each_key(&block)
end

#edge?(node1, node2) ⇒ Boolean Also known as: has_edge?

Checks if the the edge consisting of two nodes is present in the graph

Examples:

graph.edge?(node1, node2)

Parameters:

  • node1 (Object)

    the first node of the edge to be checked

  • node2 (Object)

    the second node of the edge to be checked

Returns:

  • (Boolean)


294
295
296
# File 'lib/networkx/graph.rb', line 294

def edge?(node1, node2)
  node?(node1) && @adj[node1].has_key?(node2)
end

#edge_subgraph(edges) ⇒ Object

Returns subgraph conisting of given edges

Examples:

graph.edge_subgraph([%w[Nagpur Wardha], %w[Nagpur Mumbai]])

Parameters:

  • edges (Array<Object, Object>)

    the edges to be included in the subraph



401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
# File 'lib/networkx/graph.rb', line 401

def edge_subgraph(edges)
  case edges
  when Array, Set
    sub_graph = NetworkX::Graph.new(**@graph)
    edges.each do |u, v|
      raise KeyError, "Edge between #{u} and #{v} does not exist in the graph!" unless @nodes.has_key?(u) \
                                                                                && @adj[u].has_key?(v)

      sub_graph.add_node(u, **@nodes[u])
      sub_graph.add_node(v, **@nodes[v])
      sub_graph.add_edge(u, v, **@adj[u][v])
    end
    sub_graph
  else
    raise ArgumentError, 'Expected Argument to be Array or Set of edges, ' \
                         "received #{edges.class.name} instead."
  end
end

#edges(data: false) ⇒ Array[[Object, Object]]

[TODO][EXPERIMENTAL]

Parameters:

  • data (bool) (defaults to: false)

    true if you want data of each edge

Returns:

  • (Array[[Object, Object]])

    edges array



241
242
243
# File 'lib/networkx/graph.rb', line 241

def edges(data: false)
  each_edge(data: data).to_a
end

#get_edge_data(node1, node2) ⇒ Object

Gets the edge data

Examples:

graph.get_edge_data(node1, node2)

Parameters:

  • node1 (Object)

    the first node of the edge

  • node2 (Object)

    the second node of the edge

Raises:

  • (KeyError)


318
319
320
321
322
# File 'lib/networkx/graph.rb', line 318

def get_edge_data(node1, node2)
  raise KeyError, 'No such edge exists!' unless node?(node1) && node?(node2)

  @adj[node1][node2]
end

#get_node_data(node) ⇒ Object

Gets the node data

Examples:

graph.get_node_data(node)

Parameters:

  • node (Object)

    the node whose data is to be fetched

Raises:

  • (ArgumentError)


305
306
307
308
309
# File 'lib/networkx/graph.rb', line 305

def get_node_data(node)
  raise ArgumentError, 'No such node exists!' unless node?(node)

  @nodes[node]
end

#infoObject



431
432
433
434
435
436
437
# File 'lib/networkx/graph.rb', line 431

def info
  info = ''
  info << "Type: #{self.class}\n"
  info << "Number of nodes: #{number_of_nodes}\n"
  info << "Number of edges: #{number_of_edges}\n"
  info
end

#multigraph?Boolean

Returns:

  • (Boolean)


439
440
441
# File 'lib/networkx/graph.rb', line 439

def multigraph?
  ['NetworkX::MultiGraph', 'NetworkX::MultiDiGraph'].include?(self.class.name)
end

#neighbours(node) ⇒ Object

Retus a hash of neighbours of a node

Examples:

graph.neighbours(node)

Parameters:

  • node (Object)

    the node whose neighbours are to be fetched

Raises:

  • (KeyError)


330
331
332
333
334
# File 'lib/networkx/graph.rb', line 330

def neighbours(node)
  raise KeyError, 'No such node exists!' unless node?(node)

  @adj[node]
end

#node?(node) ⇒ Boolean Also known as: has_node?

Checks if a node is present in the graph

Examples:

graph.node?(node1)

Parameters:

  • node (Object)

    the node to be checked

Returns:

  • (Boolean)


282
283
284
# File 'lib/networkx/graph.rb', line 282

def node?(node)
  @nodes.has_key?(node)
end

#nodes(data: false) ⇒ Hash | Array

Return nodes of graph

Parameters:

  • data (bool) (defaults to: false)

    true if you want data of each edge

Returns:

  • (Hash | Array)

    if data is true, it returns hash including data. otherwise, simple nodes array.



222
223
224
225
226
227
228
# File 'lib/networkx/graph.rb', line 222

def nodes(data: false)
  if data
    @nodes
  else
    @nodes.keys
  end
end

#number_of_edgesObject

Returns number of edges

Examples:

graph.number_of_edges


348
349
350
# File 'lib/networkx/graph.rb', line 348

def number_of_edges
  @adj.values.map(&:length).sum / 2
end

#number_of_nodesObject

Returns number of nodes

Examples:

graph.number_of_nodes


340
341
342
# File 'lib/networkx/graph.rb', line 340

def number_of_nodes
  @nodes.length
end

#put_graph_x2Object

Experimental For debug.



229
230
231
232
233
234
235
# File 'lib/networkx/others/generators.rb', line 229

def put_graph_x2
  output = <<~"OUTPUT"
    #{number_of_nodes} #{number_of_edges}
    #{edges.map { |edge| edge.join(' ') }.join("\n")}
  OUTPUT
  puts output
end

#remove_edge(node1, node2) ⇒ Object

Removes edge from the graph

Examples:

graph.remove_edge('Noida', 'Bangalore')

Parameters:

  • node1 (Object)

    the first node of the edge

  • node2 (Object)

    the second node of the edge

Raises:

  • (KeyError)


149
150
151
152
153
154
155
156
# File 'lib/networkx/graph.rb', line 149

def remove_edge(node1, node2)
  raise KeyError, "#{node1} is not a valid node." unless @nodes.has_key?(node1)
  raise KeyError, "#{node2} is not a valid node" unless @nodes.has_key?(node2)
  raise KeyError, 'The given edge is not a valid one.' unless @adj[node1].has_key?(node2)

  @adj[node1].delete(node2)
  @adj[node2].delete(node1) if node1 != node2
end

#remove_edges(edges) ⇒ Object Also known as: remove_edges_from

Removes multiple edges from the graph

Examples:

graph.remove_edges([%w[Noida Bangalore], %w[Bangalore Chennai]])

Parameters:

  • edges (Array<Object>)

    the array of edges to be removed



164
165
166
167
168
169
170
171
172
# File 'lib/networkx/graph.rb', line 164

def remove_edges(edges)
  case edges
  when Array, Set
    edges.each { |node1, node2| remove_edge(node1, node2) }
  else
    raise ArgumentError, 'Expected Arguement to be Array or Set of edges, ' \
                         "received #{edges.class.name} instead."
  end
end

#remove_node(node) ⇒ Object

Removes node from the graph

Examples:

graph.remove_node("Noida")

Parameters:

  • node (Object)

    the node to be removed

Raises:

  • (KeyError)


117
118
119
120
121
122
123
# File 'lib/networkx/graph.rb', line 117

def remove_node(node)
  raise KeyError, "Error in deleting node #{node} from Graph." unless @nodes.has_key?(node)

  @adj[node].each_key { |k| @adj[k].delete(node) }
  @adj.delete(node)
  @nodes.delete(node)
end

#remove_nodes(nodes) ⇒ Object Also known as: remove_nodes_from

Removes multiple nodes from the graph

Examples:

graph.remove_nodes(["Noida", "Bangalore"])

Parameters:

  • nodes (Array<Object>)

    the array of nodes to be removed



131
132
133
134
135
136
137
138
139
# File 'lib/networkx/graph.rb', line 131

def remove_nodes(nodes)
  case nodes
  when Set, Array
    nodes.each { |node| remove_node(node) }
  else
    raise ArgumentError, 'Expected argument to be an Array or Set of nodes, ' \
                         "received #{nodes.class.name} instead."
  end
end

#size(is_weighted = false) ⇒ Object

Returns the size of the graph

Examples:

graph.size(true)

Parameters:

  • is_weighted (Bool) (defaults to: false)

    if true, method returns sum of weights of all edges else returns number of edges



359
360
361
362
363
364
365
366
367
368
# File 'lib/networkx/graph.rb', line 359

def size(is_weighted = false)
  if is_weighted
    graph_size = 0
    @adj.each do |_, hash_val|
      hash_val.each { |_, v| graph_size += v[:weight] if v.has_key?(:weight) }
    end
    return graph_size / 2
  end
  number_of_edges
end

#subgraph(nodes) ⇒ Object

Returns subgraph consisting of given array of nodes

Examples:

graph.subgraph(%w[Mumbai Nagpur])

Parameters:

  • nodes (Array<Object>)

    the nodes to be included in the subgraph



376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
# File 'lib/networkx/graph.rb', line 376

def subgraph(nodes)
  case nodes
  when Array, Set
    sub_graph = NetworkX::Graph.new(**@graph)
    nodes.each do |u, _|
      raise KeyError, "#{u} does not exist in the current graph!" unless @nodes.has_key?(u)

      sub_graph.add_node(u, **@nodes[u])
      @adj[u].each do |v, edge_val|
        sub_graph.add_edge(u, v, **edge_val) if @adj[u].has_key?(v) && nodes.include?(v)
      end
    end
    sub_graph
  else
    raise ArgumentError, 'Expected Argument to be Array or Set of nodes, ' \
                         "received #{nodes.class.name} instead."
  end
end