Условие остановки, если случайное блуждание находится в диапазоне случайно инициализированных значений

У меня есть случайная прогулка по 2D-сетке со случайно инициализированными позициями. Я ищу условие, при котором, если случайное блуждание находится в пределах некоторого диапазона начальных позиций других случайных блужданий, оно остановится.

Хотя я обнаружил, что это легко реализовать в простом случае, у меня возникли проблемы с реализацией в случае N случайных блужданий. Это связано с тем, что код должен проверять диапазон значений вокруг каждой начальной позиции, кроме той, которая находится вокруг текущего случайного блуждания.

P.S. Это мой первый пост о переполнении стека. Пожалуйста, дайте мне знать, если я был слишком расплывчатым или не следовал правилам задавать вопросы здесь.

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()

person Peter Petrov    schedule 07.10.2018    source источник


Ответы (1)


Это хорошо заданный вопрос, за исключением того факта, что вы могли бы лучше определить «в пределах некоторого диапазона начальных позиций других случайных блужданий». Я предполагаю, что вы имеете в виду некоторое расстояние по 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()

введите здесь описание изображения

person Paul Brodersen    schedule 08.10.2018
comment
Привет, спасибо за ответ! Это именно то, к чему я стремился, но как расстояние в плоскости xy (или, скажем, квадрат вокруг каждой начальной точки). Изменить: я заметил, что вы отредактировали свой код! - person Peter Petrov; 08.10.2018
comment
Да, я думаю, это может быть связано с тем, что я забыл стереть xstore и ystore из-за преждевременной неудачной попытки. Моментально обновит код. - person Paul Brodersen; 08.10.2018
comment
Эта версия теперь должна создавать более интерпретируемое изображение. Возможно, у вас недостаточно репутации для публикации изображения, в противном случае это маленький значок изображения над текстовым полем. - person Paul Brodersen; 08.10.2018
comment
На самом деле периодические граничные условия обрабатываются неправильно. Не могу исправить это сейчас, так как через минуту или две я буду AFK. Дайте мне знать, если они доставят вам проблемы. По сути, вы также хотите проверить расстояние (для x) xvec + 100 - xstore[j+1], сравнить его с xvec - xstore[j+1], взять минимальное из двух, а затем выполнить проверку. - person Paul Brodersen; 08.10.2018
comment
Спасибо за удивительный ответ. Итак, как я понимаю, ваш скрипт останавливается вокруг квадрата длиной 3 вокруг всех начальных точек, кроме первой? Также есть ли у вас какие-либо рекомендации для участков вокруг границы? Я думал замаскировать все значения на границе (x, y = lsize), но это оставило бы пробел в графике. - person Peter Petrov; 08.10.2018
comment
На данный момент я не вижу никаких проблем с граничным условием. Также в чем причина использования np.nan вместо np.zeroes? Еще раз спасибо за такую ​​помощь! - person Peter Petrov; 08.10.2018
comment
Что касается граничных условий, предположим, что (0,0) является началом координат. В нынешнем виде обход, проходящий через (100, 100), вполне разрешен, даже если вы, кажется, хотите применить периодические граничные условия, и, следовательно, расстояние до (0,0) равно (1, 1). - person Paul Brodersen; 09.10.2018
comment
Что касается использования np.nan: 0 является допустимым значением для ваших координат x и y. Использование NaN предотвращает любую путаницу с точками, проходящими через начало координат, а также позволяет вам строить линии без необходимости явно отслеживать длину линий (поскольку NaN подавляются моей matplotlib по умолчанию). - person Paul Brodersen; 09.10.2018
comment
Понятно, сегодня попробую реализовать. Спасибо за обстоятельный ответ! - person Peter Petrov; 09.10.2018
comment
Сделано еще одно обновление, которое удаляет скачки границ с графиков. В будущем постарайтесь, чтобы объем вопроса был как можно меньше. Последующие вопросы, относящиеся именно к рассматриваемой проблеме, хороши, но только для косвенно связанных проблем вам действительно следует открыть другую ветку. Повеселись! - person Paul Brodersen; 09.10.2018