4

I'm simulating a 2-dimensional random walk, with direction 0 < θ < 2π and T=1000 steps. I already have:

a=np.zeros((1000,2), dtype=np.float)

def randwalk(x,y):
    theta=2*math.pi*rd.rand() # Theta is a random angle between 0 and 2pi
    x+=math.cos(theta);          # Since spatial unit = 1
    y+=math.sin(theta);          # Since spatial unit = 1
    return (x,y)

x, y = 0., 0.
for i in range(1000):
    x, y = randwalk(x,y)
    a[i,:] = x, y

This generates a single walk, and stores all intermediate coordinates in the numpy array a. How can I edit my code to repeat the walk 12 times (using a new random seed every time) and then save each run in a separate text file? Do I need a while loop within my randwalk function?

Guess:

rwalkrepeat = []

for _ in range(12):
    a=np.zeros((1000,2), dtype=np.float)
    x, y = 0., 0.
    for i in range(1000):
        x, y = randwalk(x,y)
        a[i,:] = x, y

rwalkrepeat.append(a)

print rwalkrepeat
  • 3
    To repeat the above 12 times, a for-loop around what you already have would work nicely. – mdurant Oct 15 '14 at 14:01
  • You should try to solve more of this on your own before posting questions. You say, "Do I need a while loop..", and the best answer to that is to try to make it work with a `while` loop. Also, try to make it work with a `for` loop, since you know about that too. Save as text?, google "numpy save as text" and see what you get.. the first hit is `numpy.savetxt` and the second is `numpy input and output`. – tom10 Oct 15 '14 at 14:57
  • @tom10 I added a guess to the post. Am I on the right lines? –  Oct 15 '14 at 16:45

3 Answers3

3

You don't need any explicit loops. The entire solution can be vectorized (untested):

nsteps = 1000
nwalks = 12
theta = 2 * np.pi * np.random.rand(nwalks, nsteps - 1)
xy = np.dstack((np.cos(theta), np.sin(theta)))
a = np.hstack((np.zeros((nwalks, 1, 2)), np.cumsum(xy, axis=1)))
NPE
  • 486,780
  • 108
  • 951
  • 1,012
0

If you use numpy, why aren't you using numpy? I'd do it this way:

n_moves = 1000
a = np.zeros((n_moves, 2))

for i in range(12):
    thetas = (2*np.pi) * np.random.rand(n_moves-1)
    a[1:,0] = np.cos(thetas)
    a[1:,1] = np.sin(thetas)
    a = np.add.accumulate(a, 0)
panda-34
  • 4,089
  • 20
  • 25
0

An approach to this which sticks with the general form of your code is:

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

a=np.zeros((1000,2), dtype=np.float)

def randwalk(x,y):
    theta=2*math.pi*rd.random() 
    x+=math.cos(theta);          
    y+=math.sin(theta);          
    return (x,y)

fn_base = "my_random_walk_%i.txt"
for j in range(12):
    rd.seed(j)
    x, y = 0., 0.
    for i in range(1000):
        x, y = randwalk(x,y)
        a[i,:] = x, y
    fn = fn_base % j
    np.savetxt(fn, a)

For the basic calculation, panda-34's and NPE's answers are also good, and take advantage of numpy's vectorization.

Here I used seed(j) to explicitly set the seed the random numbers. The advantage of this is that each result will be repeatable as long as the seed is the same, even if, say, they are not run in sequence, or you change the array length, etc. This isn't necessary though if one didn't want repeatable runs -- then random would just seed from the time and all random number throughout all runs would be different.

Explanation for file names: since OP requested saving each of multiple runs to different files, I thought it would be good to have numbered files, eg, here my_random_walk_0.txt, my_random_walk_1.txt, etc. In my example I used the name fn_base as a variable to hold the general format of the filename, so that, say, the code fn = fn_base % 17 would set fn equal to my_random_walk_17.txt (this is a bit old school for python, read about "string formatting" in python for more).

tom10
  • 67,082
  • 10
  • 127
  • 137
  • Thank you, this works great. As you can probably tell I'm very inexperienced with Python, what are fn and fn_base? –  Oct 15 '14 at 18:06
  • I've added an explanation at the end of my answer. – tom10 Oct 15 '14 at 18:21