使用Python的另一种简单随机游走模拟(二维)

时间:2012-02-23 21:50:36

标签: python

我正在尝试从书中解决二维随机游走问题,探索python。 但是,我无法弄清楚如何才能解决这个问题。我做了一些研究,但那些太复杂,无法理解它是什么。我是初学者。所以,通过查看我无法理解代码。请详细解释这个问题。

无论如何,问题是:

  

随机游走的二维变化从中间开始   网格,例如11乘11阵列。醉酒的每一步都有四个   选择:上,下,左或右。在我们描述的章节的前面   如何创建二维数字数组。使用此数据   类型,写一个二维随机游走的模拟。

好的,我所知道的; 我知道如何在python中创建二维数组:

times = [0] * 11
for i in range(0,11):
    times[i] = [0] * 11

我得到了“randint”功能的想法:

我最近也写过这个问题的一维变体。但它是一个意大利面条代码,它非常脏,我也不确定它是否正确。

我的代码在这里:

'''
Created on Feb 11, 2012

@author: msarialp
'''
from random import randint

def drunken_man():
    steps = 0
    times = [0] * 11
    left_move = 0
    right_move = 0
    i = 0
    while left_move < 5 or right_move < 5:
        value = randint(0,1)
        times[5] = 1
        if value == 1:
            steps += 1
            print("He moved left")
            left_move += 1
            if right_move > 0:
                right_move -= 1
            if left_move == 1:
                times[4] += 1
            elif left_move == 2:
                times[3] += 1
            elif left_move == 3:
                times[2] += 1
            elif left_move == 4:
                times[1] += 1
            #elif left_move == 5:
                #times[0] += 1
        elif value == 0:
            steps += 1
            print("He moved right")
            right_move += 1
            if left_move > 0:
                left_move -= 1
            if right_move == 1:
                times[6] += 1
            elif right_move == 2:
                times[7] += 1
            elif right_move == 3:
                times[8] += 1
            elif right_move == 4:
                times[9] += 1
            #elif right_move == 5:
                #times[10] += 1
        times[i] += 1                
    for i in range(1,10):
        print("He took {steps} steps until he reaches end of the sidewalk.".format(steps = steps),  "He stood on {1} square at {0} times".format(times[i], i) )

def main():
    drunken_man()

    return 0
if __name__ == '__main__':
    main()

编辑一个

从Dan Gerhardsson那里得到一些好的建议。 我决定编辑我的问题。 所以我在这个问题上: 我明白怎样才能跟踪和检查我醉酒的男人两步的步骤。

使用元组来解决这个问题是非常容易理解的。

所以,在我的所有代码段都在这里之后,请检查并给我任何反馈。

def two_dimensional_random_walk():
    steps = 0
    times = [0] * 11
    for i in range(0,11):
        times[i] = [0] * 11
    x = 5
    y = 5
    moves = [(1,0), (0,1), (-1,0), (0,-1)]  
    while x<11 and x >= 0 or y < 11 and y >= 0:  
        dx, dy = moves[randint(0,3)]
        x += dx
        y += dy
        if dx == 1 and dy == 0:
            print("He moved right")
        elif dx == 0 and dy == 1:
            print("He moved up")
        elif dx == -1 and dy == 0:
            print("He moved left")
        elif dx == 0 and dy == -1:
            print("He moved down")
        try:
            times[x][y] += 1
            steps += 1
        except IndexError:
            break

我的打印功能是:

for i in range(0,11):
    for j in range(0,11):
        print("He took {steps} steps until he reaches end of the sidewalk.".format(steps = steps),  "He stood on {1}x{2} square at {0} times".format(times[i][j], i+1,j+1) )   

总而言之,我想在Dan Gerhardsson的帮助下,我解决了这个问题。

但是,为什么我不会用这些提示改变我的一维解决方案。

def drunken_man():
steps = 0
x = 6
times = [0] * 11
moves = [(1), (-1)]

while x < 11 and x >= 0:
    dx = moves[randint(0,1)]
    print(dx, x)
    x += dx
    try:
        times[x] += 1
        steps += 1
    except IndexError:
        break           
