简体   繁体   English

Python 中的 Random Walk 项目:我怎样才能让我的一个步行者走的频率是其他方向的两倍?

[英]Random Walk project in Python: How can I make one of my walkers walk twice as often as any other direction?

Here is the code I have so far.这是我到目前为止的代码。 But in line 104 I have one of my walkers, Mi-Ma, walking south two times compared to the other directions each time it is called, but when I coded this I misread the description of the project.但是在第 104 行,我的一个步行者 Mi-Ma 每次被调用时,与其他方向相比,向南走了两次,但是当我编写这个代码时,我误读了项目的描述。 Instead of always walking south two times it should instead walk twice as often as any other directions.与其总是向南走两次,不如向其他方向走两倍。 What can I do to make her walk twice as often and not just two times each times south is called?我该怎么做才能让她走两次,而不是每次向南走两次?

import turtle as ts
from math import sqrt
from random import choices, seed
from statistics import mean, stdev
from sys import argv
import tempfile
import subprocess

def save_to_image(dest='random_walk.png'):
    '''Saves the turtle canvas to dest. Do not modify this function.'''
    with tempfile.NamedTemporaryFile(prefix='random_walk',
                                     suffix='.eps') as tmp:
        ts.getcanvas().postscript(file=tmp.name)
        subprocess.run(['gs',
                        '-dSAFER',
                        '-o',
                        dest,
                        '-r200',
                        '-dEPSCrop',
                        '-sDEVICE=png16m',
                        tmp.name],
                       stdout=subprocess.DEVNULL)

def get_args() -> tuple:
    walk_lengths = list(map(int, argv[1].split(',')))
    n = int(argv[2])
    walker_name = argv[3]
    return (walk_lengths, n, walker_name)


class RandomWalker:
    '''
    Class to represent the random walker.
    '''
    directions = dict(
        North=[0, +1],
        South=[0, -1],
        East=[+1, 0],
        West=[-1, 0],
    )

    def __init__(self, name, N, S, E, W, color, shape) -> None:
        '''
        Initialisation function
            Parameters:
                name (str) : name of random walker
                N,S,E,W (int) : weights for moving in the specified direction
                color (str) : color for plot representation
                shape (str) : shape for plot representation
        '''
        self.name = name
        self.N = N
        self.S = S
        self.E = E
        self.W = W
        self.color = color
        self.shape = shape

    def take_walk(self, walk_length, n) -> list:
        '''
        Takes a random walk
            Parameters:
                walk_length (int): Length of random walk
            Returns:
                List of final destinations
        '''
        walker_weight = (self.N, self.S, self.E, self.W)
        directions = list(RandomWalker.directions.keys())
        final_postions = []

        for _ in range(n):
            position = [0, 0]
            for step in range(walk_length):
                random_direction = choices(
                    directions, weights=walker_weight, k=1)[0]
                delta_direction = RandomWalker.directions[random_direction]
                position[0] += delta_direction[0]
                position[1] += delta_direction[1]
            final_postions.append(position)

        final_distances = list(map(lambda pos: sqrt(
            pos[0]**2 + pos[1]**2), final_postions))

        Mean = mean(final_distances)
        CV = stdev(final_distances)/Mean
        Max = max(final_distances)
        Min = min(final_distances)

        print(f'{self.name} random walk of {walk_length} steps\nMean = {Mean:.1f} CV = {CV:.1f}\nMax = {Max:.1f} Min = {Min:.1f}')

        return final_postions

    @staticmethod
    def get_walkers(walker_name: str) -> list:
        '''
        Returns the instances of the RandomWalkers
            Parameters:
                walker_name: mentions the random_walker; 'all' for all walkers
            Returns:
                A list containing instance of random walkers.
        '''
        walkers = {
            'Pa': RandomWalker('Pa', 1, 1, 1, 1, 'black', 'circle'),
            'Mi-Ma': RandomWalker('Mi-Ma', 1, 2, 1, 1, 'green', 'square'),
            'Reg': RandomWalker('Reg', 0, 0, 1, 1, 'red', 'triangle'),
        }
        if walker_name in walkers:
            return [(walkers[walker_name])]
        elif walker_name == 'all':
            return list(walkers.values())
        else:
            raise Exception(f'Inavlid walker_name, "{walker_name}"')


def simulate(walk_lengths: list, n: int, walker_name: str) -> list:
    '''
    Simulating random walks
        Parameters:
            walk_lengths (list) : length of random walks to simulate
            n (int) : number of random walks to simulate
            walker_name (str) : mentions the random_walker; 'all' for all walkers
        Returns:
            Data for plotting (list) of form [shape, color, final_postions, walk_length]
    '''
    walkers = RandomWalker.get_walkers(walker_name)

    data_for_plotting = []
    for walker in walkers:
        for walk_length in walk_lengths:
            final_postion = walker.take_walk(walk_length, n)
            data_for_plotting.append(
                [walker.shape, walker.color, final_postion, walk_length])
    return data_for_plotting


def plot(data_for_plotting: list = []) -> None:
    '''
    Function to plot
        Parameters:
            data_for_plotting (list) of form [shape, color, final_postions, walk_length]
    '''

    ts.screensize(300, 400)
    turtle = ts.Turtle()
    turtle.speed(0)
    turtle.shapesize(0.5, 0.5)
    turtle.up()



    for shape, color, positions, walk_length in data_for_plotting:

        if walk_length > 100:
            continue

        turtle.shape(shape)
        turtle.color(color)

        for position in positions:
            x, y = position
            scale = 5
            turtle.goto(x*scale, y*scale)
            turtle.stamp()

    save_to_image()
