如何将自定义函数应用于Numpy数组所有位置,优化蒙特卡洛模拟更新逻辑
蒙特卡洛/Metropolis自旋模拟全位点扫描修改方案
以下是修改后的可运行代码,符合你要求的「每次扫描遍历全部位置、满足判据的位置统一更新」的逻辑,同时修复了原代码隐藏的索引错误:
import numpy as np N = 10 J = 1 H = 2 def calcEnergy(config, J, H): energy = 0 for i in range(config.size): spin = config[i] neighbour = config[(i + 1) % N] energy = energy - J * (spin * neighbour) - H * neighbour return energy def ChangeInEnergy(J, H, spin, spinleft, spinright): dE = 2 * H * spin + 2 * J * spin * (spinleft + spinright) return dE def CasinoTime(sweeps, beta, J, H, debug=False): config = np.random.choice([-1, 1], (N, 1)) averagespins = [] if debug: print("Starting Configuration:", np.transpose(config)) runningenergy = calcEnergy(config, J, H) for sweep_idx in range(sweeps): # 基于当前未修改的构型收集所有需要翻转的位点 flip_mask = np.zeros(N, dtype=bool) total_dE = 0 for spinlocation in range(N): spin = config[spinlocation] # 修复原代码的索引错误:邻居索引使用位点位置而非自旋值 spinright = config[(spinlocation + 1) % N] spinleft = config[(spinlocation - 1) % N] dE = ChangeInEnergy(J, H, spin, spinleft, spinright) r = np.random.random() if r < min(1, np.exp(-beta * dE)): flip_mask[spinlocation] = True total_dE += dE # 统一翻转所有符合条件的位点 config[flip_mask] *= -1 runningenergy += total_dE averagespin = config.mean() averagespins.append(averagespin) if debug: print(f"{sweep_idx}: ", np.transpose(config), "Energy:", runningenergy, "Spin:", averagespin) return averagespins averagespins = CasinoTime(sweeps=20, beta=0.1, J=1, H=2, debug=True)
关键改动说明
- 修复原代码核心bug:原代码计算左右邻居时错误使用自旋值
spin作为索引,改为使用位点位置索引spinlocation,保证邻居计算逻辑正确 - 调整单轮扫描逻辑:每轮扫描先遍历全部N个位点,基于未修改的当前构型逐个计算能量变化和翻转判据,符合Metropolis算法同批次更新的规则
- 统一更新构型:所有位点判断完成后,通过掩码数组一次性翻转所有符合条件的位点,避免中间修改的自旋值影响同轮其他位点的判断
- 兼容原有逻辑:提前统计本轮所有翻转带来的总能量变化,一次性更新总能量,和原有能量、平均自旋的统计逻辑完全兼容
内容的提问来源于stack exchange,提问作者mskhan1399
相关产品推荐
相关产品推荐

