Back

2026-04-22

Building a Schelling Segregation Model w/ a Cellular Automata

A simulation-first look at how simple local preferences can produce large-scale segregation, built with React, Canvas, and a fast CA update loop.

Schelling model simulation preview

Why I Built This

In my theoretical computer science class, we were given the choice of creating a project for extra credit involving cellular automata, and I am always looking for a new challenge.

The central question is straightforward:

  • If agents only prefer a modest fraction of similar neighbors, what does the full system become over time?

The surprising answer is that even mild local preference can still create highly segregated global patterns.

Background

Thomas Schelling introduced this model to show that segregation does not require centralized coordination. Individual decisions, each made locally, can compound into a city-scale pattern that no single agent explicitly planned.

That makes this model a good fit for computational exploration:

  • The rules are simple enough to implement clearly.
  • The outcomes are rich enough to produce non-obvious behavior.
  • The state space is so large that simulation is more practical than exhaustive analysis.

Project Overview

This implementation is a 2D cellular automaton on a 50 x 50 grid with three possible cell states:

  • Empty
  • Group A agent
  • Group B agent

At each step:

  1. Agents evaluate the eight-cell Moore neighborhood.
  2. Agents with similarity below a tolerance threshold tau are marked unsatisfied.
  3. Unsatisfied agents move into shuffled empty cells.
  4. The process repeats until the system stabilizes or reaches the run limit.

The end result is an interactive simulation where you can tune the tolerance and densities, then watch cluster formation unfold in real time.

Technical Deep Dive

Model and update rule

I formalized satisfaction using a local ratio:

same_group_neighbors / total_non_empty_neighbors >= tau

If an agent has no non-empty neighbors, it is treated as satisfied by default. This avoids undefined behavior in sparse areas of the grid and keeps the simulation stable.

Rendering and performance strategy

I used Canvas rather than DOM cells because the simulation redraws frequently. This keeps frame updates smooth and avoids the overhead of managing thousands of React elements per tick.

Key implementation decisions:

  • Store simulation state in refs to avoid unnecessary React re-renders per frame.
  • Perform neighborhood checks in an O(n^2) pass per step.
  • Use shuffle-and-fill relocation for unsatisfied agents to keep movement randomized and unbiased.
  • Support variable speed (sub-1x and multi-step per frame) so the simulation is both inspectable and fast.

Observed behavior

Across runs, I consistently observed:

  • Early random noise with small local clusters.
  • A rapid transition phase where clusters merge.
  • Plateau behavior where happiness stabilizes and cross-group boundaries shrink.

One of the most interesting outcomes is threshold sensitivity: small changes in tau can dramatically alter convergence behavior.

What This Project Demonstrates

  • Emergence: local rules can create large-scale structure.
  • Non-linearity: small parameter changes can produce disproportionately large effects.
  • Simulation as method: when state spaces explode combinatorially, simulation becomes the practical way to reason about dynamics.

This project strengthened my understanding of cellular automata, iterative system design, and performance-minded frontend implementation for scientific visualization.

Closing Notes

I built this as a school project, but it ended up being one of the clearest examples I have worked on for turning abstract theory into visible behavior.

If you want to reproduce the same effect quickly, start with a mid-range tolerance and equal group densities, then sweep the tolerance up and down to see where behavior shifts from stable mixing to strong segregation.

Schelling model simulation final view