Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 17 additions & 43 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,55 +1,29 @@
# Random Walk Simulation
# Instructions for the random walker scipt:

This is a **group exercise**, so you should be working in pairs of two students. It's **30% of your final grade**.
The random walker creates a random path for a number of steps and number of walkers, specified by the user. The output is an image, which shows the walk for every walker in different
plots.

The Goal is to **practise writing readable, maintainable and reliable code collaboratively.**
## Instructions to the user

## Group Exercise
1. Clone the repository from Github
2. Move to the cloned repository via the command line
3. Specify the number of steps, the number of walkers and the name of the outputfile (as can be seen in the screenshot below)
Important: **the number of walkers cannot be higher than 12**
4. You need to call the script with python, writing: python walker.py ...
5. For example: python walker.py 10 4 ./test_image.png

1. One student of your group forks the code from [https://github.com/advanced-geoscripting-2021/random_walker.git](https://github.com/advanced-geoscripting-2021/random_walker.git)
100000 = number of steps

2. This student invites the other student as a collaborator to the forked repository. Now you can both work on the code.

3. Adapt the code to fulfil the requirements (see below).
4 = number of walkers

4. Code review: Each group reviews the code of another group.
./test_image.pn = name of the outputfile

5. Improve your code based on the review you got.

Example for setting the parameters:

## Write an extended random walk program
![image](https://github.com/hn437/random_walk/blob/yannik/screenshot_readme.PNG)

In this repo you find a basic implementation of a [random walk simulation](https://en.wikipedia.org/wiki/Random_walk) in 2-dimensional space taken from [this blogpost](https://www.geeksforgeeks.org/random-walk-implementation-python/). Running the code yields an image which shows the path of the random walk.

![random_walk](rand_walk_100000.png)

The program works but it is not very readable. In addition, you should **extend the program based on the requirements listed below.

**Remember to apply the best practices in scientific computing** to make the code more readable, maintainable, reusable and efficient.

### Minimum requirements:

Extend the program so the following requirements are met:

1. The program should be able to simulate multiple random walkers.
2. The program should be executable from the command line.
3. The user should be able to specify the number of random walkers through a command line parameter.
4. Document the dependencies and instructions of how to run the program in your README.md.

### Additional requirements:

1. Create three different types of walkers, e.g. a "fast walker" which has a bigger step size.
2. Add a "landscape" in which the random walkers are walking in which contains obstacles which the walkers cannot cross (e.g. a lake)
3. Invent and implement another functionality of your own.

Be creative here! :)

## Code Review

Review the code of another group: (tuesday afternoon or wednesday morning)

1. Does it work properly? Try to make it fail!
2. Are the best-practices implemented in the code?
3. Is the documentation clear?
4. Can you adapt the code easily? E.g. try to create a new type of random walker which moves two cells per iteration.
Example for the output:

![image](https://github.com/hn437/random_walk/blob/yannik/output.png)
40 changes: 0 additions & 40 deletions main.py

This file was deleted.

Binary file added output.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added screenshot_readme.PNG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
55 changes: 55 additions & 0 deletions tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Random Walk Simulation

This is a **group exercise**, so you should be working in pairs of two students. It's **30% of your final grade**.

The Goal is to **practise writing readable, maintainable and reliable code collaboratively.**

## Group Exercise

1. One student of your group forks the code from [https://github.com/advanced-geoscripting-2021/random_walker.git](https://github.com/advanced-geoscripting-2021/random_walker.git)

2. This student invites the other student as a collaborator to the forked repository. Now you can both work on the code.

3. Adapt the code to fulfil the requirements (see below).

4. Code review: Each group reviews the code of another group.

5. Improve your code based on the review you got.


## Write an extended random walk program

In this repo you find a basic implementation of a [random walk simulation](https://en.wikipedia.org/wiki/Random_walk) in 2-dimensional space taken from [this blogpost](https://www.geeksforgeeks.org/random-walk-implementation-python/). Running the code yields an image which shows the path of the random walk.

![random_walk](rand_walk_100000.png)

The program works but it is not very readable. In addition, you should **extend the program based on the requirements listed below.

**Remember to apply the best practices in scientific computing** to make the code more readable, maintainable, reusable and efficient.

### Minimum requirements:

Extend the program so the following requirements are met:

1. The program should be able to simulate multiple random walkers.
2. The program should be executable from the command line.
3. The user should be able to specify the number of random walkers through a command line parameter.
4. Document the dependencies and instructions of how to run the program in your README.md.

### Additional requirements:

1. Create three different types of walkers, e.g. a "fast walker" which has a bigger step size.
2. Add a "landscape" in which the random walkers are walking in which contains obstacles which the walkers cannot cross (e.g. a lake)
3. Invent and implement another functionality of your own.

Be creative here! :)

## Code Review

Review the code of another group: (tuesday afternoon or wednesday morning)

1. Does it work properly? Try to make it fail!
2. Are the best-practices implemented in the code?
3. Is the documentation clear?
4. Can you adapt the code easily? E.g. try to create a new type of random walker which moves two cells per iteration.

138 changes: 138 additions & 0 deletions walker.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""A Random Walk Simulation For Multiple Walkers"""

# Python code for 2D random walk.
# Source: https://www.geeksforgeeks.org/random-walk-implementation-python/
import sys
import numpy as np
import matplotlib.pyplot as plt


def create_walkers(number_of_steps, number_of_walkers):
"""
Creates a list of numpy arrays which each hold the coordinates of a walker. The coordinates
are randomly chosen in a range from 0 to the number of steps
:param number_of_steps: the number of steps the walker will make. This defines the
dimension of the array which represents the walker
:param number_of_walkers: the number of walkers defines the number of arrays, which
will be created
:return: a list, the 'scene' which contains all walkers, so all arrays containing coordinates
"""
scene = []
for _ in range(number_of_walkers):
# create the array of a walker and add it to the scene-list
walker = np.random.randint(low=0, high=number_of_steps,
size=(number_of_steps, 2))
scene.append(walker)

return scene


def calculate_the_path(walker, number_of_steps):
"""
Calculates the path the walker walks
:param walker: The array representing the walker, holding random coordinates
:param number_of_steps: the number of steps the walker takes
:return: the updated array representing the walker, holding all coordinates the walker walks to
"""
# split coordinates
x_coord = walker[:, 0]
y_coord = walker[:, 1]

# calculate new coordinates for each step
for stepnumber in range(1, number_of_steps):
direction_of_step = np.random.randint(1, 4)
if direction_of_step == 1: # east
x_coord[stepnumber] = x_coord[stepnumber - 1] + 1
y_coord[stepnumber] = y_coord[stepnumber - 1]
elif direction_of_step == 2: # west
x_coord[stepnumber] = x_coord[stepnumber - 1] - 1
y_coord[stepnumber] = y_coord[stepnumber - 1]
elif direction_of_step == 3: # north
x_coord[stepnumber] = x_coord[stepnumber - 1]
y_coord[stepnumber] = y_coord[stepnumber - 1] + 1
else: # south
x_coord[stepnumber] = x_coord[stepnumber - 1]
y_coord[stepnumber] = y_coord[stepnumber - 1] - 1

# return all coordinates of the path
return walker


def plot_the_paths(list_of_walkers, outputfilename):
"""
Creates the plot of the calculated path of the walker
:param list_of_walkers: Arrays representing the walkers. Each array holds the
coordinates of the respective path the walker walked.
:param outputfilename: The file which will be created with the plotted paths
"""
# define the number of rows and columns of subplots
if len(list_of_walkers) == 1:
columns_of_plots = 1
else:
columns_of_plots = 2
rows_of_plots = round(len(list_of_walkers)/2)

# create the subplots
figure, axis = plt.subplots(rows_of_plots, columns_of_plots)
for counter in enumerate(list_of_walkers):
# get the coordinates of this walker, get its subplot and plot the path in it
x_coords = counter[1][:, 0]
y_coords = counter[1][:, 1]

row = int(counter[0]/2)
if counter[0] % 2 == 0:
column = 0
else:
column = 1

axis[row, column].plot(x_coords, y_coords)
axis[row, column].set_title(f'Walker {counter[0]+1}')

if len(list_of_walkers) % 2 != 0:
# if the number of walkers is odd, delete the last (unused) subplot
figure.delaxes(axis[(rows_of_plots - 1), 1])

# arange subplot to not interfere each other, save the figure to the outputfile and
# show the plot to the user
figure.tight_layout()
plt.savefig(outputfilename)
plt.show()


def main():
"""The main program. Reads in the user definitions, creates the scene, calculates
the path and plots it"""
try:
# read in specifications defined by the user
number_of_steps = int(sys.argv[1]) + 1
number_of_walkers = int(sys.argv[2])
outputfilename = sys.argv[3]

assert number_of_steps > 1, "number_of_steps must be greater than '0'. " \
"You stated '{}'".format(number_of_steps - 1)
assert number_of_walkers > 0, "number_of_walkers must be greater than '1'. " \
"You stated '{}'".format(number_of_walkers)
assert number_of_walkers <= 12, "number_of_walkers must be max. '12'. " \
"You stated '{}'".format(number_of_walkers)
except ValueError as err:
print("Error: one of the inputs was not correctly specified.\n"
"The Input must be specified as 'python main.py number_of_steps "
"number_of_walkers outputfilename'.\n"
"Inputformats: number_of_steps --> Integer, number_of_walkers --> "
"Integer, outputfilename --> string\n"
"outputfilename: path_to_output/filename.png\n"
"The number of walkers and the number of steps to be made must be "
"positive & at least 1\n\n\n",
err)
sys.exit(1)

scene = create_walkers(number_of_steps, number_of_walkers)
for walker in scene:
walker = calculate_the_path(walker, number_of_steps)
plot_the_paths(scene, outputfilename)


if __name__ == "__main__":
main()