Entropy and Information
Cellular Automata From First Principles 19: Entropy and Information
A row with almost all zeros is highly predictable.
A row containing a balanced mixture of zeros and ones is less predictable.
Shannon entropy gives us a precise way to measure that uncertainty.
Binary entropy
If a binary state contains a fraction p of ones, then:
H = -p log2(p) - (1-p) log2(1-p)
In Python:
import math
import numpy as np
def binary_entropy(state):
p = float(np.mean(state))
if p in (0.0, 1.0):
return 0.0
return -(p * math.log2(p) + (1 - p) * math.log2(1 - p))
The maximum is 1 bit when zeros and ones occur equally often.
Entropy is not complexity
Consider random coin flips.
They can have nearly maximal entropy.
But random noise has little reusable structure.
So:
high entropy != complex organization
Entropy measures uncertainty in a distribution.
It does not tell us whether patterns persist, interact or compute.
Neighborhood entropy
Instead of counting individual cells, count local patterns.
For a radius-1 elementary automaton, collect neighborhoods of length three:
from collections import Counter
def neighborhood_entropy(state, width=3):
patterns = []
n = len(state)
for i in range(n):
pattern = tuple(state[(i + j) % n] for j in range(width))
patterns.append(pattern)
counts = Counter(patterns)
total = len(patterns)
entropy = 0.0
for count in counts.values():
p = count / total
entropy -= p * math.log2(p)
return entropy
Now we measure diversity of local structures rather than only the global proportion of ones.
Entropy over time
def entropy_curve(history):
return np.array([binary_entropy(row) for row in history])
Useful questions include:
Does entropy collapse?
Does it remain high?
Does it oscillate?
Does it rise from a simple seed?
That last case is particularly interesting: simple initial conditions producing sustained informational diversity.
Compare entropy with activity
Create a joint record:
def information_summary(history):
entropies = entropy_curve(history)
activities = np.array([
np.mean(history[t] != history[t - 1])
for t in range(1, len(history))
])
return {
"mean_entropy": float(entropies.mean()),
"tail_entropy": float(entropies[-50:].mean()),
"mean_activity": float(activities.mean()),
}
Rules can now occupy different regions:
low entropy / low activity
high entropy / high activity
high entropy / low activity
moderate entropy / sustained activity
Those regions often correspond to qualitatively different dynamics.
Compression as another lens
Structured data often compresses well.
Random data usually does not.
Python gives us a quick experiment:
import zlib
def compression_ratio(history):
raw = np.packbits(history.astype(np.uint8)).tobytes()
compressed = zlib.compress(raw)
return len(compressed) / len(raw)
This is not a formal complexity measure, but it can expose repeated structure that simple cell entropy misses.
The interesting middle
A recurring idea in complex systems is that interesting behavior often appears between two extremes:
perfect order <------> random disorder
Cellular automata make that idea visible.
Some rules freeze.
Some become repetitive.
Some behave almost chaotically.
A smaller set supports persistent structures and interactions.
Our metrics will help us search that middle rather than selecting purely by eye.
Next: repetition
Entropy tells us about uncertainty.
But a system can have a rich-looking state and still repeat exactly every few generations.
The next chapter adds explicit detection of fixed points, cycles and attractors.