2

This here is a version of the random walk problem using only numpy arrays. To find the times the position is revisited over 500 steps we have to compare a sorted array of the positions with its offset, record the time it is near 0 and then increase the offset.

Here's my code so far, the problem is in the 'while' loop where I'm trying to store the final amount of times the position is revisited as elements in the 'zeroArray'

When I run it I get an index error, no results recorded and a counter which has iterated many times too many even though the Boolean expression for the loop to stop has changed.

edit: How to find the repeated position with numpy array: 1) sort the final position array into increasing order. 2) Compare slices with increasing offsets as long as you find positions within 0.001m at that offset that is you compare positions to the neighbouring postions(offset 1). you might find 18 cases where the neighbours math that at two spaces you might find only 2 cases. And at three spaces you will find 0 at which point you stop.

import numpy as np
import random

MAX_STEP_SIZE = 0.90    # maximum size of a single step [m]
NUM_STEPS = 500         # number of steps in a random walk []
NUM_WALKS = 10        # number of random walks in a run []
TOLERANCE = 0.001    # separation of points considered the same [m]
STEP_TO_RECORD_1 = 100 # first step to record and analyze []
STEP_TO_RECORD_2 = 500 # 2nd step to record and analyze []
random.seed(12345)

#......................................................................distance
def distance(posA, posB) :
    """Distance between two positions"""
    return np.abs(posA - posB)


#...............................................................initialPosition
def initialPosition() :
    """Initial position of walker at the start of a random walk"""
    return 0.0

def genPositions(nSteps, maxStep) :
    """Return the new position after a random step between -maxStep and
    maxStep, given the previous position"""
    genArray1 = (maxStep - (-maxStep))*(np.random.random(nSteps+1)) + (-maxStep)
    genArray1[0]=initialPosition()    
    return np.cumsum(genArray1)

oneStep = np.zeros(NUM_WALKS)
fiveStep = np.zeros(NUM_WALKS)
zeroStep = np.zeros(NUM_WALKS)
walkArray = np.zeros(NUM_WALKS)
counter = 1
hitcounter = 0
zerocounter = 0
keepchecking = bool(1)

for ii in range(NUM_WALKS):
    position = (genPositions(NUM_STEPS, MAX_STEP_SIZE))   
    oneStep[ii] = position[100]
    fiveStep[ii] = position[-1]
    zeroArray = np.sort(position)
    while keepchecking == bool(1):
        zerocounter = 0
        for jj in range(len(zeroArray)):
            hitcounter = 0
            if distance(zeroArray[jj+counter], zeroArray[jj]) <= TOLERANCE:
               hitcounter +=1
            zerocounter += hitcounter
            counter +=1
            if hitcounter == 0:
                keepchecking = bool(0)
    zeroStep[ii] = zerocounter

Thanks for any help,

1 Answers1

2

You can do a direct comparison of your positions vector against itself as:

deltas = np.abs(position[None, :] - position[:, None])

Now, deltas[i, j] is the distance between the positions at step i and step j. You can get your hits as:

hits = deltas <= TOLERANCE

To get pairs of close positions, you can do the following:

row, col = np.nonzero(hits)
idx = row < col # get rid of the diagonal and the upper triangular part
row = row[idx]
col = col[idx]

As an example:

>>> position = genPositions(NUM_STEPS, MAX_STEP_SIZE)
>>> row, col = np.nonzero(np.abs(position[None, :] -
...                              position[:, None]) < TOLERANCE)
>>> idx = row < col
>>> row= row[idx]
>>> col = col[idx]
>>> row
array([ 35,  40, 112, 162, 165, 166, 180, 182, 200, 233, 234, 252, 253,
       320, 323, 325, 354, 355, 385, 432, 443, 451], dtype=int64)
>>> col
array([ 64,  78, 115, 240, 392, 246, 334, 430, 463, 366, 413, 401, 315,
       380, 365, 348, 438, 435, 401, 483, 473, 492], dtype=int64)

>>> for j in xrange(len(row)) :
...     print '{0}, {1} --> {2}, {3}'.format(row[j], col[j], position[row[j]],
...                                          position[col[j]]) 
... 
35, 64 --> 2.56179226445, 2.56275159205
40, 78 --> 2.97310455111, 2.97247314695
112, 115 --> 3.40413767436, 3.40420856824
...
432, 483 --> 10.2560778101, 10.2556475598
443, 473 --> 10.7463713139, 10.7460626764
451, 492 --> 12.3804383241, 12.3805940238
Jaime
  • 65,696
  • 17
  • 124
  • 159
  • How come when I try to quantify the number of True's from hits it returns values of over 500 times for walks of only 500 positions? I tried np.sum(hits), and np.count_nonzero(hits) – user2193007 Mar 21 '13 at 01:26
  • @user2193007 `hits` has 501 `True`s in the diagonal, and you are counting twice every hit, both as `(i, j)` and as `(j, i)`. Subtract 501 from the total and divide by 2 to get the real number of hits. – Jaime Mar 21 '13 at 02:02
  • Thanks!! Sorry to be a bother but if you could also give a link to resource that could teach me a bit about slicing of numpy arrays that would be amazing! – user2193007 Mar 21 '13 at 02:11
  • @user2193007 [This](http://www.scipy.org/Tentative_NumPy_Tutorial) is a good starting point, and [this](http://docs.scipy.org/doc/numpy/reference/arrays.indexing.html) is the section of the docs on it. In general, the numpy docs are all you need. – Jaime Mar 21 '13 at 03:38