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
|
||||
print("RECRUITING")
|
||||
for agent_id in self.model.get_unique_ids(self.model.N_r):
|
||||
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")
|
||||
@ -219,8 +220,8 @@ class RandomWalkerAnt(Agent):
|
||||
if self.energy < self.model.e_min:
|
||||
self.model.schedule.remove(self)
|
||||
#update list of dead agents for time step
|
||||
self.model.dead_agents[self.model.schedule.steps-1] += 1
|
||||
|
||||
self.model.dying_agents += 1
|
||||
|
||||
else:
|
||||
self._choose_next_pos()
|
||||
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
|
||||
|
||||
fig, ax = plt.subplots()
|
||||
fig.set_figwidth(10)
|
||||
fig.set_figheight(10)
|
||||
fig.set_dpi(600)
|
||||
im = ax.hexbin(
|
||||
X.reshape(-1),
|
||||
Y.reshape(-1),
|
||||
@ -24,8 +27,11 @@ def plot_hexagon(A, title=None, block=True):
|
||||
ax.set_aspect(1)
|
||||
ax.set(xlim=(-4, X.max()+4,), ylim=(-4, Y.max()+4))
|
||||
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):
|
||||
plt.title(title)
|
||||
plt.show(block=block)
|
||||
pass
|
||||
#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
|
||||
|
||||
|
||||
def plot_heatmap():
|
||||
from hexplot import plot_hexagon
|
||||
def run_model():
|
||||
from tqdm import tqdm
|
||||
# nests rather far away but also partially clumped.
|
||||
np.random.seed(6)
|
||||
|
||||
from model import kwargs_paper_setup1 as kwargs
|
||||
kwargs["gamma"] /= 3 # field decays slower
|
||||
kwargs["beta"] /= 3 # drop rates decays slower
|
||||
kwargs["d_e"] /= 3 # live longer, search longer
|
||||
kwargs["d_s"] /= 3 # live longer, search longer
|
||||
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
|
||||
|
||||
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
|
||||
plot_hexagon(a, title="food locations", block=False)
|
||||
for _ in tqdm(range(model.max_steps)):
|
||||
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__":
|
||||
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")
|
||||
#res = fixed_distance_tests()
|
||||
#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.successful_ants = 0 # for viviane's graph
|
||||
self.connectivity = 0 # for viviane's persistence
|
||||
self.dying_agents = 0
|
||||
|
||||
fields=["A", "B", "nests", "food", "res"]
|
||||
self.schedule = SimultaneousActivation(self)
|
||||
@ -129,8 +130,6 @@ class ActiveWalkerModel(Model):
|
||||
self.max_steps = max_steps
|
||||
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):
|
||||
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"],
|
||||
"pheromone_b": lambda m: m.grid.fields["B"],
|
||||
"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,
|
||||
},
|
||||
agent_reporters={}
|
||||
@ -154,10 +154,8 @@ class ActiveWalkerModel(Model):
|
||||
self.datacollector.collect(self) # keep at end of __init___
|
||||
|
||||
# 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):
|
||||
threshold = 0.0000001 #the value of A
|
||||
threshold = 0.5 # half of min sens
|
||||
connectivity = 0 #initial value of connectivity
|
||||
connected_food_sources = [] #empty list of connected food sources
|
||||
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
|
||||
|
||||
# why not normalize to 0-1 ?
|
||||
print(f"{connectivity=}")
|
||||
return connectivity #we want the connectivity (0-5)
|
||||
|
||||
def agent_density(self):
|
||||
@ -198,9 +195,11 @@ class ActiveWalkerModel(Model):
|
||||
|
||||
|
||||
def step(self):
|
||||
self.dying_agents = 0
|
||||
self.schedule.step() # step() and advance() all agents
|
||||
|
||||
if self.schedule.steps % 100 == 0:
|
||||
self.connectivity = self.bfs()
|
||||
pass
|
||||
|
||||
# apply decay rate on pheromone levels
|
||||
for key in ("A", "B"):
|
||||
@ -209,12 +208,8 @@ class ActiveWalkerModel(Model):
|
||||
|
||||
|
||||
self.datacollector.collect(self)
|
||||
self.alive_agents[self.schedule.steps-1] = len(self.schedule.agents)
|
||||
|
||||
|
||||
if self.schedule.steps >= self.max_steps:
|
||||
self.plot_alive_agents()
|
||||
self.plot_aliveDead_agents()
|
||||
self.running = False
|
||||
|
||||
def get_unique_id(self) -> int:
|
||||
@ -225,35 +220,7 @@ class ActiveWalkerModel(Model):
|
||||
for _ in range(num_ids):
|
||||
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.
|
||||
|
||||
|
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