Message Boards Message Boards

[Numberphile] - Abelian Sandpiles - Done in the Wolfram Language

POSTED BY: Sander Huisman
12 Replies

You can easily generalize for n dimensions by (albeit incredible slow!!!!):

ClearAll@Sandpile    
Sandpile[x_SparseArray] := Sandpile@Normal@x
Normal@Sandpile[s_List] ^:= s    
Sandpile /: Sandpile[a_List] + Sandpile[n_Integer] := Sandpile@a + Sandpile[ConstantArray[n, Dimensions@a]]
Sandpile /: Sandpile[a_List] + Sandpile[b_List] /; Dimensions@a === Dimensions@b := Module[
  {sum, temp, rest, sides},
  sum = a + b;      
  sides = Permutations@Append[ConstantArray[0, {ArrayDepth@a - 1}], 1];
  sides = Join[sides, -sides];
  While[Max@sum >= 4,
   sum = ArrayPad[sum, 1, 0];
   temp = Quotient[sum, 4];
   sum -= 4 temp;
   sum += Total[RotateLeft[temp, ##1] & /@ sides];
   sum = ArrayPad[sum, -1]
   ];
  Sandpile@sum
  ]

Sandpile$Colors = {0 -> Black, 1 -> Yellow, 2 -> Blue, 3 -> Red, _Integer -> Pink};
Format[Sandpile[t_List /; ArrayDepth@t <= 2]] := ArrayPlot[If[ArrayDepth@t == 1, {t}, t] /. Sandpile$Colors, 
  ImageSize -> 400, Frame -> False]
Format[Sandpile[t_List /; ArrayDepth@t == 3]] := ListDensityPlot3D[t, ImageSize -> 400, Axes -> False,
  ColorFunction -> (Blend[{{0, Black}, {1, Yellow}, {2, Blue}, {3, Red}}, #] &),
  ColorFunctionScaling -> False, SphericalRegion -> True, Boxed -> False]
POSTED BY: Thales Fernandes

Thanks for sharing! Unit directions can also be created using:

UnitVector[3, #] & /@ Range[3]

But using permutations is also quite neat actually... I'm not sure if '4' should be the toppling value for all dimensions; I think it should be equal to the number of neighbours. So for squares: 2 in 1D, 4 in 2D, 6 in 3D et cetera. There are examples with hexagons (in 2D), where they take 6 as the toppling value...

I'm not quite sure why it is so slow though... maybe because sand is created because of the '4' thing.

Maybe you can explain me the difference between definition of the forms:

Sandpile /: Sandpile[a_List] + Sandpile[n_Integer] :=  ...
Sandpile[a_List] + Sandpile[n_Integer] ^:=  ...

I'm not very cognisant on this...

POSTED BY: Sander Huisman

Thanks for sharing! Unit directions can also be created using:

UnitVector[3, #] & /@ Range[3]

Clever!

I'm not sure if '4' should be the toppling value for all dimensions

In my 30 seconds deep internet research (Wikipedia) I couldn't find anything about the toppling number and dimensionality, I guessed it could be the number of neighbors too, but...

Maybe you can explain me the difference between definition of the forms:

No difference whatsoever in this case. I just don't like using ^:= (If that is a good enough reason, lol), and in some situations the upvalues are shared among different variables, therefore it offers more "control" (says the guy who likes excessive use of @!).

POSTED BY: Thales Fernandes

Hi Sander, Really great a I learned a lot from it! Many thanks!! And indeed the video starts a bit boring/puzzled (like where is this getting to) but is very nice at the end. Thanks!

POSTED BY: l van Veen

I don't often use ^:= but this was a good point to use it. Though I guess one could also use TagSet, not sure though. Both I only use once a year or so haha. Also I thought it would be a good idea to show the Format[...] 'trick', most people don't know about it, but can be very useful to see what is going on...

POSTED BY: Sander Huisman

enter image description here - Congratulations! This post is now a Staff Pick! Thank you for your wonderful contributions. Please, keep them coming!

POSTED BY: Moderation Team

You won the price :) If you're going to the tech event in Amsterdam I'll buy you a beer!

POSTED BY: l van Veen

For me it's just conservation of sand; if you add '1' sand to all your neighbours, you should take away 'neighbours' amount of sand in the centre... annihilating of magically creating sand is not good I guess...

ok ok, I'm still a bit confused on the syntax, but if she works she works... all good.

POSTED BY: Sander Huisman

For me it's just conservation of sand

As a physicist myself, I'm ashamed I haven't thought that...

Perhaps a better generalization would've be a graph, where a node topple its content to its neighbors if it has more sand than neighbors and the outer nodes (boundary) works as a dump site, where it can hold an infinite amount of sand without toppling.

I'm still a bit confused on the syntax

You can find more info at stackexchange. I just prefer TagSet over UpSet, since it makes more obvious what upvalues you are modifying.

POSTED BY: Thales Fernandes

Great! I found a C++ implementation and use it with LibraryLink template to simulate when you put a large pile of sand on a single cell:

https://community.wolfram.com/groups/-/m/t/1927307

POSTED BY: Shenghui Yang

Thanks!

POSTED BY: Sander Huisman

I'm not sure if I will be able to attend it. I know it is very close from France, but well... I will let you know if I do go.

POSTED BY: Sander Huisman
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract