Este artigo foi compartilhado da comunidade Huawei Cloud " Um guia completo para implementar o processamento de dados gráficos em Python, da lista de bordas original à matriz de adjacência " por Lemony Hug.
Na teoria dos grafos e na análise de redes, um grafo é uma estrutura de dados muito importante que consiste em nós (ou vértices) e nas arestas que conectam esses nós. Em Python, podemos representar um gráfico usando uma matriz de adjacência, onde as linhas e colunas da matriz representam nós, e os valores na matriz representam se existem arestas entre os nós.
Lista de bordas original
Suponha que temos uma lista de arestas primitiva onde cada elemento representa uma aresta, por exemplo:
arestas = [(0, 1), (0, 2), (1, 2), (2, 3)]
Neste exemplo, cada tupla representa a existência de uma aresta entre o nó e o nó . (a, b)
a
b
Converter para matriz de adjacência
Primeiro precisamos determinar o número de nós no gráfico e então criar uma matriz zero de tamanho correspondente. A seguir, percorremos a lista de arestas original e definimos o elemento da matriz correspondente como 1 com base nos dois nós de cada aresta. A matriz final obtida é a matriz de adjacência que precisamos.
Vamos ver como implementar este processo em código Python:
def bordas_para_adjacência_matriz(arestas): # Encontre o número de nós no gráfico max_node = max(max(edge) para aresta em arestas) + 1 #Criar matriz zero matriz_adjacência = [[0] * max_node para _ no intervalo (max_node)] # Percorre a lista de arestas original e atualiza a matriz de adjacência para borda nas bordas: matriz_adjacência[edge[0]][edge[1]] = 1 adjacency_matrix[edge[1]][edge[0]] = 1 # Se for um gráfico não direcionado, as arestas são bidirecionais retornar matriz_adjacência # teste arestas = [(0, 1), (0, 2), (1, 2), (2, 3)] matriz_adjacência = arestas_para_matriz_adjacência (arestas) para linha em adjacência_matrix: imprimir (linha)
Neste código, edges_to_adjacency_matrix
a função aceita a lista de arestas original como argumento e retorna a matriz de adjacência correspondente. Em seguida, realizamos o teste na lista de arestas fornecida e geramos a matriz de adjacência resultante.
Expanda e otimize
Embora o código acima possa completar a conversão da lista de arestas original na matriz de adjacência, algumas extensões e otimizações podem ser necessárias em aplicações práticas.
-
Processamento de gráficos direcionados e não direcionados : o código atual lida com gráficos não direcionados por padrão. Se for um gráfico direcionado, o código precisa ser modificado de acordo com necessidades específicas e o relacionamento de adjacência é definido apenas em uma direção.
-
Lidando com pesos : Às vezes, uma vantagem não é apenas uma relação entre existência ou ausência, mas também pode ter um peso. Código modificado para suportar gráficos ponderados.
-
Use matrizes esparsas : para gráficos grandes, matrizes de adjacência podem ocupar muita memória. Considere o uso de matrizes esparsas para economizar espaço de memória.
-
Otimização de desempenho : Para listas de arestas em grande escala, o desempenho do código precisa ser considerado. Você pode tentar usar estruturas de dados ou algoritmos mais eficientes para implementar o processo de conversão.
Aqui estão alguns exemplos de otimizações em seu código:
importar numpy como np def bordas_to_adjacency_matrix(arestas, direcionado=Falso): max_node = max(max(edge) para aresta em arestas) + 1 matriz_adjacência = np.zeros((nó_max, nó_max)) para borda nas bordas: se direcionado: matriz_adjacência[edge[0]][edge[1]] = 1 outro: matriz_adjacência[edge[0]][edge[1]] = 1 matriz_adjacência[edge[1]][edge[0]] = 1 retornar matriz_adjacência # teste arestas = [(0, 1), (0, 2), (1, 2), (2, 3)] matriz_adjacência = arestas_para_matriz_adjacência (arestas) print("Matriz de adjacência do gráfico não direcionado:") imprimir (matriz_adjacência) arestas_direcionadas = [(0, 1), (0, 2), (1, 2), (2, 3)] matriz_adjacência_direcionada = bordas_para_matriz_adjacência (bordas_direcionadas, direcionadas = Verdadeiro) print("\nMatriz de adjacência do grafo direcionado:") imprimir (matriz_adjacência_dirigida)
No código otimizado, utilizamos a biblioteca NumPy para criar e manipular matrizes, o que pode melhorar o desempenho e a legibilidade do código. Ao mesmo tempo, adicionamos um parâmetro para indicar o tipo de gráfico para suportar a conversão de gráficos direcionados e não direcionados. directed
Otimize o consumo de memória usando matrizes esparsas
Ao lidar com gráficos grandes, a matriz de adjacência pode tornar-se muito esparsa, com a maioria dos seus elementos sendo zeros. Para otimizar o uso de memória, uma matriz esparsa pode ser usada para representar relacionamentos de adjacência.
Há uma variedade de bibliotecas em Python que podem lidar com matrizes esparsas, entre as quais a biblioteca Scipy fornece várias operações e algoritmos para matrizes esparsas. Vamos dar uma olhada em como otimizar seu código usando matrizes esparsas no Scipy:
importar numpy como np de scipy.sparse importar lil_matrix def bordas_to_adjacency_matrix(arestas, direcionado=Falso): max_node = max(max(edge) para aresta em arestas) + 1 matriz_adjacência = lil_matrix((max_node, max_node), dtype=np.int8) para borda nas bordas: se direcionado: matriz_adjacência[edge[0], edge[1]] = 1 outro: matriz_adjacência[edge[0], edge[1]] = 1 matriz_adjacência[edge[1], edge[0]] = 1 retornar matriz_adjacência # teste arestas = [(0, 1), (0, 2), (1, 2), (2, 3)] matriz_adjacência = arestas_para_matriz_adjacência (arestas) print("Matriz de adjacência do gráfico não direcionado:") imprimir(adjacência_matrix.toarray()) arestas_direcionadas = [(0, 1), (0, 2), (1, 2), (2, 3)] matriz_adjacência_direcionada = bordas_para_matriz_adjacência (bordas_direcionadas, direcionadas = Verdadeiro) print("\nMatriz de adjacência do grafo direcionado:") imprimir(directed_adjacency_matrix.toarray())
Nesta versão do código, usamos para criar uma matriz esparsa. Ele pode lidar com grandes matrizes esparsas com eficiência e armazena apenas elementos diferentes de zero, economizando memória. scipy.sparse.lil_matrix
Por meio dessa otimização, podemos processar dados gráficos maiores sem causar degradação de desempenho ou problemas de falta de memória devido ao uso excessivo de memória.
Listas de bordas ponderadas de processo
Em alguns casos, as arestas do gráfico não representam apenas as relações de conexão entre os nós, mas também podem conter informações de peso. Por exemplo, em uma rede de transporte, as arestas podem representar estradas e os pesos podem representar o comprimento ou o tempo de viagem de uma estrada.
Vamos ver como podemos modificar o código para suportar listas de arestas ponderadas:
importar numpy como np de scipy.sparse importar lil_matrix def bordas_to_adjacency_matrix(arestas, direcionado=Falso, ponderado=Falso): max_node = max(max(edge[0], edge[1]) para aresta em arestas) + 1 matriz_adjacência = lil_matrix((max_node, max_node), dtype=np.float32) para borda nas bordas: se direcionado: se ponderado: matriz_adjacência[edge[0], edge[1]] = edge[2] outro: matriz_adjacência[edge[0], edge[1]] = 1 outro: se ponderado: matriz_adjacência[edge[0], edge[1]] = edge[2] matriz_adjacência[edge[1], edge[0]] = edge[2] outro: matriz_adjacência[edge[0], edge[1]] = 1 matriz_adjacência[edge[1], edge[0]] = 1 retornar matriz_adjacência # teste arestas_ponderadas = [(0, 1, 5), (0, 2, 3), (1, 2, 2), (2, 3, 7)] matriz_de_adjacência ponderada = bordas_para_matriz_de_adjacência (bordas_ponderadas, ponderada = Verdadeiro) print("Matriz de adjacência ponderada:") imprimir(weighted_adjacency_matrix.toarray())
Nesta versão do código, adicionamos um parâmetro para indicar se a aresta é ponderada. Se o argumento for , então as informações de peso serão extraídas da lista de arestas e salvas na matriz de adjacência. Caso contrário, os valores na matriz de adjacência ainda representam a presença ou ausência da aresta. weighted
weighted
True
Com esta modificação, podemos processar dados gráficos com informações de peso e reter essas informações na matriz de adjacência para análises e cálculos posteriores.
Visualização de gráficos
Ao lidar com dados gráficos, a visualização é uma ferramenta poderosa que pode nos ajudar a compreender intuitivamente a estrutura e as características do gráfico. Existem muitas bibliotecas em Python que podem ser usadas para visualizar dados gráficos, entre as quais NetworkX é uma biblioteca comumente usada que fornece funções ricas para criar, manipular e visualizar gráficos.
Vamos ver como usar NetworkX para visualizar nossa matriz de adjacência gerada:
importar networkx como nx importar matplotlib.pyplot como plt def visualizar_adjacência_matriz(adjacência_matriz): G = nx.from_numpy_matrix(adjacência_matriz) pos = nx.spring_layout(G) # Define a posição do nó nx.draw(G, pos, with_labels=True, node_color='skyblue', node_size=500, font_size=10) # imagem edge_labels = {(i, j): w['weight'] for i, j, w in G.edges(data=True)} # Obtenha pesos de aresta nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels, font_size=10) # Desenhar pesos de borda plt.title("Visualização do gráfico") plt.show() # teste arestas_ponderadas = [(0, 1, 5), (0, 2, 3), (1, 2, 2), (2, 3, 7)] matriz_de_adjacência ponderada = bordas_para_matriz_de_adjacência (bordas_ponderadas, ponderada = Verdadeiro) print("Matriz de adjacência ponderada:") imprimir(weighted_adjacency_matrix.toarray()) visualize_adjacency_matrix(weighted_adjacency_matrix.toarray())
Neste código, primeiro convertemos a matriz de adjacência em um objeto gráfico usando funções do NetworkX. Em seguida, use a posição do nó definido e desenhe o gráfico usando a função. Finalmente, plotamos os pesos das arestas usando uma função. from_numpy_matrix
spring_layout
draw
draw_networkx_edge_labels
Através da visualização, podemos ver claramente a estrutura do gráfico e compreender intuitivamente as relações de conexão e as informações de peso entre os nós.
Converter matriz de adjacência em lista de arestas brutas
No processamento de dados gráficos, às vezes precisamos converter a matriz de adjacência de volta à sua forma original de lista de arestas. Isso pode ser útil em certos algoritmos e aplicações, pois alguns algoritmos podem ser mais adequados para usar listas de arestas para representar o gráfico.
Vamos ver como escrever código para conseguir essa conversão:
importar numpy como np def matriz_adjacência_to_edges(matriz_adjacência): arestas = [] para i no intervalo (adjacência_matrix.shape[0]): para j no intervalo (adjacência_matrix.shape[1]): se matriz_adjacência[i, j] != 0: bordas.append((i, j, matriz_adjacência[i, j])) bordas de retorno # teste matriz_adjacência = np.array([[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 1], [0, 0, 1, 0]], dtype=np.float32) print("Matriz de adjacência original:") imprimir (matriz_adjacência) arestas = matriz_adjacência_to_arestas(matriz_adjacência) print("\nLista de arestas convertidas:") imprimir (bordas)
Neste código, iteramos cada elemento da matriz de adjacência e se o valor do elemento for diferente de zero, o convertemos em uma aresta na lista de arestas. Para gráficos com pesos, também salvamos as informações de peso na lista de arestas.
Através deste processo de conversão, podemos converter o gráfico representado pela matriz de adjacência na forma de uma lista de arestas, facilitando assim a implementação e aplicação de alguns algoritmos.
Resumo e Perspectiva
Este artigo apresenta como usar Python para converter a lista de arestas original em uma matriz de adjacência e conduz uma série de extensões e otimizações para atender às necessidades de diferentes cenários. Cobrimos vários aspectos do processamento de dados gráficos, desde o processamento de gráficos direcionados e não direcionados, listas de arestas ponderadas, até o uso de matrizes esparsas para otimizar o uso de memória, até a visualização de gráficos e conversão de matrizes de adjacência em listas de arestas brutas.
Em aplicações práticas, o processamento de dados gráficos é um campo muito importante e amplamente utilizado, envolvendo análise de redes, redes sociais, planejamento de transportes, bioinformática e muitos outros campos. Dominar as habilidades de processamento de dados gráficos pode nos ajudar a compreender e analisar melhor estruturas de dados complexas para resolver problemas práticos.
No futuro, à medida que a escala e a complexidade dos dados continuarem a aumentar, o campo do processamento de dados gráficos enfrentará mais desafios e oportunidades. Podemos esperar o surgimento de ferramentas e algoritmos mais eficientes, flexíveis e ricos em recursos para atender às necessidades e desafios em constante mudança. Ao mesmo tempo, também podemos continuar a aprender e explorar, melhorar constantemente as nossas capacidades e níveis no domínio do processamento de dados gráficos e dar maiores contribuições para a resolução de problemas práticos.
Espero que este artigo o ajude a compreender e aplicar o processamento de dados gráficos. Você também pode estudar e explorar mais este campo e contribuir para o desenvolvimento da ciência e engenharia de dados.
Clique para seguir e conhecer as novas tecnologias da Huawei Cloud o mais rápido possível~
A equipe da Google Python Foundation foi demitida. O Google confirmou as demissões, e as equipes envolvidas em Flutter, Dart e Python correram para a lista de favoritos do GitHub - Como as linguagens e estruturas de programação de código aberto podem ser tão fofas? Xshell 8 abre teste beta: suporta protocolo RDP e pode se conectar remotamente ao Windows 10/11 Quando os passageiros se conectam ao WiFi ferroviário de alta velocidade , a "maldição de 35 anos" dos codificadores chineses surge quando eles se conectam à alta velocidade. rail WiFi. A primeira ferramenta de pesquisa de IA do MySQL com suporte de longo prazo versão 8.4 GA Perplexica : Completamente de código aberto e gratuito, uma alternativa de código aberto ao Perplexity Os executivos da Huawei avaliam o valor do código aberto Hongmeng: Ele ainda tem seu próprio sistema operacional, apesar da supressão contínua. por países estrangeiros. A empresa alemã de software automotivo Elektrobit abriu o código-fonte de uma solução de sistema operacional automotivo baseada no Ubuntu.