Skip to content
This repository was archived by the owner on Oct 25, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 54 additions & 27 deletions week09/improvement/boids.py
Original file line number Diff line number Diff line change
@@ -1,44 +1,71 @@
"""
A deliberately bad implementation of
An improved implementation of
[Boids](http://dl.acm.org/citation.cfm?doid=37401.37406)
for use as an exercise on refactoring.

This code simulates the swarming behaviour of bird-like objects ("boids").
"""

from matplotlib import pyplot as plt
from matplotlib import animation
Aspects of boid motion simulated:
1. Boids want to fly towards centre of flock
2. Boids want to fly away from nearby boids
3. Boids want to have similar velocity to nearby boids
"""

# import random for definining boids' initial states
import random

boids_x=[random.uniform(-450,50.0) for x in range(50)]
boids_y=[random.uniform(300.0,600.0) for x in range(50)]
boid_x_velocities=[random.uniform(0,10.0) for x in range(50)]
boid_y_velocities=[random.uniform(-20.0,20.0) for x in range(50)]
boids=(boids_x,boids_y,boid_x_velocities,boid_y_velocities)
# set number of boids
num_boids = 50
xmin = -450
xmax = 50
ymin = 60
ymax = 300
xvmin = 0
xvmax = 10
yvmin = -20
yvmax = 20

# create boids within function using user-defined values
def create_boids(num_boids,xmin,xmax,ymin,ymax,xvmin,xvmax,yvmin,yvmax):
# produce list of each variable
boids_x=[random.uniform(xmin,xmax) for x in range(num_boids)]
boids_y=[random.uniform(ymin,ymax) for x in range(num_boids)]
boid_x_velocities=[random.uniform(xvmin,xvmax) for x in range(num_boids)]
boid_y_velocities=[random.uniform(yxmin,yvmax) for x in range(num_boids)]
# produce tuple of variable lists
boids=(boids_x,boids_y,boid_x_velocities,boid_y_velocities)
return boids

def update_boids(boids):
boids = create_boids(num_boids,xmin,xmax,ymin,ymax,xvmin,xvmax,yvmin,yvmax)

# define variables for updating
centre_scale = 0.01
local_vel_scale = 0.125
repel_thresh = 100
local_vel_thresh = 10000

def update_boids(boids, centre_scale, local_vel_scale, repel_thresh, local_vel_thresh):
# define positions and velocities of boids
# xs - list of boid x positions
# ys - list of boid y positions
# xvs - list of boid x velocities
# yvs - list of boid y velocities
xs,ys,xvs,yvs=boids
# Fly towards the middle
for i in range(len(xs)):
for j in range(len(xs)):
xvs[i]=xvs[i]+(xs[j]-xs[i])*0.01/len(xs)
for i in range(len(xs)):
for j in range(len(xs)):
yvs[i]=yvs[i]+(ys[j]-ys[i])*0.01/len(xs)
# Fly away from nearby boids
# simulate different aspects of boid motion
for i in range(len(xs)):
# iterate over all other boids to define interactions
for j in range(len(xs)):
if (xs[j]-xs[i])**2 + (ys[j]-ys[i])**2 < 100:
# Fly towards the middle (1)
xvs[i]=xvs[i]+(xs[j]-xs[i])*centre_scale/len(xs)
yvs[i]=yvs[i]+(ys[j]-ys[i])*centre_scale/len(xs)
# Fly away from nearby boids (2)
if (xs[j]-xs[i])**2 + (ys[j]-ys[i])**2 < repel_thresh:
xvs[i]=xvs[i]+(xs[i]-xs[j])
yvs[i]=yvs[i]+(ys[i]-ys[j])
# Try to match speed with nearby boids
for i in range(len(xs)):
for j in range(len(xs)):
if (xs[j]-xs[i])**2 + (ys[j]-ys[i])**2 < 10000:
xvs[i]=xvs[i]+(xvs[j]-xvs[i])*0.125/len(xs)
yvs[i]=yvs[i]+(yvs[j]-yvs[i])*0.125/len(xs)
# Move according to velocities
for i in range(len(xs)):
# Try to match speed with nearby boids (3)
if (xs[j]-xs[i])**2 + (ys[j]-ys[i])**2 < local_vel_thresh:
xvs[i]=xvs[i]+(xvs[j]-xvs[i])*local_vel_scale/len(xs)
yvs[i]=yvs[i]+(yvs[j]-yvs[i])*local_vel_scale/len(xs)
# Move according to velocities
xs[i]=xs[i]+xvs[i]
ys[i]=ys[i]+yvs[i]
23 changes: 11 additions & 12 deletions week09/refactoring/initial_global.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
def average_age():
def average_age(group):
"""Compute the average age of the group's members."""
all_ages = [person["age"] for person in group.values()]
return sum(all_ages) / len(group)


def forget(person1, person2):
def forget(group, person1, person2):
"""Remove the connection between two people."""
group[person1]["relations"].pop(person2, None)
group[person2]["relations"].pop(person1, None)


def add_person(name, age, job, relations):
def add_person(group, name, age, job, relations):
"""Add a new person with the given characteristics to the group."""
new_person = {
"age": age,
Expand All @@ -19,8 +19,8 @@ def add_person(name, age, job, relations):
}
group[name] = new_person


group = {
if __name__ == "__main__":
group = {
"Jill": {
"age": 26,
"job": "biologist",
Expand All @@ -43,19 +43,18 @@ def add_person(name, age, job, relations):
"Jill": "partner"
}
}
}
}

nash_relations = {
nash_relations = {
"John": "cousin",
"Zalika": "landlord"
}
}

add_person("Nash", 34, "chef", nash_relations)
add_person(group, "Nash", 34, "chef", nash_relations)

forget("Nash", "John")
forget(group, "Nash", "John")

if __name__ == "__main__":
assert len(group) == 4, "Group should have 4 members"
assert average_age() == 28.75, "Average age of the group is incorrect!"
assert average_age(group) == 28.75, "Average age of the group is incorrect!"
assert len(group["Nash"]["relations"]) == 1, "Nash should only have one relation"
print("All assertions have passed!")