Class: NetworkX::MultiGraph

Inherits:
Graph
  • Object
show all
Defined in:
lib/networkx/multigraph.rb

Overview

Describes the class for making MultiGraphs

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from Graph

#add_edges, #add_edges_from, #add_node, #add_nodes, #add_nodes_from, #add_path, #add_weighted_edge, #add_weighted_edges, #add_weighted_edges_from, balanced_tree, barbell_graph, #bfs_edges, #bfs_nodes, bull_graph, circular_ladder_graph, #clear, complete_edges, complete_graph, cubical_graph, cycle_graph, #degree, #dfs_edges, #dfs_postorder_nodes, #dfs_preorder_nodes, diamond_graph, #directed?, dodecahedral_graph, #each_bfs_edge, #each_bfs_node, #each_dfs_edge, #each_dfs_postorder_node, #each_dfs_preorder_node, #each_node, #edges, empty_graph, #get_edge_data, #get_node_data, heawood_graph, house_graph, house_x_graph, #info, #initialize, ladder_graph, lollipop_graph, moebius_kantor_graph, #neighbours, #node?, null_graph, #number_of_nodes, octahedral_graph, path_graph, #put_graph_x2, read_edgelist, read_weighted_edgelist, #remove_edges, #remove_node, #remove_nodes, star_graph, tetrahedral_graph, trivial_graph, wheel_graph

Constructor Details

This class inherits a constructor from NetworkX::Graph

Instance Attribute Details

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

Stores the edges and their attributes in an adjencency list form

Returns:

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

    the current value of adj



8
9
10
# File 'lib/networkx/multigraph.rb', line 8

def adj
  @adj
end

#graphHash{ Object => Object } (readonly)

Stores the attributes of the gra

Returns:

  • (Hash{ Object => Object })

    the current value of graph



8
9
10
# File 'lib/networkx/multigraph.rb', line 8

def graph
  @graph
end

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

Stores the nodes and their attributes

Returns:

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

    the current value of nodes



8
9
10
# File 'lib/networkx/multigraph.rb', line 8

def nodes
  @nodes
end

Instance Method Details

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

Adds the respective edge

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



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

def add_edge(node1, node2, **edge_attrs)
  add_node(node1)
  add_node(node2)
  key = new_edge_key(node1, node2)
  all_edge_attrs = @adj[node1][node2] || {}
  all_edge_attrs[key] = edge_attrs
  @adj[node1][node2] = all_edge_attrs
  @adj[node2][node1] = all_edge_attrs
end

#each_edge(data: false) ⇒ Object



112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/networkx/multigraph.rb', line 112

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

  @adj.each do |v, ws|
    ws.each do |w, key_and_info|
      next if v > w

      key_and_info.each do |key, info|
        data ? yield(v, w, key, info) : yield(v, w, key)
      end
    end
  end
end

#edge?(node1, node2, key = nil) ⇒ Boolean

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

  • key (Integer) (defaults to: nil)

    the key of the given edge

Returns:

  • (Boolean)


98
99
100
101
102
# File 'lib/networkx/multigraph.rb', line 98

def edge?(node1, node2, key = nil)
  return super(node1, node2) if key.nil?

  node?(node1) && @adj[node1].has_key?(node2) && @adj[node1][node2].has_key?(key)
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



176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/networkx/multigraph.rb', line 176

def edge_subgraph(edges)
  case edges
  when Array, Set
    sub_graph = NetworkX::MultiGraph.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])
      @adj[u][v].each { |_, keyval| sub_graph.add_edge(u, v, **keyval) }
    end
    sub_graph
  else
    raise ArgumentError, 'Expected Argument to be Array or Set of edges, ' \
                         "received #{edges.class.name} instead."
  end
end

#has_edge?(node1, node2, key = nil) ⇒ Boolean

Returns:

  • (Boolean)


104
105
106
107
108
109
110
# File 'lib/networkx/multigraph.rb', line 104

def has_edge?(node1, node2, key = nil)
  return super(node1, node2) if key.nil?

  return false unless node?(node1) && @adj[node1].has_key?(node2)

  @adj[node1][node2].any? { |_index, data| data[:key] == key }
end

#multigraph?Boolean

Returns:

  • (Boolean)


195
196
197
# File 'lib/networkx/multigraph.rb', line 195

def multigraph?
  true
end

#new_edge_key(node1, node2) ⇒ Object

Returns a new key

Parameters:

  • node1 (Object)

    the first node of a given edge

  • node2 (Object)

    the second node of a given edge



13
14
15
16
17
18
19
# File 'lib/networkx/multigraph.rb', line 13

def new_edge_key(node1, node2)
  return 0 if @adj[node1][node2].nil?

  key = @adj[node1][node2].length
  key += 1 while @adj[node1][node2].has_key?(key)
  key
end

#number_of_edgesObject

Returns number of edges

Examples:

graph.number_of_edges


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

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

#remove_edge(node1, node2, key = nil) ⇒ 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)


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

def remove_edge(node1, node2, key = nil)
  return super(node1, node2) if key.nil?

  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)

  if @adj[node1][node2].none? { |_index, data| data[:key] == key }
    raise KeyError, 'The given edge is not a valid one'
  end

  @adj[node1][node2].delete_if { |_indx, data| data[:key] == key }
  @adj[node2][node1].delete_if { |_indx, data| data[:key] == key }
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



71
72
73
74
75
76
77
78
79
80
# File 'lib/networkx/multigraph.rb', line 71

def size(is_weighted = false)
  if is_weighted
    graph_size = 0
    @adj.each do |_, hash_val|
      hash_val.each { |_, v| v.each { |_, attrs| graph_size += attrs[:weight] if attrs.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



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/networkx/multigraph.rb', line 149

def subgraph(nodes)
  case nodes
  when Array, Set
    sub_graph = NetworkX::MultiGraph.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|
        next if u > v

        edge_val.each { |_, keyval| sub_graph.add_edge(u, v, **keyval) 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

#to_undirectedObject

Returns the undirected version of the graph

Examples:

graph.to_undirected


130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/networkx/multigraph.rb', line 130

def to_undirected
  graph = NetworkX::Graph.new(**@graph)
  @nodes.each { |node, node_attr| graph.add_node(node, **node_attr) }
  @adj.each do |node1, node1_edges|
    node1_edges.each do |node2, node1_node2|
      edge_attrs = {}
      node1_node2.each { |_key, attrs| edge_attrs.merge!(attrs) }
      graph.add_edge(node1, node2, **edge_attrs)
    end
  end
  graph
end