|
import matplotlib.pyplot as plt |
|
import random |
|
import numpy as np |
|
import pandas as pd |
|
from matplotlib.lines import Line2D |
|
|
|
|
|
def single_random_walk(iters, agent_number, ax, step_size = 1, random_seed = None): |
|
if random_seed: |
|
random.seed(random_seed) |
|
|
|
iters = int(iters) |
|
directions = ['east', 'north', 'west', 'south'] |
|
start_point = [0, 0] |
|
|
|
def distance_from_start(final_coord, start_coord, round_to=2): |
|
return round(np.sqrt((final_coord[0] - start_coord[0])**2 + (final_coord[1] - start_coord[1])**2), round_to) |
|
|
|
def step_addition(old_coord, step): |
|
return [sum(x) for x in zip(old_coord, step)] |
|
|
|
def step_determination(): |
|
direction = random.choice(directions) |
|
if direction == 'east': |
|
return [1*step_size, 0] |
|
elif direction == 'west': |
|
return [-1*step_size, 0] |
|
elif direction == 'north': |
|
return [0, 1*step_size] |
|
elif direction == 'south': |
|
return [0, -1*step_size] |
|
|
|
coordinate_list = [start_point] |
|
|
|
for _ in range(iters): |
|
new_step = step_determination() |
|
new_coordinate = step_addition(coordinate_list[-1], new_step) |
|
coordinate_list.append(new_coordinate) |
|
|
|
x = [i[0] for i in coordinate_list] |
|
y = [i[1] for i in coordinate_list] |
|
df = pd.DataFrame({'x':x,'y':y}) |
|
|
|
|
|
base_marker_size = 10 |
|
markersize = base_marker_size / np.sqrt(iters) |
|
|
|
|
|
plot = ax.plot(x, y, marker='o', markersize=markersize, linestyle='None', alpha=0.5, label = 'Agent {i}'.format(i=agent_number+1)) |
|
color = plot[0].get_color() |
|
ax.plot(x[-1], y[-1], marker='o', markersize=5, color = 'black') |
|
ax.text(x[-1], y[-1], 'End {i}'.format(i=agent_number+1), color = 'black', alpha=1.0) |
|
|
|
return ax, df, color |
|
|
|
|
|
|
|
def multi_agent_walk(agent_count, iters, step_size = 1, random_seed = None): |
|
assert agent_count >= 1, "Number of agents must be >= than 1" |
|
agent_count = int(agent_count) |
|
iters = int(iters) |
|
|
|
def displacement_calc(df): |
|
x1,y1 = df.iloc[0] |
|
x2,y2 = df.iloc[-1] |
|
return np.round(np.sqrt((x2-x1)**2 + (y2-y1)**2),1) |
|
|
|
if random_seed is None: |
|
random_seed = random.randint(0,1000000) |
|
|
|
random_seed = int(random_seed) |
|
assert type(random_seed) == int, "Random seed must be an integer" |
|
|
|
random.seed(random_seed) |
|
random_numbers = [random.randint(0,100000) for _ in range(agent_count)] |
|
|
|
|
|
fig, ax = plt.subplots(figsize=(8,8)) |
|
color_list = [] |
|
|
|
for i in range(agent_count): |
|
if i == 0: |
|
ax, df, color = single_random_walk(iters=iters, ax=ax, step_size=step_size, agent_number=i, random_seed=random_numbers[i]) |
|
color_list.append(color) |
|
|
|
else: |
|
ax, df_new, color = single_random_walk(iters=iters, ax=ax, step_size=step_size, agent_number=i, random_seed=random_numbers[i]) |
|
df = pd.concat([df,df_new], axis=1) |
|
x_columns = [f'x{i}' for i in range(1, i+2)] |
|
y_columns = [f'y{i}' for i in range(1, i+2)] |
|
new_column_names = [val for pair in zip(x_columns, y_columns) for val in pair] |
|
df.columns = new_column_names |
|
color_list.append(color) |
|
|
|
ax.plot(0,0, marker='X', markersize=8, color='black') |
|
ax.text(0, 0, 'Start (0,0)') |
|
|
|
plt.grid() |
|
plt.title('Random 2D Walk with {} agents\n #Steps = {}, Step size = {}, random seed = {}\nAll agents start from the origin'.format(agent_count, iters, step_size, random_seed)) |
|
|
|
displacement = [displacement_calc(df.iloc[:,[i,i+1]]) for i in range(0,agent_count*2,2)] |
|
end_point = [(df.iloc[-1,i]) for i in range(0,agent_count*2,2)] |
|
|
|
end_point = [(df.iloc[-1,i], df.iloc[-1,i+1]) for i in range(0,agent_count*2,2)] |
|
|
|
agent_number = [i+1 for i in range(agent_count)] |
|
legend_df = pd.DataFrame({'#':agent_number, 'dis.':displacement, 'End Point':end_point, }) |
|
info_box = legend_df.to_string(index=False) |
|
|
|
ax.text(0.01, 0.99, info_box, |
|
transform=ax.transAxes, |
|
verticalalignment='top', |
|
bbox=dict(boxstyle='round', facecolor='white', alpha=0.5) |
|
) |
|
|
|
lines = [] |
|
for i in range(len(color_list)): |
|
lines.append(Line2D([0], [0], color=color_list[i], lw=9, linestyle=':')) |
|
|
|
labels = [f'Agent {i+1}' for i in range(len(color_list))] |
|
plt.legend(lines, labels, |
|
loc='best', |
|
handlelength=1.01, |
|
handletextpad=0.21, |
|
fancybox=True, |
|
fontsize=10, |
|
) |
|
|
|
fig.canvas.draw() |
|
image_array = np.array(fig.canvas.renderer.buffer_rgba()) |
|
csv_file = "2d_random_walk_coordinates.csv" |
|
df.to_csv(csv_file, index=False) |
|
|
|
try: |
|
return image_array, csv_file |
|
except: |
|
return image_array, None |
|
|
|
|
|
|
|
|
|
|