三维空间原子节点精确连接3个最近邻的实现问题
解决方法:构建3-正则无向邻接矩阵(基于距离优先级)
看起来你需要的是一个无向的3-正则图——每个节点恰好有3个双向连接的邻居,且邻居选择严格遵循距离由近到远的优先级。当前的实现只保证了出度为3,但忽略了双向性,导致出现单向边和入度不一致的问题,下面是针对性的解决方案:
核心思路
我们需要先为每个节点初始化最近邻,然后遍历所有单向边,按照你提出的规则调整:
- 若节点A的邻居包含B,但B的邻居不含A:优先让A移除B,从候选列表中找下一个最近的未连接节点
- 若A无法找到可替换的节点(极端情况),则让B将其当前邻居中距离最远的那个替换为A,确保距离优先级
代码实现
import numpy as np # 假设dist_mat是已预处理好的31×31原子距离矩阵 n_nodes = dist_mat.shape[0] target_degree = 3 # 每个节点的目标入度/出度 # 步骤1:为每个节点生成按距离从小到大排序的邻居候选列表(排除自身) sorted_neighbor_candidates = [] for node in range(n_nodes): # 收集所有非自身节点的索引和对应距离 neighbor_dist_pairs = [(other_node, dist_mat[node][other_node]) for other_node in range(n_nodes) if other_node != node] # 按距离升序排序,只保留节点索引 neighbor_dist_pairs.sort(key=lambda x: x[1]) sorted_neighbor_candidates.append([pair[0] for pair in neighbor_dist_pairs]) # 步骤2:初始化邻接矩阵和节点邻居集合(方便快速查询) adj_matrix = np.zeros((n_nodes, n_nodes), dtype=int) node_neighbor_sets = [set() for _ in range(n_nodes)] # 先给每个节点分配前3个最近的邻居 for node in range(n_nodes): for neighbor in sorted_neighbor_candidates[node][:target_degree]: adj_matrix[node][neighbor] = 1 node_neighbor_sets[node].add(neighbor) # 步骤3:处理单向边,调整连接以满足双向性和度数要求 for node_a in range(n_nodes): # 复制当前邻居列表,避免遍历过程中修改集合导致的异常 current_neighbors = list(node_neighbor_sets[node_a]) for node_b in current_neighbors: # 检测单向边:node_a连node_b,但node_b没连node_a if adj_matrix[node_b][node_a] != 1: # 尝试让node_a替换node_b,找下一个候选邻居 replacement_success = False for candidate in sorted_neighbor_candidates[node_a]: if candidate not in node_neighbor_sets[node_a]: # 移除旧邻居node_b,添加新候选 adj_matrix[node_a][node_b] = 0 node_neighbor_sets[node_a].remove(node_b) adj_matrix[node_a][candidate] = 1 node_neighbor_sets[node_a].add(candidate) replacement_success = True break # 如果node_a找不到可替换的候选(极端情况),让node_b替换最远邻居为node_a if not replacement_success: # 找到node_b当前邻居中距离最远的节点 farthest_neighbor = max(node_neighbor_sets[node_b], key=lambda x: dist_mat[node_b][x]) # 替换操作 adj_matrix[node_b][farthest_neighbor] = 0 node_neighbor_sets[node_b].remove(farthest_neighbor) adj_matrix[node_b][node_a] = 1 node_neighbor_sets[node_b].add(node_a) # 验证结果 print("每个节点的出度:", np.sum(adj_matrix, axis=1)) print("每个节点的入度:", np.sum(adj_matrix, axis=0))
关键细节说明
- 排序候选列表:预先生成按距离排序的邻居列表,确保我们始终按照距离优先级选择新邻居
- 集合存储邻居:用
set来存储每个节点的邻居,能快速判断某个节点是否已被连接,提升调整效率 - 单向边处理逻辑:严格遵循你提出的优先级——先调整发起单向边的节点,只有当无法调整时才修改被连接节点的邻居,保证距离优先的原则
运行完代码后,你会得到一个无向的邻接矩阵,每个节点的入度和出度都会严格等于3,且所有连接都是双向的。
内容的提问来源于stack exchange,提问作者WhySoSerious
相关产品推荐
相关产品推荐

