如何生成无重复粒子位置的二维NumPy数组(蒙特卡洛模拟)
问题分析与解决方案
原代码的核心问题
你写的重复检查逻辑完全错误:np.equal(particle_positions[:(i+1)], r).any() 是逐元素对比数组切片和r的每个值,只要有任意一个位置的元素相等就返回True,而不是判断整个三维坐标是否完全重复。比如数组里已有[1,2,3],新生成[4,2,5],因为第二个元素都是2,这行代码会误判为重复,导致你觉得“唯一元素被跳过”。
另外初始数组是全0的np.zeros([N,3], dtype=int),当i=0时,particle_positions[:1]是[[0,0,0]],如果第一次生成的r恰好是[0,0,0],逻辑没问题,但后续的重复判断全错。
修复后的代码
先修正重复检查逻辑,确保判断的是整个三维坐标是否重复:
import numpy as np import random as rnd N = 10 # 粒子数量 L = 10 # 盒子边长 particle_positions = np.zeros([N, 3], dtype=int) i = 0 for _ in range(N): while True: # 生成随机三维坐标 r = np.array([rnd.randint(0, L), rnd.randint(0, L), rnd.randint(0, L)]) # 检查是否和已生成的坐标完全重复:按行判断每个坐标是否与r完全匹配 is_duplicate = np.any(np.all(particle_positions[:i] == r, axis=1)) if not is_duplicate: particle_positions[i] = r i += 1 break
这里np.all(particle_positions[:i] == r, axis=1)会对每个已有的坐标,逐元素判断是否和r完全一致(axis=1表示按行处理,把每个三维坐标当作整体),再用np.any()判断是否存在重复的坐标。
更高效的实现(避免循环重试)
当N较大或L较小时(可选坐标总数(L+1)^3接近N),循环重试的效率会很低。可以直接生成所有可能的坐标,再随机抽取N个不重复的:
import numpy as np N = 10 L = 10 # 生成所有可能的三维坐标组合 all_positions = np.array(np.meshgrid(range(L+1), range(L+1), range(L+1))).T.reshape(-1, 3) # 随机选择N个不重复的坐标 particle_positions = all_positions[np.random.choice(len(all_positions), N, replace=False)]
这种方法更简洁高效,但要注意如果(L+1)^3 < N会报错(没有足够多的不重复坐标),这时需要调整N或L的取值。
内容的提问来源于stack exchange,提问作者Ossydeus
相关产品推荐
相关产品推荐

