robossembler.org/docs/models/growth/growth.ipynb

368 lines
17 KiB
Text
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"cells": [
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"2 2\n",
"2 2\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"Traceback (most recent call last):\n",
" File \"C:\\ProgramData\\Anaconda3\\lib\\site-packages\\matplotlib\\cbook\\__init__.py\", line 388, in process\n",
" proxy(*args, **kwargs)\n",
" File \"C:\\ProgramData\\Anaconda3\\lib\\site-packages\\matplotlib\\cbook\\__init__.py\", line 228, in __call__\n",
" return mtd(*args, **kwargs)\n",
" File \"C:\\ProgramData\\Anaconda3\\lib\\site-packages\\matplotlib\\animation.py\", line 1308, in _handle_resize\n",
" self._init_draw()\n",
" File \"C:\\ProgramData\\Anaconda3\\lib\\site-packages\\matplotlib\\animation.py\", line 1750, in _init_draw\n",
" self._draw_frame(next(self.new_frame_seq()))\n",
" File \"C:\\ProgramData\\Anaconda3\\lib\\site-packages\\matplotlib\\animation.py\", line 1772, in _draw_frame\n",
" self._drawn_artists = self._func(framedata, *self._args)\n",
" File \"<ipython-input-3-63ec1324f14b>\", line 268, in updatefig\n",
" im1=plt.imshow(Zm, cmap=plt.get_cmap('magma').with_extremes(bad='#101020'))\n",
"AttributeError: 'ListedColormap' object has no attribute 'with_extremes'\n",
"Traceback (most recent call last):\n",
" File \"C:\\ProgramData\\Anaconda3\\lib\\site-packages\\matplotlib\\cbook\\__init__.py\", line 388, in process\n",
" proxy(*args, **kwargs)\n",
" File \"C:\\ProgramData\\Anaconda3\\lib\\site-packages\\matplotlib\\cbook\\__init__.py\", line 228, in __call__\n",
" return mtd(*args, **kwargs)\n",
" File \"C:\\ProgramData\\Anaconda3\\lib\\site-packages\\matplotlib\\animation.py\", line 1308, in _handle_resize\n",
" self._init_draw()\n",
" File \"C:\\ProgramData\\Anaconda3\\lib\\site-packages\\matplotlib\\animation.py\", line 1750, in _init_draw\n",
" self._draw_frame(next(self.new_frame_seq()))\n",
" File \"C:\\ProgramData\\Anaconda3\\lib\\site-packages\\matplotlib\\animation.py\", line 1772, in _draw_frame\n",
" self._drawn_artists = self._func(framedata, *self._args)\n",
" File \"<ipython-input-3-63ec1324f14b>\", line 268, in updatefig\n",
" im1=plt.imshow(Zm, cmap=plt.get_cmap('magma').with_extremes(bad='#101020'))\n",
"AttributeError: 'ListedColormap' object has no attribute 'with_extremes'\n"
]
}
],
"source": [
"%matplotlib tk\n",
"import time, math\n",
"from random import random\n",
"import numpy as np\n",
"from IPython import display\n",
"from IPython.display import clear_output\n",
"from PIL import Image\n",
"import matplotlib.pyplot as plt\n",
"import matplotlib.animation as animation\n",
"\n",
"# Генерация карт по картинке\n",
"\n",
"Terrain=np.sign(np.array(Image.open(\"test.png\"))[:,:,0])\n",
"ShowTerrain=Terrain*1.0\n",
"Flow=Store=TransportActivity=Conc=Terrain*0.0\n",
"Dir=Terrain*0\n",
"\n",
"# Генерация случайных препятствий\n",
"\n",
"#for i in range(100):\n",
"# Terrain[int(random()*Live.shape[0]-2),int(random()*Live.shape[1]-2)]=0\n",
"\n",
"# Настройка параметров клетки\n",
" \n",
"START_COMPLETENESS = 1\n",
"#GROW_COMPLETENESS = 7\n",
"REP_COMPLETENESS = 20\n",
"#MAX_COMPLETENESS = 100\n",
"\n",
"# Настройка параметров распространеняи сигнала об активном строительстве \n",
"\n",
"INCOMPLETENESS_SIGNAL_EMISSION_RATIO = 0.1\n",
"INCOMPLETENESS_SIGNAL_DIFFUSION_RATIO = 0.45\n",
"INCOMPLETENESS_SIGNAL_DECAY_RATIO = 0.9\n",
"INCOMPLETENESS_SIGNAL_THRESHOLD = 1\n",
"\n",
"# Настройка бобмбардировки \n",
" \n",
"BOMB_MIN=0\n",
"BOMB_START=60000\n",
"BOMB_MAX=1\n",
"BOMB_SIZE=2\n",
"b=BOMB_MIN\n",
"\n",
"# Выбор способа отображения цифровыми клавишами 0-5\n",
"\n",
"def on_press(event):\n",
" global DISPLAY\n",
" global ax\n",
" global plt\n",
" DISPLAY=int(event.key)\n",
" if DISPLAY==0:\n",
" ax.set_title('Terrain') \n",
" elif DISPLAY==1:\n",
" ax.set_title('Incompleteness Signal Concentration')\n",
" elif DISPLAY==2:\n",
" ax.set_title('Incompleteness Signal Direction')\n",
" elif DISPLAY==3:\n",
" ax.set_title('Transport Direction')\n",
" elif DISPLAY==4:\n",
" ax.set_title('Storage')\n",
" elif DISPLAY==5:\n",
" ax.set_title('Transport Activity')\n",
" plt.draw()\n",
"\n",
"# Настройка графического отображения\n",
"\n",
"fig=plt.figure()#(figsize=(7, 5))\n",
"ax=fig.add_subplot(1, 1, 1)\n",
"im1=plt.imshow(ShowTerrain, cmap=plt.get_cmap('bone'), animated=True)\n",
"fig.canvas.mpl_connect('key_press_event', on_press)\n",
"DISPLAY=0\n",
"ax.set_title('Terrain') \n",
"writer = animation.writers['ffmpeg'](fps=15, metadata=dict(artist='Me'), bitrate=1800)\n",
"framecounter=0\n",
"\n",
"# Словарь для хранения клеток по координатам\n",
"\n",
"cells={}\n",
" \n",
"class Cell():\n",
" def __init__(self,x,y):\n",
" self.x=x\n",
" self.y=y\n",
" self.productivity=1\n",
" self.transportivity=10\n",
" self.completeness=START_COMPLETENESS\n",
" self.conc=0\n",
" self.flow=0\n",
" self.storage=0\n",
" cells[(self.x,self.y)] = self\n",
" self.refresh()\n",
" def refresh(self):\n",
" if self.completeness<1:\n",
" self.destroy()\n",
" addconc=(REP_COMPLETENESS-self.completeness)*INCOMPLETENESS_SIGNAL_EMISSION_RATIO\n",
" if self.completeness>=REP_COMPLETENESS:\n",
" addconc=0\n",
" self.conc+=addconc\n",
" self.conc*=INCOMPLETENESS_SIGNAL_DECAY_RATIO\n",
" def destroy(self):\n",
" del cells[(self.x,self.y)]\n",
"\n",
"# Создаем первоначальную клетку\n",
" \n",
"a=Cell(20,20)\n",
"a.completeness=REP_COMPLETENESS\n",
"a.refresh()\n",
"\n",
"# Расчеты в каждом кадре\n",
"\n",
"def updatefig(*args):\n",
" global b,TransportActivity,ShowTerrain,Store,framecounter\n",
" \n",
" # Очистка карт для визуализации\n",
" \n",
" TransportActivity=Terrain*0.0\n",
" ShowTerrain=Terrain*1\n",
" Store=Terrain*0.0\n",
" Conc=Terrain*0.0\n",
" \n",
" clist=list(cells.values())\n",
" for c in clist: # Расчеты для каждой клетки\n",
" c.refresh()\n",
" \n",
" # Отображение различных параметров клетки \n",
" Store[c.x,c.y]=c.storage\n",
" ShowTerrain[c.x,c.y]=c.completeness\n",
" Conc[c.x,c.y]=c.conc\n",
" \n",
" if c.completeness>=REP_COMPLETENESS: # Если клетка зрелая, то:\n",
" c.storage+=c.productivity # Производство объектов на склад\n",
" \n",
" # Составляем список соседних участков с учетом границ карты\n",
" \n",
" neighbors=[]\n",
" if c.x>0:\n",
" neighbors.append((c.x-1,c.y))\n",
" if c.x<Terrain.shape[0]-1:\n",
" neighbors.append((c.x+1,c.y))\n",
" if c.y>0:\n",
" neighbors.append((c.x,c.y-1))\n",
" if c.y<Terrain.shape[1]-1:\n",
" neighbors.append((c.x,c.y+1)) \n",
"\n",
" candidatemax=0\n",
" concmax=0\n",
" fx=0\n",
" fy=0\n",
" cneed=None\n",
" \n",
" for (nx,ny) in neighbors: # Для каждого участка из списка соседей\n",
" if (nx,ny) in cells.keys(): # Если на нем есть клетка \n",
" \n",
" # Расчет градиента сигнала роста\n",
" \n",
" f=cells[(nx,ny)]\n",
" vconc=f.conc-c.conc\n",
" fx+=vconc*(nx-c.x)\n",
" fy+=vconc*(ny-c.y)\n",
" \n",
" # Выявление соседа с наибольшей концентрацией сигнала роста\n",
" \n",
" if f.conc>concmax:\n",
" cneed=f\n",
" needer=int((nx-c.x)+2*(ny-c.y)+3)\n",
" if needer==5:\n",
" needer=3\n",
" concmax=f.conc\n",
" \n",
" # Диффузия сигнала роста\n",
" \n",
" aconc=(c.conc+f.conc)/2\n",
" dconc=(aconc-c.conc)*INCOMPLETENESS_SIGNAL_DIFFUSION_RATIO \n",
" c.conc+=dconc\n",
" f.conc-=dconc\n",
"\n",
" # Выявление наиболее готовой недостроенной соседней клетки\n",
" \n",
" if f.completeness<REP_COMPLETENESS: \n",
" if candidatemax<f.completeness:\n",
" candidatemax=f.completeness\n",
" candidate=(nx,ny)\n",
" \n",
" # Если на участке нет клетки, проверяем можно ли там построить новую\n",
" # Постройка новых клеток имеет меньший приоритет, чем достройка начатых\n",
" \n",
" else: \n",
" if Terrain[nx,ny]>0:\n",
" if candidatemax<1:\n",
" candidate=(nx,ny)\n",
" candidatemax=1\n",
" \n",
" # Отображение на картах направления транспорта и градиента сигнала роста\n",
" \n",
" if concmax>0:\n",
" Dir[c.x,c.y]=needer\n",
" Flow[c.x,c.y]=math.atan2(fx,fy)\n",
" \n",
" \n",
" if candidatemax>0: # Если есть недостроенные или пустые участки\n",
" if candidatemax==1: # Если есть только пустые\n",
" cneed=Cell(candidate[0],candidate[1]) # Создать клетку\n",
" else: # Иначе\n",
" cneed=cells[(candidate[0],candidate[1])] # Помогаем строящейся клетке\n",
" \n",
" # Транспорт объектов в соседние клетки\n",
" \n",
" if cneed:\n",
" \n",
" # Установим объем грузоперевозок в зависимости от концентрации сигнала роста\n",
" # и ограничим его минимум и максимум\n",
" \n",
" kgr=(cneed.conc)/INCOMPLETENESS_SIGNAL_THRESHOLD\n",
" if kgr<0:\n",
" kgr=0\n",
" if kgr>1:\n",
" kgr=1\n",
" \n",
" # Если запасы не меньше, чем планируемый экспорт,\n",
" # то отправим сколько планировали\n",
" \n",
" if c.storage>=c.transportivity*kgr:\n",
" cneed.completeness+=c.transportivity*kgr # Передача\n",
" TransportActivity[c.x,c.y]+=c.transportivity*kgr # Отображение на карте перевозок\n",
" c.storage-=c.transportivity*kgr # Удаление со склада\n",
"\n",
" # Иначе отправим сколько можем\n",
" \n",
" else:\n",
" cneed.completeness+=c.storage # Передача \n",
" TransportActivity[c.x,c.y]+=c.storage # Отображение на карте перевозок \n",
" c.storage=0 # Удаление со склада\n",
" \n",
" # Если получатель принял больше чем нужно для строительства, \n",
" # излишки у него складируются\n",
" # (на следующем ходу он может передать их дальше)\n",
" \n",
" if cneed.completeness>REP_COMPLETENESS:\n",
" cneed.storage+=cneed.completeness-REP_COMPLETENESS\n",
" cneed.completeness=REP_COMPLETENESS\n",
" cneed.refresh()\n",
" \n",
" # Бомбардировка\n",
" \n",
" if len(cells)>BOMB_START:\n",
" b=BOMB_MAX\n",
" for i in range(b): \n",
" sx=int(random()*Terrain.shape[0])\n",
" sy=int(random()*Terrain.shape[1])\n",
" for xi in range(sx,sx+BOMB_SIZE):\n",
" for yi in range(sy,sy+BOMB_SIZE):\n",
" if (xi,yi) in cells.keys():\n",
" cells[(xi,yi)].destroy()\n",
"\n",
" # Вывод текстом номера кадра и числа клеток (чтобы следить за процессом при записи анимации в файл) \n",
" \n",
" framecounter+=1\n",
" clear_output(wait=True)\n",
" print(framecounter,len(cells)) \n",
" \n",
" # Отображение выбранной карты\n",
" \n",
" if DISPLAY==0:\n",
" im1=plt.imshow(ShowTerrain, cmap=plt.get_cmap('bone'))\n",
" elif DISPLAY==1:\n",
" Zm = np.ma.masked_where(Terrain == 0, Conc)\n",
" im1=plt.imshow(Zm, cmap=plt.get_cmap('magma').with_extremes(bad='#101020'))\n",
" elif DISPLAY==2:\n",
" Zm = np.ma.masked_where(TransportActivity<0.1, Flow)\n",
" im1=plt.imshow(Zm, cmap=plt.get_cmap('hsv').with_extremes(bad='k'))\n",
" elif DISPLAY==3:\n",
" Zm = np.ma.masked_where(TransportActivity<0.1, Dir)\n",
" im1=plt.imshow(Zm, cmap=plt.get_cmap('brg').with_extremes(bad='k'))\n",
" elif DISPLAY==4:\n",
" im1=plt.imshow(Store, cmap=plt.get_cmap('gist_stern'))\n",
" elif DISPLAY==5:\n",
" Zm = np.ma.masked_where(Terrain == 0, TransportActivity)\n",
" im1=plt.imshow(Zm, cmap=plt.get_cmap('hot').with_extremes(bad='#101020'))\n",
" return im1,\n",
"\n",
"# Настройка анимации\n",
"ani = animation.FuncAnimation(fig, updatefig, frames=600, interval=3, blit=True)\n",
"plt.show()\n",
"#ani.save('im0.mp4', writer=writer) # Сохранить анимацию в файле"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"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.6.5"
}
},
"nbformat": 4,
"nbformat_minor": 1
}