You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

绘制双曲格点图时遇NetworkXError:节点无位置的技术问询

双曲格点模拟程序的NetworkX节点位置错误修复

问题描述

开发基于Python的双曲格点模拟程序,用于研究双曲格点密度、曲率与AdS空间、AdS/CFT对偶的关系,使用matplotlib、numpy、networkx库。运行时出现NetworkXError提示“节点无位置”,调整node_size、edge_color、with_labels参数无效。

错误栈信息

Traceback (most recent call last):
  File "C:\Users\zorty\Masaüstü\.venv\Lib\site-packages\networkx\drawing\nx_pylab.py", line 445, in draw_networkx_nodes
    xy = np.asarray([pos[v] for v in nodelist])
                     ~~~^^^
KeyError: (np.float64(0.70848), np.float64(0.0))

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "c:\Users\zorty\Masaüstü\Project.py", line 51, in <module>
    nx.draw(G, pos, node_size=10, edge_color="blue", with_labels=False)
  File "C:\Users\zorty\Masaüstü\.venv\Lib\site-packages\networkx\drawing\nx_pylab.py", line 126, in draw
    draw_networkx(G, pos=pos, ax=ax, **kwds)
  File "C:\Users\zorty\Masaüstü\.venv\Lib\site-packages\networkx\drawing\nx_pylab.py", line 314, in draw_networkx
    draw_networkx_nodes(G, pos, **node_kwds)
  File "C:\Users\zorty\Masaüstü\.venv\Lib\site-packages\networkx\drawing\nx_pylab.py", line 447, in draw_networkx_nodes
    raise nx.NetworkXError(f"Node {err} has no position.") from err
networkx.exception.NetworkXError: Node (np.float64(0.70848), np.float64(0.0)) has no position.

错误原因分析

  1. 递归终止逻辑缺陷:当递归深度达到max_depth时,函数直接返回,未为该层节点添加pos属性。但这些节点在上一层递归中已通过G.add_edge被自动加入图中,导致绘图时找不到位置信息。
  2. 浮点数类型不匹配:节点标识使用numpy.float64元组,后续属性查找时可能出现匹配失效的问题。

修复后的完整代码

import numpy as np
import matplotlib.pyplot as plt
import networkx as nx
import random
from collections import deque

# 双曲格点参数
p = 7       # 每个多边形的边数(七边形)
q = 3       # 每个顶点连接的多边形数
depth = 4   # 递归深度

# 初始化图
G = nx.Graph()

def hyperbolic_polygon_vertices(sides, center, radius):
    angles = np.linspace(0, 2 * np.pi, sides, endpoint=False)
    vertices = []
    for angle in angles:
        x = center[0] + radius * np.cos(angle)
        y = center[1] + radius * np.sin(angle)
        vertices.append((float(x), float(y)))  # 转换为Python原生float
    return vertices

def add_hyperbolic_lattice(G, center, radius, depth, max_depth):
    # 先为当前节点添加位置属性,确保所有节点都有pos
    pos_x = float(radius * np.cos(center[0]))
    pos_y = float(radius * np.sin(center[1]))
    G.add_node(center, pos=(pos_x, pos_y))
    
    # 达到最大深度时停止递归,不再生成子节点
    if depth >= max_depth:
        return
    
    # 生成相邻节点
    angle_offset = 2 * np.pi / q
    for i in range(q):
        angle = i * angle_offset
        new_radius = radius * 0.8  # 调整半径模拟双曲空间深度效果
        new_center_x = float(center[0] + new_radius * np.cos(angle))
        new_center_y = float(center[1] + new_radius * np.sin(angle))
        new_center = (new_center_x, new_center_y)
        
        # 添加边并递归生成子节点
        G.add_edge(center, new_center)
        add_hyperbolic_lattice(G, new_center, new_radius, depth + 1, max_depth)

# 初始化中心节点
initial_center = (0.0, 0.0)  # 使用Python原生float
initial_radius = 0.3
add_hyperbolic_lattice(G, initial_center, initial_radius, 0, depth)

# 绘制双曲格点
pos = nx.get_node_attributes(G, 'pos')
nx.draw(G, pos, node_size=10, edge_color="blue", with_labels=False)
plt.title("Hyperbolic Lattice (Poincaré Disk)")
plt.show()

# 按距离计算密度
def calculate_density_by_distance(G, center, max_distance):
    distances = nx.single_source_shortest_path_length(G, center)
    density_by_distance = {}

    for distance in range(1, max_distance + 1):
        nodes_in_ring = [node for node, dist in distances.items() if dist == distance]
        if nodes_in_ring:
            area = np.pi * ((distance + 1)**2 - distance**2)  # 近似环面积
            density_by_distance[distance] = len(nodes_in_ring) / area

    return density_by_distance

# 计算并绘制密度-距离曲线
center_node = initial_center
density_data = calculate_density_by_distance(G, center_node, max_distance=5)

plt.plot(density_data.keys(), density_data.values())
plt.xlabel("Distance from Center")
plt.ylabel("Density")
plt.title("Density vs Distance in Hyperbolic Lattice")
plt.show()

# 分析边界连通性(AdS/CFT类比)
distances = nx.single_source_shortest_path_length(G, center_node)
max_distance = max(distances.values())
boundary_nodes = [node for node, dist in distances.items() if dist == max_distance]
boundary_connectivity = np.mean([G.degree(node) for node in boundary_nodes])

print("Average connectivity at boundary (AdS/CFT analogy):", boundary_connectivity)

# 模拟到边界的网络流(黑洞热力学类比)
boundary_node = random.choice(boundary_nodes)
try:
    flow_value, _ = nx.maximum_flow(G, center_node, boundary_node)
    print("Simulated flow value (energy transfer to boundary):", flow_value)
except Exception as e:
    print(f"Error calculating flow: {e}")

关键修复点

  1. 调整递归逻辑:将G.add_node移到递归终止条件之前,确保所有被加入图的节点都带有pos属性,包括达到最大深度的节点。
  2. 统一浮点数类型:将所有节点坐标转换为Python原生float,避免numpy.float64元组导致的属性查找匹配问题。
  3. 优化错误捕获:在网络流计算中捕获具体异常信息,提升调试效率。

内容的提问来源于stack exchange,提问作者Elly_0

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 22:14:58