2

I was trying to generate a random walk in 1D just with the random module. If a position at a certain moment is x, then the next position can be x+1 or x-1 with equal probability. I need to find the final position after 100 moves (start=0).

I have developed the following code, but I am not sure how I should should define the equal probability among the choices.

import random
def randomwalk1D(n):
    x = 0
    start = x
    xposition = [start]
    probabilities = [0.5, 0.5]
    for i in range(1, n + 1):
        step = random.choice(probabilities)
        if step > probabilities[0]:
            x += 1
        elif step < probabilities[1]:
            x -= 1
        xposition.append(start)
    return xposition

The function return just zeroes as result (putting n = 100). I only want to only use the random module. Could someone advise on what to do from here?

BrokenBenchmark
  • 18,126
  • 7
  • 21
  • 33
12666727b9
  • 1,133
  • 1
  • 8
  • 22

3 Answers3

2

There are two issues with your code:

  1. You need to pass the choices of -1 and 1 to random.choice(), not the weights of those choices. You can also get rid of the direct comparisons with the elements from probabilities and the sampled step. If you want weighted sampling, use numpy.random.choice.
  2. You're adding start to the xpositions list repeatedly, even though you never update it. To resolve, append x instead, which represents the actual current position.

Here is a code snippet that resolves both issues.

import random
def randomwalk1D(n):
    x = 0
    start = x
    xposition = [start]
    probabilities = [-1, 1]
    for i in range(1, n + 1):
        x += random.choice(probabilities)
        xposition.append(x)
    return xposition

print(randomwalk1D(100))
BrokenBenchmark
  • 18,126
  • 7
  • 21
  • 33
2

There's some good answers already posted, so I'll add that there's some optimizations that could be made:

import random
def randomwalk1D(n):
    x = 0
    xposition = [x]
    for _ in range(n):
        step = random.randint(0,1)
        if step:
            x += 1
        else:
            x -= 1
        xposition.append(x)
    return xposition

This removes start, as we can simply define x = 0 and since you want your list to start with this value, instantiate the list with [x] included.

    x = 0
    xposition = [x]

Instead of for i in range(1, n + 1):, we're using for _ in range(n). This cycles the same amount of times, but starting at the default of 0 instead. Because there's no use of the variable i, we're using _ which is a standard to indicate that the value doesn't matter, we only want to cycle a certain number of times.

    for _ in range(n):

Instead of a list of numbers and random.randchoice, we're using random.randint(0,1). This range is inclusive, so it will return 0, or 1.

step = random.randint(0,1)

Then, because 1 is "truthy", we can simply test if step: to test if 1, and then use else: otherwise.

        if step:
            x += 1
        else:
            x -= 1
>>> randomwalk1D(10) 
[0, 1, 2, 3, 2, 3, 4, 3, 4, 3, 4]

Edit:

If weighted numbers are needed, the following modification could be made to the code:

        choices = (0,1)
        weights = (10,1)
        step = random.choices(choices, weights=weights).pop()

step will be defined as either 0 or 1, with 0 being 10 times more likely than 1.

1

I think there are two separate problems in your code, that are leading to the results you are seeing:

  • The result of your random.choice(probabilities) expression is always a value of 0.5. With that, both of the following if statements can never be triggered, and x always remains the same value.
  • When you append the steps with xposition.append you are appending the start value, which also remains the same over iterations of the for loop, so only 0 will ever be appended.

Additionally, there might be some confusion about what random.choice actually does.
It takes a iterable, and uniformly chooses one of it's items to output. Since you have given it [0.5, 0.5] that means, you can only ever get 0.5 as an output. Perhaps you could just generate a uniformly random number, using random.uniform(0, 1) as step. That way you can just decide the direction to walk in based on step >= 0.5 or step < 0.5.

Jonas V
  • 668
  • 2
  • 5
  • 20