mardi 30 novembre 2021

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. 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.

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. Let’s assume that Pa wanders eastward from the initial location on the first step. How far away might Pa be from the initial location after the second step? 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. So, on average Pa will be further away after two steps than after one step. 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. 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."




Aucun commentaire:

Enregistrer un commentaire