Back to Home

Firefly Synchronization in Wolfram Language

Article describes the implementation of the firefly synchronization model in Wolfram Language. Transition from agent-based model to vectorized cellular automaton using convolutions ListConvolve. Rendering optimization via NumericArray and video generation. Demonstrates emergent behavior on examples of 2–200 agents and 50×50 fields.

Fireflies Synchronize: Cellular Automaton Code
Advertisement 728x90

Synchronizing Fireflies: From Agent Models to Cellular Automata in Wolfram Language

Fireflies synchronize their flashes through local interactions. Each agent has an internal timer in the range [0,1], decaying at a rate of 0.01 per step. When it reaches 0, a flash occurs (state 1), affecting neighbors within a specified radius.

The key mechanism is adaptive phase correction: if a neighbor flashes, the current timer shifts forward or backward based on its position in the cycle. The direction is determined by Sign[2 Round[state] - 1]: negative for states closer to 0, positive for those closer to 1.

Agent Model: Generation and Connections

First, place n agents in a region and assign random initial states:

Google AdInline article slot
generateFireFlies[n_:200, region_:Rectangle[{-10,-10}, {10,10}]] := fireFlies = With[{ 
  pos = RandomPoint[region, n]
},
  Transpose[{pos, Table[RandomReal[{0,1.0}], {Length[pos]}]}]
];

Each firefly is a pair {position, state}. Connection matrix is computed using Euclidean distance:

bakeConnections[r_:3.7] := (
  connectionMatrix = Table[
    If[i == j, Infinity, Power[Norm[i[[1]] - j[[1]]], 2]]
  , {i, fireFlies}, {j, fireFlies}];

  connectionMatrix = MapIndexed[
    Function[{value, index},
      If[value < r, index[[1]], Nothing]
    ],
    #
  ] & /@ connectionMatrix
);

Core operations per step:

  • Decay: Clip[state - 0.01, {0,1}]
  • Flash: when state == 0 → 1
  • Correction: if neighbor is in state 1, state + Sign[2 Round[state] - 1] * 0.0001

Update: fireFlies = MapIndexed[adjust, decay /@ flash /@ fireFlies];

Google AdInline article slot

Testing at Small Scale

For two agents, synchronization takes ~10 cycles. State plots show convergence:

generateFireFlies[2, Circle[{0,0},0.5]];
bakeConnections[2.0];

Visualization with animation via EventHandler[AnimationFrameListener[...]] demonstrates phase alignment.

With 200 agents, use colored disks:

Google AdInline article slot
cf = Blend[{Darker[Red], Yellow}, #] &;
Graphics[{ 
  Table[
    With[{i = i, xy = fireFlies[[i,1]]},
      {RGBColor[colors[[i]]], Disk[xy, 0.3]}
    ], {i, Length[fireFlies]}
  ],
  EventHandler[AnimationFrameListener[colors], update]
}, Background->Black]

Blurring a duplicated layer creates a glowing effect.

Transition to Cellular Automaton

Logic resembles Game of Life but with continuous states. A 25×25 grid is initialized with RandomReal[{0,1.01}, {25,25}].

Flashes are detected via Floor[field]. Neighbor influence uses a 3×3 convolution kernel:

ListConvolve[
  {{1.0,1.0,1.0}, {1.0,0.0,1.0}, {1.0,1.0,1.0}},
  Floor[field],
  2, 0
]

Correction: (2.0 Round[field] - 1.0) * Clip[convolution, {0, 0.001}]. Decay-flash: Map[Clip[# - 0.01, {0.0,1.0}, {1.0,1.0}], f, {2}].

Full loop in Refresh at 30 FPS:

Module[{f = RandomReal[{0,1.01}, {25,25}]}, Refresh[
  f = Map[Clip[# - 0.01, {0.0,1.0}, {1.0,1.0}]&, f, {2}];

  f = Clip[
    f + (2.0 Round[f] - 1.0)
      Clip[
        ListConvolve[
          {{1.0,1.0,1.0}, {1.0,0.0,1.0}, {1.0,1.0,1.0}},
          Floor[f],
          2, 0
        ], {0, 0.001}
      ],
    {0., 1.0}
  ];

  ArrayPlot[f, Frame->True, ColorFunction->"PlumColors"]
, 1/30.0]]

Wave-like patterns emerge over iterations.

Performance Optimization

ArrayPlot in Refresh works well for prototypes, but for larger scales, use NumericArray and Image:

field = RandomReal[{0,1.0}, {50,50}];

render = Function[Null,
  Do[
    field = Map[Clip[# - 0.01, {0.0,1.0}, {1.0,1.0}]&, field, {2}];
    field = Clip[
      field + (2.0 Round[field] - 1.0)
        Clip[ListConvolve[{{1,1,1},{1,0,1},{1,1,1}}, Floor[field], 2, 0], {0,0.001}],
      {0.,1.0}
    ];
  , {2}];

  imageBuffer = NumericArray[255.0 field, "Byte", "ClipAndRound"];
];

Image[imageBuffer, "Byte", Epilog -> EventHandler[AnimationFrameListener[imageBuffer], render], Magnification -> 20]

On a 50×50 grid, radar-like structures appear.

Video Generation

For export:

movie = Table[
  render[];
  ImageResize[Colorize[Image[imageBuffer]], Scaled[6], Method->"NearestNeighbor"],
  {600}
];
FrameListVideo[movie, FrameRate->60]

The model scales from agent-based systems to GPU-friendly convolutions, showcasing emergent behavior.

Key Takeaways

  • Local rules (decay + adaptive correction) lead to global synchronization.
  • Agent model → cellular automaton: convolution replaces neighbor loops.
  • Sign[2 Round[state] - 1] enables bidirectional phase adjustment.
  • NumericArray + Image optimize rendering for large fields.
  • Rectangular convolution kernel produces square patterns; for realism, Gaussian kernels are preferred.

— Editorial Team

Advertisement 728x90

Read Next