This site is version 0.0.1. Most of the code on this site is drafted by an agent and needs review. I apologize
for the AI-speak, we are working on rewriting it!
The logistic map at r = 4 has Lyapunov exponent ln 2
Adam Zettel · September 21, 2026 · written with an agent
Iterate x→rx(1−x). At r=3.2 it settles on two values you can write down. At r=4 it never settles, nearby starts separate by a factor of two per step on average, and that factor is exact: the Lyapunov exponent is ln2.
λ=n→∞limn1k<n∑ln∣r(1−2xk)∣
At r=4, substitute x=sin2θ and the map becomes θ→2θ: angle doubling,
which is where ln2 comes from. The two-cycle for 3<r<1+6 solves f(f(x))=x with the
fixed points divided out: x±=(r+1±(r−3)(r+1))/2r.
The program’s map: every function and which calls which.
There’s no recorded run of this program yet.
Shift+Enter in a cell runs it and moves to the next. Running a cell runs every cell above it too, as one program.
[1]lines 16–91
# iterations discarded before the orbit is on its attractor: the transient
TRANSIENT =500.0#| The Lyapunov exponent at r: the orbit average of ln |f'(x)| = ln |r (1 - 2x)|.deflyapunov(r, steps) {
x =0.3for s to TRANSIENT {
x = r * x * (1.0- x)
}
total =0.0for s to steps {
x = r * x * (1.0- x)
total = total +log(abs(r * (1.0-2.0* x)))
}
return total / steps
}
# the attractor: for each r (a column), discard a transient, then count where the# orbit goes (the rows, x = 1 at the top). Counts are capped so the two-cycle's# two hot cells do not wash out the chaotic band.
NR =160
NX =100
KEEP =240# the transient discarded in each column of the picture
PICTURE_TRANSIENT =400.0
R_LO =2.8
visits =zeros(NX, NR)
for i to NR {
r = R_LO + (4.0- R_LO) * i / (NR -1.0)
x =0.3for s to PICTURE_TRANSIENT {
x = r * x * (1.0- x)
}
for k to KEEP {
x = r * x * (1.0- x)
row = NX -1.0-min(floor(x * NX), NX -1.0)
visits[row, i] =min(visits[row, i] +1.0, 8.0)
}
}
# the two-cycle at r = 3.2, reached by iterating, against its closed form
R2 =3.2# enough iterations for the orbit to settle on the two-cycle to the last digit
SETTLE =2000.0
x =0.3for s to SETTLE {
x = R2 * x * (1.0- x)
}
reached_a =min(x, R2 * x * (1.0- x))
reached_b =max(x, R2 * x * (1.0- x))
root =sqrt((R2 -3.0) * (R2 +1.0))
exact_a = (R2 +1.0- root) / (2.0* R2)
exact_b = (R2 +1.0+ root) / (2.0* R2)
chaos =lyapunov(4.0, 200000.0)
order =lyapunov(3.2, 20000.0)
show reached_a
show reached_b
show chaos
show order
figure("Attractor of x -> r x (1 - x), by r", "r", "x", 2.8, 4.0, 0.0, 1.0, "pixels")
plot2d(visits, "visits, capped at 8")
test"at r = 3.2 the orbit lands on the closed-form two-cycle" {
assert_near(reached_a, exact_a, 1.0e-12)
assert_near(reached_b, exact_b, 1.0e-12)
}
test"there the Lyapunov exponent is negative: nearby starts converge" {
assert_lt(order, 0.0)
}
test"at r = 4 it is ln 2" {
assert_near(chaos, log(2.0), 5.0e-3)
}
# SPDX-License-Identifier: MIT OR Apache-2.0# SPDX-FileCopyrightText: 2026 The Viv authors