Re: weighting CA neighbors by distance

*To*: mathgroup at smc.vnet.net*Subject*: [mg29886] Re: [mg29866] weighting CA neighbors by distance*From*: Daniel Lichtblau <danl at wolfram.com>*Date*: Tue, 17 Jul 2001 01:00:32 -0400 (EDT)*References*: <200107140536.BAA18400@smc.vnet.net>*Sender*: owner-wri-mathgroup at wolfram.com

Brent Pedersen wrote: > > I am doing some variations of cellular automata. > Using only the actual value of the neighbors in determining the value of > the current cell, I can use: > > Apply[Plus, Map[RotateRight[mat1, ##] &, nbrs]]; > > where mat1 is the matrix of values for whatever the CA is modelling. > and nbrs is a list of pairs (eg. > {{-1,-1},{-1,0},{-1,1},{0,-1},{0,1},{1,-1},{1,0}, > {1,1}} for the 8 cell moore neighborhood.) defining the neighborhood I > am interested in. > > The line above sums all neighbors as they are but, I wish to weight the > neighbors > according to their distance (eg. {-1,-1} is farther away than {-1,0} > when using the > RotateRight function. > I think I may be able to do this with ListConvolve, or Inner but I can't > figure it out. > Anyone have any ideas? You can do this with ListCorrelate. We construct an example as below. npoints = 7; SeedRandom[1111]; In[19]:= InputForm[mat = Table[Random[Integer, 10], {npoints}, {npoints}]] Out[19]//InputForm= {{8, 3, 9, 8, 7, 2, 9}, {7, 3, 3, 10, 9, 8, 0}, {3, 2, 1, 0, 4, 1, 7}, {3, 0, 7, 0, 0, 5, 6}, {1, 0, 1, 6, 2, 1, 9}, {10, 3, 4, 7, 4, 3, 6}, {2, 3, 7, 2, 8, 8, 10}} Suppose you wish to weight adjacent elements with 1, and diagonal neighbors with 1/2. We can use the kernel below for this. kernel = {{1/2, 1, 1/2}, {1, 0, 1}, {1/2, 1, 1/2}}; as implicitly continued cyclicly. In[25]:= InputForm[newmat = ListCorrelate[kernel, mat, {2, -2}]] Out[25]//InputForm= {{29, 65/2, 30, 83/2, 41, 91/2, 65/2}, {49/2, 51/2, 59/2, 61/2, 69/2, 51/2, 38}, {47/2, 17, 37/2, 49/2, 43/2, 63/2, 43/2}, {19, 15, 6, 17, 15, 19, 27}, {59/2, 17, 22, 35/2, 37/2, 27, 49/2}, {23, 45/2, 47/2, 25, 57/2, 67/2, 38}, {83/2, 61/2, 57/2, 42, 31, 36, 73/2}} If instead you want to regard the matrix as implicitly bordered by zeros, you can do that as follows. In[27]:= InputForm[newmat2 = ListCorrelate[kernel, mat, {2, -2}, 0]] Out[27]//InputForm= {{23/2, 25, 41/2, 32, 28, 57/2, 6}, {33/2, 51/2, 59/2, 61/2, 69/2, 51/2, 51/2}, {27/2, 17, 37/2, 49/2, 43/2, 63/2, 27/2}, {5, 15, 6, 17, 15, 19, 22}, {29/2, 17, 22, 35/2, 37/2, 27, 17}, {15/2, 45/2, 47/2, 25, 57/2, 67/2, 53/2}, {29/2, 19, 14, 26, 19, 26, 31/2}} Getting the various parameters exactly right for your intended use may take some fiddling, so don't assume either of the above is quite what you need. But I think they should put you within shouting distance, and I tested that the cyclic case, with ones for all weights except at the center, agrees with your code on this example. I illustrated with exact matrices and weights, and that may be appropriate for cellular automata in 2D. Note that for many purposes, e.g. image processing with values in a continuum, it will be faster to use approximate arithmetic. Daniel Lichtblau Wolfram Research

**References**:**weighting CA neighbors by distance***From:*Brent Pedersen <bpederse@nature.berkeley.edu>