update plotting functions

This commit is contained in:
Alexander Bocken 2023-06-29 17:16:31 +02:00
parent ee6ab086d8
commit db1d59843b
Signed by: Alexander
GPG Key ID: 1D237BE83F9B05E8
5 changed files with 139 additions and 64 deletions

View File

@ -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()

View File

@ -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
View File

@ -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()

View File

@ -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
View 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}")