正方形随机环绕行走模拟结果波动异常:代码问题还是模拟特性?
咱们先从代码里的问题拆解,再聊聊模拟波动的本质:
一、你的代码存在几个关键问题
这些问题会直接导致结果偏差或异常波动:
重复模拟的逻辑错误
你当前的代码是先跑一次move_func得到固定路径pl,然后重复100次统计这条固定路径的结果——这相当于把同一条路径的统计值重复计算100次,完全不是“100次独立模拟”!这会让结果的波动完全不符合预期,甚至出现奇怪的偏差。移动向量的生成效率低且概率近似不准
用replicate(p*1000, ...)生成大矩阵再采样的方式,本质是用有限样本近似概率:如果p不是0.5的整数倍,p*1000会得到非整数,导致实际采样的概率和你设定的p/2、1-p有偏差。而且每次循环都重新生成这个大矩阵,效率极低。顶点匹配的潜在bug
test_in_H里用identical比较向量,很容易因为维度问题(比如x是2x1列向量,H的列是1x2行向量)返回FALSE,导致统计漏算。
二、模拟本身的波动是正常的
即便代码修正,你依然会看到结果波动,这是随机行走的固有属性:
- 这个随机过程是马尔可夫链,当步数
n有限时,起始顶点的出现频率是一个随机变量,本身就有方差。只有当n趋近于无穷大时,频率才会收敛到理论平稳分布(这里的0.25)。 - 波动大小和总样本量直接相关:如果每次模拟走
n步,重复100次,总样本量是100*(n+1)(别忘了初始点也算一个顶点)。样本量越小,波动越明显。比如n=100时,总样本量是10100,起始顶点的期望次数是2525,标准差约43,频率波动在±0.04左右;当n=1000时,波动会缩小到±0.01左右。
三、修正后的代码示例
我给你调整了代码,解决上述问题,同时提升效率:
# 生成随机行走路径:x是起始顶点(2维向量),n是步数,p是移动参数 move_func <- function(x, n, p){ pl <- matrix(x, nrow = 2, ncol = 1) # 初始化路径矩阵,每列是一个顶点 # 定义三种移动向量及对应概率 moves <- list(c(1, 0), c(0, 1), c(1, 1)) probs <- c(p/2, p/2, 1 - p) for(i in 1:n){ # 按概率随机选择移动向量 selected_move <- sample(moves, size = 1, prob = probs)[[1]] x <- (x + selected_move) %% 2 # 更新当前顶点 pl <- cbind(pl, x) # 追加到路径矩阵 } return(pl) } # 判断顶点x是否属于子集H(H是列向量组成的矩阵) test_in_H <- function(x, H){ # 用元素比较代替identical,避免维度问题 any(apply(H, 2, function(h) all(x == h))) } # 模拟参数设置 start_vertex <- c(0, 0) n_steps <- 1000 # 行走步数 p <- 0.5 # 移动参数 target_subset <- matrix(c(0, 0), nrow = 2) # 要统计的起始顶点子集 # 正确的100次独立模拟 sim_results <- replicate(100, { path <- move_func(start_vertex, n_steps, p) # 统计目标子集出现的次数,除以总顶点数(步数+1) sum(apply(path, 2, test_in_H, H = target_subset)) / (n_steps + 1) }) # 输出结果 cat("平均频率:", mean(sim_results), "\n") cat("频率标准差(波动大小):", sd(sim_results), "\n")
总结
- 你当前的结果波动异常,主要是代码逻辑错误导致的,修正后波动会回到随机过程的正常范围。
- 正常的模拟波动是随机过程的固有属性,通过增大行走步数
n和重复模拟次数,可以有效减小波动,但无法完全消除。
内容的提问来源于stack exchange,提问作者user901823
相关产品推荐
相关产品推荐

