Complex network and NetworkX - drawing of directed and undirected graphs

575c5b65bc750e440f3e586152867658.png

Table of contents

1. Introduction to networkx

2. Introduction to Complex Networks

Three, the introduction of the picture

4. Statistical indicators of the network 

5. Basic Tutorial


1. Introduction to networkx

NetworkX is a Python library for creating, manipulating, and studying complex networks. It provides a wide range of functions that enable users to generate various types of graphs, perform common graph operations, analyze graph properties, and visualize network structures.

Here are some of NetworkX's key features and capabilities:

  1. Create and manipulate graphs: NetworkX allows users to create many types of graphs, including undirected graphs, directed graphs, weighted graphs, and more. It provides simple interfaces to add nodes and edges, and supports common graph operations such as adding, removing, and modifying nodes and edges.

  2. Graph Analysis and Algorithms: NetworkX provides a number of graph analysis and algorithm tools that enable users to study and analyze various properties and characteristics of networks. For example, the degree distribution, shortest path, connectivity, clustering coefficient, centrality index, etc. of a graph can be calculated.

  3. Graph generators: NetworkX provides a variety of graph generators for generating graphs with specific characteristics. For example, a random graph generator can be used to generate a random network, a small-world graph generator can be used to generate a small-world network, or a Barabasi-Albert graph generator can be used to generate a scale-free network.

  4. Visualization: NetworkX supports graph visualization for a more intuitive understanding and presentation of the network structure. It can use various layout algorithms to visualize nodes and edges, and provides flexible parameter control to adjust the visualization effect.

  5. Extensibility: NetworkX is highly extensible and can be integrated with other Python scientific computing libraries such as NumPy, SciPy, and Pandas. This enables users to extend the functionality of NetworkX by leveraging the functionality of other libraries.

2. Introduction to Complex Networks

24c1092c669ff5433c55ab82c8d67491.png

 

A complex network is a network structure composed of a large number of nodes and connections between them, in which there are very rich and complex relationships between nodes and connections. Compared with simple networks (such as regular networks or complete graphs), complex networks are closer to various real systems in the real world, such as social networks, the Internet, neural networks, logistics networks, etc.

The characteristics and properties of complex networks include: small-world properties, scale-free properties, community structures, and high robustness;

Qian Xuesen gave a stricter definition of complex networks: networks with some or all of the properties of self-organization, self-similarity, attractors, small worlds, and scale-free are called complex networks.

  1. Self-organization: refers to the ability of complex networks to form a spontaneous organizational structure through the interaction and adjustment of nodes without external control or guidance. This self-organization enables the network to adapt and evolve in dynamic environments.

  2. Self-similarity: Indicates that complex networks have similar structures and characteristics at different scales. In other words, a part of the network has similar properties to the whole, and this property exists at multiple levels.

  3. Attractor: Refers to the steady state or dynamic behavior of complex networks during the evolution process, which can be regarded as the attractor of the network. An attractor can be a node or a collection of nodes with properties of stability and attracting other nodes.

  4. Small-world: It means that the average shortest path length between nodes in a complex network is short and the aggregation is high. This means that any two nodes in the network can be connected to each other through a small number of intermediate nodes, and the nodes present a certain clustering or cluster structure.

  5. Scale-free: Indicates that the degree distribution of complex networks presents a power law distribution, that is, only a few nodes have very high degrees, while most nodes have relatively low degrees. This scale-free property means that there are a small number of core nodes in the network, which have a significant impact on the structure and function of the entire network.

Three, the introduction of the picture

Graph (graph) is a data structure composed of a set of nodes (vertices) and the edges (edges) that connect them. It is used to represent relationships or interactions between entities and provides a way to visualize and analyze those relationships. Graph is the basis of graph theory, which is widely used in computer science, social network analysis, logistics planning, biological network and other fields.

The following are some basic concepts and properties of graphs:

  • Node (Vertices): Also known as a vertex or a node, it represents an entity or element in a graph. Nodes can represent persons, objects, events, etc.

  • Edges: also known as connections, relationships or arcs, represent the association relationship between nodes. Edges can be directed (pointing from one node to another) or undirected (no directionality).

  • Weights: An optional attribute that represents the strength, distance, or other measure of an edge.

  • Path (Path): refers to a series of edges in the graph along which one node can reach another node.

  • Degree: The degree of a node refers to the number of edges connected to the node. For directed graphs, it is divided into In-degree and Out-degree.

According to the nature and structure of graphs, graphs can be divided into different types, including but not limited to the following:

  • Undirected Graph: The edges in the graph have no directionality, that is, they can move in both directions along the edges. For example, a friendship graph in a social network can be modeled as an undirected graph.

  • Directed Graph: The edges in the graph are directional, that is, from one node to another. For example, web page link relationships in the Internet can be modeled as directed graphs.

  • Weighted Graph: The edges in the graph are weighted to represent the strength, distance or other measures of the edges. For example, roads in a transportation network can be modeled as a weighted graph, with weights representing the length of the road or the degree of congestion.

  • Multigraph: The edges in the graph allow repetition, that is, there can be multiple identical edges connecting the same pair of nodes. For example, multiple communication lines in a communication network can be modeled as a multigraph.

  • Cyclic Graph and Acyclic Graph: A cyclic graph contains at least one cycle (a cycle refers to a path starting from a node and returning to the original node through a series of edges), while an acyclic graph does not contain any ring.

So how should we choose which graph to use according to the actual situation?

  1. Undirected graph vs. directed graph:

    • If the relationships in your problem are undirected, or you only care about the connections between nodes without regard to the direction, then an undirected graph is an appropriate choice.
    • If the relationships in the problem have clear directionality, and the connections between nodes are directed rather than bidirectional, then a directed graph is a more appropriate choice.
  2. Weighted graph vs. unweighted graph:

    • Weighted graphs are an appropriate choice if the edges in your problem have a notion of weight or strength, and you need to consider edge weights as part of network structure and analysis.
    • If the edges in the problem have no weights or the weights have no substantial impact on the solution of the problem, then an unweighted graph can suffice.
  3. Multiplot vs. Singleplot:

    • If the problem allows multiple edges of the same type between nodes, and you need to account for and analyze information about these multiple edges, then a multigraph is an appropriate choice.
    • If there is only a single connection between the nodes in question, and duplicate edges do not need to be considered, then a singlet graph can suffice.
  4. Cyclic graph vs. acyclic graph:

    • If there are cycles between the nodes in the problem (a cycle is a path starting from a node and returning to the original node through a series of edges), and you need to consider the influence of the ring and analyze the characteristics of the ring, then a graph with a ring is an appropriate s Choice.
    • If there are no cycles between the nodes in the problem, or if the cycles have no substantial effect on the solution of the problem, then an acyclic graph can suffice.

Here's how to create several graphs:

  1. Create an Undirected Graph:
    import networkx as nx
    
    # 创建一个空的无向图
    G = nx.Graph()
    
    # 添加节点
    G.add_nodes_from([1, 2, 3, 4])
    
    # 添加边
    G.add_edges_from([(1, 2), (2, 3), (3, 4), (4, 1)])
    
    # 或者可以使用下面的方式一次性添加边
    # edges = [(1, 2), (2, 3), (3, 4), (4, 1)]
    # G.add_edges_from(edges)
    
    

  2. Create a Directed Graph:
    import networkx as nx
    
    # 创建一个空的有向图
    G = nx.DiGraph()
    
    # 添加节点
    G.add_nodes_from([1, 2, 3, 4])
    
    # 添加有向边
    G.add_edges_from([(1, 2), (2, 3), (3, 4), (4, 1)])
    
    # 或者可以使用下面的方式一次性添加有向边
    # edges = [(1, 2), (2, 3), (3, 4), (4, 1)]
    # G.add_edges_from(edges)
    
    

  3. Create a Weighted Graph:
    import networkx as nx
    
    # 创建一个空的加权图
    G = nx.Graph()
    
    # 添加节点
    G.add_nodes_from([1, 2, 3, 4])
    
    # 添加带权边
    G.add_weighted_edges_from([(1, 2, 0.5), (2, 3, 1.2), (3, 4, 0.8), (4, 1, 1.5)])
    
    # 或者可以使用下面的方式一次性添加带权边
    # weighted_edges = [(1, 2, 0.5), (2, 3, 1.2), (3, 4, 0.8), (4, 1, 1.5)]
    # G.add_weighted_edges_from(weighted_edges)
    
    

  4. Create a multigraph (Multigraph):
    import networkx as nx
    
    # 创建一个空的多重图
    # G = nx.MultiGraph() # 创建多重无向图
    # G = nx.MultiDigraph() # 创建多重有向图
    
    G = nx.MultiGraph()
    
    # 添加节点
    G.add_nodes_from([1, 2, 3, 4])
    
    # 添加多重边
    G.add_edges_from([(1, 2), (1, 2), (2, 3), (3, 4)])
    
    

  5. Create a Cyclic Graph:
    import networkx as nx
    
    # 创建一个带环的有向图
    G = nx.DiGraph()
    
    # 添加节点
    G.add_nodes_from([1, 2, 3, 4])
    
    # 添加有向边,形成环
    G.add_edges_from([(1, 2), (2, 3), (3, 4), (4, 1)])
    
    

G.clear() #清空图

For more related content, please see the official website: Tutorial - NetworkX 3.1 Documentation

4. Statistical indicators of the network 

  1. Number of nodes: Indicates the number of nodes in the network and is used to measure the size of the network.

  2. Number of edges: Indicates the number of edges in the network and is used to describe the connection relationship between nodes.

  3. Average degree: Calculate the average of the degrees of all nodes in the network, and the degree refers to the number of edges connected to the node. The average degree reflects the connection density and complexity of the network.

  4. Clustering coefficient (Clustering coefficient): Used to measure the closeness between node neighbors. The clustering coefficient can be used to evaluate the clustering and community structure of nodes in the network.

  5. Shortest path length: Indicates the length of the shortest path between any two nodes in the network. The shortest path length is used to measure the distance between nodes and the "small world" nature of the network.

  6. Centrality: Measures the importance or influence of a node in the network. Common centrality indicators include Degree centrality, Betweenness centrality, and Closeness centrality.

  7. Degree distribution: Describes the probability distribution of node degrees. The degree distribution can be used to study the scale-free nature of the network and the importance distribution of nodes.

  8. Community structure: used to describe subgraphs or communities in a network, where nodes are tightly connected within the same community, while connections between communities are relatively sparse.

  9. Assortativity: Measures the degree to which nodes tend to connect with nodes with similarity. Assortativeness can be used to study the preferences and community structure of nodes in the network.

  10. Strongly connected components: For a directed graph, a strongly connected component is a subset of nodes in which there is a directed path between any two nodes.

5. Basic Tutorial

#添加节点
import networkx as nx
import matplotlib.pyplot as plt
G = nx.Graph()                 #建立一个空的无向图G
G.add_node('1')                  #添加一个节点1
nx.draw(G, with_labels=True)
plt.show()

G.add_nodes_from(['2','3','4','5'])    #加点集合
nx.draw(G, with_labels=True)
plt.show()

G.add_cycle(['6', '7', '8', '9'])  # 加环
G.add_edges_from([('6', '7'), ('7', '8'), ('8', '9'), ('9', '6')])  # 添加边
nx.draw(G, with_labels=True)
plt.show()

H = nx.path_graph(10)          #返回由10个节点挨个连接的无向图,所以有9条边
G.add_nodes_from(H)            #创建一个子图H加入G
G.add_node(H)                  #直接将图作为节点
nx.draw(G, with_labels=True)
plt.show()

 

#访问节点
print('图中所有的节点', G.nodes())
print('图中节点的个数', G.number_of_nodes())

 All nodes in the graph ['1', '2', '3', '4', '5', '6', '7', '8', '9', 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, <networkx.classes.graph.Graph object at 0x00000237BEC80A90>]
