Una guía completa para el procesamiento de datos gráficos en Python, desde listas de bordes sin formato hasta matrices de adyacencia

Este artículo es compartido por la comunidad de la nube de Huawei " Una guía completa para implementar el procesamiento de datos gráficos en Python desde la lista de bordes original hasta la matriz de adyacencia " por Lemony Hug.

En teoría de grafos y análisis de redes, un gráfico es una estructura de datos muy importante que consta de nodos (o vértices) y los bordes que conectan estos nodos. En Python, podemos representar un gráfico usando una matriz de adyacencia, donde las filas y columnas de la matriz representan nodos y los valores en la matriz representan si hay bordes entre los nodos.

Lista de bordes originales

Supongamos que tenemos una lista de aristas primitiva donde cada elemento representa una arista, por ejemplo:

aristas = [(0, 1), (0, 2), (1, 2), (2, 3)]

En este ejemplo, cada tupla representa la existencia de un borde entre el nodo y el nodo . (a, b)  a  b 

Convertir a matriz de adyacencia

Primero debemos determinar la cantidad de nodos en el gráfico y luego crear una matriz cero del tamaño correspondiente. A continuación, recorremos la lista de bordes original y configuramos el elemento de matriz correspondiente en 1 en función de los dos nodos de cada borde. La matriz final obtenida es la matriz de adyacencia que necesitamos.

Veamos cómo implementar este proceso en código Python:

def bordes_a_adjacency_matrix(bordes):
    # Encuentra el número de nodos en el gráfico.
    max_node = max(max(borde) para borde en bordes) + 1
    
    #Crear matriz cero
    adjacency_matrix = [[0] * max_node para _ en el rango (max_node)]
    
    # Recorrer la lista de bordes original y actualizar la matriz de adyacencia
    para borde en bordes:
        adjacency_matrix[borde[0]][borde[1]] = 1
        adjacency_matrix[edge[1]][edge[0]] = 1 # Si es un gráfico no dirigido, los bordes son bidireccionales
    
    devolver matriz_adyacencia

# prueba
aristas = [(0, 1), (0, 2), (1, 2), (2, 3)]
matriz_adyacencia = bordes_a_matriz_adyacencia (bordes)
para la fila en adjacency_matrix:
    imprimir (fila)

En este código, edges_to_adjacency_matrix la función acepta la lista de aristas original como argumento y devuelve la matriz de adyacencia correspondiente. Luego realizamos la prueba en la lista de bordes dada y generamos la matriz de adyacencia resultante.

Ampliar y optimizar

Aunque el código anterior puede completar la conversión de la lista de bordes original a la matriz de adyacencia, es posible que se requieran algunas extensiones y optimizaciones en aplicaciones prácticas.

  1. Procesamiento de gráficos dirigidos y no dirigidos : El código actual maneja gráficos no dirigidos de forma predeterminada. Si se trata de un gráfico dirigido, el código debe modificarse de acuerdo con las necesidades específicas y la relación de adyacencia solo se establece en una dirección.

  2. Manejo de pesos : A veces una ventaja no es sólo una relación entre existencia o ausencia, sino que también puede tener un peso. Código modificado para admitir gráficos ponderados.

  3. Utilice matrices dispersas : para gráficos grandes, las matrices de adyacencia pueden ocupar mucha memoria. Considere la posibilidad de utilizar matrices dispersas para ahorrar espacio en la memoria.

  4. Optimización del rendimiento : para listas perimetrales a gran escala, se debe considerar el rendimiento del código. Puede intentar utilizar estructuras de datos o algoritmos más eficientes para implementar el proceso de conversión.

A continuación se muestran algunos ejemplos de optimizaciones de su código:

importar numpy como np

def bordes_a_adjacency_matrix(bordes, dirigidos=Falso):
    max_node = max(max(borde) para borde en bordes) + 1
    adyacencia_matrix = np.zeros((max_node, max_node))
    para borde en bordes:
        si se le indica:
            adjacency_matrix[borde[0]][borde[1]] = 1
        demás:
            adjacency_matrix[borde[0]][borde[1]] = 1
            adjacency_matrix[borde[1]][borde[0]] = 1
    devolver matriz_adyacencia

# prueba
aristas = [(0, 1), (0, 2), (1, 2), (2, 3)]
matriz_adyacencia = bordes_a_matriz_adyacencia (bordes)
print("Matriz de adyacencia del gráfico no dirigido:")
imprimir (matriz_adyacencia)

bordes_dirigidos = [(0, 1), (0, 2), (1, 2), (2, 3)]
direct_adjacency_matrix = bordes_a_adjacency_matrix(directed_edges, dirigido=Verdadero)
print("\nMatriz de adyacencia del gráfico dirigido:")
imprimir (matriz_adyacencia_dirigida)

En el código optimizado, utilizamos la biblioteca NumPy para crear y manipular matrices, lo que puede mejorar el rendimiento y la legibilidad del código. Al mismo tiempo, agregamos un parámetro para indicar el tipo de gráfico para admitir la conversión de gráficos dirigidos y no dirigidos. directed 

Optimice el uso de memoria utilizando matrices dispersas

Cuando se trata de gráficos grandes, la matriz de adyacencia puede volverse muy escasa, siendo la mayoría de sus elementos ceros. Para optimizar el uso de la memoria, se puede utilizar una matriz dispersa para representar las relaciones de adyacencia.

Hay una variedad de bibliotecas en Python que pueden manejar matrices dispersas, entre las cuales la biblioteca Scipy proporciona varias operaciones y algoritmos para matrices dispersas. Echemos un vistazo a cómo optimizar su código usando matrices dispersas en Scipy:

importar numpy como np
desde scipy.sparse importar lil_matrix

def bordes_a_adjacency_matrix(bordes, dirigidos=Falso):
    max_node = max(max(borde) para borde en bordes) + 1
    adjacency_matrix = lil_matrix((max_node, max_node), dtype=np.int8)
    para borde en bordes:
        si se le indica:
            matriz_adyacencia[borde[0], borde[1]] = 1
        demás:
            matriz_adyacencia[borde[0], borde[1]] = 1
            matriz_adyacencia[borde[1], borde[0]] = 1
    devolver matriz_adyacencia

# prueba
aristas = [(0, 1), (0, 2), (1, 2), (2, 3)]
matriz_adyacencia = bordes_a_matriz_adyacencia (bordes)
print("Matriz de adyacencia del gráfico no dirigido:")
imprimir(adyacencia_matrix.toarray())

bordes_dirigidos = [(0, 1), (0, 2), (1, 2), (2, 3)]
direct_adjacency_matrix = bordes_a_adjacency_matrix(directed_edges, dirigido=Verdadero)
print("\nMatriz de adyacencia del gráfico dirigido:")
imprimir (directed_adjacency_matrix.toarray())

En esta versión del código, utilizamos para crear una matriz dispersa. Puede manejar matrices grandes y dispersas de manera eficiente y solo almacena elementos distintos de cero, ahorrando así memoria. scipy.sparse.lil_matrix 

A través de esta optimización, podemos procesar datos de gráficos más grandes sin causar degradación del rendimiento o problemas de falta de memoria debido al uso excesivo de memoria.

Listas de bordes ponderados de proceso

En algunos casos, los bordes del gráfico no solo representan las relaciones de conexión entre nodos, sino que también pueden tener información de peso. Por ejemplo, en una red de transporte, los bordes pueden representar carreteras y los pesos pueden representar la longitud o el tiempo de viaje de una carretera.

Veamos cómo podemos modificar el código para admitir listas de bordes ponderados:

importar numpy como np
desde scipy.sparse importar lil_matrix

def bordes_a_adjacency_matrix(bordes, dirigido=Falso, ponderado=Falso):
    max_node = max(max(borde[0], borde[1]) para borde en bordes) + 1
    adjacency_matrix = lil_matrix((max_node, max_node), dtype=np.float32)
    para borde en bordes:
        si se le indica:
            si está ponderado:
                adjacency_matrix[borde[0], borde[1]] = borde[2]
            demás:
                matriz_adyacencia[borde[0], borde[1]] = 1
        demás:
            si está ponderado:
                adjacency_matrix[borde[0], borde[1]] = borde[2]
                adjacency_matrix[borde[1], borde[0]] = borde[2]
            demás:
                matriz_adyacencia[borde[0], borde[1]] = 1
                matriz_adyacencia[borde[1], borde[0]] = 1
    devolver matriz_adyacencia

# prueba
bordes_ponderados = [(0, 1, 5), (0, 2, 3), (1, 2, 2), (2, 3, 7)]
matriz_de_adjacencia_ponderada = bordes_a_matriz_de_adyacencia(bordes_ponderados, ponderada=Verdadero)
print("Matriz de adyacencia ponderada:")
imprimir(weighted_adjacency_matrix.toarray())

En esta versión del código, agregamos un parámetro para indicar si el borde está ponderado. Si el argumento es , entonces la información de peso se extrae de la lista de bordes y se guarda en la matriz de adyacencia. De lo contrario, los valores en la matriz de adyacencia aún representan la presencia o ausencia del borde. weighted  weighted  True

Con esta modificación, podemos procesar datos del gráfico con información de peso y retener esta información en la matriz de adyacencia para análisis y cálculos posteriores.

Visualización de gráficos.

Cuando se trata de datos gráficos, la visualización es una herramienta poderosa que puede ayudarnos a comprender intuitivamente la estructura y las características del gráfico. Hay muchas bibliotecas en Python que se pueden usar para visualizar datos de gráficos, entre las cuales NetworkX es una biblioteca de uso común que proporciona funciones ricas para crear, manipular y visualizar gráficos.

Veamos cómo usar NetworkX para visualizar nuestra matriz de adyacencia generada:

importar networkx como nx
importar matplotlib.pyplot como plt

def visualizar_adjacency_matrix(adjacency_matrix):
    G = nx.from_numpy_matrix(matriz_adyacencia)
    pos = nx.spring_layout(G) # Definir la posición del nodo
    nx.draw(G, pos, with_labels=True, node_color='skyblue', node_size=500, font_size=10) # 绘制图
    edge_labels = {(i, j): w['weight'] para i, j, w en G.edges(data=True)} # Obtener pesos de borde
    nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels, font_size=10) # Dibujar pesos de borde
    plt.title("Visualización de gráficos")
    plt.mostrar()

# prueba
bordes_ponderados = [(0, 1, 5), (0, 2, 3), (1, 2, 2), (2, 3, 7)]
matriz_de_adjacencia_ponderada = bordes_a_matriz_de_adyacencia(bordes_ponderados, ponderada=Verdadero)
print("Matriz de adyacencia ponderada:")
imprimir(weighted_adjacency_matrix.toarray())

visualize_adjacency_matrix(weighted_adjacency_matrix.toarray())

En este código, primero convertimos la matriz de adyacencia en un objeto gráfico usando las funciones de NetworkX. Luego use la posición del nodo definido y dibuje el gráfico usando la función. Finalmente, trazamos los pesos de los bordes usando una función. from_numpy_matrix  spring_layout  draw  draw_networkx_edge_labels 

A través de la visualización, podemos ver claramente la estructura del gráfico y comprender intuitivamente las relaciones de conexión y la información de peso entre los nodos.

Convertir la matriz de adyacencia en una lista de bordes sin formato

En el procesamiento de datos de gráficos, a veces necesitamos convertir la matriz de adyacencia a su forma de lista de bordes original. Esto puede resultar útil en determinados algoritmos y aplicaciones, ya que algunos algoritmos pueden ser más adecuados para utilizar listas de aristas para representar el gráfico.

Veamos cómo escribir código para lograr esta conversión:

importar numpy como np

def adjacency_matrix_to_edges(adjacency_matrix):
    bordes = []
    para i en el rango (adjacency_matrix.shape[0]):
        para j en el rango (adjacency_matrix.shape[1]):
            si adjacency_matrix[i, j]!= 0:
                bordes.append((i, j, adjacency_matrix[i, j]))
    bordes de retorno

# prueba
matriz_adyacencia = np.array([[0, 1, 0, 0],
                              [1, 0, 1, 0],
                              [0, 1, 0, 1],
                              [0, 0, 1, 0]], tipod=np.float32)
print("Matriz de adyacencia original:")
imprimir (matriz_adyacencia)

bordes = adjacency_matrix_to_edges(adjacency_matrix)
print("\nLista de aristas convertidas:")
imprimir (bordes)

En este código, iteramos a través de cada elemento de la matriz de adyacencia y si el valor del elemento es distinto de cero, lo convertimos en un borde en la lista de bordes. Para gráficos con pesos, también guardamos la información de peso en la lista de bordes.

A través de este proceso de conversión, podemos convertir el gráfico representado por la matriz de adyacencia en una lista de aristas, lo que facilita la implementación y aplicación de algunos algoritmos.

Resumen y perspectivas

Este artículo presenta cómo usar Python para convertir la lista de bordes original en una matriz de adyacencia y realiza una serie de extensiones y optimizaciones para satisfacer las necesidades de diferentes escenarios. Cubrimos múltiples aspectos del procesamiento de datos de gráficos, desde el procesamiento de gráficos dirigidos y no dirigidos, listas de bordes ponderados, hasta el uso de matrices dispersas para optimizar el uso de la memoria, la visualización de gráficos y la conversión de matrices de adyacencia a listas de bordes sin procesar.

En aplicaciones prácticas, el procesamiento de datos gráficos es un campo muy importante y ampliamente utilizado, que involucra análisis de redes, redes sociales, planificación del transporte, bioinformática y muchos otros campos. Dominar las habilidades del procesamiento de datos gráficos puede ayudarnos a comprender y analizar mejor estructuras de datos complejas para resolver problemas prácticos.

En el futuro, a medida que la escala y la complejidad de los datos sigan aumentando, el campo del procesamiento de datos gráficos enfrentará más desafíos y oportunidades. Podemos esperar que surjan herramientas y algoritmos más eficientes, flexibles y ricos en funciones para abordar las necesidades y los desafíos cambiantes. Al mismo tiempo, también podemos continuar aprendiendo y explorando, mejorando constantemente nuestras habilidades y niveles en el campo del procesamiento de datos gráficos y haciendo mayores contribuciones a la resolución de problemas prácticos.

Espero que este artículo le ayude a comprender y aplicar el procesamiento de datos gráficos. También puede seguir estudiando y explorando este campo y contribuyendo al desarrollo de la ciencia y la ingeniería de datos.

Haga clic para seguir y conocer las nuevas tecnologías de Huawei Cloud lo antes posible ~

 

El equipo de la Fundación Google Python fue despedido. Google confirmó los despidos y los equipos involucrados en Flutter, Dart y Python se apresuraron a la lista caliente de GitHub: ¿Cómo pueden ser tan lindos los lenguajes y marcos de programación de código abierto? Xshell 8 abre la prueba beta: admite el protocolo RDP y puede conectarse de forma remota a Windows 10/11 Cuando los pasajeros se conectan al WiFi del tren de alta velocidad , la "maldición de 35 años" de los codificadores chinos aparece cuando se conectan a la alta velocidad. Rail WiFi, la primera herramienta de búsqueda de IA con soporte a largo plazo de la versión 8.4 GA. Perplexica: completamente de código abierto y gratuito, una alternativa de código abierto a Perplexity. Los ejecutivos de Huawei evalúan el valor del código abierto. Hongmeng: todavía tiene su propio sistema operativo a pesar de la continua supresión. por países extranjeros, la empresa alemana de software para automóviles Elektrobit abrió una solución de sistema operativo para automóviles basada en Ubuntu.
{{o.nombre}}
{{m.nombre}}

Supongo que te gusta

Origin my.oschina.net/u/4526289/blog/11065906
Recomendado
Clasificación