def main():
    plotting_data = simulate(*get_args())
    plot(plotting_data)

if __name__ == "__main__":
    main()

Here is the part of the project description that asks for this step.这是要求执行此步骤的项目描述部分。 It is in the last paragraph.它在最后一段。

"Farmer John has an old grandparent (Pa) that likes to wander off randomly when working in the barn. Pa starts from the barn and every second takes one step in a random direction North, South, East or West. What is Pa's expected distance away from the barn after 1000 steps? If Pa takes many steps, will Pa be likely to move ever further from the origin, or be more likely to wander back to the origin over and over, and end up not far from where he started? Let's write a simulation to find out. “农夫约翰有一位老祖父母(Pa),他在谷仓工作时喜欢随意走动。Pa 从谷仓开始,每一秒都向北、南、东或西随机方向迈出一步。Pa 的预期距离是多少1000步后离开谷仓?如果Pa走了很多步,Pa会不会离原点越来越远,或者更有可能一遍又一遍地回到原点,最终离他开始的地方不远?让我们编写一个模拟来找出答案。

This particular barn is in the center of a large grassy field.这个特殊的谷仓位于一大片草地的中心。 One day Pa starts to wander off, and notices that the grass has been mysteriously cut (by John) to resemble graph paper.有一天,爸爸开始走神,注意到草被(约翰)神秘地剪成了方格纸。 Notice that after one step Pa is always exactly one unit away from the start.请注意,在一步之后,Pa 总是与起点正好相距一个单位。 Let's assume that Pa wanders eastward from the initial location on the first step.假设 Pa 在第一步从初始位置向东游荡。 How far away might Pa be from the initial location after the second step?在第二步之后,Pa 可能离初始位置多远? John sees that with a probability of 0.25 Pa will be 0 units away, with a probability of 0.25 Pa will be 2 units away, and with a probability of 0.5 Pa will be √2 units away. John 看到 0.25 Pa 的概率是 0 个单位,0.25 Pa 的概率是 2 个单位,0.5 Pa 的概率是 √2 个单位。 So, on average Pa will be further away after two steps than after one step.因此,平均而言,两步后的 Pa 会比一步后的距离更远。 What about the third step?第三步呢? If the second step is to the north or south, the third step will bring the farmer closer to origin half the time and further half the time.如果第二步是向北或向南,则第三步将使农民更接近原产地一半的时间和更远的一半时间。 If the second step is to the west (back to the start), the third step will be away from the origin.如果第二步向西(回到起点),第三步将远离原点。 If the second step is to the east, the third step will be closer to the origin a quarter of the time, and further away three quarters of the time.如果第二步向东,第三步离原点近四分之一,离原点远四分之三。

It seems like the more steps Pa takes, the greater the expected distance from the origin.似乎 Pa 采取的步数越多,与原点的预期距离就越大。 We could continue this exhaustive enumeration of possibilities and perhaps develop a pretty good intuition about how this distance grows with respect to the number of steps.我们可以继续对可能性进行详尽的列举,或许可以对这个距离如何随着步数增长有一个很好的直觉。 However, it is getting pretty tedious, so it seems like a better idea to write a program to do it for us.然而,它变得相当乏味,所以编写一个程序来为我们做这件事似乎是一个更好的主意。

However, there are a couple more twists to the situation.然而,情况还有一些曲折。 Pa's wife Mi-Ma, another grandparent of John's, also likes to wander away randomly, but riding an old mule.爸爸的妻子米玛,约翰的另一位祖父母,也喜欢乱走,但骑着一头老骡子。 The mule goes South twice as often as any other direction.骡子向南走的频率是其他方向的两倍。 Lastly, John's favorite hog Reg has an odd habit of wandering off too, but only randomly going east or west at each step, never north or south.最后,约翰最喜欢的猪雷格也有一个奇怪的流浪习惯,但只是在每一步都随机向东或向西走,从不向北或向南。 People think he's a sun-follower, but nobody's really sure.人们认为他是太阳追随者,但没有人真正确定。 John figures your Python program ought to model these two as well, while you're at it." John 认为您的 Python 程序也应该是 model 这两个程序,而您正在使用它。”

Using the random.choices function (as you do), this can be achieved using the weights parameter:使用random.choices function (就像你一样),这可以使用weights参数来实现:

from random import choices

random_direction = choices(population=['N', 'E', 'S', 'W'],
                           weights=[1, 1, 2, 1],
                           k=1)[0]

You could make a single call of choices out of the for loop BTW, since this is a choice with replacement.顺便说一句,您可以从 for 循环中进行一次choices调用,因为这是一个替换选择。 Something like random_direction=choices(..., k=n) .类似random_direction=choices(..., k=n)的东西。

Alternatively, you could use random.choice without s repeating the south direction (inside the for loop here since this only picks one direction at a time):或者,您可以使用random.choice而不s重复南方向(在此处的for循环内,因为它一次只选择一个方向):

from random import choice

random_direction = choice(seq=['N', 'E', 'S', 'S', 'W'])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM