1

I am implementing the Biham-Middleton-Levine Traffic Model for testing and have encountered an issue with the speed of my implementation.


import matplotlib.pyplot as plt
from matplotlib import colors
import numpy as np
import random

data = np.random.rand(10, 10) * 20

# create discrete colormap
cmap = colors.ListedColormap(['white','red', 'blue'])
bounds = [-0.5,0.5,1.5,2.5]
norm = colors.BoundaryNorm(bounds, cmap.N)

p = 0.5
iter = 1000

sizex = 10
sizey = 10

road = np.zeros((sizex,sizey))
for posx in range(np.shape(road)[0]):
    for posy in range(np.shape(road)[1]):
        if random.uniform(0,1)<p:
            if random.uniform(0,1)<0.5:
                road[posx][posy] = 1
            else:
                road[posx][posy] = 2

road[1][1]=1
road[1,2]=2
print(road)

def check(posx, posy, surf):
    type = surf[posx][posy]
    
    if type == 1:
        posx, posy = posy, posx
        surf = np.transpose(surf)   
    
    if posx+1<np.shape(surf)[0]:
            
        if surf[posx+1][posy] == 0:
            surf[posx][posy] = 0
            surf[posx+1][posy] = type

    elif posx+1 == np.shape(surf)[0]:

        if surf[0][posy] == 0:
            surf[0][posy] = type
            surf[posx][posy] = 0

fig, ax = plt.subplots()
ax.grid(which='major', axis='both', linestyle='-', color='k', linewidth=1)
ax.set_xticks(np.arange(-.5, sizex, 1));
ax.set_yticks(np.arange(-.5, sizey, 1));
ax.set_xticklabels([])
ax.set_yticklabels([])
                                                                                                
for iteration in range(iter):
    
    checklist_x = []
    checklist_y = []
    
    for posx in range(np.shape(road)[0]):
        for posy in range(np.shape(road)[1]):
            if road[posx][posy] == 1:
                checklist_x.append((posx,posy))             
                
    for posx in range(np.shape(road)[0]):
        for posy in range(np.shape(road)[1]):
            if road[posx][posy] == 2:
                checklist_y.append((posx,posy))
                
    for car in checklist_x:
        check(car[0],car[1],road)
        
    for car in checklist_y:
        check(car[0],car[1],road)
                
    
    ax.imshow(road, cmap=cmap, norm=norm)

    plt.show()
print('done')

My implementation runs very slowly, although this is mostly due to the way that I am drawing the cell grid,

fig, ax = plt.subplots()
ax.grid(which='major', axis='both', linestyle='-', color='k', linewidth=1)
ax.set_xticks(np.arange(-.5, sizex, 1));
ax.set_yticks(np.arange(-.5, sizey, 1));
ax.set_xticklabels([])
ax.set_yticklabels([])
                                                                                                
for iteration in range(iter):
    
    checklist_x = []
    checklist_y = []
    
    for posx in range(np.shape(road)[0]):
        for posy in range(np.shape(road)[1]):
            if road[posx][posy] == 1:
                checklist_x.append((posx,posy))             
                
    for posx in range(np.shape(road)[0]):
        for posy in range(np.shape(road)[1]):
            if road[posx][posy] == 2:
                checklist_y.append((posx,posy))
                
    for car in checklist_x:
        check(car[0],car[1],road)
        
    for car in checklist_y:
        check(car[0],car[1],road)
                
    
    ax.imshow(road, cmap=cmap, norm=norm)

    plt.show()
print('done')

The cell grid is redrawn over every iteration, which is very intensive, and greatly outweighs the computation time for working out in array form what the next iteration should be. Is there any way to cache or otherwise avoid redrawing the entire thing every step?

Bart Weil
  • 11
  • 1
  • If you care about speed, do not use python lists for 2D array. Use *Numpy* instead which is much faster for that. – Jérôme Richard May 12 '21 at 16:56
  • I am using numpy for my cell grid, and there are many other improvements that could be made to streamline the logic, but what is most intensive by far is the plotting of the grid at each step. – Bart Weil May 12 '21 at 17:26
  • matplotlib is a good tool for fancy graphs but clearly not for high performance. It is often fast enough to compute several graphs per second on data of reasonable size. If you need to work on big data, then something else like *VTK* is probably better suited. If you just need to generate a bunch of independent graphs, then you can also use the *multiprocessing* package to parallelize the graph generation. – Jérôme Richard May 12 '21 at 17:35

0 Answers0