随机游走在随机初始化值范围内的停止条件

Stopping condition if a random walk is within a range of randomly initialised values

我在具有随机初始化位置的 2D 网格上随机游走。我正在寻找一个条件,如果随机游走在其他随机游走的初始位置的某个范围内,它将停止。

虽然我发现这在简单的情况下很容易实现,但在 N 次随机游动的情况下实现起来却遇到了麻烦。这是因为代码需要检查每个初始位置周围的一系列值,但当前随机游走周围的值除外。

P.S 这是我第一次 post 堆栈溢出。请让我知道我是否过于含糊或没有遵循此处提出问题的指南。

import numpy.random as rd               #importing libraries
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
import numpy.ma as ma

lsize=100
T=1000 #n of steps
N=5 #n of walks
xvec=np.zeros(N)
yvec=np.zeros(N)
xstore=np.zeros(T+1)
ystore=np.zeros(T+1)
xmat=np.zeros((T+1,N))
ymat=np.zeros((T+1,N))

for i in range(N):    #randomly assigns initial position
    xcor=rd.randint(1,lsize)
    ycor=rd.randint(1,lsize)
    xvec[i]=xcor
    yvec[i]=ycor

for i in range(N):
    xstore[0]=xvec[i]
    ystore[0]=yvec[i]
    for j in range(T):
            A=[0,1,2,3]
            temp=rd.choice(A)
            if temp==0:
                ystore[j+1]=ystore[j]+1 #up
                xstore[j+1]=xstore[j]
            elif temp==1:
                xstore[j+1]=xstore[j]+1 #right
                ystore[j+1]=ystore[j]
            elif temp==2:
                ystore[j+1]=ystore[j]-1 #down
                xstore[j+1]=xstore[j]
            elif temp==3:
                xstore[j+1]=xstore[j]-1 #left
                ystore[j+1]=ystore[j]
            xstore[j+1]=np.mod(xstore[j+1], lsize+1)
            ystore[j+1]=np.mod(ystore[j+1], lsize+1)
    xmat[:,i]=xstore
    ymat[:,i]=ystore
plt.plot(xmat,ymat)
plt.show()

除了您本可以更好地定义 "within some range of the initial positions of the other random walks" 之外,这是一个问得很好的问题。我假设您指的是 x 或 y 中的某个距离或 x,y 平面中的某个距离标准。下面仅概述了 x 中距离标准的解决方案,但对其他标准的扩展很简单。

基本上,您需要在内部 for 循环的末尾有一个检查标准:

distance_in_x = np.mod(np.abs(xvec - xstore[j+1]), lsize)
distance_in_x[i] = np.inf # effectively mask that position
if np.any(distance_in_x <= min_distance_in_x):
    break

这假设您已经在上面的某处定义了 min_distance_in_x。 基本技巧是通过向其添加无穷大来掩盖步行本身到原点的距离。同样,您也可以只添加 min_distance_in_x 以确保下一行中的检查永远不会选择该来源。

编辑

对于起点原点周围的正方形,脚本变为:

import numpy.random as rd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
import numpy.ma as ma

lsize=100
T=1000 #n of steps
N=10 #n of walks
xvec=np.zeros(N)
yvec=np.zeros(N)
xmat=np.full((T+1,N), np.nan)
ymat=np.full((T+1,N), np.nan)

min_distance_in_x = 3
min_distance_in_y = 3

# randomly assigns initial position
for i in range(N):
    xcor=rd.randint(1,lsize)
    ycor=rd.randint(1,lsize)
    xvec[i]=xcor
    yvec[i]=ycor

# walk
for i in range(N):
    xstore=np.full(T+1, np.nan)
    ystore=np.full(T+1, np.nan)
    xstore[0]=xvec[i]
    ystore[0]=yvec[i]

    for j in range(T):
        A=[0,1,2,3]
        temp=rd.choice(A)
        if temp==0:
            ystore[j+1]=ystore[j]+1 #up
            xstore[j+1]=xstore[j]
        elif temp==1:
            xstore[j+1]=xstore[j]+1 #right
            ystore[j+1]=ystore[j]
        elif temp==2:
            ystore[j+1]=ystore[j]-1 #down
            xstore[j+1]=xstore[j]
        elif temp==3:
            xstore[j+1]=xstore[j]-1 #left
            ystore[j+1]=ystore[j]

        xstore[j+1]=np.mod(xstore[j+1], lsize+1)
        ystore[j+1]=np.mod(ystore[j+1], lsize+1)

        distance_in_x = np.abs(xvec - xstore[j+1])
        distance_in_x[i] = np.inf # effectively mask that position

        distance_in_y = np.abs(yvec - ystore[j+1])
        distance_in_y[i] = np.inf # effectively mask that position

        if np.any(np.logical_and(distance_in_x <= min_distance_in_x,
                                 distance_in_y <= min_distance_in_y)):
            print("Got too close on run #{}!".format(i))
            break

    xmat[:,i]=xstore
    ymat[:,i]=ystore

for x, y in zip(xmat.T, ymat.T):
    # break the line by inserting NaNs where the boundary is crossed (i.e. a step size > 1)
    linebreaks, = np.where((np.abs(np.diff(x)) > 1) | (np.abs(np.diff(y)) > 1))
    if linebreaks.size > 0 :
        x = np.insert(x, linebreaks+1, np.nan)
        y = np.insert(y, linebreaks+1, np.nan)

    # plot lines
    plt.plot(x, y)

# plot start points
plt.gca().set_prop_cycle(None) # resets color cycle
for x, y in zip(xmat[0,:], ymat[0,:]):
    plt.plot(x, y, 'o', ms=10)

# plot end points
plt.gca().set_prop_cycle(None) # resets color cycle
for x, y in zip(xmat.T, ymat.T):
    # select last non-nan entry
    x = x[~np.isnan(x)][-1]
    y = y[~np.isnan(y)][-1]
    plt.plot(x, y, '^', ms=10)

plt.show()