update plotting functions
This commit is contained in:
parent
ee6ab086d8
commit
db1d59843b
5
agent.py
5
agent.py
@ -160,6 +160,7 @@ class RandomWalkerAnt(Agent):
|
|||||||
|
|
||||||
|
|
||||||
# recruit new ants
|
# recruit new ants
|
||||||
|
print("RECRUITING")
|
||||||
for agent_id in self.model.get_unique_ids(self.model.N_r):
|
for agent_id in self.model.get_unique_ids(self.model.N_r):
|
||||||
if self.model.schedule.get_agent_count() < self.model.N_m:
|
if self.model.schedule.get_agent_count() < self.model.N_m:
|
||||||
agent = RandomWalkerAnt(unique_id=agent_id, model=self.model, look_for_pheromone="B", drop_pheromone="A")
|
agent = RandomWalkerAnt(unique_id=agent_id, model=self.model, look_for_pheromone="B", drop_pheromone="A")
|
||||||
@ -219,8 +220,8 @@ class RandomWalkerAnt(Agent):
|
|||||||
if self.energy < self.model.e_min:
|
if self.energy < self.model.e_min:
|
||||||
self.model.schedule.remove(self)
|
self.model.schedule.remove(self)
|
||||||
#update list of dead agents for time step
|
#update list of dead agents for time step
|
||||||
self.model.dead_agents[self.model.schedule.steps-1] += 1
|
self.model.dying_agents += 1
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self._choose_next_pos()
|
self._choose_next_pos()
|
||||||
self._adjust_pheromone_drop_rate()
|
self._adjust_pheromone_drop_rate()
|
||||||
|
12
hexplot.py
12
hexplot.py
@ -13,6 +13,9 @@ def plot_hexagon(A, title=None, block=True):
|
|||||||
Y[:,i] += 1
|
Y[:,i] += 1
|
||||||
|
|
||||||
fig, ax = plt.subplots()
|
fig, ax = plt.subplots()
|
||||||
|
fig.set_figwidth(10)
|
||||||
|
fig.set_figheight(10)
|
||||||
|
fig.set_dpi(600)
|
||||||
im = ax.hexbin(
|
im = ax.hexbin(
|
||||||
X.reshape(-1),
|
X.reshape(-1),
|
||||||
Y.reshape(-1),
|
Y.reshape(-1),
|
||||||
@ -24,8 +27,11 @@ def plot_hexagon(A, title=None, block=True):
|
|||||||
ax.set_aspect(1)
|
ax.set_aspect(1)
|
||||||
ax.set(xlim=(-4, X.max()+4,), ylim=(-4, Y.max()+4))
|
ax.set(xlim=(-4, X.max()+4,), ylim=(-4, Y.max()+4))
|
||||||
ax.axis(False)
|
ax.axis(False)
|
||||||
plt.colorbar(im)
|
ax.set_xmargin(0)
|
||||||
|
ax.set_ymargin(0)
|
||||||
|
#plt.colorbar(im, shrink=0.7)
|
||||||
|
|
||||||
if(title is not None):
|
if(title is not None):
|
||||||
plt.title(title)
|
pass
|
||||||
plt.show(block=block)
|
#plt.title(title)
|
||||||
|
plt.savefig(f"{title}.png")
|
||||||
|
68
main.py
68
main.py
@ -310,41 +310,71 @@ def place_blocking_object(center, radius, model):
|
|||||||
model.grid.fields['res'][pos] = infinity
|
model.grid.fields['res'][pos] = infinity
|
||||||
|
|
||||||
|
|
||||||
def plot_heatmap():
|
def run_model():
|
||||||
from hexplot import plot_hexagon
|
|
||||||
from tqdm import tqdm
|
from tqdm import tqdm
|
||||||
# nests rather far away but also partially clumped.
|
# nests rather far away but also partially clumped.
|
||||||
np.random.seed(6)
|
np.random.seed(6)
|
||||||
|
|
||||||
from model import kwargs_paper_setup1 as kwargs
|
from model import kwargs_paper_setup1 as kwargs
|
||||||
kwargs["gamma"] /= 3 # field decays slower
|
kwargs["gamma"] /= 2
|
||||||
kwargs["beta"] /= 3 # drop rates decays slower
|
kwargs["beta"] /= 2
|
||||||
kwargs["d_e"] /= 3 # live longer, search longer
|
kwargs["d_e"] /= 5 # live longer, search longer
|
||||||
kwargs["d_s"] /= 3 # live longer, search longer
|
kwargs["d_s"] /= 5 # live longer, search longer
|
||||||
|
kwargs["N_0"] *= 2 # more initial roamers/scouts
|
||||||
|
kwargs["max_steps"] *= 2 # more initial roamers/scouts
|
||||||
|
|
||||||
model = ActiveWalkerModel(**kwargs)
|
model = ActiveWalkerModel(**kwargs)
|
||||||
a = np.zeros_like(model.grid.fields['food'])
|
a = np.zeros_like(model.grid.fields['food'])
|
||||||
a[np.nonzero(model.grid.fields['food'])] = 1
|
a[np.nonzero(model.grid.fields['food'])] = 1
|
||||||
a[np.nonzero(model.grid.fields['nests'])] = -1
|
a[np.nonzero(model.grid.fields['nests'])] = -1
|
||||||
plot_hexagon(a, title="food locations", block=False)
|
|
||||||
for _ in tqdm(range(model.max_steps)):
|
for _ in tqdm(range(model.max_steps)):
|
||||||
model.step()
|
model.step()
|
||||||
|
return model
|
||||||
|
|
||||||
for time in np.arange(0, model.max_steps + 1, 1000):
|
|
||||||
pheromone_concentration = model.datacollector.get_model_vars_dataframe()["pheromone_a"][time]
|
|
||||||
a = pheromone_concentration
|
|
||||||
#plot_hexagon(a)
|
|
||||||
pheromone_concentration = model.datacollector.get_model_vars_dataframe()["pheromone_b"][time]
|
|
||||||
b = pheromone_concentration
|
|
||||||
#plot_hexagon(b)
|
|
||||||
c = np.max([a,b], axis=0)
|
|
||||||
c = a + b
|
|
||||||
c = np.clip(c, 0, 200)
|
|
||||||
plot_hexagon(c)
|
|
||||||
|
|
||||||
|
|
||||||
|
from model import kwargs_paper_setup1 as kwargs
|
||||||
|
kwargs["gamma"] /= 2
|
||||||
|
kwargs["beta"] /= 2
|
||||||
|
kwargs["d_e"] /= 5 # live longer, search longer
|
||||||
|
kwargs["d_s"] /= 5 # live longer, search longer
|
||||||
|
kwargs["N_0"] *= 2 # more initial roamers/scouts
|
||||||
|
kwargs["max_steps"] *= 2 # more initial roamers/scouts
|
||||||
|
|
||||||
|
def run_model_objects(step, seed=None, title=None):
|
||||||
|
from tqdm import tqdm
|
||||||
|
# nests rather far away but also partially clumped.
|
||||||
|
np.random.seed(6)
|
||||||
|
from hexplot import plot_hexagon
|
||||||
|
model = ActiveWalkerModel(**kwargs)
|
||||||
|
a = np.zeros_like(model.grid.fields['food'])
|
||||||
|
a[np.nonzero(model.grid.fields['food'])] = 1
|
||||||
|
a[np.nonzero(model.grid.fields['nests'])] = -1
|
||||||
|
for current_step in tqdm(range(model.max_steps)):
|
||||||
|
if current_step == step:
|
||||||
|
if seed is not None:
|
||||||
|
np.random.seed(seed)
|
||||||
|
for _ in range(10):
|
||||||
|
coord = np.random.randint(0, 100, size=2)
|
||||||
|
coord = (coord[0], coord[1])
|
||||||
|
place_blocking_object(center=coord,radius=5, model=model)
|
||||||
|
a = model.grid.fields["res"]
|
||||||
|
if title is not None:
|
||||||
|
plot_hexagon(a, title=title)
|
||||||
|
model.step()
|
||||||
|
return model
|
||||||
|
|
||||||
#if __name__ == "__main__":
|
#if __name__ == "__main__":
|
||||||
plot_heatmap()
|
#plot_heatmap()
|
||||||
|
#res = run_model_no_objects()
|
||||||
|
for i in range(10):
|
||||||
|
res = run_model_objects(step=6000, seed=i+100, title=f"objects/blockings_run_{i}")
|
||||||
|
from plot import plot_alive_ants_vs_time, dead_ants_vs_time, plot_connectivity_vs_time
|
||||||
|
plot_alive_ants_vs_time(res, title=f"objects/run_{i}")
|
||||||
|
dead_ants_vs_time(res, title=f"objects/dead_ants_run_{i}")
|
||||||
|
plot_connectivity_vs_time(res, title=f"objects/conn_run_{i}")
|
||||||
|
|
||||||
|
|
||||||
#print("DISTANCE TEST VS SUCCESSFUL ANTS OBJECT INBETWEEN")
|
#print("DISTANCE TEST VS SUCCESSFUL ANTS OBJECT INBETWEEN")
|
||||||
#res = fixed_distance_tests()
|
#res = fixed_distance_tests()
|
||||||
#res = fixed_distance_object_between()
|
#res = fixed_distance_object_between()
|
||||||
|
47
model.py
47
model.py
@ -101,6 +101,7 @@ class ActiveWalkerModel(Model):
|
|||||||
self.N_f : int = N_f #num food sources
|
self.N_f : int = N_f #num food sources
|
||||||
self.successful_ants = 0 # for viviane's graph
|
self.successful_ants = 0 # for viviane's graph
|
||||||
self.connectivity = 0 # for viviane's persistence
|
self.connectivity = 0 # for viviane's persistence
|
||||||
|
self.dying_agents = 0
|
||||||
|
|
||||||
fields=["A", "B", "nests", "food", "res"]
|
fields=["A", "B", "nests", "food", "res"]
|
||||||
self.schedule = SimultaneousActivation(self)
|
self.schedule = SimultaneousActivation(self)
|
||||||
@ -129,8 +130,6 @@ class ActiveWalkerModel(Model):
|
|||||||
self.max_steps = max_steps
|
self.max_steps = max_steps
|
||||||
self.grid.add_nest(nest_position)
|
self.grid.add_nest(nest_position)
|
||||||
|
|
||||||
self.dead_agents = [i*0 for i in range(self.max_steps)]
|
|
||||||
self.alive_agents = [self.N_r for i in range(self.max_steps)]
|
|
||||||
|
|
||||||
for agent_id in self.get_unique_ids(N_0):
|
for agent_id in self.get_unique_ids(N_0):
|
||||||
if self.schedule.get_agent_count() < self.N_m:
|
if self.schedule.get_agent_count() < self.N_m:
|
||||||
@ -146,7 +145,8 @@ class ActiveWalkerModel(Model):
|
|||||||
model_reporters = {"pheromone_a": lambda m: m.grid.fields["A"],
|
model_reporters = {"pheromone_a": lambda m: m.grid.fields["A"],
|
||||||
"pheromone_b": lambda m: m.grid.fields["B"],
|
"pheromone_b": lambda m: m.grid.fields["B"],
|
||||||
"alive_ants": lambda m: m.schedule.get_agent_count(),
|
"alive_ants": lambda m: m.schedule.get_agent_count(),
|
||||||
"sucessful_walkers": lambda m: m.successful_ants,
|
"dying_ants": lambda m: m.dying_agents,
|
||||||
|
"successful_walkers": lambda m: m.successful_ants,
|
||||||
"connectivity": lambda m: m.connectivity,
|
"connectivity": lambda m: m.connectivity,
|
||||||
},
|
},
|
||||||
agent_reporters={}
|
agent_reporters={}
|
||||||
@ -154,10 +154,8 @@ class ActiveWalkerModel(Model):
|
|||||||
self.datacollector.collect(self) # keep at end of __init___
|
self.datacollector.collect(self) # keep at end of __init___
|
||||||
|
|
||||||
# Breadth-first-search algorithm for connectivity
|
# Breadth-first-search algorithm for connectivity
|
||||||
# TODO: Implement pheromone B (take max of the two or sum?)
|
|
||||||
# alex: what's to say against max?
|
|
||||||
def bfs(self):
|
def bfs(self):
|
||||||
threshold = 0.0000001 #the value of A
|
threshold = 0.5 # half of min sens
|
||||||
connectivity = 0 #initial value of connectivity
|
connectivity = 0 #initial value of connectivity
|
||||||
connected_food_sources = [] #empty list of connected food sources
|
connected_food_sources = [] #empty list of connected food sources
|
||||||
visited = [] #empty list of visited (by the algorithm) nodes
|
visited = [] #empty list of visited (by the algorithm) nodes
|
||||||
@ -186,7 +184,6 @@ class ActiveWalkerModel(Model):
|
|||||||
connected_food_sources = connected_food_sources + list([current_node]) #and it is added to the list of connected food sources
|
connected_food_sources = connected_food_sources + list([current_node]) #and it is added to the list of connected food sources
|
||||||
|
|
||||||
# why not normalize to 0-1 ?
|
# why not normalize to 0-1 ?
|
||||||
print(f"{connectivity=}")
|
|
||||||
return connectivity #we want the connectivity (0-5)
|
return connectivity #we want the connectivity (0-5)
|
||||||
|
|
||||||
def agent_density(self):
|
def agent_density(self):
|
||||||
@ -198,9 +195,11 @@ class ActiveWalkerModel(Model):
|
|||||||
|
|
||||||
|
|
||||||
def step(self):
|
def step(self):
|
||||||
|
self.dying_agents = 0
|
||||||
self.schedule.step() # step() and advance() all agents
|
self.schedule.step() # step() and advance() all agents
|
||||||
|
|
||||||
if self.schedule.steps % 100 == 0:
|
if self.schedule.steps % 100 == 0:
|
||||||
self.connectivity = self.bfs()
|
pass
|
||||||
|
|
||||||
# apply decay rate on pheromone levels
|
# apply decay rate on pheromone levels
|
||||||
for key in ("A", "B"):
|
for key in ("A", "B"):
|
||||||
@ -209,12 +208,8 @@ class ActiveWalkerModel(Model):
|
|||||||
|
|
||||||
|
|
||||||
self.datacollector.collect(self)
|
self.datacollector.collect(self)
|
||||||
self.alive_agents[self.schedule.steps-1] = len(self.schedule.agents)
|
|
||||||
|
|
||||||
|
|
||||||
if self.schedule.steps >= self.max_steps:
|
if self.schedule.steps >= self.max_steps:
|
||||||
self.plot_alive_agents()
|
|
||||||
self.plot_aliveDead_agents()
|
|
||||||
self.running = False
|
self.running = False
|
||||||
|
|
||||||
def get_unique_id(self) -> int:
|
def get_unique_id(self) -> int:
|
||||||
@ -225,35 +220,7 @@ class ActiveWalkerModel(Model):
|
|||||||
for _ in range(num_ids):
|
for _ in range(num_ids):
|
||||||
yield self.get_unique_id()
|
yield self.get_unique_id()
|
||||||
|
|
||||||
def plot_aliveDead_agents(self):
|
|
||||||
|
|
||||||
import matplotlib.pyplot as plt
|
|
||||||
|
|
||||||
plt.figure()
|
|
||||||
x = [i for i in range(self.max_steps)]
|
|
||||||
plt.plot(x, self.dead_agents, label="dead ants")
|
|
||||||
plt.plot(x, self.alive_agents, label="alive ants")
|
|
||||||
plt.title("Number of ants alive and dead per time step")
|
|
||||||
plt.legend(loc="best")
|
|
||||||
plt.xlabel('time steps')
|
|
||||||
plt.ylabel('Number of ants')
|
|
||||||
|
|
||||||
plt.show()
|
|
||||||
|
|
||||||
def plot_alive_agents(self):
|
|
||||||
|
|
||||||
import matplotlib.pyplot as plt
|
|
||||||
|
|
||||||
plt.figure()
|
|
||||||
x = [i for i in range(self.max_steps)]
|
|
||||||
plt.plot(x, self.alive_agents, label="alive ants")
|
|
||||||
plt.title("Number of ants alive per time step")
|
|
||||||
plt.legend(loc="best")
|
|
||||||
plt.xlabel('time steps')
|
|
||||||
plt.ylabel('Number of ants')
|
|
||||||
|
|
||||||
plt.show()
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, version 3.
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, version 3.
|
||||||
|
|
||||||
|
71
plot.py
Normal file
71
plot.py
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
#!/bin/python
|
||||||
|
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import numpy as np
|
||||||
|
from hexplot import plot_hexagon
|
||||||
|
|
||||||
|
def plot_alive_ants_vs_time(model, title=None):
|
||||||
|
y = model.datacollector.get_model_vars_dataframe()["alive_ants"]
|
||||||
|
plt.figure(figsize=(10,10), dpi=600)
|
||||||
|
plt.plot(y)
|
||||||
|
plt.xlabel("time step")
|
||||||
|
plt.ylabel("alive agents")
|
||||||
|
if title is None:
|
||||||
|
plt.savefig("alive_agents_over_time.eps")
|
||||||
|
else:
|
||||||
|
plt.savefig(f"{title}.png")
|
||||||
|
|
||||||
|
|
||||||
|
def plot_connectivity_vs_time(model, title=None):
|
||||||
|
y = model.datacollector.get_model_vars_dataframe()["connectivity"]
|
||||||
|
plt.figure(figsize=(10,10), dpi=600)
|
||||||
|
plt.plot(y)
|
||||||
|
plt.xlabel("time step")
|
||||||
|
plt.ylabel("No. of food sources connected to the nest")
|
||||||
|
if title is None:
|
||||||
|
plt.savefig("connectivity_over_time.eps")
|
||||||
|
else:
|
||||||
|
plt.savefig(f"{title}.png")
|
||||||
|
|
||||||
|
|
||||||
|
def dead_ants_vs_time(model, title=None):
|
||||||
|
y = np.cumsum(model.datacollector.get_model_vars_dataframe()["dying_ants"])
|
||||||
|
plt.figure(figsize=(10,10), dpi=600)
|
||||||
|
plt.plot(y)
|
||||||
|
plt.xlabel("time step")
|
||||||
|
plt.ylabel("dead agents")
|
||||||
|
if title is None:
|
||||||
|
plt.savefig("dead_agents_over_time.eps")
|
||||||
|
else:
|
||||||
|
plt.savefig(f"{title}.png")
|
||||||
|
|
||||||
|
|
||||||
|
def cum_successful_ants_vs_time(model, title=None):
|
||||||
|
y = model.datacollector.get_model_vars_dataframe()["successful_walkers"]
|
||||||
|
plt.figure(figsize=(10,10), dpi=600)
|
||||||
|
plt.plot(y)
|
||||||
|
plt.xlabel("time step")
|
||||||
|
plt.ylabel("cummulative successful agents")
|
||||||
|
if title is None:
|
||||||
|
plt.savefig("cumsum_successful_agents_over_time.eps")
|
||||||
|
else:
|
||||||
|
plt.savefig(f"{title}.png")
|
||||||
|
|
||||||
|
|
||||||
|
def plot_heatmap(model, low=10, high=200):
|
||||||
|
for time in np.arange(0, model.max_steps + 1, 1000):
|
||||||
|
pheromone_concentration = model.datacollector.get_model_vars_dataframe()["pheromone_a"][time]
|
||||||
|
a = pheromone_concentration
|
||||||
|
#plot_hexagon(a)
|
||||||
|
pheromone_concentration = model.datacollector.get_model_vars_dataframe()["pheromone_b"][time]
|
||||||
|
b = pheromone_concentration
|
||||||
|
#plot_hexagon(b)
|
||||||
|
c = np.max([a,b], axis=0)
|
||||||
|
c = a + b
|
||||||
|
c = np.clip(c, 1, 1000000000)
|
||||||
|
c = np.log(c)
|
||||||
|
c = c/np.max(c)
|
||||||
|
food_locations = np.nonzero(model.grid.fields['food'])
|
||||||
|
x_food = [ food[0] for food in food_locations ]
|
||||||
|
y_food = [ food[1] for food in food_locations ]
|
||||||
|
plot_hexagon(c, title=f"cummulative pheromone density at timestep {time}")
|
Loading…
Reference in New Issue
Block a user