117 lines
4.0 KiB
Python
117 lines
4.0 KiB
Python
import numpy as np
|
|
import matplotlib.pyplot as plt
|
|
import matplotlib.mlab as mlab
|
|
import scipy.io as scio
|
|
from IPython import embed
|
|
|
|
|
|
def create_food_blotch(size_x=51, size_y=51, noise=0.01, threshold=0.008):
|
|
x = np.arange(-np.round(size_x/2), np.round(size_x/2)+1)
|
|
y = np.arange(-np.round(size_y/2), np.round(size_y/2)+1)
|
|
X, Y = np.meshgrid(x, y)
|
|
Z = mlab.bivariate_normal(X, Y, sigmax=10, sigmay=10)
|
|
food = (np.random.rand(size_x, size_y) * noise) + Z
|
|
return food
|
|
|
|
|
|
def create_world(width=100, height=100, d=0.1, food_sources=100, noise=0.01):
|
|
my_world = np.zeros((int(width/d), int(height/d)))
|
|
print("placing food sources ...")
|
|
for i in range(food_sources):
|
|
x = np.random.randint(0, width/d)
|
|
y = np.random.randint(0, height/d)
|
|
food = create_food_blotch(noise=noise)
|
|
if (x + food.shape[1]) > my_world.shape[1]:
|
|
x -= food.shape[1]
|
|
if (y + food.shape[0]) > my_world.shape[0]:
|
|
y -= food.shape[0]
|
|
my_world[y:y+food.shape[0], x:x+food.shape[1]] += food
|
|
return my_world
|
|
|
|
|
|
def get_step():
|
|
options = [-1, 1]
|
|
step = np.asarray([options[np.random.randint(0, 2)], options[np.random.randint(0, 2)]])
|
|
return step
|
|
|
|
|
|
def is_valid_step(pos, step, max_x, max_y):
|
|
new_pos = pos + step
|
|
if (new_pos[0] < max_y) & (new_pos[1] < max_x) & (new_pos[0] >= 0) & (new_pos[1] >= 0):
|
|
return True
|
|
return False
|
|
|
|
|
|
def do_valid_step(pos, max_x, max_y):
|
|
valid = False
|
|
while not valid:
|
|
step = get_step()
|
|
valid = is_valid_step(pos, step, max_x, max_y)
|
|
new_pos = pos + step
|
|
return new_pos, step
|
|
|
|
|
|
def random_walk(world, steps=10000):
|
|
x_positions = np.zeros(steps)
|
|
y_positions = np.zeros(steps)
|
|
start_x = np.random.randint(0, world.shape[1])
|
|
start_y = np.random.randint(0, world.shape[0])
|
|
eaten_food = 0
|
|
new_pos = np.asarray([start_y, start_x])
|
|
for i in range(steps):
|
|
new_pos, step = do_valid_step(new_pos, world.shape[1], world.shape[0])
|
|
x_positions[i] = new_pos[1]
|
|
y_positions[i] = new_pos[0]
|
|
eaten_food += world[new_pos[0], new_pos[1]]
|
|
world[new_pos[0], new_pos[1]] = 0.0
|
|
return x_positions, y_positions, eaten_food
|
|
|
|
|
|
def not_so_random_walk(world, steps=10000):
|
|
x_positions = np.zeros(steps)
|
|
y_positions = np.zeros(steps)
|
|
start_x = np.random.randint(0, world.shape[1])
|
|
start_y = np.random.randint(0, world.shape[0])
|
|
previous_food = 0.0
|
|
current_food = 0.0
|
|
eaten_food = 0
|
|
pos = np.asarray([start_y, start_x])
|
|
step = None
|
|
for i in range(steps):
|
|
gradient = current_food - previous_food
|
|
if (gradient <= 0) or ((step is not None) and \
|
|
(not is_valid_step(pos, step, world.shape[1], world.shape[0]))):
|
|
pos, step = do_valid_step(pos, world.shape[1], world.shape[0])
|
|
else:
|
|
pos += step
|
|
x_positions[i] = pos[1]
|
|
y_positions[i] = pos[0]
|
|
previous_food = current_food
|
|
current_food = world[pos[0], pos[1]]
|
|
eaten_food += current_food
|
|
world[pos[0], pos[1]] -= current_food
|
|
return x_positions, y_positions, eaten_food
|
|
|
|
|
|
if __name__ == '__main__':
|
|
print("create world... ")
|
|
world = create_world(noise=0.0, food_sources=50)
|
|
trials = 10
|
|
gain_random = np.zeros(trials)
|
|
gain_nsr = np.zeros(trials)
|
|
print("run")
|
|
for i in range(trials):
|
|
x, y, gain_random[i] = random_walk(world.copy(), 100000)
|
|
x2, y2, gain_nsr[i] = not_so_random_walk(world.copy(), 100000)
|
|
|
|
print("random walk yields: %.2f +- %.2f food per 100000 steps" % (np.mean(gain_random),
|
|
np.std(gain_random)))
|
|
print("not so random walk yields: %.2f +- %.2f food per 100000 steps" % (np.mean(gain_nsr),
|
|
np.std(gain_nsr)))
|
|
|
|
scio.savemat('random_world.mat', {'world': world})
|
|
plt.imshow(world)
|
|
plt.scatter(x[::2], y[::2], s=0.5, color='red')
|
|
plt.scatter(x2[::2], y2[::2], s=0.5, color='green')
|
|
plt.show()
|