The number of nodes in the graph is 20

G.remove_node(1)    #删除指定节点
G.remove_nodes_from(['2','3','4','5'])    #删除集合中的节点
nx.draw(G, with_labels=True)
plt.show()

#添加边
F = nx.Graph() # 创建无向图
F.add_edge(11,12)   #一次添加一条边
nx.draw(F, with_labels=True)
plt.show()

 

e=(13,14)        #e是一个元组
F.add_edge(*e) #这是python中解包裹的过程
nx.draw(F, with_labels=True)
plt.show()

 

F.add_edges_from([(1,2),(1,3)])#通过添加list来添加多条边
nx.draw(F, with_labels=True)
plt.show()

 

#通过添加任何ebunch来添加边
F.add_edges_from(H.edges()) #不能写作F.add_edges_from(H)
nx.draw(F, with_labels=True)
plt.show()

 

#访问边
print('图中所有的边', F.edges())
print('图中边的个数', F.number_of_edges()) 

All edges in the graph [(11, 12), (13, 14), (1, 2), (1, 3), (1, 0), (2, 3), (3, 4), (4 , 5), (5, 6), (6, 7), (7, 8), (8, 9)]
The number of edges in the graph is 12

#实例:在networkx中列出节点和边
import networkx as nx
import matplotlib.pyplot as plt
G = nx.DiGraph()
G.add_edges_from([('0', '1'), ('0', '2'), ('0', '3')])
G.add_edges_from([('4', '41'), ('1', '11'), ('1', '12'), ('1', '13')])
G.add_edges_from([('2', '21'), ('2', '22')])
G.add_edges_from([('13', '131'), ('22', '221')])
G.add_edges_from([('131', '221'), ('221', '131')])
G.add_nodes_from(['5','6','7','8'])
nx.draw(G, with_labels=True)
plt.show()

 6. Examples of undirected and directed graphs of handwritten numbers

Construction of an undirected graph:

Read the image and grayscale it:

Read the image using OpenCV library and convert it to grayscale image. Then convert the image to a float data type.

image = cv2.imread("./num/0_4.jpg")
gray_img = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray_img = np.float32(gray_img)

For corner detection:

Use cv2.cornerHarrisa function to detect corners in an image.

corners_img = cv2.cornerHarris(gray_img, block_size, sobel_size, k)

Select feature points:

Use cv2.goodFeaturesToTrackthe function to select the first num_keypoints corner points in the image as feature points.

num_keypoints = 50
corners = cv2.goodFeaturesToTrack(gray_img, num_keypoints, 0.01, 10)
corners = np.intp(corners)

Construct eigenvectors and graphs:

Here, we constructed a feature vector using the coordinates of the feature points and created an undirected graph using the NetworkX library. Each node in the graph represents a feature point, and the position attribute (pos) of the node indicates the position of the feature point on the image. Then, according to the nearest neighbor principle, connect each node with its two nearest neighbor nodes.

feature_vector = np.zeros((num_keypoints, 2))

for i, corner in enumerate(corners):
    x, y = corner.ravel()
    feature_vector[i] = [x, y]
    G.add_node(i, pos=(x, y))

for i in range(len(feature_vector)):
    distances = np.sqrt(np.sum((feature_vector - feature_vector[i])**2, axis=1))
    closest_neighbors = np.argsort(distances)[1:3]
    for neighbor in closest_neighbors:
        G.add_edge(i, neighbor, weight=1)

Full code:

import cv2
import networkx as nx
import numpy as np
from matplotlib import pyplot as plt

# detector parameters
block_size = 3
sobel_size = 3
k = 0.06

image = cv2.imread("./num/0_4.jpg")
gray_img = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray_img = np.float32(gray_img)

# detect the corners with appropriate values as input parameters
corners_img = cv2.cornerHarris(gray_img, block_size, sobel_size, k)

# set the number of keypoints to be selected
num_keypoints = 50

# find the top num_keypoints corners in the corners_img
corners = cv2.goodFeaturesToTrack(gray_img, num_keypoints, 0.01, 10)
corners = np.intp(corners)

# create an empty feature vector with n dimensions
feature_vector = np.zeros((num_keypoints, 2))

# iterate over the corners and construct the feature vector
for i, corner in enumerate(corners):
    x, y = corner.ravel()
    feature_vector[i] = [x, y]
    # print the extracted keypoints
    print("Keypoint %d: x=%d, y=%d" % (i+1, x, y))

# create an empty graph
G = nx.Graph()

# add nodes to the graph
for i, feature in enumerate(feature_vector):
    x, y = feature
    G.add_node(i, pos=(x, y))

# add edges to the graph (connecting each node to its two closest neighbors)
for i in range(len(feature_vector)):
    distances = np.sqrt(np.sum((feature_vector - feature_vector[i])**2, axis=1))
    closest_neighbors = np.argsort(distances)[1:3] # exclude the node itself
    for neighbor in closest_neighbors:
        G.add_edge(i, neighbor, weight=1)

# draw the graph
pos = nx.get_node_attributes(G, 'pos')
nx.draw_networkx(G, pos=pos, with_labels=False, node_size=50)

# show the image with the detected corners and feature vector
for r in range(image.shape[0]):
    for c in range(image.shape[1]):
        pix = corners_img[r, c]
        if pix > 0.05 * corners_img.max():
            cv2.circle(image, (c, r), 5, (0, 0, 255), 0)

# plot the feature vector on the image
for i in range(num_keypoints):
    x, y = feature_vector[i]
    cv2.circle(image, (int(x), int(y)), 10, (0, 255, 0), -1)

# convert the image back to RGB format
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

# display the image
plt.imshow(image)
plt.show()

The construction of a directed graph:

Full code:

import cv2
import networkx as nx
import numpy as np
from matplotlib import pyplot as plt

# detector parameters
block_size = 3
sobel_size = 3
k = 0.06

image = cv2.imread("./num/0_7.jpg")
gray_img = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray_img = np.float32(gray_img)

# detect the corners with appropriate values as input parameters
corners_img = cv2.cornerHarris(gray_img, block_size, sobel_size, k)

# set the number of keypoints to be selected
num_keypoints = 50

# find the top num_keypoints corners in the corners_img
corners = cv2.goodFeaturesToTrack(gray_img, num_keypoints, 0.01, 10)
corners = np.intp(corners)

# create an empty feature vector with n dimensions
feature_vector = np.zeros((num_keypoints, 2))

# iterate over the corners and construct the feature vector
for i, corner in enumerate(corners):
    x, y = corner.ravel()
    feature_vector[i] = [x, y]

# create an empty directed graph
G = nx.DiGraph()

# add nodes to the graph
for i, feature in enumerate(feature_vector):
    x, y = feature
    G.add_node(i, pos=(x, y))

# add edges to the graph
for i in range(len(feature_vector)):
    distances = np.sqrt(np.sum((feature_vector[i] - feature_vector)**2, axis=1))
    closest_indices = np.argsort(distances)[1:3]
    for j in closest_indices:
        G.add_edge(i, j, weight=1)

# draw the graph
pos = nx.get_node_attributes(G, 'pos')
nx.draw_networkx(G, pos=pos, with_labels=False, node_size=50)

# show the image with the detected corners and feature vector
for r in range(image.shape[0]):
    for c in range(image.shape[1]):
        pix = corners_img[r, c]
        if pix > 0.05 * corners_img.max():
            cv2.circle(image, (c, r), 5, (0, 0, 255), 0)

# plot the feature vector on the image
for i in range(num_keypoints):
    x, y = feature_vector[i]
    cv2.circle(image, (int(x), int(y)), 10, (0, 255, 0), -1)

# convert the image back to RGB format
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

# display the image
plt.imshow(image)
plt.show()

 

Reference link:

Complex Network and NetworkX - Zhihu (zhihu.com)

Guess you like

Origin blog.csdn.net/weixin_45897172/article/details/131019344