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

如何基于NetworkX构建边邻接站点约束的随机引导图网络

基于NetworkX构建满足站点信号覆盖约束的随机建筑引导图网络

实现核心是先明确边的合法性校验规则,再基于规则筛选候选边生成随机网络,不要先生成随机边再事后校验删除,后者效率低且容易产生大量孤立节点。

前置准备

  • 加载两份数据源:将建筑、站点数据分别解析为(唯一ID, x坐标, y坐标)格式的列表,根据业务场景提前定义站点信号覆盖半径coverage_radius,即站点能覆盖到邻近边的最大距离
  • 数据量较大时,提前用scipy.spatial.KDTree对站点坐标构建空间索引,避免每次校验边都遍历全量站点计算距离,大幅提升运算效率
  • 点到线段的距离计算直接调用shapely库的内置几何方法,不用手写几何公式,减少计算bug

边合法性校验规则(核心约束)

两个建筑节点之间可以连边的充要条件是:两点构成的线段上,存在至少一个点到最近站点的距离小于等于信号覆盖半径,覆盖场景包括:

  • 站点距离某一侧建筑节点足够近
  • 站点处于线段中间位置,到线段的垂直距离在覆盖半径内

校验时可以先通过线段外接矩形过滤掉距离过远的站点,只对矩形范围内的候选站点做精确距离计算,进一步压缩计算量

随机建网流程

  1. 从全量建筑中随机抽取指定数量的建筑,作为网络的初始节点集合
  2. 枚举所有节点对,逐条通过上述校验规则筛选,得到所有符合覆盖要求的合法边池
  3. 根据需要的网络拓扑从合法边池中选边:要纯随机图就按设定的边密度随机抽边,要连通图可以先基于合法边生成最小生成树保证全连通,再随机补充边调整密度,要k近邻网络就为每个节点选择距离最近的k个合法邻居连边
  4. 最终校验:遍历网络所有边重新做覆盖校验,同时检查连通性、节点度等拓扑指标是否符合要求,不满足则重新抽边/抽节点迭代

代码实现

先安装依赖:
pip install networkx shapely scipy numpy

完整可运行示例:

import random
import networkx as nx
import numpy as np
from scipy.spatial import KDTree
from shapely.geometry import LineString, Point

# ------------ 参数配置 ------------
SELECT_BUILDING_NUM = 50  # 随机选取的建筑节点数量
COVERAGE_RADIUS = 300     # 站点信号覆盖半径,单位与坐标单位保持一致
EDGE_DENSITY = 0.08       # 随机网络目标边密度,取值范围0-1
# 模拟数据,实际使用时替换为本地文件读取逻辑即可
buildings = [(i, random.uniform(0, 10000), random.uniform(0, 10000)) for i in range(1000)]
stations = [(i, random.uniform(0, 10000), random.uniform(0, 10000)) for i in range(200)]
# ----------------------------------

# 构建站点KDTree用于快速近邻查询
station_coords = np.array([(s[1], s[2]) for s in stations])
station_tree = KDTree(station_coords)

def check_edge_cover(b1, b2):
    """校验两个建筑构成的边是否被至少一个站点信号覆盖"""
    x1, y1 = b1[1], b1[2]
    x2, y2 = b2[1], b2[2]
    line = LineString([(x1, y1), (x2, y2)])
    # 先筛出线段外接矩形周边的候选站点,减少后续计算量
    center_x, center_y = (x1+x2)/2, (y1+y2)/2
    search_r = max(abs(x1-x2), abs(y1-y2))/2 + COVERAGE_RADIUS
    candidate_idx = station_tree.query_ball_point((center_x, center_y), r=search_r)
    for idx in candidate_idx:
        sx, sy = station_coords[idx]
        if line.distance(Point(sx, sy)) <= COVERAGE_RADIUS:
            return True
    return False

# 初始化网络
G = nx.Graph()
selected_buildings = random.sample(buildings, SELECT_BUILDING_NUM)
for b in selected_buildings:
    G.add_node(b[0], pos=(b[1], b[2]))

# 生成合法边池
valid_edges = []
for i in range(len(selected_buildings)):
    for j in range(i+1, len(selected_buildings)):
        b1, b2 = selected_buildings[i], selected_buildings[j]
        if check_edge_cover(b1, b2):
            edge_len = np.hypot(b1[1]-b2[1], b1[2]-b2[2])
            valid_edges.append((b1[0], b2[0], edge_len))

# 按目标密度抽边生成网络
target_edge_count = int(EDGE_DENSITY * SELECT_BUILDING_NUM * (SELECT_BUILDING_NUM - 1) / 2)
chosen_edges = random.sample(valid_edges, min(target_edge_count, len(valid_edges)))
G.add_weighted_edges_from(chosen_edges)

# 如需保证网络全连通,补充最小生成树边
if not nx.is_connected(G):
    valid_full_graph = nx.Graph()
    valid_full_graph.add_weighted_edges_from(valid_edges)
    mst_edges = nx.minimum_spanning_edges(valid_full_graph, data=True)
    G.add_edges_from(mst_edges)

效果验证

生成网络后可直接遍历所有边调用check_edge_cover做二次校验,确认无不符合约束的边;可视化直接调用NetworkX的绘图接口,传入节点坐标属性即可得到和目标样式一致的网络:
随机引导图网络示例

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 19:06:41