for i in range(1,11):
    print("He took {0} steps until he reaches end of the sidewalk.".format(steps),  "He stood on {1} square at {0} times".format(times[i], i) )

编辑二(最终修改)

我不确定是否有必要编辑我的帖子以应用Dan Gerhardsson的提示。为了帮助那些像我一样错过积分的人,我决定将所有内容组合在一起。

所以这是我的功能与Dan Gerhardsson的提示相结合:

def two_dimensional_random_walk():
steps = 0 # Steps counter for understand how many steps that our drunken man take
grid_size = 11 # Grid size variable,
# Creating Two dimensional array by using lists
times = [0] * grid_size 
for i in range(0,grid_size):
    times[i] = [0] * grid_size
# Initial variables to start in the middle of grid
x = 5
y = 5
# Tuples to get directions and decide where to go
moves = [(1,0, "right"), (0,1, "up"), (-1,0, "left"), (0,-1, "down")] 
# My loop for evaluate the steps
while True:  
    dx, dy, position = moves[randint(0,3)] # By using randint I could make decision randomly
    x += dx
    y += dy
    print("He moved", position)
    try:
        times[x][y] += 1 # And here is, how many times have he stood on each square
        steps += 1
    except IndexError: # The exit of loop
        break
# My print function which answers these questions (How long will it be until he reaeches the end of the sidewalk, and how many times will he have stood on each square)
for i in range(0,11):
    for j in range(0,11):
        print("He took {steps} steps until he reaches end of the sidewalk.".format(steps = steps),  "He stood on {1}x{2} square at {0} times".format(times[i][j], i+1,j+1) )

感谢Dan Gerhardsson的大帮助。 我想我终于得到了解决方案。

2 个答案:

答案 0 :(得分:9)

我至少可以给你一些提示。所以你有四个可能的举动。每个移动都可以用一个元组来表示,元组是x和y方向的位移:

moves = [(0, 1), (1, 0), (0, -1), (-1, 0)]

要在中心设置起始位置:

grid_size = 11
x = grid_size // 2
y = grid_size // 2

存储醉酒男子的位置并在模拟的每个步骤中更新它。像这样:

# Displacement:
dx, dy = random.choice(moves)

# Update position:
x += dx
y += dy

这可能不是初学者级别的代码,但是不是用if语句检查边界,而是可以尝试更新计数,并处理异常,如果位置在网格之外,则引发异常:

try:
    # Update counter.
    times[x][y] += 1
except IndexError:
    # Exit the simulation loop.
    break

希望这有帮助。

编辑 - 对第二个版本的评论:

由于您想在每个步骤中打印方向,您可以将其添加到元组:

moves = [(0, 1, 'up'), (1, 0, 'right'), (0, -1, 'down'), (-1, 0, 'left')]

然后您可以替换打印方向的if语句:

dx, dy, direction = random.choice(moves)
print('He moved', direction)

当您在当前解决方案中使用try-except时,您不需要检查while语句中的边界。你可以这样做:

while True:
    ...

因为异常处理程序中的中断将退出循环。

我的最后一条建议是用变量替换一些数字文字。网格大小,例如出现在不止一个地方。您应该创建一个变量并在其余代码中引用它:

grid_size = 11
times = [0] * grid_size
    for i in range(grid_size):
        times[i] = [0] * grid_size

如果要运行具有不同网格大小的代码,则使用变量而不是数字文字意味着您只需在一个位置进行更改。

答案 1 :(得分:1)

我制作了一个类似的随机游走程序,允许醉酒男子使用球坐标在三维空间的任何方向行走。

import random
import math
def rw3(n,tries):
    s = 0
    for m in range(1,tries+1):
        x = 0
        y = 0
        z = 0
        pi = math.pi
        for step in range(1,n+1):
            t = random.uniform(0,2*pi)
            f = random.uniform(0,2*pi)
            p = 1
            x += p*math.sin(f)*math.cos(t)
            y += p*math.sin(f)*math.sin(t)
            z += p*math.cos(f)
        s += (x**2+y**2+z**2)**.5
    return s/tries
life = 42
while life:
    n = int(input("Please enter the number of steps: "))
    tries = int(input("How many times should I perform the experiment? "))
    print()
    print(rw3(n,tries))
    print()