简体   繁体   中英

Python Data Structure Recommendations for a 2D Grid

I am looking to implement an Ant Colony Optimization algorithm in Python, though am new to both Python and Object Oriented Programming so the learning curve has been rather steep. At this point, I am stuck as to how to address the following situation:

  • As ants walk around a 2D grid, they will encounter obstacles, pheromone deposits by other ants, food, etc. What data structure do I use to represent this 2D world and the aforementioned properties of each cell?

I had tried a 2D array, thinking that array[x-coord][y-coord] could point to a {} (dictionary) with the appropriate properties (Obstacle: 'Yes / 'No', Pheromone Level: X %, etc.) . Unfortunately, though NumPy lets me create a 2D array, I cannot assign dictionary objects to the various coordinates.

from numpy import *

myArray = array([[1,2,3,4],
                 [5,6,7,8],
                 [9,10,11,12]])

myArray[2][2]={}

Returns:

Traceback (most recent call last):
  File "/Users/amormachine/Desktop/PythonTest.py", line 7, in <module>
    myArray[2][2]={}
TypeError: long() argument must be a string or a number, not 'dict'
[Finished in 0.6s with exit code 1]

I am not committed to either dictionaries or this paradigm for implementing this project and would certainly appreciate the wisdom of the group.

sure you can, you just cant if your dtype is int ... so make your array with objects and you can use objects...

In [43]: a = [[{},{},{}],[{},{},{}]]

In [44]: a = numpy.array(a)

In [45]: a[1][1] = {'hello':'world','something':5}

In [46]: a
Out[46]:
array([[{}, {}, {}],
       [{}, {'hello': 'world', 'something': 5}, {}]], dtype=object)

although not sure whay you will gain using numpy with objects, you may be better off just leaving it as a list of lists

In plain Python I would be going for the list-of-dicts approach but with NumPy I find it more natural to work with separate arrays for different attributes rather than trying to keep things in one structure.

import numpy as np

grid_shape = (120,80)

# example of random initialization with this grid shape
pheremone_level = np.random.rand(*grid_shape)
obstacle = np.random.rand(*grid_shape) > 0.8

As @bitwise says it entirely depends on what operations you want to perform. Generally the "correct" way in NumPy will be much closer to how you would write it in Matlab than non-NumPy Python. Unfortunately I'm not familiar with how Ant Colony Optimization works so I can't say what's more suitable.

I was looking for something related to structured 2D grids and google led me to this page.

Although my solution is not entirely related to grids for what has been asked in the question, and I didn't want to repeat a question for 'structured 2D grid' data structure, I'm posting my solution here. I hope it will be useful to the audience searching for 2D structured grid and redirected here by search engines

Note: the method returns only the cell vertices and the vertex connectivity of each cells. Other quantities like cell volume, cell centroid, circumcircle, incircle, etc as needed for the application can be easily generated by adding additional routines

import numpy as np
import matplotlib.pyplot as plt

def create_structured_grid(corner1=None, corner2=None, nx=5, ny=5, plt_=True, annotate=True):
   """
   creates a structured grid of rectangular lattice

   input:
   ------
       corner1 : [x_start, y_start]
       corner2 : [x_end, y_end]
       nx      : numpts in x
       ny      : numpts in y
       plt_    : boolean whether to plot or not
       annotate: whether to annotate the grid points or not
   output:
   -------
       vertex_array : numpy.array((numpts, dim),dtype=float) of vertices
       connectivity : numpy.array((num_cells, 2**dim), dtyp=int) of
                   vertex connectivity for each cell
       plots   : additionally plots if boolean values are true
   """
   #corner1 = np.array([0.0, 0.0])
   #corner2 = np.array([1.0, 1.0])
   dim = len(corner1) #currently only for 2D,
   x_pts = np.linspace(corner1[0], corner2[0], nx)
   y_pts = np.linspace(corner1[1], corner2[1], ny)

   Xv, Yv = np.meshgrid(x_pts, y_pts)
   numpts = nx*ny
   vertex_array = np.zeros((numpts, 2), dtype=float)

   vertex_array[:,0] = np.reshape(Xv, numpts)
   vertex_array[:,1] = np.reshape(Yv, numpts)

   num_cells = int(nx-1)*(ny-1)
   connectivity = np.zeros((num_cells, int(2**dim)), dtype=int)

   rows = ny-1
   cols = nx-1
   for row in range(rows):
       for col in range(cols):
           num = nx*row + col
           connectivity[cols*row + col] = [num+0, num+1, num+nx, num+nx+1]

   if plt_:
       X,Y = vertex_array.T
       fig = plt.figure()
       ax = fig.add_subplot(111)
       ax.set_aspect('equal')
       plt.scatter(X,Y, marker='o', s=50, color='g', alpha=1.0)
       plt.plot(Xv,Yv, linewidth=2, color='k')
       plt.plot(Yv,Xv, linewidth=2, color='k')
       if annotate:
           for idx, cc in enumerate(vertex_array):
               plt.text(cc[0], cc[1],  str(idx), color='k', verticalalignment='bottom', horizontalalignment='right', fontsize='medium')
       plt.show(block=False)

   return vertex_array, connectivity

A call to function can be like this:

c1 = np.array([0.0, 0.0])
c2 = np.array([1.0, 1.0])
vertices, connctivity = create_structured_grid(corner1=c1, corner2=c2, nx=4, ny=4)

vertices = array([[ 0.        ,  0.        ],
                  [ 0.33333333,  0.        ],
                  [ 0.66666667,  0.        ],
                  [ 1.        ,  0.        ],
                  [ 0.        ,  0.33333333],
                  [ 0.33333333,  0.33333333],
                  [ 0.66666667,  0.33333333],
                  [ 1.        ,  0.33333333],
                  [ 0.        ,  0.66666667],
                  [ 0.33333333,  0.66666667],
                  [ 0.66666667,  0.66666667],
                  [ 1.        ,  0.66666667],
                  [ 0.        ,  1.        ],
                  [ 0.33333333,  1.        ],
                  [ 0.66666667,  1.        ],
                  [ 1.        ,  1.        ]])
connectivity = array([[ 0,  1,  5,  6],
                      [ 1,  2,  6,  7],
                      [ 2,  3,  7,  8],
                      [ 4,  5,  9, 10],
                      [ 5,  6, 10, 11],
                      [ 6,  7, 11, 12],
                      [ 8,  9, 13, 14],
                      [ 9, 10, 14, 15],
                      [10, 11, 15, 16]])

在此输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM