<jupyter_start><jupyter_text>Imports used<jupyter_code>import random
import numpy as np
import matplotlib.pyplot as plt

import agentframework as af<jupyter_output><empty_output><jupyter_text>1. Agent-Based Modelling<jupyter_code>random.seed(10)

y0, x0 = 50, 50 # y then x because of reading image files
#print('Initial: ',x0,y0)

def perturb(x):
    return x + random.choice([-1,1])

for _ in range(2):
    x0, y0 = perturb(x0), perturb(y0)
#print('Perturbed: ',x0, y0)

y1, x1 = 50, 50
for _ in range(2):
    x1, y1 = perturb(x1), perturb(y1)

def distance(x0,y0,x1,y1):
    return np.sqrt((x1-x0)**2 + (y1-y0)**2)

d= distance(x0,y0,x1,y1)
print("Distance: ",d)

# randomise starting values, use this as the start. 0 to 99 since randint is inclusive of end point.
x0, y0 = random.randint(0,99),random.randint(0,99)<jupyter_output>Distance:  2.0<jupyter_text>2. Code Shrinking I<jupyter_code>agents = []
random.seed(10)
for _ in range(2):
    agents.append([random.randint(0,99),random.randint(0,99)])
agents
print('Normal: ',max(agents))

import operator
print('itemgetter: ',max(agents,key=operator.itemgetter(1)))

# or use custom:
def second(l):
    return l[1]
print('Custom key: ',max(agents,key=second))
plt.ylim(0, 99)
plt.xlim(0, 99)
plt.scatter(agents[0][0],agents[0][1])
plt.scatter(agents[1][0],agents[1][1])
plt.title("Plot each point separately")
plt.show()

# alternative plotting method using numpy slicing
np_agents = np.array(agents)
plt.ylim(0, 99)
plt.xlim(0, 99)
plt.scatter(np_agents[:,0],np_agents[:,1],c=['blue','orange'])
plt.title('Plot using x and y coordinate lists')
plt.show()<jupyter_output><empty_output><jupyter_text>3. Code Skrinking II<jupyter_code>random.seed(100)

#### INITIALISE

num_of_agents = 10
agents = []
for _ in range(num_of_agents):
    agents.append([random.randint(0,100),random.randint(0,100)])

#### UPDATE POSITIONS

agents_new = agents.copy()
for i in range(len(agents)):
    x,y = agents[i]
    for _ in range(2):
        x, y = perturb(x), perturb(y)
    # update agent coordinates
    agents_new[i] = [x,y]

#### PLOT 

# plot initial positions
np_agents = np.array(agents)
plt.scatter(np_agents[:,0],np_agents[:,1],c='teal',label='Initial')
# plot final positions
np_agents_new = np.array(agents_new)
plt.scatter(np_agents_new[:,0],np_agents_new[:,1],c='orange',label='Final')

plt.title('Initial and final positions of agents')
plt.ylim(0, 100)
plt.xlim(0, 100)
plt.legend()
plt.show()<jupyter_output><empty_output><jupyter_text>Dealing with boundries...<jupyter_code>def perturb_new(x): 
    return (x + random.choice([-1,1])) % 100
random.seed(100)

#### INITIALISE

num_of_agents = 10
agents = []
for _ in range(num_of_agents):
    agents.append([random.randint(0,100),random.randint(0,100)])

#### UPDATE POSITIONS

agents_new = agents.copy()
for i in range(len(agents)):
    x,y = agents[i]
    for _ in range(10):
        x, y = perturb_new(x), perturb_new(y)
    # update agent coordinates
    agents_new[i] = [x,y]

#### PLOT 

# plot initial positions
np_agents = np.array(agents)
plt.scatter(np_agents[:,0],np_agents[:,1],c='teal',label='Initial')
# plot final positions
np_agents_new = np.array(agents_new)
plt.scatter(np_agents_new[:,0],np_agents_new[:,1],c='orange',label='Final')

plt.title('Torus plane - Initial and final positions of agents')
plt.ylim(0, 100)
plt.xlim(0, 100)
plt.legend()
plt.show()<jupyter_output><empty_output><jupyter_text>4. Building Tools<jupyter_code># import time
# start = time.clock()
# # The code to run, here.
# end = time.clock()
# print("time = " + str(end - start))
def distance_between(agents_row_a, agents_row_b):
    return np.sqrt(
        ((agents_row_a[0] - agents_row_b[0])**2) 
        + ((agents_row_a[1] - agents_row_b[1])**2))
dists = []
for i in range(num_of_agents):
    agent_a = agents_new[i]
    for j in range(num_of_agents):
        # 2. Don't check against itself
        if i != j:
            agent_b = agents_new[j]
            dists.append(distance_between(agent_a,agent_b))
print('Min: ',round(min(dists),2),' Max: ',round(max(dists),2))
plt.hist(dists,bins=20)
plt.title('Histogram of distances between agents')
plt.show()<jupyter_output>Min:  1.0  Max:  93.74<jupyter_text>Do the above for different number of agents:<jupyter_code>def run_sim(num_of_agents,num_runs,plot=False):
    
    random.seed(100)
    
    #### INITIALISE
    agents = []
    for _ in range(num_of_agents):
        agents.append([random.randint(0,100),random.randint(0,100)])

    #### UPDATE POSITIONS

    agents_new = agents.copy()
    for i in range(len(agents)):
        x,y = agents[i]
        for _ in range(num_runs):
            x, y = perturb_new(x), perturb_new(y)
        # update agent coordinates
        agents_new[i] = [x,y]
    
    if plot:
        #### PLOT 

        # plot initial positions
        np_agents = np.array(agents)
        plt.scatter(np_agents[:,0],np_agents[:,1],c='teal')
        # plot final positions
        np_agents_new = np.array(agents_new)
        plt.scatter(np_agents_new[:,0],np_agents_new[:,1],c='orange')

        plt.ylim(0, 100)
        plt.xlim(0, 100)
        plt.show()
    
    dists = []
    for i in range(num_of_agents):
        agent_a = agents_new[i]
        for j in range(num_of_agents):
            # 2. Don't check against itself
            if i != j:
                agent_b = agents_new[j]
                dists.append(distance_between(agent_a,agent_b))
    
    return dists
# test
dists = run_sim(10,100,True)
# Time it...
import time
times = []
Ns_to_test = list(range(1,800,50))

for n in Ns_to_test:
    start = time.perf_counter() # .perf_counter() since .clock() is deprecated in Python 3.3
    _ = run_sim(n,100)
    end = time.perf_counter()
    times.append(end - start)
plt.scatter(Ns_to_test,times)
plt.title('Time taken to run simulations')
plt.ylabel('Time Taken [s]')
plt.xlabel('Number of Agents')
plt.show()<jupyter_output><empty_output><jupyter_text>5. Agents!<jupyter_code># Write separate file to describe agent class and import it here
# USES RANDOM Integer between 0 and 300 (as required for final exercise).
import agentframework as af 

def distance_between(agents_row_a, agents_row_b):
    return np.sqrt(
        ((agents_row_a[0] - agents_row_b[0])**2) 
        + ((agents_row_a[1] - agents_row_b[1])**2))
# USES RANDOM INT from 0 to 300 (as required for final exercise)
agent_1 = af.Agent([],[]) # [],[] for backward compatibility of agentframework: expects environment, list_of_agents
print(agent_1.get_x(), agent_1.get_y())
agent_1.set_x(10)
agent_1.set_y(10)
print(agent_1.get_x(), agent_1.get_y())
agent_1.move(optimised=False)
print(agent_1.get_x(), agent_1.get_y())<jupyter_output>9 11<jupyter_text>Testing (from Lectures)<jupyter_code>def distance_between(agents_row_a, agents_row_b):
    return (((agents_row_a.get_x() - agents_row_b.get_x())**2) +
    ((agents_row_a.get_y() - agents_row_b.get_y())**2))**0.5

num_of_agents = 10
num_of_iterations = 100
agents = []

# Make the agents
for i in range(num_of_agents):
    agents.append(af.Agent([],[]))

# Move the agents
for j in range(num_of_iterations):
    for i in range(num_of_agents):
        agents[i].move(optimised=False)

plt.xlim(0, 300)
plt.ylim(0, 300)
for i in range(num_of_agents):
    plt.scatter(agents[i].get_x(),agents[i].get_y())
plt.show()

for agents_row_a in agents:
    for agents_row_b in agents:
        distance = distance_between(agents_row_a, agents_row_b)<jupyter_output><empty_output><jupyter_text>Testing (personal)<jupyter_code>random.seed(100)

#### INITIALISE

num_of_agents = 10
agents = []
for _ in range(num_of_agents):
    agents.append(af.Agent([],[])) # [],[] for backward compatibility of agentframework 

# plot initial positions
np_agents = np.array([[agent.get_x(),agent.get_y()] for agent in agents])
plt.scatter(np_agents[:,0],np_agents[:,1],c='teal',label='Initial')

#### UPDATE POSITIONS
steps = 10
for step in range(steps):
    for i in range(len(agents)):
        agents[i].move(optimised=False)

# plot final positions
np_agents_new = np.array([[agent.get_x(),agent.get_y()] for agent in agents])
plt.scatter(np_agents_new[:,0],np_agents_new[:,1],c='orange',label='Final')

plt.title('Torus plane - Initial and final positions of agents')
plt.ylim(0, 300)
plt.xlim(0, 300)
plt.legend()
plt.show()<jupyter_output><empty_output><jupyter_text>6. I/O<jupyter_code>environment = []

with open('data/in.txt') as f:
    for line in f:
        parsed_line = line.split(',')
        rowlist = []
        for value in parsed_line:
            rowlist.append(int(value))
            
        environment.append(rowlist)
        
plt.imshow(environment)
#plt.axis('off')
plt.show()<jupyter_output><empty_output><jupyter_text>Eating...<jupyter_code>random.seed(100)

#### INITIALISE

# import environment
environment = []
with open('data/in.txt') as f:
    for line in f:
        parsed_line = line.split(',')
        rowlist = []
        for value in parsed_line:
            rowlist.append(int(value))
        environment.append(rowlist)

# create agents
num_of_agents = 10
agents = []
for _ in range(num_of_agents):
    agents.append(af.Agent(environment,agents))

# plot initial positions
np_agents = np.array([[agent.get_x(),agent.get_y()] for agent in agents])
plt.scatter(np_agents[:,0],np_agents[:,1],c='white',label='Initial')
plt.imshow(environment, cmap='YlGn', vmin=0, vmax=250)
plt.title('Initial')
plt.show()

#### MOVE AND EAT

num_steps = 200
for _ in range(num_steps):
    for i in range(len(agents)):
        agents[i].move(optimised=False)
        agents[i].eat()

# plot final positions
np_agents_new = np.array([[agent.get_x(),agent.get_y()] for agent in agents])
plt.scatter(np_agents_new[:,0],np_agents_new[:,1],c='white',label='Final')
plt.imshow(environment, cmap='YlGn', vmin=0, vmax=250)

plt.title('Final')
plt.show()<jupyter_output><empty_output><jupyter_text>Extras<jupyter_code># write out environment file
import pandas as pd
pd.DataFrame(environment).to_csv('data/in_final.txt')

# write stores
stores = [agent.get_store() for agent in agents]
pd.Series(stores).to_csv('data/stores.txt')

# eat what's left: done in agentframework.py file

# sick up 50 if eaten 100, in agentframework.py file<jupyter_output><empty_output><jupyter_text>7. Communicating<jupyter_code>random.seed(100)

# global variables

num_of_agents = 10
num_steps = 200
neighbourhood = 20 # NEW

#### INITIALISE

environment = []
with open('data/in.txt') as f:
    for line in f:
        parsed_line = line.split(',')
        rowlist = []
        for value in parsed_line:
            rowlist.append(int(value))
        environment.append(rowlist)
        
        
agents = []
for _ in range(num_of_agents):
    agents.append(af.Agent(environment,agents)) 
    # the agents list will update, and since only a link is given to the agents,
    # everyone will get a full list

# TEST each agent has list of others
# print(agents[0].agents[6].get_x(),agents[0].agents[6].get_y())
# print(agents[6].get_x(),agents[6].get_y())
# agents[0].share_with_neighbours(neighbourhood)

# plot initial positions
np_agents = np.array([[agent.get_x(),agent.get_y()] for agent in agents])
plt.scatter(np_agents[:,0],np_agents[:,1],c='white',label='Initial')
plt.imshow(environment)
# plt.ylim(0, 100)
# plt.xlim(0, 100)
plt.title('Initial')
plt.show()


