NetworkX - Graph

https://networkx.org/documentation/stable/reference/classes/index.html

https://networkx.org/documentation/stable/reference/classes/graph.html

GRAPH


G = nx.Graph()   # undirected graph
G = nx.Graph(edge_list)   # a list of 2-tuples
G = nx.Graph(other_graph)   # a copy
G = nx.Graph(name="My graph")   # 'name' is a graph attribute
G.graph["name"] = "Small graph"   # changing 'name'
G.graph["day"] = "Monday"
print(G)   # Small graph
print(G.graph)   # {'name': 'Small graph', 'day': 'Monday'}
# G.graph is a dict with graph attributes

NODES

Graph nodes can be any hashable object e.g., a number, a text string, etc. [do not use None!]


# Adding nodes.

# G.add_node(node)
# G.add_node(node, key1=value1, key2=value2)
# G.add_node(node, **node_attribute_dict)
#     but not: G.add_node(node, node_attribute_dict)
#
# (1) G.add_node(node)   # first create, then add attributes
# (2a) G.nodes[node]['key'] = value
# (2b) G.nodes[node].update(node_attribute_dict)
# G.nodes[node] is node_attribute_dict.
# Use G.add_node() to add new nodes!
#
# G.add_nodes_from(iterable)
# G.add_nodes_from(iterable, key=value)   # the same for all nodes
#     iterable can yield nodes or 2-tuples (node, node_attribute_dict)
# G.add_nodes_from(other_graph)

G.add_nodes_from( [1, 2, 3] )
G.add_nodes_from( [ (4, {"color": "red"}), (5, {"color": "green"}) ] )
G.add_nodes_from( [6, 7], color="black" )

G.nodes   # NodeView(...)
list(G.nodes)   # a list of nodes

G.nodes.data()   # NodeDataView(...)
list(G.nodes.data())   # a list of 2-tuples (node, node_attribute_dict)

for node in G.nodes:   # iteration over nodes
    G.nodes[node]['size'] = None

# Using attributes.

D = nx.get_node_attributes(G, "attr")   # {node1: value1, node2; value2, ...}
# Returns a dictionary of attributes keyed by node.
# Nodes without this attribute are not included in the returned dict.

#D = nx.get_node_attributes(G, "color", default="white") # networkx version 3
# Default value of the node attribute if there is no value set
# for that node in graph. 

nx.set_node_attributes(G, {node1: value1, node2; value2, ...}, "attr")

# A dictionary of dictionaries can be used as the second argument.
nx.set_node_attributes(G, {node1: {"attr1": value1}, node2: {"attr2": value2}, ...})

EDGES


# Adding edges.

# G.add_edge(node1, node2)
# G.add_edge(node1, node2, key1=value1, key2=value2)
#     Note that key1 and key2 are like Python names here (not numbers!).
# G.add_edge(node1, node2, **edge_attribute_dict)
#     but not: G.add_edge(node1, node2, edge_attribute_dict)
#
# (1) G.add_edge(node1, node2)   # first create, then add attributes
# (2a) G[node1][node2]['key'] = value
# (2b) G[node1][node2].update(edge_attribute_dict)
# (2c) G.edges[node1,node2]['key'] = value
# (2d) G.edges[node1,node2].update(edge_attribute_dict)
#     Note that we can use numbers here as keys.
# G[node1][node2] and G.edges[node1,node2] are edge_attribute_dict.
# Use G.add_edge() to add new edges!
#
# G.add_edges_from(iterable)
# G.add_edges_from(iterable, key=value)   # the same for all edges
#     iterable can yield 2-tuples (node1, node2)
#     or 3-tuples (node1, node2, edge_attribute_dict)
# G.add_weighted_edges_from(iterable)
#     iterable can yield 3-tuples (node1, node2, weight)

G.add_edge(1, 2)
G.add_edges_from( [ (7, 8) ] )
G.add_edges_from( [ (2, 3, {'weight': 3.1415}) ] )
G.add_weighted_edges_from( [ (4, 5, 0.5), (5, 6, 1.2)] )

G.edges   # EdgeView(...)
list(G.edges)   # a list of 2-tuples (node1, node2)

G.edges.data()  # EdgeDataView(...)
list(G.edges.data())   # a list of 3-tuples (node1, node2, edge_attribute_dict)

for (source, target) in G.edges:   # iteration over edges
    G[source][target]['length'] = None
    #G.edges[source,target]['length'] = None

for edge in G.edges:   # edge is 2-tuple
    G.edges[edge]['color'] = 'black'

# Using attributes.

D = nx.get_edge_attributes(G, "attr")   # {(node1, node2): value1, ...}
# Returns a dictionary of attributes keyed by edge (2-tuple).

#D = nx.get_edge_attributes(G, "color", default="white") # networkx version 3

nx.set_edge_attributes(G, {edge1: value1, edge2; value2, ...}, "attr")

nx.set_edge_attributes(G, {edge1: {"attr1": value1}, edge2: {"attr": value2}, ...})

NEIGHBORS


G[source]   # AtlasView(...)
list(G[source])   # a list of neighbors for source

for target in G[source]:   # read-only
    print("edge from {} to {}".format(source, target))

REMOVING ELEMENTS


G.remove_node(node)
G.remove_nodes_from(iterable)

G.remove_edge(node1, node2)
G.remove_edges_from(iterable)

G.clear()   # removing all nodes and edges

EXERCISES

Create an undirected graph G. Color nodes from G using a greedy algorithm.
https://networkx.org/documentation/stable/reference/algorithms/coloring.html


def trivial_node_coloring(graph):
    """Trivial node coloring."""
    counter = 0
    for node in graph.nodes:
        graph.nodes[node]['color'] = counter
        counter += 1

Create an undirected graph G. Color edges from G using a greedy algorithm.


def trivial_edge_coloring(graph):
    """Trivial edge coloring."""
    counter = 0
    for edge in graph.edges:
        graph.edges[edge]['color'] = counter
        counter += 1