在具有可变时间增量的模拟中适当地缩放随机运动
Properly scale random movement in simulation with variable time delta
我想编写一维运动粒子的模拟。模拟具有以下参数:
max_speed
: 粒子能达到的最大速度(in meters/second)
delta
:两次模拟步骤之间的时间间隔(以秒为单位)
iters
:运行模拟的步数
下面是一个工作模拟的例子。它 returns 两个值列表:一个用于每个时间步的粒子位置,另一个用于每个时间步的相应秒数。
import random
def simulate_particle(max_speed, delta, iters):
current_position = 0
positions = [current_position]
seconds = [0]
for frame in range(1, iters+1):
max_distance_possible = max_speed * delta
current_position += max_distance_possible * random.uniform(-1, 1)
positions.append(current_position)
seconds.append(frame * delta)
return positions, seconds
如您所见,粒子在下一帧的位置由以下因素决定:
- 计算粒子能够在两帧之间移动的最大可能距离(考虑到
max_speed
和 delta
参数)
- 将此值乘以从 [-1, 1] 上的均匀分布采样的值(以增加一些随机性)
这里的问题是 粒子运动与 delta
参数 相关联。由于较大的 delta
s 允许更大的最大距离,因此在具有较大 delta
s 的模拟中,粒子更容易远离起始位置。
这是此问题的图形表示:
import matplotlib.pyplot as plt
for delta, iters, color in zip(
[600, 60, 6], # decreasing deltas
[10, 100, 1000], # larger number of iterations to achieve same end time
['blue', 'orange', 'green'],
):
for repeat in range(50): # run simulations 50 times for each delta
ys, xs = simulate_particle(max_speed=5, delta=delta, iters=iters)
label = f'{delta=}, {iters=}' if repeat == 0 else None
plt.plot(xs, ys, color=color, label=label)
plt.xlabel('Time (s)')
plt.ylabel('Position')
plt.legend()
plt.show()
输出:
我理解为什么会发生这种情况:与从更广泛的分布中多次采样相比,从狭窄的分布中多次采样更难达到极值。
我的问题是 我该如何解决这个问题? 我可以做一些标准化吗?我尝试将均匀分布更改为其他分布(例如高斯分布),但最终还是发生了同样的效果。
如您所知,您正在模拟不同的过程,这就是您获得不同行为的原因。
“重新缩放”曲线的一种方法是以缩小的单位绘制结果:将时间 (x
) 数组除以 delta
(设置时间刻度)和位置 (y
) array by delta * max_speed
(它设置了长度刻度)以获得类似的东西(注意我放大以突出显示三组轨迹之间的重叠更明显的绘图区域):
您 运行 的主要任务是将多个随机 运行 直接组合到 Central Limit Theorem 中。即,如您所见,当您将多个均匀绘制相加时,您会在最终粒子位置接近正态分布,而不是单个较大的均匀分布。从均匀分布中提取以跳过时间步意味着您将从肩部比您应该的大得多的分布中有效地采样。因此,蓝线爆炸了。
要解决这个问题,您应该弄清楚您真正的基本时间步长 delta0
是什么,然后 运行 就可以了。如果你想加速一些因素,那么你应该从 Irwin–Hall distribution 中绘制,并通过你将对 [0, 1] 均匀分布进行的相同转换缩放和移动绘制以使其在 [ -1, 1] 范围。而且无论你是否加速,你都应该改变你的 max_distance_possible
方程以依赖基本时间步长。
例如,这里有一些伪代码来替换主循环:
delta0 = 1
speedupfactor = 10
delta = speedupfactor * delta0
# IrwinHall scaled and shifted as if the underlying uniform draw was over [-1,1]
randdraw = 2*IrwinHall(n=speedupfactor) - speedupfactor
max_distance_possible = max_speed * delta0
current_position += max_distance_possible * randdraw
positions.append(current_position)
seconds.append(frame * delta)
如果您的过程确实是连续的,那么 delta0 = 0
的极限情况意味着这将等同于从纯正态分布中绘制,您可以改为这样做。这意味着您必须根据标准偏差而不是最大速度来定义运动。
不幸的是 scipy.stats 没有 Irwin-Hall 作为概率分布,但它在 sympy 中实现为 sympy.stats.UniformSum()
我想编写一维运动粒子的模拟。模拟具有以下参数:
max_speed
: 粒子能达到的最大速度(in meters/second)delta
:两次模拟步骤之间的时间间隔(以秒为单位)iters
:运行模拟的步数
下面是一个工作模拟的例子。它 returns 两个值列表:一个用于每个时间步的粒子位置,另一个用于每个时间步的相应秒数。
import random
def simulate_particle(max_speed, delta, iters):
current_position = 0
positions = [current_position]
seconds = [0]
for frame in range(1, iters+1):
max_distance_possible = max_speed * delta
current_position += max_distance_possible * random.uniform(-1, 1)
positions.append(current_position)
seconds.append(frame * delta)
return positions, seconds
如您所见,粒子在下一帧的位置由以下因素决定:
- 计算粒子能够在两帧之间移动的最大可能距离(考虑到
max_speed
和delta
参数) - 将此值乘以从 [-1, 1] 上的均匀分布采样的值(以增加一些随机性)
这里的问题是 粒子运动与 delta
参数 相关联。由于较大的 delta
s 允许更大的最大距离,因此在具有较大 delta
s 的模拟中,粒子更容易远离起始位置。
这是此问题的图形表示:
import matplotlib.pyplot as plt
for delta, iters, color in zip(
[600, 60, 6], # decreasing deltas
[10, 100, 1000], # larger number of iterations to achieve same end time
['blue', 'orange', 'green'],
):
for repeat in range(50): # run simulations 50 times for each delta
ys, xs = simulate_particle(max_speed=5, delta=delta, iters=iters)
label = f'{delta=}, {iters=}' if repeat == 0 else None
plt.plot(xs, ys, color=color, label=label)
plt.xlabel('Time (s)')
plt.ylabel('Position')
plt.legend()
plt.show()
输出:
我理解为什么会发生这种情况:与从更广泛的分布中多次采样相比,从狭窄的分布中多次采样更难达到极值。
我的问题是 我该如何解决这个问题? 我可以做一些标准化吗?我尝试将均匀分布更改为其他分布(例如高斯分布),但最终还是发生了同样的效果。
如您所知,您正在模拟不同的过程,这就是您获得不同行为的原因。
“重新缩放”曲线的一种方法是以缩小的单位绘制结果:将时间 (x
) 数组除以 delta
(设置时间刻度)和位置 (y
) array by delta * max_speed
(它设置了长度刻度)以获得类似的东西(注意我放大以突出显示三组轨迹之间的重叠更明显的绘图区域):
您 运行 的主要任务是将多个随机 运行 直接组合到 Central Limit Theorem 中。即,如您所见,当您将多个均匀绘制相加时,您会在最终粒子位置接近正态分布,而不是单个较大的均匀分布。从均匀分布中提取以跳过时间步意味着您将从肩部比您应该的大得多的分布中有效地采样。因此,蓝线爆炸了。
要解决这个问题,您应该弄清楚您真正的基本时间步长 delta0
是什么,然后 运行 就可以了。如果你想加速一些因素,那么你应该从 Irwin–Hall distribution 中绘制,并通过你将对 [0, 1] 均匀分布进行的相同转换缩放和移动绘制以使其在 [ -1, 1] 范围。而且无论你是否加速,你都应该改变你的 max_distance_possible
方程以依赖基本时间步长。
例如,这里有一些伪代码来替换主循环:
delta0 = 1
speedupfactor = 10
delta = speedupfactor * delta0
# IrwinHall scaled and shifted as if the underlying uniform draw was over [-1,1]
randdraw = 2*IrwinHall(n=speedupfactor) - speedupfactor
max_distance_possible = max_speed * delta0
current_position += max_distance_possible * randdraw
positions.append(current_position)
seconds.append(frame * delta)
如果您的过程确实是连续的,那么 delta0 = 0
的极限情况意味着这将等同于从纯正态分布中绘制,您可以改为这样做。这意味着您必须根据标准偏差而不是最大速度来定义运动。
不幸的是 scipy.stats 没有 Irwin-Hall 作为概率分布,但它在 sympy 中实现为 sympy.stats.UniformSum()