### MOVE AND EAT

for _ in range(num_steps):
    
    random.shuffle(agents) # shuffle agents before each iteration
    for i in range(len(agents)):
        agents[i].move(optimised=False)
        agents[i].eat()
        agents[i].share_with_neighbours(neighbourhood)

# plot final positions
np_agents_new = np.array([[agent.get_x(),agent.get_y()] for agent in agents])
plt.scatter(np_agents_new[:,0],np_agents_new[:,1],c='white',label='Final')
plt.imshow(environment)

plt.title('Final')
plt.show()<jupyter_output><empty_output><jupyter_text>8. AnimationSome modification of the given "animatedmodel2.py" file.<jupyter_code>import matplotlib.animation 
%matplotlib qt
num_of_agents = 10
num_of_iterations = 100
agents = []

fig = plt.figure(figsize=(7, 7))
ax = fig.add_axes([0, 0, 1, 1])


#ax.set_autoscale_on(False)

# Make the agents.
for i in range(num_of_agents):
    agents.append([random.randint(0,100),random.randint(0,100)])

def update(frame_number):
    
    fig.clear()   

    for i in range(num_of_agents):
            if random.random() < 0.5:
                agents[i][0]  = (agents[i][0] + 1) % 99 
            else:
                agents[i][0]  = (agents[i][0] - 1) % 99
            
            if random.random() < 0.5:
                agents[i][1]  = (agents[i][1] + 1) % 99 
            else:
                agents[i][1]  = (agents[i][1] - 1) % 99 
        
   
    
    for i in range(num_of_agents):
        plt.scatter(agents[i][0],agents[i][1])
        #print(agents[i][0],agents[i][1])


animation = matplotlib.animation.FuncAnimation(fig, update, interval=1)

plt.show()<jupyter_output><empty_output><jupyter_text>...continued in python files to be run in terminal.Rest of practical is presented as the stand-alone final file - model.py and agentframework.py  Data imports: (do not run)1. Reading variables in from command line2. Scraping initial positions for the agents from the internetPasted here since these methods are ommitted from the final file (can be found in older versions in the "old" folder).<jupyter_code>##### COMMANDLINE: n_agents n_iters neighbourhood_size
import sys
print(sys.argv)
if len(sys.argv) > 1:
    args = sys.argv[1:]
    print('#### USING COMMANDLINE ARGUMENTS: ',args)
    num_agents = int(args[0])
    num_iters = int(args[1])
    neighbourhood = int(args[2])
else:
    print('#### USING DEFAULT ARGUMENTS: ',num_agents,num_iters,neighbourhood)
#### READ POSITIONS FROM the INTERNET
import requests
from bs4 import BeautifulSoup

r = requests.get('https://www.geog.leeds.ac.uk/courses/computing/practicals/python/agent-framework/part9/data.html',verify=False)
page = r.text
soup = BeautifulSoup(page,'html.parser')
xs = soup.find_all(attrs={"class": "x"})
ys = soup.find_all(attrs={"class": "y"})
num_agents = len(xs) # overwrite num_agents  ########## IMPORTANT

agents = []
for i in range(num_agents):
    ### FOR IMPORTING POSITIONS FROM URL
    init_coords = [int(xs[i].text)*3,int(ys[i].text)*3]
    agents.append(af.Agent(environment,agents,init_coords))
int(xs[i].text)
# #### FOR TESTING OF MATING
# positions = [[50,50],[52,52]]
# genders = ['m','f']
# num_agents = len(positions)
# agents = []
# for i in range(num_agents):
#     agents.append(af.Agent(environment,agents,positions[i],genders[i]))<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1543766216031681, 'fraction_numerical': 0.02744776730848013, 'mean_word_length': 4.3126586869786, 'pattern_counts': {'":': 2, '<': 64, '<?xml version=': 0, '>': 63, 'https://': 1, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '16', 'dir': 'jupyter-structured-clean-dedup', 'id': '241430', 'license': 'MIT', 'n_tokens_mistral': 5806, 'n_tokens_neox': 5371, 'n_words': 1103, 'path': 'Jupyter Workbook.ipynb', 'repo_name': 'amiraliemami/SheepSim', 'size': '14646'}