Skip to content
Snippets Groups Projects
Commit 81426ab7 authored by markr's avatar markr
Browse files

Upload New File

parent ffa0b61c
Branches
No related tags found
No related merge requests found
from graphics import * # get here: http://mcsp.wartburg.edu/zelle/python/graphics.py
import time
import random
import math
import csv
# imports from our files
from help_functions import *
from classes import *
from check_boundarys import *
'''
plot is not used here, because we could not figure
out a way to close the plot and continue with the next generation
'''
# ------------------------------------------------------------------
# global varibles
# window dimensions
winWidth = 700
winHeight = 700
# set true to show visualisation/write data in csv
visual = True
writecsv = False
# names for csvs
GENERATIONS = "generations.csv"
TIMESTEPS = "timesteps.csv"
if visual:
window = GraphWin("Window", winWidth, winHeight)
else:
window = None
# max time for one generation
maxTime = 10000
# number of agents
agentNum = 80
# number of predators
predNum = agentNum//10
# number of generations
generations = 500
# food cluster variables
# soll insgesamt immer 128 ergeben
foodCluster = 16
clusterSize = 8
clusterradius = 20
# isFood turns on food simulation,
# isPred turns on predator simulation
isFood = False
isPred = True
Both = False
# timestep
t = 0.1
# values of Agents as given in the Paper
rr = 5
# area an agent can see
As = 5000 * (rr**2)
Am = 5 * (rr**2) * t
# mutation values,
# determine how fast aspects of Agents can mutate
m_zoo_r = 5/2.0
m_zoa_r = 10/2.0
m_speed = 0.1/2.0
m_food = 0.1/2.0
m_pred = 0.1/2.0
m_noise = 0.05/2.0
# ------------------------------------------------------------------
# Ackland
# returns three lists, one for each zone,
# contaning all other agent in the zone.
# ignores al agents in the angle behind the current agent defined by blind.
# the zones zor/zoo/zoa are defined by their radii zor_r/zoo_r/zoa_r
# exactly the same as in couzin, but gets more arguments,
# because they are not global here
def neigbour_in_zones(agent, agents, zor_r, zoo_r, zoa_r, blind):
zor = []
zoo = []
zoa = []
for neighbour in agents:
# find distance in x and y direction,
# and use them to calculate the angle between
# the movement-vector of agent and
# the directiction-vector between agent and neighbour
disVecX = neighbour.point.getX() - agent.point.getX()
disVecY = neighbour.point.getY() - agent.point.getY()
alpha = calc_angle(agent.x_velocity, agent.y_velocity, disVecX, disVecY)
if (agent == neighbour):
True
elif alpha < 180 - blind and alpha > 180 + blind:
True
# if neighbour can be seen:
# get distance dis between agent and neighbour,
# and check if neighbour is in a zone of agent
else:
dis = absvec(neighbour.point.getX() - agent.point.getX(), neighbour.point.getY() - agent.point.getY())
if dis <= zor_r:
zor.append(neighbour)
elif dis <= zoo_r:
zoo.append(neighbour)
elif dis <= zoa_r:
zoa.append(neighbour)
return [zor, zoo, zoa]
# update Velocity a la couzin
# exactly the same as in couzin, but noise is
# not global and attributes are named differently
# for some reason...
def updateV_couzin(agent, zones):
dx = 0
dy = 0
#zor not empty
if zones[0] != []:
for neighbour in zones[0]:
disX = neighbour.point.getX() - agent.point.getX()
disY = neighbour.point.getY() - agent.point.getY()
rX = disX / absvec(disX, disY)
rY = disY / absvec(disX, disY)
dx += rX / absvec(rX, rY)
dy += rY / absvec(rX, rY)
dx = -dx
dy = -dy
# zoo not empty; zoa empty
elif zones[1] != [] and zones[2] == []:
for neighbour in zones[1]:
dx += neighbour.x_velocity / absvec(neighbour.x_velocity, neighbour.y_velocity)
dy += neighbour.y_velocity / absvec(neighbour.x_velocity, neighbour.y_velocity)
dx += agent.x_velocity / absvec(agent.x_velocity, agent.y_velocity)
dy += agent.y_velocity / absvec(agent.x_velocity, agent.y_velocity)
# zoo empty; zoa not empty
elif zones[1] == [] and zones[2] != []:
for neighbour in zones[2]:
disX = neighbour.point.getX() - agent.point.getX()
disY = neighbour.point.getY() - agent.point.getY()
rX = disX / absvec(disX, disY)
rY = disY / absvec(disX, disY)
dx += rX / absvec(rX, rY)
dy += rY / absvec(rX, rY)
# zoo and zoa not empty
elif zones[1] != [] and zones[2] != []:
for neighbour in zones[1]:
dx += neighbour.x_velocity / absvec(neighbour.x_velocity, neighbour.y_velocity)
dy += neighbour.y_velocity / absvec(neighbour.x_velocity, neighbour.y_velocity)
dx += agent.x_velocity / absvec(agent.x_velocity, agent.y_velocity)
dy += agent.y_velocity / absvec(agent.x_velocity, agent.y_velocity)
for neighbour in zones[2]:
disX = neighbour.point.getX() - agent.point.getX()
disY = neighbour.point.getY() - agent.point.getY()
rX = disX / absvec(disX, disY)
rY = disY / absvec(disX, disY)
dx += rX / absvec(rX, rY)
dy += rY / absvec(rX, rY)
dx = 0.5*dx
dy = 0.5*dy
# all zones empty
else:
dx = agent.x_velocity
dy = agent.y_velocity
# randomness factor / error
dx += random.uniform(-agent.noise/2, agent.noise/2)
dy += random.uniform(-agent.noise/2, agent.noise/2)
return [dx, dy]
# checks if neares food is in zor, if yes, eat it
# else checks if neares food is in zoa,
# and returns vector pointing in it´s direction
def check_food(agent, foods):
dX = 0
dY = 0
if foods == []:
return [dX,dY]
nearestFood = nearest_neighbour(agent, foods)
dis = distance(agent.point.getX(), nearestFood.point.getX(), agent.point.getY(), nearestFood.point.getY())
if dis <= agent.zor_r:
if visual:
nearestFood.point.undraw()
foods.remove(nearestFood)
agent.foodLevel += 1
elif dis <= agent.zoa_r:
disX = nearestFood.point.getX() - agent.point.getX()
disY = nearestFood.point.getY() - agent.point.getY()
rX = disX / absvec(disX, disY)
rY = disY / absvec(disX, disY)
dX = rX / absvec(rX, rY)
dY = rY / absvec(rX, rY)
return [dX, dY]
# else checks if neares predator is in zoa,
# and returns vector pointing in it´s direction
def check_predator(agent, predators):
dX=0
dY=0
if predators == []:
return [dX,dY]
nearestPred = nearest_neighbour(agent, predators)
dis = distance(agent.point.getX(), nearestPred.point.getX(), agent.point.getY(), nearestPred.point.getY())
if dis <= agent.zoa_r:
disX = nearestPred.point.getX() - agent.point.getX()
disY = nearestPred.point.getY() - agent.point.getY()
rX = disX / absvec(disX, disY)
rY = disY / absvec(disX, disY)
dX = rX / absvec(rX, rY)
dY = rY / absvec(rX, rY)
return [dX, dY]
# checks if neares prey is in zor, if yes, eat it
# else checks if neares prey is in zoa,
# and returns vector pointing in it´s direction
def check_prey(predator, agents):
dX = predator.x_velocity
dY = predator.y_velocity
if agents == []:
return [dX,dY]
nearestPrey = nearest_neighbour(predator, agents)
dis = distance(predator.point.getX(), nearestPrey.point.getX(), predator.point.getY(), nearestPrey.point.getY())
if dis <= predator.zor_r:
if visual:
nearestPrey.point.undraw()
nearestPrey.line.undraw()
agents.remove(nearestPrey)
predator.hasEaten = True
elif dis <= predator.zoa_r:
disX = nearestPrey.point.getX() - predator.point.getX()
disY = nearestPrey.point.getY() - predator.point.getY()
rX = disX / absvec(disX, disY)
rY = disY / absvec(disX, disY)
dX = rX / absvec(rX, rY)
dY = rY / absvec(rX, rY)
return [dX, dY]
# return new velocity, taking food and predators into acount
def updateV_final(agent, matrix, foods, predators):
vc = updateV_couzin(agent, matrix)
vf = check_food(agent, foods)
vp = check_predator(agent, predators)
vvX = vc[0] + agent.food_pref * vf[0] - agent.anti_pred * vp[0]
vvY = vc[1] + agent.food_pref * vf[1] - agent.anti_pred * vp[1]
return [vvX, vvY]
# ------------------------------------------------------------------
# update functions
#update agents
def update_couzin(agents, foods, predators, winWidth, winHeight, window):
# Velocity update
for agent in agents:
neigh_matrix = neigbour_in_zones(agent, agents, agent.zor_r, agent.zoo_r, agent.zoa_r, agent.blind_angle,)
agent.tempvelocity = updateV_final(agent, neigh_matrix, foods, predators)
# move, draw
for agent in agents:
# test if in ragne of agent.turn_angle, if not rotate angle by maxTurn in
# direction of new direction
radTurn = math.radians(agent.turn_angle)
negRadTurn = math.radians(360-agent.turn_angle)
# check if rotation is in range of turn-angle
agent = move_agent_couzin(agent, agent.turn_angle, radTurn, negRadTurn)
# normalise direction vector to 1, and multiply by constant speed
x = agent.x_velocity/absvec(agent.x_velocity, agent.y_velocity) * agent.speed
agent.y_velocity = agent.y_velocity/absvec(agent.x_velocity, agent.y_velocity) * agent.speed
agent.x_velocity = x
agent = checkBoundary(agent, winWidth, winHeight)
# draw agent
if visual:
agent.drawLine()
return agents
#update predator
def update_predator(predator, agents, winWidth, winHeight, window):
predator.tempvelocity = check_prey(predator, agents)
radTurn = math.radians(predator.turn_angle)
negRadTurn = math.radians(360-predator.turn_angle)
# check if rotation is in range of turn-angle
predator = move_agent_couzin(predator, predator.turn_angle, radTurn, negRadTurn)
# normalise diection vector to 1, and multiply by constant speed
x = predator.x_velocity/absvec(predator.x_velocity, predator.y_velocity) * predator.speed
predator.y_velocity = predator.y_velocity/absvec(predator.x_velocity, predator.y_velocity) * predator.speed
predator.x_velocity = x
predator = checkBoundary(predator, winWidth, winHeight)
# draw predator
if visual:
predator.drawLine()
return predator
# ------------------------------------------------------------------
# next gen functions
# mutate agent in order to get a child
def mutate(parent):
point = Point(random.uniform(0,winWidth/2), random.uniform(0,winHeight/2))
child = AcklandAgent(point, window)
# give them a random starting direction
child.x_velocity = random.uniform(-1, 1)
child.y_velocity = random.uniform(-1, 1)
child.zoa_r = random.uniform(parent.zoa_r - m_zoa_r, parent.zoa_r + m_zoa_r )
child.zoa_r = max (child.zoa_r, math.sqrt(As/(2*math.pi)) )
child.zoo_r = random.uniform(parent.zoo_r - m_zoo_r, parent.zoo_r + m_zoo_r)
child.zoo_r = min( child.zoa_r ,max(child.zoo_r, child.zor_r))
child.speed = random.uniform(parent.speed - m_speed, parent.speed + m_speed)
child.speed = min( 5 ,max(child.speed, 1))
child.blind_angle = (360 - math.degrees(As/(child.zoa_r**2)) ) / 2
child.turn_angle = math.degrees(Am/(2*(child.speed**2)))
child.food_pref = random.uniform(parent.food_pref - m_food, parent.food_pref + m_food)
child.anti_pred = random.uniform(parent.anti_pred - m_pred, parent.anti_pred + m_pred)
child.noise = random.uniform(parent.noise - m_noise, parent.noise + m_noise)
return child
# --------------------------------------------------------------
# get next generation food simulation
# generate a "wheel of fortune"
# depending on foodLevel of agent:
# has eaten more <->
# higher probability to get picked as parent
def generateWheel(agents):
wheel = []
currentsum = 0
for agent in agents:
currentsum += agent.foodLevel
wheel.append(currentsum)
return wheel
# use wheel to pick an agent to mutate
# in order to get a child
def pickParent(agents, wheel):
r = random.randrange(wheel[-1]) +1
for i in range(len(wheel)):
if r <= wheel[i]:
return agents[i]
# generate next Generation of agents for the food simulation
def nextGen_food(agents):
wheel = generateWheel(agents)
tempAgents = []
for i in range(agentNum):
if wheel[-1] == 0:
parent = pickParent_simple_random(agents)
else:
parent = pickParent(agents, wheel)
child = mutate(parent)
tempAgents.append(child)
return tempAgents
# --------------------------------------------------------------
# get next generation predator simulation
# just pick one of those that survived randomly as parent
def pickParent_simple_random(agents):
r = random.randrange(len(agents))
return agents[r]
# generate next Generation of agents for the predator simulation
def nextGen_pred(agents):
tempAgents = []
for i in range(agentNum):
parent = pickParent_simple_random(agents)
child = mutate(parent)
tempAgents.append(child)
return tempAgents
# --------------------------------------------------------------
# main
def main():
agents = []
foods = []
predators = []
# open csv to collect data
if writecsv:
with open(GENERATIONS,'w') as csvfile:
filewriter = csv.writer(csvfile, delimiter=',',quotechar='|',quoting = csv.QUOTE_MINIMAL)
filewriter.writerow(["Iterations","Speed","turn","food pref","zoa","zoo","blind","noise","antipred"])
with open(TIMESTEPS,'w') as csvfile:
filewriter = csv.writer(csvfile, delimiter=',',quotechar='|',quoting = csv.QUOTE_MINIMAL)
filewriter.writerow(["Generations","Timestep","x","y","x_velocity","y_velocity","foodlevel"])
widthTemp = winWidth
heightTemp = winHeight
maxLife = 1000
global window
# first generation , random
for i in range (agentNum):
agent = AcklandAgent(Point(random.uniform(0,winWidth/2), random.uniform(0,winHeight/2)) , window)
agents.append(agent.create_random_agent(rr, As, Am))
for j in range(generations):
if isPred or Both:
for i in range(predNum):
predator = Predator(Point(random.uniform(0,winWidth), random.uniform(0,winHeight)) , window)
predators.append(predator.create_random_predator(rr, As))
# -----ausgabe------
print ("generation " + str(j))
avgSpeed = 0
avgTurn = 0
avgFood = 0
avgPred = 0
avgZOA = 0
avgZOO = 0
avgBlind = 0
avgNoise = 0
maxSpeed = 0
maxTurnAngle = 0
for agent in agents:
avgSpeed += agent.speed
avgPred += agent.anti_pred
avgTurn += agent.turn_angle
avgFood += agent.food_pref
avgZOA += agent.zoa_r
avgZOO += agent.zoo_r
avgBlind += agent.blind_angle
avgNoise += agent.noise
if agent.speed > maxSpeed:
maxSpeed = agent.speed
if agent.turn_angle > maxTurnAngle:
maxTurnAngle = agent.turn_angle
avgSpeed /= agentNum
avgTurn /= agentNum
avgFood /= agentNum
avgZOA /= agentNum
avgZOO /= agentNum
avgBlind /= agentNum
avgNoise /= agentNum
avgPred /= agentNum
if writecsv:
for agent in agents:
with open(GENERATIONS,'a') as csvfile:
filewriter = csv.writer(csvfile, delimiter=',',quotechar='|',quoting = csv.QUOTE_MINIMAL)
filewriter.writerow([j, agent.speed, agent.turn_angle, agent.food_pref, agent.zoa_r, agent.zoo_r, agent.blind_angle, agent.noise, agent.anti_pred])
# -----ausgabe ende------
if isFood or Both:
widthTemp = winWidth/2
heightTemp = winHeight/2
else:
widthTemp = winWidth
heightTemp = winHeight
# main loop
for timeStep in range(maxTime):
# every 50 timesteps collect data
if timeStep % 50 == 0 and j % 50 == 0 and writecsv:
for agent in agents:
with open(TIMESTEPS,'a') as csvfile:
filewriter = csv.writer(csvfile, delimiter=',',quotechar='|',quoting = csv.QUOTE_MINIMAL)
filewriter.writerow([j,timeStep,agent.point.getX(),agent.point.getY(),agent.x_velocity,agent.y_velocity,agent.foodLevel])
# generate food and release agents at 1/4 of maxtime
if timeStep == maxTime * 0.025 and (isFood or Both):
foods = []
for j in range (foodCluster):
x = random.uniform(widthTemp + clusterradius, winWidth-clusterradius)
y = random.uniform(heightTemp + clusterradius, winHeight- clusterradius)
for k in range (clusterSize):
xk = random.uniform(x - clusterradius, x + clusterradius)
yk = random.uniform(y - clusterradius, y + clusterradius)
f = Food(Point(xk, yk))
if visual:
f.point.setFill("blue")
f.point.draw(window)
foods.append(f)
widthTemp = winWidth
heightTemp = winHeight
# exit generation if enough food has been eaten
if timeStep >= maxTime * 0.025 and isFood:
if len(foods) <= 1.0/8 * clusterSize * foodCluster:
break
# start predating / update predators
if timeStep >= maxTime * 0.025 and (isPred or Both):
if predators == []:
break
else:
# delete current predator if it has eaten
if(predators[-1].hasEaten or predators[-1].lifeTime >= maxLife):
if visual:
predators[-1].line.undraw()
predators.pop()
else:
predators[-1] = update_predator(predators[-1], agents, winWidth, winHeight, window)
predators[-1].lifeTime += 1
# update agents
agents = update_couzin(agents, foods, predators, widthTemp, heightTemp, window)
print ("eating time: " + str(timeStep))
# new windos and new generation
if visual:
window.close()
window = GraphWin("Window", winWidth, winHeight)
if isFood or Both:
agents = nextGen_food(agents)
elif isPred:
agents = nextGen_pred(agents)
main()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment