Skip to content

Instantly share code, notes, and snippets.

@quaquel
Created January 16, 2024 16:31
Show Gist options
  • Select an option

  • Save quaquel/b2e8c7be21aee4e1ffdf6e2fd4286dff to your computer and use it in GitHub Desktop.

Select an option

Save quaquel/b2e8c7be21aee4e1ffdf6e2fd4286dff to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "506a9a81-79f0-480e-adcf-b98d15c2f193",
"metadata": {},
"outputs": [],
"source": [
"from typing import List, Any\n",
"import random\n",
"from functools import cache\n",
"\n",
"from mesa import Model, Agent\n",
"\n",
"class GridCell:\n",
" @property\n",
" def neighbors(self):\n",
" return [entry.content for entry in self.neighborhood if entry.content != None]\n",
" \n",
" def __init__(self, i:int, j:int) -> None:\n",
" self.i = i\n",
" self.j = j\n",
" self.coords = (i, j)\n",
" self._neighborhood = None\n",
" self.content = None\n",
"\n",
" self.left: GridCell = None\n",
" self.right: GridCell = None\n",
" self.top: GridCell = None\n",
" self.bottom: GridCell = None\n",
" self.topleft: GridCell = None\n",
" self.topright: GridCell = None\n",
" self.bottomright: GridCell = None\n",
" self.bottomleft: GridCell = None\n",
"\n",
" def _calculate_neighborhood(self):\n",
" neighborhood = [self.topleft, self.top, self.topright, \n",
" self.right, self.bottomright, self.bottom,\n",
" self.bottomleft, self.left]\n",
" neighborhood = [entry for entry in neighborhood if entry != None]\n",
" self.neighborhood = neighborhood\n",
"\n",
"\n",
"class Grid:\n",
" def __init__(self, width:int, height:int, torus:bool = False) -> None:\n",
" self.width = width\n",
" self.height = height\n",
" self.torus = torus\n",
"\n",
" self.cells: List[List[GridCell]] = [[GridCell(j, i) for i in range(width)] for j in range(height)]\n",
" \n",
" # connect within a row\n",
" for row in self.cells:\n",
" for cell1, cell2 in zip(row, row[1::]):\n",
" cell1.right = cell2\n",
" cell2.left = cell1\n",
"\n",
" if torus:\n",
" for row in self.cells:\n",
" row[0].left = row[-1]\n",
" row[-1].right = row[0]\n",
"\n",
" # connect across rows\n",
" for entry in zip(self.cells, self.cells[1::]):\n",
" for cell1, cell2 in zip(*entry):\n",
" cell1.bottom = cell2\n",
" cell1.bottomleft = cell2.left\n",
" cell1.bottomright = cell2.right\n",
"\n",
" cell2.top = cell1\n",
" cell2.topright = cell1.left\n",
" cell2.topleft = cell1.right\n",
"\n",
" if torus:\n",
" for cell1, cell2 in zip(self.cells[0], self.cells[-1]):\n",
" cell1.top = cell2\n",
" cell1.topleft = cell2.left\n",
" cell1.topright = cell2.right\n",
"\n",
" cell2.bottom = cell1\n",
" cell2.bottomleft = cell1.left\n",
" cell2.bottomright = cell1.right\n",
"\n",
" for row in self.cells:\n",
" for cell in row:\n",
" cell._calculate_neighborhood()\n",
"\n",
" @cache\n",
" def get_neighborhood(self, coords, radius):\n",
" i, j = coords\n",
" \n",
" neighborhood = {}\n",
" if radius==0:\n",
" return {self.cells[i][j]:None}\n",
" else:\n",
" radius = radius - 1\n",
" for cell in self.cells[i][j].neighborhood:\n",
" neighborhood = neighborhood | self.get_neighborhood(cell.coords, radius)\n",
" \n",
" return neighborhood\n",
"\n",
" def get_neighbors(self, coords, radius):\n",
" neighborhood = self.get_neighborhood(coords, radius)\n",
" \n",
" return [content for entry in neighborhood if (content := entry.conten != None)]\n",
"\n",
" \n",
" def place_agent(self, agent, pos):\n",
" pass\n",
"\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "d8255039-4b64-490f-b45c-02c192ccfaa0",
"metadata": {},
"outputs": [],
"source": [
"random.seed(42)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "068985d2-3752-440f-a7f4-3e2b9ce33b26",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"646 ms ± 1.52 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n"
]
}
],
"source": [
"%%timeit\n",
"grid = Grid(1000, 1000, torus=True)\n",
"\n",
"# a = grid.cells[0][1]\n",
"# print([entry.coords for entry in a.neighbors])\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "6e28896c-ea44-4ac3-900e-76212add9384",
"metadata": {},
"outputs": [],
"source": [
"random.seed(42)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "7c856c69-5010-4aa6-aff4-c3ee1f7fbfd3",
"metadata": {},
"outputs": [],
"source": [
"model = Model()\n",
"\n",
"grid = Grid(100, 100)\n",
"\n",
"counter = 0\n",
"for i in range(100):\n",
" for j in range(100):\n",
" grid.cells[i][j].neighborhood\n",
" if random.random() > 0.2:\n",
" agent = Agent(model.next_id(), model)\n",
" grid.cells[i][j].content = agent"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "1b149cf6-0da4-4c66-82ad-7e835dad975e",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"469 ns ± 17.1 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)\n"
]
}
],
"source": [
"%%timeit\n",
"grid.cells[random.randint(0, 99)][random.randint(0, 99)].neighbors"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "a3ba0513-1477-4e1a-bc23-a226f35dabec",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"616 ns ± 10.2 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)\n"
]
}
],
"source": [
"%%timeit\n",
"grid.get_neighborhood((random.randint(0, 99), random.randint(0, 99)), radius=3)"
]
},
{
"cell_type": "markdown",
"id": "ec8d067c-8f0e-4d07-9c55-880225799daf",
"metadata": {},
"source": [
"# MESA"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "7a5bff9a-940a-4ebd-9711-331c9d870365",
"metadata": {},
"outputs": [],
"source": [
"from mesa.space import SingleGrid\n"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "da4e7b8e-961a-48aa-836b-3790aa1d0c89",
"metadata": {},
"outputs": [],
"source": [
"random.seed(42)"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "4487d5d9-1e3c-4442-8f75-d8a0a684419e",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"40.5 ms ± 206 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)\n"
]
}
],
"source": [
"%%timeit\n",
"grid = SingleGrid(1000, 1000, torus=True)"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "9024706d-3b92-4778-9115-86fb5cfa8f9a",
"metadata": {},
"outputs": [],
"source": [
"random.seed(42)"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "f384c770-ca3c-4d6a-b9ec-aff7c6eac00b",
"metadata": {},
"outputs": [],
"source": [
"model = Model()\n",
"\n",
"grid = SingleGrid(1000, 1000, torus=True)\n",
"\n",
"counter = 0\n",
"for i in range(100):\n",
" for j in range(100):\n",
" if random.random() > 0.2:\n",
" agent = Agent(model.next_id(), model)\n",
" grid.place_agent(agent, (i,j))"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "571a4cfc-20df-46eb-81d6-457d7389692b",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1.35 µs ± 27.4 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)\n"
]
}
],
"source": [
"%%timeit\n",
"grid.get_neighbors((random.randint(0, 99), random.randint(0, 99)), moore=False, radius=1)"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "a92425ec-8b8c-4ae9-90b3-244368e92273",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"2.95 µs ± 117 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)\n"
]
}
],
"source": [
"%%timeit\n",
"grid.get_neighbors((random.randint(0, 99), random.randint(0, 99)), moore=False, radius=3)"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "d73d031c",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"4.83 µs ± 125 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)\n"
]
}
],
"source": [
"%%timeit\n",
"grid.get_neighbors((random.randint(0, 99), random.randint(0, 99)), moore=True, radius=3)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.6"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment